/*I'm trying to get a reliable method of calculating processor mhz. If . you can read & compile C . you know what your system's actual clock rate is . you have 10 minutes then please compile and run the following small program and tell me if it works. Please try it with "cc -O" (but if it doesn't work, try "cc"). In either case, please tell me . your cpu type (alpha, mips, whatever) . your cpu mhz . your model number (Indigo 2, etc) . the C compiler you used and the options you used If it didn't work, please add "-S" to the command line and also send me mhz.s. If you want to debug it yourself, note that the program runs an unrolled loop and measures that cost. If the compiler optimizes out the unrolled loop (which it could) then I need to try more tricks to defeat the optimization. Thanks much. */ /* * mhz.c - calculate clock rate and megahertz * * Usage: mhz [-c] * * The sparc specific code is to get around a feature of SuperSPARC * that does two adds in one clock. Apparently, only SuperSPARC does this. * Thanks to John Mashey (mash@sgi.com) for explaining SuperSPARC to me. * * The AIX specific code is because the C compiler on rs6000s does not * respect the register directive. "a" below is a stack variable and * there are two instructions per increment instead of one. * Please note that this may not be correct for other AIX systems. * * Copyright (c) 1994 Larry McVoy. Distributed under the FSF GPL with * additional restriction that results may published only if * (1) the benchmark is unmodified, and * (2) the version in the sccsid below is included in the report. * Support for this development by Sun Microsystems is gratefully acknowledged. */ char *id = "$Id: mhz.c,v 1.2 1996/05/30 07:33:07 lm Exp lm $\n"; #include #include #define ENOUGH 1000000 static struct timeval start_tv, stop_tv; void start() { (void) gettimeofday(&start_tv, (struct timezone *) 0); } void tvsub(tdiff, t1, t0) struct timeval *tdiff, *t1, *t0; { tdiff->tv_sec = t1->tv_sec - t0->tv_sec; tdiff->tv_usec = t1->tv_usec - t0->tv_usec; if (tdiff->tv_usec < 0) tdiff->tv_sec--, tdiff->tv_usec += 1000000; } unsigned long stop() { struct timeval tdiff; (void) gettimeofday(&stop_tv, (struct timezone *) 0); tvsub(&tdiff, &stop_tv, &start_tv); return (tdiff.tv_sec * 1000000 + tdiff.tv_usec); } int N; main(ac, av) char **av; { double adj, mhz; int i; N = 0; do { if (!N) { N = 1000000; } else { /* * Adjust the amount of time proportional to how * far we need to go. We want ENOUGH/i to be ~1. * * For systems with low resolution clocks, i can * be 0 or very close to 0. We don't know how * much time we spent, it could be anywhere from * 1 to 9999 usecs. We pretend it was 1000 usecs. * The 129 value is because some systems bump the * timeval each time you call gettimeofday(). */ if (i <= 129) { i = 1000; } adj = (ENOUGH * 1.5)/i; /* printf("N=%d i=%d adjust=%.5f\n", N, i, adj); */ N *= adj; } i = loop(1); } while (i < ENOUGH); /* * We figure that the loop overhead is about 5 instructions out of 1000. * So we figure that we acually execute N * 1.005 instructions. */ mhz = (N * 1.005) / i; if (ac == 2 && !strcmp(av[1], "-c")) { printf("%.4f\n", 1000 / mhz); } else { printf("%.0f Mhz, %.2f nanosec clock\n", mhz, 1000 / mhz); } exit(0); } loop(reg) register reg; { register i, a; /* time empty loop */ a = i = N - 1000; start(); while (i > 0) { #ifdef _AIX /* really for the rs6000 only */ # define FOUR a++; a++; #endif #ifdef sparc # define FOUR a >>= reg; a >>= reg; a >>= reg; a >>= reg; #endif #if !defined(sparc) && !defined(_AIX) # define FOUR a += reg; a += reg; a += reg; a += reg; #endif #define TWENTY FOUR FOUR FOUR FOUR FOUR #define H TWENTY TWENTY TWENTY TWENTY TWENTY H H H H H H H H H H i -= 1000; } i = stop(a); return (i); }