X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=procps%2Fpowertop.c;h=ce85f4191e0f605dfd67e1f00f072956201a4b92;hb=2b1559056cf32c42675ecd937796e1455bcb5c2c;hp=3d98b9bdaaf47b9e37cb96878c765b67c641955c;hpb=d8b687f99257772f62edd7c4641427280841e1c5;p=oweals%2Fbusybox.git diff --git a/procps/powertop.c b/procps/powertop.c index 3d98b9bda..ce85f4191 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ -//applet:IF_POWERTOP(APPLET(powertop, _BB_DIR_BIN, _BB_SUID_DROP)) +//applet:IF_POWERTOP(APPLET(powertop, BB_DIR_USR_SBIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_POWERTOP) += powertop.o @@ -39,7 +39,7 @@ /* Frequency of the ACPI timer */ #define FREQ_ACPI 3579.545 -#define FREQ_ACPI_1000 3579545 +#define FREQ_ACPI_1000 3579545 /* Max filename length of entry in /sys/devices subsystem */ #define BIG_SYSNAME_LEN 16 @@ -82,7 +82,6 @@ struct globals { ullong last_usage[MAX_CSTATE_COUNT]; ullong start_duration[MAX_CSTATE_COUNT]; ullong last_duration[MAX_CSTATE_COUNT]; - char cstate_names[MAX_CSTATE_COUNT][16]; #if ENABLE_FEATURE_USE_TERMIOS struct termios init_settings; #endif @@ -116,8 +115,8 @@ static int write_str_to_file(const char *fname, const char *str) } /* Make it more readable */ -#define start_timer() write_str_to_file("/proc/timer_stats", "1\n") -#define stop_timer() write_str_to_file("/proc/timer_stats", "0\n") +#define start_timer() write_str_to_file("/proc/timer_stats", "1\n") +#define stop_timer() write_str_to_file("/proc/timer_stats", "0\n") static NOINLINE void clear_lines(void) { @@ -170,7 +169,7 @@ static void read_cstate_counts(ullong *usage, ullong *duration) if (len < 3 || len > BIG_SYSNAME_LEN) continue; - sprintf(buf, "/proc/acpi/processor/%s/power", d->d_name); + sprintf(buf, "%s/%s/power", "/proc/acpi/processor", d->d_name); fp = fopen_for_read(buf); if (!fp) continue; @@ -322,31 +321,18 @@ static void process_irq_counts(void) /* 0: 143646045 153901007 IO-APIC-edge timer * ^ */ + *p = '\0'; /* Deal with non-maskable interrupts -- make up fake numbers */ - nr = -1; - if (buf[0] != ' ' && !isdigit(buf[0])) { -//TODO: optimize - if (strncmp(buf, "NMI:", 4) == 0) - nr = 20000; - if (strncmp(buf, "RES:", 4) == 0) - nr = 20001; - if (strncmp(buf, "CAL:", 4) == 0) - nr = 20002; - if (strncmp(buf, "TLB:", 4) == 0) - nr = 20003; - if (strncmp(buf, "TRM:", 4) == 0) - nr = 20004; - if (strncmp(buf, "THR:", 4) == 0) - nr = 20005; - if (strncmp(buf, "SPU:", 4) == 0) - nr = 20006; + nr = index_in_strings("NMI\0RES\0CAL\0TLB\0TRM\0THR\0SPU\0", buf); + if (nr >= 0) { + nr += 20000; } else { /* bb_strtou doesn't eat leading spaces, using strtoul */ + errno = 0; nr = strtoul(buf, NULL, 10); + if (errno) + continue; } - if (nr == -1) - continue; - p++; /* 0: 143646045 153901007 IO-APIC-edge timer * ^ @@ -363,7 +349,7 @@ static void process_irq_counts(void) } /* 0: 143646045 153901007 IO-APIC-edge timer * NMI: 1 2 Non-maskable interrupts - * ^ + * ^ */ if (nr < 20000) { /* Skip to the interrupt name, e.g. 'timer' */ @@ -374,7 +360,7 @@ static void process_irq_counts(void) } name = p; - strchrnul(name, '\n')[0] = '\0'; + chomp(p); /* Save description of the interrupt */ if (nr >= 20000) sprintf(irq_desc, " : %s", name); @@ -407,12 +393,11 @@ static NOINLINE int process_timer_stats(void) char buf[128]; char line[15 + 3 + 128]; int n; - ullong totalticks; FILE *fp; buf[0] = '\0'; - totalticks = 0; + n = 0; fp = NULL; if (!G.cant_enable_timer_stats) fp = fopen_for_read("/proc/timer_stats"); @@ -431,33 +416,41 @@ static NOINLINE int process_timer_stats(void) while (fgets(buf, sizeof(buf), fp)) { const char *count, *process, *func; char *p; - int cnt; + int idx; + unsigned cnt; count = skip_whitespace(buf); p = strchr(count, ','); if (!p) continue; *p++ = '\0'; - if (strcmp(strchrnul(count, ' '), " total events") == 0) + cnt = bb_strtou(count, NULL, 10); + if (strcmp(skip_non_whitespace(count), " total events") == 0) { +#if ENABLE_FEATURE_POWERTOP_PROCIRQ + n = cnt / G.total_cpus; + if (n > 0 && n < G.interrupt_0) { + sprintf(line, " : %s", "extra timer interrupt"); + save_line(line, G.interrupt_0 - n); + } +#endif break; - p = skip_whitespace(p); /* points to pid */ - -/* Find char ' ', then eat remaining spaces */ -#define ADVANCE(p) do { \ - (p) = strchr((p), ' '); \ - if (!(p)) \ - continue; \ - *(p) = '\0'; \ - (p)++; \ - (p) = skip_whitespace(p); \ -} while (0) - /* Get process name */ - ADVANCE(p); - process = p; - /* Get function */ - ADVANCE(p); + } + if (strchr(count, 'D')) + continue; /* deferred */ + p = skip_whitespace(p); /* points to pid now */ + process = NULL; + get_func_name: + p = strchr(p, ' '); + if (!p) + continue; + *p++ = '\0'; + p = skip_whitespace(p); + if (process == NULL) { + process = p; + goto get_func_name; + } func = p; -#undef ADVANCE + //if (strcmp(process, "swapper") == 0 // && strcmp(func, "hrtimer_start_range_ns (tick_sched_timer)\n") == 0 //) { @@ -465,52 +458,33 @@ static NOINLINE int process_timer_stats(void) // func = "Load balancing tick"; //} - if (strncmp(func, "tick_nohz_", 10) == 0) + if (is_prefixed_with(func, "tick_nohz_")) continue; - if (strncmp(func, "tick_setup_sched_timer", 20) == 0) + if (is_prefixed_with(func, "tick_setup_sched_timer")) continue; //if (strcmp(process, "powertop") == 0) // continue; - if (strcmp(process, "insmod") == 0) - process = "[kernel module]"; - if (strcmp(process, "modprobe") == 0) - process = "[kernel module]"; - if (strcmp(process, "swapper") == 0) - process = ""; + idx = index_in_strings("insmod\0modprobe\0swapper\0", process); + if (idx != -1) { + process = idx < 2 ? "[kernel module]" : ""; + } - strchrnul(p, '\n')[0] = '\0'; + chomp(p); - { - char *tmp; - cnt = bb_strtoull(count, &tmp, 10); - p = tmp; - } - while (*p != '\0') { - if (*p++ == 'D') /* deferred */ - goto skip; - } + // 46D\01136\0kondemand/1\0do_dbs_timer (delayed_work_timer_fn) + // ^ ^ ^ + // count process func //if (strchr(process, '[')) sprintf(line, "%15.15s : %s", process, func); //else // sprintf(line, "%s", process); save_line(line, cnt); - skip: ; } fclose(fp); } - n = 0; -#if ENABLE_FEATURE_POWERTOP_PROCIRQ - if (strstr(buf, "total events")) { - n = bb_strtoull(buf, NULL, 10) / G.total_cpus; - if (n > 0 && n < G.interrupt_0) { - sprintf(line, " : %s", "extra timer interrupt"); - save_line(line, G.interrupt_0 - n); - } - } -#endif return n; } @@ -519,7 +493,7 @@ static NOINLINE int process_timer_stats(void) * Get information about CPU using CPUID opcode. */ static void cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, - unsigned int *edx) + unsigned int *edx) { /* EAX value specifies what information to return */ __asm__( @@ -540,9 +514,9 @@ static void cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, } #endif +#ifdef __i386__ static NOINLINE void print_intel_cstates(void) { -#ifdef __i386__ int bios_table[8] = { 0 }; int nbios = 0; DIR *cpudir; @@ -567,7 +541,7 @@ static NOINLINE void print_intel_cstates(void) if (!isdigit(d->d_name[3])) continue; - len = sprintf(fname, "/sys/devices/system/cpu/%s/cpuidle", d->d_name); + len = sprintf(fname, "%s/%s/cpuidle", "/sys/devices/system/cpu", d->d_name); dir = opendir(fname); if (!dir) continue; @@ -617,7 +591,7 @@ static NOINLINE void print_intel_cstates(void) if (!edx || !(ecx & 1)) return; - printf("Your CPU supports the following C-states: "); + printf("Your %s the following C-states: ", "CPU supports"); i = 0; while (edx) { if (edx & 7) @@ -628,14 +602,16 @@ static NOINLINE void print_intel_cstates(void) bb_putchar('\n'); /* Print BIOS C-States */ - printf("Your BIOS reports the following C-states: "); - for (i = 0; i < 8; i++) + printf("Your %s the following C-states: ", "BIOS reports"); + for (i = 0; i < ARRAY_SIZE(bios_table); i++) if (bios_table[i]) printf("C%u ", i); bb_putchar('\n'); -#endif } +#else +# define print_intel_cstates() ((void)0) +#endif static void show_timerstats(void) { @@ -651,7 +627,6 @@ static void show_timerstats(void) int i, n = 0; char strbuf6[6]; - strbuf6[5] = '\0'; puts("\nTop causes for wakeups:"); for (i = 0; i < G.lines_cnt; i++) { if ((G.lines[i].count > 0 /*|| G.lines[i].disk_count > 0*/) @@ -663,7 +638,7 @@ static void show_timerstats(void) /*char c = ' '; if (G.lines[i].disk_count) c = 'D';*/ - smart_ulltoa5(G.lines[i].count, strbuf6, " KMGTPEZY"); + smart_ulltoa5(G.lines[i].count, strbuf6, " KMGTPEZY")[0] = '\0'; printf(/*" %5.1f%% (%s)%c %s\n"*/ " %5.1f%% (%s) %s\n", G.lines[i].count * 100.0 / G.lines_cumulative_count, @@ -674,7 +649,7 @@ static void show_timerstats(void) } else { bb_putchar('\n'); bb_error_msg("no stats available; run as root or" - " enable the cpufreq_stats module"); + " enable the timer_stats module"); } } @@ -690,8 +665,8 @@ static void show_timerstats(void) // no ACPI power usage estimate available // // Top causes for wakeups: -// 32.4% ( 26.7) : extra timer interrupt -// 29.0% ( 23.9) : hrtimer_start_range_ns (tick_sched_timer) +// 32.4% ( 26.7) : extra timer interrupt +// 29.0% ( 23.9) : hrtimer_start_range_ns (tick_sched_timer) // 9.0% ( 7.5) : hrtimer_start (tick_sched_timer) // 6.5% ( 5.3) : ata_piix // 5.0% ( 4.1) inetd : hrtimer_start_range_ns (hrtimer_wakeup) @@ -699,7 +674,7 @@ static void show_timerstats(void) //usage:#define powertop_trivial_usage //usage: "" //usage:#define powertop_full_usage "\n\n" -//usage: "Analyze power consumption on Intel-based laptops\n" +//usage: "Analyze power consumption on Intel-based laptops" int powertop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) @@ -729,7 +704,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) /* Get number of CPUs */ G.total_cpus = get_cpu_count(); - printf("Collecting data for "DEFAULT_SLEEP_STR" seconds\n"); + puts("Collecting data for "DEFAULT_SLEEP_STR" seconds"); #if ENABLE_FEATURE_USE_TERMIOS tcgetattr(0, (void *)&G.init_settings); @@ -806,22 +781,19 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) if (totalevents == 0 && G.maxcstate <= 1) { /* This should not happen */ - sprintf(cstate_lines[5], "< Detailed C-state information is not " - "available.>\n"); + strcpy(cstate_lines[0], "C-state information is not available\n"); } else { double percentage; - double newticks; + unsigned newticks; newticks = G.total_cpus * DEFAULT_SLEEP * FREQ_ACPI_1000 - totalticks; - /* Handle rounding errors: do not display negative values */ - if (newticks < 0) + if ((int)newticks < 0) newticks = 0; sprintf(cstate_lines[0], "Cn\t\t Avg residency\n"); percentage = newticks * 100.0 / (G.total_cpus * DEFAULT_SLEEP * FREQ_ACPI_1000); - sprintf(cstate_lines[1], "C0 (cpu running) (%4.1f%%)\n", - percentage); + sprintf(cstate_lines[1], "C0 (cpu running) (%4.1f%%)\n", percentage); /* Compute values for individual C-states */ for (i = 0; i < MAX_CSTATE_COUNT; i++) { @@ -831,11 +803,8 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) / (cur_usage[i] - G.last_usage[i] + 0.1) / FREQ_ACPI; percentage = (cur_duration[i] - G.last_duration[i]) * 100 / (G.total_cpus * DEFAULT_SLEEP * FREQ_ACPI_1000); - - if (!G.cstate_names[i][0]) - sprintf(G.cstate_names[i], "C%u", i + 1); - sprintf(cstate_lines[i + 2], "%s\t\t%5.1fms (%4.1f%%)\n", - G.cstate_names[i], slept, percentage); + sprintf(cstate_lines[i + 2], "C%u\t\t%5.1fms (%4.1f%%)\n", + i + 1, slept, percentage); //if (maxsleep < slept) // maxsleep = slept; } @@ -844,7 +813,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) for (i = 0; i < MAX_CSTATE_COUNT + 2; i++) if (cstate_lines[i][0]) - printf("%s", cstate_lines[i]); + fputs(cstate_lines[i], stdout); i = process_timer_stats(); #if ENABLE_FEATURE_POWERTOP_PROCIRQ