Remove the unused functions print_firm_kind() and firm_identify_thing().
[libfirm] / ir / common / timing.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
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.
10  *
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.
14  *
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
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   platform neutral timing utilities
23  * @version $Id: debug.c 17143 2008-01-02 20:56:33Z beck $
24  */
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "timing.h"
31 #include "xmalloc.h"
32
33 #ifdef _WIN32
34 #define WIN32_LEAN_AND_MEAN
35 #include <windows.h>
36 #include <mmsystem.h>
37
38 /* Win32 timer value. */
39 typedef union {
40         unsigned lo_prec;       /**< 32bit low precision time in milli seconds */
41         LARGE_INTEGER hi_prec;  /**< 64bit high precision time in micro seconds */
42 } ir_timer_val_t;
43
44 #else
45
46 #include <unistd.h>
47 #define HAVE_GETTIMEOFDAY
48
49 /*
50  * Just, if we have gettimeofday()
51  * Someday, we will have a check here.
52  */
53 #ifndef __USE_BSD
54 #define __USE_BSD
55 #endif
56 #include <sys/time.h>
57
58 /* Linux timer value. */
59 typedef struct timeval ir_timer_val_t;
60
61 #endif /* _Win32 */
62
63 #include <stddef.h>
64
65 static inline void _time_get(ir_timer_val_t *val);
66 static inline void _time_reset(ir_timer_val_t *val);
67 static inline unsigned long _time_to_msec(const ir_timer_val_t *val);
68 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
69                 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
70 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
71                 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
72
73 /**
74  * A timer.
75  */
76 struct ir_timer_t {
77         ir_timer_val_t elapsed;     /**< the elapsed time so far */
78         ir_timer_val_t start;       /**< the start value of the timer */
79         ir_timer_t     *link;       /**< link to the next entry in the timer stack */
80         unsigned       running : 1; /**< set if this timer is running */
81 };
82
83 /** The top of the timer stack */
84 static ir_timer_t *timer_stack;
85
86 ir_timer_t *ir_timer_new(void)
87 {
88         ir_timer_t *timer = XMALLOCZ(ir_timer_t);
89
90         _time_reset(&timer->elapsed);
91         _time_reset(&timer->start);
92         timer->link    = NULL;
93         timer->running = 0;
94
95         return timer;
96 }
97
98 void ir_timer_free(ir_timer_t *timer)
99 {
100         xfree(timer);
101 }
102
103 #ifdef HAVE_GETTIMEOFDAY
104
105 static inline void _time_get(ir_timer_val_t *val)
106 {
107         gettimeofday(val, NULL);
108 }
109
110 static inline void _time_reset(ir_timer_val_t *val)
111 {
112         timerclear(val);
113 }
114
115 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
116 {
117         return (unsigned long) elapsed->tv_sec * 1000UL
118                 + (unsigned long) elapsed->tv_usec / 1000UL;
119 }
120
121 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
122 {
123         return (unsigned long) elapsed->tv_sec * 1000000UL
124                 + (unsigned long) elapsed->tv_usec;
125 }
126
127 static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
128                 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
129 {
130         timeradd(lhs, rhs, res);
131                 return res;
132 }
133
134 static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
135                 const ir_timer_val_t *lhs, const ir_timer_val_t *rhs)
136 {
137         timersub(lhs, rhs, res);
138         return res;
139 }
140
141 #elif defined(_WIN32)
142
143 static inline void _time_get(ir_timer_val_t *val)
144 {
145         if (!QueryPerformanceCounter(&val->hi_prec))
146                 val->lo_prec = timeGetTime();
147 }
148
149 static inline void _time_reset(ir_timer_val_t *val)
150 {
151         memset(val, 0, sizeof(val[0]));
152 }
153
154 static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
155 {
156         LARGE_INTEGER freq;
157
158         if (!QueryPerformanceFrequency(&freq))
159                 return (unsigned long) elapsed->lo_prec;
160
161         return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
162 }
163
164 static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
165 {
166         LARGE_INTEGER freq;
167
168         if (!QueryPerformanceFrequency(&freq))
169                 return (unsigned long) elapsed->lo_prec;
170
171         return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
172 }
173
174 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)
175 {
176         LARGE_INTEGER dummy;
177         if (QueryPerformanceFrequency(&dummy))
178                 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
179         else
180                 res->lo_prec = lhs->lo_prec + rhs->lo_prec;
181
182         return res;
183 }
184
185 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)
186 {
187         LARGE_INTEGER dummy;
188         if (QueryPerformanceFrequency(&dummy))
189                 res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
190         else
191                 res->lo_prec = lhs->lo_prec - rhs->lo_prec;
192
193         return res;
194 }
195
196 #endif /* _WIN32 */
197
198 #if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
199
200 #include <sys/types.h>
201 #include <sched.h>
202
203 static struct sched_param std_sched_param;
204 static int std_sched_param_init = 0;
205
206 int ir_timer_enter_high_priority(void)
207 {
208         pid_t pid = getpid();
209
210         struct sched_param p;
211         int res, max, algo;
212
213         if (!std_sched_param_init) {
214                 res = sched_getparam(pid, &std_sched_param);
215                 std_sched_param_init = 1;
216         }
217
218         algo = sched_getscheduler(pid);
219         max  = sched_get_priority_max(algo);
220
221         memcpy(&p, &std_sched_param, sizeof(p));
222         p.sched_priority = max;
223         res = sched_setparam(pid, &p);
224
225         return res;
226 }
227
228 int ir_timer_leave_high_priority(void)
229 {
230         int res   = 0;
231         pid_t pid = getpid();
232
233         if (std_sched_param_init)
234                 res = sched_setparam(pid, &std_sched_param);
235
236         return res;
237 }
238
239 #elif defined(_WIN32)
240
241 static int initial_priority = THREAD_PRIORITY_NORMAL;
242
243 int ir_timer_leave_high_priority(void)
244 {
245         int res = 0;
246         if (!SetThreadPriority(GetCurrentThread(), initial_priority)) {
247                 fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
248                 res = GetLastError();
249         }
250
251         return res;
252 }
253
254 int ir_timer_enter_high_priority(void)
255 {
256         int res = 0;
257         initial_priority = GetThreadPriority(GetCurrentThread());
258         if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
259                 fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
260                 res = GetLastError();
261         }
262
263         return res;
264 }
265
266
267 #else
268
269 int ir_timer_enter_high_priority(void)
270 {
271         fprintf(stderr, "POSIX scheduling API not present\n");
272         return 0;
273 }
274
275 int ir_timer_leave_high_priority(void)
276 {
277         return 0;
278 }
279
280 #endif
281
282
283 #ifdef __linux__
284
285 #include <malloc.h>
286 size_t ir_get_heap_used_bytes(void)
287 {
288         struct mallinfo mi = mallinfo();
289         return mi.uordblks;
290 }
291
292 #elif defined(_WIN32) /* __linux__ */
293
294 #include <malloc.h>
295
296 size_t ir_get_heap_used_bytes(void)
297 {
298         _HEAPINFO hinfo;
299         int heapstatus;
300         size_t res = 0;
301         hinfo._pentry = NULL;
302         while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
303                 res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
304         return res;
305 }
306
307 #else
308
309 size_t ir_get_heap_used_bytes(void)
310 {
311         fprintf(stderr, "function not implemented\n");
312         return 0;
313 }
314
315 #endif
316
317 /* reset a timer */
318 void ir_timer_reset(ir_timer_t *timer)
319 {
320         _time_reset(&timer->elapsed);
321         _time_reset(&timer->start);
322         timer->running = 0;
323 }
324
325 /* start a timer */
326 void ir_timer_start(ir_timer_t *timer)
327 {
328         _time_reset(&timer->start);
329         _time_get(&timer->start);
330         timer->running = 1;
331 }
332
333 void ir_timer_reset_and_start(ir_timer_t *timer)
334 {
335   _time_reset(&timer->elapsed);
336   ir_timer_start(timer);
337 }
338
339 /* stop a running timer */
340 void ir_timer_stop(ir_timer_t *timer)
341 {
342         /* If the timer is running stop, measure the time and add it to the
343          * elapsed time. */
344         if (timer->running) {
345                 ir_timer_val_t val;
346                 ir_timer_val_t tgt;
347
348                 _time_get(&val);
349                 timer->running = 0;
350                 _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
351                 _time_reset(&timer->start);
352         }
353 }
354
355 /* push a timer on the stack */
356 int ir_timer_push(ir_timer_t *timer)
357 {
358         if (timer->link)
359                 return 0;
360         timer->link = timer_stack;
361         if (timer_stack)
362                 ir_timer_stop(timer_stack);
363         ir_timer_start(timer);
364         timer_stack = timer;
365         return 1;
366 }
367
368 /* pop a timer from the stack */
369 ir_timer_t *ir_timer_pop(void)
370 {
371         ir_timer_t *timer = timer_stack;
372         if (timer) {
373                 ir_timer_stop(timer);
374                 timer_stack = timer->link;
375                 timer->link = NULL;
376                 if (timer_stack)
377                         ir_timer_start(timer_stack);
378         }
379         return timer;
380 }
381
382 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
383 {
384         ir_timer_val_t v;
385         const ir_timer_val_t *elapsed = &timer->elapsed;
386
387         if (timer->running) {
388                 elapsed = &v;
389                 _time_get(&v);
390                 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
391         }
392         return _time_to_msec(elapsed);
393 }
394
395 unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
396 {
397         ir_timer_val_t v;
398         const ir_timer_val_t *elapsed = &timer->elapsed;
399
400         if (timer->running) {
401                 elapsed = &v;
402                 _time_get(&v);
403                 _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
404         }
405         return _time_to_usec(elapsed);
406 }