~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/event/ngx_event_busy_lock.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.