/* hpTime.c Standalone test of the hires timer code from _lsprof4.c. Usage: hpTime [] where is a optional sleep time in seconds. Use 0 to see the overhead of hpTimer function calls. The _lsprof4.c code has been duplicated and slightly modified to exercise various builds and use an unsigned 64-bit type for hires timer values. Sample build and output on: 1. RHEL 3 update 7 $ gcc -v ... gcc version 4.1.2 $ gcc -O3 -o hpTime hpTime.c $ hpTime test: sleeping for 1 secs (x86) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 2623443435 ticks or 1.003745268 secs $ hpTime 4 test: sleeping for 4 secs (x86) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 10471388967 ticks or 4.006422886 secs $ hpTime 0 test: sleeping for 0 secs (x86) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 19 ticks or 0.000000007 secs 2. RHEL 3 update 7, 64-bit $ gcc -v ... gcc version 4.1.2 $ gcc -O3 -m64 -o hpTime hpTime.c $ hpTime test: sleeping for 1 secs (x86) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 2618620695 ticks or 1.001902958 secs $ hpTime 5 test: sleeping for 5 secs (x86) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 13091450026 ticks or 5.008889191 secs [jbrouwers@localhost ~]$ hpTime 0 test: sleeping for 0 secs (x86) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 21 ticks or 0.000000008 secs 3. RHEL 3 update 7, rdtscll $ gcc -v ... gcc version 4.1.2 $ gcc -DRDTSCLL -O3 -o hpTime hpTime.c $ hpTime test: sleeping for 1 secs (rdtscll) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 2638513000 ticks or 1.009563887 secs $ hpTime 5 test: sleeping for 5 secs (rdtscll) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 13069212486 ticks or 5.000604024 secs $ hpTime 0 test: sleeping for 0 secs (rdtscll) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 18 ticks or 0.000000007 secs 4. RHEL 3 update 7, 64-bit rdtscll $ gcc -v ... gcc version 4.1.2 $ gcc -DRDTSCLL -m64 -O3 -o hpTime hpTime.c $ hpTime test: sleeping for 1 secs (rdtscll) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 2637057449 ticks or 1.008977073 secs $ hpTime 6 test: sleeping for 6 secs (rdtscll) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 15690711956 ticks or 6.003505371 secs $ hpTime 0 test: sleeping for 0 secs (rdtscll) ... resolution 0.383 nsecs/tick (2.614 GHz) sleep time 18 ticks or 0.000000007 secs 5. CentOS 4.5 (Final) $ gcc -v ... gcc version 3.4.6 20060404 (Red Hat 3.4.6-8) $ gcc -O3 -o hpTime hpTime.c $ hpTime test: sleeping for 1 secs (x86) ... resolution 0.834 nsecs/tick (1.199 GHz) sleep time 1200391272 ticks or 1.001197414 secs $ hpTime 5 test: sleeping for 5 secs (x86) ... resolution 0.834 nsecs/tick (1.199 GHz) sleep time 5995248528 ticks or 5.000414272 secs $ hpTime 0 test: sleeping for 0 secs (x86) ... resolution 0.834 nsecs/tick (1.199 GHz) sleep time 128 ticks or 0.000000107 secs 6. CentOS 4.7 (Final), xVM 2.2.2 VirtualBox $ gcc -v ... gcc version 3.4.6 20060404 (Red Hat 3.4.6-10) $ gcc -O3 -o hpTime hpTime.c $ hpTime test: sleeping for 1 secs (x86) ... resolution 0.545 nsecs/tick (1.836 GHz) sleep time 1841023884 ticks or 1.002718521 secs $ hpTime 8 test: sleeping for 8 secs (x86) ... resolution 0.543 nsecs/tick (1.840 GHz) sleep time 14725436693 ticks or 8.001291819 secs $ hpTime 0 test: sleeping for 0 secs (x86) ... resolution 0.545 nsecs/tick (1.834 GHz) sleep time 1691 ticks or 0.000000922 secs 7. MacOS X 10.4.11 Tiger (Core Duo Intel) % gcc -v ... Target: i686-apple-darwin8 gcc version 4.0.1 (Apple Computer, Inc. build 5367) % gcc -O3 -o hpTime hpTime.c % hpTime test: sleeping for 1 secs (TB) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 1000045727 ticks or 1.000045727 secs % hpTime 4 test: sleeping for 4 secs (TB) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 4000040117 ticks or 4.000040117 secs % hpTime 0 test: sleeping for 0 secs (TB) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 96 ticks or 0.000000096 secs % sysctl hw.tbfrequency hw.tbfrequency: 1000000000 8. MacOS X 10.3.9 Panther (PowerPC) % gcc -v ... gcc version 3.3 20030304 (Apple Computer, Inc. build 1671) % gcc -O3 -o hpTime hpTime.c % hpTime test: sleeping for 1 secs (TB) ... resolution 40.145 nsecs/tick (0.025 GHz) sleep time 24911770 ticks or 1.000085830 secs % hpTime 5 test: sleeping for 5 secs (TB) ... resolution 40.145 nsecs/tick (0.025 GHz) sleep time 124549562 ticks or 5.000056283 secs % hpTime 0 test: sleeping for 0 secs (TB) ... resolution 40.145 nsecs/tick (0.025 GHz) sleep time 6 ticks or 0.000000241 secs % sysctl hw.tbfrequency hw.tbfrequency: 24909600 9. MacOS X 10.3.9 Panther (PowerPC asm) % gcc -v ... gcc version 3.3 20030304 (Apple Computer, Inc. build 1671) % gcc -U__APPLE__ -O5 -o hpTime hpTime.c % hpTime test: sleeping for 1 secs (ppc) ... resolution 40.146 nsecs/tick (0.025 GHz) sleep time 24911901 ticks or 1.000122135 secs % hpTime 7 test: sleeping for 7 secs (ppc) ... resolution 40.145 nsecs/tick (0.025 GHz) sleep time 174368953 ticks or 7.000065822 secs % hpTime 0 test: sleeping for 0 secs (ppc) ... resolution 40.144 nsecs/tick (0.025 GHz) sleep time 2 ticks or 0.000000161 secs 10. Solaris 10 (Opteron) > cc -V cc: Sun C 5.8 2005/10/13 > cc -DSOLARIS -xO3 -o hpTime hpTime.c > hpTime test: sleeping for 1 secs (hrtime) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 1007477233 ticks or 1.007477233 secs > hpTime 6 test: sleeping for 6 secs (hrtime) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 6000725228 ticks or 6.000725228 secs > hpTime 0 test: sleeping for 0 secs (hrtime) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 178 ticks or 0.000000178 secs 11. Solaris 10 (Opteron), 64-bit > cc -V cc: Sun C 5.8 2005/10/13 > cc -xarch=amd64 -DSOLARIS -xO3 -o hpTime hpTime.c > hpTime test: sleeping for 1 secs (hrtime) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 1009813958 ticks or 1.009813958 secs > hpTime 6 test: sleeping for 6 secs (hrtime) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 6001179611 ticks or 6.001179611 secs > hpTime 0 test: sleeping for 0 secs (hrtime) ... resolution 1.000 nsecs/tick (1.000 GHz) sleep time 171 ticks or 0.000000171 secs */ #include #include #ifdef MS_WINDOWS # define HPTIME "PC" # define hpTime_t long long /* ? */ # include static hpTime_t hpTimer(void) { LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart; } static double hpTimerUnit(void) { LARGE_INTEGER li; if (QueryPerformanceFrequency(&li)) return 1.0 / li.QuadPart; else return 0.000001; /* unlikely */ } #elif defined(__APPLE__) /* Use MacOS X time base (TB) available for Intel and PowerPC. See example 7.41 timebase_demo.c from the book "MacOS X Internals" by Amit Singh, , and . */ # define HPTIME "TB" # define hpTime_t u_int64_t # include # include static hpTime_t /* return TB as ticks */ hpTimer(void) { return (hpTime_t)mach_absolute_time(); } static double /* return TB resolution as secs/tick */ hpTimerUnit(void) { mach_timebase_info_data_t info; info.denom = info.numer = 0; if (mach_timebase_info(&info) == KERN_SUCCESS && info.denom && info.numer) { /* TB info ratio is nanosec ticks */ return 1.0e-9 * (double)info.numer / (double)info.denom; } else return 1.0e-9; /* unlikely */ } #elif defined(SOLARIS) || defined(__hppa) || defined(hppa) /* means HP_UX? */ /* Solaris and HP-UX both provide a function gethrtime returning a 64-bit time stamp with nanosec resolution */ # define HPTIME "hrtime" # define hpTime_t hrtime_t # include /* sleep */ # include static hpTime_t hpTimer(void) { return (hpTime_t)gethrtime(); } static double hpTimerUnit(void) { return 1.0e-9; /* nanosec ticks */ } #else /* !MS_WINDOWS && !__APPLE__ && !SOLARIS && !HP_UX */ # define hpTime_t unsigned long long # include /* ? */ # include # ifdef RDTSCLL /* some Linux distros */ # include # endif # ifdef GETTIMEOFDAY_NO_TZ # define _LSPROF_TV(tv) (!gettimeofday(&tv) \ ? (((hpTime_t)tv.tv_sec * 1000000) + \ (hpTime_t)tv.tv_usec) \ : (hpTime_t)++tv.tv_sec) /* unlikely */ # else # define _LSPROF_TV(tv) (!gettimeofday(&tv, (struct timezone *)NULL) \ ? (((hpTime_t)tv.tv_sec * 1000000) + \ (hpTime_t)tv.tv_usec) \ : (hpTime_t)++tv.tv_sec) /* unlikely */ # endif # ifdef __GNUC__ /* or PYCC_GCC? */ # define _LSPROF_TSC 1 /* try time stamp count (TSC or TB) */ # else # undef _LSPROF_TSC /* no TSC */ # endif static hpTime_t hpTimer (void) { hpTime_t t; # if defined(_LSPROF_TSC) && defined(rdtscll) # define HPTIME "rdtscll" /* rdtscll() is defined in of certain, recent Linux distros */ rdtscll(t); # elif defined(_LSPROF_TSC) && (defined(__i386__) || defined(__x86_64__)) # define HPTIME "x86" unsigned int hi, lo; __asm__ __volatile__ ( "rdtsc \n\t" : "=a"(lo), "=d"(hi) : ); t = (((hpTime_t)hi) << 32) | lo; # elif defined(_LSPROF_TSC) && (defined(__ppc64__) || defined(__POWERPC64__)) # define HPTIME "ppc64" __asm__ __volatile__ ( "mftb %0 \n\t" : "=r"(t) : ); # elif defined(_LSPROF_TSC) && (defined(__ppc__) || defined(__POWERPC__)) unsigned int hi, lo, hj; # define HPTIME "ppc" /* avoid label (causes duplicate symbols for -O3 and above with older GNU C compilers) */ do { __asm__ __volatile__ ( "mftbu %0 \n\t" "mftb %1 \n\t" "mftbu %2 \n\t" : "=r"(hi), "=r"(lo), "=r"(hj) : ); } while (hi != hj); t = (((hpTime_t)hi) << 32) | lo; # else /* gettimeofday as usec ticks */ # define HPTIME "GTOD" struct timeval tv; t = _LSPROF_TV(tv); # undef _LSPROF_TSC /* no TSC*/ # endif return (t); } # ifdef _LSPROF_TSC /* start ticks and time, set at initialzation in init_lsprof */ static hpTime_t hpTime0 = 0; static hpTime_t usTime0 = 0; static double hpTimerUnit(void) { /* determine TSC resolution by waiting an add'l 250 usecs since initialization */ struct timeval tv; hpTime_t hp, us, usTime1; usTime1 = usTime0 + 250000; do { hp = hpTimer(); us = _LSPROF_TV(tv); /* reset on wrap around of any */ if (hpTime0 > hp || usTime0 > us || usTime0 >= usTime1) { hpTime0 = hp; usTime0 = us; usTime1 = us + 250000; } } while (us <= usTime1 || hp <= hpTime0); return 1.0e-6 * (double)(us - usTime0) / (double)(hp - hpTime0); } # else /* !_LSPROF_TSC */ static double hpTimerUnit(void) { return 1.0e-6; /* usec ticks */ } # endif /* _LSPROF_TSC */ #endif int main(int argc, char **argv) { hpTime_t t, d; double r, Hz; int s = 1; /* default sleep time */ #ifdef _LSPROF_TSC struct timeval tv; int w = 4; /* warm up */ while (w-- > 0) hpTime0 = hpTimer(); usTime0 = _LSPROF_TV(tv); #endif /* _LSPROF_TSC */ if (argc == 2) { /* */ int a = atoi(argv[1]); if (a >= 0 && a <= 60) s = a; } printf("test: sleeping for %d secs (%s) ...\n", s, HPTIME); t = hpTimer(); if (s > 0) sleep(s); d = hpTimer() - t; r = hpTimerUnit(); Hz = r ? (1.0 / r) : 0.0; printf("resolution %.3f nsecs/tick (%.3f GHz)\n", r * 1.0e9, (double)Hz * 1.0e-9); printf("sleep time %llu ticks or %.9f secs\n", d, r * (double)d); exit(0); }