diff --git a/configure.in b/configure.in index 7978d04754..cb5319c152 100644 --- a/configure.in +++ b/configure.in @@ -461,7 +461,7 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_MALLOC AC_TYPE_SIGNAL AC_FUNC_STRFTIME -AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs]) +AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create]) AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups]) AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp]) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 590e01ace2..37c672334f 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2050,6 +2050,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_timerfd(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); diff --git a/src/switch_core.c b/src/switch_core.c index 96e4b4ae27..73516cf168 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1635,6 +1635,8 @@ static void switch_load_core_config(const char *file) } } else if (!strcasecmp(var, "enable-monotonic-timing")) { switch_time_set_monotonic(switch_true(var)); + } else if (!strcasecmp(var, "enable-softtimer-timerfd")) { + switch_time_set_timerfd(switch_true(var)); } else if (!strcasecmp(var, "enable-clock-nanosleep")) { switch_time_set_nanosleep(switch_true(var)); } else if (!strcasecmp(var, "enable-cond-yield")) { diff --git a/src/switch_time.c b/src/switch_time.c index 2a3ee2b515..375682e005 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -34,6 +34,9 @@ #include #include #include "private/switch_core_pvt.h" +#ifdef HAVE_TIMERFD_CREATE +#include +#endif //#if defined(DARWIN) #define DISABLE_1MS_COND @@ -58,6 +61,13 @@ static int MONO = 1; static int MONO = 0; #endif +#if defined(HAVE_TIMERFD_CREATE) +// We'll default this to 1 after we have had some positive feedback that it works well +static int TFD = 0; +#else +static int TFD = 0; +#endif + static int NANO = 0; static int OFFSET = 0; @@ -72,18 +82,10 @@ static DWORD win32_last_get_time_tick = 0; CRITICAL_SECTION timer_section; #endif -#define ONEMS -#ifdef ONEMS static int STEP_MS = 1; static int STEP_MIC = 1000; static uint32_t TICK_PER_SEC = 1000; static int MS_PER_TICK = 10; -#else -static int STEP_MS = 10; -static int STEP_MIC = 10000; -static uint32_t TICK_PER_SEC = 1000; -static int MS_PER_TICK = 10; -#endif static switch_memory_pool_t *module_pool = NULL; @@ -310,8 +312,23 @@ SWITCH_DECLARE(time_t) switch_epoch_time_now(time_t *t) SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable) { +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) MONO = enable ? 1 : 0; switch_time_sync(); +#else + MONO = 0; +#endif +} + + +SWITCH_DECLARE(void) switch_time_set_timerfd(switch_bool_t enable) +{ +#if defined(HAVE_TIMERFD_CREATE) + TFD = enable ? 1 : 0; + switch_time_sync(); +#else + TFD = 0; +#endif } @@ -487,9 +504,6 @@ 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 = 10000; switch_time_sync(); } @@ -662,6 +676,29 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) switch_time_t ts = 0, last = 0; int fwd_errs = 0, rev_errs = 0; int profile_tick = 0; + int tfd = -1; + +#ifdef HAVE_TIMERFD_CREATE + struct itimerspec spec = { { 0 } }; + + if (MONO && TFD) { + tfd = timerfd_create(CLOCK_MONOTONIC, 0); + + if (tfd > -1) { + spec.it_interval.tv_sec = 0; + spec.it_interval.tv_nsec = 1000000; + spec.it_value.tv_sec = spec.it_interval.tv_sec; + spec.it_value.tv_nsec = spec.it_interval.tv_nsec; + + if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &spec, NULL)) { + close(tfd); + tfd = -1; + } + } + } +#else + tfd = -1; +#endif runtime.profile_timer = switch_new_profile_timer(); switch_get_system_idle_time(runtime.profile_timer, &runtime.profile_time); @@ -740,7 +777,13 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) if (globals.timer_count >= runtime.tipping_point) { os_yield(); } else { - do_sleep(1000); + if (tfd > -1 && globals.RUNNING == 1) { + uint64_t exp; + int r; + r = read(tfd, &exp, sizeof(exp)); + } else { + do_sleep(1000); + } } last = ts; @@ -838,6 +881,11 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) } } + if (tfd > -1) { + close(tfd); + tfd = -1; + } + switch_mutex_lock(globals.mutex); globals.RUNNING = 0;