blob: 2d0bad571754b4909188fc22ae7e3e82b08dc749 [file] [log] [blame]
Igor Sysoevea17edc2004-03-02 21:14:37 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoevea17edc2004-03-02 21:14:37 +00007#include <ngx_config.h>
8#include <ngx_core.h>
9#include <ngx_event.h>
10
Igor Sysoevea17edc2004-03-02 21:14:37 +000011
12static int ngx_event_busy_lock_look_cachable(ngx_event_busy_lock_t *bl,
Igor Sysoevc2068d02005-10-19 12:33:58 +000013 ngx_event_busy_lock_ctx_t *ctx);
Igor Sysoevea17edc2004-03-02 21:14:37 +000014static void ngx_event_busy_lock_handler(ngx_event_t *ev);
15static void ngx_event_busy_lock_posted_handler(ngx_event_t *ev);
16
17
18/*
19 * NGX_OK: the busy lock is held
Igor Sysoevea17edc2004-03-02 21:14:37 +000020 * NGX_AGAIN: the all busy locks are held but we will wait the specified time
Igor Sysoev11dbe972004-03-29 17:43:58 +000021 * NGX_BUSY: ctx->timer == 0: there are many the busy locks
22 * ctx->timer != 0: there are many the waiting locks
Igor Sysoevea17edc2004-03-02 21:14:37 +000023 */
24
Igor Sysoevc2068d02005-10-19 12:33:58 +000025ngx_int_t
26ngx_event_busy_lock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx)
Igor Sysoevea17edc2004-03-02 21:14:37 +000027{
28 ngx_int_t rc;
29
Igor Sysoevc2068d02005-10-19 12:33:58 +000030 ngx_mutex_lock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +000031
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++;
Igor Sysoev9e580192006-02-01 18:22:15 +000038
Igor Sysoevea17edc2004-03-02 21:14:37 +000039 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);
Igor Sysoev899b44e2005-05-12 14:58:06 +000044 ctx->event->handler = ngx_event_busy_lock_handler;
Igor Sysoevea17edc2004-03-02 21:14:37 +000045
Igor Sysoev0ed19cc2004-06-10 18:36:57 +000046 if (bl->events) {
Igor Sysoevea17edc2004-03-02 21:14:37 +000047 bl->last->next = ctx;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +000048
49 } else {
50 bl->events = ctx;
Igor Sysoevea17edc2004-03-02 21:14:37 +000051 }
Igor Sysoev0ed19cc2004-06-10 18:36:57 +000052
Igor Sysoevea17edc2004-03-02 21:14:37 +000053 bl->last = ctx;
54
55 rc = NGX_AGAIN;
56
57 } else {
58 rc = NGX_BUSY;
59 }
60
Igor Sysoevea17edc2004-03-02 21:14:37 +000061 ngx_mutex_unlock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +000062
63 return rc;
64}
65
66
Igor Sysoevc2068d02005-10-19 12:33:58 +000067ngx_int_t
68ngx_event_busy_lock_cachable(ngx_event_busy_lock_t *bl,
69 ngx_event_busy_lock_ctx_t *ctx)
Igor Sysoevea17edc2004-03-02 21:14:37 +000070{
71 ngx_int_t rc;
72
Igor Sysoevc2068d02005-10-19 12:33:58 +000073 ngx_mutex_lock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +000074
75 rc = ngx_event_busy_lock_look_cachable(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);
Igor Sysoev899b44e2005-05-12 14:58:06 +000092 ctx->event->handler = ngx_event_busy_lock_handler;
Igor Sysoevea17edc2004-03-02 21:14:37 +000093
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
Igor Sysoevea17edc2004-03-02 21:14:37 +0000106 ngx_mutex_unlock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000107
108 return rc;
109}
110
111
Igor Sysoevc2068d02005-10-19 12:33:58 +0000112void
113ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
114 ngx_event_busy_lock_ctx_t *ctx)
Igor Sysoevea17edc2004-03-02 21:14:37 +0000115{
116 ngx_event_t *ev;
117 ngx_event_busy_lock_ctx_t *wakeup;
118
Igor Sysoevc2068d02005-10-19 12:33:58 +0000119 ngx_mutex_lock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000120
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 /*
Igor Sysoev5edf3872004-03-03 16:14:15 +0000131 * MP: all ctx's and their queue must be in shared memory,
132 * each ctx has pid to wake up
Igor Sysoevea17edc2004-03-02 21:14:37 +0000133 */
134
135 if (wakeup == NULL) {
Igor Sysoevea17edc2004-03-02 21:14:37 +0000136 ngx_mutex_unlock(bl->mutex);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000137 return;
Igor Sysoevea17edc2004-03-02 21:14:37 +0000138 }
139
140 if (ctx->md5) {
141 for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
Igor Sysoev5edf3872004-03-03 16:14:15 +0000142 if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) {
Igor Sysoevea17edc2004-03-02 21:14:37 +0000143 continue;
144 }
145
Igor Sysoevea17edc2004-03-02 21:14:37 +0000146 wakeup->handler = ngx_event_busy_lock_posted_handler;
147 wakeup->cache_updated = 1;
148
149 ev = wakeup->event;
150
Igor Sysoevc2068d02005-10-19 12:33:58 +0000151 ngx_post_event(ev, &ngx_posted_events);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000152 }
153
Igor Sysoevea17edc2004-03-02 21:14:37 +0000154 ngx_mutex_unlock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000155
156 } else {
157 bl->waiting--;
158
Igor Sysoevea17edc2004-03-02 21:14:37 +0000159 ngx_mutex_unlock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000160
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
Igor Sysoevc2068d02005-10-19 12:33:58 +0000170 ngx_post_event(ev, &ngx_posted_events);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000171 }
Igor Sysoevea17edc2004-03-02 21:14:37 +0000172}
173
174
Igor Sysoevc2068d02005-10-19 12:33:58 +0000175void
176ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
177 ngx_event_busy_lock_ctx_t *ctx)
Igor Sysoevea17edc2004-03-02 21:14:37 +0000178{
179 ngx_event_busy_lock_ctx_t *c, *p;
180
Igor Sysoevc2068d02005-10-19 12:33:58 +0000181 ngx_mutex_lock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000182
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
Igor Sysoevea17edc2004-03-02 21:14:37 +0000199 ngx_mutex_unlock(bl->mutex);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000200}
201
202
Igor Sysoevc2068d02005-10-19 12:33:58 +0000203static ngx_int_t
204ngx_event_busy_lock_look_cachable(ngx_event_busy_lock_t *bl,
205 ngx_event_busy_lock_ctx_t *ctx)
Igor Sysoevea17edc2004-03-02 21:14:37 +0000206{
207 ngx_int_t free;
208 ngx_uint_t i, bit, cachable, mask;
209
210 bit = 0;
211 cachable = 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) {
Igor Sysoev5edf3872004-03-03 16:14:15 +0000226 ctx->waiting = 1;
227 ctx->slot = i;
Igor Sysoevea17edc2004-03-02 21:14:37 +0000228 return NGX_AGAIN;
229 }
230 cachable++;
231
232 } else if (free == -1) {
233 free = i;
234 }
235
236 if (cachable == bl->cachable) {
237 if (free == -1 && cachable < 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->cachable++;
263 bl->busy++;
264
265 return NGX_OK;
266}
267
268
Igor Sysoevc2068d02005-10-19 12:33:58 +0000269static void
270ngx_event_busy_lock_handler(ngx_event_t *ev)
Igor Sysoevea17edc2004-03-02 21:14:37 +0000271{
Igor Sysoev899b44e2005-05-12 14:58:06 +0000272 ev->handler = ngx_event_busy_lock_posted_handler;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000273
274 ngx_post_event(ev, &ngx_posted_events);
Igor Sysoevea17edc2004-03-02 21:14:37 +0000275}
276
277
Igor Sysoevc2068d02005-10-19 12:33:58 +0000278static void
279ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
Igor Sysoevea17edc2004-03-02 21:14:37 +0000280{
281 ngx_event_busy_lock_ctx_t *ctx;
282
283 ctx = ev->data;
284 ctx->handler(ev);
285}