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_info * | ast_module_info = &__mod_info |
static struct ao2_container * | timerfd_timers |
static struct ast_timing_interface | timerfd_timing |
static void * | timing_funcs_handle |
timerfd timing interface
Definition in file res_timing_timerfd.c.
#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().
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 }
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.
struct ast_module_info* ast_module_info = &__mod_info [static] |
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.
struct ast_timing_interface timerfd_timing [static] |
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().