/* * hyptop - Show hypervisor performance data on System z * * Provide CPU Items * * Copyright IBM Corp. 2010, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "sd.h" /* * Return CPU type of "cpu" */ static char *l_cpu_type(struct sd_cpu_item *item, struct sd_cpu *cpu) { (void) item; return sd_cpu_type_str(cpu); } /* * Return CPU state of "cpu" */ static char *l_cpu_state(struct sd_cpu_item *item, struct sd_cpu *cpu) { (void) item; return sd_cpu_state_str(sd_cpu_state(cpu)); } /* * value = (value_current - value_prev) / online_time_diff */ static double l_cpu_diff(struct sd_cpu_item *item, struct sd_cpu *cpu, int sign) { u64 online_time_diff_us; double factor, diff_us; if (sd_cpu_state(cpu) == SD_CPU_STATE_STOPPED) return 0; if (!cpu->d_prev || !cpu->d_cur) return 0; if (!sd_cpu_type_selected(cpu->type)) return 0; online_time_diff_us = l_sub_64(cpu->d_cur->online_time_us, cpu->d_prev->online_time_us); if (online_time_diff_us == 0) return 0; factor = util_usecs_to_secs(online_time_diff_us) * cpu->cnt; if (sign) diff_us = l_cpu_info_s64(cpu->d_cur, item->offset) - l_cpu_info_s64(cpu->d_prev, item->offset); else diff_us = l_sub_64(l_cpu_info_u64(cpu->d_cur, item->offset), l_cpu_info_u64(cpu->d_prev, item->offset)); diff_us /= factor; return diff_us; } /* * unsigned value = (value_current - value_prev) / online_time_diff */ static u64 l_cpu_diff_u64(struct sd_cpu_item *item, struct sd_cpu *cpu) { return l_cpu_diff(item, cpu, 0); } /* * signed value = (value_current - value_prev) / online_time_diff */ static s64 l_cpu_diff_s64(struct sd_cpu_item *item, struct sd_cpu *cpu) { return l_cpu_diff(item, cpu, 1); } /* * Return true, if CPU item has been set */ static inline int l_cpu_item_set(struct sd_cpu_item *item, struct sd_cpu *cpu) { return l_cpu_info_set(cpu->d_cur, item->offset); } /* * Return cpu item value */ static u64 l_cpu_item_64(struct sd_cpu_item *item, struct sd_cpu *cpu) { if (!cpu->d_cur) return 0; if (!sd_cpu_type_selected(cpu->type)) return 0; if (item->table_col.agg == TABLE_COL_AGG_MAX) return l_cpu_info_u64(cpu->d_cur, item->offset); else return l_cpu_info_u64(cpu->d_cur, item->offset) / cpu->cnt; } static u64 l_cpu_smt_util(struct sd_cpu_item *item, struct sd_cpu *cpu) { u64 core_us, thr_us, mgm_us; (void)item; core_us = sd_cpu_item_u64(&sd_cpu_item_core_diff, cpu); thr_us = sd_cpu_item_u64(&sd_cpu_item_thread_diff, cpu); mgm_us = sd_cpu_item_u64(&sd_cpu_item_mgm_diff, cpu); return ht_calculate_smt_util(core_us, thr_us, mgm_us, cpu->threads_per_core); } /* * CPU item definitions */ struct sd_cpu_item sd_cpu_item_type = { .table_col = TABLE_COL_STR('p', "type"), .type = SD_TYPE_STR, .desc = "CPU type", .fn_str = l_cpu_type, }; struct sd_cpu_item sd_cpu_item_state = { .table_col = TABLE_COL_STR('a', "stat"), .type = SD_TYPE_STR, .desc = "CPU state", .fn_str = l_cpu_state, }; struct sd_cpu_item sd_cpu_item_core_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'c', "core"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(cpu_time_us), .desc = "Core dispatch time per second", .fn_u64 = l_cpu_diff_u64, }; struct sd_cpu_item sd_cpu_item_cpu_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'c', "cpu"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(cpu_time_us), .desc = "CPU time per second", .fn_u64 = l_cpu_diff_u64, }; struct sd_cpu_item sd_cpu_item_thread_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'e', "the"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(thread_time_us), .desc = "Thread time per second", .fn_u64 = l_cpu_diff_u64, }; struct sd_cpu_item sd_cpu_item_smt_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'S', "smt"), .type = SD_TYPE_U64, .desc = "Real CPU SMT utilization", .fn_u64 = l_cpu_smt_util, }; struct sd_cpu_item sd_cpu_item_mgm_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(mgm_time_us), .desc = "Management time per second", .fn_set = l_cpu_item_set, .fn_u64 = l_cpu_diff_u64, }; struct sd_cpu_item sd_cpu_item_wait_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'w', "wait"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(wait_time_us), .desc = "Wait time per second", .fn_u64 = l_cpu_diff_u64, }; struct sd_cpu_item sd_cpu_item_steal_diff = { .table_col = TABLE_COL_STIME_DIFF_SUM(table_col_unit_perc, 's', "steal"), .type = SD_TYPE_S64, .offset = SD_CPU_INFO_OFFSET(steal_time_us), .desc = "Steal time per second", .fn_s64 = l_cpu_diff_s64, }; struct sd_cpu_item sd_cpu_item_core = { .table_col = TABLE_COL_TIME_SUM(table_col_unit_hm, 'C', "core+"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(cpu_time_us), .desc = "Total core dispatch time", .fn_u64 = l_cpu_item_64, }; struct sd_cpu_item sd_cpu_item_cpu = { .table_col = TABLE_COL_TIME_SUM(table_col_unit_hm, 'C', "cpu+"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(cpu_time_us), .desc = "Total CPU time", .fn_u64 = l_cpu_item_64, }; struct sd_cpu_item sd_cpu_item_thread = { .table_col = TABLE_COL_TIME_SUM(table_col_unit_hm, 'E', "the+"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(thread_time_us), .desc = "Total thread time", .fn_u64 = l_cpu_item_64, }; struct sd_cpu_item sd_cpu_item_mgm = { .table_col = TABLE_COL_TIME_SUM(table_col_unit_hm, 'M', "mgm+"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(mgm_time_us), .desc = "Total management time", .fn_set = l_cpu_item_set, .fn_u64 = l_cpu_item_64, }; struct sd_cpu_item sd_cpu_item_wait = { .table_col = TABLE_COL_TIME_SUM(table_col_unit_hm, 'W', "wait+"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(wait_time_us), .desc = "Total wait time", .fn_u64 = l_cpu_item_64, }; struct sd_cpu_item sd_cpu_item_steal = { .table_col = TABLE_COL_STIME_SUM(table_col_unit_hm, 'T', "steal+"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(steal_time_us), .desc = "Total steal time", .fn_u64 = l_cpu_item_64, }; struct sd_cpu_item sd_cpu_item_online = { .table_col = TABLE_COL_TIME_MAX(table_col_unit_dhm, 'o', "online"), .type = SD_TYPE_U64, .offset = SD_CPU_INFO_OFFSET(online_time_us), .desc = "Online time", .fn_u64 = l_cpu_item_64, };