Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_event_busy_lock.c
Go to the documentation of this file.
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,
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 
28 {
29  ngx_int_t rc;
30 
31  ngx_mutex_lock(bl->mutex);
32 
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 
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 
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
116 {
117  ngx_event_t *ev;
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 
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 
172  }
173 }
174 
175 
176 void
179 {
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,
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 
276 }
277 
278 
279 static void
280 ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
281 {
283 
284  ctx = ev->data;
285  ctx->handler(ev);
286 }