2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief platform neutral timing utilities
34 #define WIN32_LEAN_AND_MEAN
38 /* Win32 timer value. */
40 unsigned lo_prec; /**< 32bit low precision time in milli seconds */
41 LARGE_INTEGER hi_prec; /**< 64bit high precision time in micro seconds */
47 #define HAVE_GETTIMEOFDAY
50 * Just, if we have gettimeofday()
51 * Someday, we will have a check here.
58 /* Linux timer value. */
59 typedef struct timeval ir_timer_val_t;
65 static inline void _time_reset(ir_timer_val_t *val);
71 ir_timer_val_t elapsed; /**< the elapsed time so far */
72 ir_timer_val_t start; /**< the start value of the timer */
73 ir_timer_t *parent; /**< parent of a timer */
74 ir_timer_t *displaced; /**< former timer in case of timer_push */
75 unsigned running : 1; /**< set if this timer is running */
78 /** The top of the timer stack */
79 static ir_timer_t *timer_stack;
81 ir_timer_t *ir_timer_new(void)
83 ir_timer_t *timer = XMALLOCZ(ir_timer_t);
84 _time_reset(&timer->elapsed);
85 _time_reset(&timer->start);
89 void ir_timer_free(ir_timer_t *timer)
94 #ifdef HAVE_GETTIMEOFDAY
96 static inline void _time_get(ir_timer_val_t *val)
98 gettimeofday(val, NULL);
101 static inline void _time_reset(ir_timer_val_t *val)
106 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
108 return (unsigned long) elapsed->tv_sec * 1000UL
109 + (unsigned long) elapsed->tv_usec / 1000UL;
112 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
114 return (unsigned long) elapsed->tv_sec * 1000000UL
115 + (unsigned long) elapsed->tv_usec;
118 static inline double _time_to_sec(const ir_timer_val_t *elapsed)
120 return (double)elapsed->tv_sec + (double)elapsed->tv_usec / 1000000.0;
123 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
124 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
126 timeradd(lhs, rhs, res);
130 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
131 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
133 timersub(lhs, rhs, res);
137 #elif defined(_WIN32)
139 static inline void _time_get(ir_timer_val_t *val)
141 if (!QueryPerformanceCounter(&val->hi_prec))
142 val->lo_prec = timeGetTime();
145 static inline void _time_reset(ir_timer_val_t *val)
147 memset(val, 0, sizeof(val[0]));
150 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
154 if (!QueryPerformanceFrequency(&freq))
155 return (unsigned long) elapsed->lo_prec;
157 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
160 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
164 if (!QueryPerformanceFrequency(&freq))
165 return (unsigned long) elapsed->lo_prec * 1000;
167 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
170 static inline double _time_to_sec(const ir_timer_val_t *elapsed)
174 if (!QueryPerformanceFrequency(&freq))
175 return (double) elapsed->lo_prec / 1000.;
177 return (double)elapsed->hi_prec.QuadPart / (double)freq.QuadPart;
180 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res, const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
183 if (QueryPerformanceFrequency(&dummy))
184 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
186 res->lo_prec = lhs->lo_prec + rhs->lo_prec;
191 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res, const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
194 if (QueryPerformanceFrequency(&dummy))
195 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
197 res->lo_prec = lhs->lo_prec - rhs->lo_prec;
204 #if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
206 #include <sys/types.h>
209 static struct sched_param std_sched_param;
210 static int std_sched_param_init = 0;
212 int ir_timer_enter_high_priority(void)
214 pid_t pid = getpid();
216 struct sched_param p;
219 if (!std_sched_param_init) {
220 res = sched_getparam(pid, &std_sched_param);
223 std_sched_param_init = 1;
226 algo = sched_getscheduler(pid);
227 max = sched_get_priority_max(algo);
230 p.sched_priority = max;
231 res = sched_setparam(pid, &p);
236 int ir_timer_leave_high_priority(void)
239 pid_t pid = getpid();
241 if (std_sched_param_init)
242 res = sched_setparam(pid, &std_sched_param);
247 #elif defined(_WIN32)
249 static int initial_priority = THREAD_PRIORITY_NORMAL;
251 int ir_timer_leave_high_priority(void)
254 if (!SetThreadPriority(GetCurrentThread(), initial_priority)) {
255 fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
256 res = GetLastError();
262 int ir_timer_enter_high_priority(void)
265 initial_priority = GetThreadPriority(GetCurrentThread());
266 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
267 fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
268 res = GetLastError();
277 int ir_timer_enter_high_priority(void)
279 fprintf(stderr, "POSIX scheduling API not present\n");
283 int ir_timer_leave_high_priority(void)
294 size_t ir_get_heap_used_bytes(void)
296 struct mallinfo mi = mallinfo();
300 #elif defined(_WIN32) /* __linux__ */
304 size_t ir_get_heap_used_bytes(void)
309 hinfo._pentry = NULL;
310 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
311 res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
317 size_t ir_get_heap_used_bytes(void)
319 fprintf(stderr, "function not implemented\n");
326 void ir_timer_reset(ir_timer_t *timer)
328 _time_reset(&timer->elapsed);
329 _time_reset(&timer->start);
334 void ir_timer_start(ir_timer_t *timer)
337 panic("timer started twice");
339 _time_reset(&timer->start);
340 _time_get(&timer->start);
343 if (timer->parent == NULL) {
344 timer->parent = timer_stack;
345 } else if (timer->parent != timer_stack) {
346 panic("timer used at different stack positions");
351 void ir_timer_reset_and_start(ir_timer_t *timer)
353 _time_reset(&timer->elapsed);
354 ir_timer_start(timer);
357 void ir_timer_stop(ir_timer_t *timer)
360 panic("attempting to stop stopped timer");
361 if (timer != timer_stack)
362 panic("timer stack error");
363 timer_stack = timer->parent;
370 _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
373 void ir_timer_init_parent(ir_timer_t *timer)
377 if (timer->parent != NULL && timer->parent != timer_stack)
378 panic("timer parent mismatch");
379 timer->parent = timer_stack;
382 void ir_timer_push(ir_timer_t *timer)
385 panic("timer started twice");
387 ir_timer_t *parent = timer->parent;
388 if (timer->parent == NULL)
389 panic("pushing timer with unknown parent");
391 timer->displaced = timer_stack;
392 for (ir_timer_t *t = timer_stack; t != parent; t = t->parent) {
394 panic("parent timer not on stack");
397 timer_stack = parent;
399 ir_timer_start(timer);
402 static void start_stack(ir_timer_t *timer, ir_timer_t *stop)
406 start_stack(timer->parent, stop);
407 ir_timer_start(timer);
410 void ir_timer_pop(ir_timer_t *timer)
413 panic("attempting to stop stopped timer");
414 ir_timer_t *displaced = timer->displaced;
415 if (displaced == NULL)
416 panic("timer start/stop/push/pop mismatch");
418 ir_timer_t *parent = timer->parent;
419 timer->displaced = NULL;
421 ir_timer_stop(timer);
422 start_stack(displaced, parent);
425 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
428 const ir_timer_val_t *elapsed = &timer->elapsed;
430 if (timer->running) {
433 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
435 return _time_to_msec(elapsed);
438 unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
441 const ir_timer_val_t *elapsed = &timer->elapsed;
443 if (timer->running) {
446 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
448 return _time_to_usec(elapsed);
451 double ir_timer_elapsed_sec(const ir_timer_t *timer)
454 const ir_timer_val_t *elapsed = &timer->elapsed;
456 if (timer->running) {
459 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
461 return _time_to_sec(elapsed);