#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_info * | ast_module_info = &__mod_info |
static struct ao2_container * | timerfd_timers |
static struct ast_timing_interface | timerfd_timing |
static void * | timing_funcs_handle |
Definition in file res_timing_timerfd.c.
#define TIMERFD_MAX_RATE 1000 |
#define TIMERFD_TIMER_BUCKETS 563 |
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) { 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 }
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] |
void* timing_funcs_handle [static] |
Definition at line 41 of file res_timing_timerfd.c.