pthread timing interface More...
#include "asterisk.h"#include <math.h>#include <sys/select.h>#include "asterisk/module.h"#include "asterisk/timing.h"#include "asterisk/utils.h"#include "asterisk/astobj2.h"#include "asterisk/time.h"#include "asterisk/lock.h"#include "asterisk/poll-compat.h"
Go to the source code of this file.
Data Structures | |
| struct | pthread_timer |
Defines | |
| #define | MAX_RATE 100 |
| #define | PTHREAD_TIMER_BUCKETS 563 |
Enumerations | |
| enum | { PIPE_READ = 0, PIPE_WRITE = 1 } |
| enum | pthread_timer_state { TIMER_STATE_IDLE, TIMER_STATE_TICKING } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| ASTERISK_FILE_VERSION (__FILE__,"$Revision: 278479 $") | |
| static int | check_timer (struct pthread_timer *timer) |
| static void * | do_timing (void *arg) |
| static struct pthread_timer * | find_timer (int handle, int unlinkobj) |
| static int | init_timing_thread (void) |
| static int | load_module (void) |
| static void | pthread_timer_ack (int handle, unsigned int quantity) |
| static void | pthread_timer_close (int handle) |
| static int | pthread_timer_cmp (void *obj, void *arg, int flags) |
| static void | pthread_timer_destructor (void *obj) |
| static int | pthread_timer_disable_continuous (int handle) |
| static int | pthread_timer_enable_continuous (int handle) |
| static enum ast_timer_event | pthread_timer_get_event (int handle) |
| static unsigned int | pthread_timer_get_max_rate (int handle) |
| static int | pthread_timer_hash (const void *obj, const int flags) |
| static int | pthread_timer_open (void) |
| static int | pthread_timer_set_rate (int handle, unsigned int rate) |
| static void | read_pipe (struct pthread_timer *timer, unsigned int num) |
| static int | run_timer (void *obj, void *arg, int flags) |
| static int | unload_module (void) |
| static void | write_byte (struct pthread_timer *timer) |
Variables | |
| static struct ast_module_info __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "pthread Timing Interface" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = 10, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ao2_container * | pthread_timers |
| static struct ast_timing_interface | pthread_timing |
| static void * | timing_funcs_handle |
| struct { | |
| ast_cond_t cond | |
| ast_mutex_t lock | |
| unsigned int stop:1 | |
| pthread_t thread | |
| } | timing_thread |
pthread timing interface
Definition in file res_timing_pthread.c.
| #define MAX_RATE 100 |
Definition at line 66 of file res_timing_pthread.c.
Referenced by pthread_timer_get_max_rate(), and pthread_timer_set_rate().
| #define PTHREAD_TIMER_BUCKETS 563 |
Definition at line 69 of file res_timing_pthread.c.
Referenced by load_module().
| anonymous enum |
Definition at line 71 of file res_timing_pthread.c.
{
PIPE_READ = 0,
PIPE_WRITE = 1
};
| enum pthread_timer_state |
Definition at line 76 of file res_timing_pthread.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 525 of file res_timing_pthread.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 525 of file res_timing_pthread.c.
| ASTERISK_FILE_VERSION | ( | __FILE__ | , |
| "$Revision: 278479 $" | |||
| ) |
| static int check_timer | ( | struct pthread_timer * | timer | ) | [static] |
| 0 | no timer tick needed |
| non-zero | write to the timing pipe needed |
Definition at line 332 of file res_timing_pthread.c.
References ast_tvdiff_ms(), ast_tvnow(), pthread_timer::interval, pthread_timer::start, pthread_timer::state, pthread_timer::tick_count, and TIMER_STATE_IDLE.
Referenced by run_timer().
{
struct timeval now;
if (timer->state == TIMER_STATE_IDLE) {
return 0;
}
now = ast_tvnow();
if (timer->tick_count < (ast_tvdiff_ms(now, timer->start) / timer->interval)) {
timer->tick_count++;
if (!timer->tick_count) {
/* Handle overflow. */
timer->start = now;
}
return 1;
}
return 0;
}
| static void* do_timing | ( | void * | arg | ) | [static] |
Definition at line 446 of file res_timing_pthread.c.
References ao2_callback, ao2_container_count(), ast_cond_timedwait(), ast_cond_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_tv(), ast_tvadd(), ast_tvnow(), OBJ_NODATA, run_timer(), and timing_thread.
Referenced by init_timing_thread().
{
struct timeval next_wakeup = ast_tvnow();
while (!timing_thread.stop) {
struct timespec ts = { 0, };
ao2_callback(pthread_timers, OBJ_NODATA, run_timer, NULL);
next_wakeup = ast_tvadd(next_wakeup, ast_tv(0, 5000));
ts.tv_sec = next_wakeup.tv_sec;
ts.tv_nsec = next_wakeup.tv_usec * 1000;
ast_mutex_lock(&timing_thread.lock);
if (!timing_thread.stop) {
if (ao2_container_count(pthread_timers)) {
ast_cond_timedwait(&timing_thread.cond, &timing_thread.lock, &ts);
} else {
ast_cond_wait(&timing_thread.cond, &timing_thread.lock);
}
}
ast_mutex_unlock(&timing_thread.lock);
}
return NULL;
}
| static struct pthread_timer * find_timer | ( | int | handle, |
| int | unlinkobj | ||
| ) | [static, read] |
Definition at line 273 of file res_timing_pthread.c.
References ao2_find, ast_assert, OBJ_POINTER, OBJ_UNLINK, pthread_timer::pipe, PIPE_READ, and timer.
Referenced by pthread_timer_ack(), pthread_timer_close(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), and pthread_timer_set_rate().
{
struct pthread_timer *timer;
struct pthread_timer tmp_timer;
int flags = OBJ_POINTER;
tmp_timer.pipe[PIPE_READ] = handle;
if (unlinkobj) {
flags |= OBJ_UNLINK;
}
if (!(timer = ao2_find(pthread_timers, &tmp_timer, flags))) {
ast_assert(timer != NULL);
return NULL;
}
return timer;
}
| static int init_timing_thread | ( | void | ) | [static] |
Definition at line 474 of file res_timing_pthread.c.
References ast_cond_init(), ast_log(), ast_mutex_init(), ast_pthread_create_background, do_timing(), LOG_ERROR, and timing_thread.
Referenced by load_module().
{
ast_mutex_init(&timing_thread.lock);
ast_cond_init(&timing_thread.cond, NULL);
if (ast_pthread_create_background(&timing_thread.thread, NULL, do_timing, NULL)) {
ast_log(LOG_ERROR, "Unable to start timing thread.\n");
return -1;
}
return 0;
}
| static int load_module | ( | void | ) | [static] |
Definition at line 487 of file res_timing_pthread.c.
References ao2_container_alloc, ao2_ref, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_timing_interface, init_timing_thread(), PTHREAD_TIMER_BUCKETS, pthread_timer_cmp(), pthread_timer_hash(), and timing_funcs_handle.
{
if (!(pthread_timers = ao2_container_alloc(PTHREAD_TIMER_BUCKETS,
pthread_timer_hash, pthread_timer_cmp))) {
return AST_MODULE_LOAD_DECLINE;
}
if (init_timing_thread()) {
ao2_ref(pthread_timers, -1);
pthread_timers = NULL;
return AST_MODULE_LOAD_DECLINE;
}
return (timing_funcs_handle = ast_register_timing_interface(&pthread_timing)) ?
AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;
}
| static void pthread_timer_ack | ( | int | handle, |
| unsigned int | quantity | ||
| ) | [static] |
Definition at line 189 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), ast_assert, find_timer(), read_pipe(), and timer.
{
struct pthread_timer *timer;
ast_assert(quantity > 0);
if (!(timer = find_timer(handle, 0))) {
return;
}
ao2_lock(timer);
read_pipe(timer, quantity);
ao2_unlock(timer);
ao2_ref(timer, -1);
}
| static void pthread_timer_close | ( | int | handle | ) | [static] |
Definition at line 142 of file res_timing_pthread.c.
References ao2_ref, find_timer(), and timer.
{
struct pthread_timer *timer;
if (!(timer = find_timer(handle, 1))) {
return;
}
ao2_ref(timer, -1);
}
| static int pthread_timer_cmp | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 321 of file res_timing_pthread.c.
References CMP_MATCH, CMP_STOP, pthread_timer::pipe, and PIPE_READ.
Referenced by load_module().
| static void pthread_timer_destructor | ( | void * | obj | ) | [static] |
Definition at line 293 of file res_timing_pthread.c.
References pthread_timer::pipe, PIPE_READ, PIPE_WRITE, and timer.
Referenced by pthread_timer_open().
{
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;
}
}
| static int pthread_timer_disable_continuous | ( | int | handle | ) | [static] |
Definition at line 227 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), pthread_timer::continuous, errno, find_timer(), read_pipe(), and timer.
{
struct pthread_timer *timer;
if (!(timer = find_timer(handle, 0))) {
errno = EINVAL;
return -1;
}
ao2_lock(timer);
if (timer->continuous) {
timer->continuous = 0;
read_pipe(timer, 1);
}
ao2_unlock(timer);
ao2_ref(timer, -1);
return 0;
}
| static int pthread_timer_enable_continuous | ( | int | handle | ) | [static] |
Definition at line 206 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), pthread_timer::continuous, errno, find_timer(), timer, and write_byte().
{
struct pthread_timer *timer;
if (!(timer = find_timer(handle, 0))) {
errno = EINVAL;
return -1;
}
ao2_lock(timer);
if (!timer->continuous) {
timer->continuous = 1;
write_byte(timer);
}
ao2_unlock(timer);
ao2_ref(timer, -1);
return 0;
}
| static enum ast_timer_event pthread_timer_get_event | ( | int | handle | ) | [static] |
Definition at line 248 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, pthread_timer::continuous, find_timer(), pthread_timer::pending_ticks, and timer.
{
struct pthread_timer *timer;
enum ast_timer_event res = AST_TIMING_EVENT_EXPIRED;
if (!(timer = find_timer(handle, 0))) {
return res;
}
ao2_lock(timer);
if (timer->continuous && timer->pending_ticks == 1) {
res = AST_TIMING_EVENT_CONTINUOUS;
}
ao2_unlock(timer);
ao2_ref(timer, -1);
return res;
}
| static unsigned int pthread_timer_get_max_rate | ( | int | handle | ) | [static] |
| static int pthread_timer_hash | ( | const void * | obj, |
| const int | flags | ||
| ) | [static] |
Definition at line 311 of file res_timing_pthread.c.
References pthread_timer::pipe, PIPE_READ, and timer.
Referenced by load_module().
{
const struct pthread_timer *timer = obj;
return timer->pipe[PIPE_READ];
}
| static int pthread_timer_open | ( | void | ) | [static] |
Definition at line 108 of file res_timing_pthread.c.
References ao2_alloc, ao2_container_count(), ao2_link, ao2_lock(), ao2_ref, ao2_unlock(), ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), errno, pthread_timer::pipe, PIPE_READ, PIPE_WRITE, pthread_timer_destructor(), pthread_timer::state, timer, TIMER_STATE_IDLE, and timing_thread.
{
struct pthread_timer *timer;
int fd;
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_lock(pthread_timers);
if (!ao2_container_count(pthread_timers)) {
ast_mutex_lock(&timing_thread.lock);
ast_cond_signal(&timing_thread.cond);
ast_mutex_unlock(&timing_thread.lock);
}
ao2_link(pthread_timers, timer);
ao2_unlock(pthread_timers);
fd = timer->pipe[PIPE_READ];
ao2_ref(timer, -1);
return fd;
}
| static int pthread_timer_set_rate | ( | int | handle, |
| unsigned int | rate | ||
| ) | [static] |
Definition at line 153 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), ast_tv(), ast_tvnow(), errno, find_timer(), pthread_timer::interval, LOG_ERROR, MAX_RATE, pthread_timer::rate, pthread_timer::start, pthread_timer::state, pthread_timer::tick_count, timer, TIMER_STATE_IDLE, and TIMER_STATE_TICKING.
{
struct pthread_timer *timer;
if (!(timer = find_timer(handle, 0))) {
errno = EINVAL;
return -1;
}
if (rate > MAX_RATE) {
ast_log(LOG_ERROR, "res_timing_pthread only supports timers at a "
"max rate of %d / sec\n", MAX_RATE);
errno = EINVAL;
return -1;
}
ao2_lock(timer);
if ((timer->rate = rate)) {
timer->interval = roundf(1000.0 / ((float) rate));
timer->start = ast_tvnow();
timer->state = TIMER_STATE_TICKING;
} else {
timer->interval = 0;
timer->start = ast_tv(0, 0);
timer->state = TIMER_STATE_IDLE;
}
timer->tick_count = 0;
ao2_unlock(timer);
ao2_ref(timer, -1);
return 0;
}
| static void read_pipe | ( | struct pthread_timer * | timer, |
| unsigned int | num | ||
| ) | [static] |
Definition at line 358 of file res_timing_pthread.c.
References ast_assert, ast_debug, ast_log(), ast_poll, buf, pthread_timer::continuous, errno, LOG_ERROR, pthread_timer::pending_ticks, pthread_timer::pipe, and PIPE_READ.
Referenced by pthread_timer_ack(), and pthread_timer_disable_continuous().
{
int rd_fd = timer->pipe[PIPE_READ];
int pending_ticks = timer->pending_ticks;
ast_assert(quantity);
if (timer->continuous && pending_ticks) {
pending_ticks--;
}
if (quantity > pending_ticks) {
quantity = pending_ticks;
}
if (!quantity) {
return;
}
do {
unsigned char buf[1024];
ssize_t res;
struct pollfd pfd = {
.fd = rd_fd,
.events = POLLIN,
};
if (ast_poll(&pfd, 1, 0) != 1) {
ast_debug(1, "Reading not available on timing pipe, "
"quantity: %u\n", quantity);
break;
}
res = read(rd_fd, buf,
(quantity < sizeof(buf)) ? quantity : sizeof(buf));
if (res == -1) {
if (errno == EAGAIN) {
continue;
}
ast_log(LOG_ERROR, "read failed on timing pipe: %s\n",
strerror(errno));
break;
}
quantity -= res;
timer->pending_ticks -= res;
} while (quantity);
}
| static int run_timer | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 429 of file res_timing_pthread.c.
References ao2_lock(), ao2_unlock(), check_timer(), pthread_timer::state, timer, TIMER_STATE_IDLE, and write_byte().
Referenced by do_timing().
{
struct pthread_timer *timer = obj;
if (timer->state == TIMER_STATE_IDLE) {
return 0;
}
ao2_lock(timer);
if (check_timer(timer)) {
write_byte(timer);
}
ao2_unlock(timer);
return 0;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 504 of file res_timing_pthread.c.
References ao2_ref, ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), ast_unregister_timing_interface(), timing_funcs_handle, and timing_thread.
{
int res;
ast_mutex_lock(&timing_thread.lock);
timing_thread.stop = 1;
ast_cond_signal(&timing_thread.cond);
ast_mutex_unlock(&timing_thread.lock);
pthread_join(timing_thread.thread, NULL);
if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
ao2_ref(pthread_timers, -1);
pthread_timers = NULL;
}
return res;
}
| static void write_byte | ( | struct pthread_timer * | timer | ) | [static] |
Definition at line 412 of file res_timing_pthread.c.
References ast_log(), errno, LOG_ERROR, pthread_timer::pending_ticks, pthread_timer::pipe, and PIPE_WRITE.
Referenced by pthread_timer_enable_continuous(), and run_timer().
{
ssize_t res;
unsigned char x = 42;
do {
res = write(timer->pipe[PIPE_WRITE], &x, 1);
} while (res == -1 && errno == EAGAIN);
if (res == -1) {
ast_log(LOG_ERROR, "Error writing to timing pipe: %s\n",
strerror(errno));
} else {
timer->pending_ticks++;
}
}
struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "pthread Timing Interface" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = 10, } [static] |
Definition at line 525 of file res_timing_pthread.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 525 of file res_timing_pthread.c.
Definition at line 104 of file res_timing_pthread.c.
Definition at line 103 of file res_timing_pthread.c.
struct ao2_container* pthread_timers [static] |
Definition at line 68 of file res_timing_pthread.c.
struct ast_timing_interface pthread_timing [static] |
Definition at line 52 of file res_timing_pthread.c.
| unsigned int stop |
Definition at line 105 of file res_timing_pthread.c.
| pthread_t thread |
Definition at line 102 of file res_timing_pthread.c.
void* timing_funcs_handle [static] |
Definition at line 41 of file res_timing_pthread.c.
Referenced by load_module(), and unload_module().
struct { ... } timing_thread [static] |
Referenced by do_timing(), init_timing_thread(), pthread_timer_open(), and unload_module().