summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenky Shankar <vshankar@redhat.com>2015-05-22 11:54:11 +0530
committerVijay Bellur <vbellur@redhat.com>2015-05-28 02:44:25 -0700
commiteaf3bfa1886928240eda3a83ab1ece3d61f7fd50 (patch)
treebe69c62dce342351e14e9043da236c459c368678
parente9290dc0db7bee31cda1cbed1d9eb68d9c404746 (diff)
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 <vshankar@redhat.com> Reviewed-on: http://review.gluster.org/10892 Tested-by: NetBSD Build System Reviewed-by: Niels de Vos <ndevos@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com>
-rw-r--r--contrib/timer-wheel/timer-wheel.c86
-rw-r--r--contrib/timer-wheel/timer-wheel.h8
2 files changed, 89 insertions, 5 deletions
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