Wed Aug 18 22:34:32 2010

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 }

Functions

static void __reg_module (void)
static void __unreg_module (void)
 ASTERISK_FILE_VERSION (__FILE__,"$Revision: 199745 $")
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .load_pri = 10, }
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 

Definition at line 75 of file res_timing_pthread.c.

00075                          {
00076    TIMER_STATE_IDLE,
00077    TIMER_STATE_TICKING,
00078 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 528 of file res_timing_pthread.c.

static void __unreg_module ( void   )  [static]

Definition at line 528 of file res_timing_pthread.c.

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

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

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

Referenced by run_timer().

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

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

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

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

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

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

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

static int init_timing_thread ( void   )  [static]

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

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

static int load_module ( void   )  [static]

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

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

00189 {
00190    struct pthread_timer *timer;
00191 
00192    ast_assert(quantity > 0);
00193 
00194    if (!(timer = find_timer(handle, 0))) {
00195       return;
00196    }
00197 
00198    ao2_lock(timer);
00199    read_pipe(timer, quantity);
00200    ao2_unlock(timer);
00201 
00202    ao2_ref(timer, -1);
00203 }

static void pthread_timer_close ( int  handle  )  [static]

Definition at line 141 of file res_timing_pthread.c.

References ao2_ref, find_timer(), and timer.

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

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

Note:
only PIPE_READ is guaranteed valid

Definition at line 320 of file res_timing_pthread.c.

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

Referenced by load_module().

00321 {
00322    struct pthread_timer *timer1 = obj, *timer2 = arg;
00323 
00324    return (timer1->pipe[PIPE_READ] == timer2->pipe[PIPE_READ]) ? CMP_MATCH | CMP_STOP : 0;
00325 }

static void pthread_timer_destructor ( void *  obj  )  [static]

Definition at line 292 of file res_timing_pthread.c.

References PIPE_READ, PIPE_WRITE, and timer.

Referenced by pthread_timer_open().

00293 {
00294    struct pthread_timer *timer = obj;
00295 
00296    if (timer->pipe[PIPE_READ] > -1) {
00297       close(timer->pipe[PIPE_READ]);
00298       timer->pipe[PIPE_READ] = -1;
00299    }
00300 
00301    if (timer->pipe[PIPE_WRITE] > -1) {
00302       close(timer->pipe[PIPE_WRITE]);
00303       timer->pipe[PIPE_WRITE] = -1;
00304    }
00305 }

static int pthread_timer_disable_continuous ( int  handle  )  [static]

Definition at line 226 of file res_timing_pthread.c.

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

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

static int pthread_timer_enable_continuous ( int  handle  )  [static]

Definition at line 205 of file res_timing_pthread.c.

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

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

static enum ast_timer_event pthread_timer_get_event ( int  handle  )  [static]

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

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

static unsigned int pthread_timer_get_max_rate ( int  handle  )  [static]

Definition at line 267 of file res_timing_pthread.c.

References MAX_RATE.

00268 {
00269    return MAX_RATE;
00270 }

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

Note:
only PIPE_READ is guaranteed valid

Definition at line 310 of file res_timing_pthread.c.

References PIPE_READ, and timer.

Referenced by load_module().

00311 {
00312    const struct pthread_timer *timer = obj;
00313 
00314    return timer->pipe[PIPE_READ];
00315 }

static int pthread_timer_open ( void   )  [static]

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

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

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

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

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

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

Definition at line 357 of file res_timing_pthread.c.

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

Referenced by pthread_timer_ack(), and pthread_timer_disable_continuous().

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

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

Definition at line 432 of file res_timing_pthread.c.

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

Referenced by do_timing().

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

static int unload_module ( void   )  [static]

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

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

static void write_byte ( struct pthread_timer timer  )  [static]

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

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


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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .load_pri = 10, } [static]

Definition at line 528 of file res_timing_pthread.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 528 of file res_timing_pthread.c.

ast_cond_t cond

Definition at line 103 of file res_timing_pthread.c.

ast_mutex_t lock

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

pthread_t thread

Definition at line 101 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 Wed Aug 18 22:34:32 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7