beloopana: Remove duplicate comments.
[libfirm] / ir / common / timing.c
index 6f6d9b6..9be9dd0 100644 (file)
@@ -1,43 +1,20 @@
 /*
- * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
- *
  * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
  */
 
 /**
  * @file
  * @brief   platform neutral timing utilities
- * @version $Id: debug.c 17143 2008-01-02 20:56:33Z beck $
  */
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
-
-#include "firm_config.h"
 
 #include <stdio.h>
 #include <string.h>
 
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
 #include "timing.h"
-#include "set.h"
-#include "hashptr.h"
+#include "xmalloc.h"
+#include "error.h"
 
 #ifdef _WIN32
 #define WIN32_LEAN_AND_MEAN
@@ -52,6 +29,7 @@ typedef union {
 
 #else
 
+#include <unistd.h>
 #define HAVE_GETTIMEOFDAY
 
 /*
@@ -70,100 +48,72 @@ typedef struct timeval ir_timer_val_t;
 
 #include <stddef.h>
 
-static INLINE void _time_get(ir_timer_val_t *val);
-static INLINE void _time_reset(ir_timer_val_t *val);
-static INLINE unsigned long _time_to_msec(const ir_timer_val_t *val);
-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);
-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);
+static inline void _time_reset(ir_timer_val_t *val);
 
 /**
  * A timer.
  */
-struct _ir_timer_t {
+struct ir_timer_t {
        ir_timer_val_t elapsed;     /**< the elapsed time so far */
        ir_timer_val_t start;       /**< the start value of the timer */
-       ir_timer_t     *link;       /**< link to the next entry in the timer stack */
-       const char     *name;       /**< the name of the timer used for identification */
-       const char     *desc;       /**< a description if the timer */
+       ir_timer_t     *parent;     /**< parent of a timer */
+       ir_timer_t     *displaced;  /**< former timer in case of timer_push */
        unsigned       running : 1; /**< set if this timer is running */
 };
 
-/**
- * Compare two timers.
- */
-static int ir_timer_cmp(const void *a, const void *b, size_t size)
-{
-       const ir_timer_t *t1 = a;
-       const ir_timer_t *t2 = b;
-       (void) size;
-       return strcmp(t1->name, t2->name);
-}
-
-/** The set containing all currently registered timers. */
-static set *timers = NULL;
-
 /** The top of the timer stack */
 static ir_timer_t *timer_stack;
 
-/** Initialize the timer module. */
-static void timing_init(void)
+ir_timer_t *ir_timer_new(void)
 {
-       timers      = new_set(ir_timer_cmp, 16);
-       timer_stack = NULL;
+       ir_timer_t *timer = XMALLOCZ(ir_timer_t);
+       _time_reset(&timer->elapsed);
+       _time_reset(&timer->start);
+       return timer;
 }
 
-ir_timer_t *ir_timer_register(const char *name, const char *desc)
+void ir_timer_free(ir_timer_t *timer)
 {
-       unsigned hash = HASH_STR(name, strlen(name));
-       ir_timer_t timer;
-
-       _time_reset(&timer.elapsed);
-       _time_reset(&timer.start);
-       timer.link = NULL;
-       timer.name = name;
-    timer.desc = desc;
-       timer.running = 0;
-
-       if (!timers)
-               timing_init();
-
-       return set_insert(timers, &timer, sizeof(timer), hash);
+       xfree(timer);
 }
 
 #ifdef HAVE_GETTIMEOFDAY
 
-static INLINE void _time_get(ir_timer_val_t *val)
+static inline void _time_get(ir_timer_val_t *val)
 {
        gettimeofday(val, NULL);
 }
 
-static INLINE void _time_reset(ir_timer_val_t *val)
+static inline void _time_reset(ir_timer_val_t *val)
 {
        timerclear(val);
 }
 
-static INLINE unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
+static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
 {
        return (unsigned long) elapsed->tv_sec * 1000UL
                + (unsigned long) elapsed->tv_usec / 1000UL;
 }
 
-static INLINE unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
+static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
 {
        return (unsigned long) elapsed->tv_sec * 1000000UL
                + (unsigned long) elapsed->tv_usec;
 }
 
-static INLINE ir_timer_val_t *_time_add(ir_timer_val_t *res,
+static inline double _time_to_sec(const ir_timer_val_t *elapsed)
+{
+       return (double)elapsed->tv_sec + (double)elapsed->tv_usec / 1000000.0;
+}
+
+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)
 {
        timeradd(lhs, rhs, res);
                return res;
 }
 
-static INLINE ir_timer_val_t *_time_sub(ir_timer_val_t *res,
+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)
 {
        timersub(lhs, rhs, res);
@@ -172,41 +122,51 @@ static INLINE ir_timer_val_t *_time_sub(ir_timer_val_t *res,
 
 #elif defined(_WIN32)
 
-static INLINE void _time_get(ir_timer_val_t *val)
+static inline void _time_get(ir_timer_val_t *val)
 {
-       if(!QueryPerformanceCounter(&val->hi_prec))
+       if (!QueryPerformanceCounter(&val->hi_prec))
                val->lo_prec = timeGetTime();
 }
 
-static INLINE void _time_reset(ir_timer_val_t *val)
+static inline void _time_reset(ir_timer_val_t *val)
 {
        memset(val, 0, sizeof(val[0]));
 }
 
-static INLINE unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
+static inline unsigned long _time_to_msec(const ir_timer_val_t *elapsed)
 {
        LARGE_INTEGER freq;
 
-       if(!QueryPerformanceFrequency(&freq))
+       if (!QueryPerformanceFrequency(&freq))
                return (unsigned long) elapsed->lo_prec;
 
        return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000) / freq.QuadPart);
 }
 
-static INLINE unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
+static inline unsigned long _time_to_usec(const ir_timer_val_t *elapsed)
 {
        LARGE_INTEGER freq;
 
-       if(!QueryPerformanceFrequency(&freq))
-               return (unsigned long) elapsed->lo_prec;
+       if (!QueryPerformanceFrequency(&freq))
+               return (unsigned long) elapsed->lo_prec * 1000;
 
        return (unsigned long) ((elapsed->hi_prec.QuadPart * 1000000) / freq.QuadPart);
 }
 
-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)
+static inline double _time_to_sec(const ir_timer_val_t *elapsed)
+{
+       LARGE_INTEGER freq;
+
+       if (!QueryPerformanceFrequency(&freq))
+               return (double) elapsed->lo_prec / 1000.;
+
+       return (double)elapsed->hi_prec.QuadPart / (double)freq.QuadPart;
+}
+
+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)
 {
        LARGE_INTEGER dummy;
-       if(QueryPerformanceFrequency(&dummy))
+       if (QueryPerformanceFrequency(&dummy))
                res->hi_prec.QuadPart = lhs->hi_prec.QuadPart + rhs->hi_prec.QuadPart;
        else
                res->lo_prec = lhs->lo_prec + rhs->lo_prec;
@@ -214,10 +174,10 @@ static INLINE ir_timer_val_t *_time_add(ir_timer_val_t *res, const ir_timer_val_
        return res;
 }
 
-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)
+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)
 {
        LARGE_INTEGER dummy;
-       if(QueryPerformanceFrequency(&dummy))
+       if (QueryPerformanceFrequency(&dummy))
                res->hi_prec.QuadPart = lhs->hi_prec.QuadPart - rhs->hi_prec.QuadPart;
        else
                res->lo_prec = lhs->lo_prec - rhs->lo_prec;
@@ -227,7 +187,7 @@ static INLINE ir_timer_val_t *_time_sub(ir_timer_val_t *res, const ir_timer_val_
 
 #endif /* _WIN32 */
 
-#if _XOPEN_REALTIME != -1
+#if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
 
 #include <sys/types.h>
 #include <sched.h>
@@ -242,15 +202,17 @@ int ir_timer_enter_high_priority(void)
        struct sched_param p;
        int res, max, algo;
 
-       if(!std_sched_param_init) {
+       if (!std_sched_param_init) {
                res = sched_getparam(pid, &std_sched_param);
+               if (res != 0)
+                       return res;
                std_sched_param_init = 1;
        }
 
        algo = sched_getscheduler(pid);
        max  = sched_get_priority_max(algo);
 
-       memcpy(&p, &std_sched_param, sizeof(p));
+       p = std_sched_param;
        p.sched_priority = max;
        res = sched_setparam(pid, &p);
 
@@ -262,7 +224,7 @@ int ir_timer_leave_high_priority(void)
        int res   = 0;
        pid_t pid = getpid();
 
-       if(std_sched_param_init)
+       if (std_sched_param_init)
                res = sched_setparam(pid, &std_sched_param);
 
        return res;
@@ -275,7 +237,7 @@ static int initial_priority = THREAD_PRIORITY_NORMAL;
 int ir_timer_leave_high_priority(void)
 {
        int res = 0;
-       if(!SetThreadPriority(GetCurrentThread(), initial_priority)) {
+       if (!SetThreadPriority(GetCurrentThread(), initial_priority)) {
                fprintf(stderr, "Failed to leave high priority (%d)\n", GetLastError());
                res = GetLastError();
        }
@@ -287,7 +249,7 @@ int ir_timer_enter_high_priority(void)
 {
        int res = 0;
        initial_priority = GetThreadPriority(GetCurrentThread());
-       if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
+       if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
                fprintf(stderr, "Failed to enter high priority (%d)\n", GetLastError());
                res = GetLastError();
        }
@@ -331,7 +293,7 @@ size_t ir_get_heap_used_bytes(void)
        int heapstatus;
        size_t res = 0;
        hinfo._pentry = NULL;
-       while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
+       while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
                res += hinfo._useflag == _USEDENTRY ? hinfo._size : 0;
        return res;
 }
@@ -357,9 +319,19 @@ void ir_timer_reset(ir_timer_t *timer)
 /* start a timer */
 void ir_timer_start(ir_timer_t *timer)
 {
+       if (timer->running)
+               panic("timer started twice");
+
        _time_reset(&timer->start);
        _time_get(&timer->start);
        timer->running = 1;
+
+       if (timer->parent == NULL) {
+               timer->parent = timer_stack;
+       } else if (timer->parent != timer_stack) {
+               panic("timer used at different stack positions");
+       }
+       timer_stack = timer;
 }
 
 void ir_timer_reset_and_start(ir_timer_t *timer)
@@ -368,47 +340,72 @@ void ir_timer_reset_and_start(ir_timer_t *timer)
   ir_timer_start(timer);
 }
 
-/* stop a running timer */
 void ir_timer_stop(ir_timer_t *timer)
 {
-       /* If the timer is running stop, measure the time and add it to the
-        * elapsed time. */
-       if(timer->running) {
-               ir_timer_val_t val;
-               ir_timer_val_t tgt;
+       if (!timer->running)
+               panic("attempting to stop stopped timer");
+       if (timer != timer_stack)
+               panic("timer stack error");
+       timer_stack = timer->parent;
+
+       ir_timer_val_t val;
+       ir_timer_val_t tgt;
+
+       _time_get(&val);
+       timer->running = 0;
+       _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
+}
+
+void ir_timer_init_parent(ir_timer_t *timer)
+{
+       if (timer == NULL)
+               return;
+       if (timer->parent != NULL && timer->parent != timer_stack)
+               panic("timer parent mismatch");
+       timer->parent = timer_stack;
+}
 
-               _time_get(&val);
-               timer->running = 0;
-               _time_add(&timer->elapsed, &timer->elapsed, _time_sub(&tgt, &val, &timer->start));
-               _time_reset(&timer->start);
+void ir_timer_push(ir_timer_t *timer)
+{
+       if (timer->running)
+               panic("timer started twice");
+
+       ir_timer_t *parent = timer->parent;
+       if (timer->parent == NULL)
+               panic("pushing timer with unknown parent");
+
+       timer->displaced = timer_stack;
+       for (ir_timer_t *t = timer_stack; t != parent; t = t->parent) {
+               if (t == NULL)
+                       panic("parent timer not on stack");
+               ir_timer_stop(t);
        }
+       timer_stack = parent;
+
+       ir_timer_start(timer);
 }
 
-/* push a timer on the stack */
-int ir_timer_push(ir_timer_t *timer)
+static void start_stack(ir_timer_t *timer, ir_timer_t *stop)
 {
-       if (timer->link)
-               return 0;
-       timer->link = timer_stack;
-       if (timer_stack)
-               ir_timer_stop(timer_stack);
+       if (timer == stop)
+               return;
+       start_stack(timer->parent, stop);
        ir_timer_start(timer);
-       timer_stack = timer;
-       return 1;
 }
 
-/* pop a timer from the stack */
-ir_timer_t *ir_timer_pop(void)
+void ir_timer_pop(ir_timer_t *timer)
 {
-       ir_timer_t *timer = timer_stack;
-       if (timer) {
-               ir_timer_stop(timer);
-               timer_stack = timer->link;
-               timer->link = NULL;
-               if (timer_stack)
-                       ir_timer_start(timer_stack);
-       }
-       return timer;
+       if (!timer->running)
+               panic("attempting to stop stopped timer");
+       ir_timer_t *displaced = timer->displaced;
+       if (displaced == NULL)
+               panic("timer start/stop/push/pop mismatch");
+
+       ir_timer_t *parent = timer->parent;
+       timer->displaced = NULL;
+
+       ir_timer_stop(timer);
+       start_stack(displaced, parent);
 }
 
 unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
@@ -416,7 +413,7 @@ unsigned long ir_timer_elapsed_msec(const ir_timer_t *timer)
        ir_timer_val_t v;
        const ir_timer_val_t *elapsed = &timer->elapsed;
 
-       if(timer->running) {
+       if (timer->running) {
                elapsed = &v;
                _time_get(&v);
                _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
@@ -429,7 +426,7 @@ unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
        ir_timer_val_t v;
        const ir_timer_val_t *elapsed = &timer->elapsed;
 
-       if(timer->running) {
+       if (timer->running) {
                elapsed = &v;
                _time_get(&v);
                _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
@@ -437,10 +434,15 @@ unsigned long ir_timer_elapsed_usec(const ir_timer_t *timer)
        return _time_to_usec(elapsed);
 }
 
-const char *ir_timer_get_name(const ir_timer_t *timer) {
-       return timer->name;
-}
+double ir_timer_elapsed_sec(const ir_timer_t *timer)
+{
+       ir_timer_val_t v;
+       const ir_timer_val_t *elapsed = &timer->elapsed;
 
-const char *ir_timer_get_description(const ir_timer_t *timer) {
-       return timer->desc;
+       if (timer->running) {
+               elapsed = &v;
+               _time_get(&v);
+               _time_add(&v, &timer->elapsed, _time_sub(&v, &v, &timer->start));
+       }
+       return _time_to_sec(elapsed);
 }