Fri Jul 24 00:41:57 2009

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"

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, TIMER_STATE_CONTINUOUS }

Functions

static void __reg_module (void)
static void __unreg_module (void)
 ASTERISK_FILE_VERSION (__FILE__,"$Revision: 176675 $")
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 (int rd_fd, unsigned int num, int clear)
static int run_timer (void *obj, void *arg, int flags)
static void set_state (struct pthread_timer *timer)
static int unload_module (void)
static void write_byte (int wr_fd)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, }
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 65 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 68 of file res_timing_pthread.c.

Referenced by load_module().


Enumeration Type Documentation

anonymous enum

Enumerator:
PIPE_READ 
PIPE_WRITE 

Definition at line 70 of file res_timing_pthread.c.

00070      {
00071    PIPE_READ =  0,
00072    PIPE_WRITE = 1
00073 };

enum pthread_timer_state

Enumerator:
TIMER_STATE_IDLE 
TIMER_STATE_TICKING 
TIMER_STATE_CONTINUOUS 

Definition at line 75 of file res_timing_pthread.c.

00075                          {
00076    TIMER_STATE_IDLE,
00077    TIMER_STATE_TICKING,
00078    TIMER_STATE_CONTINUOUS,
00079 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 513 of file res_timing_pthread.c.

static void __unreg_module ( void   )  [static]

Definition at line 513 of file res_timing_pthread.c.

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

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 337 of file res_timing_pthread.c.

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

Referenced by run_timer().

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

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

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

00438 {
00439    struct timeval next_wakeup = ast_tvnow();
00440 
00441    while (!timing_thread.stop) {
00442       struct timespec ts = { 0, };
00443 
00444       ao2_callback(pthread_timers, OBJ_NODATA, run_timer, NULL);
00445 
00446       next_wakeup = ast_tvadd(next_wakeup, ast_tv(0, 5000));
00447 
00448       ts.tv_sec = next_wakeup.tv_sec;
00449       ts.tv_nsec = next_wakeup.tv_usec * 1000;
00450 
00451       ast_mutex_lock(&timing_thread.lock);
00452       if (!timing_thread.stop) {
00453          if (ao2_container_count(pthread_timers)) {
00454             ast_cond_timedwait(&timing_thread.cond, &timing_thread.lock, &ts);
00455          } else {
00456             ast_cond_wait(&timing_thread.cond, &timing_thread.lock);
00457          }
00458       }
00459       ast_mutex_unlock(&timing_thread.lock);
00460    }
00461 
00462    return NULL;
00463 }

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

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

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

static int init_timing_thread ( void   )  [static]

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

00466 {
00467    ast_mutex_init(&timing_thread.lock);
00468    ast_cond_init(&timing_thread.cond, NULL);
00469 
00470    if (ast_pthread_create_background(&timing_thread.thread, NULL, do_timing, NULL)) {
00471       ast_log(LOG_ERROR, "Unable to start timing thread.\n");
00472       return -1;
00473    }
00474 
00475    return 0;
00476 }

static int load_module ( void   )  [static]

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

References ao2_ref, ast_assert, find_timer(), PIPE_READ, read_pipe(), timer, and TIMER_STATE_CONTINUOUS.

00198 {
00199    struct pthread_timer *timer;
00200 
00201    ast_assert(quantity > 0);
00202 
00203    if (!(timer = find_timer(handle, 0))) {
00204       return;
00205    }
00206 
00207    if (timer->state == TIMER_STATE_CONTINUOUS) {
00208       /* Leave the pipe alone, please! */
00209       return;
00210    }
00211 
00212    read_pipe(timer->pipe[PIPE_READ], quantity, 0);
00213 
00214    ao2_ref(timer, -1);
00215 }

static void pthread_timer_close ( int  handle  )  [static]

Definition at line 140 of file res_timing_pthread.c.

References ao2_ref, find_timer(), and timer.

00141 {
00142    struct pthread_timer *timer;
00143 
00144    if (!(timer = find_timer(handle, 1))) {
00145       return;
00146    }
00147 
00148    ao2_ref(timer, -1);
00149 }

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

Note:
only PIPE_READ is guaranteed valid

Definition at line 326 of file res_timing_pthread.c.

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

Referenced by load_module().

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

static void pthread_timer_destructor ( void *  obj  )  [static]

Definition at line 298 of file res_timing_pthread.c.

References PIPE_READ, PIPE_WRITE, and timer.

Referenced by pthread_timer_open().

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

static int pthread_timer_disable_continuous ( int  handle  )  [static]

Definition at line 236 of file res_timing_pthread.c.

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

00237 {
00238    struct pthread_timer *timer;
00239 
00240    if (!(timer = find_timer(handle, 0))) {
00241       errno = EINVAL;
00242       return -1;
00243    }
00244 
00245    ao2_lock(timer);
00246    set_state(timer);
00247    read_pipe(timer->pipe[PIPE_READ], 0, 1);
00248    ao2_unlock(timer);
00249 
00250    ao2_ref(timer, -1);
00251 
00252    return 0;
00253 }

static int pthread_timer_enable_continuous ( int  handle  )  [static]

Definition at line 217 of file res_timing_pthread.c.

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

00218 {
00219    struct pthread_timer *timer;
00220 
00221    if (!(timer = find_timer(handle, 0))) {
00222       errno = EINVAL;
00223       return -1;
00224    }
00225 
00226    ao2_lock(timer);
00227    timer->state = TIMER_STATE_CONTINUOUS;
00228    write_byte(timer->pipe[PIPE_WRITE]);
00229    ao2_unlock(timer);
00230 
00231    ao2_ref(timer, -1);
00232 
00233    return 0;
00234 }

static enum ast_timer_event pthread_timer_get_event ( int  handle  )  [static]

Definition at line 255 of file res_timing_pthread.c.

References ao2_ref, AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, find_timer(), timer, and TIMER_STATE_CONTINUOUS.

00256 {
00257    struct pthread_timer *timer;
00258    enum ast_timer_event res = AST_TIMING_EVENT_EXPIRED;
00259 
00260    if (!(timer = find_timer(handle, 0))) {
00261       return res;
00262    }
00263 
00264    if (timer->state == TIMER_STATE_CONTINUOUS) {
00265       res = AST_TIMING_EVENT_CONTINUOUS;
00266    }
00267 
00268    ao2_ref(timer, -1);
00269 
00270    return res;
00271 }

static unsigned int pthread_timer_get_max_rate ( int  handle  )  [static]

Definition at line 273 of file res_timing_pthread.c.

References MAX_RATE.

00274 {
00275    return MAX_RATE;
00276 }

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

Note:
only PIPE_READ is guaranteed valid

Definition at line 316 of file res_timing_pthread.c.

References PIPE_READ, and timer.

Referenced by load_module().

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

static int pthread_timer_open ( void   )  [static]

Definition at line 106 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.

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

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

Definition at line 168 of file res_timing_pthread.c.

References ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), errno, find_timer(), LOG_ERROR, MAX_RATE, set_state(), timer, and TIMER_STATE_CONTINUOUS.

