1 /**
2 * Program to exercise CPU frequency switching via sysfs.
3 * You probably want to turn on userspace switching and disable
4 * powernowd/cpuspeed/powersaved programs.
5 */
6
7 /*
8 * Copyright (C) 2003-2006 IBM
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 * 02111-1307, USA.
24 */
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32
33 static unsigned int cpunum = 0;
34
check_writable(const char * fname)35 static int check_writable(const char *fname)
36 {
37 int fd;
38
39 fd = open(fname, O_WRONLY);
40 if (fd >= 0)
41 close(fd);
42
43 return fd >= 0;
44 }
45
seed_random(void)46 static int seed_random(void)
47 {
48 int fp;
49 long seed;
50
51 fp = open("/dev/urandom", O_RDONLY);
52 if (fp < 0) {
53 perror("/dev/urandom");
54 return 0;
55 }
56
57 if (read(fp, &seed, sizeof(seed)) != sizeof(seed)) {
58 perror("read random seed");
59 return 0;
60 }
61
62 close(fp);
63 srand(seed);
64
65 return 1;
66 }
67
get_randnum(unsigned int max)68 static unsigned int get_randnum(unsigned int max)
69 {
70 return (unsigned int)((float)max * (rand() / (RAND_MAX + 1.0)));
71 }
72
set_cpuspeed(const char * ctrlfile,unsigned int speed)73 static int set_cpuspeed(const char *ctrlfile, unsigned int speed)
74 {
75 int fd, x;
76 unsigned int y;
77 char buf[256];
78
79 /* First try to write a new speed. */
80 fd = open(ctrlfile, O_WRONLY);
81 if (fd < 0) {
82 perror(ctrlfile);
83 return 0;
84 }
85
86 printf("CPU %d speed set to %u kHz.\n", cpunum, speed);
87 fflush(stdout);
88
89 x = snprintf(buf, 256, "%u\n", speed);
90 x = write(fd, buf, x);
91
92 if (x == 0) {
93 perror("Setting new speed");
94 close(fd);
95 return 0;
96 }
97 close(fd);
98
99 /* Sleep for a while */
100 usleep(500000);
101
102 /* Now try to read the speed */
103 fd = open(ctrlfile, O_RDONLY);
104 if (fd < 0) {
105 perror(ctrlfile);
106 return 0;
107 }
108
109 x = read(fd, buf, 256);
110 if (x == 0) {
111 perror("Reading speed");
112 close(fd);
113 return 0;
114 }
115 close(fd);
116
117 y = atoi(buf);
118 if (y != speed) {
119 printf("ERROR: Set CPU %d speed to %u but speed is now %u!\n",
120 cpunum, speed, y);
121 fflush(stdout);
122 return -1;
123 }
124
125 return 1;
126 }
127
main(int argc,char * argv[])128 int main(int argc, char *argv[])
129 {
130 const char *ctrl;
131 unsigned int rounds;
132 unsigned int *frequencies;
133 int y;
134 unsigned int x, num_freqs;
135 int ret = 0;
136
137 /* Usage: cpufreq control_file rounds [frequencies...] */
138 if (argc < 6) {
139 printf
140 ("Usage: %s control_file rounds cpunum [frequencies...]\n",
141 argv[0]);
142 ret = 1;
143 goto out;
144 }
145
146 /* copy command line args */
147 ctrl = argv[1];
148 if (!check_writable(ctrl)) {
149 perror(ctrl);
150 ret = 2;
151 goto out;
152 }
153
154 rounds = atoi(argv[2]);
155 cpunum = atoi(argv[3]);
156
157 num_freqs = argc - 4;
158 frequencies = calloc(num_freqs, sizeof(unsigned int));
159 if (frequencies == NULL) {
160 perror("Error allocating memory");
161 ret = 3;
162 goto out;
163 }
164
165 for (x = 4; x < argc; x++) {
166 frequencies[x - 4] = atoi(argv[x]);
167 }
168
169 /* Now run program. */
170 printf("Running %u loops with these %d frequencies:\n", rounds,
171 num_freqs);
172 for (x = 0; x < num_freqs; x++) {
173 printf("%u KHz\n", frequencies[x]);
174 }
175
176 fflush(stdout);
177
178 seed_random();
179
180 for (x = rounds; x > 0; x--) {
181 y = get_randnum(num_freqs);
182 y = set_cpuspeed(ctrl, frequencies[y]);
183 if (y != 1) {
184 ret = 4;
185 goto out;
186 }
187 }
188
189 out:
190 printf("Exiting with return code %d.\n", ret);
191 fflush(stdout);
192 return ret;
193 }
194