diff options
Diffstat (limited to 'libglusterfs/src/timer.c')
| -rw-r--r-- | libglusterfs/src/timer.c | 128 | 
1 files changed, 71 insertions, 57 deletions
diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c index a072985acce..bcdc5da5571 100644 --- a/libglusterfs/src/timer.c +++ b/libglusterfs/src/timer.c @@ -15,6 +15,10 @@  #include "timespec.h"  #include "libglusterfs-messages.h" +/* fwd decl */ +static gf_timer_registry_t * +gf_timer_registry_init (glusterfs_ctx_t *); +  gf_timer_t *  gf_timer_call_after (glusterfs_ctx_t *ctx,                       struct timespec delta, @@ -33,17 +37,6 @@ gf_timer_call_after (glusterfs_ctx_t *ctx,                  return NULL;          } -        /* ctx and its fields are not accessed inside mutex!? -         * TODO: Even with this there is a possiblity of race -         * when cleanup_started is set after checking for it -         */ -        if (ctx->cleanup_started) { -                gf_msg_callingfn ("timer", GF_LOG_INFO, 0, -                                  LG_MSG_CTX_CLEANUP_STARTED, "ctx cleanup " -                                  "started"); -                return NULL; -        } -          reg = gf_timer_registry_init (ctx);          if (!reg) { @@ -62,7 +55,7 @@ gf_timer_call_after (glusterfs_ctx_t *ctx,          event->callbk = callbk;          event->data = data;          event->xl = THIS; -        pthread_mutex_lock (®->lock); +        LOCK (®->lock);          {                  trav = reg->active.prev;                  while (trav != ®->active) { @@ -75,10 +68,11 @@ gf_timer_call_after (glusterfs_ctx_t *ctx,                  event->prev->next = event;                  event->next->prev = event;          } -        pthread_mutex_unlock (®->lock); +        UNLOCK (®->lock);          return event;  } +  int32_t  gf_timer_call_cancel (glusterfs_ctx_t *ctx,                        gf_timer_t *event) @@ -93,7 +87,12 @@ gf_timer_call_cancel (glusterfs_ctx_t *ctx,                  return 0;          } -        reg = gf_timer_registry_init (ctx); +        LOCK (&ctx->lock); +        { +                reg = ctx->timer; +        } +        UNLOCK (&ctx->lock); +          if (!reg) {                  gf_msg ("timer", GF_LOG_ERROR, 0, LG_MSG_INIT_TIMER_FAILED,                          "!reg"); @@ -101,53 +100,42 @@ gf_timer_call_cancel (glusterfs_ctx_t *ctx,                  return 0;          } -        pthread_mutex_lock (®->lock); +        LOCK (®->lock);          { -		fired = event->fired; -		if (fired) -			goto unlock; +                fired = event->fired; +                if (fired) +                        goto unlock;                  event->next->prev = event->prev;                  event->prev->next = event->next;          }  unlock: -        pthread_mutex_unlock (®->lock); +        UNLOCK (®->lock); -	if (!fired) { -		GF_FREE (event); -		return 0; +        if (!fired) { +                GF_FREE (event); +                return 0;          }          return -1;  } -static void __delete_entry (gf_timer_t *event) { + +static void +__delete_entry (gf_timer_t *event) {          event->next->prev = event->prev;          event->prev->next = event->next;          GF_FREE (event);  } -void * -gf_timer_proc (void *ctx) + +static void * +gf_timer_proc (void *data)  { -        gf_timer_registry_t *reg = NULL; +        gf_timer_registry_t *reg = data;          const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, };          gf_timer_t *event = NULL;          xlator_t   *old_THIS = NULL; -        if (ctx == NULL) -        { -                gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL, -                                  LG_MSG_INVALID_ARG, "invalid argument"); -                return NULL; -        } - -        reg = gf_timer_registry_init (ctx); -        if (!reg) { -                gf_msg ("timer", GF_LOG_ERROR, 0, LG_MSG_INIT_TIMER_FAILED, -                        "!reg"); -                return NULL; -        } -          while (!reg->fin) {                  uint64_t now;                  struct timespec now_ts; @@ -158,7 +146,7 @@ gf_timer_proc (void *ctx)                          uint64_t at;                          char need_cbk = 0; -                        pthread_mutex_lock (®->lock); +                        LOCK (®->lock);                          {                                  event = reg->active.next;                                  at = TS (event->at); @@ -169,7 +157,7 @@ gf_timer_proc (void *ctx)                                          event->fired = _gf_true;                                  }                          } -                        pthread_mutex_unlock (®->lock); +                        UNLOCK (®->lock);                          if (need_cbk) {                                  old_THIS = NULL;                                  if (event->xl) { @@ -188,7 +176,7 @@ gf_timer_proc (void *ctx)                  nanosleep (&sleepts, NULL);          } -        pthread_mutex_lock (®->lock); +        LOCK (®->lock);          {                  /* Do not call gf_timer_call_cancel(),                   * it will lead to deadlock @@ -200,42 +188,58 @@ gf_timer_proc (void *ctx)                          __delete_entry (event);                  }          } -        pthread_mutex_unlock (®->lock); -        pthread_mutex_destroy (®->lock); -        GF_FREE (((glusterfs_ctx_t *)ctx)->timer); +        UNLOCK (®->lock); +        LOCK_DESTROY (®->lock);          return NULL;  } -gf_timer_registry_t * + +static gf_timer_registry_t *  gf_timer_registry_init (glusterfs_ctx_t *ctx)  { +        gf_timer_registry_t *reg = NULL; +          if (ctx == NULL) {                  gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL,                                    LG_MSG_INVALID_ARG, "invalid argument");                  return NULL;          } -        if (!ctx->timer) { -                gf_timer_registry_t *reg = NULL; +        if (ctx->cleanup_started) { +                gf_msg_callingfn ("timer", GF_LOG_INFO, 0, +                                  LG_MSG_CTX_CLEANUP_STARTED, +                                  "ctx cleanup started"); +                return NULL; +        } +        LOCK (&ctx->lock); +        { +                reg = ctx->timer; +        } +        UNLOCK (&ctx->lock); +        if (!reg) {                  reg = GF_CALLOC (1, sizeof (*reg),                                   gf_common_mt_gf_timer_registry_t);                  if (!reg) -                        goto out; +                        return NULL; -                pthread_mutex_init (®->lock, NULL); +                LOCK_INIT (®->lock);                  reg->active.next = ®->active;                  reg->active.prev = ®->active; -                ctx->timer = reg; -                gf_thread_create (®->th, NULL, gf_timer_proc, ctx); - +                LOCK (&ctx->lock); +                { +                        ctx->timer = reg; +                } +                UNLOCK (&ctx->lock); +                gf_thread_create (®->th, NULL, gf_timer_proc, reg);          } -out: -        return ctx->timer; + +        return reg;  } +  void  gf_timer_registry_destroy (glusterfs_ctx_t *ctx)  { @@ -245,8 +249,18 @@ gf_timer_registry_destroy (glusterfs_ctx_t *ctx)          if (ctx == NULL)                  return; -        reg = ctx->timer; +        LOCK (&ctx->lock); +        { +                reg = ctx->timer; +                ctx->timer = NULL; +        } +        UNLOCK (&ctx->lock); + +        if (!reg) +                return; +          thr_id = reg->th;          reg->fin = 1;          pthread_join (thr_id, NULL); +        GF_FREE (reg);  }  | 
