Mon Jun 27 16:51:20 2011

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: 278465 $")
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
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 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().


Enumeration Type Documentation

anonymous enum

Enumerator:
PIPE_READ 
PIPE_WRITE 

Definition at line 71 of file res_timing_pthread.c.

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

enum pthread_timer_state

Enumerator:
TIMER_STATE_IDLE 
TIMER_STATE_TICKING 

Definition at line 76 of file res_timing_pthread.c.

00076                          {
00077    TIMER_STATE_IDLE,
00078    TIMER_STATE_TICKING,
00079 };


Function Documentation

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: 278465 $"   
)

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

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

Referenced by run_timer().

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

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

Referenced by init_timing_thread().

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

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

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

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

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().

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

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

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.

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

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.

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

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

Note:
only PIPE_READ is guaranteed valid

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().

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

static void pthread_timer_destructor ( void *  obj  )  [static]

Definition at line 293 of file res_timing_pthread.c.

References PIPE_READ, PIPE_WRITE, and timer.

Referenced by pthread_timer_open().

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

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, errno, find_timer(), read_pipe(), and timer.

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

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, errno, find_timer(), timer, and write_byte().

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

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, find_timer(), and timer.

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

static unsigned int pthread_timer_get_max_rate ( int  handle  )  [static]

Definition at line 268 of file res_timing_pthread.c.

References MAX_RATE.

00269 {
00270    return MAX_RATE;
00271 }

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

Note:
only PIPE_READ is guaranteed valid

Definition at line 311 of file res_timing_pthread.c.

References PIPE_READ, and timer.

Referenced by load_module().

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

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_timers, timer, TIMER_STATE_IDLE, and timing_thread.

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

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(), LOG_ERROR, MAX_RATE, timer, TIMER_STATE_IDLE, and TIMER_STATE_TICKING.

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

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, errno, LOG_ERROR, PIPE_READ, and timer.

Referenced by pthread_timer_ack(), and pthread_timer_disable_continuous().

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

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(), timer, TIMER_STATE_IDLE, and write_byte().

Referenced by do_timing().

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

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(), pthread_timers, timing_funcs_handle, and timing_thread.

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

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, PIPE_WRITE, and timer.

Referenced by pthread_timer_enable_continuous(), and run_timer().

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


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [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.

ast_cond_t cond

Definition at line 104 of file res_timing_pthread.c.

ast_mutex_t lock

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.

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

struct ast_timing_interface pthread_timing [static]

Definition at line 52 of file res_timing_pthread.c.

Referenced by load_module().

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.

struct { ... } timing_thread [static]

Data for the timing thread.

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


Generated on Mon Jun 27 16:51:20 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7