diff options
Diffstat (limited to 'libglusterfs/src/timer.c')
| -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);  | 
