2 * Copyright 2009, Intel Corporation
3 * Copyright 2009, Sun Microsystems, Inc
5 * This file is part of PowerTOP
7 * This program file is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU General Public License
17 * along with this program in a file named COPYING; if not, write to the
18 * Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
23 * Arjan van de Ven <arjan@linux.intel.com>
24 * Eric C Saxe <eric.saxe@sun.com>
25 * Aubrey Li <aubrey.li@intel.com>
31 * For the avoidance of doubt, except that if any license choice other
32 * than GPL or LGPL is available it will apply instead, Sun elects to
33 * use only the General Public License version 2 (GPLv2) at this time
34 * for any software where a choice of GPL license versions is made
35 * available with the language indicating that GPLv2 or any later
36 * version may be used, or where a choice of which version of the GPL
37 * is applied is otherwise unspecified.
51 * Global variables, see powertop.h for comments and extern declarations.
52 * These are ordered by type, grouped by usage.
55 int g_total_events
, g_top_events
;
56 int g_npstates
, g_max_cstate
, g_longest_cstate
;
59 uint_t g_ncpus_observed
;
61 processorid_t
*g_cpu_table
;
63 double g_interval_length
;
64 hrtime_t g_total_c_time
;
68 uint_t g_observed_cpu
;
70 event_info_t g_event_info
[EVENT_NUM_MAX
];
71 state_info_t g_cstate_info
[NSTATES
];
72 freq_state_info_t g_pstate_info
[NSTATES
];
73 cpu_power_info_t
*g_cpu_power_states
;
75 boolean_t g_turbo_supported
;
76 boolean_t g_sig_resize
;
81 static const int true = 1;
84 pt_sig_handler(int sig
)
88 g_sig_resize
= B_TRUE
;
94 main(int argc
, char **argv
)
96 double interval
, interval_usr
;
97 hrtime_t interval_start
;
98 int index2
= 0, c
, dump_count
= 0;
100 boolean_t root_user
= B_FALSE
;
101 struct pollfd pollset
;
103 static struct option opts
[] = {
104 { "dump", 1, NULL
, 'd' },
105 { "time", 1, NULL
, 't' },
106 { "help", 0, NULL
, 'h' },
107 { "cpu", 1, NULL
, 'c' },
108 { "verbose", 0, NULL
, 'v' },
112 pt_set_progname(argv
[0]);
115 * Enumerate the system's CPUs, populate cpu_table, g_ncpus
117 if ((g_ncpus
= g_ncpus_observed
= pt_enumerate_cpus()) == 0)
120 if ((g_bit_depth
= pt_get_bit_depth()) < 0)
124 interval
= interval_usr
= INTERVAL_DEFAULT
;
125 g_op_mode
= PT_MODE_DEFAULT
;
130 g_turbo_supported
= B_FALSE
;
131 g_sig_resize
= B_FALSE
;
134 while ((c
= getopt_long(argc
, argv
, "d:t:hvc:", opts
, &index2
))
146 g_op_mode
|= PT_MODE_DUMP
;
148 dump_count
= (int)strtod(optarg
, &endptr
);
150 if (dump_count
<= 0 || *endptr
!= '\0') {
162 g_op_mode
|= PT_MODE_TIME
;
163 interval
= interval_usr
= (double)strtod(optarg
,
166 if (*endptr
!= '\0' || interval
< 1 ||
167 interval
> INTERVAL_MAX
) {
174 if (PT_ON_CPU
|| PT_ON_VERBOSE
) {
179 g_op_mode
|= PT_MODE_VERBOSE
;
182 if (PT_ON_CPU
|| PT_ON_VERBOSE
) {
187 g_op_mode
|= PT_MODE_CPU
;
188 g_observed_cpu
= (uint_t
)strtod(optarg
, &endptr
);
190 if (g_observed_cpu
>= g_ncpus
) {
196 g_ncpus_observed
= 1;
198 if ((g_argv
= malloc(sizeof (char *))) == NULL
)
199 return (EXIT_FAILURE
);
201 if ((*g_argv
= malloc(sizeof (char) * 5)) == NULL
)
202 return (EXIT_FAILURE
);
204 (void) snprintf(*g_argv
, 5, "%d\0", g_observed_cpu
);
220 (void) printf("%s %s\n\n", TITLE
, COPYRIGHT_INTEL
);
222 (void) printf("Collecting data for %.2f second(s) \n",
225 /* Prepare P-state statistics */
226 if (pt_cpufreq_stat_prepare() == 0)
227 g_features
|= FEATURE_PSTATE
;
229 /* Prepare C-state statistics */
230 if (pt_cpuidle_stat_prepare() == 0)
231 g_features
|= FEATURE_CSTATE
;
234 * PowerTop was unable to run a DTrace program,
235 * most likely for lack of permissions.
239 /* Prepare event statistics */
240 if (pt_events_stat_prepare() != -1)
241 g_features
|= FEATURE_EVENTS
;
244 * If the system is running on battery, find out what's
245 * the kstat module for it
247 pt_battery_mod_lookup();
249 /* Prepare turbo statistics */
250 if (pt_turbo_stat_prepare() == 0)
251 g_features
|= FEATURE_TURBO
;
254 * Initialize the display.
257 pt_display_init_curses();
258 pt_display_setup(B_FALSE
);
259 (void) signal(SIGWINCH
, pt_sig_handler
);
261 pt_display_title_bar();
262 pt_display_status_bar();
265 pollset
.fd
= STDIN_FILENO
;
266 pollset
.events
= POLLIN
;
270 * Installs the initial suggestions, running as root and turning CPU
271 * power management ON.
273 if (geteuid() != 0) {
277 pt_cpufreq_suggest();
286 interval_start
= gethrtime();
289 if (poll(&pollset
, (nfds_t
)1,
290 (int)(interval
* MILLISEC
)) > 0)
291 (void) read(STDIN_FILENO
, &key
, 1);
293 (void) sleep((int)interval
);
296 g_interval_length
= (double)(gethrtime() - interval_start
)
302 (void) memset(g_event_info
, 0,
303 EVENT_NUM_MAX
* sizeof (event_info_t
));
304 (void) memset(g_cstate_info
, 0,
305 NSTATES
* sizeof (state_info_t
));
307 /* Collect idle state transition stats */
308 if (g_features
& FEATURE_CSTATE
&&
309 pt_cpuidle_stat_collect(g_interval_length
) < 0) {
310 /* Reinitialize C-state statistics */
311 if (pt_cpuidle_stat_prepare() != 0)
317 /* Collect frequency change stats */
318 if (g_features
& FEATURE_PSTATE
&&
319 pt_cpufreq_stat_collect(g_interval_length
) < 0) {
320 /* Reinitialize P-state statistics */
321 if (pt_cpufreq_stat_prepare() != 0)
327 /* Collect event statistics */
328 if (g_features
& FEATURE_EVENTS
&&
329 pt_events_stat_collect() < 0) {
330 /* Reinitialize event statistics */
331 if (pt_events_stat_prepare() != 0)
337 /* Collect turbo statistics */
338 if (g_features
& FEATURE_TURBO
&&
339 pt_turbo_stat_collect() < 0)
342 /* Show CPU power states */
345 /* Show wakeups events affecting PM */
346 if (g_features
& FEATURE_EVENTS
) {
347 pt_display_wakeups(g_interval_length
);
348 pt_display_events(g_interval_length
);
353 if (key
&& !PT_ON_DUMP
) {
354 switch (toupper(key
)) {
365 * Check if the user has activated the current
368 if (g_curr_sugg
!= NULL
&&
369 toupper(key
) == g_curr_sugg
->key
&&
377 /* Exits if user requested a dump */
378 if (PT_ON_DUMP
&& !dump_count
)
381 /* No key pressed, will suggest something */
382 if (!key
&& !dump_count
)
385 /* Refresh display */
390 pt_cpufreq_suggest();
393 * Update the interval based on how long the CPU was in the
394 * longest c-state during the last snapshot. If the user
395 * specified an interval we skip this bit and keep it fixed.
397 if (g_features
& FEATURE_CSTATE
&& !PT_ON_TIME
&&
398 g_longest_cstate
> 0 &&
399 g_cstate_info
[g_longest_cstate
].events
> 0) {
400 double deep_idle_res
= (((double)
401 g_cstate_info
[g_longest_cstate
].total_time
/MICROSEC
402 /g_ncpus
)/g_cstate_info
[g_longest_cstate
].events
);
404 if (deep_idle_res
< INTERVAL_DEFAULT
||
405 (g_total_events
/interval
) < 1)
406 interval
= INTERVAL_DEFAULT
;
408 interval
= INTERVAL_UPDATE(deep_idle_res
);
411 * Restore interval after a refresh.
414 interval
= interval_usr
;
418 return (EXIT_SUCCESS
);