From eaf3bfa1886928240eda3a83ab1ece3d61f7fd50 Mon Sep 17 00:00:00 2001 From: Venky Shankar Date: Fri, 22 May 2015 11:54:11 +0530 Subject: contrib/timer-wheel: mod_timer() and friends Couple of timer-wheel api's to modify timer expiry times: mod_timer() mod_timer_pending() Both the api's perform almost the same job with one minute difference: mod_timer_pending() modifies timer expiry only if the timer is pending (i.e. being tracked in timer-wheel). Change-Id: Iae64934854ccfd6b081b849bff998ae3c3021bac BUG: 1224596 Signed-off-by: Venky Shankar Reviewed-on: http://review.gluster.org/10892 Tested-by: NetBSD Build System Reviewed-by: Niels de Vos Tested-by: Gluster Build System --- contrib/timer-wheel/timer-wheel.c | 86 +++++++++++++++++++++++++++++++++++++-- contrib/timer-wheel/timer-wheel.h | 8 +++- 2 files changed, 89 insertions(+), 5 deletions(-) (limited to 'contrib') diff --git a/contrib/timer-wheel/timer-wheel.c b/contrib/timer-wheel/timer-wheel.c index 77fbfbe9953..df8bb31fe87 100644 --- a/contrib/timer-wheel/timer-wheel.c +++ b/contrib/timer-wheel/timer-wheel.c @@ -85,11 +85,12 @@ apply_slack(struct tvec_base *base, struct gf_tw_timer_list *timer) } static inline void -gf_tw_detach_timer (struct gf_tw_timer_list *timer) +__gf_tw_detach_timer (struct gf_tw_timer_list *timer) { struct list_head *entry = &timer->entry; list_del (entry); + entry->next = NULL; } static inline int @@ -141,7 +142,7 @@ run_timers (struct tvec_base *base) fn = timer->function; data = timer->data; - gf_tw_detach_timer (timer); + __gf_tw_detach_timer (timer); fn (timer, data, call_time); } } @@ -166,6 +167,38 @@ void *runner (void *arg) } +static inline int timer_pending (struct gf_tw_timer_list *timer) +{ + struct list_head *entry = &timer->entry; + + return (entry->next != NULL); +} + +static inline int __detach_if_pending (struct gf_tw_timer_list *timer) +{ + if (!timer_pending (timer)) + return 0; + + __gf_tw_detach_timer (timer); + return 1; +} + +static inline int __mod_timer (struct tvec_base *base, + struct gf_tw_timer_list *timer, int pending_only) +{ + int ret = 0; + + ret = __detach_if_pending (timer); + if (!ret && pending_only) + goto done; + + ret = 1; + __gf_tw_add_timer (base, timer); + + done: + return ret; +} + /* interface */ /** @@ -185,9 +218,54 @@ void gf_tw_add_timer (struct tvec_base *base, struct gf_tw_timer_list *timer) /** * Remove a timer from the timer wheel */ -void gf_tw_del_timer (struct gf_tw_timer_list *timer) +void gf_tw_del_timer (struct tvec_base *base, struct gf_tw_timer_list *timer) { - gf_tw_detach_timer (timer); + pthread_spin_lock (&base->lock); + { + if (timer_pending (timer)) + __gf_tw_detach_timer (timer); + } + pthread_spin_lock (&base->lock); +} + +int gf_tw_mod_timer_pending (struct tvec_base *base, + struct gf_tw_timer_list *timer, + unsigned long expires) +{ + int ret = 1; + + pthread_spin_lock (&base->lock); + { + timer->expires = expires + base->timer_sec; + timer->expires = apply_slack (base, timer); + + ret = __mod_timer (base, timer, 1); + } + pthread_spin_unlock (&base->lock); + + return ret; +} + +int gf_tw_mod_timer (struct tvec_base *base, + struct gf_tw_timer_list *timer, unsigned long expires) +{ + int ret = 1; + + pthread_spin_lock (&base->lock); + { + /* fast path optimization */ + if (timer_pending (timer) && timer->expires == expires) + goto unblock; + + timer->expires = expires + base->timer_sec; + timer->expires = apply_slack (base, timer); + + ret = __mod_timer (base, timer, 0); + } + unblock: + pthread_spin_unlock (&base->lock); + + return ret; } int gf_tw_cleanup_timers (struct tvec_base *base) diff --git a/contrib/timer-wheel/timer-wheel.h b/contrib/timer-wheel/timer-wheel.h index 74b8dfdff5e..c52f2fc9b9c 100644 --- a/contrib/timer-wheel/timer-wheel.h +++ b/contrib/timer-wheel/timer-wheel.h @@ -66,6 +66,12 @@ struct gf_tw_timer_list { struct tvec_base *gf_tw_init_timers (); int gf_tw_cleanup_timers (struct tvec_base *); void gf_tw_add_timer (struct tvec_base *, struct gf_tw_timer_list *); -void gf_tw_del_timer (struct gf_tw_timer_list *); +void gf_tw_del_timer (struct tvec_base *, struct gf_tw_timer_list *); + +int gf_tw_mod_timer_pending (struct tvec_base *, + struct gf_tw_timer_list *, unsigned long); + +int gf_tw_mod_timer (struct tvec_base *, + struct gf_tw_timer_list *, unsigned long); #endif -- cgit