From: Pekka Riikonen Date: Sat, 1 Sep 2007 09:25:58 +0000 (+0000) Subject: Added silc_timer_tick and silc_timer_synchronize. X-Git-Tag: 1.2.beta1~134 X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=commitdiff_plain;h=ab2995608e4061f88231bdba3f1f5f2709503701 Added silc_timer_tick and silc_timer_synchronize. --- diff --git a/lib/silcutil/silctimer.c b/lib/silcutil/silctimer.c index 90371274..3973752e 100644 --- a/lib/silcutil/silctimer.c +++ b/lib/silcutil/silctimer.c @@ -25,12 +25,13 @@ void silc_timer_start(SilcTimer timer) { struct timeval curtime; - memset(timer, 0, sizeof(timer)); - silc_gettimeofday(&curtime); timer->start_sec = curtime.tv_sec; timer->start_usec = curtime.tv_usec; - + timer->timer_sec = 0; + timer->timer_usec = 0; + timer->sync_diff = 0; + timer->sync_tdiff = 0; timer->running = TRUE; } @@ -48,6 +49,7 @@ void silc_timer_stop(SilcTimer timer) } timer->timer_sec = curtime.tv_sec - timer->start_sec; timer->timer_usec = curtime.tv_usec - timer->start_usec; + timer->timer_usec -= timer->sync_diff; timer->running = FALSE; } @@ -90,6 +92,7 @@ void silc_timer_value(SilcTimer timer, } timer->timer_sec = curtime.tv_sec - timer->start_sec; timer->timer_usec = curtime.tv_usec - timer->start_usec; + timer->timer_usec -= timer->sync_diff; } if (elapsed_time_seconds) @@ -125,3 +128,40 @@ SilcBool silc_timer_is_running(SilcTimer timer) { return timer->running; } + +#if 0 +void silc_timer_synchronize(SilcTimer timer) +{ + SilcUInt32 tdiff, cumu, i; + SilcUInt64 t1, t2, tcumu; + + /* Sync normal timer */ + for (i = 0, cumu = 0; i < 5; i++) { + silc_timer_start(timer); + silc_timer_stop(timer); + silc_timer_value(timer, NULL, &tdiff); + cumu += tdiff; + } + + timer->sync_diff = cumu; + if (timer->sync_diff > 5) + timer->sync_diff /= 5; + + /* Sync CPU tick count */ + tcumu = 0; + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, FALSE); + tcumu += (t2 - t1); + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, FALSE); + tcumu += (t2 - t1); + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, FALSE); + tcumu += (t2 - t1); + timer->sync_tdiff = tcumu / 3; + + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, TRUE); + timer->sync_tdiff += (int)(t2 - t1); +} +#endif diff --git a/lib/silcutil/silctimer.h b/lib/silcutil/silctimer.h index c53da041..845b46a7 100644 --- a/lib/silcutil/silctimer.h +++ b/lib/silcutil/silctimer.h @@ -165,4 +165,125 @@ SilcBool silc_timer_is_running(SilcTimer timer); #include "silctimer_i.h" +/****f* silcutil/SilcTimerAPI/silc_timer_tick + * + * SYNOPSIS + * + * SilcUInt64 silc_timer_tick(SilcTimer &timer, SilcBool adjust) + * + * DESCRIPTION + * + * Returns the current CPU tick count. You should call the + * silc_timer_synchronize before using this function to make sure the + * overhead of measuring the CPU tick count is not included in the + * tick count. If the `adjust' is TRUE and the silc_timer_synchronize + * has been called the returned value is adjusted to be more accurate. + * + * EXAMPLES + * + * // Synchronize timer for more accurate CPU tick counts + * silc_timer_synchronize(&timer); + * start = silc_timer_tick(&timer, FALSE); + * do_something(); + * stop = silc_tiemr_tick(&timer, TRUE); + * + ***/ + +static inline +SilcUInt64 silc_timer_tick(SilcTimer timer, SilcBool adjust) +{ +#if defined(__GNUC__) || defined(__ICC) +#ifdef SILC_I486 + SilcUInt64 x; + asm volatile ("rdtsc" : "=A" (x)); + return adjust ? x - timer->sync_tdiff : x; + +#elif SILC_X86_64 + SilcUInt64 x; + SilcUInt32 hi, lo; + asm volatile ("rdtsc" : "=a" (lo), "=d" (hi)); + x = ((SilcUInt64)lo | ((SilcUInt64)hi << 32)); + return adjust ? x - timer->sync_tdiff : x; + +#elif SILC_POWERPC + SilcUInt32 hi, lo, tmp; + asm volatile ("0: \n\t" + "mftbu %0 \n\t" + "mftb %1 \n\t" + "mftbu %2 \n\t" + "cmpw %2,%0 \n\t" + "bne 0b \n" + : "=r" (hi), "=r" (lo), "=r" (tmp)); + x = ((SilcUInt64)lo | ((SilcUInt64)hi << 32)); + return adjust ? x - timer->sync_tdiff : x; +#endif /* SILC_I486 */ + +#elif defined(SILC_WIN32) + __asm rdtsc + +#else + return 0; +#endif /* __GNUC__ || __ICC */ +} + +/****f* silcutil/SilcTimerAPI/silc_timer_synchronize + * + * SYNOPSIS + * + * void silc_timer_synchronize(SilcTimer timer); + * + * DESCRIPTION + * + * Synchronizes the `timer'. This call will attempt to synchronize the + * timer for more accurate results with high resolution timing. Call + * this before you start using time `timer'. + * + * EXAMPLE + * + * // Synchronized timer + * silc_timer_synchronize(&timer); + * silc_timer_start(&timer); + * ... time passes ... + * silc_timer_stop(&timer); + * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec); + * + ***/ + +static inline +void silc_timer_synchronize(SilcTimer timer) +{ + SilcUInt32 tdiff, cumu, i; + SilcUInt64 t1, t2; + + /* Sync normal timer */ + for (i = 0, cumu = 0; i < 5; i++) { + silc_timer_start(timer); + silc_timer_stop(timer); + silc_timer_value(timer, NULL, &tdiff); + cumu += (int)tdiff; + } + + timer->sync_diff = cumu; + if (timer->sync_diff > 5) + timer->sync_diff /= 5; + + /* Sync CPU tick count */ + cumu = 0; + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, FALSE); + cumu += (t2 - t1); + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, FALSE); + cumu += (t2 - t1); + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, FALSE); + cumu += (t2 - t1); + + timer->sync_tdiff = cumu / 3; + + t1 = silc_timer_tick(timer, FALSE); + t2 = silc_timer_tick(timer, TRUE); + timer->sync_tdiff += (int)(t2 - t1); +} + #endif /* SILCTIMER_H */ diff --git a/lib/silcutil/silctimer_i.h b/lib/silcutil/silctimer_i.h index 3709f4f9..cefaac04 100644 --- a/lib/silcutil/silctimer_i.h +++ b/lib/silcutil/silctimer_i.h @@ -29,7 +29,9 @@ struct SilcTimerObject { SilcUInt64 timer_sec; /* Timer seconds */ SilcUInt32 start_usec; /* Start microseconds */ SilcUInt32 timer_usec; /* Timer microseconds */ - unsigned int running : 1; /* Set when timer is running */ + unsigned int running : 1; /* Set when timer is running */ + unsigned int sync_diff : 15; /* Synchronization delta */ + unsigned int sync_tdiff : 16; /* Synchronization tick delta */ }; #endif /* SILCTIMER_I_H */ diff --git a/lib/silcutil/tests/test_silcmutex.c b/lib/silcutil/tests/test_silcmutex.c index 4b1a732b..49367adb 100644 --- a/lib/silcutil/tests/test_silcmutex.c +++ b/lib/silcutil/tests/test_silcmutex.c @@ -16,47 +16,9 @@ typedef struct { SilcMutex mutex; SilcUInt64 cpu_freq = 0; int max_locks, max_locks2; +SilcTimerStruct timer; -/* RDTSC */ -#ifdef SILC_I486 -static __inline__ unsigned long long rdtsc(void) -{ - unsigned long long int x; - __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); - return x; -} - -#elif SILC_X86_64 -typedef unsigned long long int unsigned long long; -static __inline__ unsigned long long rdtsc(void) -{ - unsigned hi, lo; - __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); - return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); -} - -#elif SILC_POWERPC -typedef unsigned long long int unsigned long long; -static __inline__ unsigned long long rdtsc(void) -{ - unsigned long long int result = 0; - unsigned long int upper, lower,tmp; - __asm__ volatile( - "0: \n" - "\tmftbu %0 \n" - "\tmftb %1 \n" - "\tmftbu %2 \n" - "\tcmpw %2,%0 \n" - "\tbne 0b \n" - : "=r"(upper),"=r"(lower),"=r"(tmp) - ); - result = upper; - result = result << 32; - result = result | lower; - - return result; -} -#endif +#define rdtsc() silc_timer_tick(&timer) void *mutex_thread(void *context) { @@ -117,13 +79,12 @@ int main(int argc, char **argv) int k, i, j, o = 0; SilcBool success; - if (argc <= 1) { - fprintf(stderr, "Usage: ./test_silcmutex \n"); - fprintf(stderr, "Example: ./test_silcmutex 3000\n"); - exit(1); - } - cpu_freq = (SilcUInt64)atoi(argv[1]); - cpu_freq *= 1000; /* Will give us milliseconds */ + silc_timer_synchronize(&timer); + val = rdtsc(); + sleep(1); + val = rdtsc() - val; + val /= 1000; /* Gives us milliseconds */ + fprintf(stderr, "CPU frequency: %llu\n", val); max_locks = MAX_LOCKS; diff --git a/lib/silcutil/tests/test_silctimer.c b/lib/silcutil/tests/test_silctimer.c index f7354d3b..11e17ed3 100644 --- a/lib/silcutil/tests/test_silctimer.c +++ b/lib/silcutil/tests/test_silctimer.c @@ -73,6 +73,10 @@ int main(int argc, char **argv) if (!schedule) goto err; + silc_timer_synchronize(&timer); + SILC_LOG_DEBUG(("sync_diff: %d", timer.sync_diff)); + SILC_LOG_DEBUG(("sync_tdiff: %d", timer.sync_tdiff)); + SILC_LOG_DEBUG(("Start timer")); silc_timer_start(&timer);