5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2007 - 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /****h* silcutil/Timer Interface
24 * SILC Timer interface provides a simple way to measure time intervals.
25 * The SILC Timer works with microsecond resolution, depending on platform.
27 * The interface also provides utility functions to get currenet CPU tick
28 * count and to delay process/thread execution.
32 * SilcTimerStruct timer;
34 * silc_timer_start(&timer);
36 * silc_timer_stop(&timer);
37 * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec);
44 /****s* silcutil/SilcTimer
48 * typedef struct SilcTimerObject *SilcTimer, SilcTimerStruct;
52 * The timer context. The context is given as argument to all
53 * silc_timer_* functions.
56 /****s* silcutil/SilcTimerStruct
60 * typedef struct SilcTimerObject *SilcTimer, SilcTimerStruct;
64 * The timer context. The context is given as argument to all
65 * silc_timer_* functions.
68 typedef struct SilcTimerObject *SilcTimer, SilcTimerStruct;
70 /****f* silcutil/silc_timer_start
74 * SilcBool silc_timer_start(SilcTimer timer);
78 * Starts the timer. If the timer is already running this will reset
79 * the timer and continue.
83 * SilcTimerStruct timer;
85 * silc_timer_start(&timer);
87 * silc_timer_stop(&timer);
88 * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec);
91 void silc_timer_start(SilcTimer timer);
93 /****f* silcutil/silc_timer_stop
97 * void silc_timer_stop(SilcTimer timer);
101 * Stop the timer. The elapsed time can be retrieved by calling the
102 * silc_timer_value function.
105 void silc_timer_stop(SilcTimer timer);
107 /****f* silcutil/silc_timer_continue
111 * void silc_timer_continue(SilcTimer timer);
115 * Continue stopped timer. If timer is running already this does nothing.
118 void silc_timer_continue(SilcTimer timer);
120 /****f* silcutil/silc_timer_value
124 * void silc_timer_value(SilcTimer timer,
125 * SilcUInt64 *elapsed_time_seconds,
126 * SilcUInt32 *elapsed_time_microseconds);
130 * Returns either the current value or the end value of the timer. If the
131 * timer is currently running this returns the currently elapsed time. If
132 * the timer is stopped this returns the cumulative elapsed time.
135 void silc_timer_value(SilcTimer timer,
136 SilcUInt64 *elapsed_time_seconds,
137 SilcUInt32 *elapsed_time_microseconds);
139 /****f* silcutil/silc_timer_value_time
143 * void silc_timer_value_time(SilcTimer timer, SilcTime ret_time);
147 * Same as silc_timer_value but returns the elapsed time to `ret_time'
148 * SilcTime structure as absolute date and time. This is useful if the
149 * returned time needs to be converted into some other format such as
150 * time and date strings.
153 void silc_timer_value_time(SilcTimer timer, SilcTime ret_time);
155 /****f* silcutil/silc_timer_start_time
159 * void silc_timer_start_time(SilcTimer timer, SilcTime ret_start_time);
163 * Returns the timer's start time into `ret_start_time' SilcTime structure.
166 void silc_timer_start_time(SilcTimer timer, SilcTime ret_start_time);
168 /****f* silcutil/silc_timer_is_running
172 * SilcBool silc_timer_is_running(SilcTimer timer);
176 * Returns TRUE if the timer is currently running, FALSE otherwise.
179 SilcBool silc_timer_is_running(SilcTimer timer);
181 #include "silctimer_i.h"
183 /****f* silcutil/silc_timer_tick
187 * SilcUInt64 silc_timer_tick(SilcTimer &timer, SilcBool adjust)
191 * Returns the current CPU tick count. You should call the
192 * silc_timer_synchronize before using this function to make sure the
193 * overhead of measuring the CPU tick count is not included in the
194 * tick count. If the `adjust' is TRUE and the silc_timer_synchronize
195 * has been called the returned value is adjusted to be more accurate.
199 * // Synchronize timer for more accurate CPU tick counts
200 * silc_timer_synchronize(&timer);
201 * start = silc_timer_tick(&timer, FALSE);
203 * stop = silc_timer_tick(&timer, TRUE);
208 SilcUInt64 silc_timer_tick(SilcTimer timer, SilcBool adjust)
210 #if defined(__GNUC__) || defined(__ICC)
211 #if defined(SILC_I486)
213 asm volatile ("rdtsc" : "=A" (x));
214 return adjust ? x - timer->sync_tdiff : x;
216 #elif defined(SILC_X86_64)
219 asm volatile ("rdtsc" : "=a" (lo), "=d" (hi));
220 x = ((SilcUInt64)lo | ((SilcUInt64)hi << 32));
221 return adjust ? x - timer->sync_tdiff : x;
223 #elif defined(SILC_POWERPC)
224 SilcUInt32 hi, lo, tmp;
225 asm volatile ("0: \n\t"
231 : "=r" (hi), "=r" (lo), "=r" (tmp));
232 x = ((SilcUInt64)lo | ((SilcUInt64)hi << 32));
233 return adjust ? x - timer->sync_tdiff : x;
237 #endif /* SILC_I486 */
239 #elif defined(SILC_WIN32)
244 #endif /* __GNUC__ || __ICC */
247 /****f* silcutil/silc_timer_synchronize
251 * void silc_timer_synchronize(SilcTimer timer);
255 * Synchronizes the `timer'. This call will attempt to synchronize the
256 * timer for more accurate results with high resolution timing. Call
257 * this before you start using the `timer'.
261 * // Synchronize timer
262 * silc_timer_synchronize(&timer);
263 * silc_timer_start(&timer);
264 * ... time passes ...
265 * silc_timer_stop(&timer);
266 * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec);
271 void silc_timer_synchronize(SilcTimer timer)
273 SilcUInt32 tdiff, cumu, i;
276 /* Sync normal timer */
277 for (i = 0, cumu = 0; i < 5; i++) {
278 silc_timer_start(timer);
279 silc_timer_stop(timer);
280 silc_timer_value(timer, NULL, &tdiff);
284 timer->sync_diff = cumu;
285 if (timer->sync_diff > 5)
286 timer->sync_diff /= 5;
288 /* Sync CPU tick count */
290 t1 = silc_timer_tick(timer, FALSE);
291 t2 = silc_timer_tick(timer, FALSE);
293 t1 = silc_timer_tick(timer, FALSE);
294 t2 = silc_timer_tick(timer, FALSE);
296 t1 = silc_timer_tick(timer, FALSE);
297 t2 = silc_timer_tick(timer, FALSE);
300 timer->sync_tdiff = cumu / 3;
302 t1 = silc_timer_tick(timer, FALSE);
303 t2 = silc_timer_tick(timer, TRUE);
304 timer->sync_tdiff += (int)(t2 - t1);
307 /****f* silcutil/silc_usleep
311 * void silc_usleep(unsigned long microseconds);
315 * Delays the execution of process/thread for the specified amount of
316 * time, which is in microseconds.
320 * The delay is only approximate and on some platforms the resolution is
321 * in fact milliseconds.
324 void silc_usleep(unsigned long microseconds);
326 #endif /* SILCTIMER_H */