mirror of https://github.com/mirror/busybox.git
powertop: fixes to output format and code shrink
function old new delta process_timer_stats - 631 +631 clear_lines 72 74 +2 process_irq_counts 729 726 -3 .rodata 145699 145530 -169 powertop_main 2341 1510 -831 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 1/2 up/down: 1359/-1729) Total: -370 bytes Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>1_18_stable
parent
373789e567
commit
c3f1fa10d6
|
@ -19,7 +19,7 @@
|
||||||
//config: help
|
//config: help
|
||||||
//config: Analyze power consumption on Intel-based laptops
|
//config: Analyze power consumption on Intel-based laptops
|
||||||
|
|
||||||
// XXX This should de configurable
|
// XXX This should be configurable
|
||||||
#define ENABLE_FEATURE_POWERTOP_PROCIRQ 1
|
#define ENABLE_FEATURE_POWERTOP_PROCIRQ 1
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
/* Frequency of the ACPI timer */
|
/* Frequency of the ACPI timer */
|
||||||
#define FREQ_ACPI 3579.545
|
#define FREQ_ACPI 3579.545
|
||||||
#define FREQ_ACPI_1000 3579545
|
#define FREQ_ACPI_1000 3579545
|
||||||
|
|
||||||
/* Max filename length of entry in /sys/devices subsystem */
|
/* Max filename length of entry in /sys/devices subsystem */
|
||||||
#define BIG_SYSNAME_LEN 16
|
#define BIG_SYSNAME_LEN 16
|
||||||
|
@ -62,12 +62,11 @@ struct irqdata {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct globals {
|
struct globals {
|
||||||
|
struct line *lines; /* the most often used member */
|
||||||
int lines_cnt;
|
int lines_cnt;
|
||||||
int lines_cumulative_count;
|
int lines_cumulative_count;
|
||||||
int linesize;
|
|
||||||
int maxcstate;
|
int maxcstate;
|
||||||
unsigned total_cpus;
|
unsigned total_cpus;
|
||||||
struct line *lines;
|
|
||||||
smallint cant_enable_timer_stats;
|
smallint cant_enable_timer_stats;
|
||||||
#if ENABLE_FEATURE_POWERTOP_PROCIRQ
|
#if ENABLE_FEATURE_POWERTOP_PROCIRQ
|
||||||
# if BLOATY_HPET_IRQ_NUM_DETECTION
|
# if BLOATY_HPET_IRQ_NUM_DETECTION
|
||||||
|
@ -120,15 +119,16 @@ static int write_str_to_file(const char *fname, const char *str)
|
||||||
#define start_timer() write_str_to_file("/proc/timer_stats", "1\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")
|
#define stop_timer() write_str_to_file("/proc/timer_stats", "0\n")
|
||||||
|
|
||||||
static void NOINLINE clear_lines(void)
|
static NOINLINE void clear_lines(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < G.lines_cnt; i++)
|
if (G.lines) {
|
||||||
free(G.lines[i].string);
|
for (i = 0; i < G.lines_cnt; i++)
|
||||||
free(G.lines);
|
free(G.lines[i].string);
|
||||||
G.lines_cnt = 0;
|
free(G.lines);
|
||||||
G.linesize = 0;
|
G.lines_cnt = 0;
|
||||||
G.lines = NULL;
|
G.lines = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_lines_cumulative_count(void)
|
static void update_lines_cumulative_count(void)
|
||||||
|
@ -220,7 +220,7 @@ static void save_line(const char *string, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new line */
|
/* Add new line */
|
||||||
G.lines = xrealloc_vector(G.lines, 1, G.lines_cnt);
|
G.lines = xrealloc_vector(G.lines, 4, G.lines_cnt);
|
||||||
G.lines[G.lines_cnt].string = xstrdup(string);
|
G.lines[G.lines_cnt].string = xstrdup(string);
|
||||||
G.lines[G.lines_cnt].count = count;
|
G.lines[G.lines_cnt].count = count;
|
||||||
/*G.lines[G.lines_cnt].disk_count = 0;*/
|
/*G.lines[G.lines_cnt].disk_count = 0;*/
|
||||||
|
@ -298,7 +298,7 @@ static int save_irq_count(int irq, ullong count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read /proc/interrupts, save IRQ counts and IRQ description */
|
/* Read /proc/interrupts, save IRQ counts and IRQ description */
|
||||||
static void process_irq_count_deltas(void)
|
static void process_irq_counts(void)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
@ -399,9 +399,121 @@ static void process_irq_count_deltas(void)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
#else /* !ENABLE_FEATURE_POWERTOP_PROCIRQ */
|
#else /* !ENABLE_FEATURE_POWERTOP_PROCIRQ */
|
||||||
# define process_irq_count_deltas() ((void)0)
|
# define process_irq_counts() ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
fp = NULL;
|
||||||
|
if (!G.cant_enable_timer_stats)
|
||||||
|
fp = fopen_for_read("/proc/timer_stats");
|
||||||
|
if (fp) {
|
||||||
|
// Example file contents:
|
||||||
|
// Timer Stats Version: v0.2
|
||||||
|
// Sample period: 1.329 s
|
||||||
|
// 76, 0 swapper hrtimer_start_range_ns (tick_sched_timer)
|
||||||
|
// 88, 0 swapper hrtimer_start_range_ns (tick_sched_timer)
|
||||||
|
// 24, 3787 firefox hrtimer_start_range_ns (hrtimer_wakeup)
|
||||||
|
// 46D, 1136 kondemand/1 do_dbs_timer (delayed_work_timer_fn)
|
||||||
|
// ...
|
||||||
|
// 1, 1656 Xorg hrtimer_start_range_ns (hrtimer_wakeup)
|
||||||
|
// 1, 2159 udisks-daemon hrtimer_start_range_ns (hrtimer_wakeup)
|
||||||
|
// 331 total events, 249.059 events/sec
|
||||||
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
const char *count, *process, *func;
|
||||||
|
char *p;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
count = skip_whitespace(buf);
|
||||||
|
p = strchr(count, ',');
|
||||||
|
if (!p)
|
||||||
|
continue;
|
||||||
|
*p++ = '\0';
|
||||||
|
if (strcmp(strchrnul(count, ' '), " total events") == 0)
|
||||||
|
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);
|
||||||
|
func = p;
|
||||||
|
#undef ADVANCE
|
||||||
|
//if (strcmp(process, "swapper") == 0
|
||||||
|
// && strcmp(func, "hrtimer_start_range_ns (tick_sched_timer)\n") == 0
|
||||||
|
//) {
|
||||||
|
// process = "[kernel scheduler]";
|
||||||
|
// func = "Load balancing tick";
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (strncmp(func, "tick_nohz_", 10) == 0)
|
||||||
|
continue;
|
||||||
|
if (strncmp(func, "tick_setup_sched_timer", 20) == 0)
|
||||||
|
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 = "<kernel core>";
|
||||||
|
|
||||||
|
strchrnul(p, '\n')[0] = '\0';
|
||||||
|
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
cnt = bb_strtoull(count, &tmp, 10);
|
||||||
|
p = tmp;
|
||||||
|
}
|
||||||
|
while (*p != '\0') {
|
||||||
|
if (*p++ == 'D') /* deferred */
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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, " <interrupt> : %s", "extra timer interrupt");
|
||||||
|
save_line(line, G.interrupt_0 - n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
/*
|
/*
|
||||||
* Get information about CPU using CPUID opcode.
|
* Get information about CPU using CPUID opcode.
|
||||||
|
@ -428,7 +540,7 @@ static void cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void NOINLINE print_intel_cstates(void)
|
static NOINLINE void print_intel_cstates(void)
|
||||||
{
|
{
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
int bios_table[8] = { 0 };
|
int bios_table[8] = { 0 };
|
||||||
|
@ -462,7 +574,7 @@ static void NOINLINE print_intel_cstates(void)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Every C-state has its own stateN directory, that
|
* Every C-state has its own stateN directory, that
|
||||||
* contains a `time' and a `usage' file.
|
* contains a 'time' and a 'usage' file.
|
||||||
*/
|
*/
|
||||||
while ((d = readdir(dir)) != NULL) {
|
while ((d = readdir(dir)) != NULL) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -525,25 +637,6 @@ static void NOINLINE print_intel_cstates(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_header(void)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
/* Clear the screen */
|
|
||||||
"\033[H\033[J"
|
|
||||||
/* Print the header */
|
|
||||||
"\033[7m%.*s\033[0m", 79, "PowerTOP (C) 2007 Intel Corporation\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void show_cstates(char cstate_lines[][64])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++)
|
|
||||||
if ((cstate_lines[i][0]))
|
|
||||||
printf("%s", cstate_lines[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void show_timerstats(void)
|
static void show_timerstats(void)
|
||||||
{
|
{
|
||||||
unsigned lines;
|
unsigned lines;
|
||||||
|
@ -556,19 +649,26 @@ static void show_timerstats(void)
|
||||||
|
|
||||||
if (!G.cant_enable_timer_stats) {
|
if (!G.cant_enable_timer_stats) {
|
||||||
int i, n = 0;
|
int i, n = 0;
|
||||||
|
char strbuf6[6];
|
||||||
|
|
||||||
|
strbuf6[5] = '\0';
|
||||||
puts("\nTop causes for wakeups:");
|
puts("\nTop causes for wakeups:");
|
||||||
for (i = 0; i < G.lines_cnt; i++) {
|
for (i = 0; i < G.lines_cnt; i++) {
|
||||||
if ((G.lines[i].count > 0 /*|| G.lines[i].disk_count > 0*/)
|
if ((G.lines[i].count > 0 /*|| G.lines[i].disk_count > 0*/)
|
||||||
&& n++ < lines
|
&& n++ < lines
|
||||||
) {
|
) {
|
||||||
char c = ' ';
|
/* NB: upstream powertop prints "(wakeups/sec)",
|
||||||
/*if (G.lines[i].disk_count)
|
* we print just "(wakeup counts)".
|
||||||
|
*/
|
||||||
|
/*char c = ' ';
|
||||||
|
if (G.lines[i].disk_count)
|
||||||
c = 'D';*/
|
c = 'D';*/
|
||||||
printf(" %5.1f%% (%5.1f)%c %s\n",
|
smart_ulltoa5(G.lines[i].count, strbuf6, " KMGTPEZY");
|
||||||
G.lines[i].count * 100.0 / G.lines_cumulative_count,
|
printf(/*" %5.1f%% (%s)%c %s\n"*/
|
||||||
G.lines[i].count * 1.0 / DEFAULT_SLEEP, c,
|
" %5.1f%% (%s) %s\n",
|
||||||
G.lines[i].string);
|
G.lines[i].count * 100.0 / G.lines_cumulative_count,
|
||||||
|
strbuf6, /*c,*/
|
||||||
|
G.lines[i].string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -606,8 +706,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
{
|
{
|
||||||
ullong cur_usage[MAX_CSTATE_COUNT];
|
ullong cur_usage[MAX_CSTATE_COUNT];
|
||||||
ullong cur_duration[MAX_CSTATE_COUNT];
|
ullong cur_duration[MAX_CSTATE_COUNT];
|
||||||
char cstate_lines[12][64];
|
char cstate_lines[MAX_CSTATE_COUNT + 2][64];
|
||||||
char buf[128];
|
|
||||||
#if ENABLE_FEATURE_USE_TERMIOS
|
#if ENABLE_FEATURE_USE_TERMIOS
|
||||||
struct termios new_settings;
|
struct termios new_settings;
|
||||||
struct pollfd pfd[1];
|
struct pollfd pfd[1];
|
||||||
|
@ -644,7 +743,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Collect initial data */
|
/* Collect initial data */
|
||||||
process_irq_count_deltas();
|
process_irq_counts();
|
||||||
|
|
||||||
/* Read initial usage and duration */
|
/* Read initial usage and duration */
|
||||||
read_cstate_counts(G.start_usage, G.start_duration);
|
read_cstate_counts(G.start_usage, G.start_duration);
|
||||||
|
@ -660,10 +759,9 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
|
|
||||||
/* The main loop */
|
/* The main loop */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/*double maxsleep = 0.0;*/
|
//double maxsleep = 0.0;
|
||||||
ullong totalticks, totalevents;
|
ullong totalticks, totalevents;
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
G.cant_enable_timer_stats |= start_timer(); /* 1 on error */
|
G.cant_enable_timer_stats |= start_timer(); /* 1 on error */
|
||||||
#if !ENABLE_FEATURE_USE_TERMIOS
|
#if !ENABLE_FEATURE_USE_TERMIOS
|
||||||
|
@ -682,7 +780,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
G.cant_enable_timer_stats |= stop_timer(); /* 1 on error */
|
G.cant_enable_timer_stats |= stop_timer(); /* 1 on error */
|
||||||
|
|
||||||
clear_lines();
|
clear_lines();
|
||||||
process_irq_count_deltas();
|
process_irq_counts();
|
||||||
|
|
||||||
/* Clear the stats */
|
/* Clear the stats */
|
||||||
memset(cur_duration, 0, sizeof(cur_duration));
|
memset(cur_duration, 0, sizeof(cur_duration));
|
||||||
|
@ -700,8 +798,8 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show title bar */
|
/* Clear the screen */
|
||||||
print_header();
|
printf("\033[H\033[J");
|
||||||
|
|
||||||
/* Clear C-state lines */
|
/* Clear C-state lines */
|
||||||
memset(&cstate_lines, 0, sizeof(cstate_lines));
|
memset(&cstate_lines, 0, sizeof(cstate_lines));
|
||||||
|
@ -711,7 +809,6 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
sprintf(cstate_lines[5], "< Detailed C-state information is not "
|
sprintf(cstate_lines[5], "< Detailed C-state information is not "
|
||||||
"available.>\n");
|
"available.>\n");
|
||||||
} else {
|
} else {
|
||||||
double slept;
|
|
||||||
double percentage;
|
double percentage;
|
||||||
double newticks;
|
double newticks;
|
||||||
|
|
||||||
|
@ -721,7 +818,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
if (newticks < 0)
|
if (newticks < 0)
|
||||||
newticks = 0;
|
newticks = 0;
|
||||||
|
|
||||||
sprintf(cstate_lines[0], "Cn\t Avg residency\n");
|
sprintf(cstate_lines[0], "Cn\t\t Avg residency\n");
|
||||||
percentage = newticks * 100.0 / (G.total_cpus * DEFAULT_SLEEP * FREQ_ACPI_1000);
|
percentage = newticks * 100.0 / (G.total_cpus * DEFAULT_SLEEP * FREQ_ACPI_1000);
|
||||||
sprintf(cstate_lines[1], "C0 (cpu running) (%4.1f%%)\n",
|
sprintf(cstate_lines[1], "C0 (cpu running) (%4.1f%%)\n",
|
||||||
percentage);
|
percentage);
|
||||||
|
@ -729,6 +826,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
/* Compute values for individual C-states */
|
/* Compute values for individual C-states */
|
||||||
for (i = 0; i < MAX_CSTATE_COUNT; i++) {
|
for (i = 0; i < MAX_CSTATE_COUNT; i++) {
|
||||||
if (cur_usage[i] != 0) {
|
if (cur_usage[i] != 0) {
|
||||||
|
double slept;
|
||||||
slept = (cur_duration[i] - G.last_duration[i])
|
slept = (cur_duration[i] - G.last_duration[i])
|
||||||
/ (cur_usage[i] - G.last_usage[i] + 0.1) / FREQ_ACPI;
|
/ (cur_usage[i] - G.last_usage[i] + 0.1) / FREQ_ACPI;
|
||||||
percentage = (cur_duration[i] - G.last_duration[i]) * 100
|
percentage = (cur_duration[i] - G.last_duration[i]) * 100
|
||||||
|
@ -736,125 +834,35 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
|
||||||
|
|
||||||
if (!G.cstate_names[i][0])
|
if (!G.cstate_names[i][0])
|
||||||
sprintf(G.cstate_names[i], "C%u", i + 1);
|
sprintf(G.cstate_names[i], "C%u", i + 1);
|
||||||
sprintf(cstate_lines[i + 2], "%s\t%5.1fms (%4.1f%%)\n",
|
sprintf(cstate_lines[i + 2], "%s\t\t%5.1fms (%4.1f%%)\n",
|
||||||
G.cstate_names[i], slept, percentage);
|
G.cstate_names[i], slept, percentage);
|
||||||
/*if (maxsleep < slept)
|
//if (maxsleep < slept)
|
||||||
maxsleep = slept;*/
|
// maxsleep = slept;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display C-states */
|
for (i = 0; i < MAX_CSTATE_COUNT + 2; i++)
|
||||||
show_cstates(cstate_lines);
|
if (cstate_lines[i][0])
|
||||||
|
printf("%s", cstate_lines[i]);
|
||||||
/* Do timer_stats info */
|
|
||||||
buf[0] = '\0';
|
|
||||||
totalticks = 0;
|
|
||||||
|
|
||||||
fp = NULL;
|
|
||||||
if (!G.cant_enable_timer_stats)
|
|
||||||
fp = fopen_for_read("/proc/timer_stats");
|
|
||||||
if (fp) {
|
|
||||||
// Examlpe file contents:
|
|
||||||
// Timer Stats Version: v0.2
|
|
||||||
// Sample period: 1.329 s
|
|
||||||
// 76, 0 swapper hrtimer_start_range_ns (tick_sched_timer)
|
|
||||||
// 88, 0 swapper hrtimer_start_range_ns (tick_sched_timer)
|
|
||||||
// 24, 3787 firefox hrtimer_start_range_ns (hrtimer_wakeup)
|
|
||||||
// 46D, 1136 kondemand/1 do_dbs_timer (delayed_work_timer_fn)
|
|
||||||
// ...
|
|
||||||
// 1, 1656 Xorg hrtimer_start_range_ns (hrtimer_wakeup)
|
|
||||||
// 1, 2159 udisks-daemon hrtimer_start_range_ns (hrtimer_wakeup)
|
|
||||||
// 331 total events, 249.059 events/sec
|
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
|
||||||
const char *count, *process, *func;
|
|
||||||
char *p;
|
|
||||||
char line[512];
|
|
||||||
int cnt = 0;
|
|
||||||
// TODO: optimize
|
|
||||||
if (strstr(buf, "total events"))
|
|
||||||
break;
|
|
||||||
count = skip_whitespace(buf);
|
|
||||||
p = strchr(count, ',');
|
|
||||||
if (!p)
|
|
||||||
continue;
|
|
||||||
*p++ = '\0';
|
|
||||||
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);
|
|
||||||
func = p;
|
|
||||||
|
|
||||||
if (strcmp(process, "swapper") == 0
|
|
||||||
&& strcmp(func, "hrtimer_start_range_ns (tick_sched_timer)\n") == 0
|
|
||||||
) {
|
|
||||||
process = "[kernel scheduler]";
|
|
||||||
func = "Load balancing tick";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(process, "insmod") == 0)
|
|
||||||
process = "[kernel module]";
|
|
||||||
if (strcmp(process, "modprobe") == 0)
|
|
||||||
process = "[kernel module]";
|
|
||||||
if (strcmp(process, "swapper") == 0)
|
|
||||||
process = "[kernel core]";
|
|
||||||
|
|
||||||
if (strncmp(func, "tick_nohz_", 10) == 0)
|
|
||||||
continue;
|
|
||||||
if (strncmp(func, "tick_setup_sched_timer", 20) == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(process, "powertop") == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
strchrnul(p, '\n')[0] = '\0';
|
|
||||||
|
|
||||||
cnt = bb_strtoull(count, &p, 10);
|
|
||||||
while (*p != '\0') {
|
|
||||||
if (*p++ == 'D')
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr(process, '['))
|
|
||||||
sprintf(line, "%s %s", process, func);
|
|
||||||
else
|
|
||||||
sprintf(line, "%s", process);
|
|
||||||
save_line(line, cnt);
|
|
||||||
skip: ;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
i = process_timer_stats();
|
||||||
#if ENABLE_FEATURE_POWERTOP_PROCIRQ
|
#if ENABLE_FEATURE_POWERTOP_PROCIRQ
|
||||||
if (strstr(buf, "total events")) {
|
if (totalevents == 0) {
|
||||||
int n = bb_strtoull(buf, NULL, 10) / G.total_cpus;
|
/* No C-state info available, use timerstats */
|
||||||
|
totalevents = i * G.total_cpus + G.total_interrupt;
|
||||||
if (totalevents == 0) {
|
if (i < 0)
|
||||||
/* No C-state info available, use timerstats */
|
totalevents += G.interrupt_0 - i;
|
||||||
totalevents = n * G.total_cpus + G.total_interrupt;
|
|
||||||
if (n < 0)
|
|
||||||
totalevents += G.interrupt_0 - n;
|
|
||||||
}
|
|
||||||
if (n > 0 && n < G.interrupt_0)
|
|
||||||
save_line("[extra timer interrupt]", G.interrupt_0 - n);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (totalevents != 0)
|
/* Upstream powertop prints wakeups per sec per CPU,
|
||||||
printf("\n\033[1mWakeups-from-idle per second : %4.1f\tinterval:"
|
* we print just raw wakeup counts.
|
||||||
"%ds\n\033[0m",
|
*/
|
||||||
(double)totalevents / DEFAULT_SLEEP / G.total_cpus, DEFAULT_SLEEP);
|
//TODO: show real seconds (think about manual refresh)
|
||||||
|
printf("\nWakeups-from-idle in %u seconds: %llu\n",
|
||||||
|
DEFAULT_SLEEP,
|
||||||
|
totalevents
|
||||||
|
);
|
||||||
|
|
||||||
update_lines_cumulative_count();
|
update_lines_cumulative_count();
|
||||||
sort_lines();
|
sort_lines();
|
||||||
|
|
Loading…
Reference in New Issue