wmauda: Fix installation dir
[dockapps.git] / wmpower-0.4.3 / src / power_management / cpufreq / cpufreq.c
blobad95557b48568811e9a19d8a0d20dddc9506549b
1 /***************************************************************************
2 cpufreq.c - description
3 -------------------
4 begin : Feb 10 2003
5 copyright : (C) 2003,2004,2005 by Noberasco Michele
6 e-mail : s4t4n@gentoo.org
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 * *
26 ***************************************************************************/
29 #define SYSFS_CPU_BASE_DIR "/sys/devices/system/cpu"
30 #define SYSFS_CPUFREQ_TEST "affected_cpus"
31 #define SYSFS_CPUFREQ_AVAIL_GOV "scaling_available_governors"
32 #define SYSFS_CPUFREQ_SET_GOV "scaling_governor"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <dirent.h>
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include "power_management.h"
41 #include "lib_utils.h"
44 /* This will contain a list of CPU that we will manage through cpufreq */
45 struct cpufreq_available_cpus
47 int cpu_number;
48 char *dir_name;
49 struct cpufreq_available_cpus *next;
50 } *available_cpus = NULL;
53 /* Add one element to the list of CPUs available for frequency scaling */
54 void add_to_cpus_list(int cpu_number, char *path)
56 struct cpufreq_available_cpus *new_cpu;
58 if (!path) return;
60 new_cpu = (struct cpufreq_available_cpus *) calloc(1, sizeof(struct cpufreq_available_cpus));
61 if (!new_cpu)
63 fprintf(stderr, "allocation failure!\n");
64 abort();
66 new_cpu->cpu_number = cpu_number;
67 new_cpu->dir_name = path;
68 new_cpu->next = NULL;
70 if (available_cpus)
71 { /* we navigate to the bottom of the list... */
72 struct cpufreq_available_cpus *curr_cpu = available_cpus;
73 for (; curr_cpu->next != NULL; curr_cpu=curr_cpu->next);
74 curr_cpu->next = new_cpu;
75 return;
78 available_cpus = new_cpu;
81 /* check CPUfreq support via the sysfs file system */
82 int check_cpufreq_2_6(void)
84 DIR *dir = opendir(SYSFS_CPU_BASE_DIR);
85 struct dirent *entry;
87 /* How many CPUs do we have? */
88 if (!dir) return 0;
89 while ((entry= readdir(dir)))
91 size_t len = 0;
92 char *line = NULL;
93 char *test;
94 char *filename;
95 FILE *fp;
97 if (!strcmp(entry->d_name, "." )) continue;
98 if (!strcmp(entry->d_name, "..")) continue;
99 if (strncmp(entry->d_name, "cpu", 3)) continue;
101 /* let's see wether this particular CPU has CPUfreq support... */
102 filename = StrApp((char**)NULL, SYSFS_CPU_BASE_DIR, "/", entry->d_name, "/cpufreq/", SYSFS_CPUFREQ_TEST, (char*)NULL);
103 fp = fopen(filename, "r");
104 if (!fp)
105 { /* no good... */
106 free(filename);
107 continue;
109 if (getline(&line, &len, fp) == -1)
110 { /* no good... */
111 free(filename);
112 fclose(fp);
113 continue;
115 fclose(fp);
116 test = (char *) calloc(strlen(line)+1, sizeof(char));
117 if (!test)
119 fprintf(stderr, "allocation failure!\n");
120 abort();
122 while (sscanf(line, "%s", test) != EOF)
123 /* let's see wether we can find a cpu number equal to our one in test file... */
124 if (!strcmp((entry->d_name)+3, test))
125 { /* Got it! */
126 int cpu_number = atoi(entry->d_name + 3) + 1;
127 add_to_cpus_list(cpu_number, StrApp((char**)NULL, SYSFS_CPU_BASE_DIR, "/", entry->d_name, "/cpufreq/", (char*)NULL));
128 break;
130 /* no good.. */
131 free(filename);
132 free(test);
133 free(line);
135 closedir(dir);
137 /* did we get results? */
138 if (available_cpus) return 1;
140 /* What a shame, all these CPU cycles for nothing! */
141 return 0;
144 /* Checks wether this machine supports CPU frequency scaling,
145 * and builds a list of CPUs available for that...
147 int check_cpufreq(void)
149 if (kernel_version == IS_2_6)
150 return check_cpufreq_2_6();
152 /* 2.4 kernels are not supported at the moment... */
154 return 0;
157 char *cpufreq_get_governor_2_6(int cpu)
159 struct cpufreq_available_cpus *curr_cpu = available_cpus;
160 char *filename;
161 FILE *fp;
162 size_t len = 0;
163 char *line = NULL;
164 char *test;
166 for (; curr_cpu!=NULL; curr_cpu=curr_cpu->next)
167 if (curr_cpu->cpu_number == cpu)
168 break;
170 if (curr_cpu->cpu_number != cpu) return NULL;
172 filename = StrApp((char**)NULL, curr_cpu->dir_name, SYSFS_CPUFREQ_SET_GOV, (char*)NULL);
173 fp = fopen(filename, "r");
175 if (!fp)
177 free(filename);
178 return NULL;
181 if (getline(&line, &len, fp) == -1)
183 fprintf(stderr, "could not read from file %s!\n", filename);
184 free(filename);
185 fclose(fp);
186 return NULL;
188 fclose(fp);
189 free(filename);
191 test = (char*) calloc(strlen(line)+1,sizeof(char));
192 if (!test)
194 fprintf(stderr, "failure allocating memory!\n");
195 abort();
197 if (sscanf(line, "%s", test) != 1)
199 free(test);
200 free(line);
201 return NULL;
203 free(line);
205 return test;
208 /* Get cpufreq governor of CPU #n, where 1<=n<=MAX, where MAX is
209 * the number of CPUs you have in your system
211 char *cpufreq_get_governor(int cpu)
213 if (cpu < 1) return NULL;
215 if (kernel_version == IS_2_6)
216 return cpufreq_get_governor_2_6(cpu);
218 /* 2.4 kernels are not supported at the moment... */
220 return NULL;
223 /* set CPUfreq governor via the sysfs file system */
224 int set_cpufreq_governor_2_6(char *governor)
226 struct cpufreq_available_cpus *curr_cpu=available_cpus;
227 int retval = 1;
229 /* Set desired governor for all available CPUs */
230 for (; curr_cpu!=NULL; curr_cpu=curr_cpu->next)
232 FILE *fp;
233 char *filename;
234 int supported = 0;
236 fprintf(stderr, "Setting CPU scaling governor \"%s\" for CPU %d...\n", governor, curr_cpu->cpu_number);
238 /* check wether this CPU supports the specified governor */
239 filename = StrApp((char**)NULL, curr_cpu->dir_name, SYSFS_CPUFREQ_AVAIL_GOV, (char*)NULL);
240 fp = fopen(filename, "r");
241 if (!fp)
243 fprintf(stderr, "could not open file %s!\n", filename);
244 free(filename);
245 retval = 0;
246 continue;
248 else
250 size_t len = 0;
251 char *line = NULL;
252 char *test;
253 int cont = 0;
255 if (getline(&line, &len, fp) == -1)
257 fprintf(stderr, "could not read from file %s!\n", filename);
258 free(filename);
259 fclose(fp);
260 retval = 0;
261 continue;
263 fclose(fp);
265 test = (char *) calloc(strlen(line)+1, sizeof(char));
266 if (!test)
268 fprintf(stderr, "failure allocating memory!\n");
269 abort();
272 while (sscanf(line+cont, "%s", test) != EOF)
274 if (!strcmp(test, governor))
276 supported = 1;
277 break;
279 cont = strstr(line, test) - line + strlen(test);
281 free(test);
282 free(line);
284 free(filename);
285 if (!supported)
287 fprintf(stderr, "sorry, this CPU does not support the speficied CPUfreq governor...\n");
288 retval = 0;
289 continue;
292 /* OK, let's set the specified governor for this CPU */
293 filename = StrApp((char**)NULL, curr_cpu->dir_name, SYSFS_CPUFREQ_SET_GOV, (char*)NULL);
295 fp = fopen(filename, "w");
296 if (!fp)
298 fprintf(stderr, "could not open file %s for writing!\n", filename);
299 free(filename);
300 retval = 0;
301 continue;
303 if (fprintf(fp, "%s", governor) <= 0)
305 fprintf(stderr, "failed writing to file %s!\n", filename);
306 free(filename);
307 fclose(fp);
308 retval = 0;
309 continue;
311 fclose(fp);
312 /* OK, we supposedly set our governor on this CPU, let's see wether it actually went through... */
313 fp = fopen(filename, "r");
314 if (!fp)
316 fprintf(stderr, "could not open file %s for reading!\n", filename);
317 free(filename);
318 retval = 0;
319 continue;
321 else
323 size_t len = 0;
324 char *line = NULL;
325 char *test;
327 if (getline(&line, &len, fp) == -1)
329 fprintf(stderr, "could not read from file %s!\n", filename);
330 free(filename);
331 fclose(fp);
332 retval = 0;
333 continue;
335 fclose(fp);
336 test = (char *) calloc(strlen(line)+1,sizeof(char));
337 if (!test)
339 fprintf(stderr, "failure allocating memory!\n");
340 abort();
342 if (sscanf(line, "%s", test) != 1)
344 fprintf(stderr, "could not read from file %s!\n", filename);
345 free(filename);
346 free(test);
347 free(line);
348 retval = 0;
349 continue;
351 free(line);
352 if (strcmp(test, governor))
354 fprintf(stderr, "failed setting specified CPUfreq governor!\n");
355 retval = 0;
357 free(test);
360 return retval;
364 /* Set cpufreq governor */
365 int cpufreq_set_governor(char *governor)
367 if (!governor) return 0;
368 if (!available_cpus) return 0;
369 if (!strlen(governor)) return 0;
371 if (kernel_version == IS_2_6)
372 return set_cpufreq_governor_2_6(governor);
375 /* 2.4 kernels are not supported at the moment */
377 return 0;