From 191081e45fd7275f14f6736d58da63e96dd1dd75 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Thu, 12 Jun 2008 14:21:32 +0000 Subject: add infrastructure so that timing source can be a loadable module... next steps are to convert channel.c and chan_iax2.c to use this new API, and to move all the DAHDI-specific timing source code into a new res_timing_dahdi module git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@122062 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- include/asterisk/timing.h | 112 +++++++++++++++++++++++++++++ main/Makefile | 2 +- main/timing.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 include/asterisk/timing.h create mode 100644 main/timing.c diff --git a/include/asterisk/timing.h b/include/asterisk/timing.h new file mode 100644 index 000000000..426eb8dbd --- /dev/null +++ b/include/asterisk/timing.h @@ -0,0 +1,112 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2008, Digium, Inc. + * + * Kevin P. Fleming + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + \file timing.h + \brief Timing source management + \author Kevin P. Fleming + + Portions of Asterisk require a timing source, a periodic trigger + for media handling activities. The functions in this file allow + a loadable module to provide a timing source for Asterisk and its + modules, so that those modules can request a 'timing handle' when + they require one. These handles are file descriptors, which can be + used with select() or poll(). + + The timing source used by Asterisk must provide the following + features: + + 1) Periodic triggers, with a configurable interval (specified in + millisconds). + + 2) Multiple outstanding triggers, each of which must be 'acked' + to clear it. Triggers must also be 'ackable' in quantity. + + 3) Continuous trigger mode, which when enabled causes every call + to poll() on the timer handle to immediately return. + + 4) Multiple 'event types', so that the code using the timer can + know whether the wakeup it received was due to a periodic trigger + or a continuous trigger. + */ + +#ifndef _ASTERISK_TIMING_H +#define _ASTERISK_TIMING_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +enum ast_timing_event { + AST_TIMING_EVENT_EXPIRED = 1, + AST_TIMING_EVENT_CONTINUOUS = 2, +}; + +struct ast_timing_functions { + int (*timer_open)(unsigned int rate); + void (*timer_close)(int handle); + void (*timer_ack)(int handle, unsigned int quantity); + int (*timer_enable_continuous)(int handle); + int (*timer_disable_continuous)(int handle); + enum ast_timing_event (*timer_get_event)(int handle); +}; + +/*! + \brief Install a set of timing functions. + \param funcs An instance of the \c ast_timing_functions structure with pointers + to the functions provided by the timing implementation. + \retval NULL on failure, or a handle to be passed to + ast_uninstall_timing_functions() on success + */ +void *ast_install_timing_functions(struct ast_timing_functions *funcs); + +/*! + \brief Uninstall a previously-installed set of timing functions. + \param handle The handle returned from a prior successful call to + ast_install_timing_functions(). + \retval none + */ +void ast_uninstall_timing_functions(void *handle); + +/*! + \brief Open a timer handle. + \param rate The rate at which the timer should trigger. + \retval -1 on failure, or a positive integer on success + */ +int ast_timer_open(unsigned int rate); + +/*! + \brief Close a previously-opened timer handle. + \param handle The timer handle to close. + \retval none + */ +void ast_timer_close(int handle); + +void ast_timer_ack(int handle, unsigned int quantity); + +int ast_timer_enable_continuous(int handle); + +int ast_timer_disable_continous(int handle); + +enum ast_timing_event ast_timer_get_event(int handle); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _ASTERISK_TIMING_H */ diff --git a/main/Makefile b/main/Makefile index 99a4df54b..679f79d6e 100644 --- a/main/Makefile +++ b/main/Makefile @@ -30,7 +30,7 @@ OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \ cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \ strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \ astobj2.o hashtab.o global_datastores.o $(RESAMPLE_OBJS) version.o \ - features.o taskprocessor.o + features.o taskprocessor.o timing.o # we need to link in the objects statically, not as a library, because # otherwise modules will not have them available if none of the static diff --git a/main/timing.c b/main/timing.c new file mode 100644 index 000000000..d87ebcc15 --- /dev/null +++ b/main/timing.c @@ -0,0 +1,174 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2008, Digium, Inc. + * + * Kevin P. Fleming + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Timing source management + * + * \author Kevin P. Fleming + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/timing.h" +#include "asterisk/lock.h" + +AST_MUTEX_DEFINE_STATIC(lock); + +static struct ast_timing_functions timer_funcs; + +void *ast_install_timing_functions(struct ast_timing_functions *funcs) +{ + if (!funcs->timer_open || + !funcs->timer_close || + !funcs->timer_ack || + !funcs->timer_get_event || + !funcs->timer_enable_continuous || + !funcs->timer_disable_continuous) { + return NULL; + } + + ast_mutex_lock(&lock); + + if (timer_funcs.timer_open) { + ast_mutex_unlock(&lock); + return NULL; + } + + timer_funcs = *funcs; + + ast_mutex_unlock(&lock); + + return &timer_funcs; +} + +void ast_uninstall_timing_functions(void *handle) +{ + ast_mutex_lock(&lock); + + if (handle != &timer_funcs) { + ast_mutex_unlock(&lock); + return; + } + + memset(&timer_funcs, 0, sizeof(timer_funcs)); + + ast_mutex_unlock(&lock); +} + +int ast_timer_open(unsigned int rate) +{ + int timer; + + ast_mutex_lock(&lock); + + if (!timer_funcs.timer_open) { + ast_mutex_unlock(&lock); + return -1; + } + + timer = timer_funcs.timer_open(rate); + + ast_mutex_unlock(&lock); + + return timer; +} + +void ast_timer_close(int timer) +{ + ast_mutex_lock(&lock); + + if (!timer_funcs.timer_close) { + ast_mutex_unlock(&lock); + return; + } + + timer_funcs.timer_close(timer); + + ast_mutex_unlock(&lock); +} + +void ast_timer_ack(int handle, unsigned int quantity) +{ + ast_mutex_lock(&lock); + + if (!timer_funcs.timer_ack) { + ast_mutex_unlock(&lock); + return; + } + + timer_funcs.timer_ack(handle, quantity); + + ast_mutex_unlock(&lock); +} + +int ast_timer_enable_continuous(int handle) +{ + int result; + + ast_mutex_lock(&lock); + + if (!timer_funcs.timer_enable_continuous) { + ast_mutex_unlock(&lock); + return -1; + } + + result = timer_funcs.timer_enable_continuous(handle); + + ast_mutex_unlock(&lock); + + return result; +} + +int ast_timer_disable_continous(int handle) +{ + int result; + + ast_mutex_lock(&lock); + + if (!timer_funcs.timer_disable_continuous) { + ast_mutex_unlock(&lock); + return -1; + } + + result = timer_funcs.timer_disable_continuous(handle); + + ast_mutex_unlock(&lock); + + return result; +} + +enum ast_timing_event ast_timer_get_event(int handle) +{ + enum ast_timing_event result; + + ast_mutex_lock(&lock); + + if (!timer_funcs.timer_get_event) { + ast_mutex_unlock(&lock); + return -1; + } + + result = timer_funcs.timer_get_event(handle); + + ast_mutex_unlock(&lock); + + return result; +} -- cgit v1.2.3