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 $
39 #define WIN32_LEAN_AND_MEAN
43 /* Win32 timer value. */
45 unsigned lo_prec; /**< 32bit low precision time in milli seconds */
46 LARGE_INTEGER hi_prec; /**< 64bit high precision time in micro seconds */
51 #define HAVE_GETTIMEOFDAY
54 * Just, if we have gettimeofday()
55 * Someday, we will have a check here.
62 /* Linux timer value. */
63 typedef struct timeval ir_timer_val_t;
69 static inline void _time_get(ir_timer_val_t *val);
70 static inline void _time_reset(ir_timer_val_t *val);
71 static inline unsigned long _time_to_msec(const ir_timer_val_t *val);
72 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
73 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
74 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
75 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
81 ir_timer_val_t elapsed; /**< the elapsed time so far */
82 ir_timer_val_t start; /**< the start value of the timer */
83 ir_timer_t *link; /**< link to the next entry in the timer stack */
84 const char *name; /**< the name of the timer used for identification */
85 const char *desc; /**< a description if the timer */
86 unsigned running : 1; /**< set if this timer is running */
92 static int ir_timer_cmp(const void *a, const void *b, size_t size)
94 const ir_timer_t *t1 = a;
95 const ir_timer_t *t2 = b;
97 return strcmp(t1->name, t2->name);
100 /** The set containing all currently registered timers. */
101 static set *timers = NULL;
103 /** The top of the timer stack */
104 static ir_timer_t *timer_stack;
106 /** Initialize the timer module. */
107 static void timing_init(void)
109 timers = new_set(ir_timer_cmp, 16);
113 ir_timer_t *ir_timer_register(const char *name, const char *desc)
115 unsigned hash = HASH_STR(name, strlen(name));
118 _time_reset(&timer.elapsed);
119 _time_reset(&timer.start);
128 return set_insert(timers, &timer, sizeof(timer), hash);
131 #ifdef HAVE_GETTIMEOFDAY
133 static inline void _time_get(ir_timer_val_t *val)
135 gettimeofday(val, NULL);
138 static inline void _time_reset(ir_timer_val_t *val)
143 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
145 return (unsigned long) elapsed->tv_sec * 1000UL
146 + (unsigned long) elapsed->tv_usec / 1000UL;
149 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
151 return (unsigned long) elapsed->tv_sec * 1000000UL
152 + (unsigned long) elapsed->tv_usec;
155 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
156 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
158 timeradd(lhs, rhs, res);
162 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
163 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
165 timersub(lhs, rhs, res);
169 #elif defined(_WIN32)
171 static inline void _time_get(ir_timer_val_t *val)
173 if(!QueryPerformanceCounter(&val->hi_prec))
174 val->lo_prec = timeGetTime();
177 static inline void _time_reset(ir_timer_val_t *val)
179 memset(val, 0, sizeof(val[0]));
182 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
186 if(!QueryPerformanceFrequency(&freq))
187 return (unsigned long) elapsed->lo_prec;
189 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
192 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
196 if(!QueryPerformanceFrequency(&freq))
197 return (unsigned long) elapsed->lo_prec;
199 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
202 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)
205 if(QueryPerformanceFrequency(&dummy))
206 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
208 res->lo_prec = lhs->lo_prec + rhs->lo_prec;
213 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)
216 if(QueryPerformanceFrequency(&dummy))
217 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
219 res->lo_prec = lhs->lo_prec - rhs->lo_prec;
226 #if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
228 #include <sys/types.h>
231 static struct sched_param std_sched_param;
232 static int std_sched_param_init = 0;
234 int ir_timer_enter_high_priority(void)
236 pid_t pid = getpid();
238 struct sched_param p;
241 if(!std_sched_param_init) {
242 res = sched_getparam(pid, &std_sched_param);
243 std_sched_param_init = 1;
246 algo = sched_getscheduler(pid);
247 max = sched_get_priority_max(algo);
249 memcpy(&p, &std_sched_param, sizeof(p));
250 p.sched_priority = max;
251 res = sched_setparam(pid, &p);
256 int ir_timer_leave_high_priority(void)
259 pid_t pid = getpid();
261 if(std_sched_param_init)
262 res = sched_setparam(pid, &std_sched_param);
267 #elif defined(_WIN32)
269 static int initial_priority = THREAD_PRIORITY_NORMAL;
271 int ir_timer_leave_high_priority(void)
274 if(!SetThreadPriority(GetCurrentThread(), initial_priority)) {
275 fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
276 res = GetLastError();
282 int ir_timer_enter_high_priority(void)
285 initial_priority = GetThreadPriority(GetCurrentThread());
286 if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
287 fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
288 res = GetLastError();
297 int ir_timer_enter_high_priority(void)
299 fprintf(stderr, "POSIX scheduling API not present\n");
303 int ir_timer_leave_high_priority(void)
314 size_t ir_get_heap_used_bytes(void)
316 struct mallinfo mi = mallinfo();
320 #elif defined(_WIN32) /* __linux__ */
324 size_t ir_get_heap_used_bytes(void)
329 hinfo._pentry = NULL;
330 while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
331 res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
337 size_t ir_get_heap_used_bytes(void)
339 fprintf(stderr, "function not implemented\n");
346 void ir_timer_reset(ir_timer_t *timer)
348 _time_reset(&timer->elapsed);
349 _time_reset(&timer->start);
354 void ir_timer_start(ir_timer_t *timer)
356 _time_reset(&timer->start);
357 _time_get(&timer->start);
361 void ir_timer_reset_and_start(ir_timer_t *timer)
363 _time_reset(&timer->elapsed);
364 ir_timer_start(timer);
367 /* stop a running timer */
368 void ir_timer_stop(ir_timer_t *timer)
370 /* If the timer is running stop, measure the time and add it to the
378 _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
379 _time_reset(&timer->start);
383 /* push a timer on the stack */
384 int ir_timer_push(ir_timer_t *timer)
388 timer->link = timer_stack;
390 ir_timer_stop(timer_stack);
391 ir_timer_start(timer);
396 /* pop a timer from the stack */
397 ir_timer_t *ir_timer_pop(void)
399 ir_timer_t *timer = timer_stack;
401 ir_timer_stop(timer);
402 timer_stack = timer->link;
405 ir_timer_start(timer_stack);
410 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
413 const ir_timer_val_t *elapsed = &timer->elapsed;
418 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
420 return _time_to_msec(elapsed);
423 unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
426 const ir_timer_val_t *elapsed = &timer->elapsed;
431 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
433 return _time_to_usec(elapsed);
436 const char *ir_timer_get_name(const ir_timer_t *timer) {
440 const char *ir_timer_get_description(const ir_timer_t *timer) {