diff options
-rw-r--r-- | channels/chan_iax2.c | 23 | ||||
-rw-r--r-- | include/asterisk/channel.h | 8 | ||||
-rw-r--r-- | include/asterisk/timing.h | 66 | ||||
-rw-r--r-- | main/channel.c | 29 | ||||
-rw-r--r-- | main/timing.c | 131 |
5 files changed, 121 insertions, 136 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 5643952af..e4d495a38 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -175,7 +175,7 @@ static int max_reg_expire; static int srvlookup = 0; -static int timingfd = -1; /* Timing file descriptor */ +static struct ast_timer *timer; /* Timer for trunking */ static struct ast_netsock_list *netsock; static struct ast_netsock_list *outsock; /*!< used if sourceaddress specified and bindaddr == INADDR_ANY */ @@ -7550,8 +7550,8 @@ static int timing_read(int *id, int fd, short events, void *cbdata) if (iaxtrunkdebug) ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", trunkmaxsize); - if (timingfd > -1) { - ast_timer_ack(timingfd, 1); + if (timer) { + ast_timer_ack(timer, 1); } /* For each peer that supports trunking... */ @@ -10359,8 +10359,8 @@ static void *network_thread(void *ignore) int res, count, wakeup; struct iax_frame *f; - if (timingfd > -1) - ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL); + if (timer) + ast_io_add(io, ast_timer_fd(timer), timing_read, AST_IO_IN | AST_IO_PRI, NULL); for(;;) { pthread_testcancel(); @@ -10669,7 +10669,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st ast_string_field_set(peer, dbsecret, v->value); } else if (!strcasecmp(v->name, "trunk")) { ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); - if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) { + if (ast_test_flag(peer, IAX_TRUNK) && !timer) { ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without a timing interface\n", peer->name); ast_clear_flag(peer, IAX_TRUNK); } @@ -10924,7 +10924,7 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); } else if (!strcasecmp(v->name, "trunk")) { ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); - if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) { + if (ast_test_flag(user, IAX_TRUNK) && !timer) { ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without a timing interface\n", user->name); ast_clear_flag(user, IAX_TRUNK); } @@ -12321,8 +12321,8 @@ static int __unload_module(void) ao2_ref(users, -1); ao2_ref(iax_peercallno_pvts, -1); ao2_ref(iax_transfercallno_pvts, -1); - if (timingfd > -1) { - ast_timer_close(timingfd); + if (timer) { + ast_timer_close(timer); } con = ast_context_find(regcontext); @@ -12463,9 +12463,8 @@ static int load_module(void) ast_manager_register( "IAXpeerlist", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peer_list, "List IAX Peers" ); ast_manager_register( "IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats, "Show IAX Netstats" ); - timingfd = ast_timer_open(); - if (timingfd > -1) { - ast_timer_set_rate(timingfd, trunkfreq); + if ((timer = ast_timer_open())) { + ast_timer_set_rate(timer, trunkfreq); } if (set_config(config, 0) == -1) { diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index b7bc66fa7..e4e8bfea7 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -492,7 +492,13 @@ struct ast_channel { unsigned short transfercapability; /*!< ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */ - char unused_old_dtmfq[AST_MAX_EXTENSION]; /*!< (deprecated, use readq instead) Any/all queued DTMF characters */ + union { + char unused_old_dtmfq[AST_MAX_EXTENSION]; /*!< (deprecated, use readq instead) Any/all queued DTMF characters */ + struct { + struct ast_timer *timer; /*!< timer object that provided timingfd */ + }; + }; + char context[AST_MAX_CONTEXT]; /*!< Dialplan: Current extension context */ char exten[AST_MAX_EXTENSION]; /*!< Dialplan: Current extension number */ char macrocontext[AST_MAX_CONTEXT]; /*!< Macro: Current non-macro context. See app_macro.c */ diff --git a/include/asterisk/timing.h b/include/asterisk/timing.h index c9a8fcba9..d93f4f408 100644 --- a/include/asterisk/timing.h +++ b/include/asterisk/timing.h @@ -93,7 +93,7 @@ struct ast_timing_interface { */ #define ast_register_timing_interface(i) _ast_register_timing_interface(i, ast_module_info->self) void *_ast_register_timing_interface(struct ast_timing_interface *funcs, - struct ast_module *mod); + struct ast_module *mod); /*! * \brief Unregister a previously registered timing interface. @@ -107,45 +107,57 @@ void *_ast_register_timing_interface(struct ast_timing_interface *funcs, */ int ast_unregister_timing_interface(void *handle); +struct ast_timer; + /*! - * \brief Open a timing fd + * \brief Open a timer * - * \retval -1 error, with errno set - * \retval >=0 success + * \retval NULL on error, with errno set + * \retval non-NULL timer handle on success * \since 1.6.1 */ -int ast_timer_open(void); +struct ast_timer *ast_timer_open(void); /*! * \brief Close an opened timing handle * - * \param handle timing fd returned from timer_open() + * \param handle timer handle returned from timer_open() * * \return nothing * \since 1.6.1 */ -void ast_timer_close(int handle); +void ast_timer_close(struct ast_timer *handle); + +/*! + * \brief Get a poll()-able file descriptor for a timer + * + * \param handle timer handle returned from timer_open() + * + * \return file descriptor which can be used with poll() to wait for events + * \since 1.6.1 + */ +int ast_timer_fd(const struct ast_timer *handle); /*! * \brief Set the timing tick rate * - * \param handle timing fd returned from timer_open() + * \param handle timer handle returned from timer_open() * \param rate ticks per second, 0 turns the ticks off if needed * - * Use this function if you want the timing fd to show input at a certain - * rate. The other alternative use of a timing fd, is using the continuous + * Use this function if you want the timer to show input at a certain + * rate. The other alternative use of a timer is the continuous * mode. * * \retval -1 error, with errno set * \retval 0 success * \since 1.6.1 */ -int ast_timer_set_rate(int handle, unsigned int rate); +int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate); /*! * \brief Acknowledge a timer event * - * \param handle timing fd returned from timer_open() + * \param handle timer handle returned from timer_open() * \param quantity number of timer events to acknowledge * * \note This function should only be called if timer_get_event() @@ -154,55 +166,55 @@ int ast_timer_set_rate(int handle, unsigned int rate); * \return nothing * \since 1.6.1 */ -void ast_timer_ack(int handle, unsigned int quantity); +void ast_timer_ack(const struct ast_timer *handle, unsigned int quantity); /*! * \brief Enable continuous mode * - * \param handle timing fd returned from timer_open() + * \param handle timer handle returned from timer_open() * - * Continuous mode causes poll() on the timing fd to immediately return + * Continuous mode causes poll() on the timer's fd to immediately return * always until continuous mode is disabled. * * \retval -1 failure, with errno set * \retval 0 success * \since 1.6.1 */ -int ast_timer_enable_continuous(int handle); +int ast_timer_enable_continuous(const struct ast_timer *handle); /*! * \brief Disable continuous mode * - * \param handle timing fd returned from timer_close() + * \param handle timer handle returned from timer_close() * * \retval -1 failure, with errno set * \retval 0 success * \since 1.6.1 */ -int ast_timer_disable_continuous(int handle); +int ast_timer_disable_continuous(const struct ast_timer *handle); /*! - * \brief Determine timing event + * \brief Retrieve timing event * - * \param handle timing fd returned by timer_open() + * \param handle timer handle returned by timer_open() * - * After poll() indicates that there is input on the timing fd, this will + * After poll() indicates that there is input on the timer's fd, this will * be called to find out what triggered it. * - * \return which event triggered the timing fd + * \return which event triggered the timer * \since 1.6.1 */ -enum ast_timer_event ast_timer_get_event(int handle); +enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle); /*! - * \brief Get maximum rate supported for a timing handle + * \brief Get maximum rate supported for a timer * - * \param handle timing fd returned by timer_open() + * \param handle timer handle returned by timer_open() * - * \return maximum rate supported for timing handle + * \return maximum rate supported by timer * \since 1.6.1 */ -unsigned int ast_timer_get_max_rate(int handle); +unsigned int ast_timer_get_max_rate(const struct ast_timer *handle); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/main/channel.c b/main/channel.c index 7afa49dd6..4b056766c 100644 --- a/main/channel.c +++ b/main/channel.c @@ -806,17 +806,19 @@ struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_ #endif } - tmp->timingfd = ast_timer_open(); - if (tmp->timingfd > -1) { + if ((tmp->timer = ast_timer_open())) { needqueue = 0; + tmp->timingfd = ast_timer_fd(tmp->timer); + } else { + tmp->timingfd = -1; } if (needqueue) { if (pipe(tmp->alertpipe)) { ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe!\n"); alertpipe_failed: - if (tmp->timingfd > -1) { - ast_timer_close(tmp->timingfd); + if (tmp->timer) { + ast_timer_close(tmp->timer); } sched_context_destroy(tmp->sched); @@ -1005,7 +1007,7 @@ static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, in chan->name, f->frametype, f->subclass, qlen, strerror(errno)); } } else if (chan->timingfd > -1) { - ast_timer_enable_continuous(chan->timingfd); + ast_timer_enable_continuous(chan->timer); } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { pthread_kill(chan->blocker, SIGURG); } @@ -1355,8 +1357,9 @@ void ast_channel_free(struct ast_channel *chan) close(fd); if ((fd = chan->alertpipe[1]) > -1) close(fd); - if ((fd = chan->timingfd) > -1) - ast_timer_close(fd); + if (chan->timer) { + ast_timer_close(chan->timer); + } #ifdef HAVE_EPOLL for (i = 0; i < AST_MAX_FDS; i++) { if (chan->epfd_data[i]) @@ -2298,13 +2301,13 @@ int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const v data = NULL; } - if (rate && rate > (max_rate = ast_timer_get_max_rate(c->timingfd))) { + if (rate && rate > (max_rate = ast_timer_get_max_rate(c->timer))) { real_rate = max_rate; } ast_debug(1, "Scheduling timer at (%u requested / %u actual) timer ticks per second\n", rate, real_rate); - res = ast_timer_set_rate(c->timingfd, real_rate); + res = ast_timer_set_rate(c->timer, real_rate); c->timingfunc = func; c->timingdata = data; @@ -2557,11 +2560,11 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) ast_clear_flag(chan, AST_FLAG_EXCEPTION); - res = ast_timer_get_event(chan->timingfd); + res = ast_timer_get_event(chan->timer); switch (res) { case AST_TIMING_EVENT_EXPIRED: - ast_timer_ack(chan->timingfd, 1); + ast_timer_ack(chan->timer, 1); if (chan->timingfunc) { /* save a copy of func/data before unlocking the channel */ @@ -2571,7 +2574,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) ast_channel_unlock(chan); func(data); } else { - ast_timer_set_rate(chan->timingfd, 0); + ast_timer_set_rate(chan->timer, 0); chan->fdno = -1; ast_channel_unlock(chan); } @@ -2582,7 +2585,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) case AST_TIMING_EVENT_CONTINUOUS: if (AST_LIST_EMPTY(&chan->readq) || !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) { - ast_timer_disable_continuous(chan->timingfd); + ast_timer_disable_continuous(chan->timer); } break; } diff --git a/main/timing.c b/main/timing.c index c24db2e29..d0e6a6d24 100644 --- a/main/timing.c +++ b/main/timing.c @@ -49,6 +49,11 @@ struct timing_holder { static struct ast_heap *timing_interfaces; +struct ast_timer { + int fd; + struct timing_holder *holder; +}; + static int timing_holder_cmp(void *_h1, void *_h2) { struct timing_holder *h1 = _h1; @@ -64,16 +69,16 @@ static int timing_holder_cmp(void *_h1, void *_h2) } void *_ast_register_timing_interface(struct ast_timing_interface *funcs, - struct ast_module *mod) + struct ast_module *mod) { struct timing_holder *h; if (!funcs->timer_open || !funcs->timer_close || - !funcs->timer_set_rate || + !funcs->timer_set_rate || !funcs->timer_ack || !funcs->timer_get_event || - !funcs->timer_get_max_rate || + !funcs->timer_get_max_rate || !funcs->timer_enable_continuous || !funcs->timer_disable_continuous) { return NULL; @@ -111,10 +116,11 @@ int ast_unregister_timing_interface(void *handle) return res; } -int ast_timer_open(void) +struct ast_timer *ast_timer_open(void) { int fd = -1; struct timing_holder *h; + struct ast_timer *t = NULL; ast_heap_rdlock(timing_interfaces); @@ -123,124 +129,88 @@ int ast_timer_open(void) ast_module_ref(h->mod); } + if (fd != -1) { + if (!(t = ast_calloc(1, sizeof(*t)))) { + h->iface->timer_close(fd); + } else { + t->fd = fd; + t->holder = h; + } + } + ast_heap_unlock(timing_interfaces); - return fd; + return t; } -void ast_timer_close(int timer) +void ast_timer_close(struct ast_timer *handle) { - struct timing_holder *h; - - ast_heap_rdlock(timing_interfaces); - - if ((h = ast_heap_peek(timing_interfaces, 1))) { - h->iface->timer_close(timer); - ast_module_unref(h->mod); - } + handle->holder->iface->timer_close(handle->fd); + ast_module_unref(handle->holder->mod); + ast_free(handle); +} - ast_heap_unlock(timing_interfaces); +int ast_timer_fd(const struct ast_timer *handle) +{ + return handle->fd; } -int ast_timer_set_rate(int handle, unsigned int rate) +int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate) { - struct timing_holder *h; int res = -1; - ast_heap_rdlock(timing_interfaces); - - if ((h = ast_heap_peek(timing_interfaces, 1))) { - res = h->iface->timer_set_rate(handle, rate); - } - - ast_heap_unlock(timing_interfaces); + res = handle->holder->iface->timer_set_rate(handle->fd, rate); return res; } -void ast_timer_ack(int handle, unsigned int quantity) +void ast_timer_ack(const struct ast_timer *handle, unsigned int quantity) { - struct timing_holder *h; - - ast_heap_rdlock(timing_interfaces); - - if ((h = ast_heap_peek(timing_interfaces, 1))) { - h->iface->timer_ack(handle, quantity); - } - - ast_heap_unlock(timing_interfaces); + handle->holder->iface->timer_ack(handle->fd, quantity); } -int ast_timer_enable_continuous(int handle) +int ast_timer_enable_continuous(const struct ast_timer *handle) { - struct timing_holder *h; int res = -1; - ast_heap_rdlock(timing_interfaces); - - if ((h = ast_heap_peek(timing_interfaces, 1))) { - res = h->iface->timer_enable_continuous(handle); - } - - ast_heap_unlock(timing_interfaces); + res = handle->holder->iface->timer_enable_continuous(handle->fd); return res; } -int ast_timer_disable_continuous(int handle) +int ast_timer_disable_continuous(const struct ast_timer *handle) { - struct timing_holder *h; int res = -1; - ast_heap_rdlock(timing_interfaces); - - if ((h = ast_heap_peek(timing_interfaces, 1))) { - res = h->iface->timer_disable_continuous(handle); - } - - ast_heap_unlock(timing_interfaces); + res = handle->holder->iface->timer_disable_continuous(handle->fd); return res; } -enum ast_timer_event ast_timer_get_event(int handle) +enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle) { - struct timing_holder *h; enum ast_timer_event res = -1; - ast_heap_rdlock(timing_interfaces); - - if ((h = ast_heap_peek(timing_interfaces, 1))) { - res = h->iface->timer_get_event(handle); - } - - ast_heap_unlock(timing_interfaces); + res = handle->holder->iface->timer_get_event(handle->fd); return res; } -unsigned int ast_timer_get_max_rate(int handle) +unsigned int ast_timer_get_max_rate(const struct ast_timer *handle) { - struct timing_holder *h; unsigned int res = 0; - ast_heap_rdlock(timing_interfaces); - - if ((h = ast_heap_peek(timing_interfaces, 1))) { - res = h->iface->timer_get_max_rate(handle); - } - - ast_heap_unlock(timing_interfaces); + res = handle->holder->iface->timer_get_max_rate(handle->fd); return res; } static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - int fd, count = 0; + struct ast_timer *timer; + int count = 0; struct timeval start, end; unsigned int test_rate = 50; - struct timing_holder *h; switch (cmd) { case CLI_INIT: @@ -268,26 +238,21 @@ static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args * ast_cli(a->fd, "Attempting to test a timer with %u ticks per second.\n", test_rate); - if ((fd = ast_timer_open()) == -1) { + if (!(timer = ast_timer_open())) { ast_cli(a->fd, "Failed to open timing fd\n"); return CLI_FAILURE; } - ast_heap_rdlock(timing_interfaces); - if ((h = ast_heap_peek(timing_interfaces, 1))) { - ast_cli(a->fd, "Using the '%s' timing module for this test.\n", h->iface->name); - h = NULL; - } - ast_heap_unlock(timing_interfaces); + ast_cli(a->fd, "Using the '%s' timing module for this test.\n", timer->holder->iface->name); start = ast_tvnow(); - ast_timer_set_rate(fd, test_rate); + ast_timer_set_rate(timer, test_rate); while (ast_tvdiff_ms((end = ast_tvnow()), start) < 1000) { int res; struct pollfd pfd = { - .fd = fd, + .fd = ast_timer_fd(timer), .events = POLLIN | POLLPRI, }; @@ -295,7 +260,7 @@ static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args * if (res == 1) { count++; - ast_timer_ack(fd, 1); + ast_timer_ack(timer, 1); } else if (!res) { ast_cli(a->fd, "poll() timed out! This is bad.\n"); } else if (errno != EAGAIN && errno != EINTR) { @@ -303,7 +268,7 @@ static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args * } } - ast_timer_close(fd); + ast_timer_close(timer); ast_cli(a->fd, "It has been %d milliseconds, and we got %d timer ticks\n", ast_tvdiff_ms(end, start), count); |