From f80a9bd02a610ba5a175325fc4a8cc49a0bc7501 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 29 Dec 2009 23:21:20 +0000 Subject: [PATCH] trade some max call count for more accurate timing in full media situations, hint: use 30ms ptime for drastic reduction in resources git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16081 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- configure.in | 2 +- src/include/switch_core.h | 1 + src/switch_core.c | 6 ++- src/switch_core_session.c | 4 +- src/switch_time.c | 88 ++++++++++++++++++++++++++++++--------- 5 files changed, 76 insertions(+), 25 deletions(-) diff --git a/configure.in b/configure.in index 313c83fc77..7a4523eeed 100644 --- a/configure.in +++ b/configure.in @@ -399,7 +399,7 @@ AC_FUNC_MALLOC AC_TYPE_SIGNAL AC_FUNC_STRFTIME AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs]) -AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups]) +AC_CHECK_FUNCS([sched_setscheduler sched_setaffinity setpriority setrlimit setgroups initgroups]) AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp]) AC_CHECK_LIB(rt, clock_gettime, [AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if you have clock_gettime()])]) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3bd75e0c5f..4f157a0cc8 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1941,6 +1941,7 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload); SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token); #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(uint32_t) switch_core_min_dtmf_duration(uint32_t duration); SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration); SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration); diff --git a/src/switch_core.c b/src/switch_core.c index ab61aa602e..c1d243580a 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1409,8 +1409,10 @@ static void switch_load_core_config(const char *file) if (tmp > 0) { switch_core_default_dtmf_duration((uint32_t) tmp); } - } else if (!strcasecmp(var, "disable-monotonic-timing")) { - switch_time_set_monotonic(SWITCH_FALSE); + } else if (!strcasecmp(var, "enable-monotonic-timing")) { + switch_time_set_monotonic(switch_true(var)); + } else if (!strcasecmp(var, "enable-clock-nanosleep")) { + switch_time_set_nanosleep(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 20cd367ccb..30e0fa4bbf 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1281,13 +1281,13 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_ switch_mutex_unlock(runtime.throttle_mutex); if (sps <= 0) { - //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Throttle Error!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Throttle Error! %d\n", session_manager.session_count); UNPROTECT_INTERFACE(endpoint_interface); return NULL; } if ((count + 1) > session_manager.session_limit) { - //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit! %d\n", session_manager.session_limit); UNPROTECT_INTERFACE(endpoint_interface); return NULL; } diff --git a/src/switch_time.c b/src/switch_time.c index 19eb412aea..5da9dee516 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -70,6 +70,7 @@ SWITCH_MODULE_DEFINITION(CORE_SOFTTIMER_MODULE, softtimer_load, softtimer_shutdo #define IDLE_SPEED 100 #define STEP_MS 1 #define STEP_MIC 1000 +#define TICK_PER_SEC 1000 struct timer_private { switch_size_t reference; @@ -85,6 +86,7 @@ struct timer_matrix { uint32_t roll; switch_mutex_t *mutex; switch_thread_cond_t *cond; + switch_thread_rwlock_t *rwlock; }; typedef struct timer_matrix timer_matrix_t; @@ -92,23 +94,39 @@ static timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS + 1]; static void do_sleep(switch_interval_time_t t) { +#if defined(HAVE_CLOCK_NANOSLEEP) || defined(DARWIN) + struct timespec ts; +#endif + #if defined(WIN32) if (t < 1000) { t = 1000; } #endif -#if defined(DARWIN) - struct timespec ts; +#if !defined(DARWIN) + if (t > 100000) { + apr_sleep(t); + } +#endif + + +#if defined(HAVE_CLOCK_NANOSLEEP) + ts.tv_sec = t / APR_USEC_PER_SEC; + ts.tv_nsec = ((t % APR_USEC_PER_SEC) * 1000) - 1000000; + 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; - nanosleep(&ts, NULL); - sched_yield(); #else apr_sleep(t); #endif +#if defined(DARWIN) +sched_yield(); +#endif + } SWITCH_DECLARE(switch_time_t) switch_micro_time_now(void) @@ -132,6 +150,12 @@ static int MONO = 1; 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) { @@ -139,6 +163,11 @@ SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable) switch_time_sync(); } +SWITCH_DECLARE(void) switch_time_set_nanosleep(switch_bool_t enable) +{ + NANO = enable ? 1 : 0; +} + static switch_time_t time_now(int64_t offset) { switch_time_t now; @@ -334,17 +363,26 @@ static switch_status_t timer_next(switch_timer_t *timer) 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) { - 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); + 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); + } else { + do_sleep(1000); } - switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex); } else { do_sleep(1000); } } - + if (globals.RUNNING == 1) { return SWITCH_STATUS_SUCCESS; } @@ -406,6 +444,13 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) switch_time_t ts = 0, last = 0; int fwd_errs = 0, rev_errs = 0; +#ifdef HAVE_SCHED_SETAFFINITY + cpu_set_t set; + CPU_ZERO(&set); + CPU_SET(0, &set); + sched_setaffinity(0, sizeof(set), &set); +#endif + switch_time_sync(); globals.STARTED = globals.RUNNING = 1; @@ -421,6 +466,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) if (ts == last) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Broken MONOTONIC Clock Detected!, Support Disabled.\n"); MONO = 0; + NANO = 0; runtime.reference = switch_time_now(); runtime.initiated = runtime.reference; break; @@ -435,15 +481,16 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) fwd_errs = rev_errs = 0; #ifndef DISABLE_1MS_COND - switch_mutex_init(&TIMER_MATRIX[1].mutex, SWITCH_MUTEX_NESTED, module_pool); - switch_thread_cond_create(&TIMER_MATRIX[1].cond, module_pool); + if (!NANO) { + switch_mutex_init(&TIMER_MATRIX[1].mutex, SWITCH_MUTEX_NESTED, module_pool); + switch_thread_cond_create(&TIMER_MATRIX[1].cond, module_pool); + } #endif - globals.use_cond_yield = globals.RUNNING == 1; - + globals.use_cond_yield = globals.RUNNING = 1; + while (globals.RUNNING == 1) { runtime.reference += STEP_MIC; - while ((ts = time_now(runtime.offset)) < runtime.reference) { if (ts < last) { if (MONO) { @@ -461,11 +508,10 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) } else { rev_errs = 0; } - do_sleep(STEP_MIC); + do_sleep(STEP_MIC); last = ts; } - if (ts > (runtime.reference + too_late)) { if (MONO) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n"); @@ -495,7 +541,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) current_ms += STEP_MS; tick += STEP_MS; - if (tick >= 1000) { + if (tick >= TICK_PER_SEC) { if (runtime.sps <= 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Rate of %d!\n", runtime.sps_total); } @@ -525,9 +571,11 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) if (TIMER_MATRIX[x].count) { TIMER_MATRIX[x].tick++; #ifdef DISABLE_1MS_COND - 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 (!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); + } } #endif if (TIMER_MATRIX[x].tick == MAX_TICK) {