aboutsummaryrefslogtreecommitdiffstats
path: root/main/sched.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-02-06 10:55:35 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-02-06 10:55:35 +0000
commit65e7ac9ff335e74d7a0a26a23383a120e41da4aa (patch)
tree09c9fd602fc5a687ca3249e3473e8ca96a35f993 /main/sched.c
parent5994e8207770dde30fe8c4f08a16b4d889b3428a (diff)
Add a common implementation of a scheduler context with a dedicated thread.
This commit expands the Asterisk scheduler API to include a common implementation of a scheduler context being processed by a dedicated thread. chan_iax2 has been updated to use this new code. Also, as a result, this resolves some race conditions related to the previous chan_iax2 scheduler handling. Related to rev 171452 which resolved the same issues in 1.4. Code from team/russell/sched_thread2 Review: http://reviewboard.digium.com/r/129/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@173858 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/sched.c')
-rw-r--r--main/sched.c144
1 files changed, 143 insertions, 1 deletions
diff --git a/main/sched.c b/main/sched.c
index d62ca115e..8b69814a3 100644
--- a/main/sched.c
+++ b/main/sched.c
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 1999 - 2008, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -70,6 +70,148 @@ struct sched_context {
#endif
};
+struct ast_sched_thread {
+ pthread_t thread;
+ ast_mutex_t lock;
+ ast_cond_t cond;
+ struct sched_context *context;
+ unsigned int stop:1;
+};
+
+static void *sched_run(void *data)
+{
+ struct ast_sched_thread *st = data;
+
+ while (!st->stop) {
+ int ms;
+ struct timespec ts = {
+ .tv_sec = 0,
+ };
+
+ ast_mutex_lock(&st->lock);
+
+ if (st->stop) {
+ ast_mutex_unlock(&st->lock);
+ return NULL;
+ }
+
+ ms = ast_sched_wait(st->context);
+
+ if (ms == -1) {
+ ast_cond_wait(&st->cond, &st->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(&st->cond, &st->lock, &ts);
+ }
+
+ ast_mutex_unlock(&st->lock);
+
+ if (st->stop) {
+ return NULL;
+ }
+
+ ast_sched_runq(st->context);
+ }
+
+ return NULL;
+}
+
+void ast_sched_thread_poke(struct ast_sched_thread *st)
+{
+ ast_mutex_lock(&st->lock);
+ ast_cond_signal(&st->cond);
+ ast_mutex_unlock(&st->lock);
+}
+
+struct sched_context *ast_sched_thread_get_context(struct ast_sched_thread *st)
+{
+ return st->context;
+}
+
+struct ast_sched_thread *ast_sched_thread_destroy(struct ast_sched_thread *st)
+{
+ if (st->thread != AST_PTHREADT_NULL) {
+ ast_mutex_lock(&st->lock);
+ st->stop = 1;
+ ast_cond_signal(&st->cond);
+ ast_mutex_unlock(&st->lock);
+ pthread_join(st->thread, NULL);
+ st->thread = AST_PTHREADT_NULL;
+ }
+
+ ast_mutex_destroy(&st->lock);
+ ast_cond_destroy(&st->cond);
+
+ if (st->context) {
+ sched_context_destroy(st->context);
+ st->context = NULL;
+ }
+
+ ast_free(st);
+
+ return NULL;
+}
+
+struct ast_sched_thread *ast_sched_thread_create(void)
+{
+ struct ast_sched_thread *st;
+
+ if (!(st = ast_calloc(1, sizeof(*st)))) {
+ return NULL;
+ }
+
+ ast_mutex_init(&st->lock);
+ ast_cond_init(&st->cond, NULL);
+
+ st->thread = AST_PTHREADT_NULL;
+
+ if (!(st->context = sched_context_create())) {
+ ast_log(LOG_ERROR, "Failed to create scheduler\n");
+ ast_sched_thread_destroy(st);
+ return NULL;
+ }
+
+ if (ast_pthread_create_background(&st->thread, NULL, sched_run, st)) {
+ ast_log(LOG_ERROR, "Failed to create scheduler thread\n");
+ ast_sched_thread_destroy(st);
+ return NULL;
+ }
+
+ return st;
+}
+
+int ast_sched_thread_add_variable(struct ast_sched_thread *st, int when, ast_sched_cb cb,
+ const void *data, int variable)
+{
+ int res;
+
+ ast_mutex_lock(&st->lock);
+ res = ast_sched_add_variable(st->context, when, cb, data, variable);
+ if (res != -1) {
+ ast_cond_signal(&st->cond);
+ }
+ ast_mutex_unlock(&st->lock);
+
+ return res;
+}
+
+int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb,
+ const void *data)
+{
+ int res;
+
+ ast_mutex_lock(&st->lock);
+ res = ast_sched_add(st->context, when, cb, data);
+ if (res != -1) {
+ ast_cond_signal(&st->cond);
+ }
+ ast_mutex_unlock(&st->lock);
+
+ return res;
+}
/* hash routines for sched */