comparison src/event/ngx_event_busy_lock.c @ 276:a2d1ccc96111

nginx-0.0.2-2004-03-03-00:14:37 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 02 Mar 2004 21:14:37 +0000
parents
children e91499541410
comparison
equal deleted inserted replaced
275:b836469c37c3 276:a2d1ccc96111
1
2 #include <ngx_config.h>
3 #include <ngx_core.h>
4 #include <ngx_event.h>
5
6 /*
7 * TODO: eliminate mutex and use atomic_xchg():
8 * ev->next = ev; ngx_atomic_xchg(ngx_posted_events, ev->next);
9 * in ngx_event_busy_unlock() and ngx_event_busy_lock_handler()
10 */
11
12
13 static int ngx_event_busy_lock_look_cachable(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_BUSY: there are many the busy locks or many the waiting locks
22 * NGX_AGAIN: the all busy locks are held but we will wait the specified time
23 * NGX_ERROR: there was error while the mutex locking
24 */
25
26 ngx_int_t ngx_event_busy_lock(ngx_event_busy_lock_t *bl,
27 ngx_event_busy_lock_ctx_t *ctx)
28 {
29 ngx_int_t rc;
30
31 #if (NGX_THREADS)
32 if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) {
33 return NGX_ERROR;
34 }
35 #endif
36
37 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
38 "event busy lock: b:%d mb:%d",
39 bl->busy, bl->max_busy);
40
41 if (bl->busy < bl->max_busy) {
42 bl->busy++;
43 rc = NGX_OK;
44
45 } else if (ctx->timer && bl->waiting < bl->max_waiting) {
46 bl->waiting++;
47 ngx_add_timer(ctx->event, ctx->timer);
48 ctx->event->event_handler = ngx_event_busy_lock_handler;
49
50 if (bl->events == NULL) {
51 bl->events = ctx;
52 } else {
53 bl->last->next = ctx;
54 }
55 bl->last = ctx;
56
57 rc = NGX_AGAIN;
58
59 } else {
60 rc = NGX_BUSY;
61 }
62
63 #if (NGX_THREADS)
64 ngx_mutex_unlock(bl->mutex);
65 #endif
66
67 return rc;
68 }
69
70
71 ngx_int_t ngx_event_busy_lock_cachable(ngx_event_busy_lock_t *bl,
72 ngx_event_busy_lock_ctx_t *ctx)
73 {
74 ngx_int_t rc;
75
76 #if (NGX_THREADS)
77 if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) {
78 return NGX_ERROR;
79 }
80 #endif
81
82 rc = ngx_event_busy_lock_look_cachable(bl, ctx);
83
84 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
85 "event busy lock: %d w:%d mw:%d",
86 rc, bl->waiting, bl->max_waiting);
87
88 /*
89 * NGX_OK: no the same request, there is free slot and we locked it
90 * NGX_BUSY: no the same request and there is no free slot
91 * NGX_AGAIN: the same request is processing
92 */
93
94 if (rc == NGX_AGAIN) {
95
96 if (ctx->timer && bl->waiting < bl->max_waiting) {
97 bl->waiting++;
98 ngx_add_timer(ctx->event, ctx->timer);
99 ctx->event->event_handler = ngx_event_busy_lock_handler;
100
101 if (bl->events == NULL) {
102 bl->events = ctx;
103 } else {
104 bl->last->next = ctx;
105 }
106 bl->last = ctx;
107
108 } else {
109 rc = NGX_BUSY;
110 }
111 }
112
113 #if (NGX_THREADS)
114 ngx_mutex_unlock(bl->mutex);
115 #endif
116
117 return rc;
118 }
119
120
121 ngx_int_t ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
122 ngx_event_busy_lock_ctx_t *ctx)
123 {
124 ngx_event_t *ev;
125 ngx_event_busy_lock_ctx_t *wakeup;
126
127 #if (NGX_THREADS)
128 if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) {
129 return NGX_ERROR;
130 }
131 #endif
132
133 if (bl->events) {
134 wakeup = bl->events;
135 bl->events = bl->events->next;
136
137 } else {
138 wakeup = NULL;
139 bl->busy--;
140 }
141
142 /*
143 * MP:
144 * nocachable (bl->md5 == NULL): ngx_shared_mutex_unlock(mutex, !wakeup)
145 * cachable (bl->md5): ???
146 */
147
148 if (wakeup == NULL) {
149 #if (NGX_THREADS)
150 ngx_mutex_unlock(bl->mutex);
151 #endif
152 return NGX_OK;
153 }
154
155 if (ctx->md5) {
156 for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
157 if (wakeup->md5 == NULL) {
158 continue;
159 }
160
161 if (ngx_memcmp(ctx->md5, wakeup->md5, 16) != 0) {
162 continue;
163 }
164
165 wakeup->handler = ngx_event_busy_lock_posted_handler;
166 wakeup->cache_updated = 1;
167
168 ev = wakeup->event;
169
170 #if (NGX_THREADS)
171 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
172 return NGX_ERROR;
173 }
174 #endif
175
176 ev->next = (ngx_event_t *) ngx_posted_events;
177 ngx_posted_events = ev;
178
179 #if (NGX_THREADS)
180 ngx_mutex_unlock(ngx_posted_events_mutex);
181 #endif
182 }
183
184 #if (NGX_THREADS)
185 ngx_mutex_unlock(bl->mutex);
186 #endif
187
188 } else {
189 bl->waiting--;
190
191 #if (NGX_THREADS)
192 ngx_mutex_unlock(bl->mutex);
193 #endif
194
195 wakeup->handler = ngx_event_busy_lock_posted_handler;
196 wakeup->locked = 1;
197
198 ev = wakeup->event;
199
200 if (ev->timer_set) {
201 ngx_del_timer(ev);
202 }
203
204 #if (NGX_THREADS)
205 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
206 return NGX_ERROR;
207 }
208 #endif
209
210 ev->next = (ngx_event_t *) ngx_posted_events;
211 ngx_posted_events = ev;
212
213 #if (NGX_THREADS)
214 ngx_mutex_unlock(ngx_posted_events_mutex);
215 #endif
216 }
217
218 return NGX_OK;
219 }
220
221
222 ngx_int_t ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
223 ngx_event_busy_lock_ctx_t *ctx)
224 {
225 ngx_event_busy_lock_ctx_t *c, *p;
226
227 #if (NGX_THREADS)
228 if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) {
229 return NGX_ERROR;
230 }
231 #endif
232
233 bl->waiting--;
234
235 if (ctx == bl->events) {
236 bl->events = ctx->next;
237
238 } else {
239 p = bl->events;
240 for (c = bl->events->next; c; c = c->next) {
241 if (c == ctx) {
242 p->next = ctx->next;
243 break;
244 }
245 p = c;
246 }
247 }
248
249 #if (NGX_THREADS)
250 ngx_mutex_unlock(bl->mutex);
251 #endif
252
253 return NGX_OK;
254 }
255
256
257 static int ngx_event_busy_lock_look_cachable(ngx_event_busy_lock_t *bl,
258 ngx_event_busy_lock_ctx_t *ctx)
259 {
260 ngx_int_t free;
261 ngx_uint_t i, bit, cachable, mask;
262
263 bit = 0;
264 cachable = 0;
265 free = -1;
266
267 #if (NGX_SUPPRESS_WARN)
268 mask = 0;
269 #endif
270
271 for (i = 0; i < bl->max_busy; i++) {
272
273 if ((bit & 7) == 0) {
274 mask = bl->md5_mask[i / 8];
275 }
276
277 if (mask & 1) {
278 if (ngx_memcmp(&bl->md5[i * 16], ctx->md5, 16) == 0) {
279 return NGX_AGAIN;
280 }
281 cachable++;
282
283 } else if (free == -1) {
284 free = i;
285 }
286
287 if (cachable == bl->cachable) {
288 if (free == -1 && cachable < bl->max_busy) {
289 free = i + 1;
290 }
291
292 break;
293 }
294
295 mask >>= 1;
296 bit++;
297 }
298
299 if (free == -1) {
300 return NGX_BUSY;
301 }
302
303 #if 0
304 if (bl->busy == bl->max_busy) {
305 return NGX_BUSY;
306 }
307 #endif
308
309 ngx_memcpy(&bl->md5[free * 16], ctx->md5, 16);
310 bl->md5_mask[free / 8] |= 1 << (free & 7);
311 ctx->slot = free;
312
313 bl->cachable++;
314 bl->busy++;
315
316 return NGX_OK;
317 }
318
319
320 static void ngx_event_busy_lock_handler(ngx_event_t *ev)
321 {
322 ev->event_handler = ngx_event_busy_lock_posted_handler;
323
324 #if (NGX_THREADS)
325 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
326 return;
327 }
328 #endif
329
330 ev->next = (ngx_event_t *) ngx_posted_events;
331 ngx_posted_events = ev;
332
333 #if (NGX_THREADS)
334 ngx_mutex_unlock(ngx_posted_events_mutex);
335 #endif
336 }
337
338
339 static void ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
340 {
341 ngx_event_busy_lock_ctx_t *ctx;
342
343 ctx = ev->data;
344 ctx->handler(ev);
345 }