[PATCH RFC] dump wakeups to stdout

Bill Nottingham notting at redhat.com
Thu Jun 28 13:56:49 PDT 2007


As powertop is run now, it's a little tricky to get the list of
offending apps recorded for posterity or reporting.

This patch adds support for dumping the displayed data to stdout,
instead of into a ncurses window. It's not the cleanest thing in
the world, but it works. Required some minor tweaks to the display
routines (mostly adding some newlines).

Other things introduced in the process:
- getopt handling so you can specify this
- add an option to change the reporting period

Opinions? I'm still debating if this is the best mechanism
for what I'd like to do with it. (Basically, make it easy for users
to submit reports.)

Bill
-------------- next part --------------
diff -ru powertop-1.7/cpufreqstats.c powertop-1.7-new/cpufreqstats.c
--- powertop-1.7/cpufreqstats.c	2007-06-17 12:05:10.000000000 -0400
+++ powertop-1.7-new/cpufreqstats.c	2007-06-28 16:38:30.000000000 -0400
@@ -42,7 +42,7 @@
 
 struct cpufreqdata delta[16];
 
-char cpufreqstrings[4][80];
+char cpufreqstrings[5][80];
 int topfreq = -1;
 
 static void zap(void)
@@ -98,6 +98,7 @@
 
 	memcpy(&oldfreqs, &freqs, sizeof(freqs));
 	memset(&cpufreqstrings, 0, sizeof(cpufreqstrings));
+	sprintf(cpufreqstrings[0], _("P-states (frequencies)\n"));
 
 	for (ret = 0; ret<16; ret++)
 		freqs[ret].count = 0;
@@ -164,8 +165,8 @@
 	qsort(&delta, maxfreq+1, sizeof(struct cpufreqdata), sort_by_freq);
 
 	topfreq = -1;
-	for (ret =0 ; ret<=maxfreq; ret++) {
-		sprintf(cpufreqstrings[ret], "%6s   %5.1f%%", HzToHuman(delta[ret].frequency), delta[ret].count * 100.0 / total_time);
+	for (ret = 0 ; ret<=maxfreq; ret++) {
+		sprintf(cpufreqstrings[ret+1], "%6s   %5.1f%%\n", HzToHuman(delta[ret].frequency), delta[ret].count * 100.0 / total_time);
 		if (delta[ret].count > total_time/2)
 			topfreq = ret;
 	}
diff -ru powertop-1.7/display.c powertop-1.7-new/display.c
--- powertop-1.7/display.c	2007-06-17 21:16:33.000000000 -0400
+++ powertop-1.7-new/display.c	2007-06-28 16:38:30.000000000 -0400
@@ -43,6 +43,7 @@
 static WINDOW *suggestion_window;
 static WINDOW *status_bar_window;
 
+#define print(win, y, x, fmt, args...) if (dump) printf(fmt, ## args); else mvwprintw(win, y, x, fmt, ## args)
 
 char status_bar_slots[10][40];
 
@@ -85,8 +86,8 @@
 
 int maxx, maxy;
 
-int maxtimerstats;
-int maxwidth;
+int maxtimerstats = 50;
+int maxwidth = 200;
 
 void setup_windows(void) 
 {
@@ -141,7 +142,7 @@
 	wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));   
 	werase(title_bar_window);
 
-	mvwprintw(title_bar_window, 0, 0,  "     PowerTOP version 1.7       (C) 2007 Intel Corporation");
+	print(title_bar_window, 0, 0,  "     PowerTOP version 1.7       (C) 2007 Intel Corporation");
 
 	wrefresh(title_bar_window);
 
@@ -152,7 +153,7 @@
 		if (strlen(status_bar_slots[i])==0)
 			continue;
 		wattron(status_bar_window, A_REVERSE);
-		mvwprintw(status_bar_window, 0, x, status_bar_slots[i]);
+		print(status_bar_window, 0, x, status_bar_slots[i]);
 		wattroff(status_bar_window, A_REVERSE);			
 		x+= strlen(status_bar_slots[i])+1;
 	}
@@ -169,15 +170,15 @@
 			wattron(cstate_window, A_BOLD);
 		else
 			wattroff(cstate_window, A_BOLD);			
-		mvwprintw(cstate_window, i, 0, "%s", cstate_lines[i]);
+		print(cstate_window, i, 0, "%s", cstate_lines[i]);
 	}
 
