Files
linux/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
Abhishek Goel f9652d5cae cpupower : Fix header name to read idle state name
The names of the idle states in the output of cpupower monitor command are
truncated to 4 characters. On POWER9, this creates ambiguity as the states
are named "stop0", "stop1", etc.

root:~# cpupower monitor
              |Idle_Stats
PKG |CORE|CPU | snoo | stop | stop | stop | stop | stop | stop
   0|   0|   0|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  1.90
   0|   0|   1|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00
   0|   0|   2|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00
   0|   0|   3|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00

This patch modifies the output to print the state name that results in a
legible output. The names will be printed with atmost 1 padding in left.

root:~# cpupower monitor
              | Idle_Stats
 PKG|CORE| CPU|snooze|stop0L| stop0|stop1L| stop1|stop2L| stop2
   0|   0|   0|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  0.72
   0|   0|   1|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00
   0|   0|   2|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00
   0|   0|   3|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|  0.00

This patch does not affect the output for intel.
Output for intel before applying the patch:

root:~# cpupower monitor
    |Idle_Stats
CPU | POLL | C1-S | C1E- | C3-S | C6-S | C7s- | C8-S | C9-S | C10-
   0|  0.00|  0.14|  0.39|  0.35|  7.41|  0.00| 17.67|  1.01| 70.03
   2|  0.00|  0.19|  0.47|  0.10|  6.50|  0.00| 29.66|  2.17| 58.07
   1|  0.00|  0.11|  0.50|  1.50|  9.11|  0.18| 18.19|  0.40| 66.63
   3|  0.00|  0.67|  0.42|  0.03|  5.84|  0.00| 12.58|  0.77| 77.14

Output for intel after applying the patch:

root:~# cpupower monitor
    | Idle_Stats
 CPU| POLL | C1-S | C1E- | C3-S | C6-S | C7s- | C8-S | C9-S | C10-
   0|  0.03|  0.33|  1.01|  0.27|  3.03|  0.00| 19.18|  0.00| 71.24
   2|  0.00|  1.58|  0.58|  0.42|  8.55|  0.09| 21.11|  0.99| 63.32
   1|  0.00|  1.26|  0.88|  0.43|  9.00|  0.02|  7.78|  4.65| 71.91
   3|  0.00|  0.30|  0.42|  0.06| 13.62|  0.21| 30.29|  0.00| 52.45

Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
Signed-off-by: Shuah Khan (Samsung OSG) <shuah@kernel.org>
2018-05-29 10:48:33 -06:00

215 lines
4.9 KiB
C

