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
33 #define WIN32_LEAN_AND_MEAN
37 /* Win32 timer value. */
39 unsigned lo_prec; /**< 32bit low precision time in milli seconds */
40 LARGE_INTEGER hi_prec; /**< 64bit high precision time in micro seconds */
46 #define HAVE_GETTIMEOFDAY
49 * Just, if we have gettimeofday()
50 * Someday, we will have a check here.
57 /* Linux timer value. */
58 typedef struct timeval ir_timer_val_t;
64 static inline void _time_reset(ir_timer_val_t *val);
70 ir_timer_val_t elapsed; /**< the elapsed time so far */
71 ir_timer_val_t start; /**< the start value of the timer */
72 ir_timer_t *link; /**< link to the next entry in the timer stack */
73 unsigned running : 1; /**< set if this timer is running */
76 /** The top of the timer stack */
77 static ir_timer_t *timer_stack;
79 ir_timer_t *ir_timer_new(void)
81 ir_timer_t *timer = XMALLOCZ(ir_timer_t);
83 _time_reset(&timer->elapsed);
84 _time_reset(&timer->start);
91 void ir_timer_free(ir_timer_t *timer)
96 #ifdef HAVE_GETTIMEOFDAY
98 static inline void _time_get(ir_timer_val_t *val)
100 gettimeofday(val, NULL);
103 static inline void _time_reset(ir_timer_val_t *val)
108 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
110 return (unsigned long) elapsed->tv_sec * 1000UL
111 + (unsigned long) elapsed->tv_usec / 1000UL;
114 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
116 return (unsigned long) elapsed->tv_sec * 1000000UL
117 + (unsigned long) elapsed->tv_usec;
120 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
121 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
123 timeradd(lhs, rhs, res);
127 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
128 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
130 timersub(lhs, rhs, res);
134 #elif defined(_WIN32)
136 static inline void _time_get(ir_timer_val_t *val)
138 if (!QueryPerformanceCounter(&val->hi_prec))
139 val->lo_prec = timeGetTime();
142 static inline void _time_reset(ir_timer_val_t *val)
144 memset(val, 0, sizeof(val[0]));
147 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
151 if (!QueryPerformanceFrequency(&freq))
152 return (unsigned long) elapsed->lo_prec;
154 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
157 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
161 if (!QueryPerformanceFrequency(&freq))
162 return (unsigned long) elapsed->lo_prec;
164 return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
167 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)
170 if (QueryPerformanceFrequency(&dummy))
171 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
173 res->lo_prec = lhs->lo_prec + rhs->lo_prec;
178 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)
181 if (QueryPerformanceFrequency(&dummy))
182 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
184 res->lo_prec = lhs->lo_prec - rhs->lo_prec;
191 #if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
193 #include <sys/types.h>
196 static struct sched_param std_sched_param;
197 static int std_sched_param_init = 0;
199 int ir_timer_enter_high_priority(void)
201 pid_t pid = getpid();
203 struct sched_param p;
206 if (!std_sched_param_init) {
207 res = sched_getparam(pid, &std_sched_param);
210 std_sched_param_init = 1;
213 algo = sched_getscheduler(pid);
214 max = sched_get_priority_max(algo);
217 p.sched_priority = max;
218 res = sched_setparam(pid, &p);
223 int ir_timer_leave_high_priority(void)
226 pid_t pid = getpid();
228 if (std_sched_param_init)
229 res = sched_setparam(pid, &std_sched_param);
234 #elif defined(_WIN32)
236 static int initial_priority = THREAD_PRIORITY_NORMAL;
238 int ir_timer_leave_high_priority(void)
241 if (!SetThreadPriority(GetCurrentThread(), initial_priority)) {
242 fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
243 res = GetLastError();
249 int ir_timer_enter_high_priority(void)
252 initial_priority = GetThreadPriority(GetCurrentThread());
253 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
254 fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
255 res = GetLastError();
264 int ir_timer_enter_high_priority(void)
266 fprintf(stderr, "POSIX scheduling API not present\n");
270 int ir_timer_leave_high_priority(void)
281 size_t ir_get_heap_used_bytes(void)
283 struct mallinfo mi = mallinfo();
287 #elif defined(_WIN32) /* __linux__ */
291 size_t ir_get_heap_used_bytes(void)
296 hinfo._pentry = NULL;
297 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
298 res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
304 size_t ir_get_heap_used_bytes(void)
306 fprintf(stderr, "function not implemented\n");
313 void ir_timer_reset(ir_timer_t *timer)
315 _time_reset(&timer->elapsed);
316 _time_reset(&timer->start);
321 void ir_timer_start(ir_timer_t *timer)
323 _time_reset(&timer->start);
324 _time_get(&timer->start);
328 void ir_timer_reset_and_start(ir_timer_t *timer)
330 _time_reset(&timer->elapsed);
331 ir_timer_start(timer);
334 /* stop a running timer */
335 void ir_timer_stop(ir_timer_t *timer)
337 /* If the timer is running stop, measure the time and add it to the
339 if (timer->running) {
345 _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
346 _time_reset(&timer->start);
350 /* push a timer on the stack */
351 int ir_timer_push(ir_timer_t *timer)
355 timer->link = timer_stack;
357 ir_timer_stop(timer_stack);
358 ir_timer_start(timer);
363 /* pop a timer from the stack */
364 ir_timer_t *ir_timer_pop(void)
366 ir_timer_t *timer = timer_stack;
368 ir_timer_stop(timer);
369 timer_stack = timer->link;
372 ir_timer_start(timer_stack);
377 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
380 const ir_timer_val_t *elapsed = &timer->elapsed;
382 if (timer->running) {
385 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
387 return _time_to_msec(elapsed);
390 unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
393 const ir_timer_val_t *elapsed = &timer->elapsed;
395 if (timer->running) {
398 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
400 return _time_to_usec(elapsed);