#define hwCLOCKdotC /* With hwCLOCKdotC defined, hwclock.h exports definitions of hwclock() and hwsec_per_clock() */ #include "hwclock.h" #if defined(__GNUC__) && __iX86__>=586 int _hwsec_per_clock_known; double _hwsec_per_clock; #ifdef USE_BOGOMIPS_FOR_TICK #define DEFAULT_BOGOMIPS 200.e6 static double bogomips_from_proc(){ FILE *fp = fopen("/proc/cpuinfo", "r"); char line[512]; if( fp == NULL ){ Warning("Can't open /proc/cpuinfo\n"); return DEFAULT_BOGOMIPS; } while( fgets(line, sizeof(line), fp) ){ char *bogo; int nscan; double bogomips; if( (bogo = strstr(line, "bogomips")) ){ /* sscanf should match any amount of whitespace around the : */ nscan = sscanf(bogo, "bogomips : %lf\n", &bogomips); if( nscan == 1 ){ fclose(fp); return bogomips*1.0e6; }else{ Warning("sscanf returns %d, on '%s' of /proc/cpuinfo bogomips line failed\n", nscan, line); fclose(fp); return DEFAULT_BOGOMIPS; /* let's just guess 200Mhz */ } } } Warning("Did not find bogomips in /proc/cpuinfo\n"); fclose(fp); return DEFAULT_BOGOMIPS; } double _get_hwsec_per_clock(void){ _hwsec_per_clock = bogomips_from_proc(); _hwsec_per_clock_known = 1; } #else /* USE_BOGOMIPS_FOR_TICK */ #define CALIBRATION_DELAY_MUSEC 100000 #include #include /* This will get called once during a program. It will call usleep with an arg of CALIBRATION_DELAY_MUSEC (currently 0.1sec). By using both hwclock() and gettimeofday() machinery to time the interval, we learn how big the hwclock ticks are */ double _get_hwsec_per_clock(void){ struct timeval tv1, tv2; hwclock_t hw1, hw2; double deltat; /* Gettimeofday, sleep for a tenth of a second, gettimeofday again. Should be pretty reasonable? */ gettimeofday(&tv1, NULL); hwclock(&hw1); usleep(CALIBRATION_DELAY_MUSEC); gettimeofday(&tv2, NULL); hwclock(&hw2); if(tv2.tv_usec < tv1.tv_usec ){ deltat = -1.0; tv2.tv_usec += 1000000; }else{ deltat = 0.0; } deltat += ((double)(tv2.tv_sec - tv1.tv_sec) + 1.e-6*(tv2.tv_usec - tv1.tv_usec)); _hwsec_per_clock = deltat / (hw2 - hw1); _hwsec_per_clock_known = 1; return _hwsec_per_clock; } #endif /* USE_BOGOMIPS_FOR_TICK */ #else /* defined( __iX86__ ) && defined(__GNUC__) */ /* Assume everything else can use gettimeofday(). After paying the expense of calling gettimeofday, there's not much point in worrying about a little arithmetic... */ #include #include #include void hwclock(hwclock_t *p){ struct timeval tv; gettimeofday(&tv, NULL); *p = (double)tv.tv_sec + 1.e-6*(tv.tv_usec); } double hwsec_per_clock(void){ return 1.0; } #endif #ifdef STANDALONE #include main(){ hwclock_t arr[20]; double max, min, sum, sum2, nsamp; int i; int verbose = 1; bzero(arr, sizeof(arr)); hwclock(arr); hwclock(arr+1); hwclock(arr+2); hwclock(arr+3); hwclock(arr+4); hwclock(arr+5); hwclock(arr+6); hwclock(arr+7); hwclock(arr+8); hwclock(arr+9); hwclock(arr+10); hwclock(arr+11); hwclock(arr+12); hwclock(arr+13); hwclock(arr+14); hwclock(arr+15); hwclock(arr+16); hwclock(arr+17); hwclock(arr+18); hwclock(arr+19); printf("hwsec_per_clock: %g sec\n", hwsec_per_clock()); max = -1.e38; min = 1.e38; sum = 0.; sum2 = 0.; for(i=1; i<20; i++){ double diff; printf("%" HWC_FMT "\n", arr[i]); diff = (double)(arr[i] - arr[i-1]); if( diff > max ) max = diff; if( diff < min ) min = diff; sum += diff; sum2 += diff*diff; } nsamp = 19.; printf("minimum timer interval(ticks) mean=%g, max=%g, min=%g, std.dev = %g\n", sum/nsamp, max, min, sqrt( (sum2 - sum*sum/nsamp)/(nsamp-1) )); } #endif