src/event/ngx_event_busy_lock.c - nginx-1.7.10

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. static ngx_int_t ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
  9.     ngx_event_busy_lock_ctx_t *ctx);
  10. static void ngx_event_busy_lock_handler(ngx_event_t *ev);
  11. static void ngx_event_busy_lock_posted_handler(ngx_event_t *ev);


  12. /*
  13. * NGX_OK:     the busy lock is held
  14. * NGX_AGAIN:  the all busy locks are held but we will wait the specified time
  15. * NGX_BUSY:   ctx->timer == 0: there are many the busy locks
  16. *             ctx->timer != 0: there are many the waiting locks
  17. */

  18. ngx_int_t
  19. ngx_event_busy_lock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx)
  20. {
  21.     ngx_int_t  rc;

  22.     ngx_mutex_lock(bl->mutex);

  23.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
  24.                    "event busy lock: b:%d mb:%d",
  25.                    bl->busy, bl->max_busy);

  26.     if (bl->busy < bl->max_busy) {
  27.         bl->busy++;

  28.         rc = NGX_OK;

  29.     } else if (ctx->timer && bl->waiting < bl->max_waiting) {
  30.         bl->waiting++;
  31.         ngx_add_timer(ctx->event, ctx->timer);
  32.         ctx->event->handler = ngx_event_busy_lock_handler;

  33.         if (bl->events) {
  34.             bl->last->next = ctx;

  35.         } else {
  36.             bl->events = ctx;
  37.         }

  38.         bl->last = ctx;

  39.         rc = NGX_AGAIN;

  40.     } else {
  41.         rc = NGX_BUSY;
  42.     }

  43.     ngx_mutex_unlock(bl->mutex);

  44.     return rc;
  45. }


  46. ngx_int_t
  47. ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
  48.     ngx_event_busy_lock_ctx_t *ctx)
  49. {
  50.     ngx_int_t  rc;

  51.     ngx_mutex_lock(bl->mutex);

  52.     rc = ngx_event_busy_lock_look_cacheable(bl, ctx);

  53.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
  54.                    "event busy lock: %d w:%d mw:%d",
  55.                    rc, bl->waiting, bl->max_waiting);

  56.     /*
  57.      * NGX_OK:     no the same request, there is free slot and we locked it
  58.      * NGX_BUSY:   no the same request and there is no free slot
  59.      * NGX_AGAIN:  the same request is processing
  60.      */

  61.     if (rc == NGX_AGAIN) {

  62.         if (ctx->timer && bl->waiting < bl->max_waiting) {
  63.             bl->waiting++;
  64.             ngx_add_timer(ctx->event, ctx->timer);
  65.             ctx->event->handler = ngx_event_busy_lock_handler;

  66.             if (bl->events == NULL) {
  67.                 bl->events = ctx;
  68.             } else {
  69.                 bl->last->next = ctx;
  70.             }
  71.             bl->last = ctx;

  72.         } else {
  73.             rc = NGX_BUSY;
  74.         }
  75.     }

  76.     ngx_mutex_unlock(bl->mutex);

  77.     return rc;
  78. }


  79. void
  80. ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
  81.     ngx_event_busy_lock_ctx_t *ctx)
  82. {
  83.     ngx_event_t                *ev;
  84.     ngx_event_busy_lock_ctx_t  *wakeup;

  85.     ngx_mutex_lock(bl->mutex);

  86.     if (bl->events) {
  87.         wakeup = bl->events;
  88.         bl->events = bl->events->next;

  89.     } else {
  90.         wakeup = NULL;
  91.         bl->busy--;
  92.     }

  93.     /*
  94.      * MP: all ctx's and their queue must be in shared memory,
  95.      *     each ctx has pid to wake up
  96.      */

  97.     if (wakeup == NULL) {
  98.         ngx_mutex_unlock(bl->mutex);
  99.         return;
  100.     }

  101.     if (ctx->md5) {
  102.         for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
  103.             if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) {
  104.                 continue;
  105.             }

  106.             wakeup->handler = ngx_event_busy_lock_posted_handler;
  107.             wakeup->cache_updated = 1;

  108.             ev = wakeup->event;

  109.             ngx_post_event(ev, &ngx_posted_events);
  110.         }

  111.         ngx_mutex_unlock(bl->mutex);

  112.     } else {
  113.         bl->waiting--;

  114.         ngx_mutex_unlock(bl->mutex);

  115.         wakeup->handler = ngx_event_busy_lock_posted_handler;
  116.         wakeup->locked = 1;

  117.         ev = wakeup->event;

  118.         if (ev->timer_set) {
  119.             ngx_del_timer(ev);
  120.         }

  121.         ngx_post_event(ev, &ngx_posted_events);
  122.     }
  123. }


  124. void
  125. ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
  126.     ngx_event_busy_lock_ctx_t *ctx)
  127. {
  128.     ngx_event_busy_lock_ctx_t  *c, *p;

  129.     ngx_mutex_lock(bl->mutex);

  130.     bl->waiting--;

  131.     if (ctx == bl->events) {
  132.         bl->events = ctx->next;

  133.     } else {
  134.         p = bl->events;
  135.         for (c = bl->events->next; c; c = c->next) {
  136.             if (c == ctx) {
  137.                 p->next = ctx->next;
  138.                 break;
  139.             }
  140.             p = c;
  141.         }
  142.     }

  143.     ngx_mutex_unlock(bl->mutex);
  144. }


  145. static ngx_int_t
  146. ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
  147.     ngx_event_busy_lock_ctx_t *ctx)
  148. {
  149.     ngx_int_t    free;
  150.     ngx_uint_t   i, bit, cacheable, mask;

  151.     bit = 0;
  152.     cacheable = 0;
  153.     free = -1;

  154. #if (NGX_SUPPRESS_WARN)
  155.     mask = 0;
  156. #endif

  157.     for (i = 0; i < bl->max_busy; i++) {

  158.         if ((bit & 7) == 0) {
  159.             mask = bl->md5_mask[i / 8];
  160.         }

  161.         if (mask & 1) {
  162.             if (ngx_memcmp(&bl->md5[i * 16], ctx->md5, 16) == 0) {
  163.                 ctx->waiting = 1;
  164.                 ctx->slot = i;
  165.                 return NGX_AGAIN;
  166.             }
  167.             cacheable++;

  168.         } else if (free == -1) {
  169.             free = i;
  170.         }

  171.         if (cacheable == bl->cacheable) {
  172.             if (free == -1 && cacheable < bl->max_busy) {
  173.                 free = i + 1;
  174.             }

  175.             break;
  176.         }

  177.         mask >>= 1;
  178.         bit++;
  179.     }

  180.     if (free == -1) {
  181.         return NGX_BUSY;
  182.     }

  183. #if 0
  184.     if (bl->busy == bl->max_busy) {
  185.         return NGX_BUSY;
  186.     }
  187. #endif

  188.     ngx_memcpy(&bl->md5[free * 16], ctx->md5, 16);
  189.     bl->md5_mask[free / 8] |= 1 << (free & 7);
  190.     ctx->slot = free;

  191.     bl->cacheable++;
  192.     bl->busy++;

  193.     return NGX_OK;
  194. }


  195. static void
  196. ngx_event_busy_lock_handler(ngx_event_t *ev)
  197. {
  198.     ev->handler = ngx_event_busy_lock_posted_handler;

  199.     ngx_post_event(ev, &ngx_posted_events);
  200. }


  201. static void
  202. ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
  203. {
  204.     ngx_event_busy_lock_ctx_t  *ctx;

  205.     ctx = ev->data;
  206.     ctx->handler(ev);
  207. }