Mon Aug 31 12:30:44 2015

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"

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 int 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 = "ac1f6a56484a8820659555499174e588" , .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 376 of file res_timing_timerfd.c.

static void __unreg_module ( void   )  [static]

Definition at line 376 of file res_timing_timerfd.c.

static int load_module ( void   )  [static]

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

00337 {
00338    int fd;
00339 
00340    /* Make sure we support the necessary clock type */
00341    if ((fd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) {
00342       ast_log(LOG_ERROR, "timerfd_create() not supported by the kernel.  Not loading.\n");
00343       return AST_MODULE_LOAD_DECLINE;
00344    }
00345 
00346    close(fd);
00347 
00348    if (!(timerfd_timers = ao2_container_alloc(TIMERFD_TIMER_BUCKETS, timerfd_timer_hash, timerfd_timer_cmp))) {
00349       return AST_MODULE_LOAD_DECLINE;
00350    }
00351 
00352    if (!(timing_funcs_handle = ast_register_timing_interface(&timerfd_timing))) {
00353       ao2_ref(timerfd_timers, -1);
00354       return AST_MODULE_LOAD_DECLINE;
00355    }
00356 
00357    return AST_MODULE_LOAD_SUCCESS;
00358 }

static void timer_destroy ( void *  obj  )  [static]

Definition at line 90 of file res_timing_timerfd.c.

References timerfd_timer::handle, and timer.

Referenced by timerfd_timer_open().

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

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

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

00173 {
00174    uint64_t expirations;
00175    int read_result = 0;
00176    int res = 0;
00177    struct timerfd_timer *our_timer, find_helper = {
00178       .handle = handle,
00179    };
00180 
00181    if (handle == -1) {
00182       ast_log(LOG_ERROR, "Attempting to ack timerfd handle -1");
00183       return -1;
00184    }
00185 
00186    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00187       ast_log(LOG_ERROR, "Couldn't find a timer with handle %d\n", handle);
00188       return -1;
00189    }
00190 
00191    ao2_lock(our_timer);
00192 
00193    do {
00194       struct itimerspec timer_status;
00195 
00196       if (timerfd_gettime(handle, &timer_status)) {
00197          ast_log(LOG_ERROR, "Call to timerfd_gettime() using handle %d error: %s\n", handle, strerror(errno));
00198          expirations = 0;
00199          res = -1;
00200          break;
00201       }
00202 
00203       if (timer_status.it_value.tv_sec == 0 && timer_status.it_value.tv_nsec == 0) {
00204          ast_debug(1, "Avoiding read on disarmed timerfd %d\n", handle);
00205          expirations = 0;
00206          break;
00207       }
00208 
00209       read_result = read(handle, &expirations, sizeof(expirations));
00210       if (read_result == -1) {
00211          if (errno == EINTR || errno == EAGAIN) {
00212             continue;
00213          } else {
00214             ast_log(LOG_ERROR, "Read error: %s\n", strerror(errno));
00215             res = -1;
00216             break;
00217          }
00218       }
00219    } while (read_result != sizeof(expirations));
00220 
00221    ao2_unlock(our_timer);
00222    ao2_ref(our_timer, -1);
00223 
00224    if (expirations != quantity) {
00225       ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations);
00226    }
00227    return res;
00228 }

static void timerfd_timer_close ( int  handle  )  [static]

Definition at line 119 of file res_timing_timerfd.c.

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

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

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 267 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.

00268 {
00269    int res;
00270    struct timerfd_timer *our_timer, find_helper = {
00271       .handle = handle,
00272    };
00273 
00274    if (handle == -1) {
00275       ast_log(LOG_ERROR, "Attempting to disable timerfd handle -1");
00276       return -1;
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       /* No reason to do anything if we're not
00287        * in continuous mode
00288        */
00289       ao2_unlock(our_timer);
00290       ao2_ref(our_timer, -1);
00291       return 0;
00292    }
00293 
00294    res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
00295    our_timer->is_continuous = 0;
00296    memset(&our_timer->saved_timer, 0, sizeof(our_timer->saved_timer));
00297    ao2_unlock(our_timer);
00298    ao2_ref(our_timer, -1);
00299    return res;
00300 }

