xref: /onnv-gate/usr/src/cmd/powertop/common/suggestions.c (revision 11122:393b5ac48d9b)
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 <unistd.h>
419338Srafael.vanoni@sun.com #include <stdio.h>
429338Srafael.vanoni@sun.com #include <stdlib.h>
439338Srafael.vanoni@sun.com #include <string.h>
449338Srafael.vanoni@sun.com #include "powertop.h"
459338Srafael.vanoni@sun.com 
469908Srafael.vanoni@sun.com /*
479908Srafael.vanoni@sun.com  * Default number of intervals we display a suggestion before moving
489908Srafael.vanoni@sun.com  * to the next.
499908Srafael.vanoni@sun.com  */
509908Srafael.vanoni@sun.com #define	PT_SUGG_DEF_SLICE	3
519908Srafael.vanoni@sun.com 
529908Srafael.vanoni@sun.com /*
539908Srafael.vanoni@sun.com  * Global pointer to the current suggestion.
549908Srafael.vanoni@sun.com  */
559908Srafael.vanoni@sun.com sugg_t	*g_curr_sugg;
569908Srafael.vanoni@sun.com 
579908Srafael.vanoni@sun.com /*
589908Srafael.vanoni@sun.com  * Head of the list of suggestions.
599908Srafael.vanoni@sun.com  */
609908Srafael.vanoni@sun.com static sugg_t *sugg;
619338Srafael.vanoni@sun.com 
629908Srafael.vanoni@sun.com /*
639908Srafael.vanoni@sun.com  * Add a new suggestion. Only one suggestion per text allowed.
649908Srafael.vanoni@sun.com  */
659908Srafael.vanoni@sun.com void
pt_sugg_add(char * text,int weight,char key,char * sb_msg,sugg_func_t * func)669908Srafael.vanoni@sun.com pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func)
679908Srafael.vanoni@sun.com {
689908Srafael.vanoni@sun.com 	sugg_t *new, *n, *pos = NULL;
699908Srafael.vanoni@sun.com 
709908Srafael.vanoni@sun.com 	/*
719908Srafael.vanoni@sun.com 	 * Text is a required field for suggestions
729908Srafael.vanoni@sun.com 	 */
739908Srafael.vanoni@sun.com 	if (text == NULL)
749908Srafael.vanoni@sun.com 		return;
759908Srafael.vanoni@sun.com 
769908Srafael.vanoni@sun.com 	if (sugg == NULL) {
779908Srafael.vanoni@sun.com 		/*
789908Srafael.vanoni@sun.com 		 * Creating first element
799908Srafael.vanoni@sun.com 		 */
809908Srafael.vanoni@sun.com 		if ((new = calloc(1, sizeof (sugg_t))) == NULL)
819908Srafael.vanoni@sun.com 			return;
829338Srafael.vanoni@sun.com 
839908Srafael.vanoni@sun.com 		if (sb_msg != NULL)
849908Srafael.vanoni@sun.com 			new->sb_msg = strdup(sb_msg);
859908Srafael.vanoni@sun.com 
869908Srafael.vanoni@sun.com 		if (text != NULL)
879908Srafael.vanoni@sun.com 			new->text = strdup(text);
889908Srafael.vanoni@sun.com 
899908Srafael.vanoni@sun.com 		new->weight = weight;
909908Srafael.vanoni@sun.com 		new->key = key;
919908Srafael.vanoni@sun.com 		new->func = func;
929908Srafael.vanoni@sun.com 		new->slice = 0;
939908Srafael.vanoni@sun.com 
949908Srafael.vanoni@sun.com 		sugg = new;
959908Srafael.vanoni@sun.com 		new->prev = NULL;
969908Srafael.vanoni@sun.com 		new->next = NULL;
979908Srafael.vanoni@sun.com 	} else {
989908Srafael.vanoni@sun.com 		for (n = sugg; n != NULL; n = n->next) {
999908Srafael.vanoni@sun.com 			if (strcmp(n->text, text) == 0)
1009908Srafael.vanoni@sun.com 				return;
1019338Srafael.vanoni@sun.com 
1029908Srafael.vanoni@sun.com 			if (weight > n->weight && pos == NULL)
1039908Srafael.vanoni@sun.com 				pos = n;
1049908Srafael.vanoni@sun.com 		}
1059908Srafael.vanoni@sun.com 		/*
1069908Srafael.vanoni@sun.com 		 * Create a new element
1079908Srafael.vanoni@sun.com 		 */
1089908Srafael.vanoni@sun.com 		if ((new = calloc(1, sizeof (sugg_t))) == NULL)
1099908Srafael.vanoni@sun.com 			return;
1109338Srafael.vanoni@sun.com 
1119908Srafael.vanoni@sun.com 		if (sb_msg != NULL)
1129908Srafael.vanoni@sun.com 			new->sb_msg = strdup(sb_msg);
1139908Srafael.vanoni@sun.com 
1149908Srafael.vanoni@sun.com 		new->text = strdup(text);
1159908Srafael.vanoni@sun.com 
1169908Srafael.vanoni@sun.com 		new->weight = weight;
1179908Srafael.vanoni@sun.com 		new->key = key;
1189908Srafael.vanoni@sun.com 		new->func = func;
1199908Srafael.vanoni@sun.com 		new->slice = 0;
1209338Srafael.vanoni@sun.com 
1219908Srafael.vanoni@sun.com 		if (pos == NULL) {
1229908Srafael.vanoni@sun.com 			/*
1239908Srafael.vanoni@sun.com 			 * Ordering placed the new element at the end
1249908Srafael.vanoni@sun.com 			 */
1259908Srafael.vanoni@sun.com 			for (n = sugg; n->next != NULL; n = n->next)
1269908Srafael.vanoni@sun.com 				;
1279338Srafael.vanoni@sun.com 
1289908Srafael.vanoni@sun.com 			n->next = new;
1299908Srafael.vanoni@sun.com 			new->prev = n;
1309908Srafael.vanoni@sun.com 			new->next = NULL;
1319908Srafael.vanoni@sun.com 		} else {
1329908Srafael.vanoni@sun.com 			if (pos == sugg) {
1339908Srafael.vanoni@sun.com 				/*
1349908Srafael.vanoni@sun.com 				 * Ordering placed the new element at the start
1359908Srafael.vanoni@sun.com 				 */
1369908Srafael.vanoni@sun.com 				new->next = sugg;
1379908Srafael.vanoni@sun.com 				new->prev = sugg;
1389908Srafael.vanoni@sun.com 				sugg->prev = new;
1399908Srafael.vanoni@sun.com 				sugg = new;
1409908Srafael.vanoni@sun.com 			} else {
1419908Srafael.vanoni@sun.com 				/*
1429908Srafael.vanoni@sun.com 				 * Ordering placed the new element somewhere in
1439908Srafael.vanoni@sun.com 				 * the middle
1449908Srafael.vanoni@sun.com 				 */
1459908Srafael.vanoni@sun.com 				new->next = pos;
1469908Srafael.vanoni@sun.com 				new->prev = pos->prev;
1479908Srafael.vanoni@sun.com 				pos->prev->next = new;
1489908Srafael.vanoni@sun.com 				pos->prev = new;
1499908Srafael.vanoni@sun.com 			}
1509908Srafael.vanoni@sun.com 		}
1519908Srafael.vanoni@sun.com 	}
1529908Srafael.vanoni@sun.com }
1539338Srafael.vanoni@sun.com 
1549908Srafael.vanoni@sun.com /*
1559908Srafael.vanoni@sun.com  * Removes a suggestion, returning 0 if not found and 1 if so.
1569908Srafael.vanoni@sun.com  */
1579908Srafael.vanoni@sun.com int
pt_sugg_remove(sugg_func_t * func)1589908Srafael.vanoni@sun.com pt_sugg_remove(sugg_func_t *func)
1599908Srafael.vanoni@sun.com {
1609908Srafael.vanoni@sun.com 	sugg_t *n;
1619908Srafael.vanoni@sun.com 	int ret = 0;
1629338Srafael.vanoni@sun.com 
1639908Srafael.vanoni@sun.com 	for (n = sugg; n != NULL; n = n->next) {
1649908Srafael.vanoni@sun.com 		if (n->func == func) {
1659908Srafael.vanoni@sun.com 			/* Removing the first element */
1669908Srafael.vanoni@sun.com 			if (n == sugg) {
1679908Srafael.vanoni@sun.com 				if (sugg->next == NULL) {
1689908Srafael.vanoni@sun.com 					/* Removing the only element */
1699908Srafael.vanoni@sun.com 					sugg = NULL;
1709908Srafael.vanoni@sun.com 				} else {
1719908Srafael.vanoni@sun.com 					sugg = n->next;
1729908Srafael.vanoni@sun.com 					sugg->prev = NULL;
1739908Srafael.vanoni@sun.com 				}
1749908Srafael.vanoni@sun.com 			} else {
1759908Srafael.vanoni@sun.com 				if (n->next == NULL) {
1769908Srafael.vanoni@sun.com 					/* Removing the last element */
1779908Srafael.vanoni@sun.com 					n->prev->next = NULL;
1789908Srafael.vanoni@sun.com 				} else {
1799908Srafael.vanoni@sun.com 					/* Removing an intermediate element */
1809908Srafael.vanoni@sun.com 					n->prev->next = n->next;
1819908Srafael.vanoni@sun.com 					n->next->prev = n->prev;
1829908Srafael.vanoni@sun.com 				}
1839908Srafael.vanoni@sun.com 			}
1849908Srafael.vanoni@sun.com 
1859908Srafael.vanoni@sun.com 			/*
1869908Srafael.vanoni@sun.com 			 * If this suggestions is currently being suggested,
1879908Srafael.vanoni@sun.com 			 * remove it and update the screen.
1889908Srafael.vanoni@sun.com 			 */
1899908Srafael.vanoni@sun.com 			if (n == g_curr_sugg) {
1909908Srafael.vanoni@sun.com 				if (n->sb_msg != NULL) {
1919908Srafael.vanoni@sun.com 					pt_display_mod_status_bar(n->sb_msg);
1929908Srafael.vanoni@sun.com 					pt_display_status_bar();
1939908Srafael.vanoni@sun.com 				}
1949908Srafael.vanoni@sun.com 				if (n->text != NULL)
1959908Srafael.vanoni@sun.com 					pt_display_suggestions(NULL);
1969908Srafael.vanoni@sun.com 			}
1979908Srafael.vanoni@sun.com 
1989908Srafael.vanoni@sun.com 			free(n);
1999908Srafael.vanoni@sun.com 			ret = 1;
2009908Srafael.vanoni@sun.com 		}
2019338Srafael.vanoni@sun.com 	}
2029338Srafael.vanoni@sun.com 
2039908Srafael.vanoni@sun.com 	return (ret);
2049908Srafael.vanoni@sun.com }
2059908Srafael.vanoni@sun.com 
2069908Srafael.vanoni@sun.com /*
2079908Srafael.vanoni@sun.com  * Chose a suggestion to display. The list of suggestions is ordered by weight,
2089908Srafael.vanoni@sun.com  * so we only worry about fariness here. Each suggestion, starting with the
2099908Srafael.vanoni@sun.com  * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals.
2109908Srafael.vanoni@sun.com  */
2119908Srafael.vanoni@sun.com void
pt_sugg_pick(void)2129908Srafael.vanoni@sun.com pt_sugg_pick(void)
2139908Srafael.vanoni@sun.com {
2149908Srafael.vanoni@sun.com 	sugg_t *n;
2159908Srafael.vanoni@sun.com 
2169908Srafael.vanoni@sun.com 	if (sugg == NULL) {
2179908Srafael.vanoni@sun.com 		g_curr_sugg = NULL;
2189908Srafael.vanoni@sun.com 		return;
2199908Srafael.vanoni@sun.com 	}
2209908Srafael.vanoni@sun.com 
2219908Srafael.vanoni@sun.com search:
2229908Srafael.vanoni@sun.com 	for (n = sugg; n != NULL; n = n->next) {
2239908Srafael.vanoni@sun.com 
2249908Srafael.vanoni@sun.com 		if (n->slice++ < PT_SUGG_DEF_SLICE) {
2259908Srafael.vanoni@sun.com 
2269908Srafael.vanoni@sun.com 			/*
2279908Srafael.vanoni@sun.com 			 * Don't need to re-suggest the current suggestion.
2289908Srafael.vanoni@sun.com 			 */
229*11122Srafael.vanoni@sun.com 			if (g_curr_sugg == n && !g_sig_resize)
2309908Srafael.vanoni@sun.com 				return;
2319338Srafael.vanoni@sun.com 
2329908Srafael.vanoni@sun.com 			/*
2339908Srafael.vanoni@sun.com 			 * Remove the current suggestion from screen.
2349908Srafael.vanoni@sun.com 			 */
2359908Srafael.vanoni@sun.com 			if (g_curr_sugg != NULL) {
2369908Srafael.vanoni@sun.com 				if (g_curr_sugg->sb_msg != NULL) {
2379908Srafael.vanoni@sun.com 					pt_display_mod_status_bar(
2389908Srafael.vanoni@sun.com 					    g_curr_sugg->sb_msg);
2399908Srafael.vanoni@sun.com 					pt_display_status_bar();
2409908Srafael.vanoni@sun.com 				}
2419908Srafael.vanoni@sun.com 				if (g_curr_sugg->text != NULL)
2429908Srafael.vanoni@sun.com 					pt_display_suggestions(NULL);
2439908Srafael.vanoni@sun.com 			}
2449908Srafael.vanoni@sun.com 
2459908Srafael.vanoni@sun.com 			if (n->sb_msg != NULL) {
2469908Srafael.vanoni@sun.com 				pt_display_mod_status_bar(n->sb_msg);
2479908Srafael.vanoni@sun.com 				pt_display_status_bar();
2489908Srafael.vanoni@sun.com 			}
2499908Srafael.vanoni@sun.com 
2509908Srafael.vanoni@sun.com 			pt_display_suggestions(n->text);
2519908Srafael.vanoni@sun.com 
2529908Srafael.vanoni@sun.com 			g_curr_sugg = n;
2539908Srafael.vanoni@sun.com 
2549908Srafael.vanoni@sun.com 			return;
2559908Srafael.vanoni@sun.com 		}
2569908Srafael.vanoni@sun.com 	}
2579908Srafael.vanoni@sun.com 
2589908Srafael.vanoni@sun.com 	/*
2599908Srafael.vanoni@sun.com 	 * All suggestions have run out of slice quotas, so we restart.
2609908Srafael.vanoni@sun.com 	 */
2619908Srafael.vanoni@sun.com 	for (n = sugg; n != NULL; n = n->next)
2629908Srafael.vanoni@sun.com 		n->slice = 0;
2639908Srafael.vanoni@sun.com 
2649908Srafael.vanoni@sun.com 	goto search;
2659338Srafael.vanoni@sun.com }
2669338Srafael.vanoni@sun.com 
2679338Srafael.vanoni@sun.com void
pt_sugg_as_root(void)2689908Srafael.vanoni@sun.com pt_sugg_as_root(void)
2699338Srafael.vanoni@sun.com {
2709908Srafael.vanoni@sun.com 	pt_sugg_add("Suggestion: run as root to get suggestions"
2719908Srafael.vanoni@sun.com 	    " for reducing system power consumption",  40, NULL, NULL,
2729908Srafael.vanoni@sun.com 	    NULL);
2739338Srafael.vanoni@sun.com }
274