xref: /titanic_53/usr/src/cmd/powertop/common/powertop.c (revision 636423db672c14451a65835f534789270ebd4dc9)
1b47b5b34SRafael Vanoni /*
2b47b5b34SRafael Vanoni  * Copyright 2009, Intel Corporation
3b47b5b34SRafael Vanoni  * Copyright 2009, Sun Microsystems, Inc
4b47b5b34SRafael Vanoni  *
5b47b5b34SRafael Vanoni  * This file is part of PowerTOP
6b47b5b34SRafael Vanoni  *
7b47b5b34SRafael Vanoni  * This program file is free software; you can redistribute it and/or modify it
8b47b5b34SRafael Vanoni  * under the terms of the GNU General Public License as published by the
9b47b5b34SRafael Vanoni  * Free Software Foundation; version 2 of the License.
10b47b5b34SRafael Vanoni  *
11b47b5b34SRafael Vanoni  * This program is distributed in the hope that it will be useful, but WITHOUT
12b47b5b34SRafael Vanoni  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13b47b5b34SRafael Vanoni  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14b47b5b34SRafael Vanoni  * for more details.
15b47b5b34SRafael Vanoni  *
16b47b5b34SRafael Vanoni  * You should have received a copy of the GNU General Public License
17b47b5b34SRafael Vanoni  * along with this program in a file named COPYING; if not, write to the
18b47b5b34SRafael Vanoni  * Free Software Foundation, Inc.,
19b47b5b34SRafael Vanoni  * 51 Franklin Street, Fifth Floor,
20b47b5b34SRafael Vanoni  * Boston, MA 02110-1301 USA
21b47b5b34SRafael Vanoni  *
22b47b5b34SRafael Vanoni  * Authors:
23b47b5b34SRafael Vanoni  *	Arjan van de Ven <arjan@linux.intel.com>
24b47b5b34SRafael Vanoni  *	Eric C Saxe <eric.saxe@sun.com>
25b47b5b34SRafael Vanoni  *	Aubrey Li <aubrey.li@intel.com>
26b47b5b34SRafael Vanoni  */
27b47b5b34SRafael Vanoni 
28b47b5b34SRafael Vanoni /*
29b47b5b34SRafael Vanoni  * GPL Disclaimer
30b47b5b34SRafael Vanoni  *
31b47b5b34SRafael Vanoni  * For the avoidance of doubt, except that if any license choice other
32b47b5b34SRafael Vanoni  * than GPL or LGPL is available it will apply instead, Sun elects to
33b47b5b34SRafael Vanoni  * use only the General Public License version 2 (GPLv2) at this time
34b47b5b34SRafael Vanoni  * for any software where a choice of GPL license versions is made
35b47b5b34SRafael Vanoni  * available with the language indicating that GPLv2 or any later
36b47b5b34SRafael Vanoni  * version may be used, or where a choice of which version of the GPL
37b47b5b34SRafael Vanoni  * is applied is otherwise unspecified.
38b47b5b34SRafael Vanoni  */
39b47b5b34SRafael Vanoni 
40b47b5b34SRafael Vanoni #include <getopt.h>
41b47b5b34SRafael Vanoni #include <unistd.h>
42b47b5b34SRafael Vanoni #include <stdio.h>
43b47b5b34SRafael Vanoni #include <stdlib.h>
44b47b5b34SRafael Vanoni #include <string.h>
45b47b5b34SRafael Vanoni #include <ctype.h>
46b47b5b34SRafael Vanoni #include <locale.h>
47b47b5b34SRafael Vanoni #include "powertop.h"
48b47b5b34SRafael Vanoni 
49b47b5b34SRafael Vanoni /*
50b47b5b34SRafael Vanoni  * Global variables, see powertop.h for comments and extern declarations.
51b47b5b34SRafael Vanoni  * These are ordered by type, grouped by usage.
52b47b5b34SRafael Vanoni  */
53b47b5b34SRafael Vanoni double 			g_ticktime, g_ticktime_usr;
54b47b5b34SRafael Vanoni double 			g_interval;
55b47b5b34SRafael Vanoni double			g_displaytime;
56b47b5b34SRafael Vanoni 
57b47b5b34SRafael Vanoni int			g_bit_depth;
58*636423dbSRafael Vanoni int 			g_total_events, g_top_events;
59b47b5b34SRafael Vanoni int			g_npstates, g_max_cstate, g_longest_cstate;
60b47b5b34SRafael Vanoni uint_t			g_ncpus;
61b47b5b34SRafael Vanoni uint_t			g_ncpus_observed;
62b47b5b34SRafael Vanoni 
63b47b5b34SRafael Vanoni processorid_t 		*g_cpu_table;
64b47b5b34SRafael Vanoni 
65b47b5b34SRafael Vanoni hrtime_t		g_total_c_time;
66b47b5b34SRafael Vanoni 
67b47b5b34SRafael Vanoni uchar_t			g_op_mode;
68b47b5b34SRafael Vanoni boolean_t		g_gui;
69b47b5b34SRafael Vanoni uint_t			g_observed_cpu;
70b47b5b34SRafael Vanoni 
71b47b5b34SRafael Vanoni event_info_t    	g_event_info[EVENT_NUM_MAX];
72b47b5b34SRafael Vanoni state_info_t		g_cstate_info[NSTATES];
73b47b5b34SRafael Vanoni freq_state_info_t	g_pstate_info[NSTATES];
74b47b5b34SRafael Vanoni cpu_power_info_t	*g_cpu_power_states;
75b47b5b34SRafael Vanoni suggestion_func 	*g_suggestion_activate;
76b47b5b34SRafael Vanoni 
77b47b5b34SRafael Vanoni boolean_t		g_turbo_supported;
78b47b5b34SRafael Vanoni 
79b47b5b34SRafael Vanoni uint_t			g_argc;
80b47b5b34SRafael Vanoni char			**g_argv;
81b47b5b34SRafael Vanoni 
82b47b5b34SRafael Vanoni char			*optarg;
83b47b5b34SRafael Vanoni 
84b47b5b34SRafael Vanoni static const int	true = 1;
85b47b5b34SRafael Vanoni 
86b47b5b34SRafael Vanoni int
87b47b5b34SRafael Vanoni main(int argc, char **argv)
88b47b5b34SRafael Vanoni {
89b47b5b34SRafael Vanoni 	hrtime_t 	last, now;
90b47b5b34SRafael Vanoni 	uint_t		features = 0, user_interval = 0;
91b47b5b34SRafael Vanoni 	int		ncursesinited = 0, index2 = 0, c, ret, dump_count = 0;
92b47b5b34SRafael Vanoni 	double		last_time;
93b47b5b34SRafael Vanoni 	char		*endptr;
94b47b5b34SRafael Vanoni 
95b47b5b34SRafael Vanoni 	static struct option opts[] = {
96b47b5b34SRafael Vanoni 		{ "dump", 1, NULL, 'd' },
97b47b5b34SRafael Vanoni 		{ "time", 1, NULL, 't' },
98b47b5b34SRafael Vanoni 		{ "help", 0, NULL, 'h' },
99b47b5b34SRafael Vanoni 		{ "cpu", 1, NULL, 'c' },
100b47b5b34SRafael Vanoni 		{ "verbose", 0, NULL, 'v' },
101b47b5b34SRafael Vanoni 		{ 0, 0, NULL, 0 }
102b47b5b34SRafael Vanoni 	};
103b47b5b34SRafael Vanoni 
104b47b5b34SRafael Vanoni 	(void) setlocale(LC_ALL, "");
105b47b5b34SRafael Vanoni 	(void) bindtextdomain("powertop", "/usr/share/locale");
106b47b5b34SRafael Vanoni 	(void) textdomain("powertop");
107b47b5b34SRafael Vanoni 
108b47b5b34SRafael Vanoni 	pt_set_progname(argv[0]);
109b47b5b34SRafael Vanoni 
110b47b5b34SRafael Vanoni 	/*
111b47b5b34SRafael Vanoni 	 * Enumerate the system's CPUs
112b47b5b34SRafael Vanoni 	 * Populate cpu_table, g_ncpus
113b47b5b34SRafael Vanoni 	 */
114b47b5b34SRafael Vanoni 	if ((g_ncpus = g_ncpus_observed = enumerate_cpus()) == 0)
115b47b5b34SRafael Vanoni 		exit(EXIT_FAILURE);
116b47b5b34SRafael Vanoni 
117b47b5b34SRafael Vanoni 	if ((g_bit_depth = get_bit_depth()) < 0)
118b47b5b34SRafael Vanoni 		exit(EXIT_FAILURE);
119b47b5b34SRafael Vanoni 
120b47b5b34SRafael Vanoni 	g_ticktime = g_ticktime_usr = INTERVAL_DEFAULT;
121b47b5b34SRafael Vanoni 	g_displaytime 	= 0.0;
122*636423dbSRafael Vanoni 	g_op_mode	= PT_MODE_DEFAULT;
123b47b5b34SRafael Vanoni 	g_gui		= B_FALSE;
124b47b5b34SRafael Vanoni 	g_max_cstate	= 0;
125b47b5b34SRafael Vanoni 	g_argv		= NULL;
126b47b5b34SRafael Vanoni 	g_argc		= 0;
127b47b5b34SRafael Vanoni 	g_observed_cpu	= 0;
128b47b5b34SRafael Vanoni 	g_turbo_supported = B_FALSE;
129b47b5b34SRafael Vanoni 
130b47b5b34SRafael Vanoni 	while ((c = getopt_long(argc, argv, "d:t:h:vc:", opts, &index2))
131b47b5b34SRafael Vanoni 	    != EOF) {
132b47b5b34SRafael Vanoni 		if (c == -1)
133b47b5b34SRafael Vanoni 			break;
134b47b5b34SRafael Vanoni 
135b47b5b34SRafael Vanoni 		switch (c) {
136b47b5b34SRafael Vanoni 		case 'd':
137*636423dbSRafael Vanoni 			if (PT_ON_DUMP)
138b47b5b34SRafael Vanoni 				usage();
139b47b5b34SRafael Vanoni 
140*636423dbSRafael Vanoni 			g_op_mode |= PT_MODE_DUMP;
141b47b5b34SRafael Vanoni 			dump_count = (int)strtod(optarg, &endptr);
142b47b5b34SRafael Vanoni 
143b47b5b34SRafael Vanoni 			if (dump_count <= 0 || *endptr != NULL)
144b47b5b34SRafael Vanoni 				usage();
145b47b5b34SRafael Vanoni 			break;
146b47b5b34SRafael Vanoni 		case 't':
147b47b5b34SRafael Vanoni 			if (user_interval)
148b47b5b34SRafael Vanoni 				usage();
149b47b5b34SRafael Vanoni 
150b47b5b34SRafael Vanoni 			user_interval = 1;
151b47b5b34SRafael Vanoni 			g_ticktime = g_ticktime_usr = (double)strtod(optarg,
152b47b5b34SRafael Vanoni 			    &endptr);
153b47b5b34SRafael Vanoni 
154b47b5b34SRafael Vanoni 			if (*endptr != NULL || g_ticktime < 1 ||
155b47b5b34SRafael Vanoni 			    g_ticktime > INTERVAL_MAX)
156b47b5b34SRafael Vanoni 				usage();
157b47b5b34SRafael Vanoni 			break;
158b47b5b34SRafael Vanoni 		case 'v':
159*636423dbSRafael Vanoni 			if (PT_ON_CPU || PT_ON_VERBOSE)
160b47b5b34SRafael Vanoni 				usage();
161b47b5b34SRafael Vanoni 
162*636423dbSRafael Vanoni 			g_op_mode |= PT_MODE_VERBOSE;
163b47b5b34SRafael Vanoni 			break;
164b47b5b34SRafael Vanoni 		case 'c':
165*636423dbSRafael Vanoni 			if (PT_ON_CPU || PT_ON_VERBOSE)
166b47b5b34SRafael Vanoni 				usage();
167b47b5b34SRafael Vanoni 
168*636423dbSRafael Vanoni 			g_op_mode |= PT_MODE_CPU;
169b47b5b34SRafael Vanoni 			g_observed_cpu = (uint_t)strtod(optarg, &endptr);
170b47b5b34SRafael Vanoni 
171b47b5b34SRafael Vanoni 			if (g_observed_cpu >= g_ncpus)
172b47b5b34SRafael Vanoni 				usage();
173b47b5b34SRafael Vanoni 
174b47b5b34SRafael Vanoni 			g_argc = 1;
175b47b5b34SRafael Vanoni 			g_ncpus_observed = 1;
176b47b5b34SRafael Vanoni 
177b47b5b34SRafael Vanoni 			if ((g_argv = malloc(sizeof (char *))) == NULL)
178b47b5b34SRafael Vanoni 				return (EXIT_FAILURE);
179b47b5b34SRafael Vanoni 
180b47b5b34SRafael Vanoni 			if ((*g_argv = malloc(sizeof (char) * 5)) == NULL)
181b47b5b34SRafael Vanoni 				return (EXIT_FAILURE);
182b47b5b34SRafael Vanoni 
183b47b5b34SRafael Vanoni 			(void) snprintf(*g_argv, 5, "%d\0", g_observed_cpu);
184b47b5b34SRafael Vanoni 			break;
185b47b5b34SRafael Vanoni 		case 'h':
186b47b5b34SRafael Vanoni 		default:
187b47b5b34SRafael Vanoni 			usage();
188b47b5b34SRafael Vanoni 			return (EXIT_USAGE);
189b47b5b34SRafael Vanoni 		}
190b47b5b34SRafael Vanoni 	}
191b47b5b34SRafael Vanoni 
192b47b5b34SRafael Vanoni 	if (optind < argc) {
193b47b5b34SRafael Vanoni 		usage();
194b47b5b34SRafael Vanoni 	}
195b47b5b34SRafael Vanoni 
196b47b5b34SRafael Vanoni 	(void) printf("%s   %s\n\n", TITLE, COPYRIGHT_INTEL);
197b47b5b34SRafael Vanoni 
198b47b5b34SRafael Vanoni 	/*
199b47b5b34SRafael Vanoni 	 * If the system is running on battery, find out what's
200b47b5b34SRafael Vanoni 	 * the kstat module for it
201b47b5b34SRafael Vanoni 	 */
202b47b5b34SRafael Vanoni 	battery_mod_lookup();
203b47b5b34SRafael Vanoni 
204b47b5b34SRafael Vanoni 	/* Prepare C-state statistics */
205b47b5b34SRafael Vanoni 	ret = pt_cpuidle_stat_prepare();
206b47b5b34SRafael Vanoni 	if (ret == 0)
207b47b5b34SRafael Vanoni 		features |= FEATURE_CSTATE;
208b47b5b34SRafael Vanoni 	else
209b47b5b34SRafael Vanoni 		/*
210b47b5b34SRafael Vanoni 		 * PowerTop was unable to run a DTrace program,
211b47b5b34SRafael Vanoni 		 * most likely for lack of permissions.
212b47b5b34SRafael Vanoni 		 */
213b47b5b34SRafael Vanoni 		exit(EXIT_FAILURE);
214b47b5b34SRafael Vanoni 
215b47b5b34SRafael Vanoni 	/* Prepare P-state statistics */
216b47b5b34SRafael Vanoni 	if (pt_cpufreq_stat_prepare() == 0)
217b47b5b34SRafael Vanoni 		features |= FEATURE_PSTATE;
218b47b5b34SRafael Vanoni 
219b47b5b34SRafael Vanoni 	/* Prepare event statistics */
220b47b5b34SRafael Vanoni 	if (pt_events_stat_prepare() != -1)
221b47b5b34SRafael Vanoni 		features |= FEATURE_EVENTS;
222b47b5b34SRafael Vanoni 
223b47b5b34SRafael Vanoni 	/* Prepare turbo statistics */
224b47b5b34SRafael Vanoni 	if (pt_turbo_stat_prepare() == 0) {
225b47b5b34SRafael Vanoni 		features |= FEATURE_TURBO;
226b47b5b34SRafael Vanoni 	}
227b47b5b34SRafael Vanoni 
228b47b5b34SRafael Vanoni 	(void) printf(_("Collecting data for %.2f second(s) \n"),
229b47b5b34SRafael Vanoni 	    (float)g_ticktime);
230b47b5b34SRafael Vanoni 
231*636423dbSRafael Vanoni 	if (!PT_ON_DUMP)
232b47b5b34SRafael Vanoni 		g_gui = B_TRUE;
233b47b5b34SRafael Vanoni 
234b47b5b34SRafael Vanoni 	last = gethrtime();
235b47b5b34SRafael Vanoni 
236b47b5b34SRafael Vanoni 	while (true) {
237b47b5b34SRafael Vanoni 		fd_set 	rfds;
238b47b5b34SRafael Vanoni 		struct 	timeval tv;
239b47b5b34SRafael Vanoni 		int 	key, reinit = 0;
240b47b5b34SRafael Vanoni 		char 	keychar;
241b47b5b34SRafael Vanoni 
242b47b5b34SRafael Vanoni 		/*
243b47b5b34SRafael Vanoni 		 * Sleep for a while waiting either for input (if we're not
244b47b5b34SRafael Vanoni 		 * in dump mode) or for the timeout to elapse
245b47b5b34SRafael Vanoni 		 */
246b47b5b34SRafael Vanoni 		FD_ZERO(&rfds);
247b47b5b34SRafael Vanoni 		FD_SET(0, &rfds);
248b47b5b34SRafael Vanoni 
249b47b5b34SRafael Vanoni 		tv.tv_sec 	= (long)g_ticktime;
250*636423dbSRafael Vanoni 		tv.tv_usec 	= (long)((g_ticktime - tv.tv_sec) * MICROSEC);
251b47b5b34SRafael Vanoni 
252*636423dbSRafael Vanoni 		if (!PT_ON_DUMP)
253b47b5b34SRafael Vanoni 			key = select(1, &rfds, NULL, NULL, &tv);
254b47b5b34SRafael Vanoni 		else
255b47b5b34SRafael Vanoni 			key = select(1, NULL, NULL, NULL, &tv);
256b47b5b34SRafael Vanoni 
257b47b5b34SRafael Vanoni 		now 		= gethrtime();
258b47b5b34SRafael Vanoni 
259b47b5b34SRafael Vanoni 		g_interval 	= (double)(now - last)/NANOSEC;
260b47b5b34SRafael Vanoni 		last 		= now;
261b47b5b34SRafael Vanoni 
262*636423dbSRafael Vanoni 		g_top_events 	= 0;
263b47b5b34SRafael Vanoni 		g_total_events 	= 0;
264b47b5b34SRafael Vanoni 
2659b37b909SRafael Vanoni 		(void) memset(g_event_info, 0,
2669b37b909SRafael Vanoni 		    EVENT_NUM_MAX * sizeof (event_info_t));
26792ad8f28SRafael Vanoni 		(void) memset(g_cstate_info, 0,
26892ad8f28SRafael Vanoni 		    NSTATES * sizeof (state_info_t));
269b47b5b34SRafael Vanoni 
270b47b5b34SRafael Vanoni 		/* Collect idle state transition stats */
271b47b5b34SRafael Vanoni 		if (features & FEATURE_CSTATE &&
272b47b5b34SRafael Vanoni 		    pt_cpuidle_stat_collect(g_interval) < 0) {
273b47b5b34SRafael Vanoni 			/* Reinitialize C-state statistics */
274b47b5b34SRafael Vanoni 			if (pt_cpuidle_stat_prepare() != 0)
275b47b5b34SRafael Vanoni 				exit(EXIT_FAILURE);
276b47b5b34SRafael Vanoni 
277b47b5b34SRafael Vanoni 			reinit = 1;
278b47b5b34SRafael Vanoni 		}
279b47b5b34SRafael Vanoni 
280b47b5b34SRafael Vanoni 		/* Collect frequency change stats */
281b47b5b34SRafael Vanoni 		if (features & FEATURE_PSTATE &&
282b47b5b34SRafael Vanoni 		    pt_cpufreq_stat_collect(g_interval) < 0) {
283b47b5b34SRafael Vanoni 			/* Reinitialize P-state statistics */
284b47b5b34SRafael Vanoni 			if (pt_cpufreq_stat_prepare() != 0)
285b47b5b34SRafael Vanoni 				exit(EXIT_FAILURE);
286b47b5b34SRafael Vanoni 
287b47b5b34SRafael Vanoni 			reinit = 1;
288b47b5b34SRafael Vanoni 		}
289b47b5b34SRafael Vanoni 
290b47b5b34SRafael Vanoni 		/* Collect event statistics */
291b47b5b34SRafael Vanoni 		if (features & FEATURE_EVENTS &&
292b47b5b34SRafael Vanoni 		    pt_events_stat_collect() < 0) {
293b47b5b34SRafael Vanoni 			/* Reinitialize event statistics */
294b47b5b34SRafael Vanoni 			if (pt_events_stat_prepare() != 0)
295b47b5b34SRafael Vanoni 				exit(EXIT_FAILURE);
296b47b5b34SRafael Vanoni 
297b47b5b34SRafael Vanoni 			reinit = 1;
298b47b5b34SRafael Vanoni 		}
299b47b5b34SRafael Vanoni 
300b47b5b34SRafael Vanoni 		if (reinit)
301b47b5b34SRafael Vanoni 			continue;
302b47b5b34SRafael Vanoni 
303b47b5b34SRafael Vanoni 		/* Collect turbo statistics */
304b47b5b34SRafael Vanoni 		if (features & FEATURE_TURBO &&
305b47b5b34SRafael Vanoni 		    pt_turbo_stat_collect() < 0) {
306b47b5b34SRafael Vanoni 			exit(EXIT_FAILURE);
307b47b5b34SRafael Vanoni 		}
308b47b5b34SRafael Vanoni 
309b47b5b34SRafael Vanoni 		/*
310b47b5b34SRafael Vanoni 		 * Initialize curses if we're not dumping and
311b47b5b34SRafael Vanoni 		 * haven't already done it
312b47b5b34SRafael Vanoni 		 */
313*636423dbSRafael Vanoni 		if (!PT_ON_DUMP) {
314b47b5b34SRafael Vanoni 			if (!ncursesinited) {
315b47b5b34SRafael Vanoni 				initialize_curses();
316b47b5b34SRafael Vanoni 				ncursesinited++;
317b47b5b34SRafael Vanoni 			}
318b47b5b34SRafael Vanoni 			setup_windows();
319b47b5b34SRafael Vanoni 			show_title_bar();
320b47b5b34SRafael Vanoni 		}
321b47b5b34SRafael Vanoni 
322b47b5b34SRafael Vanoni 		/* Show CPU power states */
323b47b5b34SRafael Vanoni 		if (features & FEATURE_CSTATE)
324b47b5b34SRafael Vanoni 			show_cstates();
325b47b5b34SRafael Vanoni 
326b47b5b34SRafael Vanoni 		/* Show wakeups events affecting PM */
327b47b5b34SRafael Vanoni 		if (features & FEATURE_EVENTS) {
328b47b5b34SRafael Vanoni 			show_wakeups(g_interval);
329b47b5b34SRafael Vanoni 			show_eventstats(g_interval);
330b47b5b34SRafael Vanoni 		}
331b47b5b34SRafael Vanoni 
332b47b5b34SRafael Vanoni 		print_battery();
333b47b5b34SRafael Vanoni 
334b47b5b34SRafael Vanoni 		g_displaytime = g_displaytime - g_ticktime;
335b47b5b34SRafael Vanoni 
336*636423dbSRafael Vanoni 		if (key && !PT_ON_DUMP) {
337b47b5b34SRafael Vanoni 			keychar = toupper(fgetc(stdin));
338b47b5b34SRafael Vanoni 
339b47b5b34SRafael Vanoni 			switch (keychar) {
340b47b5b34SRafael Vanoni 			case 'Q':
341b47b5b34SRafael Vanoni 				cleanup_curses();
342b47b5b34SRafael Vanoni 				exit(EXIT_SUCCESS);
343b47b5b34SRafael Vanoni 				break;
344b47b5b34SRafael Vanoni 			case 'R':
345b47b5b34SRafael Vanoni 				g_ticktime = 3;
346b47b5b34SRafael Vanoni 				break;
347b47b5b34SRafael Vanoni 			}
348b47b5b34SRafael Vanoni 			if (keychar == g_suggestion_key &&
349b47b5b34SRafael Vanoni 			    g_suggestion_activate) {
350b47b5b34SRafael Vanoni 				g_suggestion_activate();
351b47b5b34SRafael Vanoni 				g_displaytime = -1.0;
352b47b5b34SRafael Vanoni 			}
353b47b5b34SRafael Vanoni 		}
354b47b5b34SRafael Vanoni 		reset_suggestions();
355b47b5b34SRafael Vanoni 
356b47b5b34SRafael Vanoni 		/* suggests PM */
357b47b5b34SRafael Vanoni 		if (geteuid() == 0) {
358b47b5b34SRafael Vanoni 			suggest_p_state();
359b47b5b34SRafael Vanoni 		} else {
360b47b5b34SRafael Vanoni 			suggest_as_root();
361b47b5b34SRafael Vanoni 		}
362b47b5b34SRafael Vanoni 
363b47b5b34SRafael Vanoni 		if (dump_count)
364b47b5b34SRafael Vanoni 			dump_count--;
365b47b5b34SRafael Vanoni 
366b47b5b34SRafael Vanoni 		/* Exits if user requested a dump */
367*636423dbSRafael Vanoni 		if (PT_ON_DUMP && !dump_count) {
368b47b5b34SRafael Vanoni 			print_all_suggestions();
369b47b5b34SRafael Vanoni 			exit(EXIT_SUCCESS);
370b47b5b34SRafael Vanoni 		}
371b47b5b34SRafael Vanoni 
372b47b5b34SRafael Vanoni 		/* No key pressed, will suggest something */
373b47b5b34SRafael Vanoni 		if (!key && !dump_count)
374b47b5b34SRafael Vanoni 			pick_suggestion();
375b47b5b34SRafael Vanoni 
376b47b5b34SRafael Vanoni 		/* Refresh display */
377*636423dbSRafael Vanoni 		if (!PT_ON_DUMP) {
378b47b5b34SRafael Vanoni 			show_title_bar();
379b47b5b34SRafael Vanoni 			update_windows();
380b47b5b34SRafael Vanoni 		}
381b47b5b34SRafael Vanoni 
382b47b5b34SRafael Vanoni 		/*
383b47b5b34SRafael Vanoni 		 * Update the interval based on how long the CPU was in the
384b47b5b34SRafael Vanoni 		 * longest c-state during the last snapshot. If the user
385b47b5b34SRafael Vanoni 		 * specified an interval we skip this bit and keep it fixed.
386b47b5b34SRafael Vanoni 		 */
387b47b5b34SRafael Vanoni 		last_time = (((double)g_cstate_info[g_longest_cstate].total_time
388*636423dbSRafael Vanoni 		    /MICROSEC/g_ncpus)/g_cstate_info[g_longest_cstate].events);
389b47b5b34SRafael Vanoni 
390b47b5b34SRafael Vanoni 		if (!user_interval)
391b47b5b34SRafael Vanoni 			if (last_time < INTERVAL_DEFAULT ||
392b47b5b34SRafael Vanoni 			    (g_total_events/g_ticktime) < 1)
393b47b5b34SRafael Vanoni 				g_ticktime = INTERVAL_DEFAULT;
394b47b5b34SRafael Vanoni 			else
395b47b5b34SRafael Vanoni 				g_ticktime = INTERVAL_UPDATE(last_time);
396b47b5b34SRafael Vanoni 
397b47b5b34SRafael Vanoni 		/*
398b47b5b34SRafael Vanoni 		 * Restore user specified interval after a refresh
399b47b5b34SRafael Vanoni 		 */
400b47b5b34SRafael Vanoni 		if (keychar == 'R' && user_interval)
401b47b5b34SRafael Vanoni 			g_ticktime = g_ticktime_usr;
402b47b5b34SRafael Vanoni 	}
403b47b5b34SRafael Vanoni 	return (EXIT_SUCCESS);
404b47b5b34SRafael Vanoni }
405b47b5b34SRafael Vanoni 
406b47b5b34SRafael Vanoni void
407b47b5b34SRafael Vanoni suggest_as_root(void)
408b47b5b34SRafael Vanoni {
409b47b5b34SRafael Vanoni 	add_suggestion("Suggestion: run as root to get suggestions"
410b47b5b34SRafael Vanoni 	    " for reducing system power consumption",  40, NULL, NULL,
411b47b5b34SRafael Vanoni 	    NULL);
412b47b5b34SRafael Vanoni }
413