Mercurial > hg > nginx-vendor-current
comparison src/event/ngx_event.h @ 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 | cc9f381affaa |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0b350454894 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #ifndef _NGX_EVENT_H_INCLUDED_ | |
8 #define _NGX_EVENT_H_INCLUDED_ | |
9 | |
10 | |
11 #include <ngx_config.h> | |
12 #include <ngx_core.h> | |
13 | |
14 | |
15 #define NGX_INVALID_INDEX 0xd0d0d0d0 | |
16 | |
17 | |
18 #if (HAVE_IOCP) | |
19 | |
20 typedef struct { | |
21 WSAOVERLAPPED ovlp; | |
22 ngx_event_t *event; | |
23 int error; | |
24 } ngx_event_ovlp_t; | |
25 | |
26 #endif | |
27 | |
28 | |
29 typedef struct { | |
30 ngx_uint_t lock; | |
31 | |
32 ngx_event_t *events; | |
33 ngx_event_t *last; | |
34 } ngx_event_mutex_t; | |
35 | |
36 | |
37 struct ngx_event_s { | |
38 void *data; | |
39 | |
40 unsigned write:1; | |
41 | |
42 unsigned accept:1; | |
43 | |
44 unsigned oneshot:1; | |
45 | |
46 /* used to detect the stale events in kqueue, rt signals and epoll */ | |
47 unsigned instance:1; | |
48 | |
49 /* | |
50 * the event was passed or would be passed to a kernel; | |
51 * in aio mode - operation was posted. | |
52 */ | |
53 unsigned active:1; | |
54 | |
55 unsigned disabled:1; | |
56 | |
57 /* the ready event; in aio mode 0 means that no operation can be posted */ | |
58 unsigned ready:1; | |
59 | |
60 /* aio operation is complete */ | |
61 unsigned complete:1; | |
62 | |
63 unsigned eof:1; | |
64 unsigned error:1; | |
65 | |
66 unsigned timedout:1; | |
67 unsigned timer_set:1; | |
68 | |
69 unsigned delayed:1; | |
70 | |
71 unsigned read_discarded:1; | |
72 | |
73 unsigned unexpected_eof:1; | |
74 | |
75 unsigned deferred_accept:1; | |
76 | |
77 /* the pending eof reported by kqueue or in aio chain operation */ | |
78 unsigned pending_eof:1; | |
79 | |
80 #if !(NGX_THREADS) | |
81 unsigned posted_ready:1; | |
82 #endif | |
83 | |
84 #if (WIN32) | |
85 /* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was succesfull */ | |
86 unsigned accept_context_updated:1; | |
87 #endif | |
88 | |
89 #if (HAVE_KQUEUE) | |
90 unsigned kq_vnode:1; | |
91 | |
92 /* the pending errno reported by kqueue */ | |
93 int kq_errno; | |
94 #endif | |
95 | |
96 /* | |
97 * kqueue only: | |
98 * accept: number of sockets that wait to be accepted | |
99 * read: bytes to read when event is ready | |
100 * or lowat when event is set with NGX_LOWAT_EVENT flag | |
101 * write: available space in buffer when event is ready | |
102 * or lowat when event is set with NGX_LOWAT_EVENT flag | |
103 * | |
104 * iocp: TODO | |
105 * | |
106 * otherwise: | |
107 * accept: 1 if accept many, 0 otherwise | |
108 */ | |
109 | |
110 #if (HAVE_KQUEUE) || (HAVE_IOCP) | |
111 int available; | |
112 #else | |
113 unsigned available:1; | |
114 #endif | |
115 | |
116 /* TODO rename to handler */ | |
117 ngx_event_handler_pt event_handler; | |
118 | |
119 | |
120 #if (HAVE_AIO) | |
121 | |
122 #if (HAVE_IOCP) | |
123 ngx_event_ovlp_t ovlp; | |
124 #else | |
125 struct aiocb aiocb; | |
126 #endif | |
127 | |
128 #endif | |
129 | |
130 u_int index; | |
131 | |
132 ngx_log_t *log; | |
133 | |
134 /* TODO: threads: padding to cache line */ | |
135 | |
136 /* | |
137 * STUB: The inline of "ngx_rbtree_t rbtree;" | |
138 */ | |
139 | |
140 ngx_int_t rbtree_key; | |
141 void *rbtree_left; | |
142 void *rbtree_right; | |
143 void *rbtree_parent; | |
144 char rbtree_color; | |
145 | |
146 | |
147 unsigned closed:1; | |
148 | |
149 #if (NGX_THREADS) | |
150 | |
151 unsigned locked:1; | |
152 | |
153 unsigned posted_ready:1; | |
154 unsigned posted_timedout:1; | |
155 unsigned posted_eof:1; | |
156 | |
157 #if (HAVE_KQUEUE) | |
158 /* the pending errno reported by kqueue */ | |
159 int posted_errno; | |
160 #endif | |
161 | |
162 #if (HAVE_KQUEUE) || (HAVE_IOCP) | |
163 int posted_available; | |
164 #else | |
165 unsigned posted_available:1; | |
166 #endif | |
167 | |
168 ngx_atomic_t *lock; | |
169 ngx_atomic_t *own_lock; | |
170 | |
171 #endif | |
172 | |
173 /* the links of the posted queue */ | |
174 ngx_event_t *next; | |
175 ngx_event_t **prev; | |
176 | |
177 | |
178 #if 0 | |
179 | |
180 /* the threads support */ | |
181 | |
182 /* | |
183 * the event thread context, we store it here | |
184 * if $(CC) does not understand __thread declaration | |
185 * and pthread_getspecific() is too costly | |
186 */ | |
187 | |
188 void *thr_ctx; | |
189 | |
190 #if (NGX_EVENT_T_PADDING) | |
191 | |
192 /* event should not cross cache line in SMP */ | |
193 | |
194 int padding[NGX_EVENT_T_PADDING]; | |
195 #endif | |
196 #endif | |
197 }; | |
198 | |
199 | |
200 typedef struct { | |
201 ngx_int_t (*add)(ngx_event_t *ev, int event, u_int flags); | |
202 ngx_int_t (*del)(ngx_event_t *ev, int event, u_int flags); | |
203 | |
204 ngx_int_t (*enable)(ngx_event_t *ev, int event, u_int flags); | |
205 ngx_int_t (*disable)(ngx_event_t *ev, int event, u_int flags); | |
206 | |
207 ngx_int_t (*add_conn)(ngx_connection_t *c); | |
208 ngx_int_t (*del_conn)(ngx_connection_t *c, u_int flags); | |
209 | |
210 ngx_int_t (*process_changes)(ngx_cycle_t *cycle, ngx_uint_t try); | |
211 ngx_int_t (*process_events)(ngx_cycle_t *cycle); | |
212 | |
213 ngx_int_t (*init)(ngx_cycle_t *cycle); | |
214 void (*done)(ngx_cycle_t *cycle); | |
215 } ngx_event_actions_t; | |
216 | |
217 | |
218 extern ngx_event_actions_t ngx_event_actions; | |
219 | |
220 | |
221 /* | |
222 * The event filter requires to read/write the whole data - | |
223 * select, poll, /dev/poll, kqueue, epoll. | |
224 */ | |
225 #define NGX_USE_LEVEL_EVENT 0x00000001 | |
226 | |
227 /* | |
228 * The event filter is deleted after a notification without an additional | |
229 * syscall - select, poll, kqueue, epoll, Solaris 10's event ports. | |
230 */ | |
231 #define NGX_USE_ONESHOT_EVENT 0x00000002 | |
232 | |
233 /* | |
234 * The event filter notifies only the changes and an initial level - | |
235 * kqueue, epoll. | |
236 */ | |
237 #define NGX_USE_CLEAR_EVENT 0x00000004 | |
238 | |
239 /* | |
240 * The event filter has kqueue features - the eof flag, errno, | |
241 * available data, etc. | |
242 */ | |
243 #define NGX_HAVE_KQUEUE_EVENT 0x00000008 | |
244 | |
245 /* | |
246 * The event filter supports low water mark - kqueue's NOTE_LOWAT. | |
247 * kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag. | |
248 */ | |
249 #define NGX_HAVE_LOWAT_EVENT 0x00000010 | |
250 | |
251 /* | |
252 * The event filter requires to do i/o operation until EAGAIN - | |
253 * epoll, rt signals. | |
254 */ | |
255 #define NGX_HAVE_GREEDY_EVENT 0x00000020 | |
256 | |
257 /* | |
258 * The event filter is epoll, | |
259 */ | |
260 #define NGX_USE_EPOLL_EVENT 0x00000040 | |
261 | |
262 /* | |
263 * No need to add or delete the event filters - rt signals. | |
264 */ | |
265 #define NGX_USE_RTSIG_EVENT 0x00000080 | |
266 | |
267 /* | |
268 * No need to add or delete the event filters - overlapped, aio_read, | |
269 * aioread, io_submit. | |
270 */ | |
271 #define NGX_USE_AIO_EVENT 0x00000100 | |
272 | |
273 /* | |
274 * Need to add socket or handle only once - i/o completion port. | |
275 * It also requires HAVE_AIO and NGX_USE_AIO_EVENT to be set. | |
276 */ | |
277 #define NGX_USE_IOCP_EVENT 0x00000200 | |
278 | |
279 | |
280 | |
281 /* | |
282 * The event filter is deleted before the closing file. | |
283 * Has no meaning for select, poll, epoll. | |
284 * | |
285 * kqueue: kqueue deletes event filters for file that closed | |
286 * so we need only to delete filters in user-level batch array | |
287 * /dev/poll: we need to flush POLLREMOVE event before closing file | |
288 */ | |
289 | |
290 #define NGX_CLOSE_EVENT 1 | |
291 #define NGX_DISABLE_EVENT 2 | |
292 | |
293 | |
294 /* these flags have a meaning only for kqueue */ | |
295 #define NGX_LOWAT_EVENT 0 | |
296 #define NGX_VNODE_EVENT 0 | |
297 | |
298 | |
299 #if (HAVE_KQUEUE) | |
300 | |
301 #define NGX_READ_EVENT EVFILT_READ | |
302 #define NGX_WRITE_EVENT EVFILT_WRITE | |
303 | |
304 #undef NGX_VNODE_EVENT | |
305 #define NGX_VNODE_EVENT EVFILT_VNODE | |
306 | |
307 /* | |
308 * NGX_CLOSE_EVENT and NGX_LOWAT_EVENT are the module flags and they would | |
309 * not go into a kernel so we need to choose the value that would not interfere | |
310 * with any existent and future kqueue flags. kqueue has such values - | |
311 * EV_FLAG1, EV_EOF and EV_ERROR. They are reserved and cleared on a kernel | |
312 * entrance. | |
313 */ | |
314 #undef NGX_CLOSE_EVENT | |
315 #define NGX_CLOSE_EVENT EV_EOF | |
316 | |
317 #undef NGX_LOWAT_EVENT | |
318 #define NGX_LOWAT_EVENT EV_FLAG1 | |
319 | |
320 #define NGX_LEVEL_EVENT 0 | |
321 #define NGX_ONESHOT_EVENT EV_ONESHOT | |
322 #define NGX_CLEAR_EVENT EV_CLEAR | |
323 | |
324 #undef NGX_DISABLE_EVENT | |
325 #define NGX_DISABLE_EVENT EV_DISABLE | |
326 | |
327 | |
328 #elif (HAVE_DEVPOLL) | |
329 | |
330 #define NGX_READ_EVENT POLLIN | |
331 #define NGX_WRITE_EVENT POLLOUT | |
332 | |
333 #define NGX_LEVEL_EVENT 0 | |
334 #define NGX_ONESHOT_EVENT 1 | |
335 | |
336 | |
337 #elif (HAVE_EPOLL) | |
338 | |
339 #define NGX_READ_EVENT EPOLLIN | |
340 #define NGX_WRITE_EVENT EPOLLOUT | |
341 | |
342 #define NGX_LEVEL_EVENT 0 | |
343 #define NGX_CLEAR_EVENT EPOLLET | |
344 #define NGX_ONESHOT_EVENT 0x70000000 | |
345 #if 0 | |
346 #define NGX_ONESHOT_EVENT EPOLLONESHOT | |
347 #endif | |
348 | |
349 | |
350 #elif (HAVE_POLL) | |
351 | |
352 #define NGX_READ_EVENT POLLIN | |
353 #define NGX_WRITE_EVENT POLLOUT | |
354 | |
355 #define NGX_LEVEL_EVENT 0 | |
356 #define NGX_ONESHOT_EVENT 1 | |
357 | |
358 | |
359 #else /* select */ | |
360 | |
361 #define NGX_READ_EVENT 0 | |
362 #define NGX_WRITE_EVENT 1 | |
363 | |
364 #define NGX_LEVEL_EVENT 0 | |
365 #define NGX_ONESHOT_EVENT 1 | |
366 | |
367 #endif /* HAVE_KQUEUE */ | |
368 | |
369 | |
370 #if (HAVE_IOCP) | |
371 #define NGX_IOCP_ACCEPT 0 | |
372 #define NGX_IOCP_IO 1 | |
373 #define NGX_IOCP_CONNECT 2 | |
374 #endif | |
375 | |
376 | |
377 #ifndef NGX_CLEAR_EVENT | |
378 #define NGX_CLEAR_EVENT 0 /* dummy declaration */ | |
379 #endif | |
380 | |
381 | |
382 #define ngx_process_changes ngx_event_actions.process_changes | |
383 #define ngx_process_events ngx_event_actions.process_events | |
384 #define ngx_done_events ngx_event_actions.done | |
385 | |
386 #define ngx_add_event ngx_event_actions.add | |
387 #define ngx_del_event ngx_event_actions.del | |
388 #define ngx_add_conn ngx_event_actions.add_conn | |
389 #define ngx_del_conn ngx_event_actions.del_conn | |
390 | |
391 #define ngx_add_timer ngx_event_add_timer | |
392 #define ngx_del_timer ngx_event_del_timer | |
393 | |
394 | |
395 #define ngx_recv ngx_io.recv | |
396 #define ngx_recv_chain ngx_io.recv_chain | |
397 #define ngx_send ngx_io.send | |
398 #define ngx_send_chain ngx_io.send_chain | |
399 | |
400 | |
401 | |
402 #define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */ | |
403 #define NGX_EVENT_CONF 0x02000000 | |
404 | |
405 | |
406 typedef struct { | |
407 ngx_uint_t connections; | |
408 ngx_uint_t use; | |
409 | |
410 ngx_flag_t multi_accept; | |
411 ngx_flag_t accept_mutex; | |
412 | |
413 ngx_msec_t accept_mutex_delay; | |
414 | |
415 u_char *name; | |
416 | |
417 #if (NGX_DEBUG) | |
418 ngx_array_t debug_connection; | |
419 #endif | |
420 } ngx_event_conf_t; | |
421 | |
422 | |
423 typedef struct { | |
424 ngx_str_t *name; | |
425 | |
426 void *(*create_conf)(ngx_cycle_t *cycle); | |
427 char *(*init_conf)(ngx_cycle_t *cycle, void *conf); | |
428 | |
429 ngx_event_actions_t actions; | |
430 } ngx_event_module_t; | |
431 | |
432 | |
433 extern ngx_atomic_t *ngx_connection_counter; | |
434 | |
435 extern ngx_atomic_t *ngx_accept_mutex_ptr; | |
436 extern ngx_atomic_t *ngx_accept_mutex; | |
437 extern ngx_uint_t ngx_accept_mutex_held; | |
438 extern ngx_msec_t ngx_accept_mutex_delay; | |
439 extern ngx_int_t ngx_accept_disabled; | |
440 | |
441 | |
442 #if (NGX_STAT_STUB) | |
443 | |
444 extern ngx_atomic_t *ngx_stat_accepted; | |
445 extern ngx_atomic_t *ngx_stat_requests; | |
446 extern ngx_atomic_t *ngx_stat_active; | |
447 extern ngx_atomic_t *ngx_stat_reading; | |
448 extern ngx_atomic_t *ngx_stat_writing; | |
449 | |
450 #endif | |
451 | |
452 | |
453 | |
454 #define ngx_accept_mutex_unlock() \ | |
455 if (ngx_accept_mutex_held) { \ | |
456 *ngx_accept_mutex = 0; \ | |
457 } | |
458 | |
459 | |
460 extern ngx_uint_t ngx_event_flags; | |
461 extern ngx_module_t ngx_events_module; | |
462 extern ngx_module_t ngx_event_core_module; | |
463 | |
464 | |
465 #define ngx_event_get_conf(conf_ctx, module) \ | |
466 (*(ngx_get_conf(conf_ctx, ngx_events_module))) [module.ctx_index]; | |
467 | |
468 | |
469 | |
470 void ngx_event_accept(ngx_event_t *ev); | |
471 ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle); | |
472 ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle); | |
473 ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); | |
474 | |
475 | |
476 #if (WIN32) | |
477 void ngx_event_acceptex(ngx_event_t *ev); | |
478 int ngx_event_post_acceptex(ngx_listening_t *ls, int n); | |
479 #endif | |
480 | |
481 | |
482 /* used in ngx_log_debugX() */ | |
483 #define ngx_event_ident(p) ((ngx_connection_t *) (p))->fd | |
484 | |
485 | |
486 #include <ngx_event_timer.h> | |
487 #include <ngx_event_posted.h> | |
488 #include <ngx_event_busy_lock.h> | |
489 | |
490 #if (WIN32) | |
491 #include <ngx_iocp_module.h> | |
492 #endif | |
493 | |
494 | |
495 | |
496 ngx_inline static int ngx_handle_read_event(ngx_event_t *rev, u_int flags) | |
497 { | |
498 if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { | |
499 | |
500 /* kqueue */ | |
501 | |
502 if (!rev->active && !rev->ready) { | |
503 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) | |
504 == NGX_ERROR) { | |
505 return NGX_ERROR; | |
506 } | |
507 } | |
508 | |
509 return NGX_OK; | |
510 | |
511 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { | |
512 | |
513 /* select, poll, /dev/poll */ | |
514 | |
515 if (!rev->active && !rev->ready) { | |
516 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) | |
517 == NGX_ERROR) | |
518 { | |
519 return NGX_ERROR; | |
520 } | |
521 | |
522 return NGX_OK; | |
523 } | |
524 | |
525 if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) { | |
526 if (ngx_del_event(rev, NGX_READ_EVENT, flags) == NGX_ERROR) { | |
527 return NGX_ERROR; | |
528 } | |
529 | |
530 return NGX_OK; | |
531 } | |
532 } | |
533 | |
534 /* aio, iocp, epoll, rtsig */ | |
535 | |
536 return NGX_OK; | |
537 } | |
538 | |
539 | |
540 ngx_inline static int ngx_handle_level_read_event(ngx_event_t *rev) | |
541 { | |
542 if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { | |
543 if (!rev->active && !rev->ready) { | |
544 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) | |
545 == NGX_ERROR) | |
546 { | |
547 return NGX_ERROR; | |
548 } | |
549 | |
550 return NGX_OK; | |
551 } | |
552 | |
553 if (rev->active && rev->ready) { | |
554 if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { | |
555 return NGX_ERROR; | |
556 } | |
557 | |
558 return NGX_OK; | |
559 } | |
560 } | |
561 | |
562 return NGX_OK; | |
563 } | |
564 | |
565 | |
566 ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, u_int flags) | |
567 { | |
568 if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { | |
569 | |
570 /* kqueue */ | |
571 | |
572 if (!wev->active && !wev->ready) { | |
573 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT|flags) | |
574 == NGX_ERROR) | |
575 { | |
576 return NGX_ERROR; | |
577 } | |
578 } | |
579 | |
580 return NGX_OK; | |
581 | |
582 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { | |
583 | |
584 /* select, poll, /dev/poll */ | |
585 | |
586 if (!wev->active && !wev->ready) { | |
587 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT) | |
588 == NGX_ERROR) | |
589 { | |
590 return NGX_ERROR; | |
591 } | |
592 | |
593 return NGX_OK; | |
594 } | |
595 | |
596 if (wev->active && wev->ready) { | |
597 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { | |
598 return NGX_ERROR; | |
599 } | |
600 | |
601 return NGX_OK; | |
602 } | |
603 } | |
604 | |
605 /* aio, iocp, epoll, rtsig */ | |
606 | |
607 return NGX_OK; | |
608 } | |
609 | |
610 | |
611 ngx_inline static int ngx_handle_level_write_event(ngx_event_t *wev) | |
612 { | |
613 if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { | |
614 if (!wev->active && !wev->ready) { | |
615 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT) | |
616 == NGX_ERROR) | |
617 { | |
618 return NGX_ERROR; | |
619 } | |
620 | |
621 return NGX_OK; | |
622 } | |
623 | |
624 if (wev->active && wev->ready) { | |
625 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { | |
626 return NGX_ERROR; | |
627 } | |
628 | |
629 return NGX_OK; | |
630 } | |
631 } | |
632 | |
633 return NGX_OK; | |
634 } | |
635 | |
636 | |
637 #endif /* _NGX_EVENT_H_INCLUDED_ */ |