xref: /aosp_15_r20/external/autotest/client/profilers/powertop/src/display.c (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li /*
2*9c5db199SXin Li  * Copyright 2007, Intel Corporation
3*9c5db199SXin Li  *
4*9c5db199SXin Li  * This file is part of PowerTOP
5*9c5db199SXin Li  *
6*9c5db199SXin Li  * This program file is free software; you can redistribute it and/or modify it
7*9c5db199SXin Li  * under the terms of the GNU General Public License as published by the
8*9c5db199SXin Li  * Free Software Foundation; version 2 of the License.
9*9c5db199SXin Li  *
10*9c5db199SXin Li  * This program is distributed in the hope that it will be useful, but WITHOUT
11*9c5db199SXin Li  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12*9c5db199SXin Li  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13*9c5db199SXin Li  * for more details.
14*9c5db199SXin Li  *
15*9c5db199SXin Li  * You should have received a copy of the GNU General Public License
16*9c5db199SXin Li  * along with this program in a file named COPYING; if not, write to the
17*9c5db199SXin Li  * Free Software Foundation, Inc.,
18*9c5db199SXin Li  * 51 Franklin Street, Fifth Floor,
19*9c5db199SXin Li  * Boston, MA 02110-1301 USA
20*9c5db199SXin Li  *
21*9c5db199SXin Li  * Authors:
22*9c5db199SXin Li  * 	Arjan van de Ven <[email protected]>
23*9c5db199SXin Li  */
24*9c5db199SXin Li 
25*9c5db199SXin Li #include <unistd.h>
26*9c5db199SXin Li #include <stdio.h>
27*9c5db199SXin Li #include <stdlib.h>
28*9c5db199SXin Li #include <string.h>
29*9c5db199SXin Li #include <stdint.h>
30*9c5db199SXin Li #include <sys/types.h>
31*9c5db199SXin Li #include <dirent.h>
32*9c5db199SXin Li #include <ncurses.h>
33*9c5db199SXin Li #include <time.h>
34*9c5db199SXin Li #include <wchar.h>
35*9c5db199SXin Li 
36*9c5db199SXin Li #include "powertop.h"
37*9c5db199SXin Li 
38*9c5db199SXin Li static WINDOW *title_bar_window;
39*9c5db199SXin Li static WINDOW *cstate_window;
40*9c5db199SXin Li static WINDOW *wakeup_window;
41*9c5db199SXin Li static WINDOW *battery_power_window;
42*9c5db199SXin Li static WINDOW *timerstat_window;
43*9c5db199SXin Li static WINDOW *suggestion_window;
44*9c5db199SXin Li static WINDOW *status_bar_window;
45*9c5db199SXin Li 
46*9c5db199SXin Li #define print(win, y, x, fmt, args...) do { if (dump) printf(fmt, ## args); else mvwprintw(win, y, x, fmt, ## args); } while (0)
47*9c5db199SXin Li 
48*9c5db199SXin Li char status_bar_slots[10][40];
49*9c5db199SXin Li 
cleanup_curses(void)50*9c5db199SXin Li static void cleanup_curses(void) {
51*9c5db199SXin Li 	endwin();
52*9c5db199SXin Li }
53*9c5db199SXin Li 
zap_windows(void)54*9c5db199SXin Li static void zap_windows(void)
55*9c5db199SXin Li {
56*9c5db199SXin Li 	if (title_bar_window) {
57*9c5db199SXin Li 		delwin(title_bar_window);
58*9c5db199SXin Li 		title_bar_window = NULL;
59*9c5db199SXin Li 	}
60*9c5db199SXin Li 	if (cstate_window) {
61*9c5db199SXin Li 		delwin(cstate_window);
62*9c5db199SXin Li 		cstate_window = NULL;
63*9c5db199SXin Li 	}
64*9c5db199SXin Li 	if (wakeup_window) {
65*9c5db199SXin Li 		delwin(wakeup_window);
66*9c5db199SXin Li 		wakeup_window = NULL;
67*9c5db199SXin Li 	}
68*9c5db199SXin Li 	if (battery_power_window) {
69*9c5db199SXin Li 		delwin(battery_power_window);
70*9c5db199SXin Li 		battery_power_window = NULL;
71*9c5db199SXin Li 	}
72*9c5db199SXin Li 	if (timerstat_window) {
73*9c5db199SXin Li 		delwin(timerstat_window);
74*9c5db199SXin Li 		timerstat_window = NULL;
75*9c5db199SXin Li 	}
76*9c5db199SXin Li 	if (suggestion_window) {
77*9c5db199SXin Li 		delwin(suggestion_window);
78*9c5db199SXin Li 		suggestion_window = NULL;
79*9c5db199SXin Li 	}
80*9c5db199SXin Li 	if (status_bar_window) {
81*9c5db199SXin Li 		delwin(status_bar_window);
82*9c5db199SXin Li 		status_bar_window = NULL;
83*9c5db199SXin Li 	}
84*9c5db199SXin Li }
85*9c5db199SXin Li 
86*9c5db199SXin Li 
87*9c5db199SXin Li int maxx, maxy;
88*9c5db199SXin Li 
89*9c5db199SXin Li int maxtimerstats = 50;
90*9c5db199SXin Li int maxwidth = 200;
91*9c5db199SXin Li 
setup_windows(void)92*9c5db199SXin Li void setup_windows(void)
93*9c5db199SXin Li {
94*9c5db199SXin Li 	getmaxyx(stdscr, maxy, maxx);
95*9c5db199SXin Li 
96*9c5db199SXin Li 	zap_windows();
97*9c5db199SXin Li 
98*9c5db199SXin Li 	title_bar_window = subwin(stdscr, 1, maxx, 0, 0);
99*9c5db199SXin Li 	cstate_window = subwin(stdscr, 7, maxx, 2, 0);
100*9c5db199SXin Li 	wakeup_window = subwin(stdscr, 1, maxx, 9, 0);
101*9c5db199SXin Li 	battery_power_window = subwin(stdscr, 2, maxx, 10, 0);
102*9c5db199SXin Li 	timerstat_window = subwin(stdscr, maxy-16, maxx, 12, 0);
103*9c5db199SXin Li 	maxtimerstats = maxy-16  -2;
104*9c5db199SXin Li 	maxwidth = maxx - 18;
105*9c5db199SXin Li 	suggestion_window = subwin(stdscr, 3, maxx, maxy-4, 0);
106*9c5db199SXin Li 	status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0);
107*9c5db199SXin Li 
108*9c5db199SXin Li 	strcpy(status_bar_slots[0], _(" Q - Quit "));
109*9c5db199SXin Li 	strcpy(status_bar_slots[1], _(" R - Refresh "));
110*9c5db199SXin Li 
111*9c5db199SXin Li 	werase(stdscr);
112*9c5db199SXin Li 	refresh();
113*9c5db199SXin Li }
114*9c5db199SXin Li 
initialize_curses(void)115*9c5db199SXin Li void initialize_curses(void)
116*9c5db199SXin Li {
117*9c5db199SXin Li 	initscr();
118*9c5db199SXin Li 	start_color();
119*9c5db199SXin Li 	keypad(stdscr, TRUE);	/* enable keyboard mapping */
120*9c5db199SXin Li 	nonl();			/* tell curses not to do NL->CR/NL on output */
121*9c5db199SXin Li 	cbreak();		/* take input chars one at a time, no wait for \n */
122*9c5db199SXin Li 	noecho();		/* dont echo input */
123*9c5db199SXin Li 	curs_set(0);		/* turn off cursor */
124*9c5db199SXin Li 	use_default_colors();
125*9c5db199SXin Li 
126*9c5db199SXin Li 	init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
127*9c5db199SXin Li 	init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
128*9c5db199SXin Li 	init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
129*9c5db199SXin Li 	init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
130*9c5db199SXin Li 	init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
131*9c5db199SXin Li 	init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
132*9c5db199SXin Li 	init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
133*9c5db199SXin Li 	init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
134*9c5db199SXin Li 
135*9c5db199SXin Li 	atexit(cleanup_curses);
136*9c5db199SXin Li }
137*9c5db199SXin Li 
show_title_bar(void)138*9c5db199SXin Li void show_title_bar(void)
139*9c5db199SXin Li {
140*9c5db199SXin Li 	int i;
141*9c5db199SXin Li 	int x;
142*9c5db199SXin Li 	wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
143*9c5db199SXin Li 	wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
144*9c5db199SXin Li 	werase(title_bar_window);
145*9c5db199SXin Li 
146*9c5db199SXin Li 	print(title_bar_window, 0, 0,  "     PowerTOP version 1.11      (C) 2007 Intel Corporation");
147*9c5db199SXin Li 
148*9c5db199SXin Li 	wrefresh(title_bar_window);
149*9c5db199SXin Li 
150*9c5db199SXin Li 	werase(status_bar_window);
151*9c5db199SXin Li 
152*9c5db199SXin Li 	x = 0;
153*9c5db199SXin Li 	for (i=0; i<10; i++) {
154*9c5db199SXin Li 		if (strlen(status_bar_slots[i])==0)
155*9c5db199SXin Li 			continue;
156*9c5db199SXin Li 		wattron(status_bar_window, A_REVERSE);
157*9c5db199SXin Li 		print(status_bar_window, 0, x, status_bar_slots[i]);
158*9c5db199SXin Li 		wattroff(status_bar_window, A_REVERSE);
159*9c5db199SXin Li 		x+= strlen(status_bar_slots[i])+1;
160*9c5db199SXin Li 	}
161*9c5db199SXin Li 	wrefresh(status_bar_window);
162*9c5db199SXin Li }
163*9c5db199SXin Li 
show_cstates(void)164*9c5db199SXin Li void show_cstates(void)
165*9c5db199SXin Li {
166*9c5db199SXin Li 	int i, count = 0;
167*9c5db199SXin Li 	werase(cstate_window);
168*9c5db199SXin Li 
169*9c5db199SXin Li 	for (i=0; i < 10; i++) {
170*9c5db199SXin Li 		if (i == topcstate+1)
171*9c5db199SXin Li 			wattron(cstate_window, A_BOLD);
172*9c5db199SXin Li 		else
173*9c5db199SXin Li 			wattroff(cstate_window, A_BOLD);
174*9c5db199SXin Li 		if (strlen(cstate_lines[i]) && count <= 6) {
175*9c5db199SXin Li 			print(cstate_window, count, 0, "%s", cstate_lines[i]);
176*9c5db199SXin Li 			count++;
177*9c5db199SXin Li 		}
178*9c5db199SXin Li 	}
179*9c5db199SXin Li 
180*9c5db199SXin Li 	for (i=0; i<6; i++) {
181*9c5db199SXin Li 		if (i == topfreq+1)
182*9c5db199SXin Li 			wattron(cstate_window, A_BOLD);
183*9c5db199SXin Li 		else
184*9c5db199SXin Li 			wattroff(cstate_window, A_BOLD);
185*9c5db199SXin Li 		print(cstate_window, i, 38, "%s", cpufreqstrings[i]);
186*9c5db199SXin Li 	}
187*9c5db199SXin Li 
188*9c5db199SXin Li 	wrefresh(cstate_window);
189*9c5db199SXin Li }
190*9c5db199SXin Li 
191*9c5db199SXin Li 
show_acpi_power_line(double rate,double cap,double capdelta,time_t ti)192*9c5db199SXin Li void show_acpi_power_line(double rate, double cap, double capdelta, time_t ti)
193*9c5db199SXin Li {
194*9c5db199SXin Li 	char buffer[1024];
195*9c5db199SXin Li 
196*9c5db199SXin Li 	sprintf(buffer,  _("no ACPI power usage estimate available") );
197*9c5db199SXin Li 
198*9c5db199SXin Li 	werase(battery_power_window);
199*9c5db199SXin Li 	if (rate > 0.001) {
200*9c5db199SXin Li 		char *c;
201*9c5db199SXin Li 		sprintf(buffer, _("Power usage (ACPI estimate): %3.1fW (%3.1f hours)"), rate, cap/rate);
202*9c5db199SXin Li 		strcat(buffer, " ");
203*9c5db199SXin Li 		c = &buffer[strlen(buffer)];
204*9c5db199SXin Li 		if (ti>180 && capdelta > 0)
205*9c5db199SXin Li 			sprintf(c, _("(long term: %3.1fW,/%3.1fh)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01));
206*9c5db199SXin Li 	}
207*9c5db199SXin Li 	else if (ti>120 && capdelta > 0.001)
208*9c5db199SXin Li 		sprintf(buffer, _("Power usage (5 minute ACPI estimate) : %5.1f W (%3.1f hours left)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01));
209*9c5db199SXin Li 
210*9c5db199SXin Li 	print(battery_power_window, 0, 0, "%s\n", buffer);
211*9c5db199SXin Li 	wrefresh(battery_power_window);
212*9c5db199SXin Li }
213*9c5db199SXin Li 
show_pmu_power_line(unsigned sum_voltage_mV,unsigned sum_charge_mAh,unsigned sum_max_charge_mAh,int sum_discharge_mA)214*9c5db199SXin Li void show_pmu_power_line(unsigned sum_voltage_mV,
215*9c5db199SXin Li                          unsigned sum_charge_mAh, unsigned sum_max_charge_mAh,
216*9c5db199SXin Li                          int sum_discharge_mA)
217*9c5db199SXin Li {
218*9c5db199SXin Li 	char buffer[1024];
219*9c5db199SXin Li 
220*9c5db199SXin Li 	if (sum_discharge_mA != 0)
221*9c5db199SXin Li 	{
222*9c5db199SXin Li 		unsigned remaining_charge_mAh;
223*9c5db199SXin Li 
224*9c5db199SXin Li 		if (sum_discharge_mA < 0)
225*9c5db199SXin Li 		{
226*9c5db199SXin Li 			/* we are currently discharging */
227*9c5db199SXin Li 			sum_discharge_mA = -sum_discharge_mA;
228*9c5db199SXin Li 			remaining_charge_mAh = sum_charge_mAh;
229*9c5db199SXin Li 		}
230*9c5db199SXin Li 		else
231*9c5db199SXin Li 		{
232*9c5db199SXin Li 			/* we are currently charging */
233*9c5db199SXin Li 			remaining_charge_mAh = (sum_max_charge_mAh
234*9c5db199SXin Li 						- sum_charge_mAh);
235*9c5db199SXin Li 		}
236*9c5db199SXin Li 
237*9c5db199SXin Li 		snprintf(buffer, sizeof(buffer),
238*9c5db199SXin Li 			 _("Power usage: %3.1fW (%3.1f hours)"),
239*9c5db199SXin Li 			 sum_voltage_mV * sum_discharge_mA / 1e6,
240*9c5db199SXin Li 			 (double)remaining_charge_mAh / sum_discharge_mA);
241*9c5db199SXin Li 	}
242*9c5db199SXin Li 	else
243*9c5db199SXin Li 		snprintf(buffer, sizeof(buffer),
244*9c5db199SXin Li 			 _("no power usage estimate available") );
245*9c5db199SXin Li 
246*9c5db199SXin Li 	werase(battery_power_window);
247*9c5db199SXin Li 	print(battery_power_window, 0, 0, "%s\n", buffer);
248*9c5db199SXin Li 	wrefresh(battery_power_window);
249*9c5db199SXin Li }
250*9c5db199SXin Li 
251*9c5db199SXin Li 
show_wakeups(double d,double interval,double C0time)252*9c5db199SXin Li void show_wakeups(double d, double interval, double C0time)
253*9c5db199SXin Li {
254*9c5db199SXin Li 	werase(wakeup_window);
255*9c5db199SXin Li 
256*9c5db199SXin Li 	wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED));
257*9c5db199SXin Li 	if (d <= 25.0)
258*9c5db199SXin Li 		wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_YELLOW));
259*9c5db199SXin Li 	if (d <= 10.0)
260*9c5db199SXin Li 		wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_GREEN));
261*9c5db199SXin Li 
262*9c5db199SXin Li 	/*
263*9c5db199SXin Li 	 * if the cpu is really busy.... then make it blue to indicate
264*9c5db199SXin Li 	 * that it's not the primary power consumer anymore
265*9c5db199SXin Li 	 */
266*9c5db199SXin Li 	if (C0time > 25.0)
267*9c5db199SXin Li 		wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_BLUE));
268*9c5db199SXin Li 
269*9c5db199SXin Li 	wattron(wakeup_window, A_BOLD);
270*9c5db199SXin Li 	print(wakeup_window, 0, 0, _("Wakeups-from-idle per second : %4.1f\tinterval: %0.1fs\n"), d, interval);
271*9c5db199SXin Li 	wrefresh(wakeup_window);
272*9c5db199SXin Li }
273*9c5db199SXin Li 
show_timerstats(int nostats,int ticktime)274*9c5db199SXin Li void show_timerstats(int nostats, int ticktime)
275*9c5db199SXin Li {
276*9c5db199SXin Li 	int i;
277*9c5db199SXin Li 	werase(timerstat_window);
278*9c5db199SXin Li 
279*9c5db199SXin Li 	if (!nostats) {
280*9c5db199SXin Li 		int counter = 0;
281*9c5db199SXin Li 		print(timerstat_window, 0, 0, _("Top causes for wakeups:\n"));
282*9c5db199SXin Li 		for (i = 0; i < linehead; i++)
283*9c5db199SXin Li 			if (lines[i].count > 0 && counter++ < maxtimerstats) {
284*9c5db199SXin Li 				if ((lines[i].count * 1.0 / ticktime) >= 10.0)
285*9c5db199SXin Li 					wattron(timerstat_window, A_BOLD);
286*9c5db199SXin Li 				else
287*9c5db199SXin Li 					wattroff(timerstat_window, A_BOLD);
288*9c5db199SXin Li 				if (showpids)
289*9c5db199SXin Li 					print(timerstat_window, i+1, 0," %5.1f%% (%5.1f)   [%6s] %s \n", lines[i].count * 100.0 / linectotal,
290*9c5db199SXin Li 						lines[i].count * 1.0 / ticktime,
291*9c5db199SXin Li 						lines[i].pid, lines[i].string);
292*9c5db199SXin Li 				else
293*9c5db199SXin Li 					print(timerstat_window, i+1, 0," %5.1f%% (%5.1f)   %s \n", lines[i].count * 100.0 / linectotal,
294*9c5db199SXin Li 						lines[i].count * 1.0 / ticktime,
295*9c5db199SXin Li 						lines[i].string);
296*9c5db199SXin Li 				}
297*9c5db199SXin Li 	} else {
298*9c5db199SXin Li 		if (geteuid() == 0) {
299*9c5db199SXin Li 			print(timerstat_window, 0, 0, _("No detailed statistics available; please enable the CONFIG_TIMER_STATS kernel option\n"));
300*9c5db199SXin Li 			print(timerstat_window, 1, 0, _("This option is located in the Kernel Debugging section of menuconfig\n"));
301*9c5db199SXin Li 			print(timerstat_window, 2, 0, _("(which is CONFIG_DEBUG_KERNEL=y in the config file)\n"));
302*9c5db199SXin Li 			print(timerstat_window, 3, 0, _("Note: this is only available in 2.6.21 and later kernels\n"));
303*9c5db199SXin Li 		} else
304*9c5db199SXin Li 			print(timerstat_window, 0, 0, _("No detailed statistics available; PowerTOP needs root privileges for that\n"));
305*9c5db199SXin Li 	}
306*9c5db199SXin Li 
307*9c5db199SXin Li 
308*9c5db199SXin Li 	wrefresh(timerstat_window);
309*9c5db199SXin Li }
310*9c5db199SXin Li 
show_suggestion(char * sug)311*9c5db199SXin Li void show_suggestion(char *sug)
312*9c5db199SXin Li {
313*9c5db199SXin Li 	werase(suggestion_window);
314*9c5db199SXin Li 	print(suggestion_window, 0, 0, "%s", sug);
315*9c5db199SXin Li 	wrefresh(suggestion_window);
316*9c5db199SXin Li }
317