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 $
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 *link; /**< link to the next entry in the timer stack */
74 unsigned running : 1; /**< set if this timer is running */
77 /** The top of the timer stack */
78 static ir_timer_t *timer_stack;
80 ir_timer_t *ir_timer_new(void)
82 ir_timer_t *timer = XMALLOCZ(ir_timer_t);
84 _time_reset(&timer->elapsed);
85 _time_reset(&timer->start);
92 void ir_timer_free(ir_timer_t *timer)
97 #ifdef HAVE_GETTIMEOFDAY
99 static inline void _time_get(ir_timer_val_t *val)
101 gettimeofday(val, NULL);
104 static inline void _time_reset(ir_timer_val_t *val)
109 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
111 return (unsigned long) elapsed->tv_sec * 1000UL
112 + (unsigned long) elapsed->tv_usec / 1000UL;
115 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
117 return (unsigned long) elapsed->tv_sec * 1000000UL
118 + (unsigned long) elapsed->tv_usec;
121 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
122 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
124 timeradd(lhs, rhs, res);
128 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
129 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
131 timersub(lhs, rhs, res);
135 #elif defined(_WIN32)
137 static inline void _time_get(ir_timer_val_t *val)
139 if (!QueryPerformanceCounter(&val->hi_prec))
140 val->lo_prec = timeGetTime();
143 static inline void _time_reset(ir_timer_val_t *val)
145 memset(val, 0, sizeof(val[0]));
148 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
152 if (!QueryPerformanceFrequency(&freq))
153 return (unsigned long) elapsed->lo_prec;
155 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
158 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
162 if (!QueryPerformanceFrequency(&freq))
163 return (unsigned long) elapsed->lo_prec;
165 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
168 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)
171 if (QueryPerformanceFrequency(&dummy))
172 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
174 res->lo_prec = lhs->lo_prec + rhs->lo_prec;
179 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)
182 if (QueryPerformanceFrequency(&dummy))
183 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
185 res->lo_prec = lhs->lo_prec - rhs->lo_prec;
192 #if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
194 #include <sys/types.h>
197 static struct sched_param std_sched_param;
198 static int std_sched_param_init = 0;
200 int ir_timer_enter_high_priority(void)
202 pid_t pid = getpid();
204 struct sched_param p;
207 if (!std_sched_param_init) {
208 res = sched_getparam(pid, &std_sched_param);
209 std_sched_param_init = 1;
212 algo = sched_getscheduler(pid);
213 max = sched_get_priority_max(algo);
216 p.sched_priority = max;
217 res = sched_setparam(pid, &p);
222 int ir_timer_leave_high_priority(void)
225 pid_t pid = getpid();
227 if (std_sched_param_init)
228 res = sched_setparam(pid, &std_sched_param);
233 #elif defined(_WIN32)
235 static int initial_priority = THREAD_PRIORITY_NORMAL;
237 int ir_timer_leave_high_priority(void)
240 if (!SetThreadPriority(GetCurrentThread(), initial_priority)) {
241 fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
242 res = GetLastError();
248 int ir_timer_enter_high_priority(void)
251 initial_priority = GetThreadPriority(GetCurrentThread());
252 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
253 fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
254 res = GetLastError();
263 int ir_timer_enter_high_priority(void)
265 fprintf(stderr, "POSIX scheduling API not present\n");
269 int ir_timer_leave_high_priority(void)
280 size_t ir_get_heap_used_bytes(void)
282 struct mallinfo mi = mallinfo();
286 #elif defined(_WIN32) /* __linux__ */
290 size_t ir_get_heap_used_bytes(void)
295 hinfo._pentry = NULL;
296 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
297 res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
303 size_t ir_get_heap_used_bytes(void)
305 fprintf(stderr, "function not implemented\n");
312 void ir_timer_reset(ir_timer_t *timer)
314 _time_reset(&timer->elapsed);
315 _time_reset(&timer->start);
320 void ir_timer_start(ir_timer_t *timer)
322 _time_reset(&timer->start);
323 _time_get(&timer->start);
327 void ir_timer_reset_and_start(ir_timer_t *timer)
329 _time_reset(&timer->elapsed);
330 ir_timer_start(timer);
333 /* stop a running timer */
334 void ir_timer_stop(ir_timer_t *timer)
336 /* If the timer is running stop, measure the time and add it to the
338 if (timer->running) {
344 _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
345 _time_reset(&timer->start);
349 /* push a timer on the stack */
350 int ir_timer_push(ir_timer_t *timer)
354 timer->link = timer_stack;
356 ir_timer_stop(timer_stack);
357 ir_timer_start(timer);
362 /* pop a timer from the stack */
363 ir_timer_t *ir_timer_pop(void)
365 ir_timer_t *timer = timer_stack;
367 ir_timer_stop(timer);
368 timer_stack = timer->link;
371 ir_timer_start(timer_stack);
376 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
379 const ir_timer_val_t *elapsed = &timer->elapsed;
381 if (timer->running) {
384 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
386 return _time_to_msec(elapsed);
389 unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
392 const ir_timer_val_t *elapsed = &timer->elapsed;
394 if (timer->running) {
397 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
399 return _time_to_usec(elapsed);