Minor cleanups
[meego-developer-tools:powertop.git] / cpufreqstats.c
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[MAX_NUM_PSTATES];
41 struct cpufreqdata oldfreqs[MAX_NUM_PSTATES];
42
43 struct cpufreqdata delta[MAX_NUM_PSTATES];
44
45 char cpufreqstrings[MAX_NUM_PSTATES+1][80];
46 int topfreq = -1;
47
48 static void zap(void)
49 {
50         memset(freqs, 0, sizeof(freqs));
51 }
52
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
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
65
66 static unsigned long turbo_hz;
67
68 static int is_turbo(unsigned long hz)
69 {
70         if (hz == turbo_hz)
71                 return 1;
72         return 0;
73 }
74
75
76 static char *HzToHuman(unsigned long hz)
77 {
78         static char buffer[1024];
79         memset(buffer, 0, 1024);
80         unsigned long long Hz;
81
82         Hz = hz;
83
84         /* default: just put the Number in */
85         sprintf(buffer,_("%9lli"), Hz);
86
87         if (Hz>1000)
88                 sprintf(buffer, _("%6lli Mhz"), (Hz+500)/1000);
89
90         if (Hz>1500000)
91                 sprintf(buffer, _("%6.2f Ghz"), (Hz+5000.0)/1000000);
92
93         if (is_turbo(hz))
94                 sprintf(buffer, "%s", _("Turbo Mode"));
95
96
97         return buffer;
98 }
99
100
101 void  do_cpufreq_stats(void)
102 {
103         DIR *dir;
104         struct dirent *dirent;
105         FILE *file;
106         char filename[PATH_MAX];
107         char line[1024];
108
109         int ret = 0;
110         int maxfreq = 0;
111         uint64_t total_time = 0;
112
113         memcpy(&oldfreqs, &freqs, sizeof(freqs));
114         memset(&cpufreqstrings, 0, sizeof(cpufreqstrings));
115         sprintf(cpufreqstrings[0], _("P-states (frequencies)\n"));
116
117         for (ret = 0; ret < MAX_NUM_PSTATES; ret++)
118                 freqs[ret].count = 0;
119
120         dir = opendir("/sys/devices/system/cpu");
121         if (!dir)
122                 return;
123
124         while ((dirent = readdir(dir))) {
125                 int i;
126                 if (dirent->d_name[0]=='.')
127                         continue;
128                 sprintf(filename, "/sys/devices/system/cpu/%s/cpufreq/stats/time_in_state", dirent->d_name);
129                 file = fopen(filename, "r");
130                 if (!file)
131                         continue;
132                 memset(line, 0, 1024);
133
134                 i = 0;
135                 while (!feof(file)) {
136                         uint64_t f,count;
137                         char *c;
138                         if (fgets(line, 1023,file)==NULL)
139                                 break;
140                         f = strtoull(line, &c, 10);
141                         if (!c)
142                                 break;
143                         count = strtoull(c, NULL, 10);
144
145                         if (freqs[i].frequency && freqs[i].frequency != f) {
146                                 zap();
147                                 break;
148                         }
149
150                         freqs[i].frequency = f;
151                         freqs[i].count += count;
152
153                         if (f && maxfreq < i)
154                                 maxfreq = i;
155                         i++;
156                         if (i >= MAX_NUM_PSTATES)
157                                 break;
158                 }
159                 fclose(file);
160         }
161
162         closedir(dir);
163
164         for (ret = 0; ret < MAX_NUM_PSTATES; ret++) {
165                 delta[ret].count = freqs[ret].count - oldfreqs[ret].count;
166                 total_time += delta[ret].count;
167                 delta[ret].frequency = freqs[ret].frequency;
168                 if (freqs[ret].frequency != oldfreqs[ret].frequency)
169                         return;  /* duff data */
170         }
171
172
173         if (!total_time)
174                 return;
175
176         qsort(&delta, maxfreq+1, sizeof(struct cpufreqdata), sort_by_count);
177         if (maxfreq>4)
178                 maxfreq=4;
179         maxpstate = maxfreq;
180         qsort(&delta, maxfreq+1, sizeof(struct cpufreqdata), sort_by_freq);
181
182         if (delta[0].frequency == delta[1].frequency + 1000)
183                 turbo_hz = delta[0].frequency;
184
185         topfreq = -1;
186         for (ret = 0 ; ret<=maxfreq; ret++) {
187                 sprintf(cpufreqstrings[ret+1], "%6s   %5.1f%%\n", HzToHuman(delta[ret].frequency), delta[ret].count * 100.0 / total_time);
188                 if (delta[ret].count > total_time/2)
189                         topfreq = ret;
190         }
191
192 }