aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2012-03-29 22:19:58 -0400
committerLen Brown <len.brown@intel.com>2012-03-29 22:27:19 -0400
commit15aaa34654831e98dd76f7738b6c7f5d05a66430 (patch)
treed4c4449fdba32e04f791bdc92fbd4042abb18d17 /tools/power
parent88c3281f7ba449992f7a33bd2452a8c6fa5503cb (diff)
tools turbostat: harden against cpu online/offline
Sometimes users have turbostat running in interval mode when they take processors offline/online. Previously, turbostat would survive, but not gracefully. Tighten up the error checking so turbostat notices changesn sooner, and print just 1 line on change: turbostat: re-initialized with num_cpus %d Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/x86/turbostat/turbostat.c115
1 files changed, 61 insertions, 54 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index fa60872b9474..ab2f682fd44c 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -71,7 +71,6 @@ unsigned int show_cpu;
71int aperf_mperf_unstable; 71int aperf_mperf_unstable;
72int backwards_count; 72int backwards_count;
73char *progname; 73char *progname;
74int need_reinitialize;
75 74
76int num_cpus; 75int num_cpus;
77cpu_set_t *cpu_mask; 76cpu_set_t *cpu_mask;
@@ -138,30 +137,24 @@ int cpu_migrate(int cpu)
138 return 0; 137 return 0;
139} 138}
140 139
141unsigned long long get_msr(int cpu, off_t offset) 140int get_msr(int cpu, off_t offset, unsigned long long *msr)
142{ 141{
143 ssize_t retval; 142 ssize_t retval;
144 unsigned long long msr;
145 char pathname[32]; 143 char pathname[32];
146 int fd; 144 int fd;
147 145
148 sprintf(pathname, "/dev/cpu/%d/msr", cpu); 146 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
149 fd = open(pathname, O_RDONLY); 147 fd = open(pathname, O_RDONLY);
150 if (fd < 0) { 148 if (fd < 0)
151 perror(pathname); 149 return -1;
152 need_reinitialize = 1;
153 return 0;
154 }
155
156 retval = pread(fd, &msr, sizeof msr, offset);
157 if (retval != sizeof msr) {
158 fprintf(stderr, "cpu%d pread(..., 0x%zx) = %jd\n",
159 cpu, offset, retval);
160 exit(-2);
161 }
162 150
151 retval = pread(fd, msr, sizeof *msr, offset);
163 close(fd); 152 close(fd);
164 return msr; 153
154 if (retval != sizeof *msr)
155 return -1;
156
157 return 0;
165} 158}
166 159
167void print_header(void) 160void print_header(void)
@@ -506,36 +499,51 @@ void compute_average(struct counters *delta, struct counters *avg)
506 free(sum); 499 free(sum);
507} 500}
508 501
509void get_counters(struct counters *cnt) 502int get_counters(struct counters *cnt)
510{ 503{
511 for ( ; cnt; cnt = cnt->next) { 504 for ( ; cnt; cnt = cnt->next) {
512 if (cpu_migrate(cnt->cpu)) { 505
513 need_reinitialize = 1; 506 if (cpu_migrate(cnt->cpu))
514 return; 507 return -1;
508
509 if (get_msr(cnt->cpu, MSR_TSC, &cnt->tsc))
510 return -1;
511
512 if (has_aperf) {
513 if (get_msr(cnt->cpu, MSR_APERF, &cnt->aperf))
514 return -1;
515 if (get_msr(cnt->cpu, MSR_MPERF, &cnt->mperf))
516 return -1;
517 }
518
519 if (do_nhm_cstates) {
520 if (get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY, &cnt->c3))
521 return -1;
522 if (get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY, &cnt->c6))
523 return -1;
515 } 524 }
516 525
517 cnt->tsc = get_msr(cnt->cpu, MSR_TSC);
518 if (do_nhm_cstates)
519 cnt->c3 = get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY);
520 if (do_nhm_cstates)
521 cnt->c6 = get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY);
522 if (do_snb_cstates)
523 cnt->c7 = get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY);
524 if (has_aperf)
525 cnt->aperf = get_msr(cnt->cpu, MSR_APERF);
526 if (has_aperf)
527 cnt->mperf = get_msr(cnt->cpu, MSR_MPERF);
528 if (do_snb_cstates)
529 cnt->pc2 = get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY);
530 if (do_nhm_cstates)
531 cnt->pc3 = get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY);
532 if (do_nhm_cstates)
533 cnt->pc6 = get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY);
534 if (do_snb_cstates) 526 if (do_snb_cstates)
535 cnt->pc7 = get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY); 527 if (get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY, &cnt->c7))
528 return -1;
529
530 if (do_nhm_cstates) {
531 if (get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY, &cnt->pc3))
532 return -1;
533 if (get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY, &cnt->pc6))
534 return -1;
535 }
536 if (do_snb_cstates) {
537 if (get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY, &cnt->pc2))
538 return -1;
539 if (get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY, &cnt->pc7))
540 return -1;
541 }
536 if (extra_msr_offset) 542 if (extra_msr_offset)
537 cnt->extra_msr = get_msr(cnt->cpu, extra_msr_offset); 543 if (get_msr(cnt->cpu, extra_msr_offset, &cnt->extra_msr))
544 return -1;
538 } 545 }
546 return 0;
539} 547}
540 548
541void print_nehalem_info(void) 549void print_nehalem_info(void)
@@ -546,7 +554,7 @@ void print_nehalem_info(void)
546 if (!do_nehalem_platform_info) 554 if (!do_nehalem_platform_info)
547 return; 555 return;
548 556
549 msr = get_msr(0, MSR_NEHALEM_PLATFORM_INFO); 557 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
550 558
551 ratio = (msr >> 40) & 0xFF; 559 ratio = (msr >> 40) & 0xFF;
552 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", 560 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
@@ -562,7 +570,7 @@ void print_nehalem_info(void)
562 if (!do_nehalem_turbo_ratio_limit) 570 if (!do_nehalem_turbo_ratio_limit)
563 return; 571 return;
564 572
565 msr = get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT); 573 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
566 574
567 ratio = (msr >> 24) & 0xFF; 575 ratio = (msr >> 24) & 0xFF;
568 if (ratio) 576 if (ratio)
@@ -755,7 +763,7 @@ int get_core_id(int cpu)
755} 763}
756 764
757/* 765/*
758 * run func(index, cpu) on every cpu in /proc/stat 766 * run func(pkg, core, cpu) on every cpu in /proc/stat
759 */ 767 */
760 768
761int for_all_cpus(void (func)(int, int, int)) 769int for_all_cpus(void (func)(int, int, int))
@@ -791,20 +799,18 @@ int for_all_cpus(void (func)(int, int, int))
791 799
792void re_initialize(void) 800void re_initialize(void)
793{ 801{
794 printf("turbostat: topology changed, re-initializing.\n");
795 free_all_counters(); 802 free_all_counters();
796 num_cpus = for_all_cpus(alloc_new_counters); 803 num_cpus = for_all_cpus(alloc_new_counters);
797 need_reinitialize = 0;
798 cpu_mask_uninit(); 804 cpu_mask_uninit();
799 cpu_mask_init(num_cpus); 805 cpu_mask_init(num_cpus);
800 printf("num_cpus is now %d\n", num_cpus); 806 printf("turbostat: re-initialized with num_cpus %d\n", num_cpus);
801} 807}
802 808
803void dummy(int pkg, int core, int cpu) { return; } 809void dummy(int pkg, int core, int cpu) { return; }
804/* 810/*
805 * check to see if a cpu came on-line 811 * check to see if a cpu came on-line
806 */ 812 */
807void verify_num_cpus(void) 813int verify_num_cpus(void)
808{ 814{
809 int new_num_cpus; 815 int new_num_cpus;
810 816
@@ -814,8 +820,9 @@ void verify_num_cpus(void)
814 if (verbose) 820 if (verbose)
815 printf("num_cpus was %d, is now %d\n", 821 printf("num_cpus was %d, is now %d\n",
816 num_cpus, new_num_cpus); 822 num_cpus, new_num_cpus);
817 need_reinitialize = 1; 823 return -1;
818 } 824 }
825 return 0;
819} 826}
820 827
821void turbostat_loop() 828void turbostat_loop()
@@ -825,25 +832,25 @@ restart:
825 gettimeofday(&tv_even, (struct timezone *)NULL); 832 gettimeofday(&tv_even, (struct timezone *)NULL);
826 833
827 while (1) { 834 while (1) {
828 verify_num_cpus(); 835 if (verify_num_cpus()) {
829 if (need_reinitialize) {
830 re_initialize(); 836 re_initialize();
831 goto restart; 837 goto restart;
832 } 838 }
833 sleep(interval_sec); 839 sleep(interval_sec);
834 get_counters(cnt_odd); 840 if (get_counters(cnt_odd)) {
841 re_initialize();
842 goto restart;
843 }
835 gettimeofday(&tv_odd, (struct timezone *)NULL); 844 gettimeofday(&tv_odd, (struct timezone *)NULL);
836
837 compute_delta(cnt_odd, cnt_even, cnt_delta); 845 compute_delta(cnt_odd, cnt_even, cnt_delta);
838 timersub(&tv_odd, &tv_even, &tv_delta); 846 timersub(&tv_odd, &tv_even, &tv_delta);
839 compute_average(cnt_delta, cnt_average); 847 compute_average(cnt_delta, cnt_average);
840 print_counters(cnt_delta); 848 print_counters(cnt_delta);
841 if (need_reinitialize) { 849 sleep(interval_sec);
850 if (get_counters(cnt_even)) {
842 re_initialize(); 851 re_initialize();
843 goto restart; 852 goto restart;
844 } 853 }
845 sleep(interval_sec);
846 get_counters(cnt_even);
847 gettimeofday(&tv_even, (struct timezone *)NULL); 854 gettimeofday(&tv_even, (struct timezone *)NULL);
848 compute_delta(cnt_even, cnt_odd, cnt_delta); 855 compute_delta(cnt_even, cnt_odd, cnt_delta);
849 timersub(&tv_even, &tv_odd, &tv_delta); 856 timersub(&tv_even, &tv_odd, &tv_delta);