xref: /titanic_53/usr/src/cmd/powertop/common/suggestions.c (revision 9bbf5ba14ae201f78f3d6b47a9fac96d68649275)
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 
46*9bbf5ba1SRafael Vanoni /*
47*9bbf5ba1SRafael Vanoni  * Default number of intervals we display a suggestion before moving
48*9bbf5ba1SRafael Vanoni  * to the next.
49*9bbf5ba1SRafael Vanoni  */
50*9bbf5ba1SRafael Vanoni #define	PT_SUGG_DEF_SLICE	3
51b47b5b34SRafael Vanoni 
52*9bbf5ba1SRafael Vanoni /*
53*9bbf5ba1SRafael Vanoni  * Global pointer to the current suggestion.
54*9bbf5ba1SRafael Vanoni  */
55*9bbf5ba1SRafael Vanoni sugg_t	*g_curr_sugg;
56b47b5b34SRafael Vanoni 
57*9bbf5ba1SRafael Vanoni /*
58*9bbf5ba1SRafael Vanoni  * Head of the list of suggestions.
59*9bbf5ba1SRafael Vanoni  */
60*9bbf5ba1SRafael Vanoni static sugg_t *sugg;
61b47b5b34SRafael Vanoni 
62*9bbf5ba1SRafael Vanoni /*
63*9bbf5ba1SRafael Vanoni  * Add a new suggestion. Only one suggestion per text allowed.
64*9bbf5ba1SRafael Vanoni  */
65b47b5b34SRafael Vanoni void
66*9bbf5ba1SRafael Vanoni pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func)
67b47b5b34SRafael Vanoni {
68*9bbf5ba1SRafael Vanoni 	sugg_t *new, *n, *pos = NULL;
69b47b5b34SRafael Vanoni 
70*9bbf5ba1SRafael Vanoni 	/*
71*9bbf5ba1SRafael Vanoni 	 * Text is a required field for suggestions
72*9bbf5ba1SRafael Vanoni 	 */
73*9bbf5ba1SRafael Vanoni 	if (text == NULL)
74b47b5b34SRafael Vanoni 		return;
75b47b5b34SRafael Vanoni 
76*9bbf5ba1SRafael Vanoni 	if (sugg == NULL) {
77*9bbf5ba1SRafael Vanoni 		/*
78*9bbf5ba1SRafael Vanoni 		 * Creating first element
79*9bbf5ba1SRafael Vanoni 		 */
80*9bbf5ba1SRafael Vanoni 		if ((new = calloc(1, sizeof (sugg_t))) == NULL)
81b47b5b34SRafael Vanoni 			return;
82b47b5b34SRafael Vanoni 
83*9bbf5ba1SRafael Vanoni 		if (sb_msg != NULL)
84*9bbf5ba1SRafael Vanoni 			new->sb_msg = strdup(sb_msg);
85b47b5b34SRafael Vanoni 
86*9bbf5ba1SRafael Vanoni 		if (text != NULL)
87*9bbf5ba1SRafael Vanoni 			new->text = strdup(text);
88*9bbf5ba1SRafael Vanoni 
89b47b5b34SRafael Vanoni 		new->weight = weight;
90b47b5b34SRafael Vanoni 		new->key = key;
91b47b5b34SRafael Vanoni 		new->func = func;
92*9bbf5ba1SRafael Vanoni 		new->slice = 0;
93*9bbf5ba1SRafael Vanoni 
94*9bbf5ba1SRafael Vanoni 		sugg = new;
95*9bbf5ba1SRafael Vanoni 		new->prev = NULL;
96*9bbf5ba1SRafael Vanoni 		new->next = NULL;
97*9bbf5ba1SRafael Vanoni 	} else {
98*9bbf5ba1SRafael Vanoni 		for (n = sugg; n != NULL; n = n->next) {
99*9bbf5ba1SRafael Vanoni 			if (strcmp(n->text, text) == 0)
100*9bbf5ba1SRafael Vanoni 				return;
101*9bbf5ba1SRafael Vanoni 
102*9bbf5ba1SRafael Vanoni 			if (weight > n->weight && pos == NULL)
103*9bbf5ba1SRafael Vanoni 				pos = n;
104*9bbf5ba1SRafael Vanoni 		}
105*9bbf5ba1SRafael Vanoni 		/*
106*9bbf5ba1SRafael Vanoni 		 * Create a new element
107*9bbf5ba1SRafael Vanoni 		 */
108*9bbf5ba1SRafael Vanoni 		if ((new = calloc(1, sizeof (sugg_t))) == NULL)
109*9bbf5ba1SRafael Vanoni 			return;
110*9bbf5ba1SRafael Vanoni 
111*9bbf5ba1SRafael Vanoni 		if (sb_msg != NULL)
112*9bbf5ba1SRafael Vanoni 			new->sb_msg = strdup(sb_msg);
113*9bbf5ba1SRafael Vanoni 
114*9bbf5ba1SRafael Vanoni 		new->text = strdup(text);
115*9bbf5ba1SRafael Vanoni 
116*9bbf5ba1SRafael Vanoni 		new->weight = weight;
117*9bbf5ba1SRafael Vanoni 		new->key = key;
118*9bbf5ba1SRafael Vanoni 		new->func = func;
119*9bbf5ba1SRafael Vanoni 		new->slice = 0;
120*9bbf5ba1SRafael Vanoni 
121*9bbf5ba1SRafael Vanoni 		if (pos == NULL) {
122*9bbf5ba1SRafael Vanoni 			/*
123*9bbf5ba1SRafael Vanoni 			 * Ordering placed the new element at the end
124*9bbf5ba1SRafael Vanoni 			 */
125*9bbf5ba1SRafael Vanoni 			for (n = sugg; n->next != NULL; n = n->next)
126*9bbf5ba1SRafael Vanoni 				;
127*9bbf5ba1SRafael Vanoni 
128*9bbf5ba1SRafael Vanoni 			n->next = new;
129*9bbf5ba1SRafael Vanoni 			new->prev = n;
130*9bbf5ba1SRafael Vanoni 			new->next = NULL;
131*9bbf5ba1SRafael Vanoni 		} else {
132*9bbf5ba1SRafael Vanoni 			if (pos == sugg) {
133*9bbf5ba1SRafael Vanoni 				/*
134*9bbf5ba1SRafael Vanoni 				 * Ordering placed the new element at the start
135*9bbf5ba1SRafael Vanoni 				 */
136*9bbf5ba1SRafael Vanoni 				new->next = sugg;
137*9bbf5ba1SRafael Vanoni 				new->prev = sugg;
138*9bbf5ba1SRafael Vanoni 				sugg->prev = new;
139*9bbf5ba1SRafael Vanoni 				sugg = new;
140*9bbf5ba1SRafael Vanoni 			} else {
141*9bbf5ba1SRafael Vanoni 				/*
142*9bbf5ba1SRafael Vanoni 				 * Ordering placed the new element somewhere in
143*9bbf5ba1SRafael Vanoni 				 * the middle
144*9bbf5ba1SRafael Vanoni 				 */
145*9bbf5ba1SRafael Vanoni 				new->next = pos;
146*9bbf5ba1SRafael Vanoni 				new->prev = pos->prev;
147*9bbf5ba1SRafael Vanoni 				pos->prev->next = new;
148*9bbf5ba1SRafael Vanoni 				pos->prev = new;
149*9bbf5ba1SRafael Vanoni 			}
150*9bbf5ba1SRafael Vanoni 		}
151*9bbf5ba1SRafael Vanoni 	}
152b47b5b34SRafael Vanoni }
153b47b5b34SRafael Vanoni 
154*9bbf5ba1SRafael Vanoni /*
155*9bbf5ba1SRafael Vanoni  * Removes a suggestion, returning 0 if not found and 1 if so.
156*9bbf5ba1SRafael Vanoni  */
157*9bbf5ba1SRafael Vanoni int
158*9bbf5ba1SRafael Vanoni pt_sugg_remove(sugg_func_t *func)
159b47b5b34SRafael Vanoni {
160*9bbf5ba1SRafael Vanoni 	sugg_t *n;
161*9bbf5ba1SRafael Vanoni 	int ret = 0;
162b47b5b34SRafael Vanoni 
163*9bbf5ba1SRafael Vanoni 	for (n = sugg; n != NULL; n = n->next) {
164*9bbf5ba1SRafael Vanoni 		if (n->func == func) {
165*9bbf5ba1SRafael Vanoni 			/* Removing the first element */
166*9bbf5ba1SRafael Vanoni 			if (n == sugg) {
167*9bbf5ba1SRafael Vanoni 				if (sugg->next == NULL) {
168*9bbf5ba1SRafael Vanoni 					/* Removing the only element */
169*9bbf5ba1SRafael Vanoni 					sugg = NULL;
170*9bbf5ba1SRafael Vanoni 				} else {
171*9bbf5ba1SRafael Vanoni 					sugg = n->next;
172*9bbf5ba1SRafael Vanoni 					sugg->prev = NULL;
173*9bbf5ba1SRafael Vanoni 				}
174*9bbf5ba1SRafael Vanoni 			} else {
175*9bbf5ba1SRafael Vanoni 				if (n->next == NULL) {
176*9bbf5ba1SRafael Vanoni 					/* Removing the last element */
177*9bbf5ba1SRafael Vanoni 					n->prev->next = NULL;
178*9bbf5ba1SRafael Vanoni 				} else {
179*9bbf5ba1SRafael Vanoni 					/* Removing an intermediate element */
180*9bbf5ba1SRafael Vanoni 					n->prev->next = n->next;
181*9bbf5ba1SRafael Vanoni 					n->next->prev = n->prev;
182*9bbf5ba1SRafael Vanoni 				}
183*9bbf5ba1SRafael Vanoni 			}
184b47b5b34SRafael Vanoni 
185*9bbf5ba1SRafael Vanoni 			/*
186*9bbf5ba1SRafael Vanoni 			 * If this suggestions is currently being suggested,
187*9bbf5ba1SRafael Vanoni 			 * remove it and update the screen.
188*9bbf5ba1SRafael Vanoni 			 */
189*9bbf5ba1SRafael Vanoni 			if (n == g_curr_sugg) {
190*9bbf5ba1SRafael Vanoni 				if (n->sb_msg != NULL) {
191*9bbf5ba1SRafael Vanoni 					pt_display_mod_status_bar(n->sb_msg);
192*9bbf5ba1SRafael Vanoni 					pt_display_status_bar();
193*9bbf5ba1SRafael Vanoni 				}
194*9bbf5ba1SRafael Vanoni 				if (n->text != NULL)
195*9bbf5ba1SRafael Vanoni 					pt_display_suggestions(NULL);
196*9bbf5ba1SRafael Vanoni 			}
197*9bbf5ba1SRafael Vanoni 
198*9bbf5ba1SRafael Vanoni 			free(n);
199*9bbf5ba1SRafael Vanoni 			ret = 1;
200*9bbf5ba1SRafael Vanoni 		}
201*9bbf5ba1SRafael Vanoni 	}
202*9bbf5ba1SRafael Vanoni 
203*9bbf5ba1SRafael Vanoni 	return (ret);
204*9bbf5ba1SRafael Vanoni }
205*9bbf5ba1SRafael Vanoni 
206*9bbf5ba1SRafael Vanoni /*
207*9bbf5ba1SRafael Vanoni  * Chose a suggestion to display. The list of suggestions is ordered by weight,
208*9bbf5ba1SRafael Vanoni  * so we only worry about fariness here. Each suggestion, starting with the
209*9bbf5ba1SRafael Vanoni  * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals.
210*9bbf5ba1SRafael Vanoni  */
211*9bbf5ba1SRafael Vanoni void
212*9bbf5ba1SRafael Vanoni pt_sugg_pick(void)
213*9bbf5ba1SRafael Vanoni {
214*9bbf5ba1SRafael Vanoni 	sugg_t *n;
215*9bbf5ba1SRafael Vanoni 
216*9bbf5ba1SRafael Vanoni 	if (sugg == NULL) {
217*9bbf5ba1SRafael Vanoni 		g_curr_sugg = NULL;
218b47b5b34SRafael Vanoni 		return;
219b47b5b34SRafael Vanoni 	}
220b47b5b34SRafael Vanoni 
221*9bbf5ba1SRafael Vanoni search:
222*9bbf5ba1SRafael Vanoni 	for (n = sugg; n != NULL; n = n->next) {
223b47b5b34SRafael Vanoni 
224*9bbf5ba1SRafael Vanoni 		if (n->slice++ < PT_SUGG_DEF_SLICE) {
225b47b5b34SRafael Vanoni 
226*9bbf5ba1SRafael Vanoni 			/*
227*9bbf5ba1SRafael Vanoni 			 * Don't need to re-suggest the current suggestion.
228*9bbf5ba1SRafael Vanoni 			 */
229*9bbf5ba1SRafael Vanoni 			if (g_curr_sugg == n)
230*9bbf5ba1SRafael Vanoni 				return;
231b47b5b34SRafael Vanoni 
232*9bbf5ba1SRafael Vanoni 			/*
233*9bbf5ba1SRafael Vanoni 			 * Remove the current suggestion from screen.
234*9bbf5ba1SRafael Vanoni 			 */
235*9bbf5ba1SRafael Vanoni 			if (g_curr_sugg != NULL) {
236*9bbf5ba1SRafael Vanoni 				if (g_curr_sugg->sb_msg != NULL) {
237*9bbf5ba1SRafael Vanoni 					pt_display_mod_status_bar(
238*9bbf5ba1SRafael Vanoni 					    g_curr_sugg->sb_msg);
239*9bbf5ba1SRafael Vanoni 					pt_display_status_bar();
240b47b5b34SRafael Vanoni 				}
241*9bbf5ba1SRafael Vanoni 				if (g_curr_sugg->text != NULL)
242*9bbf5ba1SRafael Vanoni 					pt_display_suggestions(NULL);
243*9bbf5ba1SRafael Vanoni 			}
244*9bbf5ba1SRafael Vanoni 
245*9bbf5ba1SRafael Vanoni 			if (n->sb_msg != NULL) {
246*9bbf5ba1SRafael Vanoni 				pt_display_mod_status_bar(n->sb_msg);
247*9bbf5ba1SRafael Vanoni 				pt_display_status_bar();
248*9bbf5ba1SRafael Vanoni 			}
249*9bbf5ba1SRafael Vanoni 
250*9bbf5ba1SRafael Vanoni 			pt_display_suggestions(n->text);
251*9bbf5ba1SRafael Vanoni 
252*9bbf5ba1SRafael Vanoni 			g_curr_sugg = n;
253*9bbf5ba1SRafael Vanoni 
254b47b5b34SRafael Vanoni 			return;
255b47b5b34SRafael Vanoni 		}
256b47b5b34SRafael Vanoni 	}
257b47b5b34SRafael Vanoni 
258*9bbf5ba1SRafael Vanoni 	/*
259*9bbf5ba1SRafael Vanoni 	 * All suggestions have run out of slice quotas, so we restart.
260*9bbf5ba1SRafael Vanoni 	 */
261*9bbf5ba1SRafael Vanoni 	for (n = sugg; n != NULL; n = n->next)
262*9bbf5ba1SRafael Vanoni 		n->slice = 0;
263*9bbf5ba1SRafael Vanoni 
264*9bbf5ba1SRafael Vanoni 	goto search;
265b47b5b34SRafael Vanoni }
266b47b5b34SRafael Vanoni 
267b47b5b34SRafael Vanoni void
268*9bbf5ba1SRafael Vanoni pt_sugg_as_root(void)
269b47b5b34SRafael Vanoni {
270*9bbf5ba1SRafael Vanoni 	pt_sugg_add("Suggestion: run as root to get suggestions"
271*9bbf5ba1SRafael Vanoni 	    " for reducing system power consumption",  40, NULL, NULL,
272*9bbf5ba1SRafael Vanoni 	    NULL);
273b47b5b34SRafael Vanoni }
274