Annotation of embedaddon/nginx/src/event/ngx_event_busy_lock.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_event.h>
11:
12:
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);
17:
18:
19: /*
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
24: */
25:
26: ngx_int_t
27: ngx_event_busy_lock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx)
28: {
29: ngx_int_t rc;
30:
31: ngx_mutex_lock(bl->mutex);
32:
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);
36:
37: if (bl->busy < bl->max_busy) {
38: bl->busy++;
39:
40: rc = NGX_OK;
41:
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;
46:
47: if (bl->events) {
48: bl->last->next = ctx;
49:
50: } else {
51: bl->events = ctx;
52: }
53:
54: bl->last = ctx;
55:
56: rc = NGX_AGAIN;
57:
58: } else {
59: rc = NGX_BUSY;
60: }
61:
62: ngx_mutex_unlock(bl->mutex);
63:
64: return rc;
65: }
66:
67:
68: ngx_int_t
69: ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
70: ngx_event_busy_lock_ctx_t *ctx)
71: {
72: ngx_int_t rc;
73:
74: ngx_mutex_lock(bl->mutex);
75:
76: rc = ngx_event_busy_lock_look_cacheable(bl, ctx);
77:
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);
81:
82: /*
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
86: */
87:
88: if (rc == NGX_AGAIN) {
89:
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;
94:
95: if (bl->events == NULL) {
96: bl->events = ctx;
97: } else {
98: bl->last->next = ctx;
99: }
100: bl->last = ctx;
101:
102: } else {
103: rc = NGX_BUSY;
104: }
105: }
106:
107: ngx_mutex_unlock(bl->mutex);
108:
109: return rc;
110: }
111:
112:
113: void
114: ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
115: ngx_event_busy_lock_ctx_t *ctx)
116: {
117: ngx_event_t *ev;
118: ngx_event_busy_lock_ctx_t *wakeup;
119:
120: ngx_mutex_lock(bl->mutex);
121:
122: if (bl->events) {
123: wakeup = bl->events;
124: bl->events = bl->events->next;
125:
126: } else {
127: wakeup = NULL;
128: bl->busy--;
129: }
130:
131: /*
132: * MP: all ctx's and their queue must be in shared memory,
133: * each ctx has pid to wake up
134: */
135:
136: if (wakeup == NULL) {
137: ngx_mutex_unlock(bl->mutex);
138: return;
139: }
140:
141: if (ctx->md5) {
142: for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
143: if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) {
144: continue;
145: }
146:
147: wakeup->handler = ngx_event_busy_lock_posted_handler;
148: wakeup->cache_updated = 1;
149:
150: ev = wakeup->event;
151:
152: ngx_post_event(ev, &ngx_posted_events);
153: }
154:
155: ngx_mutex_unlock(bl->mutex);
156:
157: } else {
158: bl->waiting--;
159:
160: ngx_mutex_unlock(bl->mutex);
161:
162: wakeup->handler = ngx_event_busy_lock_posted_handler;
163: wakeup->locked = 1;
164:
165: ev = wakeup->event;
166:
167: if (ev->timer_set) {
168: ngx_del_timer(ev);
169: }
170:
171: ngx_post_event(ev, &ngx_posted_events);
172: }
173: }
174:
175:
176: void
177: ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
178: ngx_event_busy_lock_ctx_t *ctx)
179: {
180: ngx_event_busy_lock_ctx_t *c, *p;
181:
182: ngx_mutex_lock(bl->mutex);
183:
184: bl->waiting--;
185:
186: if (ctx == bl->events) {
187: bl->events = ctx->next;
188:
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;
195: }
196: p = c;
197: }
198: }
199:
200: ngx_mutex_unlock(bl->mutex);
201: }
202:
203:
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)
207: {
208: ngx_int_t free;
209: ngx_uint_t i, bit, cacheable, mask;
210:
211: bit = 0;
212: cacheable = 0;
213: free = -1;
214:
215: #if (NGX_SUPPRESS_WARN)
216: mask = 0;
217: #endif
218:
219: for (i = 0; i < bl->max_busy; i++) {
220:
221: if ((bit & 7) == 0) {
222: mask = bl->md5_mask[i / 8];
223: }
224:
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;
230: }
231: cacheable++;
232:
233: } else if (free == -1) {
234: free = i;
235: }
236:
237: if (cacheable == bl->cacheable) {
238: if (free == -1 && cacheable < bl->max_busy) {
239: free = i + 1;
240: }
241:
242: break;
243: }
244:
245: mask >>= 1;
246: bit++;
247: }
248:
249: if (free == -1) {
250: return NGX_BUSY;
251: }
252:
253: #if 0
254: if (bl->busy == bl->max_busy) {
255: return NGX_BUSY;
256: }
257: #endif
258:
259: ngx_memcpy(&bl->md5[free * 16], ctx->md5, 16);
260: bl->md5_mask[free / 8] |= 1 << (free & 7);
261: ctx->slot = free;
262:
263: bl->cacheable++;
264: bl->busy++;
265:
266: return NGX_OK;
267: }
268:
269:
270: static void
271: ngx_event_busy_lock_handler(ngx_event_t *ev)
272: {
273: ev->handler = ngx_event_busy_lock_posted_handler;
274:
275: ngx_post_event(ev, &ngx_posted_events);
276: }
277:
278:
279: static void
280: ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
281: {
282: ngx_event_busy_lock_ctx_t *ctx;
283:
284: ctx = ev->data;
285: ctx->handler(ev);
286: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>