diff options
author | Joshua Colp <jcolp@digium.com> | 2014-02-07 20:01:45 +0000 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2014-02-07 20:01:45 +0000 |
commit | e8e2f91bbac77ca50dddc4a496512475990a8764 (patch) | |
tree | fdbb590820a386771e01916e9dbd7809bd187232 /res/res_timing_kqueue.c | |
parent | 5fd63e2d0beeae4e118a7567716b586899166090 (diff) |
timing: Improve performance for most timing implementations.
This change allows timing implementation data to be stored directly
on the timer itself thus removing the requirement for many
implementations to do a container lookup for the same information.
This means that API calls into timing implementations can directly
access the information they need instead of having to find it.
Review: https://reviewboard.asterisk.org/r/3175/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407749 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_timing_kqueue.c')
-rw-r--r-- | res/res_timing_kqueue.c | 188 |
1 files changed, 58 insertions, 130 deletions
diff --git a/res/res_timing_kqueue.c b/res/res_timing_kqueue.c index b5bc01f3f..3c0bfcc73 100644 --- a/res/res_timing_kqueue.c +++ b/res/res_timing_kqueue.c @@ -48,14 +48,15 @@ static void *timing_funcs_handle; -static int kqueue_timer_open(void); -static void kqueue_timer_close(int handle); -static int kqueue_timer_set_rate(int handle, unsigned int rate); -static int kqueue_timer_ack(int handle, unsigned int quantity); -static int kqueue_timer_enable_continuous(int handle); -static int kqueue_timer_disable_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 void *kqueue_timer_open(void); +static void kqueue_timer_close(void *data); +static int kqueue_timer_set_rate(void *data, unsigned int rate); +static int kqueue_timer_ack(void *data, unsigned int quantity); +static int kqueue_timer_enable_continuous(void *data); +static int kqueue_timer_disable_continuous(void *data); +static enum ast_timer_event kqueue_timer_get_event(void *data); +static unsigned int kqueue_timer_get_max_rate(void *data); +static int kqueue_timer_fd(void *data); static struct ast_timing_interface kqueue_timing = { .name = "kqueue", @@ -68,10 +69,9 @@ static struct ast_timing_interface kqueue_timing = { .timer_disable_continuous = kqueue_timer_disable_continuous, .timer_get_event = kqueue_timer_get_event, .timer_get_max_rate = kqueue_timer_get_max_rate, + .timer_fd = kqueue_timer_fd, }; -static struct ao2_container *kqueue_timers; - struct kqueue_timer { int handle; uint64_t nsecs; @@ -79,73 +79,34 @@ struct kqueue_timer { unsigned int is_continuous:1; }; -static int kqueue_timer_hash(const void *obj, const int flags) -{ - const struct kqueue_timer *timer = obj; - - return timer->handle; -} - -static int kqueue_timer_cmp(void *obj, void *args, int flags) -{ - struct kqueue_timer *timer1 = obj, *timer2 = args; - return timer1->handle == timer2->handle ? CMP_MATCH | CMP_STOP : 0; -} - static void timer_destroy(void *obj) { struct kqueue_timer *timer = obj; close(timer->handle); } -#define lookup_timer(a) _lookup_timer(a, __FILE__, __LINE__, __PRETTY_FUNCTION__) -static struct kqueue_timer *_lookup_timer(int handle, const char *file, int line, const char *func) -{ - struct kqueue_timer *our_timer, find_helper = { - .handle = handle, - }; - - if (!(our_timer = ao2_find(kqueue_timers, &find_helper, OBJ_POINTER))) { - ast_log(__LOG_ERROR, file, line, func, "Couldn't find timer with handle %d\n", handle); - /* API says we set errno */ - errno = ESRCH; - return NULL; - } - return our_timer; -} - -static int kqueue_timer_open(void) +static void *kqueue_timer_open(void) { struct kqueue_timer *timer; - int handle; if (!(timer = ao2_alloc(sizeof(*timer), timer_destroy))) { ast_log(LOG_ERROR, "Could not allocate memory for kqueue_timer structure\n"); return -1; } - if ((handle = kqueue()) < 0) { + if ((timer->handle = kqueue()) < 0) { ast_log(LOG_ERROR, "Failed to create kqueue timer: %s\n", strerror(errno)); ao2_ref(timer, -1); return -1; } - timer->handle = handle; - ao2_link(kqueue_timers, timer); - /* Get rid of the reference from the allocation */ - ao2_ref(timer, -1); - return handle; + return timer; } -static void kqueue_timer_close(int handle) +static void kqueue_timer_close(void *data) { - struct kqueue_timer *our_timer; + struct kqueue_timer *timer = data; - if (!(our_timer = lookup_timer(handle))) { - return; - } - - ao2_unlink(kqueue_timers, our_timer); - ao2_ref(our_timer, -1); + ao2_ref(timer, -1); } static void kqueue_set_nsecs(struct kqueue_timer *our_timer, uint64_t nsecs) @@ -183,107 +144,90 @@ static void kqueue_set_nsecs(struct kqueue_timer *our_timer, uint64_t nsecs) #endif } -static int kqueue_timer_set_rate(int handle, unsigned int rate) +static int kqueue_timer_set_rate(void *data, unsigned int rate) { - struct kqueue_timer *our_timer; + struct kqueue_timer *timer = data; - if (!(our_timer = lookup_timer(handle))) { - return -1; - } - - kqueue_set_nsecs(our_timer, (our_timer->nsecs = rate ? (long) (1000000000 / rate) : 0L)); - ao2_ref(our_timer, -1); + kqueue_set_nsecs(timer, (timer->nsecs = rate ? (long) (1000000000 / rate) : 0L)); return 0; } -static int kqueue_timer_ack(int handle, unsigned int quantity) +static int kqueue_timer_ack(void *data, unsigned int quantity) { - struct kqueue_timer *our_timer; + struct kqueue_timer *timer = data; - if (!(our_timer = lookup_timer(handle))) { - return -1; - } - - if (our_timer->unacked < quantity) { + if (timer->unacked < quantity) { ast_debug(1, "Acking more events than have expired?!!\n"); - our_timer->unacked = 0; - ao2_ref(our_timer, -1); + timer->unacked = 0; return -1; } else { - our_timer->unacked -= quantity; + timer->unacked -= quantity; } - ao2_ref(our_timer, -1); return 0; } -static int kqueue_timer_enable_continuous(int handle) +static int kqueue_timer_enable_continuous(void *data) { - struct kqueue_timer *our_timer; + struct kqueue_timer *timer = data; - if (!(our_timer = lookup_timer(handle))) { - return -1; - } + kqueue_set_nsecs(timer, 1); + timer->is_continuous = 1; + timer->unacked = 0; - kqueue_set_nsecs(our_timer, 1); - our_timer->is_continuous = 1; - our_timer->unacked = 0; - ao2_ref(our_timer, -1); return 0; } -static int kqueue_timer_disable_continuous(int handle) +static int kqueue_timer_disable_continuous(void *data) { - struct kqueue_timer *our_timer; + struct kqueue_timer *timer = data; - if (!(our_timer = lookup_timer(handle))) { - return -1; - } + kqueue_set_nsecs(timer, timer->nsecs); + timer->is_continuous = 0; + timer->unacked = 0; - kqueue_set_nsecs(our_timer, our_timer->nsecs); - our_timer->is_continuous = 0; - our_timer->unacked = 0; - ao2_ref(our_timer, -1); return 0; } -static enum ast_timer_event kqueue_timer_get_event(int handle) +static enum ast_timer_event kqueue_timer_get_event(void *data) { + struct kqueue_timer *timer = data; enum ast_timer_event res = -1; - struct kqueue_timer *our_timer; struct timespec sixty_seconds = { 60, 0 }; struct kevent kev; - if (!(our_timer = lookup_timer(handle))) { - return -1; - } - /* If we have non-ACKed events, just return immediately */ - if (our_timer->unacked == 0) { - if (kevent(handle, NULL, 0, &kev, 1, &sixty_seconds) > 0) { - our_timer->unacked += kev.data; + if (timer->unacked == 0) { + if (kevent(timer->handle, NULL, 0, &kev, 1, &sixty_seconds) > 0) { + timer->unacked += kev.data; } } - if (our_timer->unacked > 0) { - res = our_timer->is_continuous ? AST_TIMING_EVENT_CONTINUOUS : AST_TIMING_EVENT_EXPIRED; + if (timer->unacked > 0) { + res = timer->is_continuous ? AST_TIMING_EVENT_CONTINUOUS : AST_TIMING_EVENT_EXPIRED; } - ao2_ref(our_timer, -1); return res; } -static unsigned int kqueue_timer_get_max_rate(int handle) +static unsigned int kqueue_timer_get_max_rate(void *data) { /* Actually, the max rate is 2^64-1 seconds, but that's not representable in a 32-bit integer. */ return UINT_MAX; } +static int kqueue_timer_fd(void *data) +{ + struct kqueue_timer *timer = data; + + return timer->handle; +} + #ifdef TEST_FRAMEWORK AST_TEST_DEFINE(test_kqueue_timing) { - int res = AST_TEST_PASS, handle, i; + int res = AST_TEST_PASS, i; uint64_t diff; struct pollfd pfd = { 0, POLLIN, 0 }; struct kqueue_timer *kt; @@ -300,14 +244,14 @@ AST_TEST_DEFINE(test_kqueue_timing) break; } - if (!(handle = kqueue_timer_open())) { + if (!(kt = kqueue_timer_open())) { ast_test_status_update(test, "Cannot open timer!\n"); return AST_TEST_FAIL; } do { - pfd.fd = handle; - if (kqueue_timer_set_rate(handle, 1000)) { + pfd.fd = ast_timer_fd(kt); + if (kqueue_timer_set_rate(kt, 1000)) { ast_test_status_update(test, "Cannot set timer rate to 1000/s\n"); res = AST_TEST_FAIL; break; @@ -322,12 +266,7 @@ AST_TEST_DEFINE(test_kqueue_timing) res = AST_TEST_FAIL; break; } - if (!(kt = lookup_timer(handle))) { - ast_test_status_update(test, "Could not find timer structure in container?!!\n"); - res = AST_TEST_FAIL; - break; - } - if (kqueue_timer_get_event(handle) <= 0) { + if (kqueue_timer_get_event(kt) <= 0) { ast_test_status_update(test, "No events generated after a poll returned successfully?!!\n"); res = AST_TEST_FAIL; break; @@ -339,7 +278,7 @@ AST_TEST_DEFINE(test_kqueue_timing) break; } #endif - kqueue_timer_enable_continuous(handle); + kqueue_timer_enable_continuous(kt); start = ast_tvnow(); for (i = 0; i < 100; i++) { if (ast_poll(&pfd, 1, 1000) < 1) { @@ -347,7 +286,7 @@ AST_TEST_DEFINE(test_kqueue_timing) res = AST_TEST_FAIL; break; } - if (kqueue_timer_get_event(handle) <= 0) { + if (kqueue_timer_get_event(kt) <= 0) { ast_test_status_update(test, "No events generated in continuous mode after 1 microsecond?!!\n"); res = AST_TEST_FAIL; break; @@ -362,7 +301,7 @@ AST_TEST_DEFINE(test_kqueue_timing) } */ } while (0); - kqueue_timer_close(handle); + kqueue_timer_close(kt); return res; } #endif @@ -379,12 +318,7 @@ AST_TEST_DEFINE(test_kqueue_timing) */ static int load_module(void) { - if (!(kqueue_timers = ao2_container_alloc(563, kqueue_timer_hash, kqueue_timer_cmp))) { - return AST_MODULE_LOAD_DECLINE; - } - if (!(timing_funcs_handle = ast_register_timing_interface(&kqueue_timing))) { - ao2_ref(kqueue_timers, -1); return AST_MODULE_LOAD_DECLINE; } @@ -394,15 +328,9 @@ static int load_module(void) static int unload_module(void) { - int res; - AST_TEST_UNREGISTER(test_kqueue_timing); - if (!(res = ast_unregister_timing_interface(timing_funcs_handle))) { - ao2_ref(kqueue_timers, -1); - kqueue_timers = NULL; - } - return res; + return ast_unregister_timing_interface(timing_funcs_handle); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "KQueue Timing Interface", |