Fri Jul 15 2011 12:02:54

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 __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Timerfd 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 = 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 __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Timerfd 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 = 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().