Thu Oct 11 06:37:17 2012

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 = AST_MODPRI_TIMING, }
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 69 of file res_timing_timerfd.c.

Referenced by timerfd_timer_get_max_rate().

#define TIMERFD_TIMER_BUCKETS   563

Definition at line 68 of file res_timing_timerfd.c.

Referenced by load_module().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 341 of file res_timing_timerfd.c.

static void __unreg_module ( void   )  [static]

Definition at line 341 of file res_timing_timerfd.c.

static int load_module ( void   )  [static]

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

00302 {
00303    int fd;
00304 
00305    /* Make sure we support the necessary clock type */
00306    if ((fd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) {
00307       ast_log(LOG_ERROR, "timerfd_create() not supported by the kernel.  Not loading.\n");
00308       return AST_MODULE_LOAD_DECLINE;
00309    }
00310 
00311    close(fd);
00312 
00313    if (!(timerfd_timers = ao2_container_alloc(TIMERFD_TIMER_BUCKETS, timerfd_timer_hash, timerfd_timer_cmp))) {
00314       return AST_MODULE_LOAD_DECLINE;
00315    }
00316 
00317    if (!(timing_funcs_handle = ast_register_timing_interface(&timerfd_timing))) {
00318       ao2_ref(timerfd_timers, -1);
00319       return AST_MODULE_LOAD_DECLINE;
00320    }
00321 
00322    return AST_MODULE_LOAD_SUCCESS;
00323 }

static void timer_destroy ( void *  obj  )  [static]

Definition at line 90 of file res_timing_timerfd.c.

References timerfd_timer::handle, and timer.

00091 {
00092    struct timerfd_timer *timer = obj;
00093    close(timer->handle);
00094 }

static void timerfd_timer_ack ( int  handle,
unsigned int  quantity 
) [static]

Definition at line 161 of file res_timing_timerfd.c.

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_log(), errno, LOG_ERROR, and OBJ_POINTER.

00162 {
00163    uint64_t expirations;
00164    int read_result = 0;
00165    struct timerfd_timer *our_timer, find_helper = {
00166       .handle = handle,
00167    };
00168 
00169    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00170       ast_log(LOG_ERROR, "Couldn't find a timer with handle %d\n", handle);
00171       return;
00172    }
00173 
00174    ao2_lock(our_timer);
00175 
00176    do {
00177       struct itimerspec timer_status;
00178 
00179       if (timerfd_gettime(handle, &timer_status)) {
00180          ast_log(LOG_ERROR, "Call to timerfd_gettime() error: %s\n", strerror(errno));
00181          expirations = 0;
00182          break;
00183       }
00184 
00185       if (timer_status.it_value.tv_sec == 0 && timer_status.it_value.tv_nsec == 0) {
00186          ast_debug(1, "Avoiding read on disarmed timerfd %d\n", handle);
00187          expirations = 0;
00188          break;
00189       }
00190 
00191       read_result = read(handle, &expirations, sizeof(expirations));
00192       if (read_result == -1) {
00193          if (errno == EINTR || errno == EAGAIN) {
00194             continue;
00195          } else {
00196             ast_log(LOG_ERROR, "Read error: %s\n", strerror(errno));
00197             break;
00198          }
00199       }
00200    } while (read_result != sizeof(expirations));
00201 
00202    ao2_unlock(our_timer);
00203    ao2_ref(our_timer, -1);
00204 
00205    if (expirations != quantity) {
00206       ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations);
00207    }
00208 }

static void timerfd_timer_close ( int  handle  )  [static]

Definition at line 118 of file res_timing_timerfd.c.

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

00119 {
00120    struct timerfd_timer *our_timer, find_helper = {
00121       .handle = handle,
00122    };
00123 
00124    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00125       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00126       return;
00127    }
00128 
00129    ao2_unlink(timerfd_timers, our_timer);
00130    ao2_ref(our_timer, -1);
00131 }

static int timerfd_timer_cmp ( void *  obj,
void *  args,
int  flags 
) [static]

Definition at line 84 of file res_timing_timerfd.c.

References CMP_MATCH, CMP_STOP, and timerfd_timer::handle.

Referenced by load_module().

00085 {
00086    struct timerfd_timer *timer1 = obj, *timer2 = args;
00087    return timer1->handle == timer2->handle ? CMP_MATCH | CMP_STOP : 0;
00088 }

static int timerfd_timer_disable_continuous ( int  handle  )  [static]

Definition at line 242 of file res_timing_timerfd.c.

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

00243 {
00244    int res;
00245    struct timerfd_timer *our_timer, find_helper = {
00246       .handle = handle,
00247    };
00248 
00249    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00250       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00251       return -1;
00252    }
00253    ao2_lock(our_timer);
00254 
00255    if(!our_timer->is_continuous) {
00256       /* No reason to do anything if we're not
00257        * in continuous mode
00258        */
00259       ao2_unlock(our_timer);
00260       ao2_ref(our_timer, -1);
00261       return 0;
00262    }
00263 
00264    res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
00265    our_timer->is_continuous = 0;
00266    memset(&our_timer->saved_timer, 0, sizeof(our_timer->saved_timer));
00267    ao2_unlock(our_timer);
00268    ao2_ref(our_timer, -1);
00269    return res;
00270 }

