#include "asterisk.h"
#include <math.h>
#include <sys/select.h>
#include "asterisk/module.h"
#include "asterisk/timing.h"
#include "asterisk/utils.h"
#include "asterisk/astobj2.h"
#include "asterisk/time.h"
#include "asterisk/lock.h"
Go to the source code of this file.
Data Structures | |
struct | pthread_timer |
Defines | |
#define | MAX_RATE 100 |
#define | PTHREAD_TIMER_BUCKETS 563 |
Enumerations | |
enum | { PIPE_READ = 0, PIPE_WRITE = 1 } |
enum | pthread_timer_state { TIMER_STATE_IDLE, TIMER_STATE_TICKING, TIMER_STATE_CONTINUOUS } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
ASTERISK_FILE_VERSION (__FILE__,"$Revision: 176675 $") | |
static int | check_timer (struct pthread_timer *timer) |
static void * | do_timing (void *arg) |
static struct pthread_timer * | find_timer (int handle, int unlinkobj) |
static int | init_timing_thread (void) |
static int | load_module (void) |
static void | pthread_timer_ack (int handle, unsigned int quantity) |
static void | pthread_timer_close (int handle) |
static int | pthread_timer_cmp (void *obj, void *arg, int flags) |
static void | pthread_timer_destructor (void *obj) |
static int | pthread_timer_disable_continuous (int handle) |
static int | pthread_timer_enable_continuous (int handle) |
static enum ast_timer_event | pthread_timer_get_event (int handle) |
static unsigned int | pthread_timer_get_max_rate (int handle) |
static int | pthread_timer_hash (const void *obj, const int flags) |
static int | pthread_timer_open (void) |
static int | pthread_timer_set_rate (int handle, unsigned int rate) |
static void | read_pipe (int rd_fd, unsigned int num, int clear) |
static int | run_timer (void *obj, void *arg, int flags) |
static void | set_state (struct pthread_timer *timer) |
static int | unload_module (void) |
static void | write_byte (int wr_fd) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "pthread 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ao2_container * | pthread_timers |
static struct ast_timing_interface | pthread_timing |
static void * | timing_funcs_handle |
struct { | |
ast_cond_t cond | |
ast_mutex_t lock | |
unsigned int stop:1 | |
pthread_t thread | |
} | timing_thread |
Data for the timing thread. |
Definition in file res_timing_pthread.c.
#define MAX_RATE 100 |
Definition at line 65 of file res_timing_pthread.c.
Referenced by pthread_timer_get_max_rate(), and pthread_timer_set_rate().
#define PTHREAD_TIMER_BUCKETS 563 |
anonymous enum |
Definition at line 70 of file res_timing_pthread.c.
00070 { 00071 PIPE_READ = 0, 00072 PIPE_WRITE = 1 00073 };
enum pthread_timer_state |
Definition at line 75 of file res_timing_pthread.c.
00075 { 00076 TIMER_STATE_IDLE, 00077 TIMER_STATE_TICKING, 00078 TIMER_STATE_CONTINUOUS, 00079 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 513 of file res_timing_pthread.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 513 of file res_timing_pthread.c.
ASTERISK_FILE_VERSION | ( | __FILE__ | , | |
"$Revision: 176675 $" | ||||
) |
static int check_timer | ( | struct pthread_timer * | timer | ) | [static] |
0 | no timer tick needed | |
non-zero | write to the timing pipe needed |
Definition at line 337 of file res_timing_pthread.c.
References ast_tvdiff_ms(), ast_tvnow(), timer, TIMER_STATE_CONTINUOUS, and TIMER_STATE_IDLE.
Referenced by run_timer().
00338 { 00339 struct timeval now; 00340 00341 if (timer->state == TIMER_STATE_IDLE || timer->state == TIMER_STATE_CONTINUOUS) { 00342 return 0; 00343 } 00344 00345 now = ast_tvnow(); 00346 00347 if (timer->tick_count < (ast_tvdiff_ms(now, timer->start) / timer->interval)) { 00348 timer->tick_count++; 00349 if (!timer->tick_count) { 00350 timer->start = now; 00351 } 00352 return 1; 00353 } 00354 00355 return 0; 00356 }
static void* do_timing | ( | void * | arg | ) | [static] |
Definition at line 437 of file res_timing_pthread.c.
References ao2_callback, ao2_container_count(), ast_cond_timedwait(), ast_cond_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_tv(), ast_tvadd(), ast_tvnow(), OBJ_NODATA, pthread_timers, run_timer(), and timing_thread.
Referenced by init_timing_thread().
00438 { 00439 struct timeval next_wakeup = ast_tvnow(); 00440 00441 while (!timing_thread.stop) { 00442 struct timespec ts = { 0, }; 00443 00444 ao2_callback(pthread_timers, OBJ_NODATA, run_timer, NULL); 00445 00446 next_wakeup = ast_tvadd(next_wakeup, ast_tv(0, 5000)); 00447 00448 ts.tv_sec = next_wakeup.tv_sec; 00449 ts.tv_nsec = next_wakeup.tv_usec * 1000; 00450 00451 ast_mutex_lock(&timing_thread.lock); 00452 if (!timing_thread.stop) { 00453 if (ao2_container_count(pthread_timers)) { 00454 ast_cond_timedwait(&timing_thread.cond, &timing_thread.lock, &ts); 00455 } else { 00456 ast_cond_wait(&timing_thread.cond, &timing_thread.lock); 00457 } 00458 } 00459 ast_mutex_unlock(&timing_thread.lock); 00460 } 00461 00462 return NULL; 00463 }
static struct pthread_timer * find_timer | ( | int | handle, | |
int | unlinkobj | |||
) | [static] |
Definition at line 278 of file res_timing_pthread.c.
References ao2_find, ast_assert, OBJ_POINTER, OBJ_UNLINK, pthread_timer::pipe, PIPE_READ, pthread_timers, and timer.
Referenced by pthread_timer_ack(), pthread_timer_close(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), and pthread_timer_set_rate().
00279 { 00280 struct pthread_timer *timer; 00281 struct pthread_timer tmp_timer; 00282 int flags = OBJ_POINTER; 00283 00284 tmp_timer.pipe[PIPE_READ] = handle; 00285 00286 if (unlinkobj) { 00287 flags |= OBJ_UNLINK; 00288 } 00289 00290 if (!(timer = ao2_find(pthread_timers, &tmp_timer, flags))) { 00291 ast_assert(timer != NULL); 00292 return NULL; 00293 } 00294 00295 return timer; 00296 }
static int init_timing_thread | ( | void | ) | [static] |
Definition at line 465 of file res_timing_pthread.c.
References ast_cond_init(), ast_log(), ast_mutex_init(), ast_pthread_create_background, do_timing(), LOG_ERROR, and timing_thread.
Referenced by load_module().
00466 { 00467 ast_mutex_init(&timing_thread.lock); 00468 ast_cond_init(&timing_thread.cond, NULL); 00469 00470 if (ast_pthread_create_background(&timing_thread.thread, NULL, do_timing, NULL)) { 00471 ast_log(LOG_ERROR, "Unable to start timing thread.\n"); 00472 return -1; 00473 } 00474 00475 return 0; 00476 }
static int load_module | ( | void | ) | [static] |
Definition at line 478 of file res_timing_pthread.c.
References ao2_container_alloc, ao2_ref, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_timing_interface, init_timing_thread(), PTHREAD_TIMER_BUCKETS, pthread_timer_cmp(), pthread_timer_hash(), pthread_timers, pthread_timing, and timing_funcs_handle.
00479 { 00480 if (!(pthread_timers = ao2_container_alloc(PTHREAD_TIMER_BUCKETS, 00481 pthread_timer_hash, pthread_timer_cmp))) { 00482 return AST_MODULE_LOAD_DECLINE; 00483 } 00484 00485 if (init_timing_thread()) { 00486 ao2_ref(pthread_timers, -1); 00487 pthread_timers = NULL; 00488 return AST_MODULE_LOAD_DECLINE; 00489 } 00490 00491 return (timing_funcs_handle = ast_register_timing_interface(&pthread_timing)) ? 00492 AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE; 00493 }
static void pthread_timer_ack | ( | int | handle, | |
unsigned int | quantity | |||
) | [static] |
Definition at line 197 of file res_timing_pthread.c.
References ao2_ref, ast_assert, find_timer(), PIPE_READ, read_pipe(), timer, and TIMER_STATE_CONTINUOUS.
00198 { 00199 struct pthread_timer *timer; 00200 00201 ast_assert(quantity > 0); 00202 00203 if (!(timer = find_timer(handle, 0))) { 00204 return; 00205 } 00206 00207 if (timer->state == TIMER_STATE_CONTINUOUS) { 00208 /* Leave the pipe alone, please! */ 00209 return; 00210 } 00211 00212 read_pipe(timer->pipe[PIPE_READ], quantity, 0); 00213 00214 ao2_ref(timer, -1); 00215 }
static void pthread_timer_close | ( | int | handle | ) | [static] |
Definition at line 140 of file res_timing_pthread.c.
References ao2_ref, find_timer(), and timer.
00141 { 00142 struct pthread_timer *timer; 00143 00144 if (!(timer = find_timer(handle, 1))) { 00145 return; 00146 } 00147 00148 ao2_ref(timer, -1); 00149 }
static int pthread_timer_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 326 of file res_timing_pthread.c.
References CMP_MATCH, CMP_STOP, pthread_timer::pipe, and PIPE_READ.
Referenced by load_module().
00327 { 00328 struct pthread_timer *timer1 = obj, *timer2 = arg; 00329 00330 return (timer1->pipe[PIPE_READ] == timer2->pipe[PIPE_READ]) ? CMP_MATCH | CMP_STOP : 0; 00331 }
static void pthread_timer_destructor | ( | void * | obj | ) | [static] |
Definition at line 298 of file res_timing_pthread.c.
References PIPE_READ, PIPE_WRITE, and timer.
Referenced by pthread_timer_open().
00299 { 00300 struct pthread_timer *timer = obj; 00301 00302 if (timer->pipe[PIPE_READ] > -1) { 00303 close(timer->pipe[PIPE_READ]); 00304 timer->pipe[PIPE_READ] = -1; 00305 } 00306 00307 if (timer->pipe[PIPE_WRITE] > -1) { 00308 close(timer->pipe[PIPE_WRITE]); 00309 timer->pipe[PIPE_WRITE] = -1; 00310 } 00311 }
static int pthread_timer_disable_continuous | ( | int | handle | ) | [static] |
Definition at line 236 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), errno, find_timer(), PIPE_READ, read_pipe(), set_state(), and timer.
00237 { 00238 struct pthread_timer *timer; 00239 00240 if (!(timer = find_timer(handle, 0))) { 00241 errno = EINVAL; 00242 return -1; 00243 } 00244 00245 ao2_lock(timer); 00246 set_state(timer); 00247 read_pipe(timer->pipe[PIPE_READ], 0, 1); 00248 ao2_unlock(timer); 00249 00250 ao2_ref(timer, -1); 00251 00252 return 0; 00253 }
static int pthread_timer_enable_continuous | ( | int | handle | ) | [static] |
Definition at line 217 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), errno, find_timer(), PIPE_WRITE, timer, TIMER_STATE_CONTINUOUS, and write_byte().
00218 { 00219 struct pthread_timer *timer; 00220 00221 if (!(timer = find_timer(handle, 0))) { 00222 errno = EINVAL; 00223 return -1; 00224 } 00225 00226 ao2_lock(timer); 00227 timer->state = TIMER_STATE_CONTINUOUS; 00228 write_byte(timer->pipe[PIPE_WRITE]); 00229 ao2_unlock(timer); 00230 00231 ao2_ref(timer, -1); 00232 00233 return 0; 00234 }
static enum ast_timer_event pthread_timer_get_event | ( | int | handle | ) | [static] |
Definition at line 255 of file res_timing_pthread.c.
References ao2_ref, AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, find_timer(), timer, and TIMER_STATE_CONTINUOUS.
00256 { 00257 struct pthread_timer *timer; 00258 enum ast_timer_event res = AST_TIMING_EVENT_EXPIRED; 00259 00260 if (!(timer = find_timer(handle, 0))) { 00261 return res; 00262 } 00263 00264 if (timer->state == TIMER_STATE_CONTINUOUS) { 00265 res = AST_TIMING_EVENT_CONTINUOUS; 00266 } 00267 00268 ao2_ref(timer, -1); 00269 00270 return res; 00271 }
static unsigned int pthread_timer_get_max_rate | ( | int | handle | ) | [static] |
Definition at line 273 of file res_timing_pthread.c.
References MAX_RATE.
00274 { 00275 return MAX_RATE; 00276 }
static int pthread_timer_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 316 of file res_timing_pthread.c.
References PIPE_READ, and timer.
Referenced by load_module().
00317 { 00318 const struct pthread_timer *timer = obj; 00319 00320 return timer->pipe[PIPE_READ]; 00321 }
static int pthread_timer_open | ( | void | ) | [static] |
Definition at line 106 of file res_timing_pthread.c.
References ao2_alloc, ao2_container_count(), ao2_link, ao2_lock(), ao2_ref, ao2_unlock(), ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), errno, pthread_timer::pipe, PIPE_READ, PIPE_WRITE, pthread_timer_destructor(), pthread_timers, timer, TIMER_STATE_IDLE, and timing_thread.
00107 { 00108 struct pthread_timer *timer; 00109 int fd; 00110 00111 if (!(timer = ao2_alloc(sizeof(*timer), pthread_timer_destructor))) { 00112 errno = ENOMEM; 00113 return -1; 00114 } 00115 00116 timer->pipe[PIPE_READ] = timer->pipe[PIPE_WRITE] = -1; 00117 timer->state = TIMER_STATE_IDLE; 00118 00119 if (pipe(timer->pipe)) { 00120 ao2_ref(timer, -1); 00121 return -1; 00122 } 00123 00124 ao2_lock(pthread_timers); 00125 if (!ao2_container_count(pthread_timers)) { 00126 ast_mutex_lock(&timing_thread.lock); 00127 ast_cond_signal(&timing_thread.cond); 00128 ast_mutex_unlock(&timing_thread.lock); 00129 } 00130 ao2_link(pthread_timers, timer); 00131 ao2_unlock(pthread_timers); 00132 00133 fd = timer->pipe[PIPE_READ]; 00134 00135 ao2_ref(timer, -1); 00136 00137 return fd; 00138 }
static int pthread_timer_set_rate | ( | int | handle, | |
unsigned int | rate | |||
) | [static] |
Definition at line 168 of file res_timing_pthread.c.
References ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), errno, find_timer(), LOG_ERROR, MAX_RATE, set_state(), timer, and TIMER_STATE_CONTINUOUS.
00169 { 00170 struct pthread_timer *timer; 00171 00172 if (!(timer = find_timer(handle, 0))) { 00173 errno = EINVAL; 00174 return -1; 00175 } 00176 00177 if (rate > MAX_RATE) { 00178 ast_log(LOG_ERROR, "res_timing_pthread only supports timers at a max rate of %d / sec\n", 00179 MAX_RATE); 00180 errno = EINVAL; 00181 return -1; 00182 } 00183 00184 ao2_lock(timer); 00185 timer->rate = rate; 00186 if (timer->state != TIMER_STATE_CONTINUOUS) { 00187 set_state(timer); 00188 } 00189 00190 ao2_unlock(timer); 00191 00192 ao2_ref(timer, -1); 00193 00194 return 0; 00195 }
static void read_pipe | ( | int | rd_fd, | |
unsigned int | num, | |||
int | clear | |||
) | [static] |
Definition at line 358 of file res_timing_pthread.c.
References ast_assert, ast_log(), buf, errno, and LOG_ERROR.
Referenced by pthread_timer_ack(), and pthread_timer_disable_continuous().
00359 { 00360 ast_assert(quantity || clear); 00361 00362 if (!quantity && clear) { 00363 quantity = 1; 00364 } 00365 00366 do { 00367 unsigned char buf[1024]; 00368 ssize_t res; 00369 fd_set rfds; 00370 struct timeval timeout = { 00371 .tv_sec = 0, 00372 }; 00373 00374 /* Make sure there is data to read */ 00375 FD_ZERO(&rfds); 00376 FD_SET(rd_fd, &rfds); 00377 00378 if (select(rd_fd + 1, &rfds, NULL, NULL, &timeout) != 1) { 00379 break; 00380 } 00381 00382 res = read(rd_fd, buf, 00383 (quantity < sizeof(buf)) ? quantity : sizeof(buf)); 00384 00385 if (res == -1) { 00386 if (errno == EAGAIN) { 00387 continue; 00388 } 00389 ast_log(LOG_ERROR, "read failed on timing pipe: %s\n", strerror(errno)); 00390 break; 00391 } 00392 00393 if (clear) { 00394 continue; 00395 } 00396 00397 quantity -= res; 00398 } while (quantity); 00399 }
static int run_timer | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 418 of file res_timing_pthread.c.
References ao2_lock(), ao2_unlock(), check_timer(), PIPE_WRITE, timer, TIMER_STATE_IDLE, and write_byte().
Referenced by do_timing().
00419 { 00420 struct pthread_timer *timer = obj; 00421 00422 if (timer->state == TIMER_STATE_IDLE) { 00423 return 0; 00424 } 00425 00426 ao2_lock(timer); 00427 00428 if (check_timer(timer)) { 00429 write_byte(timer->pipe[PIPE_WRITE]); 00430 } 00431 00432 ao2_unlock(timer); 00433 00434 return 0; 00435 }
static void set_state | ( | struct pthread_timer * | timer | ) | [static] |
Definition at line 151 of file res_timing_pthread.c.
References ast_tv(), ast_tvnow(), pthread_timer::rate, timer, TIMER_STATE_IDLE, and TIMER_STATE_TICKING.
00152 { 00153 unsigned int rate = timer->rate; 00154 00155 if (rate) { 00156 timer->state = TIMER_STATE_TICKING; 00157 timer->interval = roundf(1000.0 / ((float) rate)); 00158 timer->start = ast_tvnow(); 00159 } else { 00160 timer->state = TIMER_STATE_IDLE; 00161 timer->interval = 0; 00162 timer->start = ast_tv(0, 0); 00163 } 00164 00165 timer->tick_count = 0; 00166 }
static int unload_module | ( | void | ) | [static] |
Definition at line 495 of file res_timing_pthread.c.
References ao2_ref, ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), ast_unregister_timing_interface(), pthread_timers, timing_funcs_handle, and timing_thread.
00496 { 00497 int res; 00498 00499 ast_mutex_lock(&timing_thread.lock); 00500 timing_thread.stop = 1; 00501 ast_cond_signal(&timing_thread.cond); 00502 ast_mutex_unlock(&timing_thread.lock); 00503 pthread_join(timing_thread.thread, NULL); 00504 00505 if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) { 00506 ao2_ref(pthread_timers, -1); 00507 pthread_timers = NULL; 00508 } 00509 00510 return res; 00511 }
static void write_byte | ( | int | wr_fd | ) | [static] |
Definition at line 401 of file res_timing_pthread.c.
References ast_log(), errno, and LOG_ERROR.
Referenced by pthread_timer_enable_continuous(), and run_timer().
00402 { 00403 do { 00404 ssize_t res; 00405 unsigned char x = 42; 00406 00407 res = write(wr_fd, &x, 1); 00408 00409 if (res == -1) { 00410 if (errno == EAGAIN) { 00411 continue; 00412 } 00413 ast_log(LOG_ERROR, "Error writing to timing pipe: %s\n", strerror(errno)); 00414 } 00415 } while (0); 00416 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "pthread 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 513 of file res_timing_pthread.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 513 of file res_timing_pthread.c.
Definition at line 102 of file res_timing_pthread.c.
Definition at line 101 of file res_timing_pthread.c.
struct ao2_container* pthread_timers [static] |
Definition at line 67 of file res_timing_pthread.c.
Referenced by do_timing(), find_timer(), load_module(), pthread_timer_open(), and unload_module().
struct ast_timing_interface pthread_timing [static] |
unsigned int stop |
Definition at line 103 of file res_timing_pthread.c.
pthread_t thread |
Definition at line 100 of file res_timing_pthread.c.
void* timing_funcs_handle [static] |
Definition at line 40 of file res_timing_pthread.c.
struct { ... } timing_thread [static] |
Data for the timing thread.
Referenced by do_timing(), init_timing_thread(), pthread_timer_open(), and unload_module().