aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-01-26 21:31:59 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-01-26 21:31:59 +0000
commitf7325f2ffe54425e9de847948fd441beaba403b7 (patch)
treeaeb2840eb320a7e825eb27f648ce1a54f8f8f505 /channels
parente0ff09fe39435a26a78177252fe60e9c1304de45 (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.c40
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;
}