add soft timer support for fd per timer use enable-softtimer-timerfd=broadcast in switch.conf.xml for orig behaviour
This commit is contained in:
parent
b6c51a5b31
commit
d6bb35ad3c
|
@ -2312,7 +2312,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);
|
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)
|
#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_monotonic(switch_bool_t enable);
|
||||||
SWITCH_DECLARE(void) switch_time_set_timerfd(switch_bool_t enable);
|
SWITCH_DECLARE(void) switch_time_set_timerfd(int enable);
|
||||||
SWITCH_DECLARE(void) switch_time_set_nanosleep(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_matrix(switch_bool_t enable);
|
||||||
SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable);
|
SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable);
|
||||||
|
|
|
@ -1934,7 +1934,19 @@ static void switch_load_core_config(const char *file)
|
||||||
} else if (!strcasecmp(var, "enable-monotonic-timing")) {
|
} else if (!strcasecmp(var, "enable-monotonic-timing")) {
|
||||||
switch_time_set_monotonic(switch_true(val));
|
switch_time_set_monotonic(switch_true(val));
|
||||||
} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
|
} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
|
||||||
switch_time_set_timerfd(switch_true(val));
|
int ival = 0;
|
||||||
|
if (val) {
|
||||||
|
if (switch_true(val)) {
|
||||||
|
ival = 2;
|
||||||
|
} else {
|
||||||
|
if (strcasecmp(val, "broadcast")) {
|
||||||
|
ival = 1;
|
||||||
|
} else if (strcasecmp(val, "fd-per-timer")) {
|
||||||
|
ival = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch_time_set_timerfd(ival);
|
||||||
} else if (!strcasecmp(var, "enable-clock-nanosleep")) {
|
} else if (!strcasecmp(var, "enable-clock-nanosleep")) {
|
||||||
switch_time_set_nanosleep(switch_true(val));
|
switch_time_set_nanosleep(switch_true(val));
|
||||||
} else if (!strcasecmp(var, "enable-cond-yield")) {
|
} else if (!strcasecmp(var, "enable-cond-yield")) {
|
||||||
|
|
|
@ -77,7 +77,7 @@ static int SYSTEM_TIME = 0;
|
||||||
timerfd seems to work well as long as it exists so if you have timerfd we'll also enable clock_nanosleep by default.
|
timerfd seems to work well as long as it exists so if you have timerfd we'll also enable clock_nanosleep by default.
|
||||||
*/
|
*/
|
||||||
#if defined(HAVE_TIMERFD_CREATE)
|
#if defined(HAVE_TIMERFD_CREATE)
|
||||||
static int TFD = 1;
|
static int TFD = 2;
|
||||||
#if defined(HAVE_CLOCK_NANOSLEEP)
|
#if defined(HAVE_CLOCK_NANOSLEEP)
|
||||||
static int NANO = 1;
|
static int NANO = 1;
|
||||||
#else
|
#else
|
||||||
|
@ -351,10 +351,10 @@ SWITCH_DECLARE(void) switch_time_set_use_system_time(switch_bool_t enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_time_set_timerfd(switch_bool_t enable)
|
SWITCH_DECLARE(void) switch_time_set_timerfd(int enable)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TIMERFD_CREATE)
|
#if defined(HAVE_TIMERFD_CREATE)
|
||||||
TFD = enable ? 1 : 0;
|
TFD = enable;
|
||||||
switch_time_sync();
|
switch_time_sync();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -385,6 +385,133 @@ SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable)
|
||||||
switch_time_sync();
|
switch_time_sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////
|
||||||
|
#ifdef HAVE_TIMERFD_CREATE
|
||||||
|
|
||||||
|
#define MAX_INTERVAL 2000 /* ms */
|
||||||
|
|
||||||
|
struct interval_timer {
|
||||||
|
int fd;
|
||||||
|
switch_size_t tick;
|
||||||
|
};
|
||||||
|
typedef struct interval_timer interval_timer_t;
|
||||||
|
|
||||||
|
static switch_status_t timerfd_start_interval(interval_timer_t *it, int interval)
|
||||||
|
{
|
||||||
|
struct itimerspec val;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
it->tick = 0;
|
||||||
|
|
||||||
|
fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
return SWITCH_STATUS_GENERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
val.it_interval.tv_sec = interval / 1000;
|
||||||
|
val.it_interval.tv_nsec = (interval % 1000) * 1000000;
|
||||||
|
val.it_value.tv_sec = 0;
|
||||||
|
val.it_value.tv_nsec = 100000;
|
||||||
|
|
||||||
|
if (timerfd_settime(fd, 0, &val, NULL) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return SWITCH_STATUS_GENERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->fd = fd;
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t timerfd_stop_interval(interval_timer_t *it)
|
||||||
|
{
|
||||||
|
close(it->fd);
|
||||||
|
it->fd = -1;
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t _timerfd_init(switch_timer_t *timer)
|
||||||
|
{
|
||||||
|
interval_timer_t *it;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (timer->interval < 1 || timer->interval > MAX_INTERVAL)
|
||||||
|
return SWITCH_STATUS_GENERR;
|
||||||
|
|
||||||
|
it = switch_core_alloc(timer->memory_pool, sizeof(*it));
|
||||||
|
if ((rc = timerfd_start_interval(it, timer->interval)) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
timer->private_info = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t _timerfd_step(switch_timer_t *timer)
|
||||||
|
{
|
||||||
|
timer->tick++;
|
||||||
|
timer->samplecount += timer->samples;
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t _timerfd_next(switch_timer_t *timer)
|
||||||
|
{
|
||||||
|
interval_timer_t *it = timer->private_info;
|
||||||
|
uint64_t x, u64 = 0;
|
||||||
|
|
||||||
|
if (read(it->fd, &u64, sizeof(u64)) < 0) {
|
||||||
|
return SWITCH_STATUS_GENERR;
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < u64; x++) {
|
||||||
|
it->tick++;
|
||||||
|
_timerfd_step(timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t _timerfd_sync(switch_timer_t *timer)
|
||||||
|
{
|
||||||
|
interval_timer_t *it = timer->private_info;
|
||||||
|
|
||||||
|
timer->tick = it->tick;
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t _timerfd_check(switch_timer_t *timer, switch_bool_t step)
|
||||||
|
{
|
||||||
|
interval_timer_t *it = timer->private_info;
|
||||||
|
int diff = (int)(timer->tick - it->tick);
|
||||||
|
|
||||||
|
if (diff > 0) {
|
||||||
|
/* still pending */
|
||||||
|
timer->diff = diff;
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
} else {
|
||||||
|
/* timer pending */
|
||||||
|
timer->diff = 0;
|
||||||
|
if (step) {
|
||||||
|
_timerfd_step(timer);
|
||||||
|
}
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t _timerfd_destroy(switch_timer_t *timer)
|
||||||
|
{
|
||||||
|
interval_timer_t *it = timer->private_info;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = timerfd_stop_interval(it);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
////////
|
||||||
|
|
||||||
|
|
||||||
static switch_time_t time_now(int64_t offset)
|
static switch_time_t time_now(int64_t offset)
|
||||||
{
|
{
|
||||||
switch_time_t now;
|
switch_time_t now;
|
||||||
|
@ -549,6 +676,10 @@ static switch_status_t timer_init(switch_timer_t *timer)
|
||||||
timer_private_t *private_info;
|
timer_private_t *private_info;
|
||||||
int sanity = 0;
|
int sanity = 0;
|
||||||
|
|
||||||
|
if (TFD == 2) {
|
||||||
|
return _timerfd_init(timer);
|
||||||
|
}
|
||||||
|
|
||||||
while (globals.STARTED == 0) {
|
while (globals.STARTED == 0) {
|
||||||
do_sleep(100000);
|
do_sleep(100000);
|
||||||
if (++sanity == 300) {
|
if (++sanity == 300) {
|
||||||
|
@ -607,9 +738,15 @@ static switch_status_t timer_init(switch_timer_t *timer)
|
||||||
|
|
||||||
static switch_status_t timer_step(switch_timer_t *timer)
|
static switch_status_t timer_step(switch_timer_t *timer)
|
||||||
{
|
{
|
||||||
timer_private_t *private_info = timer->private_info;
|
timer_private_t *private_info;
|
||||||
uint64_t samples;
|
uint64_t samples;
|
||||||
|
|
||||||
|
if (TFD == 2) {
|
||||||
|
return _timerfd_step(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private_info = timer->private_info;
|
||||||
|
|
||||||
if (globals.RUNNING != 1 || private_info->ready == 0) {
|
if (globals.RUNNING != 1 || private_info->ready == 0) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -630,7 +767,13 @@ static switch_status_t timer_step(switch_timer_t *timer)
|
||||||
|
|
||||||
static switch_status_t timer_sync(switch_timer_t *timer)
|
static switch_status_t timer_sync(switch_timer_t *timer)
|
||||||
{
|
{
|
||||||
timer_private_t *private_info = timer->private_info;
|
timer_private_t *private_info;
|
||||||
|
|
||||||
|
if (TFD == 2) {
|
||||||
|
return _timerfd_sync(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private_info = timer->private_info;
|
||||||
|
|
||||||
if (globals.RUNNING != 1 || private_info->ready == 0) {
|
if (globals.RUNNING != 1 || private_info->ready == 0) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
|
@ -648,14 +791,24 @@ static switch_status_t timer_sync(switch_timer_t *timer)
|
||||||
|
|
||||||
static switch_status_t timer_next(switch_timer_t *timer)
|
static switch_status_t timer_next(switch_timer_t *timer)
|
||||||
{
|
{
|
||||||
timer_private_t *private_info = timer->private_info;
|
timer_private_t *private_info;
|
||||||
|
|
||||||
#ifdef DISABLE_1MS_COND
|
#ifdef DISABLE_1MS_COND
|
||||||
int cond_index = timer->interval;
|
int cond_index = timer->interval;
|
||||||
#else
|
#else
|
||||||
int cond_index = 1;
|
int cond_index = 1;
|
||||||
#endif
|
#endif
|
||||||
int delta = (int) (private_info->reference - TIMER_MATRIX[timer->interval].tick);
|
int delta;
|
||||||
|
|
||||||
|
if (TFD == 2) {
|
||||||
|
return _timerfd_next(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private_info = timer->private_info;
|
||||||
|
|
||||||
|
delta = (int) (private_info->reference - TIMER_MATRIX[timer->interval].tick);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* sync up timer if it's not been called for a while otherwise it will return instantly several times until it catches up */
|
/* sync up timer if it's not been called for a while otherwise it will return instantly several times until it catches up */
|
||||||
if (delta < -1) {
|
if (delta < -1) {
|
||||||
|
@ -695,9 +848,15 @@ static switch_status_t timer_next(switch_timer_t *timer)
|
||||||
|
|
||||||
static switch_status_t timer_check(switch_timer_t *timer, switch_bool_t step)
|
static switch_status_t timer_check(switch_timer_t *timer, switch_bool_t step)
|
||||||
{
|
{
|
||||||
timer_private_t *private_info = timer->private_info;
|
timer_private_t *private_info;
|
||||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (TFD == 2) {
|
||||||
|
return _timerfd_check(timer, step);
|
||||||
|
}
|
||||||
|
|
||||||
|
private_info = timer->private_info;
|
||||||
|
|
||||||
if (globals.RUNNING != 1 || !private_info->ready) {
|
if (globals.RUNNING != 1 || !private_info->ready) {
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -724,7 +883,14 @@ static switch_status_t timer_check(switch_timer_t *timer, switch_bool_t step)
|
||||||
|
|
||||||
static switch_status_t timer_destroy(switch_timer_t *timer)
|
static switch_status_t timer_destroy(switch_timer_t *timer)
|
||||||
{
|
{
|
||||||
timer_private_t *private_info = timer->private_info;
|
timer_private_t *private_info;
|
||||||
|
|
||||||
|
if (TFD == 2) {
|
||||||
|
return _timerfd_destroy(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private_info = timer->private_info;
|
||||||
|
|
||||||
if (timer->interval < MAX_ELEMENTS) {
|
if (timer->interval < MAX_ELEMENTS) {
|
||||||
switch_mutex_lock(globals.mutex);
|
switch_mutex_lock(globals.mutex);
|
||||||
TIMER_MATRIX[timer->interval].count--;
|
TIMER_MATRIX[timer->interval].count--;
|
||||||
|
|
Loading…
Reference in New Issue