{
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;
}
}
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;
}
}
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)
{
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
#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 */
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 */
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)
{
int k, i, j, o = 0;
SilcBool success;
- if (argc <= 1) {
- fprintf(stderr, "Usage: ./test_silcmutex <cpu_freq_mhz>\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;
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);