From f97846f492211e8efab95101232af404f216bb98 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 Dec 2009 20:55:04 +0000 Subject: [PATCH] more timer changes git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16098 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/private/switch_core_pvt.h | 13 ++ src/include/switch_core.h | 1 + src/switch_core.c | 2 + src/switch_core_session.c | 8 +- src/switch_time.c | 198 +++++++++++++++++++------- 5 files changed, 165 insertions(+), 57 deletions(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 5ad57b0c7b..6408920724 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -218,6 +218,19 @@ struct switch_runtime { extern struct switch_runtime runtime; + +struct switch_session_manager { + switch_memory_pool_t *memory_pool; + switch_hash_t *session_table; + uint32_t session_count; + uint32_t session_limit; + switch_size_t session_id; +}; + +extern struct switch_session_manager session_manager; + + + switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage); void switch_core_sqldb_stop(void); void switch_core_session_init(switch_memory_pool_t *pool); diff --git a/src/include/switch_core.h b/src/include/switch_core.h index ea35537910..9ec21f039c 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1942,6 +1942,7 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_ #define switch_check_network_list_ip(_ip_str, _list_name) switch_check_network_list_ip_token(_ip_str, _list_name, NULL) SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable); SWITCH_DECLARE(void) switch_time_set_nanosleep(switch_bool_t enable); +SWITCH_DECLARE(void) switch_time_set_matrix(switch_bool_t enable); SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable); SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration); SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration); diff --git a/src/switch_core.c b/src/switch_core.c index abf58511e5..184b6e1cb3 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1415,6 +1415,8 @@ static void switch_load_core_config(const char *file) switch_time_set_nanosleep(switch_true(var)); } else if (!strcasecmp(var, "enable-cond-yield")) { switch_time_set_cond_yield(switch_true(var)); + } else if (!strcasecmp(var, "enable-timer-matrix")) { + switch_time_set_matrix(switch_true(var)); } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) { switch_core_session_limit(atoi(val)); } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) { diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 30e0fa4bbf..d2ef5490a1 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -36,13 +36,7 @@ #include "switch_core.h" #include "private/switch_core_pvt.h" -static struct { - switch_memory_pool_t *memory_pool; - switch_hash_t *session_table; - uint32_t session_count; - uint32_t session_limit; - switch_size_t session_id; -} session_manager; +struct switch_session_manager session_manager; #ifdef SWITCH_DEBUG_RWLOCKS SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line) diff --git a/src/switch_time.c b/src/switch_time.c index 6d6a78f32d..cf142d5962 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -45,6 +45,32 @@ #define MAX_TICK UINT32_MAX - 1024 +#define MAX_ELEMENTS 3600 +#define IDLE_SPEED 100 + +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) +static int MONO = 1; +#else +static int MONO = 0; +#endif + +#if defined(HAVE_CLOCK_NANOSLEEP) +static int NANO = 1; +#else +static int NANO = 0; +#endif + + +static int OFFSET = 0; + +static int COND = 0; + +static int MATRIX = 1; + +static int STEP_MS = 10; +static int STEP_MIC = 10000; +static int TICK_PER_SEC = 100; + static int MS_PER_TICK = 10; static switch_memory_pool_t *module_pool = NULL; @@ -66,12 +92,6 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown); SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime); SWITCH_MODULE_DEFINITION(CORE_SOFTTIMER_MODULE, softtimer_load, softtimer_shutdown, softtimer_runtime); -#define MAX_ELEMENTS 3600 -#define IDLE_SPEED 100 -#define STEP_MS 1 -#define STEP_MIC 1000 -#define TICK_PER_SEC 1000 - struct timer_private { switch_size_t reference; switch_size_t start; @@ -92,6 +112,15 @@ typedef struct timer_matrix timer_matrix_t; static timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS + 1]; +static void os_yield(void) +{ +#if defined(WIN32) + SwitchToThread(); +#else + sched_yield(); +#endif +} + static void do_sleep(switch_interval_time_t t) { #if defined(HAVE_CLOCK_NANOSLEEP) || defined(DARWIN) @@ -105,16 +134,18 @@ static void do_sleep(switch_interval_time_t t) #endif #if !defined(DARWIN) - if (t > 100000) { + if (t > 100000 || !NANO) { apr_sleep(t); + return; } #endif - #if defined(HAVE_CLOCK_NANOSLEEP) - ts.tv_sec = t / APR_USEC_PER_SEC; - ts.tv_nsec = ((t % APR_USEC_PER_SEC) * 1000) - 1000000; + t -= OFFSET; + ts.tv_sec = t / 1000000; + ts.tv_nsec = ((t % 1000000) * 1000); clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); + #elif defined(DARWIN) ts.tv_sec = t / APR_USEC_PER_SEC; ts.tv_nsec = (t % APR_USEC_PER_SEC) * 1000; @@ -129,6 +160,48 @@ sched_yield(); } +static switch_interval_time_t average_time(switch_interval_time_t t, int reps) +{ + int x = 0; + switch_time_t start, stop, sum = 0; + + for(x = 0; x < reps; x++) { + start = switch_time_now(); + do_sleep(t); + stop = switch_time_now(); + sum += (stop - start); + } + + return sum / reps; + +} + +static void calibrate_clock(void) +{ + int x; + switch_interval_time_t avg, val = 1000, want = 1000; + int over = 0, under = 0, good = 0; + + for (x = 0; x < 500; x++) { + avg = average_time(val, 100); + + if (abs(want - avg) <= 2) { + if (++good > 10) { + break; + } + } else if (avg > want) { + val--; + over++; + } else if (avg < want) { + val++; + under++; + } + } + + OFFSET = want - val; +} + + SWITCH_DECLARE(switch_time_t) switch_micro_time_now(void) { return (globals.RUNNING == 1 && runtime.timestamp) ? runtime.timestamp : switch_time_now(); @@ -144,33 +217,41 @@ SWITCH_DECLARE(time_t) switch_epoch_time_now(time_t *t) return now; } -#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) -static int MONO = 1; -#else -static int MONO = 0; -#endif - -#if defined(HAVE_CLOCK_NANOSLEEP) -static int NANO = 1; -#else -static int NANO = 0; -#endif - - SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable) { MONO = enable ? 1 : 0; switch_time_sync(); } + +SWITCH_DECLARE(void) switch_time_set_matrix(switch_bool_t enable) +{ + MATRIX = enable ? 1 : 0; + if (MATRIX) { + STEP_MS = 1; + STEP_MIC = 1000; + TICK_PER_SEC = 1000; + } else { + STEP_MS = 10; + STEP_MIC = 10000; + TICK_PER_SEC = 100; + } + switch_time_sync(); +} + SWITCH_DECLARE(void) switch_time_set_nanosleep(switch_bool_t enable) { +#if defined(HAVE_CLOCK_NANOSLEEP) NANO = enable ? 1 : 0; +#endif } SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable) { - globals.use_cond_yield = enable ? 1 : 0; + COND = enable ? 1 : 0; + if (COND) { + MATRIX = 1; + } } static switch_time_t time_now(int64_t offset) @@ -226,6 +307,11 @@ SWITCH_DECLARE(void) switch_sleep(switch_interval_time_t t) SWITCH_DECLARE(void) switch_cond_next(void) { + if (session_manager.session_count > 1000) { + os_yield(); + return; + } + #ifdef DISABLE_1MS_COND do_sleep(1000); #else @@ -291,6 +377,10 @@ static switch_status_t timer_init(switch_timer_t *timer) if (timer->interval > 0 && timer->interval < MS_PER_TICK) { MS_PER_TICK = timer->interval; + STEP_MS = 1; + STEP_MIC = 1000; + TICK_PER_SEC = 1000; + switch_time_sync(); } return SWITCH_STATUS_SUCCESS; @@ -366,33 +456,31 @@ static switch_status_t timer_next(switch_timer_t *timer) } timer_step(timer); + if (!MATRIX) { + do_sleep(1000 * timer->interval); + goto end; + } + while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) { check_roll(); - - if (NANO) { - do_sleep(1000 * timer->interval); - continue; - } - + if (globals.use_cond_yield == 1) { - if (switch_mutex_lock(TIMER_MATRIX[cond_index].mutex) == SWITCH_STATUS_SUCCESS) { - if (TIMER_MATRIX[timer->interval].tick < private_info->reference) { - switch_thread_cond_wait(TIMER_MATRIX[cond_index].cond, TIMER_MATRIX[cond_index].mutex); - } - switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex); + switch_mutex_lock(TIMER_MATRIX[cond_index].mutex); + if (TIMER_MATRIX[timer->interval].tick < private_info->reference) { + switch_thread_cond_wait(TIMER_MATRIX[cond_index].cond, TIMER_MATRIX[cond_index].mutex); + } + switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex); + } else { + if (session_manager.session_count > 1000) { + os_yield(); } else { do_sleep(1000); } - } else { - do_sleep(1000); } } - if (globals.RUNNING == 1) { - return SWITCH_STATUS_SUCCESS; - } - - return SWITCH_STATUS_FALSE; + end: + return globals.RUNNING == 1 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; } static switch_status_t timer_check(switch_timer_t *timer, switch_bool_t step) @@ -492,7 +580,11 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) } #endif - globals.use_cond_yield = globals.RUNNING = 1; + calibrate_clock(); + switch_time_sync(); + + globals.use_cond_yield = COND; + globals.RUNNING = 1; while (globals.RUNNING == 1) { runtime.reference += STEP_MIC; @@ -513,7 +605,13 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) } else { rev_errs = 0; } - do_sleep(STEP_MIC); + + if (session_manager.session_count > 1000) { + os_yield(); + } else { + do_sleep(STEP_MIC); + } + last = ts; } @@ -570,18 +668,18 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) #endif - if ((current_ms % MS_PER_TICK) == 0) { + if (MATRIX && (current_ms % MS_PER_TICK) == 0) { for (x = MS_PER_TICK; x <= MAX_ELEMENTS; x += MS_PER_TICK) { if ((current_ms % x) == 0) { if (TIMER_MATRIX[x].count) { TIMER_MATRIX[x].tick++; #ifdef DISABLE_1MS_COND - if (!NANO) { - if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) { - switch_thread_cond_broadcast(TIMER_MATRIX[x].cond); - switch_mutex_unlock(TIMER_MATRIX[x].mutex); - } + + if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_broadcast(TIMER_MATRIX[x].cond); + switch_mutex_unlock(TIMER_MATRIX[x].mutex); } + #endif if (TIMER_MATRIX[x].tick == MAX_TICK) { TIMER_MATRIX[x].tick = 0;