diff options
Diffstat (limited to 'src/common/timer.c')
-rw-r--r-- | src/common/timer.c | 479 |
1 files changed, 236 insertions, 243 deletions
diff --git a/src/common/timer.c b/src/common/timer.c index c239a9d70..bb2458233 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -26,12 +26,12 @@ #define TIMER_MAX_INTERVAL 1000 // timers (array) -static struct TimerData* timer_data = NULL; +static struct TimerData *timer_data = NULL; static int timer_data_max = 0; static int timer_data_num = 0; // free timers (array) -static int* free_timer_list = NULL; +static int *free_timer_list = NULL; static int free_timer_list_max = 0; static int free_timer_list_pos = 0; @@ -53,85 +53,87 @@ time_t start_time; /*---------------------------- - * Timer debugging + * Timer debugging *----------------------------*/ struct timer_func_list { - struct timer_func_list* next; - TimerFunc func; - char* name; + struct timer_func_list *next; + TimerFunc func; + char *name; } *tfl_root = NULL; /// Sets the name of a timer function. -int add_timer_func_list(TimerFunc func, char* name) +int add_timer_func_list(TimerFunc func, char *name) { - struct timer_func_list* tfl; - - if (name) { - for( tfl=tfl_root; tfl != NULL; tfl=tfl->next ) - {// check suspicious cases - if( func == tfl->func ) - ShowWarning("add_timer_func_list: duplicating function %p(%s) as %s.\n",tfl->func,tfl->name,name); - else if( strcmp(name,tfl->name) == 0 ) - ShowWarning("add_timer_func_list: function %p has the same name as %p(%s)\n",func,tfl->func,tfl->name); - } - CREATE(tfl,struct timer_func_list,1); - tfl->next = tfl_root; - tfl->func = func; - tfl->name = aStrdup(name); - tfl_root = tfl; - } - return 0; + struct timer_func_list *tfl; + + if (name) { + for (tfl=tfl_root; tfl != NULL; tfl=tfl->next) { + // check suspicious cases + if (func == tfl->func) + ShowWarning("add_timer_func_list: duplicating function %p(%s) as %s.\n",tfl->func,tfl->name,name); + else if (strcmp(name,tfl->name) == 0) + ShowWarning("add_timer_func_list: function %p has the same name as %p(%s)\n",func,tfl->func,tfl->name); + } + CREATE(tfl,struct timer_func_list,1); + tfl->next = tfl_root; + tfl->func = func; + tfl->name = aStrdup(name); + tfl_root = tfl; + } + return 0; } /// Returns the name of the timer function. -char* search_timer_func_list(TimerFunc func) +char *search_timer_func_list(TimerFunc func) { - struct timer_func_list* tfl; + struct timer_func_list *tfl; - for( tfl=tfl_root; tfl != NULL; tfl=tfl->next ) - if (func == tfl->func) - return tfl->name; + for (tfl=tfl_root; tfl != NULL; tfl=tfl->next) + if (func == tfl->func) + return tfl->name; - return "unknown timer function"; + return "unknown timer function"; } /*---------------------------- - * Get tick time + * Get tick time *----------------------------*/ #if defined(ENABLE_RDTSC) static uint64 RDTSC_BEGINTICK = 0, RDTSC_CLOCK = 0; -static __inline uint64 _rdtsc(){ - register union{ - uint64 qw; - uint32 dw[2]; - } t; +static __inline uint64 _rdtsc() +{ + register union { + uint64 qw; + uint32 dw[2]; + } t; + + asm volatile("rdtsc":"=a"(t.dw[0]), "=d"(t.dw[1])); - asm volatile("rdtsc":"=a"(t.dw[0]), "=d"(t.dw[1]) ); - - return t.qw; + return t.qw; } -static void rdtsc_calibrate(){ - uint64 t1, t2; - int32 i; - - ShowStatus("Calibrating Timer Source, please wait... "); - - RDTSC_CLOCK = 0; - - for(i = 0; i < 5; i++){ - t1 = _rdtsc(); - usleep(1000000); //1000 MS - t2 = _rdtsc(); - RDTSC_CLOCK += (t2 - t1) / 1000; - } - RDTSC_CLOCK /= 5; - - RDTSC_BEGINTICK = _rdtsc(); - - ShowMessage(" done. (Frequency: %u Mhz)\n", (uint32)(RDTSC_CLOCK/1000) ); +static void rdtsc_calibrate() +{ + uint64 t1, t2; + int32 i; + + ShowStatus("Calibrating Timer Source, please wait... "); + + RDTSC_CLOCK = 0; + + for (i = 0; i < 5; i++) { + t1 = _rdtsc(); + usleep(1000000); //1000 MS + t2 = _rdtsc(); + RDTSC_CLOCK += (t2 - t1) / 1000; + } + RDTSC_CLOCK /= 5; + + RDTSC_BEGINTICK = _rdtsc(); + + ShowMessage(" done. (Frequency: %u Mhz)\n", (uint32)(RDTSC_CLOCK/1000)); } #endif @@ -140,19 +142,19 @@ static void rdtsc_calibrate(){ static unsigned int tick(void) { #if defined(WIN32) - return GetTickCount(); + return GetTickCount(); #elif defined(ENABLE_RDTSC) - // - return (unsigned int)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK); - // + // + return (unsigned int)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK); + // #elif defined(HAVE_MONOTONIC_CLOCK) - struct timespec tval; - clock_gettime(CLOCK_MONOTONIC, &tval); - return tval.tv_sec * 1000 + tval.tv_nsec / 1000000; + struct timespec tval; + clock_gettime(CLOCK_MONOTONIC, &tval); + return tval.tv_sec * 1000 + tval.tv_nsec / 1000000; #else - struct timeval tval; - gettimeofday(&tval, NULL); - return tval.tv_sec * 1000 + tval.tv_usec / 1000; + struct timeval tval; + gettimeofday(&tval, NULL); + return tval.tv_sec * 1000 + tval.tv_usec / 1000; #endif } @@ -165,14 +167,14 @@ static int gettick_count = 1; unsigned int gettick_nocache(void) { - gettick_count = TICK_CACHE; - gettick_cache = tick(); - return gettick_cache; + gettick_count = TICK_CACHE; + gettick_cache = tick(); + return gettick_cache; } unsigned int gettick(void) { - return ( --gettick_count == 0 ) ? gettick_nocache() : gettick_cache; + return (--gettick_count == 0) ? gettick_nocache() : gettick_cache; } ////////////////////////////// #else @@ -180,110 +182,108 @@ unsigned int gettick(void) // tick doesn't get cached unsigned int gettick_nocache(void) { - return tick(); + return tick(); } unsigned int gettick(void) { - return tick(); + return tick(); } ////////////////////////////////////////////////////////////////////////// #endif ////////////////////////////////////////////////////////////////////////// /*====================================== - * CORE : Timer Heap + * CORE : Timer Heap *--------------------------------------*/ /// Adds a timer to the timer_heap static void push_timer_heap(int tid) { - BHEAP_ENSURE(timer_heap, 1, 256); - BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP); + BHEAP_ENSURE(timer_heap, 1, 256); + BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP); } /*========================== - * Timer Management + * Timer Management *--------------------------*/ /// Returns a free timer id. static int acquire_timer(void) { - int tid; - - // select a free timer - if (free_timer_list_pos) { - do { - tid = free_timer_list[--free_timer_list_pos]; - } while(tid >= timer_data_num && free_timer_list_pos > 0); - } else - tid = timer_data_num; - - // check available space - if( tid >= timer_data_num ) - for (tid = timer_data_num; tid < timer_data_max && timer_data[tid].type; tid++); - if (tid >= timer_data_num && tid >= timer_data_max) - {// expand timer array - timer_data_max += 256; - if( timer_data ) - RECREATE(timer_data, struct TimerData, timer_data_max); - else - CREATE(timer_data, struct TimerData, timer_data_max); - memset(timer_data + (timer_data_max - 256), 0, sizeof(struct TimerData)*256); - } - - if( tid >= timer_data_num ) - timer_data_num = tid + 1; - - return tid; + int tid; + + // select a free timer + if (free_timer_list_pos) { + do { + tid = free_timer_list[--free_timer_list_pos]; + } while (tid >= timer_data_num && free_timer_list_pos > 0); + } else + tid = timer_data_num; + + // check available space + if (tid >= timer_data_num) + for (tid = timer_data_num; tid < timer_data_max && timer_data[tid].type; tid++); + if (tid >= timer_data_num && tid >= timer_data_max) { + // expand timer array + timer_data_max += 256; + if (timer_data) + RECREATE(timer_data, struct TimerData, timer_data_max); + else + CREATE(timer_data, struct TimerData, timer_data_max); + memset(timer_data + (timer_data_max - 256), 0, sizeof(struct TimerData)*256); + } + + if (tid >= timer_data_num) + timer_data_num = tid + 1; + + return tid; } /// Starts a new timer that is deleted once it expires (single-use). /// Returns the timer's id. int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data) { - int tid; - - tid = acquire_timer(); - timer_data[tid].tick = tick; - timer_data[tid].func = func; - timer_data[tid].id = id; - timer_data[tid].data = data; - timer_data[tid].type = TIMER_ONCE_AUTODEL; - timer_data[tid].interval = 1000; - push_timer_heap(tid); - - return tid; + int tid; + + tid = acquire_timer(); + timer_data[tid].tick = tick; + timer_data[tid].func = func; + timer_data[tid].id = id; + timer_data[tid].data = data; + timer_data[tid].type = TIMER_ONCE_AUTODEL; + timer_data[tid].interval = 1000; + push_timer_heap(tid); + + return tid; } /// Starts a new timer that automatically restarts itself (infinite loop until manually removed). /// Returns the timer's id, or INVALID_TIMER if it fails. int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval) { - int tid; - - if( interval < 1 ) - { - ShowError("add_timer_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick())); - return INVALID_TIMER; - } - - tid = acquire_timer(); - timer_data[tid].tick = tick; - timer_data[tid].func = func; - timer_data[tid].id = id; - timer_data[tid].data = data; - timer_data[tid].type = TIMER_INTERVAL; - timer_data[tid].interval = interval; - push_timer_heap(tid); - - return tid; + int tid; + + if (interval < 1) { + ShowError("add_timer_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick())); + return INVALID_TIMER; + } + + tid = acquire_timer(); + timer_data[tid].tick = tick; + timer_data[tid].func = func; + timer_data[tid].id = id; + timer_data[tid].data = data; + timer_data[tid].type = TIMER_INTERVAL; + timer_data[tid].interval = interval; + push_timer_heap(tid); + + return tid; } /// Retrieves internal timer data -const struct TimerData* get_timer(int tid) -{ - return ( tid >= 0 && tid < timer_data_num ) ? &timer_data[tid] : NULL; +const struct TimerData *get_timer(int tid) { + return (tid >= 0 && tid < timer_data_num) ? &timer_data[tid] : NULL; } /// Marks a timer specified by 'id' for immediate deletion once it expires. @@ -291,142 +291,135 @@ const struct TimerData* get_timer(int tid) /// Returns 0 on success, < 0 on failure. int delete_timer(int tid, TimerFunc func) { - if( tid < 0 || tid >= timer_data_num ) - { - ShowError("delete_timer error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func)); - return -1; - } - if( timer_data[tid].func != func ) - { - ShowError("delete_timer error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func)); - return -2; - } - - timer_data[tid].func = NULL; - timer_data[tid].type = TIMER_ONCE_AUTODEL; - - return 0; + if (tid < 0 || tid >= timer_data_num) { + ShowError("delete_timer error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func)); + return -1; + } + if (timer_data[tid].func != func) { + ShowError("delete_timer error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func)); + return -2; + } + + timer_data[tid].func = NULL; + timer_data[tid].type = TIMER_ONCE_AUTODEL; + + return 0; } /// Adjusts a timer's expiration time. /// Returns the new tick value, or -1 if it fails. int addtick_timer(int tid, unsigned int tick) { - return settick_timer(tid, timer_data[tid].tick+tick); + return settick_timer(tid, timer_data[tid].tick+tick); } /// Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one). /// Returns the new tick value, or -1 if it fails. int settick_timer(int tid, unsigned int tick) { - size_t i; - - // search timer position - ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid); - if( i == BHEAP_LENGTH(timer_heap) ) - { - ShowError("settick_timer: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); - return -1; - } - - if( (int)tick == -1 ) - tick = 0;// add 1ms to avoid the error value -1 - - if( timer_data[tid].tick == tick ) - return (int)tick;// nothing to do, already in propper position - - // pop and push adjusted timer - BHEAP_POPINDEX(timer_heap, i, DIFFTICK_MINTOPCMP); - timer_data[tid].tick = tick; - BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP); - return (int)tick; + size_t i; + + // search timer position + ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid); + if (i == BHEAP_LENGTH(timer_heap)) { + ShowError("settick_timer: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + return -1; + } + + if ((int)tick == -1) + tick = 0;// add 1ms to avoid the error value -1 + + if (timer_data[tid].tick == tick) + return (int)tick;// nothing to do, already in propper position + + // pop and push adjusted timer + BHEAP_POPINDEX(timer_heap, i, DIFFTICK_MINTOPCMP); + timer_data[tid].tick = tick; + BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP); + return (int)tick; } /// Executes all expired timers. /// Returns the value of the smallest non-expired timer (or 1 second if there aren't any). int do_timer(unsigned int tick) { - int diff = TIMER_MAX_INTERVAL; // return value - - // process all timers one by one - while( BHEAP_LENGTH(timer_heap) ) - { - int tid = BHEAP_PEEK(timer_heap);// top element in heap (smallest tick) - - diff = DIFF_TICK(timer_data[tid].tick, tick); - if( diff > 0 ) - break; // no more expired timers to process - - // remove timer - BHEAP_POP(timer_heap, DIFFTICK_MINTOPCMP); - timer_data[tid].type |= TIMER_REMOVE_HEAP; - - if( timer_data[tid].func ) - { - if( diff < -1000 ) - // timer was delayed for more than 1 second, use current tick instead - timer_data[tid].func(tid, tick, timer_data[tid].id, timer_data[tid].data); - else - timer_data[tid].func(tid, timer_data[tid].tick, timer_data[tid].id, timer_data[tid].data); - } - - // in the case the function didn't change anything... - if( timer_data[tid].type & TIMER_REMOVE_HEAP ) - { - timer_data[tid].type &= ~TIMER_REMOVE_HEAP; - - switch( timer_data[tid].type ) - { - default: - case TIMER_ONCE_AUTODEL: - timer_data[tid].type = 0; - if (free_timer_list_pos >= free_timer_list_max) { - free_timer_list_max += 256; - RECREATE(free_timer_list,int,free_timer_list_max); - memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int)); - } - free_timer_list[free_timer_list_pos++] = tid; - break; - case TIMER_INTERVAL: - if( DIFF_TICK(timer_data[tid].tick, tick) < -1000 ) - timer_data[tid].tick = tick + timer_data[tid].interval; - else - timer_data[tid].tick += timer_data[tid].interval; - push_timer_heap(tid); - break; - } - } - } - - return cap_value(diff, TIMER_MIN_INTERVAL, TIMER_MAX_INTERVAL); + int diff = TIMER_MAX_INTERVAL; // return value + + // process all timers one by one + while (BHEAP_LENGTH(timer_heap)) { + int tid = BHEAP_PEEK(timer_heap);// top element in heap (smallest tick) + + diff = DIFF_TICK(timer_data[tid].tick, tick); + if (diff > 0) + break; // no more expired timers to process + + // remove timer + BHEAP_POP(timer_heap, DIFFTICK_MINTOPCMP); + timer_data[tid].type |= TIMER_REMOVE_HEAP; + + if (timer_data[tid].func) { + if (diff < -1000) + // timer was delayed for more than 1 second, use current tick instead + timer_data[tid].func(tid, tick, timer_data[tid].id, timer_data[tid].data); + else + timer_data[tid].func(tid, timer_data[tid].tick, timer_data[tid].id, timer_data[tid].data); + } + + // in the case the function didn't change anything... + if (timer_data[tid].type & TIMER_REMOVE_HEAP) { + timer_data[tid].type &= ~TIMER_REMOVE_HEAP; + + switch (timer_data[tid].type) { + default: + case TIMER_ONCE_AUTODEL: + timer_data[tid].type = 0; + if (free_timer_list_pos >= free_timer_list_max) { + free_timer_list_max += 256; + RECREATE(free_timer_list,int,free_timer_list_max); + memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int)); + } + free_timer_list[free_timer_list_pos++] = tid; + break; + case TIMER_INTERVAL: + if (DIFF_TICK(timer_data[tid].tick, tick) < -1000) + timer_data[tid].tick = tick + timer_data[tid].interval; + else + timer_data[tid].tick += timer_data[tid].interval; + push_timer_heap(tid); + break; + } + } + } + + return cap_value(diff, TIMER_MIN_INTERVAL, TIMER_MAX_INTERVAL); } unsigned long get_uptime(void) { - return (unsigned long)difftime(time(NULL), start_time); + return (unsigned long)difftime(time(NULL), start_time); } void timer_init(void) { #if defined(ENABLE_RDTSC) - rdtsc_calibrate(); + rdtsc_calibrate(); #endif - time(&start_time); + time(&start_time); } void timer_final(void) { - struct timer_func_list *tfl; - struct timer_func_list *next; - - for( tfl=tfl_root; tfl != NULL; tfl = next ) { - next = tfl->next; // copy next pointer - aFree(tfl->name); // free structures - aFree(tfl); - } - - if (timer_data) aFree(timer_data); - BHEAP_CLEAR(timer_heap); - if (free_timer_list) aFree(free_timer_list); + struct timer_func_list *tfl; + struct timer_func_list *next; + + for (tfl=tfl_root; tfl != NULL; tfl = next) { + next = tfl->next; // copy next pointer + aFree(tfl->name); // free structures + aFree(tfl); + } + + if (timer_data) aFree(timer_data); + BHEAP_CLEAR(timer_heap); + if (free_timer_list) aFree(free_timer_list); } |