Mercurial > hg > nginx-quic
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 } |