diff options
author | Thomas Renninger <trenn@suse.de> | 2012-11-27 07:17:48 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2012-11-27 17:07:20 -0500 |
commit | c8cfc3c6bf404b0f110631d5bba234982e6ad24f (patch) | |
tree | dd6e71768799b81cca6e78fb0a26a45526a5af85 /tools | |
parent | ea1021ffa65a81da3d393fcbd7509d6e40d4d325 (diff) |
cpupower: Provide -c param for cpupower monitor to schedule process on all cores
If an MSR based monitor is run in parallel this is not needed. This is the
default case on all/most Intel machines.
But when only sysfs info is read via cpupower monitor -m Idle_Stats (typically
the case for non root users) or when other monitors are PCI based (AMD),
Idle_Stats, read from sysfs can be totally bogus:
cpupower monitor -m Idle_Stats
PKG |CORE|CPU | POLL | C1-N | C3-N | C6-N
0| 0| 0| 0.00| 0.00| 0.24| 99.81
0| 0| 32| 0.00| 0.00| 0.00| 100.7
...
0| 17| 20| 0.00| 0.00| 0.00| 173.1
0| 17| 52| 0.00| 0.00| 0.07| 173.0
0| 18| 68| 0.00| 0.00| 0.00| 0.00
0| 18| 76| 0.00| 0.00| 0.00| 0.00
...
With the -c option all cores are woken up and the kernel
did update cpuidle statistics before reading out sysfs.
This causes some overhead. Therefore avoid if possible, use
if needed:
cpupower monitor -c -m Idle_Stats
PKG |CORE|CPU | POLL | C1-N | C3-N | C6-N
0| 0| 0| 0.00| 0.00| 0.00| 100.2
0| 0| 32| 0.00| 0.00| 0.00| 100.2
...
0| 8| 8| 0.00| 0.00| 0.00| 99.82
0| 8| 40| 0.00| 0.00| 0.00| 99.81
0| 9| 24| 0.00| 0.00| 0.00| 100.3
0| 9| 56| 0.00| 0.00| 0.00| 100.2
0| 16| 4| 0.00| 0.00| 0.00| 99.75
0| 16| 36| 0.00| 0.00| 0.00| 99.38
...
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'tools')
4 files changed, 48 insertions, 3 deletions
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1 index 1141c2073719..e01c35d13b6e 100644 --- a/tools/power/cpupower/man/cpupower-monitor.1 +++ b/tools/power/cpupower/man/cpupower-monitor.1 | |||
@@ -7,11 +7,11 @@ cpupower\-monitor \- Report processor frequency and idle statistics | |||
7 | .RB "\-l" | 7 | .RB "\-l" |
8 | 8 | ||
9 | .B cpupower monitor | 9 | .B cpupower monitor |
10 | .RB [ "\-m <mon1>," [ "<mon2>,..." ] ] | 10 | .RB [ -c ] [ "\-m <mon1>," [ "<mon2>,..." ] ] |
11 | .RB [ "\-i seconds" ] | 11 | .RB [ "\-i seconds" ] |
12 | .br | 12 | .br |
13 | .B cpupower monitor | 13 | .B cpupower monitor |
14 | .RB [ "\-m <mon1>," [ "<mon2>,..." ] ] | 14 | .RB [ -c ][ "\-m <mon1>," [ "<mon2>,..." ] ] |
15 | .RB command | 15 | .RB command |
16 | .br | 16 | .br |
17 | .SH DESCRIPTION | 17 | .SH DESCRIPTION |
@@ -64,6 +64,17 @@ Only display specific monitors. Use the monitor string(s) provided by \-l option | |||
64 | Measure intervall. | 64 | Measure intervall. |
65 | .RE | 65 | .RE |
66 | .PP | 66 | .PP |
67 | \-c | ||
68 | .RS 4 | ||
69 | Schedule the process on every core before starting and ending measuring. | ||
70 | This could be needed for the Idle_Stats monitor when no other MSR based | ||
71 | monitor (has to be run on the core that is measured) is run in parallel. | ||
72 | This is to wake up the processors from deeper sleep states and let the | ||
73 | kernel re | ||
74 | -account its cpuidle (C-state) information before reading the | ||
75 | cpuidle timings from sysfs. | ||
76 | .RE | ||
77 | .PP | ||
67 | command | 78 | command |
68 | .RS 4 | 79 | .RS 4 |
69 | Measure idle and frequency characteristics of an arbitrary command/workload. | 80 | Measure idle and frequency characteristics of an arbitrary command/workload. |
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h index f84985f630e2..aa9e95486a2d 100644 --- a/tools/power/cpupower/utils/helpers/helpers.h +++ b/tools/power/cpupower/utils/helpers/helpers.h | |||
@@ -114,6 +114,7 @@ struct cpupower_topology { | |||
114 | 114 | ||
115 | extern int get_cpu_topology(struct cpupower_topology *cpu_top); | 115 | extern int get_cpu_topology(struct cpupower_topology *cpu_top); |
116 | extern void cpu_topology_release(struct cpupower_topology cpu_top); | 116 | extern void cpu_topology_release(struct cpupower_topology cpu_top); |
117 | |||
117 | /* CPU topology/hierarchy parsing ******************/ | 118 | /* CPU topology/hierarchy parsing ******************/ |
118 | 119 | ||
119 | /* X86 ONLY ****************************************/ | 120 | /* X86 ONLY ****************************************/ |
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c index 7a657f3da23b..c4bae9203a69 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c +++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c | |||
@@ -39,6 +39,7 @@ static int mode; | |||
39 | static int interval = 1; | 39 | static int interval = 1; |
40 | static char *show_monitors_param; | 40 | static char *show_monitors_param; |
41 | static struct cpupower_topology cpu_top; | 41 | static struct cpupower_topology cpu_top; |
42 | static unsigned int wake_cpus; | ||
42 | 43 | ||
43 | /* ToDo: Document this in the manpage */ | 44 | /* ToDo: Document this in the manpage */ |
44 | static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', }; | 45 | static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', }; |
@@ -314,16 +315,28 @@ int fork_it(char **argv) | |||
314 | int do_interval_measure(int i) | 315 | int do_interval_measure(int i) |
315 | { | 316 | { |
316 | unsigned int num; | 317 | unsigned int num; |
318 | int cpu; | ||
319 | |||
320 | if (wake_cpus) | ||
321 | for (cpu = 0; cpu < cpu_count; cpu++) | ||
322 | bind_cpu(cpu); | ||
317 | 323 | ||
318 | for (num = 0; num < avail_monitors; num++) { | 324 | for (num = 0; num < avail_monitors; num++) { |
319 | dprint("HW C-state residency monitor: %s - States: %d\n", | 325 | dprint("HW C-state residency monitor: %s - States: %d\n", |
320 | monitors[num]->name, monitors[num]->hw_states_num); | 326 | monitors[num]->name, monitors[num]->hw_states_num); |
321 | monitors[num]->start(); | 327 | monitors[num]->start(); |
322 | } | 328 | } |
329 | |||
323 | sleep(i); | 330 | sleep(i); |
331 | |||
332 | if (wake_cpus) | ||
333 | for (cpu = 0; cpu < cpu_count; cpu++) | ||
334 | bind_cpu(cpu); | ||
335 | |||
324 | for (num = 0; num < avail_monitors; num++) | 336 | for (num = 0; num < avail_monitors; num++) |
325 | monitors[num]->stop(); | 337 | monitors[num]->stop(); |
326 | 338 | ||
339 | |||
327 | return 0; | 340 | return 0; |
328 | } | 341 | } |
329 | 342 | ||
@@ -332,7 +345,7 @@ static void cmdline(int argc, char *argv[]) | |||
332 | int opt; | 345 | int opt; |
333 | progname = basename(argv[0]); | 346 | progname = basename(argv[0]); |
334 | 347 | ||
335 | while ((opt = getopt(argc, argv, "+li:m:")) != -1) { | 348 | while ((opt = getopt(argc, argv, "+lci:m:")) != -1) { |
336 | switch (opt) { | 349 | switch (opt) { |
337 | case 'l': | 350 | case 'l': |
338 | if (mode) | 351 | if (mode) |
@@ -351,6 +364,9 @@ static void cmdline(int argc, char *argv[]) | |||
351 | mode = show; | 364 | mode = show; |
352 | show_monitors_param = optarg; | 365 | show_monitors_param = optarg; |
353 | break; | 366 | break; |
367 | case 'c': | ||
368 | wake_cpus = 1; | ||
369 | break; | ||
354 | default: | 370 | default: |
355 | print_wrong_arg_exit(); | 371 | print_wrong_arg_exit(); |
356 | } | 372 | } |
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h index 9312ee1f2dbc..9e43f3371fbc 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h +++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h | |||
@@ -65,4 +65,21 @@ extern long long timespec_diff_us(struct timespec start, struct timespec end); | |||
65 | "could be inaccurate\n"), mes, ov); \ | 65 | "could be inaccurate\n"), mes, ov); \ |
66 | } | 66 | } |
67 | 67 | ||
68 | |||
69 | /* Taken over from x86info project sources -> return 0 on success */ | ||
70 | #include <sched.h> | ||
71 | #include <sys/types.h> | ||
72 | #include <unistd.h> | ||
73 | static inline int bind_cpu(int cpu) | ||
74 | { | ||
75 | cpu_set_t set; | ||
76 | |||
77 | if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) { | ||
78 | CPU_ZERO(&set); | ||
79 | CPU_SET(cpu, &set); | ||
80 | return sched_setaffinity(getpid(), sizeof(set), &set); | ||
81 | } | ||
82 | return 1; | ||
83 | } | ||
84 | |||
68 | #endif /* __CPUIDLE_INFO_HW__ */ | 85 | #endif /* __CPUIDLE_INFO_HW__ */ |