19338Srafael.vanoni@sun.com /* 29338Srafael.vanoni@sun.com * Copyright 2009, Intel Corporation 39338Srafael.vanoni@sun.com * Copyright 2009, Sun Microsystems, Inc 49338Srafael.vanoni@sun.com * 59338Srafael.vanoni@sun.com * This file is part of PowerTOP 69338Srafael.vanoni@sun.com * 79338Srafael.vanoni@sun.com * This program file is free software; you can redistribute it and/or modify it 89338Srafael.vanoni@sun.com * under the terms of the GNU General Public License as published by the 99338Srafael.vanoni@sun.com * Free Software Foundation; version 2 of the License. 109338Srafael.vanoni@sun.com * 119338Srafael.vanoni@sun.com * This program is distributed in the hope that it will be useful, but WITHOUT 129338Srafael.vanoni@sun.com * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 139338Srafael.vanoni@sun.com * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 149338Srafael.vanoni@sun.com * for more details. 159338Srafael.vanoni@sun.com * 169338Srafael.vanoni@sun.com * You should have received a copy of the GNU General Public License 179338Srafael.vanoni@sun.com * along with this program in a file named COPYING; if not, write to the 189338Srafael.vanoni@sun.com * Free Software Foundation, Inc., 199338Srafael.vanoni@sun.com * 51 Franklin Street, Fifth Floor, 209338Srafael.vanoni@sun.com * Boston, MA 02110-1301 USA 219338Srafael.vanoni@sun.com * 229338Srafael.vanoni@sun.com * Authors: 239338Srafael.vanoni@sun.com * Arjan van de Ven <arjan@linux.intel.com> 249338Srafael.vanoni@sun.com * Eric C Saxe <eric.saxe@sun.com> 259338Srafael.vanoni@sun.com * Aubrey Li <aubrey.li@intel.com> 269338Srafael.vanoni@sun.com */ 279338Srafael.vanoni@sun.com 289338Srafael.vanoni@sun.com /* 299338Srafael.vanoni@sun.com * GPL Disclaimer 309338Srafael.vanoni@sun.com * 319338Srafael.vanoni@sun.com * For the avoidance of doubt, except that if any license choice other 329338Srafael.vanoni@sun.com * than GPL or LGPL is available it will apply instead, Sun elects to 339338Srafael.vanoni@sun.com * use only the General Public License version 2 (GPLv2) at this time 349338Srafael.vanoni@sun.com * for any software where a choice of GPL license versions is made 359338Srafael.vanoni@sun.com * available with the language indicating that GPLv2 or any later 369338Srafael.vanoni@sun.com * version may be used, or where a choice of which version of the GPL 379338Srafael.vanoni@sun.com * is applied is otherwise unspecified. 389338Srafael.vanoni@sun.com */ 399338Srafael.vanoni@sun.com 409338Srafael.vanoni@sun.com #include <stdlib.h> 419338Srafael.vanoni@sun.com #include <string.h> 42*9908Srafael.vanoni@sun.com #include <unistd.h> 439338Srafael.vanoni@sun.com #include <curses.h> 44*9908Srafael.vanoni@sun.com #include <signal.h> 45*9908Srafael.vanoni@sun.com #include <fcntl.h> 469338Srafael.vanoni@sun.com #include "powertop.h" 479338Srafael.vanoni@sun.com 48*9908Srafael.vanoni@sun.com /* 49*9908Srafael.vanoni@sun.com * Minimum terminal height and width to run PowerTOP on curses mode. 50*9908Srafael.vanoni@sun.com */ 51*9908Srafael.vanoni@sun.com #define PT_MIN_COLS 70 52*9908Srafael.vanoni@sun.com #define PT_MIN_ROWS 15 53*9908Srafael.vanoni@sun.com 54*9908Srafael.vanoni@sun.com /* 55*9908Srafael.vanoni@sun.com * Display colors 56*9908Srafael.vanoni@sun.com */ 57*9908Srafael.vanoni@sun.com #define PT_COLOR_DEFAULT 1 58*9908Srafael.vanoni@sun.com #define PT_COLOR_HEADER_BAR 2 59*9908Srafael.vanoni@sun.com #define PT_COLOR_ERROR 3 60*9908Srafael.vanoni@sun.com #define PT_COLOR_RED 4 61*9908Srafael.vanoni@sun.com #define PT_COLOR_YELLOW 5 62*9908Srafael.vanoni@sun.com #define PT_COLOR_GREEN 6 63*9908Srafael.vanoni@sun.com #define PT_COLOR_BRIGHT 7 64*9908Srafael.vanoni@sun.com #define PT_COLOR_BLUE 8 65*9908Srafael.vanoni@sun.com 66*9908Srafael.vanoni@sun.com /* 67*9908Srafael.vanoni@sun.com * Constants for pt_display_setup() 68*9908Srafael.vanoni@sun.com */ 69*9908Srafael.vanoni@sun.com #define SINGLE_LINE_SW 1 70*9908Srafael.vanoni@sun.com #define LENGTH_SUGG_SW 2 71*9908Srafael.vanoni@sun.com #define TITLE_LINE 1 72*9908Srafael.vanoni@sun.com #define BLANK_LINE 1 73*9908Srafael.vanoni@sun.com #define NEXT_LINE 1 749338Srafael.vanoni@sun.com 759338Srafael.vanoni@sun.com #define print(win, y, x, fmt, args...) \ 769711Srafael.vanoni@sun.com if (PT_ON_DUMP) \ 779338Srafael.vanoni@sun.com (void) printf(fmt, ## args); \ 789338Srafael.vanoni@sun.com else \ 799338Srafael.vanoni@sun.com (void) mvwprintw(win, y, x, fmt, ## args); 809338Srafael.vanoni@sun.com 81*9908Srafael.vanoni@sun.com enum pt_subwindows { 82*9908Srafael.vanoni@sun.com SW_TITLE, 83*9908Srafael.vanoni@sun.com SW_IDLE, 84*9908Srafael.vanoni@sun.com SW_FREQ, 85*9908Srafael.vanoni@sun.com SW_WAKEUPS, 86*9908Srafael.vanoni@sun.com SW_POWER, 87*9908Srafael.vanoni@sun.com SW_EVENTS, 88*9908Srafael.vanoni@sun.com SW_SUGG, 89*9908Srafael.vanoni@sun.com SW_STATUS, 90*9908Srafael.vanoni@sun.com SW_COUNT 91*9908Srafael.vanoni@sun.com }; 929338Srafael.vanoni@sun.com 93*9908Srafael.vanoni@sun.com typedef struct sb_slot { 94*9908Srafael.vanoni@sun.com char *msg; 95*9908Srafael.vanoni@sun.com struct sb_slot *prev; 96*9908Srafael.vanoni@sun.com struct sb_slot *next; 97*9908Srafael.vanoni@sun.com } sb_slot_t; 98*9908Srafael.vanoni@sun.com 99*9908Srafael.vanoni@sun.com static WINDOW *sw[SW_COUNT]; 100*9908Srafael.vanoni@sun.com static int win_cols, win_rows; 101*9908Srafael.vanoni@sun.com static sb_slot_t *status_bar; 1029338Srafael.vanoni@sun.com 1039338Srafael.vanoni@sun.com static void 104*9908Srafael.vanoni@sun.com pt_display_cleanup(void) 105*9908Srafael.vanoni@sun.com { 106*9908Srafael.vanoni@sun.com (void) endwin(); 107*9908Srafael.vanoni@sun.com } 108*9908Srafael.vanoni@sun.com 109*9908Srafael.vanoni@sun.com static void 110*9908Srafael.vanoni@sun.com pt_display_get_size(void) 1119338Srafael.vanoni@sun.com { 112*9908Srafael.vanoni@sun.com getmaxyx(stdscr, win_rows, win_cols); 113*9908Srafael.vanoni@sun.com 114*9908Srafael.vanoni@sun.com if (win_rows < PT_MIN_ROWS || win_cols < PT_MIN_COLS) { 115*9908Srafael.vanoni@sun.com pt_display_cleanup(); 116*9908Srafael.vanoni@sun.com (void) printf("\n\nPowerTOP cannot run in such a small " 117*9908Srafael.vanoni@sun.com "terminal window. Please resize it.\n\n"); 118*9908Srafael.vanoni@sun.com exit(EXIT_FAILURE); 1199338Srafael.vanoni@sun.com } 1209338Srafael.vanoni@sun.com } 1219338Srafael.vanoni@sun.com 122*9908Srafael.vanoni@sun.com /* 123*9908Srafael.vanoni@sun.com * Signal handler, currently only used for window resizing. 124*9908Srafael.vanoni@sun.com */ 125*9908Srafael.vanoni@sun.com static void 126*9908Srafael.vanoni@sun.com pt_display_resize(int sig) 1279338Srafael.vanoni@sun.com { 128*9908Srafael.vanoni@sun.com int i; 129*9908Srafael.vanoni@sun.com 130*9908Srafael.vanoni@sun.com switch (sig) { 131*9908Srafael.vanoni@sun.com case SIGWINCH: 132*9908Srafael.vanoni@sun.com for (i = 0; i < SW_COUNT; i++) 133*9908Srafael.vanoni@sun.com if (sw[i] != NULL) { 134*9908Srafael.vanoni@sun.com (void) delwin(sw[i]); 135*9908Srafael.vanoni@sun.com sw[i] = NULL; 136*9908Srafael.vanoni@sun.com } 137*9908Srafael.vanoni@sun.com 138*9908Srafael.vanoni@sun.com pt_display_cleanup(); 139*9908Srafael.vanoni@sun.com (void) pt_display_init_curses(); 140*9908Srafael.vanoni@sun.com pt_display_setup(B_TRUE); 141*9908Srafael.vanoni@sun.com 142*9908Srafael.vanoni@sun.com pt_display_title_bar(); 143*9908Srafael.vanoni@sun.com 144*9908Srafael.vanoni@sun.com pt_display_update(); 145*9908Srafael.vanoni@sun.com 146*9908Srafael.vanoni@sun.com break; 147*9908Srafael.vanoni@sun.com } 1489338Srafael.vanoni@sun.com } 1499338Srafael.vanoni@sun.com 1509338Srafael.vanoni@sun.com /* 1519338Srafael.vanoni@sun.com * This part was re-written to be human readable and easy to modify. Please 1529338Srafael.vanoni@sun.com * try to keep it that way and help us save some time. 1539338Srafael.vanoni@sun.com * 1549338Srafael.vanoni@sun.com * Friendly reminder: 1559338Srafael.vanoni@sun.com * subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x) 1569338Srafael.vanoni@sun.com */ 1579338Srafael.vanoni@sun.com void 158*9908Srafael.vanoni@sun.com pt_display_setup(boolean_t resized) 1599338Srafael.vanoni@sun.com { 1609338Srafael.vanoni@sun.com /* 1619338Srafael.vanoni@sun.com * These variables are used to properly set the initial y position and 1629338Srafael.vanoni@sun.com * number of lines in each subwindow, as the number of supported CPU 1639338Srafael.vanoni@sun.com * states affects their placement. 1649338Srafael.vanoni@sun.com */ 165*9908Srafael.vanoni@sun.com int cstate_lines, event_lines, pos_y = 0; 1669338Srafael.vanoni@sun.com 167*9908Srafael.vanoni@sun.com /* 168*9908Srafael.vanoni@sun.com * In theory, all systems have at least two idle states. We add two here 169*9908Srafael.vanoni@sun.com * since we have to use DTrace to figure out how many this box has. 170*9908Srafael.vanoni@sun.com */ 171*9908Srafael.vanoni@sun.com cstate_lines = TITLE_LINE + max((g_max_cstate+2), g_npstates); 1729338Srafael.vanoni@sun.com 173*9908Srafael.vanoni@sun.com sw[SW_TITLE] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); 1749338Srafael.vanoni@sun.com 1759338Srafael.vanoni@sun.com pos_y += NEXT_LINE + BLANK_LINE; 176*9908Srafael.vanoni@sun.com sw[SW_IDLE] = subwin(stdscr, cstate_lines, win_cols/2 + 1, pos_y, 0); 177*9908Srafael.vanoni@sun.com sw[SW_FREQ] = subwin(stdscr, cstate_lines, win_cols/2 - 8, pos_y, 178*9908Srafael.vanoni@sun.com win_cols/2 + 8); 1799338Srafael.vanoni@sun.com 1809338Srafael.vanoni@sun.com pos_y += cstate_lines + BLANK_LINE; 181*9908Srafael.vanoni@sun.com sw[SW_WAKEUPS] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); 1829338Srafael.vanoni@sun.com 1839338Srafael.vanoni@sun.com pos_y += NEXT_LINE; 184*9908Srafael.vanoni@sun.com sw[SW_POWER] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); 1859338Srafael.vanoni@sun.com 1869338Srafael.vanoni@sun.com pos_y += NEXT_LINE + BLANK_LINE; 187*9908Srafael.vanoni@sun.com event_lines = win_rows - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW - 1889338Srafael.vanoni@sun.com pos_y; 189*9908Srafael.vanoni@sun.com 190*9908Srafael.vanoni@sun.com if (event_lines > 0) { 191*9908Srafael.vanoni@sun.com sw[SW_EVENTS] = subwin(stdscr, event_lines, win_cols, pos_y, 0); 192*9908Srafael.vanoni@sun.com } else { 193*9908Srafael.vanoni@sun.com (void) printf("\n\nPowerTOP cannot run in such a small " 194*9908Srafael.vanoni@sun.com "terminal window, please resize it.\n\n"); 195*9908Srafael.vanoni@sun.com exit(EXIT_FAILURE); 196*9908Srafael.vanoni@sun.com } 1979338Srafael.vanoni@sun.com 1989338Srafael.vanoni@sun.com pos_y += event_lines + NEXT_LINE; 199*9908Srafael.vanoni@sun.com sw[SW_SUGG] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); 2009338Srafael.vanoni@sun.com 2019338Srafael.vanoni@sun.com pos_y += BLANK_LINE + NEXT_LINE; 202*9908Srafael.vanoni@sun.com sw[SW_STATUS] = subwin(stdscr, SINGLE_LINE_SW, win_cols, pos_y, 0); 203*9908Srafael.vanoni@sun.com 204*9908Srafael.vanoni@sun.com if (!resized) { 205*9908Srafael.vanoni@sun.com status_bar = NULL; 2069338Srafael.vanoni@sun.com 207*9908Srafael.vanoni@sun.com pt_display_mod_status_bar(_("Q - Quit")); 208*9908Srafael.vanoni@sun.com pt_display_mod_status_bar(_("R - Refresh")); 209*9908Srafael.vanoni@sun.com } 2109338Srafael.vanoni@sun.com 211*9908Srafael.vanoni@sun.com pt_display_status_bar(); 2129338Srafael.vanoni@sun.com } 2139338Srafael.vanoni@sun.com 214*9908Srafael.vanoni@sun.com /* 215*9908Srafael.vanoni@sun.com * This routine handles all the necessary curses initialization. 216*9908Srafael.vanoni@sun.com */ 2179338Srafael.vanoni@sun.com void 218*9908Srafael.vanoni@sun.com pt_display_init_curses(void) 2199338Srafael.vanoni@sun.com { 2209338Srafael.vanoni@sun.com (void) initscr(); 221*9908Srafael.vanoni@sun.com 222*9908Srafael.vanoni@sun.com (void) atexit(pt_display_cleanup); 223*9908Srafael.vanoni@sun.com (void) signal(SIGWINCH, pt_display_resize); 224*9908Srafael.vanoni@sun.com 225*9908Srafael.vanoni@sun.com pt_display_get_size(); 226*9908Srafael.vanoni@sun.com 2279338Srafael.vanoni@sun.com (void) start_color(); 2289338Srafael.vanoni@sun.com 2299338Srafael.vanoni@sun.com /* 2309338Srafael.vanoni@sun.com * Enable keyboard mapping 2319338Srafael.vanoni@sun.com */ 2329338Srafael.vanoni@sun.com (void) keypad(stdscr, TRUE); 2339338Srafael.vanoni@sun.com 2349338Srafael.vanoni@sun.com /* 2359338Srafael.vanoni@sun.com * Tell curses not to do NL->CR/NL on output 2369338Srafael.vanoni@sun.com */ 2379338Srafael.vanoni@sun.com (void) nonl(); 2389338Srafael.vanoni@sun.com 2399338Srafael.vanoni@sun.com /* 2409338Srafael.vanoni@sun.com * Take input chars one at a time, no wait for \n 2419338Srafael.vanoni@sun.com */ 2429338Srafael.vanoni@sun.com (void) cbreak(); 2439338Srafael.vanoni@sun.com 2449338Srafael.vanoni@sun.com /* 2459338Srafael.vanoni@sun.com * Dont echo input 2469338Srafael.vanoni@sun.com */ 2479338Srafael.vanoni@sun.com (void) noecho(); 2489338Srafael.vanoni@sun.com 2499338Srafael.vanoni@sun.com /* 2509338Srafael.vanoni@sun.com * Turn off cursor 2519338Srafael.vanoni@sun.com */ 2529338Srafael.vanoni@sun.com (void) curs_set(0); 2539338Srafael.vanoni@sun.com 2549338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK); 2559338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE); 2569338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED); 2579338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED); 2589338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW); 2599338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN); 2609338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE); 2619338Srafael.vanoni@sun.com (void) init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK); 262*9908Srafael.vanoni@sun.com } 2639338Srafael.vanoni@sun.com 264*9908Srafael.vanoni@sun.com void 265*9908Srafael.vanoni@sun.com pt_display_update(void) 266*9908Srafael.vanoni@sun.com { 267*9908Srafael.vanoni@sun.com (void) doupdate(); 268*9908Srafael.vanoni@sun.com } 269*9908Srafael.vanoni@sun.com 270*9908Srafael.vanoni@sun.com void 271*9908Srafael.vanoni@sun.com pt_display_title_bar(void) 272*9908Srafael.vanoni@sun.com { 273*9908Srafael.vanoni@sun.com char title_pad[10]; 274*9908Srafael.vanoni@sun.com 275*9908Srafael.vanoni@sun.com (void) wattrset(sw[SW_TITLE], COLOR_PAIR(PT_COLOR_HEADER_BAR)); 276*9908Srafael.vanoni@sun.com (void) wbkgd(sw[SW_TITLE], COLOR_PAIR(PT_COLOR_HEADER_BAR)); 277*9908Srafael.vanoni@sun.com (void) werase(sw[SW_TITLE]); 278*9908Srafael.vanoni@sun.com 279*9908Srafael.vanoni@sun.com (void) snprintf(title_pad, 10, "%%%ds", 280*9908Srafael.vanoni@sun.com (win_cols - strlen(TITLE))/2 + strlen(TITLE)); 281*9908Srafael.vanoni@sun.com 282*9908Srafael.vanoni@sun.com /* LINTED: E_SEC_PRINTF_VAR_FMT */ 283*9908Srafael.vanoni@sun.com print(sw[SW_TITLE], 0, 0, title_pad, TITLE); 284*9908Srafael.vanoni@sun.com 285*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_TITLE]); 2869338Srafael.vanoni@sun.com } 2879338Srafael.vanoni@sun.com 2889338Srafael.vanoni@sun.com void 289*9908Srafael.vanoni@sun.com pt_display_status_bar(void) 2909338Srafael.vanoni@sun.com { 291*9908Srafael.vanoni@sun.com sb_slot_t *n = status_bar; 292*9908Srafael.vanoni@sun.com int x = 0; 293*9908Srafael.vanoni@sun.com 294*9908Srafael.vanoni@sun.com (void) werase(sw[SW_STATUS]); 295*9908Srafael.vanoni@sun.com 296*9908Srafael.vanoni@sun.com while (n && x < win_cols) { 297*9908Srafael.vanoni@sun.com (void) wattron(sw[SW_STATUS], A_REVERSE); 298*9908Srafael.vanoni@sun.com print(sw[SW_STATUS], 0, x, "%s", n->msg); 299*9908Srafael.vanoni@sun.com (void) wattroff(sw[SW_STATUS], A_REVERSE); 300*9908Srafael.vanoni@sun.com x += strlen(n->msg) + 1; 301*9908Srafael.vanoni@sun.com 302*9908Srafael.vanoni@sun.com n = n->next; 303*9908Srafael.vanoni@sun.com } 304*9908Srafael.vanoni@sun.com 305*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_STATUS]); 306*9908Srafael.vanoni@sun.com } 3079338Srafael.vanoni@sun.com 308*9908Srafael.vanoni@sun.com /* 309*9908Srafael.vanoni@sun.com * Adds or removes items to the status bar automatically. 310*9908Srafael.vanoni@sun.com * Only one instance of an item allowed. 311*9908Srafael.vanoni@sun.com */ 312*9908Srafael.vanoni@sun.com void 313*9908Srafael.vanoni@sun.com pt_display_mod_status_bar(char *msg) 314*9908Srafael.vanoni@sun.com { 315*9908Srafael.vanoni@sun.com sb_slot_t *new, *n; 316*9908Srafael.vanoni@sun.com boolean_t found = B_FALSE, first = B_FALSE; 317*9908Srafael.vanoni@sun.com 318*9908Srafael.vanoni@sun.com if (msg == NULL) { 319*9908Srafael.vanoni@sun.com pt_error("%s : can't add an empty status bar item.", __FILE__); 320*9908Srafael.vanoni@sun.com return; 321*9908Srafael.vanoni@sun.com } 322*9908Srafael.vanoni@sun.com 323*9908Srafael.vanoni@sun.com if (status_bar != NULL) { 324*9908Srafael.vanoni@sun.com /* 325*9908Srafael.vanoni@sun.com * Non-empty status bar. Look for an entry matching this msg. 326*9908Srafael.vanoni@sun.com */ 327*9908Srafael.vanoni@sun.com for (n = status_bar; n != NULL; n = n->next) { 328*9908Srafael.vanoni@sun.com 329*9908Srafael.vanoni@sun.com if (strcmp(msg, n->msg) == 0) { 330*9908Srafael.vanoni@sun.com if (n != status_bar) 331*9908Srafael.vanoni@sun.com n->prev->next = n->next; 332*9908Srafael.vanoni@sun.com else 333*9908Srafael.vanoni@sun.com first = B_TRUE; 3349338Srafael.vanoni@sun.com 335*9908Srafael.vanoni@sun.com if (n->next != NULL) { 336*9908Srafael.vanoni@sun.com n->next->prev = n->prev; 337*9908Srafael.vanoni@sun.com if (first) 338*9908Srafael.vanoni@sun.com status_bar = n->next; 339*9908Srafael.vanoni@sun.com } else { 340*9908Srafael.vanoni@sun.com if (first) 341*9908Srafael.vanoni@sun.com status_bar = NULL; 342*9908Srafael.vanoni@sun.com } 3439338Srafael.vanoni@sun.com 344*9908Srafael.vanoni@sun.com free(n); 345*9908Srafael.vanoni@sun.com found = B_TRUE; 346*9908Srafael.vanoni@sun.com } 347*9908Srafael.vanoni@sun.com } 3489338Srafael.vanoni@sun.com 349*9908Srafael.vanoni@sun.com /* 350*9908Srafael.vanoni@sun.com * Found and removed at least one occurrance of msg, refresh 351*9908Srafael.vanoni@sun.com * the bar and return. 352*9908Srafael.vanoni@sun.com */ 353*9908Srafael.vanoni@sun.com if (found) { 354*9908Srafael.vanoni@sun.com return; 355*9908Srafael.vanoni@sun.com } else { 356*9908Srafael.vanoni@sun.com /* 357*9908Srafael.vanoni@sun.com * Inserting a new msg, walk to the end of the bar. 358*9908Srafael.vanoni@sun.com */ 359*9908Srafael.vanoni@sun.com for (n = status_bar; n->next != NULL; n = n->next) 360*9908Srafael.vanoni@sun.com ; 361*9908Srafael.vanoni@sun.com } 3629338Srafael.vanoni@sun.com } 363*9908Srafael.vanoni@sun.com 364*9908Srafael.vanoni@sun.com if ((new = calloc(1, sizeof (sb_slot_t))) == NULL) { 365*9908Srafael.vanoni@sun.com pt_error("%s : failed to allocate a new slot\n", __FILE__); 366*9908Srafael.vanoni@sun.com } else { 367*9908Srafael.vanoni@sun.com new->msg = strdup(msg); 368*9908Srafael.vanoni@sun.com 369*9908Srafael.vanoni@sun.com /* 370*9908Srafael.vanoni@sun.com * Check if it's the first entry. 371*9908Srafael.vanoni@sun.com */ 372*9908Srafael.vanoni@sun.com if (status_bar == NULL) { 373*9908Srafael.vanoni@sun.com status_bar = new; 374*9908Srafael.vanoni@sun.com new->prev = NULL; 375*9908Srafael.vanoni@sun.com } else { 376*9908Srafael.vanoni@sun.com new->prev = n; 377*9908Srafael.vanoni@sun.com n->next = new; 378*9908Srafael.vanoni@sun.com } 379*9908Srafael.vanoni@sun.com new->next = NULL; 380*9908Srafael.vanoni@sun.com } 3819338Srafael.vanoni@sun.com } 3829338Srafael.vanoni@sun.com 3839338Srafael.vanoni@sun.com void 384*9908Srafael.vanoni@sun.com pt_display_states(void) 3859338Srafael.vanoni@sun.com { 3869338Srafael.vanoni@sun.com char c[100]; 3879338Srafael.vanoni@sun.com int i; 3889338Srafael.vanoni@sun.com double total_pstates = 0.0, avg, res; 3899338Srafael.vanoni@sun.com uint64_t p0_speed, p1_speed; 3909338Srafael.vanoni@sun.com 391*9908Srafael.vanoni@sun.com print(sw[SW_IDLE], 0, 0, "%s\tAvg\tResidency\n", g_msg_idle_state); 392*9908Srafael.vanoni@sun.com 393*9908Srafael.vanoni@sun.com if (g_features & FEATURE_CSTATE) { 394*9908Srafael.vanoni@sun.com res = (((double)g_cstate_info[0].total_time / g_total_c_time)) 395*9908Srafael.vanoni@sun.com * 100; 396*9908Srafael.vanoni@sun.com (void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res); 397*9908Srafael.vanoni@sun.com print(sw[SW_IDLE], 1, 0, "%s", c); 398*9908Srafael.vanoni@sun.com 399*9908Srafael.vanoni@sun.com for (i = 1; i <= g_max_cstate; i++) { 400*9908Srafael.vanoni@sun.com /* 401*9908Srafael.vanoni@sun.com * In situations where the load is too intensive, the 402*9908Srafael.vanoni@sun.com * system might not transition at all. 403*9908Srafael.vanoni@sun.com */ 404*9908Srafael.vanoni@sun.com if (g_cstate_info[i].events > 0) 405*9908Srafael.vanoni@sun.com avg = (((double)g_cstate_info[i].total_time/ 406*9908Srafael.vanoni@sun.com MICROSEC)/g_cstate_info[i].events); 407*9908Srafael.vanoni@sun.com else 408*9908Srafael.vanoni@sun.com avg = 0; 409*9908Srafael.vanoni@sun.com 410*9908Srafael.vanoni@sun.com res = ((double)g_cstate_info[i].total_time/ 411*9908Srafael.vanoni@sun.com g_total_c_time) * 100; 412*9908Srafael.vanoni@sun.com 413*9908Srafael.vanoni@sun.com (void) sprintf(c, "C%d\t\t\t%.1fms\t(%.1f%%)\n", 414*9908Srafael.vanoni@sun.com i, (float)avg, (float)res); 415*9908Srafael.vanoni@sun.com print(sw[SW_IDLE], i + 1, 0, "%s", c); 416*9908Srafael.vanoni@sun.com } 4179338Srafael.vanoni@sun.com } 4189338Srafael.vanoni@sun.com 419*9908Srafael.vanoni@sun.com if (!PT_ON_DUMP) 420*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_IDLE]); 4219338Srafael.vanoni@sun.com 422*9908Srafael.vanoni@sun.com print(sw[SW_FREQ], 0, 0, "%s\n", g_msg_freq_state); 4239338Srafael.vanoni@sun.com 424*9908Srafael.vanoni@sun.com if (g_features & FEATURE_PSTATE) { 4259338Srafael.vanoni@sun.com for (i = 0; i < g_npstates; i++) { 426*9908Srafael.vanoni@sun.com total_pstates += 427*9908Srafael.vanoni@sun.com (double)(g_pstate_info[i].total_time/ 4289711Srafael.vanoni@sun.com g_ncpus_observed/MICROSEC); 4299338Srafael.vanoni@sun.com } 4309338Srafael.vanoni@sun.com 4319338Srafael.vanoni@sun.com /* 4329338Srafael.vanoni@sun.com * display ACPI_PSTATE from P(n) to P(1) 4339338Srafael.vanoni@sun.com */ 4349338Srafael.vanoni@sun.com for (i = 0; i < g_npstates - 1; i++) { 4359338Srafael.vanoni@sun.com (void) sprintf(c, "%4lu Mhz\t%.1f%%", 4369338Srafael.vanoni@sun.com (long)g_pstate_info[i].speed, 437*9908Srafael.vanoni@sun.com 100 * (g_pstate_info[i].total_time/ 438*9908Srafael.vanoni@sun.com g_ncpus_observed/MICROSEC/total_pstates)); 439*9908Srafael.vanoni@sun.com print(sw[SW_FREQ], i+1, 0, "%s\n", c); 4409338Srafael.vanoni@sun.com } 4419338Srafael.vanoni@sun.com 4429338Srafael.vanoni@sun.com /* 4439338Srafael.vanoni@sun.com * Display ACPI_PSTATE P0 according to if turbo 4449338Srafael.vanoni@sun.com * mode is supported 4459338Srafael.vanoni@sun.com */ 4469338Srafael.vanoni@sun.com if (g_turbo_supported) { 4479338Srafael.vanoni@sun.com p1_speed = g_pstate_info[g_npstates - 2].speed; 4489338Srafael.vanoni@sun.com 4499338Srafael.vanoni@sun.com /* 4509338Srafael.vanoni@sun.com * If g_turbo_ratio <= 1.0, it will be ignored. 4519338Srafael.vanoni@sun.com * we display P(0) as P(1) + 1. 4529338Srafael.vanoni@sun.com */ 4539338Srafael.vanoni@sun.com if (g_turbo_ratio <= 1.0) { 4549338Srafael.vanoni@sun.com p0_speed = p1_speed + 1; 4559338Srafael.vanoni@sun.com } else { 4569338Srafael.vanoni@sun.com /* 457*9908Srafael.vanoni@sun.com * If g_turbo_ratio > 1.0, that means 458*9908Srafael.vanoni@sun.com * turbo mode works. So, P(0) = ratio * 459*9908Srafael.vanoni@sun.com * P(1); 4609338Srafael.vanoni@sun.com */ 461*9908Srafael.vanoni@sun.com p0_speed = (uint64_t)(p1_speed * 462*9908Srafael.vanoni@sun.com g_turbo_ratio); 4639338Srafael.vanoni@sun.com if (p0_speed < (p1_speed + 1)) 464*9908Srafael.vanoni@sun.com p0_speed = p1_speed + 1; 4659338Srafael.vanoni@sun.com } 4669338Srafael.vanoni@sun.com /* 4679338Srafael.vanoni@sun.com * Reset the ratio for the next round 4689338Srafael.vanoni@sun.com */ 4699338Srafael.vanoni@sun.com g_turbo_ratio = 0.0; 4709338Srafael.vanoni@sun.com 4719338Srafael.vanoni@sun.com /* 4729338Srafael.vanoni@sun.com * Setup the string for the display 4739338Srafael.vanoni@sun.com */ 4749338Srafael.vanoni@sun.com (void) sprintf(c, "%4lu Mhz(turbo)\t%.1f%%", 4759338Srafael.vanoni@sun.com (long)p0_speed, 4769338Srafael.vanoni@sun.com 100 * (g_pstate_info[i].total_time/ 4779711Srafael.vanoni@sun.com g_ncpus_observed/MICROSEC/total_pstates)); 4789338Srafael.vanoni@sun.com } else { 4799338Srafael.vanoni@sun.com (void) sprintf(c, "%4lu Mhz\t%.1f%%", 4809338Srafael.vanoni@sun.com (long)g_pstate_info[i].speed, 4819338Srafael.vanoni@sun.com 100 * (g_pstate_info[i].total_time/ 4829711Srafael.vanoni@sun.com g_ncpus_observed/MICROSEC/total_pstates)); 4839338Srafael.vanoni@sun.com } 484*9908Srafael.vanoni@sun.com print(sw[SW_FREQ], i+1, 0, "%s\n", c); 485*9908Srafael.vanoni@sun.com } else { 486*9908Srafael.vanoni@sun.com if (g_npstates == 1) { 487*9908Srafael.vanoni@sun.com (void) sprintf(c, "%4lu Mhz\t%.1f%%", 488*9908Srafael.vanoni@sun.com (long)g_pstate_info[0].speed, 100.0); 489*9908Srafael.vanoni@sun.com print(sw[SW_FREQ], 1, 0, "%s\n", c); 490*9908Srafael.vanoni@sun.com } 4919338Srafael.vanoni@sun.com } 4929338Srafael.vanoni@sun.com 4939711Srafael.vanoni@sun.com if (!PT_ON_DUMP) 494*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_FREQ]); 4959338Srafael.vanoni@sun.com } 4969338Srafael.vanoni@sun.com 4979338Srafael.vanoni@sun.com void 498*9908Srafael.vanoni@sun.com pt_display_acpi_power(uint32_t flag, double rate, double rem_cap, double cap, 4999338Srafael.vanoni@sun.com uint32_t state) 5009338Srafael.vanoni@sun.com { 5019338Srafael.vanoni@sun.com char buffer[1024]; 5029338Srafael.vanoni@sun.com 5039338Srafael.vanoni@sun.com (void) sprintf(buffer, _("no ACPI power usage estimate available")); 5049338Srafael.vanoni@sun.com 5059711Srafael.vanoni@sun.com if (!PT_ON_DUMP) 506*9908Srafael.vanoni@sun.com (void) werase(sw[SW_POWER]); 507*9908Srafael.vanoni@sun.com 5089338Srafael.vanoni@sun.com if (flag) { 5099338Srafael.vanoni@sun.com char *c; 5109338Srafael.vanoni@sun.com (void) sprintf(buffer, "Power usage (ACPI estimate): %.3fW", 5119338Srafael.vanoni@sun.com rate); 5129338Srafael.vanoni@sun.com (void) strcat(buffer, " "); 5139338Srafael.vanoni@sun.com c = &buffer[strlen(buffer)]; 5149338Srafael.vanoni@sun.com switch (state) { 5159338Srafael.vanoni@sun.com case 0: 5169338Srafael.vanoni@sun.com (void) sprintf(c, "(running on AC power, fully " 5179338Srafael.vanoni@sun.com "charged)"); 5189338Srafael.vanoni@sun.com break; 5199338Srafael.vanoni@sun.com case 1: 5209338Srafael.vanoni@sun.com (void) sprintf(c, "(discharging: %3.1f hours)", 5219338Srafael.vanoni@sun.com (uint32_t)rem_cap/rate); 5229338Srafael.vanoni@sun.com break; 5239338Srafael.vanoni@sun.com case 2: 5249338Srafael.vanoni@sun.com (void) sprintf(c, "(charging: %3.1f hours)", 5259338Srafael.vanoni@sun.com (uint32_t)(cap - rem_cap)/rate); 5269338Srafael.vanoni@sun.com break; 5279338Srafael.vanoni@sun.com case 4: 5289338Srafael.vanoni@sun.com (void) sprintf(c, "(##critically low battery power##)"); 5299338Srafael.vanoni@sun.com break; 5309338Srafael.vanoni@sun.com } 5319338Srafael.vanoni@sun.com 5329338Srafael.vanoni@sun.com } 533*9908Srafael.vanoni@sun.com 534*9908Srafael.vanoni@sun.com print(sw[SW_POWER], 0, 0, "%s\n", buffer); 5359711Srafael.vanoni@sun.com if (!PT_ON_DUMP) 536*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_POWER]); 5379338Srafael.vanoni@sun.com } 5389338Srafael.vanoni@sun.com 5399338Srafael.vanoni@sun.com void 540*9908Srafael.vanoni@sun.com pt_display_wakeups(double interval) 5419338Srafael.vanoni@sun.com { 5429338Srafael.vanoni@sun.com char c[100]; 5439338Srafael.vanoni@sun.com int i, event_sum = 0; 5449711Srafael.vanoni@sun.com event_info_t *event = g_event_info; 5459338Srafael.vanoni@sun.com 5469711Srafael.vanoni@sun.com if (!PT_ON_DUMP) { 547*9908Srafael.vanoni@sun.com (void) werase(sw[SW_WAKEUPS]); 548*9908Srafael.vanoni@sun.com (void) wbkgd(sw[SW_WAKEUPS], COLOR_PAIR(PT_COLOR_RED)); 549*9908Srafael.vanoni@sun.com (void) wattron(sw[SW_WAKEUPS], A_BOLD); 5509338Srafael.vanoni@sun.com } 5519338Srafael.vanoni@sun.com 5529338Srafael.vanoni@sun.com /* 5539338Srafael.vanoni@sun.com * calculate the actual total event number 5549338Srafael.vanoni@sun.com */ 5559711Srafael.vanoni@sun.com for (i = 0; i < g_top_events; i++, event++) 5569711Srafael.vanoni@sun.com event_sum += event->total_count; 5579338Srafael.vanoni@sun.com 5589338Srafael.vanoni@sun.com /* 5599338Srafael.vanoni@sun.com * g_total_events is the sum of the number of Cx->C0 transition, 5609338Srafael.vanoni@sun.com * So when the system is very busy, the idle thread will have no 5619338Srafael.vanoni@sun.com * chance or very seldom to be scheduled, this could cause >100% 5629338Srafael.vanoni@sun.com * event report. Re-assign g_total_events to the actual event 5639338Srafael.vanoni@sun.com * number is a way to avoid this issue. 5649338Srafael.vanoni@sun.com */ 5659338Srafael.vanoni@sun.com if (event_sum > g_total_events) 5669338Srafael.vanoni@sun.com g_total_events = event_sum; 5679338Srafael.vanoni@sun.com 5689338Srafael.vanoni@sun.com (void) sprintf(c, "Wakeups-from-idle per second: %4.1f\tinterval: " 5699338Srafael.vanoni@sun.com "%.1fs", (double)(g_total_events/interval), interval); 570*9908Srafael.vanoni@sun.com print(sw[SW_WAKEUPS], 0, 0, "%s\n", c); 5719338Srafael.vanoni@sun.com 5729711Srafael.vanoni@sun.com if (!PT_ON_DUMP) 573*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_WAKEUPS]); 5749338Srafael.vanoni@sun.com } 5759338Srafael.vanoni@sun.com 5769338Srafael.vanoni@sun.com void 577*9908Srafael.vanoni@sun.com pt_display_events(double interval) 5789338Srafael.vanoni@sun.com { 5799338Srafael.vanoni@sun.com char c[100]; 5809338Srafael.vanoni@sun.com int i; 5819338Srafael.vanoni@sun.com double events; 5829711Srafael.vanoni@sun.com event_info_t *event = g_event_info; 5839338Srafael.vanoni@sun.com 5849711Srafael.vanoni@sun.com if (!PT_ON_DUMP) { 585*9908Srafael.vanoni@sun.com (void) werase(sw[SW_EVENTS]); 586*9908Srafael.vanoni@sun.com (void) wbkgd(sw[SW_EVENTS], COLOR_PAIR(PT_COLOR_DEFAULT)); 587*9908Srafael.vanoni@sun.com (void) wattron(sw[SW_EVENTS], COLOR_PAIR(PT_COLOR_DEFAULT)); 5889338Srafael.vanoni@sun.com } 5899338Srafael.vanoni@sun.com 5909338Srafael.vanoni@sun.com /* 5919338Srafael.vanoni@sun.com * Sort the event report list 5929338Srafael.vanoni@sun.com */ 5939711Srafael.vanoni@sun.com if (g_top_events > EVENT_NUM_MAX) 5949711Srafael.vanoni@sun.com g_top_events = EVENT_NUM_MAX; 5959338Srafael.vanoni@sun.com 5969711Srafael.vanoni@sun.com qsort((void *)g_event_info, g_top_events, sizeof (event_info_t), 5979338Srafael.vanoni@sun.com event_compare); 5989338Srafael.vanoni@sun.com 5999711Srafael.vanoni@sun.com if (PT_ON_CPU) 6009338Srafael.vanoni@sun.com (void) sprintf(c, "Top causes for wakeups on CPU %d:\n", 6019338Srafael.vanoni@sun.com g_observed_cpu); 6029338Srafael.vanoni@sun.com else 6039338Srafael.vanoni@sun.com (void) sprintf(c, "Top causes for wakeups:\n"); 6049338Srafael.vanoni@sun.com 605*9908Srafael.vanoni@sun.com print(sw[SW_EVENTS], 0, 0, "%s", c); 6069338Srafael.vanoni@sun.com 6079711Srafael.vanoni@sun.com for (i = 0; i < g_top_events; i++, event++) { 6089338Srafael.vanoni@sun.com 6099711Srafael.vanoni@sun.com if (g_total_events > 0 && event->total_count > 0) 6109711Srafael.vanoni@sun.com events = (double)event->total_count/ 6119338Srafael.vanoni@sun.com (double)g_total_events; 6129338Srafael.vanoni@sun.com else 6139338Srafael.vanoni@sun.com continue; 6149338Srafael.vanoni@sun.com 6159338Srafael.vanoni@sun.com (void) sprintf(c, "%4.1f%% (%5.1f)", 100 * events, 6169711Srafael.vanoni@sun.com (double)event->total_count/interval); 617*9908Srafael.vanoni@sun.com print(sw[SW_EVENTS], i+1, 0, "%s", c); 618*9908Srafael.vanoni@sun.com print(sw[SW_EVENTS], i+1, 16, "%20s :", 6199711Srafael.vanoni@sun.com event->offender_name); 620*9908Srafael.vanoni@sun.com print(sw[SW_EVENTS], i+1, 40, "%-64s\n", 6219711Srafael.vanoni@sun.com event->offense_name); 6229338Srafael.vanoni@sun.com } 6239338Srafael.vanoni@sun.com 6249711Srafael.vanoni@sun.com if (!PT_ON_DUMP) 625*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_EVENTS]); 6269338Srafael.vanoni@sun.com } 6279338Srafael.vanoni@sun.com 6289338Srafael.vanoni@sun.com void 629*9908Srafael.vanoni@sun.com pt_display_suggestions(char *sug) 6309338Srafael.vanoni@sun.com { 631*9908Srafael.vanoni@sun.com (void) werase(sw[SW_SUGG]); 632*9908Srafael.vanoni@sun.com 633*9908Srafael.vanoni@sun.com if (sug != NULL) 634*9908Srafael.vanoni@sun.com print(sw[SW_SUGG], 0, 0, "%s", sug); 635*9908Srafael.vanoni@sun.com 636*9908Srafael.vanoni@sun.com (void) wnoutrefresh(sw[SW_SUGG]); 637*9908Srafael.vanoni@sun.com 638*9908Srafael.vanoni@sun.com pt_display_update(); 6399338Srafael.vanoni@sun.com } 640