Thu Apr 28 2011 17:14:02

Asterisk developer's documentation


res_timing_timerfd.c File Reference

timerfd timing interface More...

#include "asterisk.h"
#include <sys/timerfd.h>
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/timing.h"
#include "asterisk/logger.h"
#include "asterisk/utils.h"
#include "asterisk/time.h"
Include dependency graph for res_timing_timerfd.c:

Go to the source code of this file.

Data Structures

struct  timerfd_timer

Defines

#define TIMERFD_MAX_RATE   1000
#define TIMERFD_TIMER_BUCKETS   563

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int load_module (void)
static void timer_destroy (void *obj)
static void timerfd_timer_ack (int handle, unsigned int quantity)
static void timerfd_timer_close (int handle)
static int timerfd_timer_cmp (void *obj, void *args, int flags)
static int timerfd_timer_disable_continuous (int handle)
static int timerfd_timer_enable_continuous (int handle)
static enum ast_timer_event timerfd_timer_get_event (int handle)
static unsigned int timerfd_timer_get_max_rate (int handle)
static int timerfd_timer_hash (const void *obj, const int flags)
static int timerfd_timer_open (void)
static int timerfd_timer_set_rate (int handle, unsigned int rate)
static int unload_module (void)

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Timerfd 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_containertimerfd_timers
static struct ast_timing_interface timerfd_timing
static void * timing_funcs_handle

Detailed Description

timerfd timing interface

Author:
Mark Michelson <mmichelson@digium.com>

Definition in file res_timing_timerfd.c.


Define Documentation

#define TIMERFD_MAX_RATE   1000

Definition at line 68 of file res_timing_timerfd.c.

Referenced by timerfd_timer_get_max_rate().

#define TIMERFD_TIMER_BUCKETS   563

Definition at line 67 of file res_timing_timerfd.c.

Referenced by load_module().


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 313 of file res_timing_timerfd.c.

static void __unreg_module ( void  ) [static]

Definition at line 313 of file res_timing_timerfd.c.

static int load_module ( void  ) [static]

Definition at line 273 of file res_timing_timerfd.c.

References ao2_container_alloc, ao2_ref, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_timing_interface, LOG_ERROR, TIMERFD_TIMER_BUCKETS, timerfd_timer_cmp(), timerfd_timer_hash(), and timing_funcs_handle.

{
   int fd;

   /* Make sure we support the necessary clock type */
   if ((fd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) {
      ast_log(LOG_ERROR, "CLOCK_MONOTONIC not supported.  Not loading.\n");
      return AST_MODULE_LOAD_DECLINE;
   }

   close(fd);

   if (!(timerfd_timers = ao2_container_alloc(TIMERFD_TIMER_BUCKETS, timerfd_timer_hash, timerfd_timer_cmp))) {
      return AST_MODULE_LOAD_DECLINE;
   }

   if (!(timing_funcs_handle = ast_register_timing_interface(&timerfd_timing))) {
      ao2_ref(timerfd_timers, -1);
      return AST_MODULE_LOAD_DECLINE;
   }

   return AST_MODULE_LOAD_SUCCESS;
}
static void timer_destroy ( void *  obj) [static]

Definition at line 89 of file res_timing_timerfd.c.

References timerfd_timer::handle, and timer.

Referenced by timerfd_timer_open().

{
   struct timerfd_timer *timer = obj;
   close(timer->handle);
}
static void timerfd_timer_ack ( int  handle,
unsigned int  quantity 
) [static]

Definition at line 160 of file res_timing_timerfd.c.

References ast_debug, ast_log(), errno, and LOG_ERROR.

{
   uint64_t expirations;
   int read_result = 0;

   do {
      read_result = read(handle, &expirations, sizeof(expirations));
      if (read_result == -1) {
         if (errno == EINTR || errno == EAGAIN) {
            continue;
         } else {
            ast_log(LOG_ERROR, "Read error: %s\n", strerror(errno));
            break;
         }
      }
   } while (read_result != sizeof(expirations));

   if (expirations != quantity) {
      ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations);
   }
}
static void timerfd_timer_close ( int  handle) [static]

Definition at line 117 of file res_timing_timerfd.c.

References ao2_find, ao2_ref, ao2_unlink, ast_log(), timerfd_timer::handle, LOG_ERROR, and OBJ_POINTER.

{
   struct timerfd_timer *our_timer, find_helper = {
      .handle = handle,
   };

   if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
      ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
      return;
   }

   ao2_unlink(timerfd_timers, our_timer);
   ao2_ref(our_timer, -1);
}
static int timerfd_timer_cmp ( void *  obj,
void *  args,
int  flags 
) [static]

Definition at line 83 of file res_timing_timerfd.c.

References CMP_MATCH, CMP_STOP, and timerfd_timer::handle.

Referenced by load_module().

{
   struct timerfd_timer *timer1 = obj, *timer2 = args;
   return timer1->handle == timer2->handle ? CMP_MATCH | CMP_STOP : 0;
}
static int timerfd_timer_disable_continuous ( int  handle) [static]

Definition at line 214 of file res_timing_timerfd.c.

References ao2_find, ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), timerfd_timer::handle, timerfd_timer::is_continuous, LOG_ERROR, OBJ_POINTER, and timerfd_timer::saved_timer.

