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 33static unsigned int cpunum = 0; 34 35static 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 46static 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 68static unsigned int get_randnum(unsigned int max) 69{ 70 return (unsigned int)((float)max * (rand() / (RAND_MAX + 1.0))); 71} 72 73static 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 128int 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 189out: 190 printf("Exiting with return code %d.\n", ret); 191 fflush(stdout); 192 return ret; 193} 194