Annotation of embedaddon/nginx/src/event/ngx_event_busy_lock.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10: #include <ngx_event.h>
! 11:
! 12:
! 13: static ngx_int_t ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
! 14: ngx_event_busy_lock_ctx_t *ctx);
! 15: static void ngx_event_busy_lock_handler(ngx_event_t *ev);
! 16: static void ngx_event_busy_lock_posted_handler(ngx_event_t *ev);
! 17:
! 18:
! 19: /*
! 20: * NGX_OK: the busy lock is held
! 21: * NGX_AGAIN: the all busy locks are held but we will wait the specified time
! 22: * NGX_BUSY: ctx->timer == 0: there are many the busy locks
! 23: * ctx->timer != 0: there are many the waiting locks
! 24: */
! 25:
! 26: ngx_int_t
! 27: ngx_event_busy_lock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx)
! 28: {
! 29: ngx_int_t rc;
! 30:
! 31: ngx_mutex_lock(bl->mutex);
! 32:
! 33: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
! 34: "event busy lock: b:%d mb:%d",
! 35: bl->busy, bl->max_busy);
! 36:
! 37: if (bl->busy < bl->max_busy) {
! 38: bl->busy++;
! 39:
! 40: rc = NGX_OK;
! 41:
! 42: } else if (ctx->timer && bl->waiting < bl->max_waiting) {
! 43: bl->waiting++;
! 44: ngx_add_timer(ctx->event, ctx->timer);
! 45: ctx->event->handler = ngx_event_busy_lock_handler;
! 46:
! 47: if (bl->events) {
! 48: bl->last->next = ctx;
! 49:
! 50: } else {
! 51: bl->events = ctx;
! 52: }
! 53:
! 54: bl->last = ctx;
! 55:
! 56: rc = NGX_AGAIN;
! 57:
! 58: } else {
! 59: rc = NGX_BUSY;
! 60: }
! 61:
! 62: ngx_mutex_unlock(bl->mutex);
! 63:
! 64: return rc;
! 65: }
! 66:
! 67:
! 68: ngx_int_t
! 69: ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
! 70: ngx_event_busy_lock_ctx_t *ctx)
! 71: {
! 72: ngx_int_t rc;
! 73:
! 74: ngx_mutex_lock(bl->mutex);
! 75:
! 76: rc = ngx_event_busy_lock_look_cacheable(bl, ctx);
! 77:
! 78: ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
! 79: "event busy lock: %d w:%d mw:%d",
! 80: rc, bl->waiting, bl->max_waiting);
! 81:
! 82: /*
! 83: * NGX_OK: no the same request, there is free slot and we locked it
! 84: * NGX_BUSY: no the same request and there is no free slot
! 85: * NGX_AGAIN: the same request is processing
! 86: */
! 87:
! 88: if (rc == NGX_AGAIN) {
! 89:
! 90: if (ctx->timer && bl->waiting < bl->max_waiting) {
! 91: bl->waiting++;
! 92: ngx_add_timer(ctx->event, ctx->timer);
! 93: ctx->event->handler = ngx_event_busy_lock_handler;
! 94:
! 95: if (bl->events == NULL) {
! 96: bl->events = ctx;
! 97: } else {
! 98: bl->last->next = ctx;
! 99: }
! 100: bl->last = ctx;
! 101:
! 102: } else {
! 103: rc = NGX_BUSY;
! 104: }
! 105: }
! 106:
! 107: ngx_mutex_unlock(bl->mutex);
! 108:
! 109: return rc;
! 110: }
! 111:
! 112:
! 113: void
! 114: ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
! 115: ngx_event_busy_lock_ctx_t *ctx)
! 116: {
! 117: ngx_event_t *ev;
! 118: ngx_event_busy_lock_ctx_t *wakeup;
! 119:
! 120: ngx_mutex_lock(bl->mutex);
! 121:
! 122: if (bl->events) {
! 123: wakeup = bl->events;
! 124: bl->events = bl->events->next;
! 125:
! 126: } else {
! 127: wakeup = NULL;
! 128: bl->busy--;
! 129: }
! 130:
! 131: /*
! 132: * MP: all ctx's and their queue must be in shared memory,
! 133: * each ctx has pid to wake up
! 134: */
! 135:
! 136: if (wakeup == NULL) {
! 137: ngx_mutex_unlock(bl->mutex);
! 138: return;
! 139: }
! 140:
! 141: if (ctx->md5) {
! 142: for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
! 143: if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) {
! 144: continue;
! 145: }
! 146:
! 147: wakeup->handler = ngx_event_busy_lock_posted_handler;
! 148: wakeup->cache_updated = 1;
! 149:
! 150: ev = wakeup->event;
! 151:
! 152: ngx_post_event(ev, &ngx_posted_events);
! 153: }
! 154:
! 155: ngx_mutex_unlock(bl->mutex);
! 156:
! 157: } else {
! 158: bl->waiting--;
! 159:
! 160: ngx_mutex_unlock(bl->mutex);
! 161:
! 162: wakeup->handler = ngx_event_busy_lock_posted_handler;
! 163: wakeup->locked = 1;
! 164:
! 165: ev = wakeup->event;
! 166:
! 167: if (ev->timer_set) {
! 168: ngx_del_timer(ev);
! 169: }
! 170:
! 171: ngx_post_event(ev, &ngx_posted_events);
! 172: }
! 173: }
! 174:
! 175:
! 176: void
! 177: ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
! 178: ngx_event_busy_lock_ctx_t *ctx)
! 179: {
! 180: ngx_event_busy_lock_ctx_t *c, *p;
! 181:
! 182: ngx_mutex_lock(bl->mutex);
! 183:
! 184: bl->waiting--;
! 185:
! 186: if (ctx == bl->events) {
! 187: bl->events = ctx->next;
! 188:
! 189: } else {
! 190: p = bl->events;
! 191: for (c = bl->events->next; c; c = c->next) {
! 192: if (c == ctx) {
! 193: p->next = ctx->next;
! 194: break;
! 195: }
! 196: p = c;
! 197: }
! 198: }
! 199:
! 200: ngx_mutex_unlock(bl->mutex);
! 201: }
! 202:
! 203:
! 204: static ngx_int_t
! 205: ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
! 206: ngx_event_busy_lock_ctx_t *ctx)
! 207: {
! 208: ngx_int_t free;
! 209: ngx_uint_t i, bit, cacheable, mask;
! 210:
! 211: bit = 0;
! 212: cacheable = 0;
! 213: free = -1;
! 214:
! 215: #if (NGX_SUPPRESS_WARN)
! 216: mask = 0;
! 217: #endif
! 218:
! 219: for (i = 0; i < bl->max_busy; i++) {
! 220:
! 221: if ((bit & 7) == 0) {
! 222: mask = bl->md5_mask[i / 8];
! 223: }
! 224:
! 225: if (mask & 1) {
! 226: if (ngx_memcmp(&bl->md5[i * 16], ctx->md5, 16) == 0) {
! 227: ctx->waiting = 1;
! 228: ctx->slot = i;
! 229: return NGX_AGAIN;
! 230: }
! 231: cacheable++;
! 232:
! 233: } else if (free == -1) {
! 234: free = i;
! 235: }
! 236:
! 237: if (cacheable == bl->cacheable) {
! 238: if (free == -1 && cacheable < bl->max_busy) {
! 239: free = i + 1;
! 240: }
! 241:
! 242: break;
! 243: }
! 244:
! 245: mask >>= 1;
! 246: bit++;
! 247: }
! 248:
! 249: if (free == -1) {
! 250: return NGX_BUSY;
! 251: }
! 252:
! 253: #if 0
! 254: if (bl->busy == bl->max_busy) {
! 255: return NGX_BUSY;
! 256: }
! 257: #endif
! 258:
! 259: ngx_memcpy(&bl->md5[free * 16], ctx->md5, 16);
! 260: bl->md5_mask[free / 8] |= 1 << (free & 7);
! 261: ctx->slot = free;
! 262:
! 263: bl->cacheable++;
! 264: bl->busy++;
! 265:
! 266: return NGX_OK;
! 267: }
! 268:
! 269:
! 270: static void
! 271: ngx_event_busy_lock_handler(ngx_event_t *ev)
! 272: {
! 273: ev->handler = ngx_event_busy_lock_posted_handler;
! 274:
! 275: ngx_post_event(ev, &ngx_posted_events);
! 276: }
! 277:
! 278:
! 279: static void
! 280: ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
! 281: {
! 282: ngx_event_busy_lock_ctx_t *ctx;
! 283:
! 284: ctx = ev->data;
! 285: ctx->handler(ev);
! 286: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>