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 $
29 #include "firm_config.h"
43 #define WIN32_LEAN_AND_MEAN
47 /* Win32 timer value. */
49 unsigned lo_prec; /**< 32bit low precision time in milli seconds */
50 LARGE_INTEGER hi_prec; /**< 64bit high precision time in micro seconds */
55 #define HAVE_GETTIMEOFDAY
58 * Just, if we have gettimeofday()
59 * Someday, we will have a check here.
66 /* Linux timer value. */
67 typedef struct timeval ir_timer_val_t;
73 static INLINE void _time_get(ir_timer_val_t *val);
74 static INLINE void _time_reset(ir_timer_val_t *val);
75 static INLINE unsigned long _time_to_msec(const ir_timer_val_t *val);
76 static INLINE ir_timer_val_t *_time_add(ir_timer_val_t *res,
77 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
78 static INLINE ir_timer_val_t *_time_sub(ir_timer_val_t *res,
79 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
85 ir_timer_val_t elapsed; /**< the elapsed time so far */
86 ir_timer_val_t start; /**< the start value of the timer */
87 ir_timer_t *link; /**< link to the next entry in the timer stack */
88 const char *name; /**< the name of the timer used for identification */
89 const char *desc; /**< a description if the timer */
90 unsigned running : 1; /**< set if this timer is running */
96 static int ir_timer_cmp(const void *a, const void *b, size_t size)
98 const ir_timer_t *t1 = a;
99 const ir_timer_t *t2 = b;
101 return strcmp(t1->name, t2->name);
104 /** The set containing all currently registered timers. */
105 static set *timers = NULL;
107 /** The top of the timer stack */
108 static ir_timer_t *timer_stack;
110 /** Initialize the timer module. */
111 static void timing_init(void)
113 timers = new_set(ir_timer_cmp, 16);
117 ir_timer_t *ir_timer_register(const char *name, const char *desc)
119 unsigned hash = HASH_STR(name, strlen(name));
122 _time_reset(&timer.elapsed);
123 _time_reset(&timer.start);
132 return set_insert(timers, &timer, sizeof(timer), hash);
135 #ifdef HAVE_GETTIMEOFDAY
137 static INLINE void _time_get(ir_timer_val_t *val)
139 gettimeofday(val, NULL);
142 static INLINE void _time_reset(ir_timer_val_t *val)
147 static INLINE unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
149 return (unsigned long) elapsed->tv_sec * 1000UL
150 + (unsigned long) elapsed->tv_usec / 1000UL;
153 static INLINE unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
155 return (unsigned long) elapsed->tv_sec * 1000000UL
156 + (unsigned long) elapsed->tv_usec;
159 static INLINE ir_timer_val_t *_time_add(ir_timer_val_t *res,
160 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
162 timeradd(lhs, rhs, res);
166 static INLINE ir_timer_val_t *_time_sub(ir_timer_val_t *res,
167 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
169 timersub(lhs, rhs, res);
173 #elif defined(_WIN32)
175 static INLINE void _time_get(ir_timer_val_t *val)
177 if(!QueryPerformanceCounter(&val->hi_prec))
178 val->lo_prec = timeGetTime();
181 static INLINE void _time_reset(ir_timer_val_t *val)
183 memset(val, 0, sizeof(val[0]));
186 static INLINE unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
190 if(!QueryPerformanceFrequency(&freq))
191 return (unsigned long) elapsed->lo_prec;
193 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
196 static INLINE unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
200 if(!QueryPerformanceFrequency(&freq))
201 return (unsigned long) elapsed->lo_prec;
203 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
206 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)
209 if(QueryPerformanceFrequency(&dummy))
210 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
212 res->lo_prec = lhs->lo_prec + rhs->lo_prec;
217 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)
220 if(QueryPerformanceFrequency(&dummy))
221 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
223 res->lo_prec = lhs->lo_prec - rhs->lo_prec;
230 #if _XOPEN_REALTIME != -1
232 #include <sys/types.h>
235 static struct sched_param std_sched_param;
236 static int std_sched_param_init = 0;
238 int ir_timer_enter_high_priority(void)
240 pid_t pid = getpid();
242 struct sched_param p;
245 if(!std_sched_param_init) {
246 res = sched_getparam(pid, &std_sched_param);
247 std_sched_param_init = 1;
250 algo = sched_getscheduler(pid);
251 max = sched_get_priority_max(algo);
253 memcpy(&p, &std_sched_param, sizeof(p));
254 p.sched_priority = max;
255 res = sched_setparam(pid, &p);
260 int ir_timer_leave_high_priority(void)
263 pid_t pid = getpid();
265 if(std_sched_param_init)
266 res = sched_setparam(pid, &std_sched_param);
271 #elif defined(_WIN32)
273 static int initial_priority = THREAD_PRIORITY_NORMAL;
275 int ir_timer_leave_high_priority(void)
278 if(!SetThreadPriority(GetCurrentThread(), initial_priority)) {
279 fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
280 res = GetLastError();
286 int ir_timer_enter_high_priority(void)
289 initial_priority = GetThreadPriority(GetCurrentThread());
290 if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
291 fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
292 res = GetLastError();
301 int ir_timer_enter_high_priority(void)
303 fprintf(stderr, "POSIX scheduling API not present\n");
307 int ir_timer_leave_high_priority(void)
318 size_t ir_get_heap_used_bytes(void)
320 struct mallinfo mi = mallinfo();
324 #elif defined(_WIN32) /* __linux__ */
328 size_t ir_get_heap_used_bytes(void)
333 hinfo._pentry = NULL;
334 while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
335 res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
341 size_t ir_get_heap_used_bytes(void)
343 fprintf(stderr, "function not implemented\n");
350 void ir_timer_reset(ir_timer_t *timer)
352 _time_reset(&timer->elapsed);
353 _time_reset(&timer->start);
358 void ir_timer_start(ir_timer_t *timer)
360 _time_reset(&timer->start);
361 _time_get(&timer->start);
365 void ir_timer_reset_and_start(ir_timer_t *timer)
367 _time_reset(&timer->elapsed);
368 ir_timer_start(timer);
371 /* stop a running timer */
372 void ir_timer_stop(ir_timer_t *timer)
374 /* If the timer is running stop, measure the time and add it to the
382 _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
383 _time_reset(&timer->start);
387 /* push a timer on the stack */
388 int ir_timer_push(ir_timer_t *timer)
392 timer->link = timer_stack;
394 ir_timer_stop(timer_stack);
395 ir_timer_start(timer);
400 /* pop a timer from the stack */
401 ir_timer_t *ir_timer_pop(void)
403 ir_timer_t *timer = timer_stack;
405 ir_timer_stop(timer);
406 timer_stack = timer->link;
409 ir_timer_start(timer_stack);
414 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
417 const ir_timer_val_t *elapsed = &timer->elapsed;
422 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
424 return _time_to_msec(elapsed);
427 unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
430 const ir_timer_val_t *elapsed = &timer->elapsed;
435 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
437 return _time_to_usec(elapsed);
440 const char *ir_timer_get_name(const ir_timer_t *timer) {
444 const char *ir_timer_get_description(const ir_timer_t *timer) {