From: Russell Bryant Date: Mon, 26 Jan 2009 21:31:59 +0000 (+0000) Subject: Resolve some synchronization issues in chan_iax2 scheduler handling. X-Git-Tag: 1.4.24-rc1~105 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=722273ced3bf0befedb58019a55f90874fa3c959;p=thirdparty%2Fasterisk.git Resolve some synchronization issues in chan_iax2 scheduler handling. The important changes here are related to the synchronization between threads adding items into the scheduler and the scheduler handling thread. By adjusting the lock and condition handling, we ensure that the scheduler thread sleeps no longer and no less than it is supposed to. We also ensure that it does not wake up more often than it has to. There is no bug report associated with this. It is just something that I found while putting scheduler thread handling into a reusable form (review 129). Review: http://reviewboard.digium.com/r/131/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@171452 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 5245bae296..511f71879f 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -986,8 +986,10 @@ static int iax2_sched_add(struct sched_context *con, int when, ast_sched_cb call { int res; + ast_mutex_lock(&sched_lock); res = ast_sched_add(con, when, callback, data); - signal_condition(&sched_lock, &sched_cond); + ast_cond_signal(&sched_cond); + ast_mutex_unlock(&sched_lock); return res; } @@ -3467,7 +3469,7 @@ static int iax2_hangup(struct ast_channel *c) ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name); iax2_destroy(callno); } else if (iaxs[callno]) { - ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)); + iax2_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)); } } else if (c->tech_pvt) { /* If this call no longer exists, but the channel still @@ -9163,28 +9165,36 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data static void *sched_thread(void *ignore) { - int count; - int res; - struct timeval tv; - struct timespec ts; - for (;;) { + int ms, count; + struct timespec ts; + pthread_testcancel(); + ast_mutex_lock(&sched_lock); - res = ast_sched_wait(sched); - if ((res > 1000) || (res < 0)) - res = 1000; - tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; - ast_cond_timedwait(&sched_cond, &sched_lock, &ts); + + ms = ast_sched_wait(sched); + + if (ms == -1) { + ast_cond_wait(&sched_cond, &sched_lock); + } else { + struct timeval tv; + tv = ast_tvadd(ast_tvnow(), ast_samp2tv(ms, 1000)); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + ast_cond_timedwait(&sched_cond, &sched_lock, &ts); + } + ast_mutex_unlock(&sched_lock); + pthread_testcancel(); count = ast_sched_runq(sched); - if (option_debug && count >= 20) + if (option_debug && count >= 20) { ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); + } } + return NULL; }