Thu Apr 28 2011 16:57:17

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"
Include dependency graph for res_timing_pthread.c:

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_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
__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_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

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.

     {
   PIPE_READ =  0,
   PIPE_WRITE = 1
};
Enumerator:
TIMER_STATE_IDLE 
TIMER_STATE_TICKING 

Definition at line 76 of file res_timing_pthread.c.


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: 278479 $"   
)
static int check_timer ( struct pthread_timer timer) [static]
Return values:
0no timer tick needed
non-zerowrite 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 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]
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().

{
   struct pthread_timer *timer1 = obj, *timer2 = arg;

   return (timer1->pipe[PIPE_READ] == timer2->pipe[PIPE_READ]) ? CMP_MATCH | CMP_STOP : 0;
}
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]

Definition at line 268 of file res_timing_pthread.c.

References MAX_RATE.

{
   return MAX_RATE;
}
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 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]
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]
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++;
   }
}

Variable Documentation

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.

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.

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