xref: /illumos-gate/usr/src/cmd/powertop/common/util.c (revision 2d83778a)
1 /*
2  * Copyright 2009, Intel Corporation
3  * Copyright 2009, Sun Microsystems, Inc
4  *
5  * This file is part of PowerTOP
6  *
7  * This program file is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; version 2 of the License.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program in a file named COPYING; if not, write to the
18  * Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301 USA
21  *
22  * Authors:
23  *	Arjan van de Ven <arjan@linux.intel.com>
24  *	Eric C Saxe <eric.saxe@sun.com>
25  *	Aubrey Li <aubrey.li@intel.com>
26  */
27 
28 /*
29  * GPL Disclaimer
30  *
31  * For the avoidance of doubt, except that if any license choice other
32  * than GPL or LGPL is available it will apply instead, Sun elects to
33  * use only the General Public License version 2 (GPLv2) at this time
34  * for any software where a choice of GPL license versions is made
35  * available with the language indicating that GPLv2 or any later
36  * version may be used, or where a choice of which version of the GPL
37  * is applied is otherwise unspecified.
38  */
39 
40 #include <stdarg.h>
41 #include <stdlib.h>
42 #include <libgen.h>
43 #include <unistd.h>
44 #include <strings.h>
45 #include <sys/systeminfo.h>
46 #include <kstat.h>
47 #include <errno.h>
48 #include "powertop.h"
49 
50 static char 	PROG_FMT[] = "%s: ";
51 static char 	ERR_FMT[] = ": %s";
52 static char 	*progname;
53 
54 void
pt_set_progname(char * name)55 pt_set_progname(char *name)
56 {
57 	progname = basename(name);
58 }
59 
60 /*PRINTFLIKE1*/
61 void
pt_error(char * format,...)62 pt_error(char *format, ...)
63 {
64 	int 	err = errno;
65 	va_list alist;
66 
67 	if (g_gui)
68 		return;
69 
70 	if (progname != NULL)
71 		(void) fprintf(stderr, PROG_FMT, progname);
72 
73 	va_start(alist, format);
74 	(void) vfprintf(stderr, format, alist);
75 	va_end(alist);
76 
77 	if (strchr(format, '\n') == NULL)
78 		(void) fprintf(stderr, ERR_FMT, strerror(err));
79 }
80 
81 /*
82  * Returns the number of online CPUs.
83  */
84 uint_t
pt_enumerate_cpus(void)85 pt_enumerate_cpus(void)
86 {
87 	int	cpuid;
88 	int	max, cpus_conf;
89 	uint_t	ncpus = 0;
90 
91 	max 		= sysconf(_SC_CPUID_MAX);
92 	cpus_conf	= sysconf(_SC_NPROCESSORS_CONF);
93 
94 	/* Fall back to one CPU if any of the sysconf calls above failed */
95 	if (max == -1 || cpus_conf == -1) {
96 		max = cpus_conf = 1;
97 	}
98 
99 	if ((g_cpu_table = malloc(cpus_conf * sizeof (processorid_t))) == NULL)
100 		return (0);
101 
102 	for (cpuid = 0; cpuid < max; cpuid++) {
103 		if (p_online(cpuid, P_STATUS) != -1) {
104 			g_cpu_table[ncpus] = cpuid;
105 			ncpus++;
106 		}
107 	}
108 	return (ncpus);
109 }
110 
111 void
pt_usage(void)112 pt_usage(void)
113 {
114 	(void) fprintf(stderr, "%s   %s\n\n", TITLE, COPYRIGHT_INTEL);
115 	(void) fprintf(stderr, "usage: powertop [option]\n");
116 	(void) fprintf(stderr, "  -d, --dump [count]	Read wakeups count "
117 	    "times and print list of top offenders\n");
118 	(void) fprintf(stderr, "  -t, --time [interval]	Default time to gather "
119 	    "data in seconds [1-30s]\n");
120 	(void) fprintf(stderr, "  -v, --verbose		Verbose mode, reports "
121 	    "kernel cyclic activity\n");
122 	(void) fprintf(stderr, "  -c, --cpu [CPU]	Only observe a specific"
123 	    " CPU\n");
124 	(void) fprintf(stderr, "  -h, --help		Show this help "
125 	    "message\n");
126 }
127 
128 int
pt_get_bit_depth(void)129 pt_get_bit_depth(void)
130 {
131 	/*
132 	 * This little routine was derived from isainfo.c to look up
133 	 * the system's bit depth. It feeds a 10 byte long buffer to
134 	 * sysinfo (we only need the first word, sysinfo truncates and
135 	 * \0 terminates the rest) from which we figure out which isa
136 	 * we're running on.
137 	 */
138 	char	buf[BIT_DEPTH_BUF];
139 
140 	if (sysinfo(SI_ARCHITECTURE_64, buf, BIT_DEPTH_BUF) == -1)
141 		if (sysinfo(SI_ARCHITECTURE_32, buf, BIT_DEPTH_BUF) == -1)
142 			return (-2);
143 
144 	if (strcmp(buf, "sparc") == 0 || strcmp(buf, "i386") == 0)
145 		return (32);
146 
147 	if (strcmp(buf, "sparcv9") == 0 || strcmp(buf, "amd64") == 0)
148 		return (64);
149 
150 	return (-3);
151 }
152 
153 /*
154  * Simple integer comparison routine for the event report qsort(3C).
155  */
156 int
pt_event_compare(const void * p1,const void * p2)157 pt_event_compare(const void *p1, const void *p2)
158 {
159 	event_info_t i = *((event_info_t *)p1);
160 	event_info_t j = *((event_info_t *)p2);
161 
162 	if (i.total_count > j.total_count)
163 		return (-1);
164 
165 	if (i.total_count < j.total_count)
166 		return (1);
167 
168 	return (0);
169 }
170