5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2007 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/SILC 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.
29 * SilcTimerStruct timer;
31 * silc_timer_start(&timer);
33 * silc_timer_stop(&timer);
34 * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec);
41 /****s* silcutil/SilcTimerAPI/SilcTimer
45 * typedef struct SilcTimerObject *SilcTimer, SilcTimerStruct;
49 * The timer context. The context is given as argument to all
50 * silc_timer_* functions.
53 typedef struct SilcTimerObject *SilcTimer, SilcTimerStruct;
55 /****f* silcutil/SilcTimerAPI/silc_timer_start
59 * SilcBool silc_timer_start(SilcTimer timer);
63 * Starts the timer. If the timer is already running this will reset
64 * the timer and continue.
68 * SilcTimerStruct timer;
70 * silc_timer_start(&timer);
72 * silc_timer_stop(&timer);
73 * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec);
76 void silc_timer_start(SilcTimer timer);
78 /****f* silcutil/SilcTimerAPI/silc_timer_stop
82 * void silc_timer_stop(SilcTimer timer);
86 * Stop the timer. The elapsed time can be retrieved by calling the
87 * silc_timer_value function.
90 void silc_timer_stop(SilcTimer timer);
92 /****f* silcutil/SilcTimerAPI/silc_timer_continue
96 * void silc_timer_continue(SilcTimer timer);
100 * Continue stopped timer. If timer is running already this does nothing.
103 void silc_timer_continue(SilcTimer timer);
105 /****f* silcutil/SilcTimerAPI/silc_timer_value
109 * void silc_timer_value(SilcTimer timer,
110 * SilcUInt64 *elapsed_time_seconds,
111 * SilcUInt32 *elapsed_time_microseconds);
115 * Returns either the current value or the end value of the timer. If the
116 * timer is currently running this returns the currently elapsed time. If
117 * the timer is stopped this returns the cumulative elapsed time.
120 void silc_timer_value(SilcTimer timer,
121 SilcUInt64 *elapsed_time_seconds,
122 SilcUInt32 *elapsed_time_microseconds);
124 /****f* silcutil/SilcTimerAPI/silc_timer_value_time
128 * void silc_timer_value_time(SilcTimer timer, SilcTime ret_time);
132 * Same as silc_timer_value but returns the elapsed time to `ret_time'
133 * SilcTime structure as absolute date and time. This is useful if the
134 * returned time needs to be converted into some other format such as
135 * time and date strings.
138 void silc_timer_value_time(SilcTimer timer, SilcTime ret_time);
140 /****f* silcutil/SilcTimerAPI/silc_timer_start_time
144 * void silc_timer_start_time(SilcTimer timer, SilcTime ret_start_time);
148 * Returns the timer's start time into `ret_start_time' SilcTime structure.
151 void silc_timer_start_time(SilcTimer timer, SilcTime ret_start_time);
153 /****f* silcutil/SilcTimerAPI/silc_timer_is_running
157 * SilcBool silc_timer_is_running(SilcTimer timer);
161 * Returns TRUE if the timer is currently running, FALSE otherwise.
164 SilcBool silc_timer_is_running(SilcTimer timer);
166 #include "silctimer_i.h"
168 /****f* silcutil/SilcTimerAPI/silc_timer_tick
172 * SilcUInt64 silc_timer_tick(SilcTimer &timer, SilcBool adjust)
176 * Returns the current CPU tick count. You should call the
177 * silc_timer_synchronize before using this function to make sure the
178 * overhead of measuring the CPU tick count is not included in the
179 * tick count. If the `adjust' is TRUE and the silc_timer_synchronize
180 * has been called the returned value is adjusted to be more accurate.
184 * // Synchronize timer for more accurate CPU tick counts
185 * silc_timer_synchronize(&timer);
186 * start = silc_timer_tick(&timer, FALSE);
188 * stop = silc_tiemr_tick(&timer, TRUE);
193 SilcUInt64 silc_timer_tick(SilcTimer timer, SilcBool adjust)
195 #if defined(__GNUC__) || defined(__ICC)
198 asm volatile ("rdtsc" : "=A" (x));
199 return adjust ? x - timer->sync_tdiff : x;
204 asm volatile ("rdtsc" : "=a" (lo), "=d" (hi));
205 x = ((SilcUInt64)lo | ((SilcUInt64)hi << 32));
206 return adjust ? x - timer->sync_tdiff : x;
209 SilcUInt32 hi, lo, tmp;
210 asm volatile ("0: \n\t"
216 : "=r" (hi), "=r" (lo), "=r" (tmp));
217 x = ((SilcUInt64)lo | ((SilcUInt64)hi << 32));
218 return adjust ? x - timer->sync_tdiff : x;
219 #endif /* SILC_I486 */
221 #elif defined(SILC_WIN32)
226 #endif /* __GNUC__ || __ICC */
229 /****f* silcutil/SilcTimerAPI/silc_timer_synchronize
233 * void silc_timer_synchronize(SilcTimer timer);
237 * Synchronizes the `timer'. This call will attempt to synchronize the
238 * timer for more accurate results with high resolution timing. Call
239 * this before you start using time `timer'.
243 * // Synchronized timer
244 * silc_timer_synchronize(&timer);
245 * silc_timer_start(&timer);
246 * ... time passes ...
247 * silc_timer_stop(&timer);
248 * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec);
253 void silc_timer_synchronize(SilcTimer timer)
255 SilcUInt32 tdiff, cumu, i;
258 /* Sync normal timer */
259 for (i = 0, cumu = 0; i < 5; i++) {
260 silc_timer_start(timer);
261 silc_timer_stop(timer);
262 silc_timer_value(timer, NULL, &tdiff);
266 timer->sync_diff = cumu;
267 if (timer->sync_diff > 5)
268 timer->sync_diff /= 5;
270 /* Sync CPU tick count */
272 t1 = silc_timer_tick(timer, FALSE);
273 t2 = silc_timer_tick(timer, FALSE);
275 t1 = silc_timer_tick(timer, FALSE);
276 t2 = silc_timer_tick(timer, FALSE);
278 t1 = silc_timer_tick(timer, FALSE);
279 t2 = silc_timer_tick(timer, FALSE);
282 timer->sync_tdiff = cumu / 3;
284 t1 = silc_timer_tick(timer, FALSE);
285 t2 = silc_timer_tick(timer, TRUE);
286 timer->sync_tdiff += (int)(t2 - t1);
289 #endif /* SILCTIMER_H */