/* * Copyright 2008, Intel Corporation * Copyright 2008, Sun Microsystems, Inc * * This file is part of PowerTOP * * This program file is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program in a file named COPYING; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * Authors: * Arjan van de Ven * Eric C Saxe * Aubrey Li */ /* * GPL Disclaimer * * For the avoidance of doubt, except that if any license choice other * than GPL or LGPL is available it will apply instead, Sun elects to * use only the General Public License version 2 (GPLv2) at this time * for any software where a choice of GPL license versions is made * available with the language indicating that GPLv2 or any later * version may be used, or where a choice of which version of the GPL * is applied is otherwise unspecified. */ #include #include #include #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; #define print(win, y, x, fmt, args...) \ if (dump) \ (void) printf(fmt, ## args); \ else \ (void) mvwprintw(win, y, x, fmt, ## args); char status_bar_slots[10][40]; int maxx, maxy; static void zap_windows(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; } } void cleanup_curses(void) { (void) endwin(); } /* * This part was re-written to be human readable and easy to modify. Please * try to keep it that way and help us save some time. * * Friendly reminder: * subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x) */ void setup_windows(void) { /* * 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); zap_windows(); cstate_lines = TITLE_LINE + max((max_cstate+1), npstates); pos_y = 0; title_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); pos_y += NEXT_LINE + BLANK_LINE; cstate_window = subwin(stdscr, cstate_lines, maxx, pos_y, 0); pos_y += cstate_lines + BLANK_LINE; wakeup_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); pos_y += NEXT_LINE; acpi_power_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); pos_y += NEXT_LINE + BLANK_LINE; event_lines = maxy - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW - pos_y; eventstat_window = subwin(stdscr, event_lines, maxx, pos_y, 0); pos_y += event_lines + NEXT_LINE; suggestion_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); pos_y += BLANK_LINE + NEXT_LINE; status_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0); (void) strcpy(status_bar_slots[0], _(" Q - Quit ")); (void) strcpy(status_bar_slots[1], _(" R - Refresh ")); (void) werase(stdscr); (void) wrefresh(status_bar_window); } void initialize_curses(void) { (void) initscr(); (void) start_color(); /* * Enable keyboard mapping */ (void) keypad(stdscr, TRUE); /* * Tell curses not to do NL->CR/NL on output */ (void) nonl(); /* * Take input chars one at a time, no wait for \n */ (void) cbreak(); /* * Dont echo input */ (void) noecho(); /* * Turn off cursor */ (void) curs_set(0); (void) init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK); (void) init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE); (void) init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED); (void) init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED); (void) init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW); (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 show_title_bar(void) { int i, x = 0, y = 0; char title_pad[10]; (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); (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); (void) wrefresh(title_bar_window); (void) werase(status_bar_window); for (i = 0; i < 10; i++) { if (strlen(status_bar_slots[i]) == 0) continue; (void) wattron(status_bar_window, A_REVERSE); print(status_bar_window, y, x, "%s", status_bar_slots[i]); (void) wattroff(status_bar_window, A_REVERSE); x += strlen(status_bar_slots[i]) + 1; } (void) wnoutrefresh(status_bar_window); } void show_cstates(void) { char c[100]; int i; double total_pstates = 0.0, avg, res; if (!dump) { (void) werase(cstate_window); (void) wattrset(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT)); (void) wbkgd(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT)); } print(cstate_window, 0, 0, "%s", "Cn\t\t\tAvg residency\n"); res = (((double)cstate_info[0].total_time / total_c_time)) * 100; (void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res); print(cstate_window, 1, 0, "%s", c); for (i = 1; i <= max_cstate; i++) { /* * In situations where the load is too intensive, the system * might not transition at all. */ if (cstate_info[i].events > 0) avg = (((double)cstate_info[i].total_time/g_ncpus)/ cstate_info[i].events); else avg = 0; res = ((double)cstate_info[i].total_time/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", "P-states (frequencies)\n"); if (npstates < 2) { (void) sprintf(c, "%4lu Mhz\t%.1f%%", (long)pstate_info[0].speed, 100.0); print(cstate_window, 1, 48, "%s\n", c); } else { for (i = 0; i < npstates; i++) { total_pstates += (double)(pstate_info[i].total_time/ g_ncpus/1000000); } for (i = 0; i < npstates; i++) { (void) sprintf(c, "%4lu Mhz\t%.1f%%", (long)pstate_info[i].speed, 100 * (pstate_info[i].total_time/g_ncpus/1000000 /total_pstates)); print(cstate_window, i+1, 48, "%s\n", c); } } if (!dump) (void) wnoutrefresh(cstate_window); } void show_acpi_power_line(uint32_t flag, double rate, double rem_cap, double cap, uint32_t state) { char buffer[1024]; (void) sprintf(buffer, _("no ACPI power usage estimate available")); if (!dump) (void) werase(acpi_power_window); if (flag) { char *c; (void) sprintf(buffer, "Power usage (ACPI estimate): %.3fW", rate); (void) strcat(buffer, " "); c = &buffer[strlen(buffer)]; switch (state) { case 0: (void) sprintf(c, "(running on AC power, fully " "charged)"); break; case 1: (void) sprintf(c, "(discharging: %3.1f hours)", rem_cap/rate); break; case 2: (void) sprintf(c, "(charging: %3.1f hours)", (cap - rem_cap)/rate); break; case 4: (void) sprintf(c, "(##critically low battery power##)"); break; } } print(acpi_power_window, 0, 0, "%s\n", buffer); if (!dump) (void) wnoutrefresh(acpi_power_window); } void show_wakeups(double interval) { char c[100]; if (!dump) { (void) werase(wakeup_window); (void) wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED)); (void) wattron(wakeup_window, A_BOLD); } (void) sprintf(c, "Wakeups-from-idle per second: %4.1f\tinterval: " "%.1fs", (double)(total_events/interval), interval); print(wakeup_window, 0, 0, "%s\n", c); if (!dump) (void) wnoutrefresh(wakeup_window); } void show_eventstats(double interval) { char c[100]; int i; double events; event_info_t *p_event = event_info; if (!dump) { (void) werase(eventstat_window); (void) wattrset(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT)); (void) wbkgd(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT)); } /* * Sort the event report list */ if (top_events > EVENT_NUM_MAX) top_events = EVENT_NUM_MAX; qsort((void *)event_info, top_events, sizeof (event_info_t), event_compare); print(eventstat_window, 0, 0, "%s", "Top causes for wakeups:\n"); for (i = 0; i < top_events; i++, p_event++) { if (total_events > 0) events = (double)p_event->total_count/ (double)total_events; else events = 0; (void) sprintf(c, "%4.1f%% (%5.1f)", 100 * events, (double)p_event->total_count/interval); print(eventstat_window, i+1, 0, "%s", c); print(eventstat_window, i+1, 16, "%20s :", p_event->offender_name); print(eventstat_window, i+1, 40, "%-64s\n", p_event->offense_name); } if (!dump) (void) wnoutrefresh(eventstat_window); } void show_suggestion(char *sug) { (void) werase(suggestion_window); print(suggestion_window, 0, 0, "%s", sug); (void) wnoutrefresh(suggestion_window); } void update_windows(void) { (void) doupdate(); }