static int timerfd_timer_enable_continuous ( int  handle  )  [static]

Definition at line 210 of file res_timing_timerfd.c.

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

00211 {
00212    int res;
00213    struct itimerspec continuous_timer = {
00214       .it_value.tv_nsec = 1L,
00215    };
00216    struct timerfd_timer *our_timer, find_helper = {
00217       .handle = handle,
00218    };
00219 
00220    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00221       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00222       return -1;
00223    }
00224    ao2_lock(our_timer);
00225 
00226    if (our_timer->is_continuous) {
00227       /*It's already in continous mode, no need to do
00228        * anything further
00229        */
00230       ao2_unlock(our_timer);
00231       ao2_ref(our_timer, -1);
00232       return 0;
00233    }
00234 
00235    res = timerfd_settime(handle, 0, &continuous_timer, &our_timer->saved_timer);
00236    our_timer->is_continuous = 1;
00237    ao2_unlock(our_timer);
00238    ao2_ref(our_timer, -1);
00239    return res;
00240 }

static enum ast_timer_event timerfd_timer_get_event ( int  handle  )  [static]

Definition at line 272 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::is_continuous, LOG_ERROR, and OBJ_POINTER.

00273 {
00274    enum ast_timer_event res;
00275    struct timerfd_timer *our_timer, find_helper = {
00276       .handle = handle,
00277    };
00278 
00279    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00280       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00281       return -1;
00282    }
00283    ao2_lock(our_timer);
00284 
00285    if (our_timer->is_continuous) {
00286       res = AST_TIMING_EVENT_CONTINUOUS;
00287    } else {
00288       res = AST_TIMING_EVENT_EXPIRED;
00289    }
00290 
00291    ao2_unlock(our_timer);
00292    ao2_ref(our_timer, -1);
00293    return res;
00294 }

static unsigned int timerfd_timer_get_max_rate ( int  handle  )  [static]

Definition at line 296 of file res_timing_timerfd.c.

References TIMERFD_MAX_RATE.

00297 {
00298    return TIMERFD_MAX_RATE;
00299 }

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

Definition at line 77 of file res_timing_timerfd.c.

References timerfd_timer::handle, and timer.

Referenced by load_module().

00078 {
00079    const struct timerfd_timer *timer = obj;
00080 
00081    return timer->handle;
00082 }

static int timerfd_timer_open ( void   )  [static]

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

00097 {
00098    struct timerfd_timer *timer;
00099    int handle;
00100 
00101    if (!(timer = ao2_alloc(sizeof(*timer), timer_destroy))) {
00102       ast_log(LOG_ERROR, "Could not allocate memory for timerfd_timer structure\n");
00103       return -1;
00104    }
00105    if ((handle = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) {
00106       ast_log(LOG_ERROR, "Failed to create timerfd timer: %s\n", strerror(errno));
00107       ao2_ref(timer, -1);
00108       return -1;
00109    }
00110 
00111    timer->handle = handle;
00112    ao2_link(timerfd_timers, timer);
00113    /* Get rid of the reference from the allocation */
00114    ao2_ref(timer, -1);
00115    return handle;
00116 }

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

Definition at line 133 of file res_timing_timerfd.c.

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

00134 {
00135    struct timerfd_timer *our_timer, find_helper = {
00136       .handle = handle,
00137    };
00138    int res = 0;
00139 
00140    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00141       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00142       return -1;
00143    }
00144    ao2_lock(our_timer);
00145 
00146    our_timer->saved_timer.it_value.tv_sec = 0;
00147    our_timer->saved_timer.it_value.tv_nsec = rate ? (long) (1000000000 / rate) : 0L;
00148    our_timer->saved_timer.it_interval.tv_sec = our_timer->saved_timer.it_value.tv_sec;
00149    our_timer->saved_timer.it_interval.tv_nsec = our_timer->saved_timer.it_value.tv_nsec;
00150 
00151    if (!our_timer->is_continuous) {
00152       res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
00153    }
00154 
00155    ao2_unlock(our_timer);
00156    ao2_ref(our_timer, -1);
00157 
00158    return res;
00159 }

static int unload_module ( void   )  [static]

Definition at line 325 of file res_timing_timerfd.c.

References ao2_ref, ast_unregister_timing_interface(), and timing_funcs_handle.

00326 {
00327    int res;
00328 
00329    if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
00330       ao2_ref(timerfd_timers, -1);
00331       timerfd_timers = NULL;
00332    }
00333 
00334    return res;
00335 }


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 = AST_MODPRI_TIMING, } [static]

Definition at line 341 of file res_timing_timerfd.c.

Definition at line 341 of file res_timing_timerfd.c.

struct ao2_container* timerfd_timers [static]

Definition at line 66 of file res_timing_timerfd.c.

Definition at line 53 of file res_timing_timerfd.c.

void* timing_funcs_handle [static]

Definition at line 42 of file res_timing_timerfd.c.


Generated on Thu Oct 11 06:37:18 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6