| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  |  * Copyright (C) 2008 - 2009, Digium, Inc. | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Kevin P. Fleming <kpfleming@digium.com> | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  |  * Russell Bryant <russell@digium.com> | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \file
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \brief Timing source management | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \author Kevin P. Fleming <kpfleming@digium.com> | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  |  * \author Russell Bryant <russell@digium.com> | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 16:20:16 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<support_level>core</support_level> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | #include "asterisk/_private.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | #include "asterisk/timing.h"
 | 
					
						
							|  |  |  | #include "asterisk/lock.h"
 | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | #include "asterisk/cli.h"
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							|  |  |  | #include "asterisk/time.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | #include "asterisk/heap.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-25 14:33:32 +00:00
										 |  |  | #include "asterisk/poll-compat.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct timing_holder { | 
					
						
							|  |  |  | 	/*! Do _not_ move this from the beginning of the struct. */ | 
					
						
							|  |  |  | 	ssize_t __heap_index; | 
					
						
							|  |  |  | 	struct ast_module *mod; | 
					
						
							|  |  |  | 	struct ast_timing_interface *iface; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | static struct ast_heap *timing_interfaces; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | struct ast_timer { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	void *data; | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	struct timing_holder *holder; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | static int timing_holder_cmp(void *_h1, void *_h2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct timing_holder *h1 = _h1; | 
					
						
							|  |  |  | 	struct timing_holder *h2 = _h2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (h1->iface->priority > h2->iface->priority) { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} else if (h1->iface->priority == h2->iface->priority) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | void *_ast_register_timing_interface(struct ast_timing_interface *funcs, | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 				     struct ast_module *mod) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	struct timing_holder *h; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 	if (!funcs->timer_open || | 
					
						
							|  |  |  | 	    !funcs->timer_close || | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	    !funcs->timer_set_rate || | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 	    !funcs->timer_ack || | 
					
						
							|  |  |  | 	    !funcs->timer_get_event || | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	    !funcs->timer_get_max_rate || | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 	    !funcs->timer_enable_continuous || | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	    !funcs->timer_disable_continuous || | 
					
						
							|  |  |  | 	    !funcs->timer_fd) { | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	if (!(h = ast_calloc(1, sizeof(*h)))) { | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	h->iface = funcs; | 
					
						
							|  |  |  | 	h->mod = mod; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	ast_heap_wrlock(timing_interfaces); | 
					
						
							|  |  |  | 	ast_heap_push(timing_interfaces, h); | 
					
						
							|  |  |  | 	ast_heap_unlock(timing_interfaces); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return h; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | int ast_unregister_timing_interface(void *handle) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	struct timing_holder *h = handle; | 
					
						
							|  |  |  | 	int res = -1; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	ast_heap_wrlock(timing_interfaces); | 
					
						
							|  |  |  | 	h = ast_heap_remove(timing_interfaces, h); | 
					
						
							|  |  |  | 	ast_heap_unlock(timing_interfaces); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	if (h) { | 
					
						
							|  |  |  | 		ast_free(h); | 
					
						
							|  |  |  | 		h = NULL; | 
					
						
							|  |  |  | 		res = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | struct ast_timer *ast_timer_open(void) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	void *data = NULL; | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	struct timing_holder *h; | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	struct ast_timer *t = NULL; | 
					
						
							| 
									
										
										
										
											2017-12-29 19:24:02 -05:00
										 |  |  | 	int idx = 1; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	ast_heap_rdlock(timing_interfaces); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 19:24:02 -05:00
										 |  |  | 	while ((h = ast_heap_peek(timing_interfaces, idx))) { | 
					
						
							|  |  |  | 		if (ast_module_running_ref(h->mod)) { | 
					
						
							|  |  |  | 			data = h->iface->timer_open(); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		idx++; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	if (data) { | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 		if (!(t = ast_calloc(1, sizeof(*t)))) { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 			h->iface->timer_close(data); | 
					
						
							| 
									
										
										
										
											2017-12-29 19:24:02 -05:00
										 |  |  | 			ast_module_unref(h->mod); | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 			t->data = data; | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 			t->holder = h; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	ast_heap_unlock(timing_interfaces); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	return t; | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | void ast_timer_close(struct ast_timer *handle) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	handle->holder->iface->timer_close(handle->data); | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	ast_module_unref(handle->holder->mod); | 
					
						
							|  |  |  | 	ast_free(handle); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | int ast_timer_fd(const struct ast_timer *handle) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	return handle->holder->iface->timer_fd(handle->data); | 
					
						
							| 
									
										
										
										
											2008-06-13 12:45:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate) | 
					
						
							| 
									
										
										
										
											2008-06-13 12:45:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	return handle->holder->iface->timer_set_rate(handle->data, rate); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-05 23:10:14 +00:00
										 |  |  | int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	return handle->holder->iface->timer_ack(handle->data, quantity); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | int ast_timer_enable_continuous(const struct ast_timer *handle) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	return handle->holder->iface->timer_enable_continuous(handle->data); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | int ast_timer_disable_continuous(const struct ast_timer *handle) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	return handle->holder->iface->timer_disable_continuous(handle->data); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle) | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	return handle->holder->iface->timer_get_event(handle->data); | 
					
						
							| 
									
										
										
										
											2008-06-12 14:21:32 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | unsigned int ast_timer_get_max_rate(const struct ast_timer *handle) | 
					
						
							| 
									
										
										
										
											2008-06-26 15:37:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-07 20:01:45 +00:00
										 |  |  | 	return handle->holder->iface->timer_get_max_rate(handle->data); | 
					
						
							| 
									
										
										
										
											2008-06-26 15:37:01 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 22:03:54 +00:00
										 |  |  | const char *ast_timer_get_name(const struct ast_timer *handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return handle->holder->iface->name; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	struct ast_timer *timer; | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 	struct timeval start, end; | 
					
						
							| 
									
										
										
										
											2008-06-19 18:30:49 +00:00
										 |  |  | 	unsigned int test_rate = 50; | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "timing test"; | 
					
						
							| 
									
										
										
										
											2008-06-19 18:30:49 +00:00
										 |  |  | 		e->usage = "Usage: timing test <rate>\n" | 
					
						
							| 
									
										
										
										
											2009-12-14 16:08:09 +00:00
										 |  |  | 		           "   Test a timer with a specified rate, 50/sec by default.\n" | 
					
						
							| 
									
										
										
										
											2008-06-19 18:30:49 +00:00
										 |  |  | 		           ""; | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-19 18:30:49 +00:00
										 |  |  | 	if (a->argc != 2 && a->argc != 3) { | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->argc == 3) { | 
					
						
							|  |  |  | 		unsigned int rate; | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 		if (sscanf(a->argv[2], "%30u", &rate) == 1) { | 
					
						
							| 
									
										
										
										
											2008-06-19 18:30:49 +00:00
										 |  |  | 			test_rate = rate; | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 			ast_cli(a->fd, "Invalid rate '%s', using default of %u\n", a->argv[2], test_rate); | 
					
						
							| 
									
										
										
										
											2008-06-19 18:30:49 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	ast_cli(a->fd, "Attempting to test a timer with %u ticks per second.\n", test_rate); | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	if (!(timer = ast_timer_open())) { | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 		ast_cli(a->fd, "Failed to open timing fd\n"); | 
					
						
							|  |  |  | 		return CLI_FAILURE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	ast_cli(a->fd, "Using the '%s' timing module for this test.\n", timer->holder->iface->name); | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 	start = ast_tvnow(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	ast_timer_set_rate(timer, test_rate); | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (ast_tvdiff_ms((end = ast_tvnow()), start) < 1000) { | 
					
						
							|  |  |  | 		int res; | 
					
						
							|  |  |  | 		struct pollfd pfd = { | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 			.fd = ast_timer_fd(timer), | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 			.events = POLLIN | POLLPRI, | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-25 02:03:13 +00:00
										 |  |  | 		res = ast_poll(&pfd, 1, 100); | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (res == 1) { | 
					
						
							|  |  |  | 			count++; | 
					
						
							| 
									
										
										
										
											2012-11-05 23:10:14 +00:00
										 |  |  | 			if (ast_timer_ack(timer, 1) < 0) { | 
					
						
							|  |  |  | 				ast_cli(a->fd, "Timer failed to acknowledge.\n"); | 
					
						
							|  |  |  | 				ast_timer_close(timer); | 
					
						
							|  |  |  | 				return CLI_FAILURE; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 		} else if (!res) { | 
					
						
							|  |  |  | 			ast_cli(a->fd, "poll() timed out!  This is bad.\n"); | 
					
						
							|  |  |  | 		} else if (errno != EAGAIN && errno != EINTR) { | 
					
						
							|  |  |  | 			ast_cli(a->fd, "poll() returned error: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 19:10:32 +00:00
										 |  |  | 	ast_timer_close(timer); | 
					
						
							| 
									
										
										
										
											2012-11-05 23:10:14 +00:00
										 |  |  | 	timer = NULL; | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  | 	ast_cli(a->fd, "It has been %" PRIi64 " milliseconds, and we got %d timer ticks\n", | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 		ast_tvdiff_ms(end, start), count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return CLI_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_cli_entry cli_timing[] = { | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(timing_test, "Run a timing test"), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-11 22:03:23 +00:00
										 |  |  | static void timing_shutdown(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ast_cli_unregister_multiple(cli_timing, ARRAY_LEN(cli_timing)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_heap_destroy(timing_interfaces); | 
					
						
							|  |  |  | 	timing_interfaces = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | int ast_timing_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-17 21:22:40 +00:00
										 |  |  | 	if (!(timing_interfaces = ast_heap_create(2, timing_holder_cmp, 0))) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-26 22:24:26 +00:00
										 |  |  | 	ast_register_cleanup(timing_shutdown); | 
					
						
							| 
									
										
										
										
											2012-12-11 22:03:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 13:03:40 +00:00
										 |  |  | 	return ast_cli_register_multiple(cli_timing, ARRAY_LEN(cli_timing)); | 
					
						
							|  |  |  | } |