00169 {
00170    struct pthread_timer *timer;
00171 
00172    if (!(timer = find_timer(handle, 0))) {
00173       errno = EINVAL;
00174       return -1;
00175    }
00176 
00177    if (rate > MAX_RATE) {
00178       ast_log(LOG_ERROR, "res_timing_pthread only supports timers at a max rate of %d / sec\n",
00179          MAX_RATE);
00180       errno = EINVAL;
00181       return -1;
00182    }
00183 
00184    ao2_lock(timer);
00185    timer->rate = rate;
00186    if (timer->state != TIMER_STATE_CONTINUOUS) {
00187       set_state(timer);
00188    }
00189    
00190    ao2_unlock(timer);
00191 
00192    ao2_ref(timer, -1);
00193 
00194    return 0;
00195 }

static void read_pipe ( int  rd_fd,
unsigned int  num,
int  clear 
) [static]

Definition at line 358 of file res_timing_pthread.c.

References ast_assert, ast_log(), buf, errno, and LOG_ERROR.

Referenced by pthread_timer_ack(), and pthread_timer_disable_continuous().

00359 {
00360    ast_assert(quantity || clear);
00361 
00362    if (!quantity && clear) {
00363       quantity = 1;
00364    }
00365 
00366    do {
00367       unsigned char buf[1024];
00368       ssize_t res;
00369       fd_set rfds;
00370       struct timeval timeout = {
00371          .tv_sec = 0,
00372       };
00373 
00374       /* Make sure there is data to read */
00375       FD_ZERO(&rfds);
00376       FD_SET(rd_fd, &rfds);
00377 
00378       if (select(rd_fd + 1, &rfds, NULL, NULL, &timeout) != 1) {
00379          break;
00380       }
00381 
00382       res = read(rd_fd, buf, 
00383          (quantity < sizeof(buf)) ? quantity : sizeof(buf));
00384 
00385       if (res == -1) {
00386          if (errno == EAGAIN) {
00387             continue;
00388          }
00389          ast_log(LOG_ERROR, "read failed on timing pipe: %s\n", strerror(errno));
00390          break;
00391       }
00392 
00393       if (clear) {
00394          continue;
00395       }
00396 
00397       quantity -= res;
00398    } while (quantity);
00399 }

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

