• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007, Intel Corporation
3  *
4  * This file is part of PowerTOP
5  *
6  * This program file is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program in a file named COPYING; if not, write to the
17  * Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301 USA
20  *
21  * Authors:
22  * 	Arjan van de Ven <arjan@linux.intel.com>
23  */
24 
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include <sys/types.h>
31 #include <dirent.h>
32 
33 #include "powertop.h"
34 
35 struct cpufreqdata {
36 	uint64_t	frequency;
37 	uint64_t	count;
38 };
39 
40 struct cpufreqdata freqs[16];
41 struct cpufreqdata oldfreqs[16];
42 
43 struct cpufreqdata delta[16];
44 
45 char cpufreqstrings[6][80];
46 int topfreq = -1;
47 
zap(void)48 static void zap(void)
49 {
50 	memset(freqs, 0, sizeof(freqs));
51 }
52 
sort_by_count(const void * av,const void * bv)53 int sort_by_count (const void *av, const void *bv)
54 {
55         const struct cpufreqdata       *a = av, *b = bv;
56         return b->count - a->count;
57 }
58 
sort_by_freq(const void * av,const void * bv)59 int sort_by_freq (const void *av, const void *bv)
60 {
61         const struct cpufreqdata       *a = av, *b = bv;
62         return b->frequency - a->frequency;
63 }
64 
HzToHuman(unsigned long hz)65 static char *HzToHuman(unsigned long hz)
66 {
67 	static char buffer[1024];
68 	memset(buffer, 0, 1024);
69 	unsigned long long Hz;
70 
71 	Hz = hz;
72 
73 	/* default: just put the Number in */
74 	sprintf(buffer,_("%9lli"), Hz);
75 
76 	if (Hz>1000)
77 		sprintf(buffer, _("%6lli Mhz"), (Hz+500)/1000);
78 
79 	if (Hz>1500000)
80 		sprintf(buffer, _("%6.2f Ghz"), (Hz+5000.0)/1000000);
81 
82 
83 	return buffer;
84 }
85 
86 
do_cpufreq_stats(void)87 void  do_cpufreq_stats(void)
88 {
89 	DIR *dir;
90 	struct dirent *dirent;
91 	FILE *file;
92 	char filename[PATH_MAX];
93 	char line[1024];
94 
95 	int ret = 0;
96 	int maxfreq = 0;
97 	uint64_t total_time = 0;
98 
99 	memcpy(&oldfreqs, &freqs, sizeof(freqs));
100 	memset(&cpufreqstrings, 0, sizeof(cpufreqstrings));
101 	sprintf(cpufreqstrings[0], _("P-states (frequencies)\n"));
102 
103 	for (ret = 0; ret<16; ret++)
104 		freqs[ret].count = 0;
105 
106 	dir = opendir("/sys/devices/system/cpu");
107 	if (!dir)
108 		return;
109 
110 	while ((dirent = readdir(dir))) {
111 		int i;
112 		if (dirent->d_name[0]=='.')
113 			continue;
114 		sprintf(filename, "/sys/devices/system/cpu/%s/cpufreq/stats/time_in_state", dirent->d_name);
115 		file = fopen(filename, "r");
116 		if (!file)
117 			continue;
118 		memset(line, 0, 1024);
119 
120 		i = 0;
121 		while (!feof(file)) {
122 			uint64_t f,count;
123 			char *c;
124 			if (fgets(line, 1023,file)==NULL)
125 				break;
126 			f = strtoull(line, &c, 10);
127 			if (!c)
128 				break;
129 			count = strtoull(c, NULL, 10);
130 
131 			if (freqs[i].frequency && freqs[i].frequency != f) {
132 				zap();
133 				break;
134 			}
135 
136 			freqs[i].frequency = f;
137 			freqs[i].count += count;
138 
139 			if (f && maxfreq < i)
140 				maxfreq = i;
141 			i++;
142 			if (i>15)
143 				break;
144 		}
145 		fclose(file);
146 	}
147 
148 	closedir(dir);
149 
150 	for (ret = 0; ret < 16; ret++) {
151 		delta[ret].count = freqs[ret].count - oldfreqs[ret].count;
152 		total_time += delta[ret].count;
153 		delta[ret].frequency = freqs[ret].frequency;
154 		if (freqs[ret].frequency != oldfreqs[ret].frequency)
155 			return;  /* duff data */
156 	}
157 
158 
159 	if (!total_time)
160 		return;
161 
162 	qsort(&delta, maxfreq+1, sizeof(struct cpufreqdata), sort_by_count);
163 	if (maxfreq>4)
164 		maxfreq=4;
165 	qsort(&delta, maxfreq+1, sizeof(struct cpufreqdata), sort_by_freq);
166 
167 	topfreq = -1;
168 	for (ret = 0 ; ret<=maxfreq; ret++) {
169 		sprintf(cpufreqstrings[ret+1], "%6s   %5.1f%%\n", HzToHuman(delta[ret].frequency), delta[ret].count * 100.0 / total_time);
170 		if (delta[ret].count > total_time/2)
171 			topfreq = ret;
172 	}
173 
174 }
175