[asterisk-commits] russell: branch group/timing r122556 - /team/group/timing/res/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Jun 13 08:52:49 CDT 2008
Author: russell
Date: Fri Jun 13 08:52:47 2008
New Revision: 122556
URL: http://svn.digium.com/view/asterisk?view=rev&rev=122556
Log:
set up data structures and implement timing API ... now to add background thread
that does the real work
Modified:
team/group/timing/res/res_timing_pthread.c
Modified: team/group/timing/res/res_timing_pthread.c
URL: http://svn.digium.com/view/asterisk/team/group/timing/res/res_timing_pthread.c?view=diff&rev=122556&r1=122555&r2=122556
==============================================================================
--- team/group/timing/res/res_timing_pthread.c (original)
+++ team/group/timing/res/res_timing_pthread.c Fri Jun 13 08:52:47 2008
@@ -34,6 +34,7 @@
#include "asterisk/module.h"
#include "asterisk/timing.h"
#include "asterisk/utils.h"
+#include "asterisk/astobj2.h"
static void *timing_funcs_handle;
@@ -55,48 +56,234 @@
.timer_get_event = pthread_timer_get_event,
};
+static struct ao2_container *pthread_timers;
+#define PTHREAD_TIMER_BUCKETS 563
+
+enum {
+ PIPE_READ = 0,
+ PIPE_WRITE = 1
+};
+
+enum pthread_timer_state {
+ TIMER_STATE_IDLE,
+ TIMER_STATE_TICKING,
+ TIMER_STATE_CONTINUOUS,
+};
+
+struct pthread_timer {
+ int pipe[2];
+ enum pthread_timer_state state;
+ unsigned int rate;
+};
+
+static void pthread_timer_destructor(void *obj);
+static struct pthread_timer *find_timer(int handle, int unlink);
+
static int pthread_timer_open(void)
{
+ struct pthread_timer *timer;
+
+ if (!(timer = ao2_alloc(sizeof(*timer), pthread_timer_destructor))) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ timer->pipe[PIPE_READ] = timer->pipe[PIPE_WRITE] = -1;
+ timer->state = TIMER_STATE_IDLE;
+
+ if (pipe(timer->pipe)) {
+ ao2_ref(timer, -1);
+ return -1;
+ }
+
+ ao2_link(pthread_timers, timer);
+
+ return timer->pipe[PIPE_READ];
+}
+
+static void pthread_timer_close(int handle)
+{
+ struct pthread_timer *timer;
+
+ if (!(timer = find_timer(handle, 1))) {
+ return;
+ }
+
+ ao2_ref(timer, -1);
+}
+
+static int pthread_timer_set_rate(int handle, unsigned int rate)
+{
+ struct pthread_timer *timer;
+
+ if (!(timer = find_timer(handle, 0))) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ao2_lock(timer);
+ timer->rate = rate;
+ timer->state = rate ? TIMER_STATE_TICKING : TIMER_STATE_IDLE;
+ ao2_unlock(timer);
+
+ ao2_ref(timer, -1);
+
return 0;
}
-static void pthread_timer_close(int handle)
-{
-}
-
-static int pthread_timer_set_rate(int handle, unsigned int rate)
-{
+static void pthread_timer_ack(int handle, unsigned int quantity)
+{
+ struct pthread_timer *timer;
+ ssize_t res;
+
+ ast_assert(quantity > 0);
+
+ if (!(timer = find_timer(handle, 0))) {
+ return;
+ }
+
+ do {
+ unsigned char buf[1024];
+
+ res = read(timer->pipe[PIPE_READ], buf, quantity);
+
+ if (res == -1) {
+ if (errno == EAGAIN) {
+ continue;
+ }
+ ast_log(LOG_ERROR, "read failed on timing pipe: %s\n", strerror(errno));
+ break;
+ }
+
+ quantity -= res;
+
+ } while (quantity);
+
+ ao2_ref(timer, -1);
+}
+
+static int pthread_timer_enable_continuous(int handle)
+{
+ struct pthread_timer *timer;
+
+ if (!(timer = find_timer(handle, 0))) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ timer->state = TIMER_STATE_CONTINUOUS;
+
+ ao2_ref(timer, -1);
+
return 0;
}
-static void pthread_timer_ack(int handle, unsigned int quantity)
-{
-}
-
-static int pthread_timer_enable_continuous(int handle)
-{
+static int pthread_timer_disable_continuous(int handle)
+{
+ struct pthread_timer *timer;
+
+ if (!(timer = find_timer(handle, 0))) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ timer->state = timer->rate ? TIMER_STATE_TICKING : TIMER_STATE_IDLE;
+
+ ao2_ref(timer, -1);
+
return 0;
}
-static int pthread_timer_disable_continuous(int handle)
-{
- return 0;
-}
-
static enum ast_timing_event pthread_timer_get_event(int handle)
{
- return 0;
+ struct pthread_timer *timer;
+ enum ast_timing_event res = AST_TIMING_EVENT_EXPIRED;
+
+ if (!(timer = find_timer(handle, 0))) {
+ return res;
+ }
+
+ if (timer->state == TIMER_STATE_CONTINUOUS) {
+ res = AST_TIMING_EVENT_CONTINUOUS;
+ }
+
+ ao2_ref(timer, -1);
+
+ return res;
+}
+
+static struct pthread_timer *find_timer(int handle, int unlink)
+{
+ struct pthread_timer *timer;
+ struct pthread_timer tmp_timer;
+ int flags = OBJ_POINTER;
+
+ tmp_timer.pipe[PIPE_READ] = handle;
+
+ if (unlink) {
+ flags |= OBJ_UNLINK;
+ }
+
+ if (!(timer = ao2_find(pthread_timers, &tmp_timer, flags))) {
+ ast_assert(timer != NULL);
+ return NULL;
+ }
+
+ return timer;
+}
+
+static void pthread_timer_destructor(void *obj)
+{
+ struct pthread_timer *timer = obj;
+
+ if (timer->pipe[PIPE_READ] > -1) {
+ close(timer->pipe[PIPE_READ]);
+ timer->pipe[PIPE_READ] = -1;
+ }
+
+ if (timer->pipe[PIPE_WRITE] > -1) {
+ close(timer->pipe[PIPE_WRITE]);
+ timer->pipe[PIPE_WRITE] = -1;
+ }
+}
+
+/*!
+ * \note only PIPE_READ is guaranteed valid
+ */
+static int pthread_timer_hash(const void *obj, const int flags)
+{
+ const struct pthread_timer *timer = obj;
+
+ return timer->pipe[PIPE_READ];
+}
+
+/*!
+ * \note only PIPE_READ is guaranteed valid
+ */
+static int pthread_timer_cmp(void *obj, void *arg, int flags)
+{
+ struct pthread_timer *timer1 = obj, *timer2 = arg;
+
+ return (timer1->pipe[PIPE_READ] == timer2->pipe[PIPE_READ]) ? CMP_MATCH : 0;
}
static int load_module(void)
{
+ if (!(pthread_timers = ao2_container_alloc(PTHREAD_TIMER_BUCKETS,
+ pthread_timer_hash, pthread_timer_cmp))) {
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
return (timing_funcs_handle = ast_install_timing_functions(&pthread_timing_functions)) ?
AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;
}
static int unload_module(void)
{
- /* ast_uninstall_timing_functions(timing_funcs_handle); */
+#if 0
+ ast_uninstall_timing_functions(timing_funcs_handle);
+ ao2_ref(pthread_timers, -1);
+#endif
/* This module can not currently be unloaded. No use count handling is being done. */
More information about the asterisk-commits
mailing list