/** * Program to exercise CPU frequency switching via sysfs. * You probably want to turn on userspace switching and disable * powernowd/cpuspeed/powersaved programs. */ /* * Copyright (C) 2003-2006 IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <stdlib.h> static unsigned int cpunum = 0; static int check_writable(const char *fname) { int fd; fd = open(fname, O_WRONLY); if (fd >= 0) close(fd); return fd >= 0; } static int seed_random(void) { int fp; long seed; fp = open("/dev/urandom", O_RDONLY); if (fp < 0) { perror("/dev/urandom"); return 0; } if (read(fp, &seed, sizeof(seed)) != sizeof(seed)) { perror("read random seed"); return 0; } close(fp); srand(seed); return 1; } static unsigned int get_randnum(unsigned int max) { return (unsigned int)((float)max * (rand() / (RAND_MAX + 1.0))); } static int set_cpuspeed(const char *ctrlfile, unsigned int speed) { int fd, x; unsigned int y; char buf[256]; /* First try to write a new speed. */ fd = open(ctrlfile, O_WRONLY); if (fd < 0) { perror(ctrlfile); return 0; } printf("CPU %d speed set to %u kHz.\n", cpunum, speed); fflush(stdout); x = snprintf(buf, 256, "%u\n", speed); x = write(fd, buf, x); if (x == 0) { perror("Setting new speed"); close(fd); return 0; } close(fd); /* Sleep for a while */ usleep(500000); /* Now try to read the speed */ fd = open(ctrlfile, O_RDONLY); if (fd < 0) { perror(ctrlfile); return 0; } x = read(fd, buf, 256); if (x == 0) { perror("Reading speed"); close(fd); return 0; } close(fd); y = atoi(buf); if (y != speed) { printf("ERROR: Set CPU %d speed to %u but speed is now %u!\n", cpunum, speed, y); fflush(stdout); return -1; } return 1; } int main(int argc, char *argv[]) { const char *ctrl; unsigned int rounds; unsigned int *frequencies; int y; unsigned int x, num_freqs; int ret = 0; /* Usage: cpufreq control_file rounds [frequencies...] */ if (argc < 6) { printf ("Usage: %s control_file rounds cpunum [frequencies...]\n", argv[0]); ret = 1; goto out; } /* copy command line args */ ctrl = argv[1]; if (!check_writable(ctrl)) { perror(ctrl); ret = 2; goto out; } rounds = atoi(argv[2]); cpunum = atoi(argv[3]); num_freqs = argc - 4; frequencies = calloc(num_freqs, sizeof(unsigned int)); if (frequencies == NULL) { perror("Error allocating memory"); ret = 3; goto out; } for (x = 4; x < argc; x++) { frequencies[x - 4] = atoi(argv[x]); } /* Now run program. */ printf("Running %u loops with these %d frequencies:\n", rounds, num_freqs); for (x = 0; x < num_freqs; x++) { printf("%u KHz\n", frequencies[x]); } fflush(stdout); seed_random(); for (x = rounds; x > 0; x--) { y = get_randnum(num_freqs); y = set_cpuspeed(ctrl, frequencies[y]); if (y != 1) { ret = 4; goto out; } } out: printf("Exiting with return code %d.\n", ret); fflush(stdout); return ret; }