diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-01-26 21:31:59 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-01-26 21:31:59 +0000 |
commit | f7325f2ffe54425e9de847948fd441beaba403b7 (patch) | |
tree | aeb2840eb320a7e825eb27f648ce1a54f8f8f505 /channels | |
parent | e0ff09fe39435a26a78177252fe60e9c1304de45 (diff) |
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: http://svn.digium.com/svn/asterisk/branches/1.4@171452 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_iax2.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 5245bae29..511f71879 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; } |