Fri Nov 12 12:09:03 2010

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 = "0901e4e500243c855563a2d78b0c03e4" , .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 303 of file res_timing_timerfd.c.

static void __unreg_module ( void   )  [static]

Definition at line 303 of file res_timing_timerfd.c.

static int load_module ( void   )  [static]

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

00264 {
00265    int fd;
00266 
00267    /* Make sure we support the necessary clock type */
00268    if ((fd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) {
00269       ast_log(LOG_ERROR, "CLOCK_MONOTONIC not supported.  Not loading.\n");
00270       return AST_MODULE_LOAD_DECLINE;
00271    }
00272 
00273    close(fd);
00274 
00275    if (!(timerfd_timers = ao2_container_alloc(TIMERFD_TIMER_BUCKETS, timerfd_timer_hash, timerfd_timer_cmp))) {
00276       return AST_MODULE_LOAD_DECLINE;
00277    }
00278 
00279    if (!(timing_funcs_handle = ast_register_timing_interface(&timerfd_timing))) {
00280       ao2_ref(timerfd_timers, -1);
00281       return AST_MODULE_LOAD_DECLINE;
00282    }
00283 
00284    return AST_MODULE_LOAD_SUCCESS;
00285 }

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

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 158 of file res_timing_timerfd.c.

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

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

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, and OBJ_POINTER.

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 209 of file res_timing_timerfd.c.

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

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

static int timerfd_timer_enable_continuous ( int  handle  )  [static]

Definition at line 180 of file res_timing_timerfd.c.

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

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

static enum ast_timer_event timerfd_timer_get_event ( int  handle  )  [static]

Definition at line 236 of file res_timing_timerfd.c.

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

00237 {
00238    enum ast_timer_event res;
00239    struct timerfd_timer *our_timer, find_helper = {
00240       .handle = handle,
00241    };
00242 
00243    if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
00244       ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
00245       return -1;
00246    }
00247 
00248    if (our_timer->is_continuous) {
00249       res = AST_TIMING_EVENT_CONTINUOUS;
00250    } else {
00251       res = AST_TIMING_EVENT_EXPIRED;
00252    }
00253 
00254    ao2_ref(our_timer, -1);
00255    return res;
00256 }

static unsigned int timerfd_timer_get_max_rate ( int  handle  )  [static]

Definition at line 258 of file res_timing_timerfd.c.

References TIMERFD_MAX_RATE.

00259 {
00260    return TIMERFD_MAX_RATE;
00261 }

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

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

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_ref, ast_log(), timerfd_timer::is_continuous, LOG_ERROR, OBJ_POINTER, and timerfd_timer::saved_timer.

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 
00144    our_timer->saved_timer.it_value.tv_sec = 0;
00145    our_timer->saved_timer.it_value.tv_nsec = rate ? (long) (1000000000 / rate) : 0L;
00146    our_timer->saved_timer.it_interval.tv_sec = our_timer->saved_timer.it_value.tv_sec;
00147    our_timer->saved_timer.it_interval.tv_nsec = our_timer->saved_timer.it_value.tv_nsec;
00148 
00149    if (!our_timer->is_continuous) {
00150       res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
00151    }
00152 
00153    ao2_ref(our_timer, -1);
00154 
00155    return res;
00156 }

static int unload_module ( void   )  [static]

Definition at line 287 of file res_timing_timerfd.c.

References ao2_ref, ast_unregister_timing_interface(), and timing_funcs_handle.

00288 {
00289    int res;
00290 
00291    if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) {
00292       ao2_ref(timerfd_timers, -1);
00293       timerfd_timers = NULL;
00294    }
00295 
00296    return res;
00297 }


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

Definition at line 303 of file res_timing_timerfd.c.

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


Generated by  doxygen 1.6.2