-	for (i=0; i<4; i++) {
+	for (i=0; i<5; i++) {
 		if (i == topfreq)
 			wattron(cstate_window, A_BOLD);
 		else
 			wattroff(cstate_window, A_BOLD);			
-		mvwprintw(cstate_window, i+2, 38, "%s", cpufreqstrings[i]);
+		print(cstate_window, i, 38, "%s", cpufreqstrings[i]);
 	}
 
 	wrefresh(cstate_window);
@@ -202,7 +203,7 @@
 	else if (ti>120 && capdelta > 0.001)
 		sprintf(buffer, _("Power usage (5 minute ACPI estimate) : %5.1f W (%3.1f hours left)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01));
 
-	mvwprintw(acpi_power_window, 0, 0, buffer);	
+	print(acpi_power_window, 0, 0, "%s\n", buffer);	
 	wrefresh(acpi_power_window);
 }
 
@@ -217,7 +218,7 @@
 		wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_GREEN));   
 		
 	wattron(wakeup_window, A_BOLD);
-	mvwprintw(wakeup_window, 0, 0, _("Wakeups-from-idle per second : %4.1f"), d);
+	print(wakeup_window, 0, 0, _("Wakeups-from-idle per second : %4.1f\n"), d);
 	wrefresh(wakeup_window);
 }
 
