Author: anthm Date: Sat Sep 16 16:18:24 2006 New Revision: 2713 Removed: freeswitch/trunk/src/mod/timers/mod_threadtimer/ Modified: freeswitch/trunk/src/mod/endpoints/mod_exosip/mod_exosip.c freeswitch/trunk/src/mod/timers/mod_softtimer/mod_softtimer.c Log: marry mod_threadsoft with mod_softtimer Modified: freeswitch/trunk/src/mod/endpoints/mod_exosip/mod_exosip.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_exosip/mod_exosip.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_exosip/mod_exosip.c Sat Sep 16 16:18:24 2006 @@ -585,7 +585,7 @@ ms, flags, key, - "thread_soft", + "soft", &err, switch_core_session_get_pool(tech_pvt->session)); if (switch_rtp_ready(tech_pvt->rtp_session)) { Modified: freeswitch/trunk/src/mod/timers/mod_softtimer/mod_softtimer.c ============================================================================== --- freeswitch/trunk/src/mod/timers/mod_softtimer/mod_softtimer.c (original) +++ freeswitch/trunk/src/mod/timers/mod_softtimer/mod_softtimer.c Sat Sep 16 16:18:24 2006 @@ -32,121 +32,131 @@ #include <switch.h> #include <stdio.h> -static const char modname[] = "mod_softtimer"; +static switch_memory_pool_t *module_pool = NULL; -#ifdef WIN32 -//#define WINTIMER -#endif +static struct { + int32_t RUNNING; + switch_mutex_t *mutex; + uint32_t timer_milliseconds; + uint32_t timer_microseconds; +} globals; +static const char modname[] = "mod_softtimer"; +#define MAX_ELEMENTS 1000 + struct timer_private { -#ifdef WINTIMER - LARGE_INTEGER freq; - LARGE_INTEGER base; - LARGE_INTEGER now; -#else - switch_time_t reference; -#endif + uint32_t reference; }; +typedef struct timer_private timer_private_t; -static inline switch_status_t soft_timer_init(switch_timer_t *timer) -{ - struct timer_private *private; +struct timer_matrix { + uint64_t tick; + uint32_t count; +}; +typedef struct timer_matrix timer_matrix_t; - private = switch_core_alloc(timer->memory_pool, sizeof(*private)); - timer->private_info = private; +static timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS+1]; -#ifdef WINTIMER - QueryPerformanceFrequency(&private->freq); - QueryPerformanceCounter(&private->base); -#else - private->reference = switch_time_now(); -#endif +#define IDLE_SPEED 100 - return SWITCH_STATUS_SUCCESS; -} -static inline switch_status_t soft_timer_next(switch_timer_t *timer) +static inline void set_timer(void) { - struct timer_private *private = timer->private_info; + uint32_t index = 0, min = IDLE_SPEED; -#ifdef WINTIMER - private->base.QuadPart += timer->interval * (private->freq.QuadPart / 1000); - for (;;) { - QueryPerformanceCounter(&private->now); - if (private->now.QuadPart >= private->base.QuadPart) { - break; + for(index = 0; index < MAX_ELEMENTS; index++) { + if (TIMER_MATRIX[index].count) { + if (min > index) { + min = index; + } } - switch_yield(100); } -#else - private->reference += timer->interval * 1000; - while (switch_time_now() < private->reference) { - switch_yield(1000); + globals.timer_milliseconds = min; + globals.timer_microseconds = min * 1000; +} + +static inline switch_status_t timer_init(switch_timer_t *timer) +{ + timer_private_t *private_info; + + if ((private_info = switch_core_alloc(timer->memory_pool, sizeof(*private_info)))) { + switch_mutex_lock(globals.mutex); + TIMER_MATRIX[timer->interval].count++; + switch_mutex_unlock(globals.mutex); + timer->private_info = private_info; + private_info->reference = TIMER_MATRIX[timer->interval].tick; + set_timer(); + + return SWITCH_STATUS_SUCCESS; } -#endif - timer->samplecount += timer->samples; + return SWITCH_STATUS_MEMERR; +} +static inline switch_status_t timer_step(switch_timer_t *timer) +{ + timer_private_t *private_info = timer->private_info; + + private_info->reference += timer->interval; + return SWITCH_STATUS_SUCCESS; } -static inline switch_status_t soft_timer_step(switch_timer_t *timer) + +static inline switch_status_t timer_next(switch_timer_t *timer) { - struct timer_private *private = timer->private_info; -#ifdef WINTIMER - private->base.QuadPart += timer->interval * (private->freq.QuadPart / 1000); -#else - private->reference += timer->interval * 1000; -#endif + timer_private_t *private_info = timer->private_info; + timer_step(timer); + while (TIMER_MATRIX[timer->interval].tick < private_info->reference) { + switch_yield(1000); + } + timer->samplecount += timer->samples; + return SWITCH_STATUS_SUCCESS; } +static inline switch_status_t timer_check(switch_timer_t *timer) -static inline switch_status_t soft_timer_check(switch_timer_t *timer) - { - struct timer_private *private = timer->private_info; -#ifdef WINTIMER - QueryPerformanceCounter(&private->now); - if (private->now.QuadPart >= private->base.QuadPart) { - private->base.QuadPart += timer->interval * (private->freq.QuadPart / 1000); - return SWITCH_STATUS_SUCCESS; + timer_private_t *private_info = timer->private_info; + switch_status_t status; + + if (TIMER_MATRIX[timer->interval].tick < private_info->reference) { + status = SWITCH_STATUS_FALSE; } else { - return SWITCH_STATUS_FALSE; + private_info->reference += timer->interval; + status = SWITCH_STATUS_SUCCESS; } -#else - if (switch_time_now() < private->reference) { - return SWITCH_STATUS_FALSE; - } else { - private->reference += timer->interval * 1000; - return SWITCH_STATUS_SUCCESS; - } -#endif - + + return status; } -static inline switch_status_t soft_timer_destroy(switch_timer_t *timer) +static inline switch_status_t timer_destroy(switch_timer_t *timer) { + switch_mutex_lock(globals.mutex); + TIMER_MATRIX[timer->interval].count--; + switch_mutex_unlock(globals.mutex); + set_timer(); timer->private_info = NULL; return SWITCH_STATUS_SUCCESS; } -static const switch_timer_interface_t soft_timer_interface = { - /*.interface_name */ "soft", - /*.timer_init */ soft_timer_init, - /*.timer_next */ soft_timer_next, - /*.timer_step */ soft_timer_step, - /*.timer_check */ soft_timer_check, - /*.timer_destroy */ soft_timer_destroy +static const switch_timer_interface_t timer_interface = { + /*.interface_name */ "thread_soft", + /*.timer_init */ timer_init, + /*.timer_next */ timer_next, + /*.timer_step */ timer_step, + /*.timer_check */ timer_check, + /*.timer_destroy */ timer_destroy }; -static const switch_loadable_module_interface_t mod_timers_module_interface = { +static const switch_loadable_module_interface_t mod_softtimer_module_interface = { /*.module_name */ modname, /*.endpoint_interface */ NULL, - /*.timer_interface */ &soft_timer_interface, + /*.timer_interface */ &timer_interface, /*.switch_dialplan_interface */ NULL, /*.switch_codec_interface */ NULL, /*.switch_application_interface */ NULL @@ -155,9 +165,81 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename) { + if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n"); + return SWITCH_STATUS_MEMERR; + } + /* connect my internal structure to the blank pointer passed to me */ - *module_interface = &mod_timers_module_interface; + *module_interface = &mod_softtimer_module_interface; /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + + + +SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void) +{ + switch_time_t reference = switch_time_now(); + uint32_t current_ms = 0; + uint32_t x; + + memset(&globals, 0, sizeof(globals)); + switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); + globals.timer_microseconds = IDLE_SPEED * 1000; + globals.timer_milliseconds = IDLE_SPEED; + + globals.RUNNING = 1; + + while(globals.RUNNING == 1) { + reference += globals.timer_microseconds; + + while (switch_time_now() < reference) { + //switch_yield((reference - now) - 1000); + switch_yield(globals.timer_microseconds >> 1); + } + + current_ms += globals.timer_milliseconds; + + for (x = 0; x < MAX_ELEMENTS; x++) { + int i = x, index; + if (i == 0) { + i = 1; + } + + index = (current_ms % i == 0) ? i : 0; + + if (TIMER_MATRIX[index].count) { + TIMER_MATRIX[index].tick += index; + } + } + + if (current_ms == MAX_ELEMENTS) { + current_ms = 0; + } + } + + switch_mutex_lock(globals.mutex); + globals.RUNNING = 0; + switch_mutex_unlock(globals.mutex); + + return SWITCH_STATUS_TERM; +} + + +SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void) +{ + + if (globals.RUNNING) { + switch_mutex_lock(globals.mutex); + globals.RUNNING = -1; + switch_mutex_unlock(globals.mutex); + + while (globals.RUNNING) { + switch_yield(10000); + } + } + return SWITCH_STATUS_SUCCESS; }