diff options
author | Jeff Darcy <jdarcy@fb.com> | 2017-11-06 06:02:24 -0800 |
---|---|---|
committer | Jeff Darcy <jeff@pl.atyp.us> | 2017-11-07 20:18:43 +0000 |
commit | 54bf1a9d46eeb5c4582977eb2bc1d4fbd4f9dd91 (patch) | |
tree | 7ce0a6d760cbd9e4241a3754f283058024919209 /libglusterfs | |
parent | 4b18826de7fda26b66ca3123a28830a9c8d72ec4 (diff) |
libglusterfs: fix (some) silliness in timer.c
This addresses two issues. First is that we currently keep
traversing the timer list even when it's no longer possible for
us to find a timer that's ready to fire. Second is that we sleep
a full second even when the next timer is due sooner.
Change-Id: I178a460d0176dbb45f972c62ee94c6df66d92ca5
Signed-off-by: Jeff Darcy <jdarcy@fb.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r-- | libglusterfs/src/timer.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c index 3d69a9f7160..069fad188e2 100644 --- a/libglusterfs/src/timer.c +++ b/libglusterfs/src/timer.c @@ -117,7 +117,7 @@ static void * gf_timer_proc (void *data) { gf_timer_registry_t *reg = data; - const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, }; + struct timespec sleepts; gf_timer_t *event = NULL; gf_timer_t *tmp = NULL; xlator_t *old_THIS = NULL; @@ -132,8 +132,29 @@ gf_timer_proc (void *data) uint64_t at; char need_cbk = 0; + /* + * This will be overridden with a shorter interval if + * there's an event scheduled sooner. That makes the + * system more responsive in most cases, but doesn't + * include the case where a timer is added while we're + * asleep. It's tempting to use pthread_cond_timedwait, + * with the caveat that we'd be relying on system time + * instead of monotonic time. That's a mess when the + * system time is adjusted. Another alternative might + * be to use pthread_kill, but that will remain TBD for + * now. + */ + sleepts.tv_sec = 1; + sleepts.tv_nsec = 0; + LOCK (®->lock); { + /* + * Using list_for_each and then always breaking + * after the first iteration might seem strange, + * but (unlike alternatives) is independent of + * the underlying list implementation. + */ list_for_each_entry_safe (event, tmp, ®->active, list) { at = TS (event->at); @@ -141,8 +162,15 @@ gf_timer_proc (void *data) need_cbk = 1; event->fired = _gf_true; list_del (&event->list); - break; + } else { + uint64_t diff = now - at; + + if (diff < 1000000000) { + sleepts.tv_sec = 0; + sleepts.tv_nsec = diff; + } } + break; } } UNLOCK (®->lock); |