static int timerfd_timer_enable_continuous ( int  handle  )  [static]

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

00231 {
00232    int res;
00233    struct itimerspec continuous_timer = {
00234       .it_value.tv_nsec = 1L,
00235    };
00236    struct timerfd_timer *our_timer, find_helper = {
00237       .handle = handle,
00238    };
00239 
00240    if (handle == -1) {
00241       ast_log(LOG_ERROR, "Attempting to enable timerfd handle -1");
00242       return -1;
00243    }
00244 
00245    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00246       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00247       return -1;
00248    }
00249    ao2_lock(our_timer);
00250 
00251    if (our_timer->is_continuous) {
00252       /*It's already in continous mode, no need to do
00253        * anything further
00254        */
00255       ao2_unlock(our_timer);
00256       ao2_ref(our_timer, -1);
00257       return 0;
00258    }
00259 
00260    res = timerfd_settime(handle, 0, &continuous_timer, &our_timer->saved_timer);
00261    our_timer->is_continuous = 1;
00262    ao2_unlock(our_timer);
00263    ao2_ref(our_timer, -1);
00264    return res;
00265 }

static enum ast_timer_event timerfd_timer_get_event ( int  handle  )  [static]

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

00303 {
00304    enum ast_timer_event res;
00305    struct timerfd_timer *our_timer, find_helper = {
00306       .handle = handle,
00307    };
00308 
00309    if (handle == -1) {
00310       ast_log(LOG_ERROR, "Attempting to get event from timerfd handle -1");
00311       return -1;
00312    }
00313 
00314    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00315       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00316       return -1;
00317    }
00318    ao2_lock(our_timer);
00319 
00320    if (our_timer->is_continuous) {
00321       res = AST_TIMING_EVENT_CONTINUOUS;
00322    } else {
00323       res = AST_TIMING_EVENT_EXPIRED;
00324    }
00325 
00326    ao2_unlock(our_timer);
00327    ao2_ref(our_timer, -1);
00328    return res;
00329 }

static unsigned int timerfd_timer_get_max_rate ( int  handle  )  [static]

Definition at line 331 of file res_timing_timerfd.c.

References TIMERFD_MAX_RATE.

00332 {
00333    return TIMERFD_MAX_RATE;
00334 }

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

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

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

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

00140 {
00141    struct timerfd_timer *our_timer, find_helper = {
00142       .handle = handle,
00143    };
00144    int res = 0;
00145 
00146    if (handle == -1) {
00147       ast_log(LOG_ERROR, "Attempting to set rate on timerfd handle -1");
00148       return -1;
00149    }
00150 
00151    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00152       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00153       return -1;
00154    }
00155    ao2_lock(our_timer);
00156 
00157    our_timer->saved_timer.it_value.tv_sec = 0;
00158    our_timer->saved_timer.it_value.tv_nsec = rate ? (long) (1000000000 / rate) : 0L;
00159    our_timer->saved_timer.it_interval.tv_sec = our_timer->saved_timer.it_value.tv_sec;
00160    our_timer->saved_timer.it_interval.tv_nsec = our_timer->saved_timer.it_value.tv_nsec;
00161 
00162    if (!our_timer->is_continuous) {
00163       res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
00164    }
00165 
00166    ao2_unlock(our_timer);
00167    ao2_ref(our_timer, -1);
00168 
00169    return res;
00170 }

static int unload_module ( void   )  [static]

Definition at line 360 of file res_timing_timerfd.c.

References ao2_ref, ast_unregister_timing_interface(), and timing_funcs_handle.

00361 {
00362    int res;
00363 
00364    if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
00365       ao2_ref(timerfd_timers, -1);
00366       timerfd_timers = NULL;
00367    }
00368 
00369    return res;
00370 }


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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_TIMING, } [static]

Definition at line 376 of file res_timing_timerfd.c.

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

Referenced by load_module(), and unload_module().


Generated on 31 Aug 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1