Sat Mar 10 01:55:43 2012

Asterisk developer's documentation


res_timing_pthread.c File Reference

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: 349194 $")
static int check_timer (struct pthread_timer *timer)
static void * do_timing (void *arg)
static struct pthread_timerfind_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 __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "pthread Timing Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_TIMING, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ao2_containerpthread_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
 Data for the timing thread.


Detailed Description

pthread timing interface

Author:
Russell Bryant <russell@digium.com>

Definition in file res_timing_pthread.c.


Define Documentation

#define MAX_RATE   100

Definition at line 70 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 73 of file res_timing_pthread.c.

Referenced by load_module().


Enumeration Type Documentation

anonymous enum

Enumerator:
PIPE_READ 
PIPE_WRITE 

Definition at line 75 of file res_timing_pthread.c.

00075      {
00076    PIPE_READ =  0,
00077    PIPE_WRITE = 1
00078 };

enum pthread_timer_state

Enumerator:
TIMER_STATE_IDLE 
TIMER_STATE_TICKING 

Definition at line 80 of file res_timing_pthread.c.

00080                          {
00081    TIMER_STATE_IDLE,
00082    TIMER_STATE_TICKING,
00083 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 529 of file res_timing_pthread.c.

static void __unreg_module ( void   )  [static]

Definition at line 529 of file res_timing_pthread.c.

ASTERISK_FILE_VERSION ( __FILE__  ,
"$Revision: 349194 $"   
)

static int check_timer ( struct pthread_timer timer  )  [static]

Return values:
0 no timer tick needed
non-zero write to the timing pipe needed

Definition at line 336 of file res_timing_pthread.c.

References ast_tvdiff_ms(), ast_tvnow(), timer, and TIMER_STATE_IDLE.

Referenced by run_timer().

00337 {
00338    struct timeval now;
00339 
00340    if (timer->state == TIMER_STATE_IDLE) {
00341       return 0;
00342    }
00343 
00344    now = ast_tvnow();
00345 
00346    if (timer->tick_count < (ast_tvdiff_ms(now, timer->start) / timer->interval)) {
00347       timer->tick_count++;
00348       if (!timer->tick_count) {
00349          /* Handle overflow. */
00350          timer->start = now;
00351       }
00352       return 1;
00353    }
00354 
00355    return 0;
00356 }

static void* do_timing ( void *  arg  )  [static]

Definition at line 450 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, pthread_timers, run_timer(), and timing_thread.

Referenced by init_timing_thread().

00451 {
00452    struct timeval next_wakeup = ast_tvnow();
00453 
00454    while (!timing_thread.stop) {
00455       struct timespec ts = { 0, };
00456 
00457       ao2_callback(pthread_timers, OBJ_NODATA, run_timer, NULL);
00458 
00459       next_wakeup = ast_tvadd(next_wakeup, ast_tv(0, 5000));
00460 
00461       ts.tv_sec = next_wakeup.tv_sec;
00462       ts.tv_nsec = next_wakeup.tv_usec * 1000;
00463 
00464       ast_mutex_lock(&timing_thread.lock);
00465       if (!timing_thread.stop) {
00466          if (ao2_container_count(pthread_timers)) {
00467             ast_cond_timedwait(&timing_thread.cond, &timing_thread.lock, &ts);
00468          } else {
00469             ast_cond_wait(&timing_thread.cond, &timing_thread.lock);
00470          }
00471       }
00472       ast_mutex_unlock(&timing_thread.lock);
00473    }
00474 
00475    return NULL;
00476 }

static struct pthread_timer * find_timer ( int  handle,
int  unlinkobj 
) [static]

Definition at line 277 of file res_timing_pthread.c.

References ao2_find, ast_assert, OBJ_POINTER, OBJ_UNLINK, pthread_timer::pipe, PIPE_READ, pthread_timers, 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().

00278 {
00279    struct pthread_timer *timer;
00280    struct pthread_timer tmp_timer;
00281    int flags = OBJ_POINTER;
00282 
00283    tmp_timer.pipe[PIPE_READ] = handle;
00284 
00285    if (unlinkobj) {
00286       flags |= OBJ_UNLINK;
00287    }
00288 
00289    if (!(timer = ao2_find(pthread_timers, &tmp_timer, flags))) {
00290       ast_assert(timer != NULL);
00291       return NULL;
00292    }
00293 
00294    return timer;
00295 }

static int init_timing_thread ( void   )  [static]

Definition at line 478 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().

00479 {
00480    ast_mutex_init(&timing_thread.lock);
00481    ast_cond_init(&timing_thread.cond, NULL);
00482 
00483    if (ast_pthread_create_background(&timing_thread.thread, NULL, do_timing, NULL)) {
00484       ast_log(LOG_ERROR, "Unable to start timing thread.\n");
00485       return -1;
00486    }
00487 
00488    return 0;
00489 }

static int load_module ( void   )  [static]

Definition at line 491 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(), pthread_timers, pthread_timing, and timing_funcs_handle.

static void pthread_timer_ack ( int  handle,
unsigned int  quantity 
) [static]

Definition at line 193 of file res_timing_pthread.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_assert, find_timer(), read_pipe(), and timer.

00194 {
00195    struct pthread_timer *timer;
00196 
00197    ast_assert(quantity > 0);
00198 
00199    if (!(timer = find_timer(handle, 0))) {
00200       return;
00201    }
00202 
00203    ao2_lock(timer);
00204    read_pipe(timer, quantity);
00205    ao2_unlock(timer);
00206 
00207    ao2_ref(timer, -1);
00208 }

static void pthread_timer_close ( int  handle  )  [static]

Definition at line 146 of file res_timing_pthread.c.

References ao2_ref, find_timer(), and timer.

00147 {
00148    struct pthread_timer *timer;
00149 
00150    if (!(timer = find_timer(handle, 1))) {
00151       return;
00152    }
00153 
00154    ao2_ref(timer, -1);
00155 }

static int pthread_timer_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Note:
only PIPE_READ is guaranteed valid

Definition at line 325 of file res_timing_pthread.c.

References CMP_MATCH, CMP_STOP, pthread_timer::pipe, and PIPE_READ.

Referenced by load_module().

00326 {
00327    struct pthread_timer *timer1 = obj, *timer2 = arg;
00328 
00329    return (timer1->pipe[PIPE_READ] == timer2->pipe[PIPE_READ]) ? CMP_MATCH | CMP_STOP : 0;
00330 }

static void pthread_timer_destructor ( void *  obj  )  [static]

Definition at line 297 of file res_timing_pthread.c.

References PIPE_READ, PIPE_WRITE, and timer.

Referenced by pthread_timer_open().

00298 {
00299    struct pthread_timer *timer = obj;
00300 
00301    if (timer->pipe[PIPE_READ] > -1) {
00302       close(timer->pipe[PIPE_READ]);
00303       timer->pipe[PIPE_READ] = -1;
00304    }
00305 
00306    if (timer->pipe[PIPE_WRITE] > -1) {
00307       close(timer->pipe[PIPE_WRITE]);
00308       timer->pipe[PIPE_WRITE] = -1;
00309    }
00310 }

static int pthread_timer_disable_continuous ( int  handle  )  [static]

Definition at line 231 of file res_timing_pthread.c.

References ao2_lock, ao2_ref, ao2_unlock, errno, find_timer(), read_pipe(), and timer.

00232 {
00233    struct pthread_timer *timer;
00234 
00235    if (!(timer = find_timer(handle, 0))) {
00236       errno = EINVAL;
00237       return -1;
00238    }
00239 
00240    ao2_lock(timer);
00241    if (timer->continuous) {
00242       timer->continuous = 0;
00243       read_pipe(timer, 1);
00244    }
00245    ao2_unlock(timer);
00246 
00247    ao2_ref(timer, -1);
00248 
00249    return 0;
00250 }

static int pthread_timer_enable_continuous ( int  handle  )  [static]

Definition at line 210 of file res_timing_pthread.c.

References ao2_lock, ao2_ref, ao2_unlock, errno, find_timer(), timer, and write_byte().

00211 {
00212    struct pthread_timer *timer;
00213 
00214    if (!(timer = find_timer(handle, 0))) {
00215       errno = EINVAL;
00216       return -1;
00217    }
00218 
00219    ao2_lock(timer);
00220    if (!timer->continuous) {
00221       timer->continuous = 1;
00222       write_byte(timer);
00223    }
00224    ao2_unlock(timer);
00225 
00226    ao2_ref(timer, -1);
00227 
00228    return 0;
00229 }

static enum ast_timer_event pthread_timer_get_event ( int  handle  )  [static]

Definition at line 252 of file res_timing_pthread.c.

References ao2_lock, ao2_ref, ao2_unlock, AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, find_timer(), and timer.

00253 {
00254    struct pthread_timer *timer;
00255    enum ast_timer_event res = AST_TIMING_EVENT_EXPIRED;
00256 
00257    if (!(timer = find_timer(handle, 0))) {
00258       return res;
00259    }
00260 
00261    ao2_lock(timer);
00262    if (timer->continuous && timer->pending_ticks == 1) {
00263       res = AST_TIMING_EVENT_CONTINUOUS;
00264    }
00265    ao2_unlock(timer);
00266 
00267    ao2_ref(timer, -1);
00268 
00269    return res;
00270 }

static unsigned int pthread_timer_get_max_rate ( int  handle  )  [static]

Definition at line 272 of file res_timing_pthread.c.

References MAX_RATE.

00273 {
00274    return MAX_RATE;
00275 }

static int pthread_timer_hash ( const void *  obj,
const int  flags 
) [static]

Note:
only PIPE_READ is guaranteed valid

Definition at line 315 of file res_timing_pthread.c.

References PIPE_READ, and timer.

Referenced by load_module().

00316 {
00317    const struct pthread_timer *timer = obj;
00318 
00319    return timer->pipe[PIPE_READ];
00320 }

static int pthread_timer_open ( void   )  [static]

Definition at line 112 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_timers, timer, TIMER_STATE_IDLE, and timing_thread.

00113 {
00114    struct pthread_timer *timer;
00115    int fd;
00116 
00117    if (!(timer = ao2_alloc(sizeof(*timer), pthread_timer_destructor))) {
00118       errno = ENOMEM;
00119       return -1;
00120    }
00121 
00122    timer->pipe[PIPE_READ] = timer->pipe[PIPE_WRITE] = -1;
00123    timer->state = TIMER_STATE_IDLE;
00124 
00125    if (pipe(timer->pipe)) {
00126       ao2_ref(timer, -1);
00127       return -1;
00128    }
00129 
00130    ao2_lock(pthread_timers);
00131    if (!ao2_container_count(pthread_timers)) {
00132       ast_mutex_lock(&timing_thread.lock);
00133       ast_cond_signal(&timing_thread.cond);
00134       ast_mutex_unlock(&timing_thread.lock);
00135    }
00136    ao2_link(pthread_timers, timer);
00137    ao2_unlock(pthread_timers);
00138 
00139    fd = timer->pipe[PIPE_READ];
00140 
00141    ao2_ref(timer, -1);
00142 
00143    return fd;
00144 }

static int pthread_timer_set_rate ( int  handle,
unsigned int  rate 
) [static]

Definition at line 157 of file res_timing_pthread.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_log(), ast_tv(), ast_tvnow(), errno, find_timer(), LOG_ERROR, MAX_RATE, timer, TIMER_STATE_IDLE, and TIMER_STATE_TICKING.

00158 {
00159    struct pthread_timer *timer;
00160 
00161    if (!(timer = find_timer(handle, 0))) {
00162       errno = EINVAL;
00163       return -1;
00164    }
00165 
00166    if (rate > MAX_RATE) {
00167       ast_log(LOG_ERROR, "res_timing_pthread only supports timers at a "
00168             "max rate of %d / sec\n", MAX_RATE);
00169       errno = EINVAL;
00170       return -1;
00171    }
00172 
00173    ao2_lock(timer);
00174 
00175    if ((timer->rate = rate)) {
00176       timer->interval = roundf(1000.0 / ((float) rate));
00177       timer->start = ast_tvnow();
00178       timer->state = TIMER_STATE_TICKING;
00179    } else {
00180       timer->interval = 0;
00181       timer->start = ast_tv(0, 0);
00182       timer->state = TIMER_STATE_IDLE;
00183    }
00184    timer->tick_count = 0;
00185 
00186    ao2_unlock(timer);
00187 
00188    ao2_ref(timer, -1);
00189 
00190    return 0;
00191 }

static void read_pipe ( struct pthread_timer timer,
unsigned int  num 
) [static]

Definition at line 362 of file res_timing_pthread.c.

References ast_assert, ast_debug, ast_log(), ast_poll, errno, LOG_ERROR, PIPE_READ, and timer.

Referenced by pthread_timer_ack(), and pthread_timer_disable_continuous().

00363 {
00364    int rd_fd = timer->pipe[PIPE_READ];
00365    int pending_ticks = timer->pending_ticks;
00366 
00367    ast_assert(quantity);
00368 
00369    if (timer->continuous && pending_ticks) {
00370       pending_ticks--;
00371    }
00372 
00373    if (quantity > pending_ticks) {
00374       quantity = pending_ticks;
00375    }
00376 
00377    if (!quantity) {
00378       return;
00379    }
00380 
00381    do {
00382       unsigned char buf[1024];
00383       ssize_t res;
00384       struct pollfd pfd = {
00385          .fd = rd_fd,
00386          .events = POLLIN,
00387       };
00388 
00389       if (ast_poll(&pfd, 1, 0) != 1) {
00390          ast_debug(1, "Reading not available on timing pipe, "
00391                "quantity: %u\n", quantity);
00392          break;
00393       }
00394 
00395       res = read(rd_fd, buf,
00396          (quantity < sizeof(buf)) ? quantity : sizeof(buf));
00397 
00398       if (res == -1) {
00399          if (errno == EAGAIN) {
00400             continue;
00401          }
00402          ast_log(LOG_ERROR, "read failed on timing pipe: %s\n",
00403                strerror(errno));
00404          break;
00405       }
00406 
00407       quantity -= res;
00408       timer->pending_ticks -= res;
00409    } while (quantity);
00410 }

static int run_timer ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 433 of file res_timing_pthread.c.

References ao2_lock, ao2_unlock, check_timer(), timer, TIMER_STATE_IDLE, and write_byte().

Referenced by do_timing().

00434 {
00435    struct pthread_timer *timer = obj;
00436 
00437    if (timer->state == TIMER_STATE_IDLE) {
00438       return 0;
00439    }
00440 
00441    ao2_lock(timer);
00442    if (check_timer(timer)) {
00443       write_byte(timer);
00444    }
00445    ao2_unlock(timer);
00446 
00447    return 0;
00448 }

static int unload_module ( void   )  [static]

Definition at line 508 of file res_timing_pthread.c.

References ao2_ref, ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_unregister_timing_interface(), pthread_timers, timing_funcs_handle, and timing_thread.

00509 {
00510    int res;
00511 
00512    ast_mutex_lock(&timing_thread.lock);
00513    timing_thread.stop = 1;
00514    ast_cond_signal(&timing_thread.cond);
00515    ast_mutex_unlock(&timing_thread.lock);
00516    pthread_join(timing_thread.thread, NULL);
00517 
00518    if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
00519       ao2_ref(pthread_timers, -1);
00520       pthread_timers = NULL;
00521    }
00522 
00523    return res;
00524 }

