Mon Jun 27 16:51:20 2011

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 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
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(), timerfd_timers, timerfd_timing, and timing_funcs_handle.

00274 {
00275    int fd;
00276 
00277    /* Make sure we support the necessary clock type */
00278    if ((fd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) {
00279       ast_log(LOG_ERROR, "timerfd_create() not supported by the kernel.  Not loading.\n");
00280       return AST_MODULE_LOAD_DECLINE;
00281    }
00282 
00283    close(fd);
00284 
00285    if (!(timerfd_timers = ao2_container_alloc(TIMERFD_TIMER_BUCKETS, timerfd_timer_hash, timerfd_timer_cmp))) {
00286       return AST_MODULE_LOAD_DECLINE;
00287    }
00288 
00289    if (!(timing_funcs_handle = ast_register_timing_interface(&timerfd_timing))) {
00290       ao2_ref(timerfd_timers, -1);
00291       return AST_MODULE_LOAD_DECLINE;
00292    }
00293 
00294    return AST_MODULE_LOAD_SUCCESS;
00295 }

static void timer_destroy ( void *  obj  )  [static]

Definition at line 89 of file res_timing_timerfd.c.

References timer.

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

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.

00161 {
00162    uint64_t expirations;
00163    int read_result = 0;
00164 
00165    do {
00166       read_result = read(handle, &expirations, sizeof(expirations));
00167       if (read_result == -1) {
00168          if (errno == EINTR || errno == EAGAIN) {
00169             continue;
00170          } else {
00171             ast_log(LOG_ERROR, "Read error: %s\n", strerror(errno));
00172             break;
00173          }
00174       }
00175    } while (read_result != sizeof(expirations));
00176 
00177    if (expirations != quantity) {
00178       ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations);
00179    }
00180 }

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(), LOG_ERROR, OBJ_POINTER, and timerfd_timers.

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

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

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

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::is_continuous, LOG_ERROR, OBJ_POINTER, timerfd_timer::saved_timer, and timerfd_timers.

00215 {
00216    int res;
00217    struct timerfd_timer *our_timer, find_helper = {
00218       .handle = handle,
00219    };
00220 
00221    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00222       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00223       return -1;
00224    }
00225    ao2_lock(our_timer);
00226 
00227    if(!our_timer->is_continuous) {
00228       /* No reason to do anything if we're not
00229        * in continuous mode
00230        */
00231       ao2_unlock(our_timer);
00232       ao2_ref(our_timer, -1);
00233       return 0;
00234    }
00235 
00236    res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
00237    our_timer->is_continuous = 0;
00238    memset(&our_timer->saved_timer, 0, sizeof(our_timer->saved_timer));
00239    ao2_unlock(our_timer);
00240    ao2_ref(our_timer, -1);
00241    return res;
00242 }

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::is_continuous, LOG_ERROR, OBJ_POINTER, timerfd_timer::saved_timer, and timerfd_timers.

00183 {
00184    int res;
00185    struct itimerspec continuous_timer = {
00186       .it_value.tv_nsec = 1L,
00187    };
00188    struct timerfd_timer *our_timer, find_helper = {
00189       .handle = handle,
00190    };
00191 
00192    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00193       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00194       return -1;
00195    }
00196    ao2_lock(our_timer);
00197 
00198    if (our_timer->is_continuous) {
00199       /*It's already in continous mode, no need to do
00200        * anything further
00201        */
00202       ao2_unlock(our_timer);
00203       ao2_ref(our_timer, -1);
00204       return 0;
00205    }
00206 
00207    res = timerfd_settime(handle, 0, &continuous_timer, &our_timer->saved_timer);
00208    our_timer->is_continuous = 1;
00209    ao2_unlock(our_timer);
00210    ao2_ref(our_timer, -1);
00211    return res;
00212 }

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::is_continuous, LOG_ERROR, OBJ_POINTER, and timerfd_timers.

00245 {
00246    enum ast_timer_event res;
00247    struct timerfd_timer *our_timer, find_helper = {
00248       .handle = handle,
00249    };
00250 
00251    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00252       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00253       return -1;
00254    }
00255    ao2_lock(our_timer);
00256 
00257    if (our_timer->is_continuous) {
00258       res = AST_TIMING_EVENT_CONTINUOUS;
00259    } else {
00260       res = AST_TIMING_EVENT_EXPIRED;
00261    }
00262 
00263    ao2_unlock(our_timer);
00264    ao2_ref(our_timer, -1);
00265    return res;
00266 }

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.

00269 {
00270    return TIMERFD_MAX_RATE;
00271 }

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

Definition at line 76 of file res_timing_timerfd.c.

References timer.

Referenced by load_module().

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

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, timer_destroy(), and timerfd_timers.

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

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::is_continuous, LOG_ERROR, OBJ_POINTER, timerfd_timer::saved_timer, and timerfd_timers.

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

static int unload_module ( void   )  [static]

Definition at line 297 of file res_timing_timerfd.c.

References ao2_ref, ast_unregister_timing_interface(), timerfd_timers, and timing_funcs_handle.

00298 {
00299    int res;
00300 
00301    if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
00302       ao2_ref(timerfd_timers, -1);
00303       timerfd_timers = NULL;
00304    }
00305 
00306    return res;
00307 }


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

Definition at line 313 of file res_timing_timerfd.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

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.

Referenced by load_module(), timerfd_timer_close(), timerfd_timer_disable_continuous(), timerfd_timer_enable_continuous(), timerfd_timer_get_event(), timerfd_timer_open(), timerfd_timer_set_rate(), and unload_module().

struct ast_timing_interface timerfd_timing [static]

Definition at line 52 of file res_timing_timerfd.c.

Referenced by load_module().

void* timing_funcs_handle [static]

Definition at line 41 of file res_timing_timerfd.c.


Generated on Mon Jun 27 16:51:20 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7