/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc
*
* Licensed under the terms of the GNU GPL License version 2.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <cpuidle.h>
#include "helpers/helpers.h"
#include "idle_monitor/cpupower-monitor.h"
#define CPUIDLE_STATES_MAX 10
static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
struct cpuidle_monitor cpuidle_sysfs_monitor;
static unsigned long long **previous_count;
static unsigned long long **current_count;
struct timespec start_time;
static unsigned long long timediff;
static int cpuidle_get_count_percent(unsigned int id, double *percent,
unsigned int cpu)
{
unsigned long long statediff = current_count[cpu][id]
- previous_count[cpu][id];
dprint("%s: - diff: %llu - percent: %f (%u)\n",
cpuidle_cstates[id].name, timediff, *percent, cpu);
if (timediff == 0)
*percent = 0.0;
else
*percent = ((100.0 * statediff) / timediff);
dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
return 0;
}
static int cpuidle_start(void)
{
int cpu, state;
clock_gettime(CLOCK_REALTIME, &start_time);
for (cpu = 0; cpu < cpu_count; cpu++) {
for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
state++) {
previous_count[cpu][state] =
cpuidle_state_time(cpu, state);
dprint("CPU %d - State: %d - Val: %llu\n",
cpu, state, previous_count[cpu][state]);
}
};
return 0;
}
static int cpuidle_stop(void)
{
int cpu, state;
struct timespec end_time;
clock_gettime(CLOCK_REALTIME, &end_time);
timediff = timespec_diff_us(start_time, end_time);
for (cpu = 0; cpu < cpu_count; cpu++) {
for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
state++) {
current_count[cpu][state] =
cpuidle_state_time(cpu, state);
dprint("CPU %d - State: %d - Val: %llu\n",
cpu, state, previous_count[cpu][state]);
}
};
return 0;
}
void fix_up_intel_idle_driver_name(char *tmp, int num)
{
/* fix up cpuidle name for intel idle driver */
if (!strncmp(tmp, "NHM-", 4)) {
switch (num) {
case 1:
strcpy(tmp, "C1");
break;
case 2:
strcpy(tmp, "C3");
break;
case 3:
strcpy(tmp, "C6");
break;
}
} else if (!strncmp(tmp, "SNB-", 4)) {
switch (num) {
case 1:
strcpy(tmp, "C1");
break;
case 2:
strcpy(tmp, "C3");
break;
case 3:
strcpy(tmp, "C6");
break;
case 4:
strcpy(tmp, "C7");
break;
}
} else if (!strncmp(tmp, "ATM-", 4)) {
switch (num) {
case 1:
strcpy(tmp, "C1");
break;
case 2:
strcpy(tmp, "C2");
break;
case 3:
strcpy(tmp, "C4");
break;
case 4:
strcpy(tmp, "C6");
break;
}
}
}
#ifdef __powerpc__
void map_power_idle_state_name(char *tmp)
{
if (!strncmp(tmp, "stop0_lite", CSTATE_NAME_LEN))
strcpy(tmp, "stop0L");
else if (!strncmp(tmp, "stop1_lite", CSTATE_NAME_LEN))
strcpy(tmp, "stop1L");
else if (!strncmp(tmp, "stop2_lite", CSTATE_NAME_LEN))
strcpy(tmp, "stop2L");
}
#else
void map_power_idle_state_name(char *tmp) { }
#endif
static struct cpuidle_monitor *cpuidle_register(void)
{
int num;
char *tmp;
int this_cpu;
this_cpu = sched_getcpu();
/* Assume idle state count is the same for all CPUs */
cpuidle_sysfs_monitor.hw_states_num = cpuidle_state_count(this_cpu);
if (cpuidle_sysfs_monitor.hw_states_num <= 0)
return NULL;
for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
tmp = cpuidle_state_name(this_cpu, num);
if (tmp == NULL)
continue;
map_power_idle_state_name(tmp);
fix_up_intel_idle_driver_name(tmp, num);
strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
free(tmp);
tmp = cpuidle_state_desc(this_cpu, num);
if (tmp == NULL)
continue;
strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
free(tmp);
cpuidle_cstates[num].range = RANGE_THREAD;
cpuidle_cstates[num].id = num;
cpuidle_cstates[num].get_count_percent =
cpuidle_get_count_percent;
};
/* Free this at program termination */
previous_count = malloc(sizeof(long long *) * cpu_count);
current_count = malloc(sizeof(long long *) * cpu_count);
for (num = 0; num < cpu_count; num++) {
previous_count[num] = malloc(sizeof(long long) *
cpuidle_sysfs_monitor.hw_states_num);
current_count[num] = malloc(sizeof(long long) *
cpuidle_sysfs_monitor.hw_states_num);
}
cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);
return &cpuidle_sysfs_monitor;
}
void cpuidle_unregister(void)
{
int num;
for (num = 0; num < cpu_count; num++) {
free(previous_count[num]);
free(current_count[num]);
}
free(previous_count);
free(current_count);
}
struct cpuidle_monitor cpuidle_sysfs_monitor = {
.name = "Idle_Stats",
.hw_states = cpuidle_cstates,
.start = cpuidle_start,
.stop = cpuidle_stop,
.do_register = cpuidle_register,
.unregister = cpuidle_unregister,
.needs_root = 0,
.overflow_s = UINT_MAX,
};