static void write_byte ( struct pthread_timer timer  )  [static]

Definition at line 416 of file res_timing_pthread.c.

References ast_log(), errno, LOG_ERROR, PIPE_WRITE, and timer.

Referenced by pthread_timer_enable_continuous(), and run_timer().

00417 {
00418    ssize_t res;
00419    unsigned char x = 42;
00420 
00421    do {
00422       res = write(timer->pipe[PIPE_WRITE], &x, 1);
00423    } while (res == -1 && errno == EAGAIN);
00424 
00425    if (res == -1) {
00426       ast_log(LOG_ERROR, "Error writing to timing pipe: %s\n",
00427             strerror(errno));
00428    } else {
00429       timer->pending_ticks++;
00430    }
00431 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "pthread Timing Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_TIMING, } [static]

Definition at line 529 of file res_timing_pthread.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 529 of file res_timing_pthread.c.

ast_cond_t cond

Definition at line 108 of file res_timing_pthread.c.

ast_mutex_t lock

Definition at line 107 of file res_timing_pthread.c.

struct ao2_container* pthread_timers [static]

Definition at line 72 of file res_timing_pthread.c.

Referenced by do_timing(), find_timer(), load_module(), pthread_timer_open(), and unload_module().

struct ast_timing_interface pthread_timing [static]

Definition at line 56 of file res_timing_pthread.c.

Referenced by load_module().

unsigned int stop

Definition at line 109 of file res_timing_pthread.c.

pthread_t thread

Definition at line 106 of file res_timing_pthread.c.

void* timing_funcs_handle [static]

Definition at line 45 of file res_timing_pthread.c.

struct { ... } timing_thread [static]

Data for the timing thread.

Referenced by do_timing(), init_timing_thread(), pthread_timer_open(), and unload_module().


Generated on Sat Mar 10 01:55:43 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7