Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / event / ngx_event_busy_lock.c
blobfdac0da8fd2fed962dba0acd2551d80e64df81cd
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
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);
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
26 ngx_int_t
27 ngx_event_busy_lock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx)
29 ngx_int_t rc;
31 ngx_mutex_lock(bl->mutex);
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);
37 if (bl->busy < bl->max_busy) {
38 bl->busy++;
40 rc = NGX_OK;
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;
47 if (bl->events) {
48 bl->last->next = ctx;
50 } else {
51 bl->events = ctx;
54 bl->last = ctx;
56 rc = NGX_AGAIN;
58 } else {
59 rc = NGX_BUSY;
62 ngx_mutex_unlock(bl->mutex);
64 return rc;
68 ngx_int_t
69 ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
70 ngx_event_busy_lock_ctx_t *ctx)
72 ngx_int_t rc;
74 ngx_mutex_lock(bl->mutex);
76 rc = ngx_event_busy_lock_look_cacheable(bl, ctx);
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);
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
88 if (rc == NGX_AGAIN) {
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;
95 if (bl->events == NULL) {
96 bl->events = ctx;
97 } else {
98 bl->last->next = ctx;
100 bl->last = ctx;
102 } else {
103 rc = NGX_BUSY;
107 ngx_mutex_unlock(bl->mutex);
109 return rc;
113 void
114 ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
115 ngx_event_busy_lock_ctx_t *ctx)
117 ngx_event_t *ev;
118 ngx_event_busy_lock_ctx_t *wakeup;
120 ngx_mutex_lock(bl->mutex);
122 if (bl->events) {
123 wakeup = bl->events;
124 bl->events = bl->events->next;
126 } else {
127 wakeup = NULL;
128 bl->busy--;
132 * MP: all ctx's and their queue must be in shared memory,
133 * each ctx has pid to wake up
136 if (wakeup == NULL) {
137 ngx_mutex_unlock(bl->mutex);
138 return;
141 if (ctx->md5) {
142 for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
143 if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) {
144 continue;
147 wakeup->handler = ngx_event_busy_lock_posted_handler;
148 wakeup->cache_updated = 1;
150 ev = wakeup->event;
152 ngx_post_event(ev, &ngx_posted_events);
155 ngx_mutex_unlock(bl->mutex);
157 } else {
158 bl->waiting--;
160 ngx_mutex_unlock(bl->mutex);
162 wakeup->handler = ngx_event_busy_lock_posted_handler;
163 wakeup->locked = 1;
165 ev = wakeup->event;
167 if (ev->timer_set) {
168 ngx_del_timer(ev);
171 ngx_post_event(ev, &ngx_posted_events);
176 void
177 ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
178 ngx_event_busy_lock_ctx_t *ctx)
180 ngx_event_busy_lock_ctx_t *c, *p;
182 ngx_mutex_lock(bl->mutex);
184 bl->waiting--;
186 if (ctx == bl->events) {
187 bl->events = ctx->next;
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;
196 p = c;
200 ngx_mutex_unlock(bl->mutex);
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)
208 ngx_int_t free;
209 ngx_uint_t i, bit, cacheable, mask;
211 bit = 0;
212 cacheable = 0;
213 free = -1;
215 #if (NGX_SUPPRESS_WARN)
216 mask = 0;
217 #endif
219 for (i = 0; i < bl->max_busy; i++) {
221 if ((bit & 7) == 0) {
222 mask = bl->md5_mask[i / 8];
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;
231 cacheable++;
233 } else if (free == -1) {
234 free = i;
237 if (cacheable == bl->cacheable) {
238 if (free == -1 && cacheable < bl->max_busy) {
239 free = i + 1;
242 break;
245 mask >>= 1;
246 bit++;
249 if (free == -1) {
250 return NGX_BUSY;
253 #if 0
254 if (bl->busy == bl->max_busy) {
255 return NGX_BUSY;
257 #endif
259 ngx_memcpy(&bl->md5[free * 16], ctx->md5, 16);
260 bl->md5_mask[free / 8] |= 1 << (free & 7);
261 ctx->slot = free;
263 bl->cacheable++;
264 bl->busy++;
266 return NGX_OK;
270 static void
271 ngx_event_busy_lock_handler(ngx_event_t *ev)
273 ev->handler = ngx_event_busy_lock_posted_handler;
275 ngx_post_event(ev, &ngx_posted_events);
279 static void
280 ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
282 ngx_event_busy_lock_ctx_t *ctx;
284 ctx = ev->data;
285 ctx->handler(ev);