xref: /titanic_50/usr/src/cmd/powertop/common/powertop.c (revision 2d83778a2c10c425b98c41d254f85f0e384d4dac)
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>
449bbf5ba1SRafael Vanoni #include <signal.h>
45b47b5b34SRafael Vanoni #include <string.h>
46b47b5b34SRafael Vanoni #include <ctype.h>
47*2d83778aSRafael Vanoni #include <poll.h>
48b47b5b34SRafael Vanoni #include "powertop.h"
49b47b5b34SRafael Vanoni 
50b47b5b34SRafael Vanoni /*
51b47b5b34SRafael Vanoni  * Global variables, see powertop.h for comments and extern declarations.
52b47b5b34SRafael Vanoni  * These are ordered by type, grouped by usage.
53b47b5b34SRafael Vanoni  */
54b47b5b34SRafael Vanoni int			g_bit_depth;
55636423dbSRafael Vanoni int 			g_total_events, g_top_events;
56b47b5b34SRafael Vanoni int			g_npstates, g_max_cstate, g_longest_cstate;
579bbf5ba1SRafael Vanoni uint_t			g_features;
58b47b5b34SRafael Vanoni uint_t			g_ncpus;
59b47b5b34SRafael Vanoni uint_t			g_ncpus_observed;
60b47b5b34SRafael Vanoni 
61b47b5b34SRafael Vanoni processorid_t 		*g_cpu_table;
62b47b5b34SRafael Vanoni 
63*2d83778aSRafael Vanoni double			g_interval_length;
64b47b5b34SRafael Vanoni hrtime_t		g_total_c_time;
65b47b5b34SRafael Vanoni 
66b47b5b34SRafael Vanoni uchar_t			g_op_mode;
67b47b5b34SRafael Vanoni boolean_t		g_gui;
68b47b5b34SRafael Vanoni uint_t			g_observed_cpu;
69b47b5b34SRafael Vanoni 
70b47b5b34SRafael Vanoni event_info_t    	g_event_info[EVENT_NUM_MAX];
71b47b5b34SRafael Vanoni state_info_t		g_cstate_info[NSTATES];
72b47b5b34SRafael Vanoni freq_state_info_t	g_pstate_info[NSTATES];
73b47b5b34SRafael Vanoni cpu_power_info_t	*g_cpu_power_states;
74b47b5b34SRafael Vanoni 
75b47b5b34SRafael Vanoni boolean_t		g_turbo_supported;
76*2d83778aSRafael Vanoni boolean_t		g_sig_resize;
77b47b5b34SRafael Vanoni 
78b47b5b34SRafael Vanoni uint_t			g_argc;
79b47b5b34SRafael Vanoni char			**g_argv;
80b47b5b34SRafael Vanoni 
81b47b5b34SRafael Vanoni char			*optarg;
82b47b5b34SRafael Vanoni 
83b47b5b34SRafael Vanoni static const int	true = 1;
84b47b5b34SRafael Vanoni 
85*2d83778aSRafael Vanoni void
86*2d83778aSRafael Vanoni pt_sig_handler(int sig)
87*2d83778aSRafael Vanoni {
88*2d83778aSRafael Vanoni 	switch (sig) {
89*2d83778aSRafael Vanoni 	case SIGWINCH:
90*2d83778aSRafael Vanoni 		g_sig_resize = B_TRUE;
91*2d83778aSRafael Vanoni 		break;
92*2d83778aSRafael Vanoni 	}
93*2d83778aSRafael Vanoni }
94*2d83778aSRafael Vanoni 
95b47b5b34SRafael Vanoni int
96b47b5b34SRafael Vanoni main(int argc, char **argv)
97b47b5b34SRafael Vanoni {
98*2d83778aSRafael Vanoni 	double		interval, interval_usr;
99*2d83778aSRafael Vanoni 	hrtime_t 	interval_start;
100*2d83778aSRafael Vanoni 	int		index2 = 0, c, dump_count = 0;
101*2d83778aSRafael Vanoni 	char		*endptr, key;
1029bbf5ba1SRafael Vanoni 	boolean_t	root_user = B_FALSE;
103*2d83778aSRafael Vanoni 	struct pollfd	pollset;
104b47b5b34SRafael Vanoni 
105b47b5b34SRafael Vanoni 	static struct option opts[] = {
106b47b5b34SRafael Vanoni 		{ "dump", 1, NULL, 'd' },
107b47b5b34SRafael Vanoni 		{ "time", 1, NULL, 't' },
108b47b5b34SRafael Vanoni 		{ "help", 0, NULL, 'h' },
109b47b5b34SRafael Vanoni 		{ "cpu", 1, NULL, 'c' },
110b47b5b34SRafael Vanoni 		{ "verbose", 0, NULL, 'v' },
111b47b5b34SRafael Vanoni 		{ 0, 0, NULL, 0 }
112b47b5b34SRafael Vanoni 	};
113b47b5b34SRafael Vanoni 
114b47b5b34SRafael Vanoni 	pt_set_progname(argv[0]);
115b47b5b34SRafael Vanoni 
116b47b5b34SRafael Vanoni 	/*
1179bbf5ba1SRafael Vanoni 	 * Enumerate the system's CPUs, populate cpu_table, g_ncpus
118b47b5b34SRafael Vanoni 	 */
119*2d83778aSRafael Vanoni 	if ((g_ncpus = g_ncpus_observed = pt_enumerate_cpus()) == 0)
120b47b5b34SRafael Vanoni 		exit(EXIT_FAILURE);
121b47b5b34SRafael Vanoni 
122*2d83778aSRafael Vanoni 	if ((g_bit_depth = pt_get_bit_depth()) < 0)
123b47b5b34SRafael Vanoni 		exit(EXIT_FAILURE);
124b47b5b34SRafael Vanoni 
1259bbf5ba1SRafael Vanoni 	g_features = 0;
126*2d83778aSRafael Vanoni 	interval = interval_usr = INTERVAL_DEFAULT;
127636423dbSRafael Vanoni 	g_op_mode = PT_MODE_DEFAULT;
128b47b5b34SRafael Vanoni 	g_max_cstate = 0;
129b47b5b34SRafael Vanoni 	g_argv = NULL;
130b47b5b34SRafael Vanoni 	g_argc = 0;
131b47b5b34SRafael Vanoni 	g_observed_cpu = 0;
132b47b5b34SRafael Vanoni 	g_turbo_supported = B_FALSE;
133*2d83778aSRafael Vanoni 	g_sig_resize = B_FALSE;
1349bbf5ba1SRafael Vanoni 	g_curr_sugg = NULL;
135b47b5b34SRafael Vanoni 
136*2d83778aSRafael Vanoni 	while ((c = getopt_long(argc, argv, "d:t:hvc:", opts, &index2))
137b47b5b34SRafael Vanoni 	    != EOF) {
138b47b5b34SRafael Vanoni 		if (c == -1)
139b47b5b34SRafael Vanoni 			break;
140b47b5b34SRafael Vanoni 
141b47b5b34SRafael Vanoni 		switch (c) {
142b47b5b34SRafael Vanoni 		case 'd':
143*2d83778aSRafael Vanoni 			if (PT_ON_DUMP) {
144*2d83778aSRafael Vanoni 				pt_usage();
145*2d83778aSRafael Vanoni 				exit(EXIT_USAGE);
146*2d83778aSRafael Vanoni 			}
147b47b5b34SRafael Vanoni 
148636423dbSRafael Vanoni 			g_op_mode |= PT_MODE_DUMP;
149*2d83778aSRafael Vanoni 			g_gui = B_FALSE;
150b47b5b34SRafael Vanoni 			dump_count = (int)strtod(optarg, &endptr);
151b47b5b34SRafael Vanoni 
152b47b5b34SRafael Vanoni 			if (dump_count <= 0 || *endptr != NULL)
153*2d83778aSRafael Vanoni 				pt_usage();
154b47b5b34SRafael Vanoni 			break;
155b47b5b34SRafael Vanoni 		case 't':
156*2d83778aSRafael Vanoni 			if (PT_ON_TIME) {
157*2d83778aSRafael Vanoni 				pt_usage();
158*2d83778aSRafael Vanoni 				exit(EXIT_USAGE);
159*2d83778aSRafael Vanoni 			}
160b47b5b34SRafael Vanoni 
161*2d83778aSRafael Vanoni 			g_op_mode |= PT_MODE_TIME;
162*2d83778aSRafael Vanoni 			interval = interval_usr = (double)strtod(optarg,
163b47b5b34SRafael Vanoni 			    &endptr);
164b47b5b34SRafael Vanoni 
165*2d83778aSRafael Vanoni 			if (*endptr != NULL || interval < 1 ||
166*2d83778aSRafael Vanoni 			    interval > INTERVAL_MAX) {
167*2d83778aSRafael Vanoni 				pt_usage();
168*2d83778aSRafael Vanoni 				exit(EXIT_USAGE);
169*2d83778aSRafael Vanoni 			}
170*2d83778aSRafael Vanoni 
171b47b5b34SRafael Vanoni 			break;
172b47b5b34SRafael Vanoni 		case 'v':
173*2d83778aSRafael Vanoni 			if (PT_ON_CPU || PT_ON_VERBOSE) {
174*2d83778aSRafael Vanoni 				pt_usage();
175*2d83778aSRafael Vanoni 				exit(EXIT_USAGE);
176*2d83778aSRafael Vanoni 			}
177b47b5b34SRafael Vanoni 
178636423dbSRafael Vanoni 			g_op_mode |= PT_MODE_VERBOSE;
179b47b5b34SRafael Vanoni 			break;
180b47b5b34SRafael Vanoni 		case 'c':
181*2d83778aSRafael Vanoni 			if (PT_ON_CPU || PT_ON_VERBOSE) {
182*2d83778aSRafael Vanoni 				pt_usage();
183*2d83778aSRafael Vanoni 				exit(EXIT_USAGE);
184*2d83778aSRafael Vanoni 			}
185b47b5b34SRafael Vanoni 
186636423dbSRafael Vanoni 			g_op_mode |= PT_MODE_CPU;
187b47b5b34SRafael Vanoni 			g_observed_cpu = (uint_t)strtod(optarg, &endptr);
188b47b5b34SRafael Vanoni 
189*2d83778aSRafael Vanoni 			if (g_observed_cpu >= g_ncpus) {
190*2d83778aSRafael Vanoni 				pt_usage();
191*2d83778aSRafael Vanoni 				exit(EXIT_USAGE);
192*2d83778aSRafael Vanoni 			}
193b47b5b34SRafael Vanoni 
194b47b5b34SRafael Vanoni 			g_argc = 1;
195b47b5b34SRafael Vanoni 			g_ncpus_observed = 1;
196b47b5b34SRafael Vanoni 
197b47b5b34SRafael Vanoni 			if ((g_argv = malloc(sizeof (char *))) == NULL)
198b47b5b34SRafael Vanoni 				return (EXIT_FAILURE);
199b47b5b34SRafael Vanoni 
200b47b5b34SRafael Vanoni 			if ((*g_argv = malloc(sizeof (char) * 5)) == NULL)
201b47b5b34SRafael Vanoni 				return (EXIT_FAILURE);
202b47b5b34SRafael Vanoni 
203b47b5b34SRafael Vanoni 			(void) snprintf(*g_argv, 5, "%d\0", g_observed_cpu);
204b47b5b34SRafael Vanoni 			break;
205b47b5b34SRafael Vanoni 		case 'h':
206*2d83778aSRafael Vanoni 			pt_usage();
207*2d83778aSRafael Vanoni 			exit(EXIT_SUCCESS);
208b47b5b34SRafael Vanoni 		default:
209*2d83778aSRafael Vanoni 			pt_usage();
210*2d83778aSRafael Vanoni 			exit(EXIT_USAGE);
211b47b5b34SRafael Vanoni 		}
212b47b5b34SRafael Vanoni 	}
213b47b5b34SRafael Vanoni 
2149bbf5ba1SRafael Vanoni 	if (optind < argc)
215*2d83778aSRafael Vanoni 		pt_usage();
216b47b5b34SRafael Vanoni 
217b47b5b34SRafael Vanoni 	(void) printf("%s   %s\n\n", TITLE, COPYRIGHT_INTEL);
218b47b5b34SRafael Vanoni 
219*2d83778aSRafael Vanoni 	(void) printf("Collecting data for %.2f second(s) \n",
220*2d83778aSRafael Vanoni 	    (float)interval);
2219bbf5ba1SRafael Vanoni 
2229bbf5ba1SRafael Vanoni 	/* Prepare P-state statistics */
2239bbf5ba1SRafael Vanoni 	if (pt_cpufreq_stat_prepare() == 0)
2249bbf5ba1SRafael Vanoni 		g_features |= FEATURE_PSTATE;
225b47b5b34SRafael Vanoni 
226b47b5b34SRafael Vanoni 	/* Prepare C-state statistics */
227*2d83778aSRafael Vanoni 	if (pt_cpuidle_stat_prepare() == 0)
2289bbf5ba1SRafael Vanoni 		g_features |= FEATURE_CSTATE;
229b47b5b34SRafael Vanoni 	else
230b47b5b34SRafael Vanoni 		/*
231b47b5b34SRafael Vanoni 		 * PowerTop was unable to run a DTrace program,
232b47b5b34SRafael Vanoni 		 * most likely for lack of permissions.
233b47b5b34SRafael Vanoni 		 */
234b47b5b34SRafael Vanoni 		exit(EXIT_FAILURE);
235b47b5b34SRafael Vanoni 
236b47b5b34SRafael Vanoni 	/* Prepare event statistics */
237b47b5b34SRafael Vanoni 	if (pt_events_stat_prepare() != -1)
2389bbf5ba1SRafael Vanoni 		g_features |= FEATURE_EVENTS;
2399bbf5ba1SRafael Vanoni 
2409bbf5ba1SRafael Vanoni 	/*
2419bbf5ba1SRafael Vanoni 	 * If the system is running on battery, find out what's
2429bbf5ba1SRafael Vanoni 	 * the kstat module for it
2439bbf5ba1SRafael Vanoni 	 */
244*2d83778aSRafael Vanoni 	pt_battery_mod_lookup();
245b47b5b34SRafael Vanoni 
246b47b5b34SRafael Vanoni 	/* Prepare turbo statistics */
2479bbf5ba1SRafael Vanoni 	if (pt_turbo_stat_prepare() == 0)
2489bbf5ba1SRafael Vanoni 		g_features |= FEATURE_TURBO;
2499bbf5ba1SRafael Vanoni 
2509bbf5ba1SRafael Vanoni 	/*
251*2d83778aSRafael Vanoni 	 * Initialize the display.
252*2d83778aSRafael Vanoni 	 */
253*2d83778aSRafael Vanoni 	if (!PT_ON_DUMP) {
254*2d83778aSRafael Vanoni 		pt_display_init_curses();
255*2d83778aSRafael Vanoni 		pt_display_setup(B_FALSE);
256*2d83778aSRafael Vanoni 		(void) signal(SIGWINCH, pt_sig_handler);
257*2d83778aSRafael Vanoni 
258*2d83778aSRafael Vanoni 		pt_display_title_bar();
259*2d83778aSRafael Vanoni 		pt_display_status_bar();
260*2d83778aSRafael Vanoni 
261*2d83778aSRafael Vanoni 		g_gui = B_TRUE;
262*2d83778aSRafael Vanoni 		pollset.fd = STDIN_FILENO;
263*2d83778aSRafael Vanoni 		pollset.events = POLLIN;
264*2d83778aSRafael Vanoni 	}
265*2d83778aSRafael Vanoni 
266*2d83778aSRafael Vanoni 	/*
2679bbf5ba1SRafael Vanoni 	 * Installs the initial suggestions, running as root and turning CPU
2689bbf5ba1SRafael Vanoni 	 * power management ON.
2699bbf5ba1SRafael Vanoni 	 */
270*2d83778aSRafael Vanoni 	if (geteuid() != 0) {
2719bbf5ba1SRafael Vanoni 		pt_sugg_as_root();
272*2d83778aSRafael Vanoni 	} else {
2739bbf5ba1SRafael Vanoni 		root_user = B_TRUE;
2749bbf5ba1SRafael Vanoni 		pt_cpufreq_suggest();
275b47b5b34SRafael Vanoni 	}
276b47b5b34SRafael Vanoni 
277b47b5b34SRafael Vanoni 	while (true) {
278*2d83778aSRafael Vanoni 		key = 0;
279b47b5b34SRafael Vanoni 
280*2d83778aSRafael Vanoni 		if (g_sig_resize)
281*2d83778aSRafael Vanoni 			pt_display_resize();
282b47b5b34SRafael Vanoni 
283*2d83778aSRafael Vanoni 		interval_start = gethrtime();
284b47b5b34SRafael Vanoni 
2859bbf5ba1SRafael Vanoni 		if (!PT_ON_DUMP) {
286*2d83778aSRafael Vanoni 			if (poll(&pollset, (nfds_t)1,
287*2d83778aSRafael Vanoni 			    (int)(interval * MILLISEC)) > 0)
288*2d83778aSRafael Vanoni 				(void) read(STDIN_FILENO, &key, 1);
289*2d83778aSRafael Vanoni 		} else {
290*2d83778aSRafael Vanoni 			(void) sleep((int)interval);
291*2d83778aSRafael Vanoni 		}
292b47b5b34SRafael Vanoni 
293*2d83778aSRafael Vanoni 		g_interval_length = (double)(gethrtime() - interval_start)
294*2d83778aSRafael Vanoni 		    /NANOSEC;
295b47b5b34SRafael Vanoni 
296636423dbSRafael Vanoni 		g_top_events = 0;
297b47b5b34SRafael Vanoni 		g_total_events = 0;
298b47b5b34SRafael Vanoni 
2999b37b909SRafael Vanoni 		(void) memset(g_event_info, 0,
3009b37b909SRafael Vanoni 		    EVENT_NUM_MAX * sizeof (event_info_t));
30192ad8f28SRafael Vanoni 		(void) memset(g_cstate_info, 0,
30292ad8f28SRafael Vanoni 		    NSTATES * sizeof (state_info_t));
303b47b5b34SRafael Vanoni 
304b47b5b34SRafael Vanoni 		/* Collect idle state transition stats */
3059bbf5ba1SRafael Vanoni 		if (g_features & FEATURE_CSTATE &&
306*2d83778aSRafael Vanoni 		    pt_cpuidle_stat_collect(g_interval_length) < 0) {
307b47b5b34SRafael Vanoni 			/* Reinitialize C-state statistics */
308b47b5b34SRafael Vanoni 			if (pt_cpuidle_stat_prepare() != 0)
309b47b5b34SRafael Vanoni 				exit(EXIT_FAILURE);
310b47b5b34SRafael Vanoni 
3119bbf5ba1SRafael Vanoni 			continue;
312b47b5b34SRafael Vanoni 		}
313b47b5b34SRafael Vanoni 
314b47b5b34SRafael Vanoni 		/* Collect frequency change stats */
3159bbf5ba1SRafael Vanoni 		if (g_features & FEATURE_PSTATE &&
316*2d83778aSRafael Vanoni 		    pt_cpufreq_stat_collect(g_interval_length) < 0) {
317b47b5b34SRafael Vanoni 			/* Reinitialize P-state statistics */
318b47b5b34SRafael Vanoni 			if (pt_cpufreq_stat_prepare() != 0)
319b47b5b34SRafael Vanoni 				exit(EXIT_FAILURE);
320b47b5b34SRafael Vanoni 
3219bbf5ba1SRafael Vanoni 			continue;
322b47b5b34SRafael Vanoni 		}
323b47b5b34SRafael Vanoni 
324b47b5b34SRafael Vanoni 		/* Collect event statistics */
3259bbf5ba1SRafael Vanoni 		if (g_features & FEATURE_EVENTS &&
326b47b5b34SRafael Vanoni 		    pt_events_stat_collect() < 0) {
327b47b5b34SRafael Vanoni 			/* Reinitialize event statistics */
328b47b5b34SRafael Vanoni 			if (pt_events_stat_prepare() != 0)
329b47b5b34SRafael Vanoni 				exit(EXIT_FAILURE);
330b47b5b34SRafael Vanoni 
331b47b5b34SRafael Vanoni 			continue;
3329bbf5ba1SRafael Vanoni 		}
333b47b5b34SRafael Vanoni 
334b47b5b34SRafael Vanoni 		/* Collect turbo statistics */
3359bbf5ba1SRafael Vanoni 		if (g_features & FEATURE_TURBO &&
3369bbf5ba1SRafael Vanoni 		    pt_turbo_stat_collect() < 0)
337b47b5b34SRafael Vanoni 			exit(EXIT_FAILURE);
338b47b5b34SRafael Vanoni 
339b47b5b34SRafael Vanoni 		/* Show CPU power states */
3409bbf5ba1SRafael Vanoni 		pt_display_states();
341b47b5b34SRafael Vanoni 
342b47b5b34SRafael Vanoni 		/* Show wakeups events affecting PM */
3439bbf5ba1SRafael Vanoni 		if (g_features & FEATURE_EVENTS) {
344*2d83778aSRafael Vanoni 			pt_display_wakeups(g_interval_length);
345*2d83778aSRafael Vanoni 			pt_display_events(g_interval_length);
346b47b5b34SRafael Vanoni 		}
347b47b5b34SRafael Vanoni 
3489bbf5ba1SRafael Vanoni 		pt_battery_print();
349b47b5b34SRafael Vanoni 
350636423dbSRafael Vanoni 		if (key && !PT_ON_DUMP) {
351*2d83778aSRafael Vanoni 			switch (toupper(key)) {
352b47b5b34SRafael Vanoni 			case 'Q':
353b47b5b34SRafael Vanoni 				exit(EXIT_SUCCESS);
354b47b5b34SRafael Vanoni 				break;
3559bbf5ba1SRafael Vanoni 
356b47b5b34SRafael Vanoni 			case 'R':
357*2d83778aSRafael Vanoni 				interval = 3;
358b47b5b34SRafael Vanoni 				break;
359b47b5b34SRafael Vanoni 			}
360b47b5b34SRafael Vanoni 
3619bbf5ba1SRafael Vanoni 			/*
3629bbf5ba1SRafael Vanoni 			 * Check if the user has activated the current
3639bbf5ba1SRafael Vanoni 			 * suggestion.
3649bbf5ba1SRafael Vanoni 			 */
3659bbf5ba1SRafael Vanoni 			if (g_curr_sugg != NULL &&
366*2d83778aSRafael Vanoni 			    toupper(key) == g_curr_sugg->key &&
367*2d83778aSRafael Vanoni 			    g_curr_sugg->func)
3689bbf5ba1SRafael Vanoni 				g_curr_sugg->func();
369b47b5b34SRafael Vanoni 		}
370b47b5b34SRafael Vanoni 
371b47b5b34SRafael Vanoni 		if (dump_count)
372b47b5b34SRafael Vanoni 			dump_count--;
373b47b5b34SRafael Vanoni 
374b47b5b34SRafael Vanoni 		/* Exits if user requested a dump */
3759bbf5ba1SRafael Vanoni 		if (PT_ON_DUMP && !dump_count)
376b47b5b34SRafael Vanoni 			exit(EXIT_SUCCESS);
377b47b5b34SRafael Vanoni 
378b47b5b34SRafael Vanoni 		/* No key pressed, will suggest something */
379b47b5b34SRafael Vanoni 		if (!key && !dump_count)
3809bbf5ba1SRafael Vanoni 			pt_sugg_pick();
381b47b5b34SRafael Vanoni 
382b47b5b34SRafael Vanoni 		/* Refresh display */
3839bbf5ba1SRafael Vanoni 		if (!PT_ON_DUMP)
3849bbf5ba1SRafael Vanoni 			pt_display_update();
3859bbf5ba1SRafael Vanoni 
3869bbf5ba1SRafael Vanoni 		if (root_user)
3879bbf5ba1SRafael Vanoni 			pt_cpufreq_suggest();
388b47b5b34SRafael Vanoni 
389b47b5b34SRafael Vanoni 		/*
390b47b5b34SRafael Vanoni 		 * Update the interval based on how long the CPU was in the
391b47b5b34SRafael Vanoni 		 * longest c-state during the last snapshot. If the user
392b47b5b34SRafael Vanoni 		 * specified an interval we skip this bit and keep it fixed.
393b47b5b34SRafael Vanoni 		 */
394*2d83778aSRafael Vanoni 		if (g_features & FEATURE_CSTATE && !PT_ON_TIME &&
395*2d83778aSRafael Vanoni 		    g_longest_cstate > 0) {
396*2d83778aSRafael Vanoni 			double deep_idle_res = (((double)
3979bbf5ba1SRafael Vanoni 			    g_cstate_info[g_longest_cstate].total_time/MICROSEC
3989bbf5ba1SRafael Vanoni 			    /g_ncpus)/g_cstate_info[g_longest_cstate].events);
399b47b5b34SRafael Vanoni 
400*2d83778aSRafael Vanoni 			if (deep_idle_res < INTERVAL_DEFAULT ||
401*2d83778aSRafael Vanoni 			    (g_total_events/interval) < 1)
402*2d83778aSRafael Vanoni 				interval = INTERVAL_DEFAULT;
403b47b5b34SRafael Vanoni 			else
404*2d83778aSRafael Vanoni 				interval = INTERVAL_UPDATE(deep_idle_res);
4059bbf5ba1SRafael Vanoni 		} else {
406b47b5b34SRafael Vanoni 			/*
4079bbf5ba1SRafael Vanoni 			 * Restore interval after a refresh.
408b47b5b34SRafael Vanoni 			 */
4099bbf5ba1SRafael Vanoni 			if (key)
410*2d83778aSRafael Vanoni 				interval = interval_usr;
411b47b5b34SRafael Vanoni 		}
412b47b5b34SRafael Vanoni 	}
413b47b5b34SRafael Vanoni 
4149bbf5ba1SRafael Vanoni 	return (EXIT_SUCCESS);
415b47b5b34SRafael Vanoni }
416