comparison src/event/ngx_event_busy_lock.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children b55cbf18157e
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
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 int ngx_event_busy_lock_look_cachable(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 * NGX_ERROR: an error occured 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_mutex_lock(bl->mutex) == NGX_ERROR) {
32 return NGX_ERROR;
33 }
34
35 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
36 "event busy lock: b:%d mb:%d",
37 bl->busy, bl->max_busy);
38
39 if (bl->busy < bl->max_busy) {
40 bl->busy++;
41 rc = NGX_OK;
42
43 } else if (ctx->timer && bl->waiting < bl->max_waiting) {
44 bl->waiting++;
45 ngx_add_timer(ctx->event, ctx->timer);
46 ctx->event->event_handler = ngx_event_busy_lock_handler;
47
48 if (bl->events) {
49 bl->last->next = ctx;
50
51 } else {
52 bl->events = ctx;
53 }
54
55 bl->last = ctx;
56
57 rc = NGX_AGAIN;
58
59 } else {
60 rc = NGX_BUSY;
61 }
62
63 ngx_mutex_unlock(bl->mutex);
64
65 return rc;
66 }
67
68
69 ngx_int_t ngx_event_busy_lock_cachable(ngx_event_busy_lock_t *bl,
70 ngx_event_busy_lock_ctx_t *ctx)
71 {
72 ngx_int_t rc;
73
74 if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) {
75 return NGX_ERROR;
76 }
77
78 rc = ngx_event_busy_lock_look_cachable(bl, ctx);
79
80 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
81 "event busy lock: %d w:%d mw:%d",
82 rc, bl->waiting, bl->max_waiting);
83
84 /*
85 * NGX_OK: no the same request, there is free slot and we locked it
86 * NGX_BUSY: no the same request and there is no free slot
87 * NGX_AGAIN: the same request is processing
88 */
89
90 if (rc == NGX_AGAIN) {
91
92 if (ctx->timer && bl->waiting < bl->max_waiting) {
93 bl->waiting++;
94 ngx_add_timer(ctx->event, ctx->timer);
95 ctx->event->event_handler = ngx_event_busy_lock_handler;
96
97 if (bl->events == NULL) {
98 bl->events = ctx;
99 } else {
100 bl->last->next = ctx;
101 }
102 bl->last = ctx;
103
104 } else {
105 rc = NGX_BUSY;
106 }
107 }
108
109 ngx_mutex_unlock(bl->mutex);
110
111 return rc;
112 }
113
114
115 ngx_int_t ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
116 ngx_event_busy_lock_ctx_t *ctx)
117 {
118 ngx_event_t *ev;
119 ngx_event_busy_lock_ctx_t *wakeup;
120
121 if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) {
122 return NGX_ERROR;
123 }
124
125 if (bl->events) {
126 wakeup = bl->events;
127 bl->events = bl->events->next;
128
129 } else {
130 wakeup = NULL;
131 bl->busy--;
132 }
133
134 /*
135 * MP: all ctx's and their queue must be in shared memory,
136 * each ctx has pid to wake up
137 */
138
139 if (wakeup == NULL) {
140 ngx_mutex_unlock(bl->mutex);
141 return NGX_OK;
142 }
143
144 if (ctx->md5) {
145 for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
146 if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) {
147 continue;
148 }
149
150 wakeup->handler = ngx_event_busy_lock_posted_handler;
151 wakeup->cache_updated = 1;
152
153 ev = wakeup->event;
154
155 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
156 return NGX_ERROR;
157 }
158
159 ngx_post_event(ev);
160
161 ngx_mutex_unlock(ngx_posted_events_mutex);
162 }
163
164 ngx_mutex_unlock(bl->mutex);
165
166 } else {
167 bl->waiting--;
168
169 ngx_mutex_unlock(bl->mutex);
170
171 wakeup->handler = ngx_event_busy_lock_posted_handler;
172 wakeup->locked = 1;
173
174 ev = wakeup->event;
175
176 if (ev->timer_set) {
177 ngx_del_timer(ev);
178 }
179
180 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
181 return NGX_ERROR;
182 }
183
184 ngx_post_event(ev);
185
186 ngx_mutex_unlock(ngx_posted_events_mutex);
187 }
188
189 return NGX_OK;
190 }
191
192
193 ngx_int_t ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
194 ngx_event_busy_lock_ctx_t *ctx)
195 {
196 ngx_event_busy_lock_ctx_t *c, *p;
197
198 if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) {
199 return NGX_ERROR;
200 }
201
202 bl->waiting--;
203
204 if (ctx == bl->events) {
205 bl->events = ctx->next;
206
207 } else {
208 p = bl->events;
209 for (c = bl->events->next; c; c = c->next) {
210 if (c == ctx) {
211 p->next = ctx->next;
212 break;
213 }
214 p = c;
215 }
216 }
217
218 ngx_mutex_unlock(bl->mutex);
219
220 return NGX_OK;
221 }
222
223
224 static int ngx_event_busy_lock_look_cachable(ngx_event_busy_lock_t *bl,
225 ngx_event_busy_lock_ctx_t *ctx)
226 {
227 ngx_int_t free;
228 ngx_uint_t i, bit, cachable, mask;
229
230 bit = 0;
231 cachable = 0;
232 free = -1;
233
234 #if (NGX_SUPPRESS_WARN)
235 mask = 0;
236 #endif
237
238 for (i = 0; i < bl->max_busy; i++) {
239
240 if ((bit & 7) == 0) {
241 mask = bl->md5_mask[i / 8];
242 }
243
244 if (mask & 1) {
245 if (ngx_memcmp(&bl->md5[i * 16], ctx->md5, 16) == 0) {
246 ctx->waiting = 1;
247 ctx->slot = i;
248 return NGX_AGAIN;
249 }
250 cachable++;
251
252 } else if (free == -1) {
253 free = i;
254 }
255
256 if (cachable == bl->cachable) {
257 if (free == -1 && cachable < bl->max_busy) {
258 free = i + 1;
259 }
260
261 break;
262 }
263
264 mask >>= 1;
265 bit++;
266 }
267
268 if (free == -1) {
269 return NGX_BUSY;
270 }
271
272 #if 0
273 if (bl->busy == bl->max_busy) {
274 return NGX_BUSY;
275 }
276 #endif
277
278 ngx_memcpy(&bl->md5[free * 16], ctx->md5, 16);
279 bl->md5_mask[free / 8] |= 1 << (free & 7);
280 ctx->slot = free;
281
282 bl->cachable++;
283 bl->busy++;
284
285 return NGX_OK;
286 }
287
288
289 static void ngx_event_busy_lock_handler(ngx_event_t *ev)
290 {
291 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
292 return;
293 }
294
295 ngx_post_event(ev);
296
297 ngx_mutex_unlock(ngx_posted_events_mutex);
298
299 ev->event_handler = ngx_event_busy_lock_posted_handler;
300 }
301
302
303 static void ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
304 {
305 ngx_event_busy_lock_ctx_t *ctx;
306
307 ctx = ev->data;
308 ctx->handler(ev);
309 }