{
   int res;
   struct timerfd_timer *our_timer, find_helper = {
      .handle = handle,
   };

   if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
      ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
      return -1;
   }
   ao2_lock(our_timer);

   if(!our_timer->is_continuous) {
      /* No reason to do anything if we're not
       * in continuous mode
       */
      ao2_unlock(our_timer);
      ao2_ref(our_timer, -1);
      return 0;
   }

   res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
   our_timer->is_continuous = 0;
   memset(&our_timer->saved_timer, 0, sizeof(our_timer->saved_timer));
   ao2_unlock(our_timer);
   ao2_ref(our_timer, -1);
   return res;
}
static int timerfd_timer_enable_continuous ( int  handle) [static]

Definition at line 182 of file res_timing_timerfd.c.

References ao2_find, ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), timerfd_timer::handle, timerfd_timer::is_continuous, LOG_ERROR, OBJ_POINTER, and timerfd_timer::saved_timer.

{
   int res;
   struct itimerspec continuous_timer = {
      .it_value.tv_nsec = 1L,
   };
   struct timerfd_timer *our_timer, find_helper = {
      .handle = handle,
   };

   if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
      ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
      return -1;
   }
   ao2_lock(our_timer);

   if (our_timer->is_continuous) {
      /*It's already in continous mode, no need to do
       * anything further
       */
      ao2_unlock(our_timer);
      ao2_ref(our_timer, -1);
      return 0;
   }

   res = timerfd_settime(handle, 0, &continuous_timer, &our_timer->saved_timer);
   our_timer->is_continuous = 1;
   ao2_unlock(our_timer);
   ao2_ref(our_timer, -1);
   return res;
}
static enum ast_timer_event timerfd_timer_get_event ( int  handle) [static]

Definition at line 244 of file res_timing_timerfd.c.

References ao2_find, ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, timerfd_timer::handle, timerfd_timer::is_continuous, LOG_ERROR, and OBJ_POINTER.

{
   enum ast_timer_event res;
   struct timerfd_timer *our_timer, find_helper = {
      .handle = handle,
   };

   if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
      ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
      return -1;
   }
   ao2_lock(our_timer);

   if (our_timer->is_continuous) {
      res = AST_TIMING_EVENT_CONTINUOUS;
   } else {
      res = AST_TIMING_EVENT_EXPIRED;
   }

   ao2_unlock(our_timer);
   ao2_ref(our_timer, -1);
   return res;
}
static unsigned int timerfd_timer_get_max_rate ( int  handle) [static]

Definition at line 268 of file res_timing_timerfd.c.

References TIMERFD_MAX_RATE.

{
   return TIMERFD_MAX_RATE;
}
static int timerfd_timer_hash ( const void *  obj,
const int  flags 
) [static]

Definition at line 76 of file res_timing_timerfd.c.

References timerfd_timer::handle, and timer.

Referenced by load_module().

{
   const struct timerfd_timer *timer = obj;

   return timer->handle;
}
static int timerfd_timer_open ( void  ) [static]

Definition at line 95 of file res_timing_timerfd.c.

References ao2_alloc, ao2_link, ao2_ref, ast_log(), errno, timerfd_timer::handle, LOG_ERROR, timer, and timer_destroy().

{
   struct timerfd_timer *timer;
   int handle;

   if (!(timer = ao2_alloc(sizeof(*timer), timer_destroy))) {
      ast_log(LOG_ERROR, "Could not allocate memory for timerfd_timer structure\n");
      return -1;
   }
   if ((handle = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) {
      ast_log(LOG_ERROR, "Failed to create timerfd timer: %s\n", strerror(errno));
      ao2_ref(timer, -1);
      return -1;
   }

   timer->handle = handle;
   ao2_link(timerfd_timers, timer);
   /* Get rid of the reference from the allocation */
   ao2_ref(timer, -1);
   return handle;
}
static int timerfd_timer_set_rate ( int  handle,
unsigned int  rate 
) [static]

Definition at line 132 of file res_timing_timerfd.c.

References ao2_find, ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), timerfd_timer::handle, timerfd_timer::is_continuous, LOG_ERROR, OBJ_POINTER, and timerfd_timer::saved_timer.

{
   struct timerfd_timer *our_timer, find_helper = {
      .handle = handle,
   };
   int res = 0;

   if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
      ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
      return -1;
   }
   ao2_lock(our_timer);

   our_timer->saved_timer.it_value.tv_sec = 0;
   our_timer->saved_timer.it_value.tv_nsec = rate ? (long) (1000000000 / rate) : 0L;
   our_timer->saved_timer.it_interval.tv_sec = our_timer->saved_timer.it_value.tv_sec;
   our_timer->saved_timer.it_interval.tv_nsec = our_timer->saved_timer.it_value.tv_nsec;

   if (!our_timer->is_continuous) {
      res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
   }

   ao2_unlock(our_timer);
   ao2_ref(our_timer, -1);

   return res;
}
static int unload_module ( void  ) [static]

Definition at line 297 of file res_timing_timerfd.c.

References ao2_ref, ast_unregister_timing_interface(), and timing_funcs_handle.

{
   int res;

   if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
      ao2_ref(timerfd_timers, -1);
      timerfd_timers = NULL;
   }

   return res;
}

Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Timerfd Timing Interface" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = 10, } [static]

Definition at line 313 of file res_timing_timerfd.c.

Definition at line 313 of file res_timing_timerfd.c.

struct ao2_container* timerfd_timers [static]

Definition at line 65 of file res_timing_timerfd.c.

Definition at line 52 of file res_timing_timerfd.c.

void* timing_funcs_handle [static]

Definition at line 41 of file res_timing_timerfd.c.

Referenced by load_module(), and unload_module().