This source file includes following definitions.
- cpuidle_state_file_exists
- cpuidle_state_read_file
- cpuidle_state_write_file
- cpuidle_state_get_one_value
- cpuidle_state_get_one_string
- cpuidle_is_state_disabled
- cpuidle_state_disable
- cpuidle_state_latency
- cpuidle_state_usage
- cpuidle_state_time
- cpuidle_state_name
- cpuidle_state_desc
- cpuidle_state_count
- sysfs_cpuidle_read_file
- sysfs_cpuidle_get_one_string
- cpuidle_get_governor
- cpuidle_get_driver
1
2
3
4
5
6
7 #include <stdio.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15
16 #include "cpuidle.h"
17 #include "cpupower_intern.h"
18
19
20
21
22
23
24
25
26
27
28 static
29 unsigned int cpuidle_state_file_exists(unsigned int cpu,
30 unsigned int idlestate,
31 const char *fname)
32 {
33 char path[SYSFS_PATH_MAX];
34 struct stat statbuf;
35
36
37 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
38 cpu, idlestate, fname);
39 if (stat(path, &statbuf) != 0)
40 return 0;
41 return 1;
42 }
43
44
45
46
47
48
49
50 static
51 unsigned int cpuidle_state_read_file(unsigned int cpu,
52 unsigned int idlestate,
53 const char *fname, char *buf,
54 size_t buflen)
55 {
56 char path[SYSFS_PATH_MAX];
57 int fd;
58 ssize_t numread;
59
60 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
61 cpu, idlestate, fname);
62
63 fd = open(path, O_RDONLY);
64 if (fd == -1)
65 return 0;
66
67 numread = read(fd, buf, buflen - 1);
68 if (numread < 1) {
69 close(fd);
70 return 0;
71 }
72
73 buf[numread] = '\0';
74 close(fd);
75
76 return (unsigned int) numread;
77 }
78
79
80
81
82
83
84
85 static
86 unsigned int cpuidle_state_write_file(unsigned int cpu,
87 unsigned int idlestate,
88 const char *fname,
89 const char *value, size_t len)
90 {
91 char path[SYSFS_PATH_MAX];
92 int fd;
93 ssize_t numwrite;
94
95 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
96 cpu, idlestate, fname);
97
98 fd = open(path, O_WRONLY);
99 if (fd == -1)
100 return 0;
101
102 numwrite = write(fd, value, len);
103 if (numwrite < 1) {
104 close(fd);
105 return 0;
106 }
107
108 close(fd);
109
110 return (unsigned int) numwrite;
111 }
112
113
114
115 enum idlestate_value {
116 IDLESTATE_USAGE,
117 IDLESTATE_POWER,
118 IDLESTATE_LATENCY,
119 IDLESTATE_TIME,
120 IDLESTATE_DISABLE,
121 MAX_IDLESTATE_VALUE_FILES
122 };
123
124 static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
125 [IDLESTATE_USAGE] = "usage",
126 [IDLESTATE_POWER] = "power",
127 [IDLESTATE_LATENCY] = "latency",
128 [IDLESTATE_TIME] = "time",
129 [IDLESTATE_DISABLE] = "disable",
130 };
131
132 static
133 unsigned long long cpuidle_state_get_one_value(unsigned int cpu,
134 unsigned int idlestate,
135 enum idlestate_value which)
136 {
137 unsigned long long value;
138 unsigned int len;
139 char linebuf[MAX_LINE_LEN];
140 char *endp;
141
142 if (which >= MAX_IDLESTATE_VALUE_FILES)
143 return 0;
144
145 len = cpuidle_state_read_file(cpu, idlestate,
146 idlestate_value_files[which],
147 linebuf, sizeof(linebuf));
148 if (len == 0)
149 return 0;
150
151 value = strtoull(linebuf, &endp, 0);
152
153 if (endp == linebuf || errno == ERANGE)
154 return 0;
155
156 return value;
157 }
158
159
160
161 enum idlestate_string {
162 IDLESTATE_DESC,
163 IDLESTATE_NAME,
164 MAX_IDLESTATE_STRING_FILES
165 };
166
167 static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
168 [IDLESTATE_DESC] = "desc",
169 [IDLESTATE_NAME] = "name",
170 };
171
172
173 static char *cpuidle_state_get_one_string(unsigned int cpu,
174 unsigned int idlestate,
175 enum idlestate_string which)
176 {
177 char linebuf[MAX_LINE_LEN];
178 char *result;
179 unsigned int len;
180
181 if (which >= MAX_IDLESTATE_STRING_FILES)
182 return NULL;
183
184 len = cpuidle_state_read_file(cpu, idlestate,
185 idlestate_string_files[which],
186 linebuf, sizeof(linebuf));
187 if (len == 0)
188 return NULL;
189
190 result = strdup(linebuf);
191 if (result == NULL)
192 return NULL;
193
194 if (result[strlen(result) - 1] == '\n')
195 result[strlen(result) - 1] = '\0';
196
197 return result;
198 }
199
200
201
202
203
204
205
206
207 int cpuidle_is_state_disabled(unsigned int cpu,
208 unsigned int idlestate)
209 {
210 if (cpuidle_state_count(cpu) <= idlestate)
211 return -1;
212
213 if (!cpuidle_state_file_exists(cpu, idlestate,
214 idlestate_value_files[IDLESTATE_DISABLE]))
215 return -2;
216 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_DISABLE);
217 }
218
219
220
221
222
223
224
225
226
227
228 int cpuidle_state_disable(unsigned int cpu,
229 unsigned int idlestate,
230 unsigned int disable)
231 {
232 char value[SYSFS_PATH_MAX];
233 int bytes_written;
234
235 if (cpuidle_state_count(cpu) <= idlestate)
236 return -1;
237
238 if (!cpuidle_state_file_exists(cpu, idlestate,
239 idlestate_value_files[IDLESTATE_DISABLE]))
240 return -2;
241
242 snprintf(value, SYSFS_PATH_MAX, "%u", disable);
243
244 bytes_written = cpuidle_state_write_file(cpu, idlestate, "disable",
245 value, sizeof(disable));
246 if (bytes_written)
247 return 0;
248 return -3;
249 }
250
251 unsigned long cpuidle_state_latency(unsigned int cpu,
252 unsigned int idlestate)
253 {
254 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
255 }
256
257 unsigned long cpuidle_state_usage(unsigned int cpu,
258 unsigned int idlestate)
259 {
260 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
261 }
262
263 unsigned long long cpuidle_state_time(unsigned int cpu,
264 unsigned int idlestate)
265 {
266 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_TIME);
267 }
268
269 char *cpuidle_state_name(unsigned int cpu, unsigned int idlestate)
270 {
271 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_NAME);
272 }
273
274 char *cpuidle_state_desc(unsigned int cpu, unsigned int idlestate)
275 {
276 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_DESC);
277 }
278
279
280
281
282
283
284 unsigned int cpuidle_state_count(unsigned int cpu)
285 {
286 char file[SYSFS_PATH_MAX];
287 struct stat statbuf;
288 int idlestates = 1;
289
290
291 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
292 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
293 return 0;
294
295 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
296 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
297 return 0;
298
299 while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
300 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
301 "cpu%u/cpuidle/state%d", cpu, idlestates);
302 idlestates++;
303 }
304 idlestates--;
305 return idlestates;
306 }
307
308
309
310
311
312
313
314 static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
315 size_t buflen)
316 {
317 char path[SYSFS_PATH_MAX];
318
319 snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
320
321 return cpupower_read_sysfs(path, buf, buflen);
322 }
323
324
325
326
327
328 enum cpuidle_string {
329 CPUIDLE_GOVERNOR,
330 CPUIDLE_GOVERNOR_RO,
331 CPUIDLE_DRIVER,
332 MAX_CPUIDLE_STRING_FILES
333 };
334
335 static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
336 [CPUIDLE_GOVERNOR] = "current_governor",
337 [CPUIDLE_GOVERNOR_RO] = "current_governor_ro",
338 [CPUIDLE_DRIVER] = "current_driver",
339 };
340
341
342 static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
343 {
344 char linebuf[MAX_LINE_LEN];
345 char *result;
346 unsigned int len;
347
348 if (which >= MAX_CPUIDLE_STRING_FILES)
349 return NULL;
350
351 len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
352 linebuf, sizeof(linebuf));
353 if (len == 0)
354 return NULL;
355
356 result = strdup(linebuf);
357 if (result == NULL)
358 return NULL;
359
360 if (result[strlen(result) - 1] == '\n')
361 result[strlen(result) - 1] = '\0';
362
363 return result;
364 }
365
366 char *cpuidle_get_governor(void)
367 {
368 char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
369 if (!tmp)
370 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
371 else
372 return tmp;
373 }
374
375 char *cpuidle_get_driver(void)
376 {
377 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
378 }
379