switch to conditional broadcast mode on slow kernels

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16308 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2010-01-14 16:02:46 +00:00
parent 0d2d07d066
commit abd116829e
6 changed files with 37 additions and 34 deletions

View File

@ -215,6 +215,7 @@ struct switch_runtime {
char *odbc_pass;
uint32_t debug_level;
uint32_t runlevel;
uint32_t tipping_point;
};
extern struct switch_runtime runtime;

View File

@ -1238,6 +1238,8 @@ SWITCH_DECLARE(void) switch_hash_this(_In_ switch_hash_index_t *hi, _Out_opt_ptr
SWITCH_DECLARE(switch_status_t) switch_core_timer_init(switch_timer_t *timer, const char *timer_name, int interval, int samples,
switch_memory_pool_t *pool);
SWITCH_DECLARE(void) switch_time_calibrate_clock(void);
/*!
\brief Wait for one cycle on an existing timer
\param timer the timer to wait on

View File

@ -1436,7 +1436,8 @@ typedef enum {
SCSC_SEND_SIGHUP,
SCSC_DEBUG_LEVEL,
SCSC_FLUSH_DB_HANDLES,
SCSC_SHUTDOWN_NOW
SCSC_SHUTDOWN_NOW,
SCSC_CALIBRATE_CLOCK
} switch_session_ctl_t;
typedef enum {

View File

@ -1470,6 +1470,8 @@ SWITCH_STANDARD_API(ctl_function)
arg = 0;
switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg);
stream->write_function(stream, "+OK\n");
} else if (!strcasecmp(argv[0], "calibrate_clock")) {
switch_core_session_ctl(SCSC_CALIBRATE_CLOCK, NULL);
} else if (!strcasecmp(argv[0], "shutdown")) {
switch_session_ctl_t command = SCSC_SHUTDOWN;
int x = 0;

View File

@ -1301,7 +1301,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
switch_rtp_init(runtime.memory_pool);
runtime.running = 1;
runtime.tipping_point = 1000;
runtime.initiated = switch_time_now();
switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL);
@ -1442,6 +1442,8 @@ static void switch_load_core_config(const char *file)
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, "tipping-point") && !zstr(val)) {
runtime.tipping_point = atoi(val);
} else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) {
switch_rtp_set_start_port((switch_port_t) atoi(val));
} else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) {
@ -1605,6 +1607,9 @@ SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, int32_
}
switch (cmd) {
case SCSC_CALIBRATE_CLOCK:
switch_time_calibrate_clock();
break;
case SCSC_FLUSH_DB_HANDLES:
switch_cache_db_flush_handles();
break;

View File

@ -177,7 +177,7 @@ static switch_interval_time_t average_time(switch_interval_time_t t, int reps)
}
#define calc_step() if (step > 11) step -= 10; else if (step > 1) step--
static void calibrate_clock(void)
SWITCH_DECLARE(void) switch_time_calibrate_clock(void)
{
int x;
switch_interval_time_t avg, val = 1000, want = 1000;
@ -188,15 +188,18 @@ static void calibrate_clock(void)
clock_getres(CLOCK_MONOTONIC, &ts);
if (ts.tv_nsec / 1000 > 1500) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Timer resolution of %ld microseconds detected!\n"
"Do you have your kernel timer set to higher than 1khz? You may experience audio problems.\n", ts.tv_nsec / 1000);
sleep(5);
"Timer resolution of %ld microseconds detected!\n"
"Do you have your kernel timer set to higher than 1khz? You may experience audio problems.\n", ts.tv_nsec / 1000);
do_sleep(5000000);
switch_time_set_cond_yield(SWITCH_TRUE);
return;
}
#endif
OFFSET = 0;
for (x = 0; x < 500; x++) {
avg = average_time(val, 100);
avg = average_time(val, 50);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Test: %ld Average: %ld Step: %d\n", (long)val, (long)avg, step);
diff = abs((int)(want - avg));
@ -204,11 +207,8 @@ static void calibrate_clock(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Abnormally large timer gap %d detected!\n"
"Do you have your kernel timer set to higher than 1khz? You may experience audio problems.\n", diff);
#ifdef WIN32
Sleep(5*1000);
#else
sleep(5);
#endif
do_sleep(5000000);
switch_time_set_cond_yield(SWITCH_TRUE);
return;
}
@ -220,12 +220,12 @@ static void calibrate_clock(void)
}
} else if (avg > want) {
if (under) {calc_step();}
under = 0;
under = good = 0;
val -= step;
over++;
} else if (avg < want) {
if (over) {calc_step();}
over = 0;
over = good = 0;
val += step;
under++;
}
@ -261,15 +261,6 @@ SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable)
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 = 10000;
} else {
STEP_MS = 10;
STEP_MIC = 10000;
TICK_PER_SEC = 1000;
}
switch_time_sync();
}
@ -286,6 +277,7 @@ SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable)
if (COND) {
MATRIX = 1;
}
switch_time_sync();
}
static switch_time_t time_now(int64_t offset)
@ -498,15 +490,15 @@ 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 (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);
}
switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex);
if (session_manager.session_count > runtime.tipping_point) {
os_yield();
} else {
if (session_manager.session_count > 1000) {
os_yield();
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);
}
switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex);
} else {
do_sleep(1000);
}
@ -640,10 +632,10 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
rev_errs = 0;
}
if (session_manager.session_count > 1000) {
if (session_manager.session_count > runtime.tipping_point) {
os_yield();
} else {
do_sleep(STEP_MIC);
do_sleep(1000);
}
last = ts;
@ -952,7 +944,7 @@ SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)
timer_interface->timer_destroy = timer_destroy;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Calibrating timer, please wait...\n");
calibrate_clock();
switch_time_calibrate_clock();
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;