Mercurial > illumos > illumos-gate
changeset 9908:4b4177fc63d9
6834110 PowerTOP's display.c needs some lovin'
author | Rafael Vanoni <rafael.vanoni@sun.com> |
---|---|
date | Fri, 19 Jun 2009 06:14:38 -0700 |
parents | 98086c85a8f7 |
children | aa280f585a3e |
files | usr/src/cmd/powertop/amd64/pt_amd64.c usr/src/cmd/powertop/common/battery.c usr/src/cmd/powertop/common/cpufreq.c usr/src/cmd/powertop/common/display.c usr/src/cmd/powertop/common/powertop.c usr/src/cmd/powertop/common/powertop.h usr/src/cmd/powertop/common/suggestions.c usr/src/cmd/powertop/i386/pt_i386.c usr/src/cmd/powertop/sparcv9/pt_sparcv9.c |
diffstat | 9 files changed, 754 insertions(+), 492 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/powertop/amd64/pt_amd64.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/amd64/pt_amd64.c Fri Jun 19 06:14:38 2009 -0700 @@ -217,3 +217,4 @@ */ const char *g_msg_idle_state = "C-states (idle power)"; const char *g_msg_freq_state = "P-states (frequencies)"; +const char *g_msg_freq_enable = "P - Enable P-states";
--- a/usr/src/cmd/powertop/common/battery.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/common/battery.c Fri Jun 19 06:14:38 2009 -0700 @@ -80,7 +80,7 @@ } void -print_battery(void) +pt_battery_print(void) { int err; @@ -105,7 +105,7 @@ err); } - show_acpi_power_line(battery_state.exist, battery_state.present_rate, + pt_display_acpi_power(battery_state.exist, battery_state.present_rate, battery_state.remain_cap, battery_state.last_cap, battery_state.bst_state); }
--- a/usr/src/cmd/powertop/common/cpufreq.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/common/cpufreq.c Fri Jun 19 06:14:38 2009 -0700 @@ -54,12 +54,12 @@ /* * Enabling PM through /etc/power.conf - * See suggest_p_state() + * See pt_cpufreq_suggest() */ static char default_conf[] = "/etc/power.conf"; static char default_pmconf[] = "/usr/sbin/pmconfig"; -static char cpupm_enable[] = " echo cpupm enable >> /etc/power.conf"; -static char cpupm_treshold[] = " echo cpu-threshold 1s >> /etc/power.conf"; +static char cpupm_enable[] = "echo cpupm enable >> /etc/power.conf"; +static char cpupm_treshold[] = "echo cpu-threshold 1s >> /etc/power.conf"; /* * Buffer containing DTrace program to track CPU frequency transitions @@ -123,8 +123,9 @@ static int pt_cpufreq_snapshot(void); static int pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *, void *); static void pt_cpufreq_stat_account(double, uint_t); -static int pt_cpufreq_snapshot_cpu(kstat_ctl_t *, - uint_t); +static int pt_cpufreq_snapshot_cpu(kstat_ctl_t *, uint_t); +static int pt_cpufreq_check_pm(void); +static void pt_cpufreq_enable(void); static int pt_cpufreq_setup(void) @@ -499,51 +500,74 @@ } /* + * Checks if PM is enabled in /etc/power.conf, enabling if not + */ +void +pt_cpufreq_suggest(void) +{ + int ret = pt_cpufreq_check_pm(); + + switch (ret) { + case 0: + pt_sugg_add("Suggestion: enable CPU power management by " + "pressing the P key", 40, 'P', (char *)g_msg_freq_enable, + pt_cpufreq_enable); + break; + } +} + +/* + * Checks /etc/power.conf and returns: + * + * 0 if CPUPM is not enabled + * 1 if there's nothing for us to do because: + * (a) the system does not support frequency scaling + * (b) there's no power.conf. + * 2 if CPUPM is enabled + * 3 if the system is running in poll-mode, as opposed to event-mode + * + * Notice the ordering of the return values, they will be picked up and + * switched upon ascendingly. + */ +static int +pt_cpufreq_check_pm(void) +{ + char line[1024]; + FILE *file; + int ret = 0; + + if (g_npstates < 2 || (file = fopen(default_conf, "r")) == NULL) + return (1); + + (void) memset(line, 0, 1024); + + while (fgets(line, 1024, file)) { + if (strstr(line, "cpupm")) { + if (strstr(line, "enable")) { + (void) fclose(file); + return (2); + } + } + if (strstr(line, "poll")) + ret = 3; + } + + (void) fclose(file); + + return (ret); +} + +/* * Used as a suggestion, sets PM in /etc/power.conf and * a 1sec threshold, then calls /usr/sbin/pmconfig */ -void -enable_p_state(void) +static void +pt_cpufreq_enable(void) { (void) system(cpupm_enable); (void) system(cpupm_treshold); (void) system(default_pmconf); + + if (pt_sugg_remove(pt_cpufreq_enable) == 0) + pt_error("%s : failed to remove a sugg.\n", __FILE__); } - -/* - * Checks if PM is enabled in /etc/power.conf, enabling if not - */ -void -suggest_p_state(void) -{ - char line[1024]; - FILE *file; - - /* - * Return if speed transition is not supported - */ - if (g_npstates < 2) - return; - - file = fopen(default_conf, "r"); - - if (!file) - return; - - (void) memset(line, 0, 1024); - - while (fgets(line, 1023, file)) { - if (strstr(line, "cpupm")) { - if (strstr(line, "enable")) { - (void) fclose(file); - return; - } - } - } - - add_suggestion("Suggestion: enable CPU power management by " - "pressing the P key", 40, 'P', "P - Enable p-state", - enable_p_state); - - (void) fclose(file); -}
--- a/usr/src/cmd/powertop/common/display.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/common/display.c Fri Jun 19 06:14:38 2009 -0700 @@ -39,16 +39,38 @@ #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <curses.h> +#include <signal.h> +#include <fcntl.h> #include "powertop.h" -static WINDOW *title_bar_window; -static WINDOW *cstate_window; -static WINDOW *wakeup_window; -static WINDOW *acpi_power_window; -static WINDOW *eventstat_window; -static WINDOW *suggestion_window; -static WINDOW *status_bar_window; +/* + * Minimum terminal height and width to run PowerTOP on curses mode. + */ +#define PT_MIN_COLS 70 +#define PT_MIN_ROWS 15 + +/* + * Display colors + */ +#define PT_COLOR_DEFAULT 1 +#define PT_COLOR_HEADER_BAR 2 +#define PT_COLOR_ERROR 3 +#define PT_COLOR_RED 4 +#define PT_COLOR_YELLOW 5 +#define PT_COLOR_GREEN 6 +#define PT_COLOR_BRIGHT 7 +#define PT_COLOR_BLUE 8 + +/* + * Constants for pt_display_setup() + */ +#define SINGLE_LINE_SW 1 +#define LENGTH_SUGG_SW 2 +#define TITLE_LINE 1 +#define BLANK_LINE 1 +#define NEXT_LINE 1 #define print(win, y, x, fmt, args...) \ if (PT_ON_DUMP) \ @@ -56,48 +78,73 @@ else \ (void) mvwprintw(win, y, x, fmt, ## args); -char g_status_bar_slots[PT_BAR_NSLOTS][PT_BAR_LENGTH]; -char g_suggestion_key; +enum pt_subwindows { + SW_TITLE, + SW_IDLE, + SW_FREQ, + SW_WAKEUPS, + SW_POWER, + SW_EVENTS, + SW_SUGG, + SW_STATUS, + SW_COUNT +}; -static int maxx, maxy; +typedef struct sb_slot { + char *msg; + struct sb_slot *prev; + struct sb_slot *next; +} sb_slot_t; + +static WINDOW *sw[SW_COUNT]; +static int win_cols, win_rows; +static sb_slot_t *status_bar; static void -zap_windows(void) +pt_display_cleanup(void) +{ + (void) endwin(); +} + +static void +pt_display_get_size(void) { - if (title_bar_window) { - (void) delwin(title_bar_window); - title_bar_window = NULL; - } - if (cstate_window) { - (void) delwin(cstate_window); - cstate_window = NULL; - } - if (wakeup_window) { - (void) delwin(wakeup_window); - wakeup_window = NULL; - } - if (acpi_power_window) { - (void) delwin(acpi_power_window); - acpi_power_window = NULL; - } - if (eventstat_window) { - (void) delwin(eventstat_window); - eventstat_window = NULL; - } - if (suggestion_window) { - (void) delwin(suggestion_window); - suggestion_window = NULL; - } - if (status_bar_window) { - (void) delwin(status_bar_window); - status_bar_window = NULL; + getmaxyx(stdscr, win_rows, win_cols); + + if (win_rows < PT_MIN_ROWS || win_cols < PT_MIN_COLS) { + pt_display_cleanup(); + (void) printf("\n\nPowerTOP cannot run in such a small " + "terminal window. Please resize it.\n\n"); + exit(EXIT_FAILURE); } } -void -cleanup_curses(void) +/* + * Signal handler, currently only used for window resizing. + */ +static void +pt_display_resize(int sig) { - (void) endwin(); + int i; + + switch (sig) { + case SIGWINCH: + for (i = 0; i < SW_COUNT; i++) + if (sw[i] != NULL) { + (void) delwin(sw[i]); + sw[i] = NULL; + } + + pt_display_cleanup(); + (void) pt_display_init_curses(); + pt_display_setup(B_TRUE); + + pt_display_title_bar(); + + pt_display_update(); + + break; + } } /* @@ -108,55 +155,75 @@ * subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x) */ void -setup_windows(void) +pt_display_setup(boolean_t resized) { /* * These variables are used to properly set the initial y position and * number of lines in each subwindow, as the number of supported CPU * states affects their placement. */ - int cstate_lines, event_lines, pos_y; - - getmaxyx(stdscr, maxy, maxx); + int cstate_lines, event_lines, pos_y = 0; - zap_windows(); + /* + * In theory, all systems have at least two idle states. We add two here + * since we have to use DTrace to figure out how many this box has. + */ + cstate_lines = TITLE_LINE + max((g_max_cstate+2), g_npstates); - cstate_lines = TITLE_LINE + max((g_max_cstate+1), g_npstates); - - pos_y = 0; - title_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); + sw[SW_TITLE] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); pos_y += NEXT_LINE + BLANK_LINE; - cstate_window = subwin(stdscr, cstate_lines, maxx, pos_y, 0); + sw[SW_IDLE] = subwin(stdscr, cstate_lines, win_cols/2 + 1, pos_y, 0); + sw[SW_FREQ] = subwin(stdscr, cstate_lines, win_cols/2 - 8, pos_y, + win_cols/2 + 8); pos_y += cstate_lines + BLANK_LINE; - wakeup_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); + sw[SW_WAKEUPS] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); pos_y += NEXT_LINE; - acpi_power_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); + sw[SW_POWER] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); pos_y += NEXT_LINE + BLANK_LINE; - event_lines = maxy - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW - + event_lines = win_rows - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW - pos_y; - eventstat_window = subwin(stdscr, event_lines, maxx, pos_y, 0); + + if (event_lines > 0) { + sw[SW_EVENTS] = subwin(stdscr, event_lines, win_cols, pos_y, 0); + } else { + (void) printf("\n\nPowerTOP cannot run in such a small " + "terminal window, please resize it.\n\n"); + exit(EXIT_FAILURE); + } pos_y += event_lines + NEXT_LINE; - suggestion_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); + sw[SW_SUGG] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); pos_y += BLANK_LINE + NEXT_LINE; - status_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); + sw[SW_STATUS] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); + + if (!resized) { + status_bar = NULL; - (void) strcpy(g_status_bar_slots[0], _(" Q - Quit ")); - (void) strcpy(g_status_bar_slots[1], _(" R - Refresh ")); + pt_display_mod_status_bar(_("Q - Quit")); + pt_display_mod_status_bar(_("R - Refresh")); + } - (void) werase(stdscr); - (void) wrefresh(status_bar_window); + pt_display_status_bar(); } +/* + * This routine handles all the necessary curses initialization. + */ void -initialize_curses(void) +pt_display_init_curses(void) { (void) initscr(); + + (void) atexit(pt_display_cleanup); + (void) signal(SIGWINCH, pt_display_resize); + + pt_display_get_size(); + (void) start_color(); /* @@ -192,86 +259,172 @@ (void) init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN); (void) init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE); (void) init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK); +} - (void) atexit(cleanup_curses); +void +pt_display_update(void) +{ + (void) doupdate(); +} + +void +pt_display_title_bar(void) +{ + char title_pad[10]; + + (void) wattrset(sw[SW_TITLE], COLOR_PAIR(PT_COLOR_HEADER_BAR)); + (void) wbkgd(sw[SW_TITLE], COLOR_PAIR(PT_COLOR_HEADER_BAR)); + (void) werase(sw[SW_TITLE]); + + (void) snprintf(title_pad, 10, "%%%ds", + (win_cols - strlen(TITLE))/2 + strlen(TITLE)); + + /* LINTED: E_SEC_PRINTF_VAR_FMT */ + print(sw[SW_TITLE], 0, 0, title_pad, TITLE); + + (void) wnoutrefresh(sw[SW_TITLE]); } void -show_title_bar(void) +pt_display_status_bar(void) { - int i, x = 0, y = 0; - char title_pad[10]; + sb_slot_t *n = status_bar; + int x = 0; + + (void) werase(sw[SW_STATUS]); + + while (n && x < win_cols) { + (void) wattron(sw[SW_STATUS], A_REVERSE); + print(sw[SW_STATUS], 0, x, "%s", n->msg); + (void) wattroff(sw[SW_STATUS], A_REVERSE); + x += strlen(n->msg) + 1; + + n = n->next; + } + + (void) wnoutrefresh(sw[SW_STATUS]); +} - (void) wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR)); - (void) wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR)); - (void) werase(title_bar_window); +/* + * Adds or removes items to the status bar automatically. + * Only one instance of an item allowed. + */ +void +pt_display_mod_status_bar(char *msg) +{ + sb_slot_t *new, *n; + boolean_t found = B_FALSE, first = B_FALSE; + + if (msg == NULL) { + pt_error("%s : can't add an empty status bar item.", __FILE__); + return; + } + + if (status_bar != NULL) { + /* + * Non-empty status bar. Look for an entry matching this msg. + */ + for (n = status_bar; n != NULL; n = n->next) { + + if (strcmp(msg, n->msg) == 0) { + if (n != status_bar) + n->prev->next = n->next; + else + first = B_TRUE; - (void) snprintf(title_pad, 10, "%%%ds", - (maxx - strlen(TITLE))/2 + strlen(TITLE)); - /* LINTED: E_SEC_PRINTF_VAR_FMT */ - print(title_bar_window, y, x, title_pad, TITLE); + if (n->next != NULL) { + n->next->prev = n->prev; + if (first) + status_bar = n->next; + } else { + if (first) + status_bar = NULL; + } - (void) wrefresh(title_bar_window); - (void) werase(status_bar_window); + free(n); + found = B_TRUE; + } + } - for (i = 0; i < PT_BAR_NSLOTS; i++) { - if (strlen(g_status_bar_slots[i]) == 0) - continue; - (void) wattron(status_bar_window, A_REVERSE); - print(status_bar_window, y, x, "%s", g_status_bar_slots[i]); - (void) wattroff(status_bar_window, A_REVERSE); - x += strlen(g_status_bar_slots[i]) + 1; + /* + * Found and removed at least one occurrance of msg, refresh + * the bar and return. + */ + if (found) { + return; + } else { + /* + * Inserting a new msg, walk to the end of the bar. + */ + for (n = status_bar; n->next != NULL; n = n->next) + ; + } } - (void) wnoutrefresh(status_bar_window); + + if ((new = calloc(1, sizeof (sb_slot_t))) == NULL) { + pt_error("%s : failed to allocate a new slot\n", __FILE__); + } else { + new->msg = strdup(msg); + + /* + * Check if it's the first entry. + */ + if (status_bar == NULL) { + status_bar = new; + new->prev = NULL; + } else { + new->prev = n; + n->next = new; + } + new->next = NULL; + } } void -show_cstates(void) +pt_display_states(void) { char c[100]; int i; double total_pstates = 0.0, avg, res; uint64_t p0_speed, p1_speed; - if (!PT_ON_DUMP) { - (void) werase(cstate_window); - (void) wattrset(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT)); - (void) wbkgd(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT)); + print(sw[SW_IDLE], 0, 0, "%s\tAvg\tResidency\n", g_msg_idle_state); + + if (g_features & FEATURE_CSTATE) { + res = (((double)g_cstate_info[0].total_time / g_total_c_time)) + * 100; + (void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res); + print(sw[SW_IDLE], 1, 0, "%s", c); + + for (i = 1; i <= g_max_cstate; i++) { + /* + * In situations where the load is too intensive, the + * system might not transition at all. + */ + if (g_cstate_info[i].events > 0) + avg = (((double)g_cstate_info[i].total_time/ + MICROSEC)/g_cstate_info[i].events); + else + avg = 0; + + res = ((double)g_cstate_info[i].total_time/ + g_total_c_time) * 100; + + (void) sprintf(c, "C%d\t\t\t%.1fms\t(%.1f%%)\n", + i, (float)avg, (float)res); + print(sw[SW_IDLE], i + 1, 0, "%s", c); + } } - print(cstate_window, 0, 0, "%s\tAvg\tresidency\n", g_msg_idle_state); - res = (((double)g_cstate_info[0].total_time / g_total_c_time)) * 100; - (void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res); - print(cstate_window, 1, 0, "%s", c); + if (!PT_ON_DUMP) + (void) wnoutrefresh(sw[SW_IDLE]); - for (i = 1; i <= g_max_cstate; i++) { - /* - * In situations where the load is too intensive, the system - * might not transition at all. - */ - if (g_cstate_info[i].events > 0) - avg = (((double)g_cstate_info[i].total_time/ - MICROSEC)/g_cstate_info[i].events); - else - avg = 0; + print(sw[SW_FREQ], 0, 0, "%s\n", g_msg_freq_state); - res = ((double)g_cstate_info[i].total_time/g_total_c_time) - * 100; - - (void) sprintf(c, "C%d\t\t\t%.1fms\t(%.1f%%)\n", i, (float)avg, - (float)res); - print(cstate_window, i + 1, 0, "%s", c); - } - - print(cstate_window, 0, 48, "%s\n", g_msg_freq_state); - - if (g_npstates < 2) { - (void) sprintf(c, "%4lu Mhz\t%.1f%%", - (long)g_pstate_info[0].speed, 100.0); - print(cstate_window, 1, 48, "%s\n", c); - } else { + if (g_features & FEATURE_PSTATE) { for (i = 0; i < g_npstates; i++) { - total_pstates += (double)(g_pstate_info[i].total_time/ + total_pstates += + (double)(g_pstate_info[i].total_time/ g_ncpus_observed/MICROSEC); } @@ -281,9 +434,9 @@ for (i = 0; i < g_npstates - 1; i++) { (void) sprintf(c, "%4lu Mhz\t%.1f%%", (long)g_pstate_info[i].speed, - 100 * (g_pstate_info[i].total_time/g_ncpus_observed/ - MICROSEC/total_pstates)); - print(cstate_window, i+1, 48, "%s\n", c); + 100 * (g_pstate_info[i].total_time/ + g_ncpus_observed/MICROSEC/total_pstates)); + print(sw[SW_FREQ], i+1, 0, "%s\n", c); } /* @@ -301,12 +454,14 @@ p0_speed = p1_speed + 1; } else { /* - * If g_turbo_ratio > 1.0, that means turbo - * mode works. So, P(0) = ratio * P(1); + * If g_turbo_ratio > 1.0, that means + * turbo mode works. So, P(0) = ratio * + * P(1); */ - p0_speed = (uint64_t)(p1_speed * g_turbo_ratio); + p0_speed = (uint64_t)(p1_speed * + g_turbo_ratio); if (p0_speed < (p1_speed + 1)) - p0_speed = p1_speed + 1; + p0_speed = p1_speed + 1; } /* * Reset the ratio for the next round @@ -326,15 +481,21 @@ 100 * (g_pstate_info[i].total_time/ g_ncpus_observed/MICROSEC/total_pstates)); } - print(cstate_window, i+1, 48, "%s\n", c); + print(sw[SW_FREQ], i+1, 0, "%s\n", c); + } else { + if (g_npstates == 1) { + (void) sprintf(c, "%4lu Mhz\t%.1f%%", + (long)g_pstate_info[0].speed, 100.0); + print(sw[SW_FREQ], 1, 0, "%s\n", c); + } } if (!PT_ON_DUMP) - (void) wnoutrefresh(cstate_window); + (void) wnoutrefresh(sw[SW_FREQ]); } void -show_acpi_power_line(uint32_t flag, double rate, double rem_cap, double cap, +pt_display_acpi_power(uint32_t flag, double rate, double rem_cap, double cap, uint32_t state) { char buffer[1024]; @@ -342,7 +503,8 @@ (void) sprintf(buffer, _("no ACPI power usage estimate available")); if (!PT_ON_DUMP) - (void) werase(acpi_power_window); + (void) werase(sw[SW_POWER]); + if (flag) { char *c; (void) sprintf(buffer, "Power usage (ACPI estimate): %.3fW", @@ -368,22 +530,23 @@ } } - print(acpi_power_window, 0, 0, "%s\n", buffer); + + print(sw[SW_POWER], 0, 0, "%s\n", buffer); if (!PT_ON_DUMP) - (void) wnoutrefresh(acpi_power_window); + (void) wnoutrefresh(sw[SW_POWER]); } void -show_wakeups(double interval) +pt_display_wakeups(double interval) { char c[100]; int i, event_sum = 0; event_info_t *event = g_event_info; if (!PT_ON_DUMP) { - (void) werase(wakeup_window); - (void) wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED)); - (void) wattron(wakeup_window, A_BOLD); + (void) werase(sw[SW_WAKEUPS]); + (void) wbkgd(sw[SW_WAKEUPS], COLOR_PAIR(PT_COLOR_RED)); + (void) wattron(sw[SW_WAKEUPS], A_BOLD); } /* @@ -404,14 +567,14 @@ (void) sprintf(c, "Wakeups-from-idle per second: %4.1f\tinterval: " "%.1fs", (double)(g_total_events/interval), interval); - print(wakeup_window, 0, 0, "%s\n", c); + print(sw[SW_WAKEUPS], 0, 0, "%s\n", c); if (!PT_ON_DUMP) - (void) wnoutrefresh(wakeup_window); + (void) wnoutrefresh(sw[SW_WAKEUPS]); } void -show_eventstats(double interval) +pt_display_events(double interval) { char c[100]; int i; @@ -419,9 +582,9 @@ event_info_t *event = g_event_info; if (!PT_ON_DUMP) { - (void) werase(eventstat_window); - (void) wattrset(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT)); - (void) wbkgd(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT)); + (void) werase(sw[SW_EVENTS]); + (void) wbkgd(sw[SW_EVENTS], COLOR_PAIR(PT_COLOR_DEFAULT)); + (void) wattron(sw[SW_EVENTS], COLOR_PAIR(PT_COLOR_DEFAULT)); } /* @@ -439,7 +602,7 @@ else (void) sprintf(c, "Top causes for wakeups:\n"); - print(eventstat_window, 0, 0, "%s", c); + print(sw[SW_EVENTS], 0, 0, "%s", c); for (i = 0; i < g_top_events; i++, event++) { @@ -451,27 +614,26 @@ (void) sprintf(c, "%4.1f%% (%5.1f)", 100 * events, (double)event->total_count/interval); - print(eventstat_window, i+1, 0, "%s", c); - print(eventstat_window, i+1, 16, "%20s :", + print(sw[SW_EVENTS], i+1, 0, "%s", c); + print(sw[SW_EVENTS], i+1, 16, "%20s :", event->offender_name); - print(eventstat_window, i+1, 40, "%-64s\n", + print(sw[SW_EVENTS], i+1, 40, "%-64s\n", event->offense_name); } if (!PT_ON_DUMP) - (void) wnoutrefresh(eventstat_window); + (void) wnoutrefresh(sw[SW_EVENTS]); } void -show_suggestion(char *sug) +pt_display_suggestions(char *sug) { - (void) werase(suggestion_window); - print(suggestion_window, 0, 0, "%s", sug); - (void) wnoutrefresh(suggestion_window); + (void) werase(sw[SW_SUGG]); + + if (sug != NULL) + print(sw[SW_SUGG], 0, 0, "%s", sug); + + (void) wnoutrefresh(sw[SW_SUGG]); + + pt_display_update(); } - -void -update_windows(void) -{ - (void) doupdate(); -}
--- a/usr/src/cmd/powertop/common/powertop.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/common/powertop.c Fri Jun 19 06:14:38 2009 -0700 @@ -41,6 +41,7 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <signal.h> #include <string.h> #include <ctype.h> #include <locale.h> @@ -52,11 +53,11 @@ */ double g_ticktime, g_ticktime_usr; double g_interval; -double g_displaytime; int g_bit_depth; int g_total_events, g_top_events; int g_npstates, g_max_cstate, g_longest_cstate; +uint_t g_features; uint_t g_ncpus; uint_t g_ncpus_observed; @@ -72,7 +73,6 @@ state_info_t g_cstate_info[NSTATES]; freq_state_info_t g_pstate_info[NSTATES]; cpu_power_info_t *g_cpu_power_states; -suggestion_func *g_suggestion_activate; boolean_t g_turbo_supported; @@ -87,10 +87,11 @@ main(int argc, char **argv) { hrtime_t last, now; - uint_t features = 0, user_interval = 0; - int ncursesinited = 0, index2 = 0, c, ret, dump_count = 0; + uint_t user_interval = 0; + int index2 = 0, c, ret, dump_count = 0; double last_time; char *endptr; + boolean_t root_user = B_FALSE; static struct option opts[] = { { "dump", 1, NULL, 'd' }, @@ -108,8 +109,7 @@ pt_set_progname(argv[0]); /* - * Enumerate the system's CPUs - * Populate cpu_table, g_ncpus + * Enumerate the system's CPUs, populate cpu_table, g_ncpus */ if ((g_ncpus = g_ncpus_observed = enumerate_cpus()) == 0) exit(EXIT_FAILURE); @@ -117,15 +117,16 @@ if ((g_bit_depth = get_bit_depth()) < 0) exit(EXIT_FAILURE); + g_features = 0; g_ticktime = g_ticktime_usr = INTERVAL_DEFAULT; - g_displaytime = 0.0; - g_op_mode = PT_MODE_DEFAULT; - g_gui = B_FALSE; - g_max_cstate = 0; - g_argv = NULL; - g_argc = 0; - g_observed_cpu = 0; + g_op_mode = PT_MODE_DEFAULT; + g_gui = B_FALSE; + g_max_cstate = 0; + g_argv = NULL; + g_argc = 0; + g_observed_cpu = 0; g_turbo_supported = B_FALSE; + g_curr_sugg = NULL; while ((c = getopt_long(argc, argv, "d:t:h:vc:", opts, &index2)) != EOF) { @@ -189,22 +190,22 @@ } } - if (optind < argc) { + if (optind < argc) usage(); - } (void) printf("%s %s\n\n", TITLE, COPYRIGHT_INTEL); - /* - * If the system is running on battery, find out what's - * the kstat module for it - */ - battery_mod_lookup(); + (void) printf(_("Collecting data for %.2f second(s) \n"), + (float)g_ticktime); + + /* Prepare P-state statistics */ + if (pt_cpufreq_stat_prepare() == 0) + g_features |= FEATURE_PSTATE; /* Prepare C-state statistics */ ret = pt_cpuidle_stat_prepare(); if (ret == 0) - features |= FEATURE_CSTATE; + g_features |= FEATURE_CSTATE; else /* * PowerTop was unable to run a DTrace program, @@ -212,31 +213,51 @@ */ exit(EXIT_FAILURE); - /* Prepare P-state statistics */ - if (pt_cpufreq_stat_prepare() == 0) - features |= FEATURE_PSTATE; + /* + * We need to initiate the display to make sure there's enough space + * in the terminal for all of PowerTOP's subwindows, but after + * pt_cpufreq_stat_prepare() which finds out how many states the + * system supports. + */ + if (!PT_ON_DUMP) { + pt_display_init_curses(); + pt_display_setup(B_FALSE); + g_gui = B_TRUE; + pt_display_title_bar(); + pt_display_status_bar(); + } /* Prepare event statistics */ if (pt_events_stat_prepare() != -1) - features |= FEATURE_EVENTS; + g_features |= FEATURE_EVENTS; + + /* + * If the system is running on battery, find out what's + * the kstat module for it + */ + battery_mod_lookup(); /* Prepare turbo statistics */ - if (pt_turbo_stat_prepare() == 0) { - features |= FEATURE_TURBO; - } + if (pt_turbo_stat_prepare() == 0) + g_features |= FEATURE_TURBO; - (void) printf(_("Collecting data for %.2f second(s) \n"), - (float)g_ticktime); - - if (!PT_ON_DUMP) - g_gui = B_TRUE; + /* + * Installs the initial suggestions, running as root and turning CPU + * power management ON. + */ + if (geteuid() != 0) + pt_sugg_as_root(); + else { + root_user = B_TRUE; + pt_cpufreq_suggest(); + } last = gethrtime(); while (true) { fd_set rfds; struct timeval tv; - int key, reinit = 0; + int key; char keychar; /* @@ -246,18 +267,18 @@ FD_ZERO(&rfds); FD_SET(0, &rfds); - tv.tv_sec = (long)g_ticktime; - tv.tv_usec = (long)((g_ticktime - tv.tv_sec) * MICROSEC); + tv.tv_sec = (long)g_ticktime; + tv.tv_usec = (long)((g_ticktime - tv.tv_sec) * MICROSEC); - if (!PT_ON_DUMP) + if (!PT_ON_DUMP) { key = select(1, &rfds, NULL, NULL, &tv); - else + } else key = select(1, NULL, NULL, NULL, &tv); - now = gethrtime(); + now = gethrtime(); - g_interval = (double)(now - last)/NANOSEC; - last = now; + g_interval = (double)(now - last)/NANOSEC; + last = now; g_top_events = 0; g_total_events = 0; @@ -268,145 +289,114 @@ NSTATES * sizeof (state_info_t)); /* Collect idle state transition stats */ - if (features & FEATURE_CSTATE && + if (g_features & FEATURE_CSTATE && pt_cpuidle_stat_collect(g_interval) < 0) { /* Reinitialize C-state statistics */ if (pt_cpuidle_stat_prepare() != 0) exit(EXIT_FAILURE); - reinit = 1; + continue; } /* Collect frequency change stats */ - if (features & FEATURE_PSTATE && + if (g_features & FEATURE_PSTATE && pt_cpufreq_stat_collect(g_interval) < 0) { /* Reinitialize P-state statistics */ if (pt_cpufreq_stat_prepare() != 0) exit(EXIT_FAILURE); - reinit = 1; + continue; } /* Collect event statistics */ - if (features & FEATURE_EVENTS && + if (g_features & FEATURE_EVENTS && pt_events_stat_collect() < 0) { /* Reinitialize event statistics */ if (pt_events_stat_prepare() != 0) exit(EXIT_FAILURE); - reinit = 1; - } - - if (reinit) continue; - - /* Collect turbo statistics */ - if (features & FEATURE_TURBO && - pt_turbo_stat_collect() < 0) { - exit(EXIT_FAILURE); } - /* - * Initialize curses if we're not dumping and - * haven't already done it - */ - if (!PT_ON_DUMP) { - if (!ncursesinited) { - initialize_curses(); - ncursesinited++; - } - setup_windows(); - show_title_bar(); + /* Collect turbo statistics */ + if (g_features & FEATURE_TURBO && + pt_turbo_stat_collect() < 0) + exit(EXIT_FAILURE); + + /* Show CPU power states */ + pt_display_states(); + + /* Show wakeups events affecting PM */ + if (g_features & FEATURE_EVENTS) { + pt_display_wakeups(g_interval); + pt_display_events(g_interval); } - /* Show CPU power states */ - if (features & FEATURE_CSTATE) - show_cstates(); - - /* Show wakeups events affecting PM */ - if (features & FEATURE_EVENTS) { - show_wakeups(g_interval); - show_eventstats(g_interval); - } - - print_battery(); - - g_displaytime = g_displaytime - g_ticktime; + pt_battery_print(); if (key && !PT_ON_DUMP) { keychar = toupper(fgetc(stdin)); switch (keychar) { case 'Q': - cleanup_curses(); exit(EXIT_SUCCESS); break; + case 'R': g_ticktime = 3; break; } - if (keychar == g_suggestion_key && - g_suggestion_activate) { - g_suggestion_activate(); - g_displaytime = -1.0; - } - } - reset_suggestions(); - /* suggests PM */ - if (geteuid() == 0) { - suggest_p_state(); - } else { - suggest_as_root(); + /* + * Check if the user has activated the current + * suggestion. + */ + if (g_curr_sugg != NULL && + keychar == g_curr_sugg->key && g_curr_sugg->func) + g_curr_sugg->func(); } if (dump_count) dump_count--; /* Exits if user requested a dump */ - if (PT_ON_DUMP && !dump_count) { - print_all_suggestions(); + if (PT_ON_DUMP && !dump_count) exit(EXIT_SUCCESS); - } /* No key pressed, will suggest something */ if (!key && !dump_count) - pick_suggestion(); + pt_sugg_pick(); /* Refresh display */ - if (!PT_ON_DUMP) { - show_title_bar(); - update_windows(); - } + if (!PT_ON_DUMP) + pt_display_update(); + + if (root_user) + pt_cpufreq_suggest(); /* * Update the interval based on how long the CPU was in the * longest c-state during the last snapshot. If the user * specified an interval we skip this bit and keep it fixed. */ - last_time = (((double)g_cstate_info[g_longest_cstate].total_time - /MICROSEC/g_ncpus)/g_cstate_info[g_longest_cstate].events); + if (g_features & FEATURE_CSTATE && !user_interval) { + last_time = (((double) + g_cstate_info[g_longest_cstate].total_time/MICROSEC + /g_ncpus)/g_cstate_info[g_longest_cstate].events); - if (!user_interval) if (last_time < INTERVAL_DEFAULT || (g_total_events/g_ticktime) < 1) g_ticktime = INTERVAL_DEFAULT; else g_ticktime = INTERVAL_UPDATE(last_time); + } else { + /* + * Restore interval after a refresh. + */ + if (key) + g_ticktime = g_ticktime_usr; + } + } - /* - * Restore user specified interval after a refresh - */ - if (keychar == 'R' && user_interval) - g_ticktime = g_ticktime_usr; - } return (EXIT_SUCCESS); } - -void -suggest_as_root(void) -{ - add_suggestion("Suggestion: run as root to get suggestions" - " for reducing system power consumption", 40, NULL, NULL, - NULL); -}
--- a/usr/src/cmd/powertop/common/powertop.h Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/common/powertop.h Fri Jun 19 06:14:38 2009 -0700 @@ -48,7 +48,7 @@ #define _(STRING) gettext(STRING) -#define TITLE "OpenSolaris PowerTOP version 1.1" +#define TITLE "OpenSolaris PowerTOP version 1.2" #define COPYRIGHT_INTEL "(C) 2009 Intel Corporation" /* @@ -79,29 +79,6 @@ #define NSTATES 32 /* - * Display colors - */ -#define PT_COLOR_DEFAULT 1 -#define PT_COLOR_HEADER_BAR 2 -#define PT_COLOR_ERROR 3 -#define PT_COLOR_RED 4 -#define PT_COLOR_YELLOW 5 -#define PT_COLOR_GREEN 6 -#define PT_COLOR_BRIGHT 7 -#define PT_COLOR_BLUE 8 - -/* - * Constants for setup_windows() - */ -#define SINGLE_LINE_SW 1 -#define LENGTH_SUGG_SW 2 -#define TITLE_LINE 1 -#define BLANK_LINE 1 -#define NEXT_LINE 1 -#define PT_BAR_NSLOTS 10 -#define PT_BAR_LENGTH 40 - -/* * Available op modes */ #define PT_MODE_DEFAULT 0x01 @@ -158,12 +135,21 @@ uint64_t t_acnt; } turbo_info_t; -typedef void (suggestion_func)(void); +/* + * Suggestions + */ +typedef void (sugg_func_t)(void); -/* - * Global variables - */ -extern double g_displaytime; +typedef struct suggestion { + char *text; + char key; + char *sb_msg; + int weight; + int slice; + sugg_func_t *func; + struct suggestion *prev; + struct suggestion *next; +} sugg_t; extern int g_bit_depth; @@ -213,12 +199,10 @@ extern state_info_t g_cstate_info[NSTATES]; extern freq_state_info_t g_pstate_info[NSTATES]; +extern uint_t g_features; extern uint_t g_ncpus; extern uint_t g_ncpus_observed; -extern char g_status_bar_slots[PT_BAR_NSLOTS] - [PT_BAR_LENGTH]; - extern cpu_power_info_t *g_cpu_power_states; /* @@ -227,8 +211,7 @@ extern boolean_t g_turbo_supported; extern double g_turbo_ratio; -extern char g_suggestion_key; -extern suggestion_func *g_suggestion_activate; +extern sugg_t *g_curr_sugg; /* * DTrace scripts for the events report @@ -247,13 +230,15 @@ /* * Platform specific messages */ -extern const char *g_msg_idle_state; -extern const char *g_msg_freq_state; +extern const char *g_msg_idle_state; +extern const char *g_msg_freq_state; +extern const char *g_msg_freq_enable; + /* * Suggestions related */ -extern void suggest_p_state(void); -extern void suggest_as_root(void); +extern void pt_cpufreq_suggest(void); +extern void pt_sugg_as_root(void); /* * See util.c @@ -269,27 +254,30 @@ /* * Display/curses related */ -extern void show_title_bar(void); -extern void setup_windows(void); -extern void initialize_curses(void); -extern void show_acpi_power_line(uint32_t, double, double, double, +extern void pt_display_setup(boolean_t); +extern void pt_display_init_curses(void); +extern void pt_display_update(void); +extern void pt_display_title_bar(void); +extern void pt_display_status_bar(void); +extern void pt_display_mod_status_bar(char *); +extern void pt_display_states(void); +extern void pt_display_acpi_power(uint32_t, double, double, double, uint32_t); -extern void show_cstates(); -extern void show_wakeups(double); -extern void show_eventstats(double); -extern void show_suggestion(char *); -extern void cleanup_curses(void); -extern void update_windows(void); +extern void pt_display_wakeups(double); +extern void pt_display_events(double); +extern void pt_display_suggestions(char *); /* * Suggestions */ -extern void pick_suggestion(void); -extern void add_suggestion(char *, int, char, char *, - suggestion_func *); -extern void reset_suggestions(void); -extern void print_all_suggestions(void); -extern void print_battery(void); +extern void pt_sugg_add(char *, int, char, char *, sugg_func_t *); +extern int pt_sugg_remove(sugg_func_t *); +extern void pt_sugg_pick(void); + +/* + * Battery + */ +extern void pt_battery_print(void); /* * DTrace stats
--- a/usr/src/cmd/powertop/common/suggestions.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/common/suggestions.c Fri Jun 19 06:14:38 2009 -0700 @@ -43,136 +43,231 @@ #include <string.h> #include "powertop.h" -struct suggestion; +/* + * Default number of intervals we display a suggestion before moving + * to the next. + */ +#define PT_SUGG_DEF_SLICE 3 + +/* + * Global pointer to the current suggestion. + */ +sugg_t *g_curr_sugg; + +/* + * Head of the list of suggestions. + */ +static sugg_t *sugg; -struct suggestion { - struct suggestion *next; +/* + * Add a new suggestion. Only one suggestion per text allowed. + */ +void +pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func) +{ + sugg_t *new, *n, *pos = NULL; + + /* + * Text is a required field for suggestions + */ + if (text == NULL) + return; + + if (sugg == NULL) { + /* + * Creating first element + */ + if ((new = calloc(1, sizeof (sugg_t))) == NULL) + return; - char *string; - int weight; - char key; - char *keystring; + if (sb_msg != NULL) + new->sb_msg = strdup(sb_msg); + + if (text != NULL) + new->text = strdup(text); + + new->weight = weight; + new->key = key; + new->func = func; + new->slice = 0; + + sugg = new; + new->prev = NULL; + new->next = NULL; + } else { + for (n = sugg; n != NULL; n = n->next) { + if (strcmp(n->text, text) == 0) + return; - suggestion_func *func; -}; + if (weight > n->weight && pos == NULL) + pos = n; + } + /* + * Create a new element + */ + if ((new = calloc(1, sizeof (sugg_t))) == NULL) + return; -static struct suggestion *suggestions; -static int total_weight; + if (sb_msg != NULL) + new->sb_msg = strdup(sb_msg); + + new->text = strdup(text); + + new->weight = weight; + new->key = key; + new->func = func; + new->slice = 0; -static char previous[1024]; + if (pos == NULL) { + /* + * Ordering placed the new element at the end + */ + for (n = sugg; n->next != NULL; n = n->next) + ; -void -reset_suggestions(void) -{ - struct suggestion *ptr; - - ptr = suggestions; + n->next = new; + new->prev = n; + new->next = NULL; + } else { + if (pos == sugg) { + /* + * Ordering placed the new element at the start + */ + new->next = sugg; + new->prev = sugg; + sugg->prev = new; + sugg = new; + } else { + /* + * Ordering placed the new element somewhere in + * the middle + */ + new->next = pos; + new->prev = pos->prev; + pos->prev->next = new; + pos->prev = new; + } + } + } +} - while (ptr) { - struct suggestion *next; +/* + * Removes a suggestion, returning 0 if not found and 1 if so. + */ +int +pt_sugg_remove(sugg_func_t *func) +{ + sugg_t *n; + int ret = 0; - next = ptr->next; - free(ptr->string); - free(ptr->keystring); - free(ptr); - ptr = next; + for (n = sugg; n != NULL; n = n->next) { + if (n->func == func) { + /* Removing the first element */ + if (n == sugg) { + if (sugg->next == NULL) { + /* Removing the only element */ + sugg = NULL; + } else { + sugg = n->next; + sugg->prev = NULL; + } + } else { + if (n->next == NULL) { + /* Removing the last element */ + n->prev->next = NULL; + } else { + /* Removing an intermediate element */ + n->prev->next = n->next; + n->next->prev = n->prev; + } + } + + /* + * If this suggestions is currently being suggested, + * remove it and update the screen. + */ + if (n == g_curr_sugg) { + if (n->sb_msg != NULL) { + pt_display_mod_status_bar(n->sb_msg); + pt_display_status_bar(); + } + if (n->text != NULL) + pt_display_suggestions(NULL); + } + + free(n); + ret = 1; + } } - suggestions = NULL; - (void) strcpy(g_status_bar_slots[8], ""); + return (ret); +} + +/* + * Chose a suggestion to display. The list of suggestions is ordered by weight, + * so we only worry about fariness here. Each suggestion, starting with the + * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals. + */ +void +pt_sugg_pick(void) +{ + sugg_t *n; + + if (sugg == NULL) { + g_curr_sugg = NULL; + return; + } + +search: + for (n = sugg; n != NULL; n = n->next) { + + if (n->slice++ < PT_SUGG_DEF_SLICE) { + + /* + * Don't need to re-suggest the current suggestion. + */ + if (g_curr_sugg == n) + return; - g_suggestion_key = -1; - g_suggestion_activate = NULL; - total_weight = 0; + /* + * Remove the current suggestion from screen. + */ + if (g_curr_sugg != NULL) { + if (g_curr_sugg->sb_msg != NULL) { + pt_display_mod_status_bar( + g_curr_sugg->sb_msg); + pt_display_status_bar(); + } + if (g_curr_sugg->text != NULL) + pt_display_suggestions(NULL); + } + + if (n->sb_msg != NULL) { + pt_display_mod_status_bar(n->sb_msg); + pt_display_status_bar(); + } + + pt_display_suggestions(n->text); + + g_curr_sugg = n; + + return; + } + } + + /* + * All suggestions have run out of slice quotas, so we restart. + */ + for (n = sugg; n != NULL; n = n->next) + n->slice = 0; + + goto search; } void -add_suggestion(char *text, int weight, char key, char *keystring, - suggestion_func *func) -{ - struct suggestion *new; - - if (!text) - return; - - new = malloc(sizeof (struct suggestion)); - - if (!new) - return; - - (void) memset(new, 0, sizeof (struct suggestion)); - - new->string = strdup(text); - new->weight = weight; - new->key = key; - - if (keystring) - new->keystring = strdup(keystring); - - new->next = suggestions; - new->func = func; - suggestions = new; - total_weight += weight; -} - -void -pick_suggestion(void) +pt_sugg_as_root(void) { - int weight, value, running = 0; - struct suggestion *ptr; - - (void) strcpy(g_status_bar_slots[8], ""); - g_suggestion_key = -1; - g_suggestion_activate = NULL; - - if (total_weight == 0 || suggestions == NULL) { - show_suggestion(""); - return; - } - - weight = total_weight; - - if (strlen(previous) && g_displaytime > 0.0) - weight += 50; - - value = rand() % weight; - ptr = suggestions; - - while (ptr) { - running += ptr->weight; - - if (strcmp(ptr->string, previous) == 0 && g_displaytime > 0.0) - running += 50; - - if (running > value) { - if (ptr->keystring) - (void) strncpy(g_status_bar_slots[8], - ptr->keystring, PT_BAR_LENGTH); - - g_suggestion_key = ptr->key; - g_suggestion_activate = ptr->func; - - show_suggestion(ptr->string); - - if (strcmp(ptr->string, previous)) { - g_displaytime = 30.0; - (void) strcpy(previous, ptr->string); - } - return; - } - ptr = ptr->next; - } - - show_suggestion(""); - (void) memset(previous, 0, sizeof (previous)); - g_displaytime = -1.0; + pt_sugg_add("Suggestion: run as root to get suggestions" + " for reducing system power consumption", 40, NULL, NULL, + NULL); } - -void -print_all_suggestions(void) -{ - struct suggestion *ptr; - - for (ptr = suggestions; ptr; ptr = ptr->next) - (void) printf("\n%s\n", ptr->string); -}
--- a/usr/src/cmd/powertop/i386/pt_i386.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/i386/pt_i386.c Fri Jun 19 06:14:38 2009 -0700 @@ -217,3 +217,4 @@ */ const char *g_msg_idle_state = "C-states (idle power)"; const char *g_msg_freq_state = "P-states (frequencies)"; +const char *g_msg_freq_enable = "P - Enable P-states";
--- a/usr/src/cmd/powertop/sparcv9/pt_sparcv9.c Fri Jun 19 20:12:07 2009 +0800 +++ b/usr/src/cmd/powertop/sparcv9/pt_sparcv9.c Fri Jun 19 06:14:38 2009 -0700 @@ -245,5 +245,6 @@ /* * sparcv9 platform specific display messages */ -const char *g_msg_idle_state = "Idle Power States\t"; +const char *g_msg_idle_state = "Idle Power States"; const char *g_msg_freq_state = "Frequency Levels"; +const char *g_msg_freq_enable = "P - Enable CPU PM";