xref: /titanic_51/usr/src/cmd/powertop/common/suggestions.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 <unistd.h>
41b47b5b34SRafael Vanoni #include <stdio.h>
42b47b5b34SRafael Vanoni #include <stdlib.h>
43b47b5b34SRafael Vanoni #include <string.h>
44b47b5b34SRafael Vanoni #include "powertop.h"
45b47b5b34SRafael Vanoni 
469bbf5ba1SRafael Vanoni /*
479bbf5ba1SRafael Vanoni  * Default number of intervals we display a suggestion before moving
489bbf5ba1SRafael Vanoni  * to the next.
499bbf5ba1SRafael Vanoni  */
509bbf5ba1SRafael Vanoni #define	PT_SUGG_DEF_SLICE	3
51b47b5b34SRafael Vanoni 
529bbf5ba1SRafael Vanoni /*
539bbf5ba1SRafael Vanoni  * Global pointer to the current suggestion.
549bbf5ba1SRafael Vanoni  */
559bbf5ba1SRafael Vanoni sugg_t	*g_curr_sugg;
56b47b5b34SRafael Vanoni 
579bbf5ba1SRafael Vanoni /*
589bbf5ba1SRafael Vanoni  * Head of the list of suggestions.
599bbf5ba1SRafael Vanoni  */
609bbf5ba1SRafael Vanoni static sugg_t *sugg;
61b47b5b34SRafael Vanoni 
629bbf5ba1SRafael Vanoni /*
639bbf5ba1SRafael Vanoni  * Add a new suggestion. Only one suggestion per text allowed.
649bbf5ba1SRafael Vanoni  */
65b47b5b34SRafael Vanoni void
669bbf5ba1SRafael Vanoni pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func)
67b47b5b34SRafael Vanoni {
689bbf5ba1SRafael Vanoni 	sugg_t *new, *n, *pos = NULL;
69b47b5b34SRafael Vanoni 
709bbf5ba1SRafael Vanoni 	/*
719bbf5ba1SRafael Vanoni 	 * Text is a required field for suggestions
729bbf5ba1SRafael Vanoni 	 */
739bbf5ba1SRafael Vanoni 	if (text == NULL)
74b47b5b34SRafael Vanoni 		return;
75b47b5b34SRafael Vanoni 
769bbf5ba1SRafael Vanoni 	if (sugg == NULL) {
779bbf5ba1SRafael Vanoni 		/*
789bbf5ba1SRafael Vanoni 		 * Creating first element
799bbf5ba1SRafael Vanoni 		 */
809bbf5ba1SRafael Vanoni 		if ((new = calloc(1, sizeof (sugg_t))) == NULL)
81b47b5b34SRafael Vanoni 			return;
82b47b5b34SRafael Vanoni 
839bbf5ba1SRafael Vanoni 		if (sb_msg != NULL)
849bbf5ba1SRafael Vanoni 			new->sb_msg = strdup(sb_msg);
85b47b5b34SRafael Vanoni 
869bbf5ba1SRafael Vanoni 		if (text != NULL)
879bbf5ba1SRafael Vanoni 			new->text = strdup(text);
889bbf5ba1SRafael Vanoni 
89b47b5b34SRafael Vanoni 		new->weight = weight;
90b47b5b34SRafael Vanoni 		new->key = key;
91b47b5b34SRafael Vanoni 		new->func = func;
929bbf5ba1SRafael Vanoni 		new->slice = 0;
939bbf5ba1SRafael Vanoni 
949bbf5ba1SRafael Vanoni 		sugg = new;
959bbf5ba1SRafael Vanoni 		new->prev = NULL;
969bbf5ba1SRafael Vanoni 		new->next = NULL;
979bbf5ba1SRafael Vanoni 	} else {
989bbf5ba1SRafael Vanoni 		for (n = sugg; n != NULL; n = n->next) {
999bbf5ba1SRafael Vanoni 			if (strcmp(n->text, text) == 0)
1009bbf5ba1SRafael Vanoni 				return;
1019bbf5ba1SRafael Vanoni 
1029bbf5ba1SRafael Vanoni 			if (weight > n->weight && pos == NULL)
1039bbf5ba1SRafael Vanoni 				pos = n;
1049bbf5ba1SRafael Vanoni 		}
1059bbf5ba1SRafael Vanoni 		/*
1069bbf5ba1SRafael Vanoni 		 * Create a new element
1079bbf5ba1SRafael Vanoni 		 */
1089bbf5ba1SRafael Vanoni 		if ((new = calloc(1, sizeof (sugg_t))) == NULL)
1099bbf5ba1SRafael Vanoni 			return;
1109bbf5ba1SRafael Vanoni 
1119bbf5ba1SRafael Vanoni 		if (sb_msg != NULL)
1129bbf5ba1SRafael Vanoni 			new->sb_msg = strdup(sb_msg);
1139bbf5ba1SRafael Vanoni 
1149bbf5ba1SRafael Vanoni 		new->text = strdup(text);
1159bbf5ba1SRafael Vanoni 
1169bbf5ba1SRafael Vanoni 		new->weight = weight;
1179bbf5ba1SRafael Vanoni 		new->key = key;
1189bbf5ba1SRafael Vanoni 		new->func = func;
1199bbf5ba1SRafael Vanoni 		new->slice = 0;
1209bbf5ba1SRafael Vanoni 
1219bbf5ba1SRafael Vanoni 		if (pos == NULL) {
1229bbf5ba1SRafael Vanoni 			/*
1239bbf5ba1SRafael Vanoni 			 * Ordering placed the new element at the end
1249bbf5ba1SRafael Vanoni 			 */
1259bbf5ba1SRafael Vanoni 			for (n = sugg; n->next != NULL; n = n->next)
1269bbf5ba1SRafael Vanoni 				;
1279bbf5ba1SRafael Vanoni 
1289bbf5ba1SRafael Vanoni 			n->next = new;
1299bbf5ba1SRafael Vanoni 			new->prev = n;
1309bbf5ba1SRafael Vanoni 			new->next = NULL;
1319bbf5ba1SRafael Vanoni 		} else {
1329bbf5ba1SRafael Vanoni 			if (pos == sugg) {
1339bbf5ba1SRafael Vanoni 				/*
1349bbf5ba1SRafael Vanoni 				 * Ordering placed the new element at the start
1359bbf5ba1SRafael Vanoni 				 */
1369bbf5ba1SRafael Vanoni 				new->next = sugg;
1379bbf5ba1SRafael Vanoni 				new->prev = sugg;
1389bbf5ba1SRafael Vanoni 				sugg->prev = new;
1399bbf5ba1SRafael Vanoni 				sugg = new;
1409bbf5ba1SRafael Vanoni 			} else {
1419bbf5ba1SRafael Vanoni 				/*
1429bbf5ba1SRafael Vanoni 				 * Ordering placed the new element somewhere in
1439bbf5ba1SRafael Vanoni 				 * the middle
1449bbf5ba1SRafael Vanoni 				 */
1459bbf5ba1SRafael Vanoni 				new->next = pos;
1469bbf5ba1SRafael Vanoni 				new->prev = pos->prev;
1479bbf5ba1SRafael Vanoni 				pos->prev->next = new;
1489bbf5ba1SRafael Vanoni 				pos->prev = new;
1499bbf5ba1SRafael Vanoni 			}
1509bbf5ba1SRafael Vanoni 		}
1519bbf5ba1SRafael Vanoni 	}
152b47b5b34SRafael Vanoni }
153b47b5b34SRafael Vanoni 
1549bbf5ba1SRafael Vanoni /*
1559bbf5ba1SRafael Vanoni  * Removes a suggestion, returning 0 if not found and 1 if so.
1569bbf5ba1SRafael Vanoni  */
1579bbf5ba1SRafael Vanoni int
1589bbf5ba1SRafael Vanoni pt_sugg_remove(sugg_func_t *func)
159b47b5b34SRafael Vanoni {
1609bbf5ba1SRafael Vanoni 	sugg_t *n;
1619bbf5ba1SRafael Vanoni 	int ret = 0;
162b47b5b34SRafael Vanoni 
1639bbf5ba1SRafael Vanoni 	for (n = sugg; n != NULL; n = n->next) {
1649bbf5ba1SRafael Vanoni 		if (n->func == func) {
1659bbf5ba1SRafael Vanoni 			/* Removing the first element */
1669bbf5ba1SRafael Vanoni 			if (n == sugg) {
1679bbf5ba1SRafael Vanoni 				if (sugg->next == NULL) {
1689bbf5ba1SRafael Vanoni 					/* Removing the only element */
1699bbf5ba1SRafael Vanoni 					sugg = NULL;
1709bbf5ba1SRafael Vanoni 				} else {
1719bbf5ba1SRafael Vanoni 					sugg = n->next;
1729bbf5ba1SRafael Vanoni 					sugg->prev = NULL;
1739bbf5ba1SRafael Vanoni 				}
1749bbf5ba1SRafael Vanoni 			} else {
1759bbf5ba1SRafael Vanoni 				if (n->next == NULL) {
1769bbf5ba1SRafael Vanoni 					/* Removing the last element */
1779bbf5ba1SRafael Vanoni 					n->prev->next = NULL;
1789bbf5ba1SRafael Vanoni 				} else {
1799bbf5ba1SRafael Vanoni 					/* Removing an intermediate element */
1809bbf5ba1SRafael Vanoni 					n->prev->next = n->next;
1819bbf5ba1SRafael Vanoni 					n->next->prev = n->prev;
1829bbf5ba1SRafael Vanoni 				}
1839bbf5ba1SRafael Vanoni 			}
184b47b5b34SRafael Vanoni 
1859bbf5ba1SRafael Vanoni 			/*
1869bbf5ba1SRafael Vanoni 			 * If this suggestions is currently being suggested,
1879bbf5ba1SRafael Vanoni 			 * remove it and update the screen.
1889bbf5ba1SRafael Vanoni 			 */
1899bbf5ba1SRafael Vanoni 			if (n == g_curr_sugg) {
1909bbf5ba1SRafael Vanoni 				if (n->sb_msg != NULL) {
1919bbf5ba1SRafael Vanoni 					pt_display_mod_status_bar(n->sb_msg);
1929bbf5ba1SRafael Vanoni 					pt_display_status_bar();
1939bbf5ba1SRafael Vanoni 				}
1949bbf5ba1SRafael Vanoni 				if (n->text != NULL)
1959bbf5ba1SRafael Vanoni 					pt_display_suggestions(NULL);
1969bbf5ba1SRafael Vanoni 			}
1979bbf5ba1SRafael Vanoni 
1989bbf5ba1SRafael Vanoni 			free(n);
1999bbf5ba1SRafael Vanoni 			ret = 1;
2009bbf5ba1SRafael Vanoni 		}
2019bbf5ba1SRafael Vanoni 	}
2029bbf5ba1SRafael Vanoni 
2039bbf5ba1SRafael Vanoni 	return (ret);
2049bbf5ba1SRafael Vanoni }
2059bbf5ba1SRafael Vanoni 
2069bbf5ba1SRafael Vanoni /*
2079bbf5ba1SRafael Vanoni  * Chose a suggestion to display. The list of suggestions is ordered by weight,
2089bbf5ba1SRafael Vanoni  * so we only worry about fariness here. Each suggestion, starting with the
2099bbf5ba1SRafael Vanoni  * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals.
2109bbf5ba1SRafael Vanoni  */
2119bbf5ba1SRafael Vanoni void
2129bbf5ba1SRafael Vanoni pt_sugg_pick(void)
2139bbf5ba1SRafael Vanoni {
2149bbf5ba1SRafael Vanoni 	sugg_t *n;
2159bbf5ba1SRafael Vanoni 
2169bbf5ba1SRafael Vanoni 	if (sugg == NULL) {
2179bbf5ba1SRafael Vanoni 		g_curr_sugg = NULL;
218b47b5b34SRafael Vanoni 		return;
219b47b5b34SRafael Vanoni 	}
220b47b5b34SRafael Vanoni 
2219bbf5ba1SRafael Vanoni search:
2229bbf5ba1SRafael Vanoni 	for (n = sugg; n != NULL; n = n->next) {
223b47b5b34SRafael Vanoni 
2249bbf5ba1SRafael Vanoni 		if (n->slice++ < PT_SUGG_DEF_SLICE) {
225b47b5b34SRafael Vanoni 
2269bbf5ba1SRafael Vanoni 			/*
2279bbf5ba1SRafael Vanoni 			 * Don't need to re-suggest the current suggestion.
2289bbf5ba1SRafael Vanoni 			 */
229*2d83778aSRafael Vanoni 			if (g_curr_sugg == n && !g_sig_resize)
2309bbf5ba1SRafael Vanoni 				return;
231b47b5b34SRafael Vanoni 
2329bbf5ba1SRafael Vanoni 			/*
2339bbf5ba1SRafael Vanoni 			 * Remove the current suggestion from screen.
2349bbf5ba1SRafael Vanoni 			 */
2359bbf5ba1SRafael Vanoni 			if (g_curr_sugg != NULL) {
2369bbf5ba1SRafael Vanoni 				if (g_curr_sugg->sb_msg != NULL) {
2379bbf5ba1SRafael Vanoni 					pt_display_mod_status_bar(
2389bbf5ba1SRafael Vanoni 					    g_curr_sugg->sb_msg);
2399bbf5ba1SRafael Vanoni 					pt_display_status_bar();
240b47b5b34SRafael Vanoni 				}
2419bbf5ba1SRafael Vanoni 				if (g_curr_sugg->text != NULL)
2429bbf5ba1SRafael Vanoni 					pt_display_suggestions(NULL);
2439bbf5ba1SRafael Vanoni 			}
2449bbf5ba1SRafael Vanoni 
2459bbf5ba1SRafael Vanoni 			if (n->sb_msg != NULL) {
2469bbf5ba1SRafael Vanoni 				pt_display_mod_status_bar(n->sb_msg);
2479bbf5ba1SRafael Vanoni 				pt_display_status_bar();
2489bbf5ba1SRafael Vanoni 			}
2499bbf5ba1SRafael Vanoni 
2509bbf5ba1SRafael Vanoni 			pt_display_suggestions(n->text);
2519bbf5ba1SRafael Vanoni 
2529bbf5ba1SRafael Vanoni 			g_curr_sugg = n;
2539bbf5ba1SRafael Vanoni 
254b47b5b34SRafael Vanoni 			return;
255b47b5b34SRafael Vanoni 		}
256b47b5b34SRafael Vanoni 	}
257b47b5b34SRafael Vanoni 
2589bbf5ba1SRafael Vanoni 	/*
2599bbf5ba1SRafael Vanoni 	 * All suggestions have run out of slice quotas, so we restart.
2609bbf5ba1SRafael Vanoni 	 */
2619bbf5ba1SRafael Vanoni 	for (n = sugg; n != NULL; n = n->next)
2629bbf5ba1SRafael Vanoni 		n->slice = 0;
2639bbf5ba1SRafael Vanoni 
2649bbf5ba1SRafael Vanoni 	goto search;
265b47b5b34SRafael Vanoni }
266b47b5b34SRafael Vanoni 
267b47b5b34SRafael Vanoni void
2689bbf5ba1SRafael Vanoni pt_sugg_as_root(void)
269b47b5b34SRafael Vanoni {
2709bbf5ba1SRafael Vanoni 	pt_sugg_add("Suggestion: run as root to get suggestions"
2719bbf5ba1SRafael Vanoni 	    " for reducing system power consumption",  40, NULL, NULL,
2729bbf5ba1SRafael Vanoni 	    NULL);
273b47b5b34SRafael Vanoni }
274