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
23 * @version $Id: debug.c 17143 2008-01-02 20:56:33Z beck $
41 #define WIN32_LEAN_AND_MEAN
45 /* Win32 timer value. */
47 unsigned lo_prec; /**< 32bit low precision time in milli seconds */
48 LARGE_INTEGER hi_prec; /**< 64bit high precision time in micro seconds */
53 #define HAVE_GETTIMEOFDAY
56 * Just, if we have gettimeofday()
57 * Someday, we will have a check here.
64 /* Linux timer value. */
65 typedef struct timeval ir_timer_val_t;
71 static INLINE void _time_get(ir_timer_val_t *val);
72 static INLINE void _time_reset(ir_timer_val_t *val);
73 static INLINE unsigned long _time_to_msec(const ir_timer_val_t *val);
74 static INLINE ir_timer_val_t *_time_add(ir_timer_val_t *res,
75 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
76 static INLINE ir_timer_val_t *_time_sub(ir_timer_val_t *res,
77 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
83 ir_timer_val_t elapsed; /**< the elapsed time so far */
84 ir_timer_val_t start; /**< the start value of the timer */
85 ir_timer_t *link; /**< link to the next entry in the timer stack */
86 const char *name; /**< the name of the timer used for identification */
87 const char *desc; /**< a description if the timer */
88 unsigned running : 1; /**< set if this timer is running */
94 static int ir_timer_cmp(const void *a, const void *b, size_t size)
96 const ir_timer_t *t1 = a;
97 const ir_timer_t *t2 = b;
99 return strcmp(t1->name, t2->name);
102 /** The set containing all currently registered timers. */
103 static set *timers = NULL;
105 /** The top of the timer stack */
106 static ir_timer_t *timer_stack;
108 /** Initialize the timer module. */
109 static void timing_init(void)
111 timers = new_set(ir_timer_cmp, 16);
115 ir_timer_t *ir_timer_register(const char *name, const char *desc)
117 unsigned hash = HASH_STR(name, strlen(name));
120 _time_reset(&timer.elapsed);
121 _time_reset(&timer.start);
130 return set_insert(timers, &timer, sizeof(timer), hash);
133 #ifdef HAVE_GETTIMEOFDAY
135 static INLINE void _time_get(ir_timer_val_t *val)
137 gettimeofday(val, NULL);
140 static INLINE void _time_reset(ir_timer_val_t *val)
145 static INLINE unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
147 return (unsigned long) elapsed->tv_sec * 1000UL
148 + (unsigned long) elapsed->tv_usec / 1000UL;
151 static INLINE unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
153 return (unsigned long) elapsed->tv_sec * 1000000UL
154 + (unsigned long) elapsed->tv_usec;
157 static INLINE ir_timer_val_t *_time_add(ir_timer_val_t *res,
158 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
160 timeradd(lhs, rhs, res);
164 static INLINE ir_timer_val_t *_time_sub(ir_timer_val_t *res,
165 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
167 timersub(lhs, rhs, res);
171 #elif defined(_WIN32)
173 static INLINE void _time_get(ir_timer_val_t *val)
175 if(!QueryPerformanceCounter(&val->hi_prec))
176 val->lo_prec = timeGetTime();
179 static INLINE void _time_reset(ir_timer_val_t *val)
181 memset(val, 0, sizeof(val[0]));
184 static INLINE unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
188 if(!QueryPerformanceFrequency(&freq))
189 return (unsigned long) elapsed->lo_prec;
191 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
194 static INLINE unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
198 if(!QueryPerformanceFrequency(&freq))
199 return (unsigned long) elapsed->lo_prec;
201 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
204 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)
207 if(QueryPerformanceFrequency(&dummy))
208 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
210 res->lo_prec = lhs->lo_prec + rhs->lo_prec;
215 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)
218 if(QueryPerformanceFrequency(&dummy))
219 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
221 res->lo_prec = lhs->lo_prec - rhs->lo_prec;
228 #if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
230 #include <sys/types.h>
233 static struct sched_param std_sched_param;
234 static int std_sched_param_init = 0;
236 int ir_timer_enter_high_priority(void)
238 pid_t pid = getpid();
240 struct sched_param p;
243 if(!std_sched_param_init) {
244 res = sched_getparam(pid, &std_sched_param);
245 std_sched_param_init = 1;
248 algo = sched_getscheduler(pid);
249 max = sched_get_priority_max(algo);
251 memcpy(&p, &std_sched_param, sizeof(p));
252 p.sched_priority = max;
253 res = sched_setparam(pid, &p);
258 int ir_timer_leave_high_priority(void)
261 pid_t pid = getpid();
263 if(std_sched_param_init)
264 res = sched_setparam(pid, &std_sched_param);
269 #elif defined(_WIN32)
271 static int initial_priority = THREAD_PRIORITY_NORMAL;
273 int ir_timer_leave_high_priority(void)
276 if(!SetThreadPriority(GetCurrentThread(), initial_priority)) {
277 fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
278 res = GetLastError();
284 int ir_timer_enter_high_priority(void)
287 initial_priority = GetThreadPriority(GetCurrentThread());
288 if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
289 fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
290 res = GetLastError();
299 int ir_timer_enter_high_priority(void)
301 fprintf(stderr, "POSIX scheduling API not present\n");
305 int ir_timer_leave_high_priority(void)
316 size_t ir_get_heap_used_bytes(void)
318 struct mallinfo mi = mallinfo();
322 #elif defined(_WIN32) /* __linux__ */
326 size_t ir_get_heap_used_bytes(void)
331 hinfo._pentry = NULL;
332 while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
333 res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
339 size_t ir_get_heap_used_bytes(void)
341 fprintf(stderr, "function not implemented\n");
348 void ir_timer_reset(ir_timer_t *timer)
350 _time_reset(&timer->elapsed);
351 _time_reset(&timer->start);
356 void ir_timer_start(ir_timer_t *timer)
358 _time_reset(&timer->start);
359 _time_get(&timer->start);
363 void ir_timer_reset_and_start(ir_timer_t *timer)
365 _time_reset(&timer->elapsed);
366 ir_timer_start(timer);
369 /* stop a running timer */
370 void ir_timer_stop(ir_timer_t *timer)
372 /* If the timer is running stop, measure the time and add it to the
380 _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
381 _time_reset(&timer->start);
385 /* push a timer on the stack */
386 int ir_timer_push(ir_timer_t *timer)
390 timer->link = timer_stack;
392 ir_timer_stop(timer_stack);
393 ir_timer_start(timer);
398 /* pop a timer from the stack */
399 ir_timer_t *ir_timer_pop(void)
401 ir_timer_t *timer = timer_stack;
403 ir_timer_stop(timer);
404 timer_stack = timer->link;
407 ir_timer_start(timer_stack);
412 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
415 const ir_timer_val_t *elapsed = &timer->elapsed;
420 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
422 return _time_to_msec(elapsed);
425 unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
428 const ir_timer_val_t *elapsed = &timer->elapsed;
433 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
435 return _time_to_usec(elapsed);
438 const char *ir_timer_get_name(const ir_timer_t *timer) {
442 const char *ir_timer_get_description(const ir_timer_t *timer) {