@@ -228,25 +229,25 @@
 
 	if (!nostats) {
 		int counter = 0;
-		mvwprintw(timerstat_window, 0, 0, _("Top causes for wakeups:"));
+		print(timerstat_window, 0, 0, _("Top causes for wakeups:\n"));
 		for (i = 0; i < linehead; i++)
 			if (lines[i].count > 0 && counter++ < maxtimerstats) {
 				if ((lines[i].count * 1.0 / ticktime) >= 10.0)
 					wattron(timerstat_window, A_BOLD);
 				else
 					wattroff(timerstat_window, A_BOLD);
-				mvwprintw(timerstat_window, i+1, 0," %5.1f%% (%5.1f)   %s ", lines[i].count * 100.0 / linectotal,
+				print(timerstat_window, i+1, 0," %5.1f%% (%5.1f)   %s \n", lines[i].count * 100.0 / linectotal,
 						lines[i].count * 1.0 / ticktime, 
 						lines[i].string);
 				}
 	} else {
 		if (getuid() == 0) {
-			mvwprintw(timerstat_window, 0, 0, _("No detailed statistics available; please enable the CONFIG_TIMER_STATS kernel option\n"));
-			mvwprintw(timerstat_window, 1, 0, _("This option is located in the Kernel Debugging section of menuconfig\n"));
-			mvwprintw(timerstat_window, 2, 0, _("(which is CONFIG_DEBUG_KERNEL=y in the config file)\n"));
-			mvwprintw(timerstat_window, 3, 0, _("Note: this is only available in 2.6.21 and later kernels\n"));
+			print(timerstat_window, 0, 0, _("No detailed statistics available; please enable the CONFIG_TIMER_STATS kernel option\n"));
+			print(timerstat_window, 1, 0, _("This option is located in the Kernel Debugging section of menuconfig\n"));
+			print(timerstat_window, 2, 0, _("(which is CONFIG_DEBUG_KERNEL=y in the config file)\n"));
+			print(timerstat_window, 3, 0, _("Note: this is only available in 2.6.21 and later kernels\n"));
 		} else
-			mvwprintw(timerstat_window, 0, 0, _("No detailed statistics available; PowerTOP needs root privileges for that\n"));
+			print(timerstat_window, 0, 0, _("No detailed statistics available; PowerTOP needs root privileges for that\n"));
 	}
 
 
@@ -256,6 +257,6 @@
 void show_suggestion(char *sug)
 {
 	werase(suggestion_window);
-	mvwprintw(suggestion_window, 0, 0, "%s", sug);
+	print(suggestion_window, 0, 0, "%s", sug);
 	wrefresh(suggestion_window);
 }
diff -ru powertop-1.7/powertop.c powertop-1.7-new/powertop.c
--- powertop-1.7/powertop.c	2007-06-17 21:16:31.000000000 -0400
+++ powertop-1.7-new/powertop.c	2007-06-28 16:44:19.000000000 -0400
@@ -22,6 +22,7 @@
  * 	Arjan van de Ven <arjan at linux.intel.com>
  */
 
+#include <getopt.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -48,6 +49,8 @@
 static int maxcstate = 0;
 int topcstate = 0;
 
+int dump = 0;
+
 #define IRQCOUNT 100
 
 struct irqdata {
@@ -372,6 +375,15 @@
 
 char cstate_lines[6][200];
 
+void usage()
+{
+	printf(_("Usage: powertop [OPTION...]\n"));
+	printf(_("  -d, --dump            read wakeups once and print list of top offenders\n"));
+	printf(_("  -t, --time=DOUBLE     default time to gather data in seconds\n"));
+	printf(_("  -h, --help            Show this help message\n"));
+	exit(0);
+}
+
 int main(int argc, char **argv)
 {
 	char line[1024];
@@ -380,14 +392,41 @@
 	uint64_t cur_usage[8], cur_duration[8];
 	double wakeups_per_second = 0;
 
-	read_data(&start_usage[0], &start_duration[0]);
-
-	system("modprobe cpufreq_stats &> /dev/null");
-
 	setlocale (LC_ALL, "");
 	bindtextdomain ("powertop", "/usr/share/locale");
 	textdomain ("powertop");
 
+	while (1) {
+		static struct option opts[] = {
+			{ "dump", 0, NULL, 'd' },
+			{ "time", 1, NULL, 't' },
+			{ "help", 0, NULL, 'h' },
+			{ 0, 0, NULL, 0 }
+		};
+		int index = 0, c;
+		
+		c = getopt_long(argc, argv, "dt:h", opts, &index);
+		if (c == -1)
+			break;
+		switch (c) {
+		case 'd':
+			dump = 1;
+			break;
+		case 't':
+			ticktime = strtod(optarg, NULL);
+			break;
+		case 'h':
+			usage();
+			break;
+		default:
+			printf("getopt returned %d\n", c);
+		}
+	}
+
+	system("modprobe cpufreq_stats &> /dev/null");
+
+	read_data(&start_usage[0], &start_duration[0]);
+
 	memcpy(last_usage, start_usage, sizeof(last_usage));
 	memcpy(last_duration, start_duration, sizeof(last_duration));
 
@@ -441,12 +480,14 @@
 				totalevents += cur_usage[i] - last_usage[i];
 			}
 
-		if (!ncursesinited) {
+		if (!ncursesinited && !dump) {
 			initialize_curses();  
 			ncursesinited++;
 		}
-		setup_windows();
-		show_title_bar();
+		if (!dump) {
+			setup_windows();
+			show_title_bar();
+		}
 
 		memset(&cstate_lines, 0, sizeof(cstate_lines));
 		topcstate = -4;
@@ -459,7 +500,7 @@
 			c0 = sysconf(_SC_NPROCESSORS_ONLN) * ticktime * 1000 * FREQ - totalticks;
 			if (c0 < 0)
 				c0 = 0;	/* rounding errors in measurement might make c0 go slightly negative.. this is confusing */
-			sprintf(cstate_lines[0], _("Cn\t    Avg residency (%is)\t\tP-states (frequencies)\n"), (int)ticktime);
+			sprintf(cstate_lines[0], _("Cn\t    Avg residency (%is)\n"), (int)ticktime);
 			sprintf(cstate_lines[1], _("C0 (cpu running)        (%4.1f%%)\n"), c0 * 100.0 / (sysconf(_SC_NPROCESSORS_ONLN) * ticktime * 1000 * FREQ));
 			for (i = 0; i < 4; i++)
 				if (cur_usage[i]) {
@@ -594,7 +635,8 @@
 		if (wakeups_per_second < 0)
 			ticktime = 2;
 
-
+		if (dump)
+			exit(EXIT_SUCCESS);
 		reset_suggestions();
 
 		suggest_kernel_config("CONFIG_USB_SUSPEND", 1,
Only in powertop-1.7-new: powertop.c~
diff -ru powertop-1.7/powertop.h powertop-1.7-new/powertop.h
--- powertop-1.7/powertop.h	2007-06-17 02:21:37.000000000 -0400
+++ powertop-1.7-new/powertop.h	2007-06-28 16:38:30.000000000 -0400
@@ -59,10 +59,11 @@
 
 
 extern char cstate_lines[6][200];
-extern char cpufreqstrings[4][80];
+extern char cpufreqstrings[5][80];
 
 extern int topcstate;
 extern int topfreq;  
+extern int dump;
 
 extern char status_bar_slots[10][40];
 extern char suggestion_key;


More information about the Power mailing list