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>