Definition at line 418 of file res_timing_pthread.c.

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

Referenced by do_timing().

00419 {
00420    struct pthread_timer *timer = obj;
00421 
00422    if (timer->state == TIMER_STATE_IDLE) {
00423       return 0;
00424    }
00425 
00426    ao2_lock(timer);
00427 
00428    if (check_timer(timer)) {
00429       write_byte(timer->pipe[PIPE_WRITE]);
00430    }
00431    
00432    ao2_unlock(timer);
00433 
00434    return 0;
00435 }

static void set_state ( struct pthread_timer timer  )  [static]

Definition at line 151 of file res_timing_pthread.c.

References ast_tv(), ast_tvnow(), pthread_timer::rate, timer, TIMER_STATE_IDLE, and TIMER_STATE_TICKING.

00152 {
00153    unsigned int rate = timer->rate;
00154 
00155    if (rate) {
00156       timer->state = TIMER_STATE_TICKING;
00157       timer->interval = roundf(1000.0 / ((float) rate));
00158       timer->start = ast_tvnow();
00159    } else {
00160       timer->state = TIMER_STATE_IDLE;
00161       timer->interval = 0;
00162       timer->start = ast_tv(0, 0);
00163    }
00164 
00165    timer->tick_count = 0;
00166 }

static int unload_module ( void   )  [static]

Definition at line 495 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.

00496 {
00497    int res;
00498 
00499    ast_mutex_lock(&timing_thread.lock);
00500    timing_thread.stop = 1;
00501    ast_cond_signal(&timing_thread.cond);
00502    ast_mutex_unlock(&timing_thread.lock);
00503    pthread_join(timing_thread.thread, NULL);
00504 
00505    if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
00506       ao2_ref(pthread_timers, -1);
00507       pthread_timers = NULL;
00508    }
00509 
00510    return res;
00511 }

static void write_byte ( int  wr_fd  )  [static]

Definition at line 401 of file res_timing_pthread.c.

References ast_log(), errno, and LOG_ERROR.

Referenced by pthread_timer_enable_continuous(), and run_timer().

00402 {
00403    do {
00404       ssize_t res;
00405       unsigned char x = 42;
00406 
00407       res = write(wr_fd, &x, 1); 
00408 
00409       if (res == -1) {
00410          if (errno == EAGAIN) {
00411             continue;
00412          }
00413          ast_log(LOG_ERROR, "Error writing to timing pipe: %s\n", strerror(errno));
00414       }
00415    } while (0);
00416 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 513 of file res_timing_pthread.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 513 of file res_timing_pthread.c.

ast_cond_t cond

Definition at line 102 of file res_timing_pthread.c.

ast_mutex_t lock

Definition at line 101 of file res_timing_pthread.c.

struct ao2_container* pthread_timers [static]

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

Referenced by load_module().

unsigned int stop

Definition at line 103 of file res_timing_pthread.c.

pthread_t thread

Definition at line 100 of file res_timing_pthread.c.

void* timing_funcs_handle [static]

Definition at line 40 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 Fri Jul 24 00:41:57 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7