#include "asterisk.h"
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.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 "asterisk/test.h"
#include "asterisk/poll-compat.h"
Go to the source code of this file.
Data Structures | |
struct | kqueue_timer |
Defines | |
#define | lookup_timer(a) _lookup_timer(a, __FILE__, __LINE__, __PRETTY_FUNCTION__) |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static struct kqueue_timer * | _lookup_timer (int handle, const char *file, int line, const char *func) |
static void | kqueue_set_nsecs (struct kqueue_timer *our_timer, uint64_t nsecs) |
static void | kqueue_timer_ack (int handle, unsigned int quantity) |
static void | kqueue_timer_close (int handle) |
static int | kqueue_timer_cmp (void *obj, void *args, int flags) |
static int | kqueue_timer_disable_continuous (int handle) |
static int | kqueue_timer_enable_continuous (int handle) |
static enum ast_timer_event | kqueue_timer_get_event (int handle) |
static unsigned int | kqueue_timer_get_max_rate (int handle) |
static int | kqueue_timer_hash (const void *obj, const int flags) |
static int | kqueue_timer_open (void) |
static int | kqueue_timer_set_rate (int handle, unsigned int rate) |
static int | load_module (void) |
static void | timer_destroy (void *obj) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "KQueue 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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 * | kqueue_timers |
static struct ast_timing_interface | kqueue_timing |
static void * | timing_funcs_handle |
Definition in file res_timing_kqueue.c.
#define lookup_timer | ( | a | ) | _lookup_timer(a, __FILE__, __LINE__, __PRETTY_FUNCTION__) |
Definition at line 99 of file res_timing_kqueue.c.
Referenced by kqueue_timer_ack(), kqueue_timer_close(), kqueue_timer_disable_continuous(), kqueue_timer_enable_continuous(), kqueue_timer_get_event(), and kqueue_timer_set_rate().
static void __reg_module | ( | void | ) | [static] |
Definition at line 395 of file res_timing_kqueue.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 395 of file res_timing_kqueue.c.
static struct kqueue_timer* _lookup_timer | ( | int | handle, | |
const char * | file, | |||
int | line, | |||
const char * | func | |||
) | [static] |
Definition at line 100 of file res_timing_kqueue.c.
References __LOG_ERROR, ao2_find, ast_log(), errno, kqueue_timer::handle, kqueue_timers, and OBJ_POINTER.
00101 { 00102 struct kqueue_timer *our_timer, find_helper = { 00103 .handle = handle, 00104 }; 00105 00106 if (!(our_timer = ao2_find(kqueue_timers, &find_helper, OBJ_POINTER))) { 00107 ast_log(__LOG_ERROR, file, line, func, "Couldn't find timer with handle %d\n", handle); 00108 /* API says we set errno */ 00109 errno = ESRCH; 00110 return NULL; 00111 } 00112 return our_timer; 00113 }
static void kqueue_set_nsecs | ( | struct kqueue_timer * | our_timer, | |
uint64_t | nsecs | |||
) | [static] |
Definition at line 149 of file res_timing_kqueue.c.
References kqueue_timer::handle.
Referenced by kqueue_timer_disable_continuous(), kqueue_timer_enable_continuous(), and kqueue_timer_set_rate().
00150 { 00151 struct timespec nowait = { 0, 1 }; 00152 #ifdef HAVE_KEVENT64 00153 struct kevent64_s kev; 00154 00155 EV_SET64(&kev, our_timer->handle, EVFILT_TIMER, EV_ADD | EV_ENABLE, NOTE_NSECONDS, 00156 nsecs, 0, 0, 0); 00157 kevent64(our_timer->handle, &kev, 1, NULL, 0, 0, &nowait); 00158 #else 00159 struct kevent kev; 00160 00161 EV_SET(&kev, our_timer->handle, EVFILT_TIMER, EV_ADD | EV_ENABLE, 00162 #ifdef NOTE_NSECONDS 00163 nsecs <= 0xFFffFFff ? NOTE_NSECONDS : 00164 #endif 00165 #ifdef NOTE_USECONDS 00166 NOTE_USECONDS 00167 #else /* Milliseconds, if no constants are defined */ 00168 0 00169 #endif 00170 , 00171 #ifdef NOTE_NSECONDS 00172 nsecs <= 0xFFffFFff ? nsecs : 00173 #endif 00174 #ifdef NOTE_USECONDS 00175 nsecs / 1000 00176 #else /* Milliseconds, if nothing else is defined */ 00177 nsecs / 1000000 00178 #endif 00179 , NULL); 00180 kevent(our_timer->handle, &kev, 1, NULL, 0, &nowait); 00181 #endif 00182 }
static void kqueue_timer_ack | ( | int | handle, | |
unsigned int | quantity | |||
) | [static] |
Definition at line 198 of file res_timing_kqueue.c.
References ast_debug, lookup_timer, and kqueue_timer::unacked.
00199 { 00200 struct kqueue_timer *our_timer; 00201 00202 if (!(our_timer = lookup_timer(handle))) { 00203 return; 00204 } 00205 00206 if (our_timer->unacked < quantity) { 00207 ast_debug(1, "Acking more events than have expired?!!\n"); 00208 our_timer->unacked = 0; 00209 } else { 00210 our_timer->unacked -= quantity; 00211 } 00212 }
static void kqueue_timer_close | ( | int | handle | ) | [static] |
Definition at line 137 of file res_timing_kqueue.c.
References ao2_ref, ao2_unlink, kqueue_timers, and lookup_timer.
00138 { 00139 struct kqueue_timer *our_timer; 00140 00141 if (!(our_timer = lookup_timer(handle))) { 00142 return; 00143 } 00144 00145 ao2_unlink(kqueue_timers, our_timer); 00146 ao2_ref(our_timer, -1); 00147 }
static int kqueue_timer_cmp | ( | void * | obj, | |
void * | args, | |||
int | flags | |||
) | [static] |
Definition at line 87 of file res_timing_kqueue.c.
References CMP_MATCH, CMP_STOP, and kqueue_timer::handle.
Referenced by load_module().
00088 { 00089 struct kqueue_timer *timer1 = obj, *timer2 = args; 00090 return timer1->handle == timer2->handle ? CMP_MATCH | CMP_STOP : 0; 00091 }
static int kqueue_timer_disable_continuous | ( | int | handle | ) | [static] |
Definition at line 229 of file res_timing_kqueue.c.
References ao2_ref, kqueue_timer::is_continuous, kqueue_set_nsecs(), lookup_timer, kqueue_timer::nsecs, and kqueue_timer::unacked.
00230 { 00231 struct kqueue_timer *our_timer; 00232 00233 if (!(our_timer = lookup_timer(handle))) { 00234 return -1; 00235 } 00236 00237 kqueue_set_nsecs(our_timer, our_timer->nsecs); 00238 our_timer->is_continuous = 0; 00239 our_timer->unacked = 0; 00240 ao2_ref(our_timer, -1); 00241 return 0; 00242 }
static int kqueue_timer_enable_continuous | ( | int | handle | ) | [static] |
Definition at line 214 of file res_timing_kqueue.c.
References ao2_ref, kqueue_timer::is_continuous, kqueue_set_nsecs(), lookup_timer, and kqueue_timer::unacked.
00215 { 00216 struct kqueue_timer *our_timer; 00217 00218 if (!(our_timer = lookup_timer(handle))) { 00219 return -1; 00220 } 00221 00222 kqueue_set_nsecs(our_timer, 1); 00223 our_timer->is_continuous = 1; 00224 our_timer->unacked = 0; 00225 ao2_ref(our_timer, -1); 00226 return 0; 00227 }
static enum ast_timer_event kqueue_timer_get_event | ( | int | handle | ) | [static] |
Definition at line 244 of file res_timing_kqueue.c.
References ao2_ref, AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, kqueue_timer::is_continuous, lookup_timer, and kqueue_timer::unacked.
00245 { 00246 enum ast_timer_event res = -1; 00247 struct kqueue_timer *our_timer; 00248 struct timespec sixty_seconds = { 60, 0 }; 00249 struct kevent kev; 00250 00251 if (!(our_timer = lookup_timer(handle))) { 00252 return -1; 00253 } 00254 00255 /* If we have non-ACKed events, just return immediately */ 00256 if (our_timer->unacked == 0) { 00257 if (kevent(handle, NULL, 0, &kev, 1, &sixty_seconds) > 0) { 00258 our_timer->unacked += kev.data; 00259 } 00260 } 00261 00262 if (our_timer->unacked > 0) { 00263 res = our_timer->is_continuous ? AST_TIMING_EVENT_CONTINUOUS : AST_TIMING_EVENT_EXPIRED; 00264 } 00265 00266 ao2_ref(our_timer, -1); 00267 return res; 00268 }
static unsigned int kqueue_timer_get_max_rate | ( | int | handle | ) | [static] |
Definition at line 270 of file res_timing_kqueue.c.
00271 { 00272 /* Actually, the max rate is 2^64-1 seconds, but that's not representable in a 32-bit integer. */ 00273 return UINT_MAX; 00274 }
static int kqueue_timer_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 80 of file res_timing_kqueue.c.
References timer.
Referenced by load_module().
00081 { 00082 const struct kqueue_timer *timer = obj; 00083 00084 return timer->handle; 00085 }
static int kqueue_timer_open | ( | void | ) | [static] |
Definition at line 115 of file res_timing_kqueue.c.
References ao2_alloc, ao2_link, ao2_ref, ast_log(), errno, kqueue_timer::handle, kqueue_timers, LOG_ERROR, timer, and timer_destroy().
00116 { 00117 struct kqueue_timer *timer; 00118 int handle; 00119 00120 if (!(timer = ao2_alloc(sizeof(*timer), timer_destroy))) { 00121 ast_log(LOG_ERROR, "Could not allocate memory for kqueue_timer structure\n"); 00122 return -1; 00123 } 00124 if ((handle = kqueue()) < 0) { 00125 ast_log(LOG_ERROR, "Failed to create kqueue timer: %s\n", strerror(errno)); 00126 ao2_ref(timer, -1); 00127 return -1; 00128 } 00129 00130 timer->handle = handle; 00131 ao2_link(kqueue_timers, timer); 00132 /* Get rid of the reference from the allocation */ 00133 ao2_ref(timer, -1); 00134 return handle; 00135 }
static int kqueue_timer_set_rate | ( | int | handle, | |
unsigned int | rate | |||
) | [static] |
Definition at line 184 of file res_timing_kqueue.c.
References ao2_ref, kqueue_set_nsecs(), lookup_timer, and kqueue_timer::nsecs.
00185 { 00186 struct kqueue_timer *our_timer; 00187 00188 if (!(our_timer = lookup_timer(handle))) { 00189 return -1; 00190 } 00191 00192 kqueue_set_nsecs(our_timer, (our_timer->nsecs = rate ? (long) (1000000000 / rate) : 0L)); 00193 ao2_ref(our_timer, -1); 00194 00195 return 0; 00196 }
static int load_module | ( | void | ) | [static] |
Definition at line 363 of file res_timing_kqueue.c.
References ao2_container_alloc, ao2_ref, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_timing_interface, AST_TEST_REGISTER, kqueue_timer_cmp(), kqueue_timer_hash(), kqueue_timers, kqueue_timing, and timing_funcs_handle.
00364 { 00365 if (!(kqueue_timers = ao2_container_alloc(563, kqueue_timer_hash, kqueue_timer_cmp))) { 00366 return AST_MODULE_LOAD_DECLINE; 00367 } 00368 00369 if (!(timing_funcs_handle = ast_register_timing_interface(&kqueue_timing))) { 00370 ao2_ref(kqueue_timers, -1); 00371 return AST_MODULE_LOAD_DECLINE; 00372 } 00373 00374 AST_TEST_REGISTER(test_kqueue_timing); 00375 return AST_MODULE_LOAD_SUCCESS; 00376 }
static void timer_destroy | ( | void * | obj | ) | [static] |
Definition at line 93 of file res_timing_kqueue.c.
References timer.
Referenced by kqueue_timer_open(), and timerfd_timer_open().
00094 { 00095 struct kqueue_timer *timer = obj; 00096 close(timer->handle); 00097 }
static int unload_module | ( | void | ) | [static] |
Definition at line 378 of file res_timing_kqueue.c.
References ao2_ref, AST_TEST_UNREGISTER, ast_unregister_timing_interface(), kqueue_timers, and timing_funcs_handle.
00379 { 00380 int res; 00381 00382 AST_TEST_UNREGISTER(test_kqueue_timing); 00383 if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) { 00384 ao2_ref(kqueue_timers, -1); 00385 kqueue_timers = NULL; 00386 } 00387 00388 return res; 00389 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "KQueue 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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 395 of file res_timing_kqueue.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 395 of file res_timing_kqueue.c.
struct ao2_container* kqueue_timers [static] |
Definition at line 71 of file res_timing_kqueue.c.
Referenced by _lookup_timer(), kqueue_timer_close(), kqueue_timer_open(), load_module(), and unload_module().
struct ast_timing_interface kqueue_timing [static] |
void* timing_funcs_handle [static] |
Definition at line 47 of file res_timing_kqueue.c.