Annotation of embedaddon/nginx/src/event/ngx_event_busy_lock.c, revision 1.1.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>