1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #ifndef _NGX_EVENT_H_INCLUDED_
9 #define _NGX_EVENT_H_INCLUDED_
10
11
12 #include <ngx_config.h>
13 #include <ngx_core.h>
14
15
16 #define NGX_INVALID_INDEX 0xd0d0d0d0
17
18
19 #if (NGX_HAVE_IOCP)
20
21 typedef struct {
22 WSAOVERLAPPED ovlp;
23 ngx_event_t *event;
24 int error;
25 } ngx_event_ovlp_t;
26
27 #endif
28
29
30 struct ngx_event_s {
31 void *data;
32
33 unsigned write:1;
34
35 unsigned accept:1;
36
37 /* used to detect the stale events in kqueue and epoll */
38 unsigned instance:1;
39
40 /*
41 * the event was passed or would be passed to a kernel;
42 * in aio mode - operation was posted.
43 */
44 unsigned active:1;
45
46 unsigned disabled:1;
47
48 /* the ready event; in aio mode 0 means that no operation can be posted */
49 unsigned ready:1;
50
51 unsigned oneshot:1;
52
53 /* aio operation is complete */
54 unsigned complete:1;
55
56 unsigned eof:1;
57 unsigned error:1;
58
59 unsigned timedout:1;
60 unsigned timer_set:1;
61
62 unsigned delayed:1;
63
64 unsigned deferred_accept:1;
65
66 /* the pending eof reported by kqueue, epoll or in aio chain operation */
67 unsigned pending_eof:1;
68
69 unsigned posted:1;
70
71 unsigned closed:1;
72
73 /* to test on worker exit */
74 unsigned channel:1;
75 unsigned resolver:1;
76
77 unsigned cancelable:1;
78
79 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK)
80 unsigned kq_vnode:1;
81
82 /* the pending errno reported by kqueue */
83 int kq_errno;
84 #endif
85
86 /*
87 * kqueue only:
88 * accept: number of sockets that wait to be accepted
89 * read: bytes to read when event is ready
90 * or lowat when event is set with NGX_LOWAT_EVENT flag
91 * write: available space in buffer when event is ready
92 * or lowat when event is set with NGX_LOWAT_EVENT flag
93 *
94 * epoll with EPOLLRDHUP:
95 * accept: 1 if accept many, 0 otherwise
96 * read: 1 if there can be data to read, 0 otherwise
97 *
98 * iocp: TODO
99 *
100 * otherwise:
101 * accept: 1 if accept many, 0 otherwise
102 */
103
104 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP) || (NGX_HAVE_FSTACK)
105 int available;
106 #else
107 unsigned available:1;
108 #endif
109
110 ngx_event_handler_pt handler;
111
112
113 #if (NGX_HAVE_IOCP)
114 ngx_event_ovlp_t ovlp;
115 #endif
116
117 ngx_uint_t index;
118
119 ngx_log_t *log;
120
121 ngx_rbtree_node_t timer;
122
123 /* the posted queue */
124 ngx_queue_t queue;
125
126 #if 0
127
128 /* the threads support */
129
130 /*
131 * the event thread context, we store it here
132 * if $(CC) does not understand __thread declaration
133 * and pthread_getspecific() is too costly
134 */
135
136 void *thr_ctx;
137
138 #if (NGX_EVENT_T_PADDING)
139
140 /* event should not cross cache line in SMP */
141
142 uint32_t padding[NGX_EVENT_T_PADDING];
143 #endif
144 #endif
145
146 #if (NGX_HAVE_FSTACK)
147 unsigned belong_to_host:1;
148 #endif
149 };
150
151
152 #if (NGX_HAVE_FILE_AIO)
153
154 struct ngx_event_aio_s {
155 void *data;
156 ngx_event_handler_pt handler;
157 ngx_file_t *file;
158
159 ngx_fd_t fd;
160
161 #if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
162 ssize_t (*preload_handler)(ngx_buf_t *file);
163 #endif
164
165 #if (NGX_HAVE_EVENTFD)
166 int64_t res;
167 #endif
168
169 #if !(NGX_HAVE_EVENTFD) || (NGX_TEST_BUILD_EPOLL)
170 ngx_err_t err;
171 size_t nbytes;
172 #endif
173
174 ngx_aiocb_t aiocb;
175 ngx_event_t event;
176 };
177
178 #endif
179
180
181 typedef struct {
182 ngx_int_t (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
183 ngx_int_t (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
184
185 ngx_int_t (*enable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
186 ngx_int_t (*disable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
187
188 ngx_int_t (*add_conn)(ngx_connection_t *c);
189 ngx_int_t (*del_conn)(ngx_connection_t *c, ngx_uint_t flags);
190
191 ngx_int_t (*notify)(ngx_event_handler_pt handler);
192
193 ngx_int_t (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer,
194 ngx_uint_t flags);
195
196 ngx_int_t (*init)(ngx_cycle_t *cycle, ngx_msec_t timer);
197 void (*done)(ngx_cycle_t *cycle);
198 } ngx_event_actions_t;
199
200
201 extern ngx_event_actions_t ngx_event_actions;
202 #if (NGX_HAVE_EPOLLRDHUP)
203 extern ngx_uint_t ngx_use_epoll_rdhup;
204 #endif
205 #if (NGX_HAVE_FSTACK)
206 extern ngx_event_actions_t ngx_ff_host_event_actions;
207 #endif
208
209
210 /*
211 * The event filter requires to read/write the whole data:
212 * select, poll, /dev/poll, kqueue, epoll.
213 */
214 #define NGX_USE_LEVEL_EVENT 0x00000001
215
216 /*
217 * The event filter is deleted after a notification without an additional
218 * syscall: kqueue, epoll.
219 */
220 #define NGX_USE_ONESHOT_EVENT 0x00000002
221
222 /*
223 * The event filter notifies only the changes and an initial level:
224 * kqueue, epoll.
225 */
226 #define NGX_USE_CLEAR_EVENT 0x00000004
227
228 /*
229 * The event filter has kqueue features: the eof flag, errno,
230 * available data, etc.
231 */
232 #define NGX_USE_KQUEUE_EVENT 0x00000008
233
234 /*
235 * The event filter supports low water mark: kqueue's NOTE_LOWAT.
236 * kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag.
237 */
238 #define NGX_USE_LOWAT_EVENT 0x00000010
239
240 /*
241 * The event filter requires to do i/o operation until EAGAIN: epoll.
242 */
243 #define NGX_USE_GREEDY_EVENT 0x00000020
244
245 /*
246 * The event filter is epoll.
247 */
248 #define NGX_USE_EPOLL_EVENT 0x00000040
249
250 /*
251 * Obsolete.
252 */
253 #define NGX_USE_RTSIG_EVENT 0x00000080
254
255 /*
256 * Obsolete.
257 */
258 #define NGX_USE_AIO_EVENT 0x00000100
259
260 /*
261 * Need to add socket or handle only once: i/o completion port.
262 */
263 #define NGX_USE_IOCP_EVENT 0x00000200
264
265 /*
266 * The event filter has no opaque data and requires file descriptors table:
267 * poll, /dev/poll.
268 */
269 #define NGX_USE_FD_EVENT 0x00000400
270
271 /*
272 * The event module handles periodic or absolute timer event by itself:
273 * kqueue in FreeBSD 4.4, NetBSD 2.0, and MacOSX 10.4, Solaris 10's event ports.
274 */
275 #define NGX_USE_TIMER_EVENT 0x00000800
276
277 /*
278 * All event filters on file descriptor are deleted after a notification:
279 * Solaris 10's event ports.
280 */
281 #define NGX_USE_EVENTPORT_EVENT 0x00001000
282
283 /*
284 * The event filter support vnode notifications: kqueue.
285 */
286 #define NGX_USE_VNODE_EVENT 0x00002000
287
288
289 /*
290 * The event filter is deleted just before the closing file.
291 * Has no meaning for select and poll.
292 * kqueue, epoll, eventport: allows to avoid explicit delete,
293 * because filter automatically is deleted
294 * on file close,
295 *
296 * /dev/poll: we need to flush POLLREMOVE event
297 * before closing file.
298 */
299 #define NGX_CLOSE_EVENT 1
300
301 /*
302 * disable temporarily event filter, this may avoid locks
303 * in kernel malloc()/free(): kqueue.
304 */
305 #define NGX_DISABLE_EVENT 2
306
307 /*
308 * event must be passed to kernel right now, do not wait until batch processing.
309 */
310 #define NGX_FLUSH_EVENT 4
311
312
313 /* these flags have a meaning only for kqueue */
314 #define NGX_LOWAT_EVENT 0
315 #define NGX_VNODE_EVENT 0
316
317
318 #if (NGX_HAVE_EPOLL) && !(NGX_HAVE_EPOLLRDHUP)
319 #define EPOLLRDHUP 0
320 #endif
321
322
323 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK)
324
325 #define NGX_READ_EVENT EVFILT_READ
326 #define NGX_WRITE_EVENT EVFILT_WRITE
327
328 #undef NGX_VNODE_EVENT
329 #define NGX_VNODE_EVENT EVFILT_VNODE
330
331 /*
332 * NGX_CLOSE_EVENT, NGX_LOWAT_EVENT, and NGX_FLUSH_EVENT are the module flags
333 * and they must not go into a kernel so we need to choose the value
334 * that must not interfere with any existent and future kqueue flags.
335 * kqueue has such values - EV_FLAG1, EV_EOF, and EV_ERROR:
336 * they are reserved and cleared on a kernel entrance.
337 */
338 #undef NGX_CLOSE_EVENT
339 #define NGX_CLOSE_EVENT EV_EOF
340
341 #undef NGX_LOWAT_EVENT
342 #define NGX_LOWAT_EVENT EV_FLAG1
343
344 #undef NGX_FLUSH_EVENT
345 #define NGX_FLUSH_EVENT EV_ERROR
346
347 #define NGX_LEVEL_EVENT 0
348 #define NGX_ONESHOT_EVENT EV_ONESHOT
349 #define NGX_CLEAR_EVENT EV_CLEAR
350
351 #undef NGX_DISABLE_EVENT
352 #define NGX_DISABLE_EVENT EV_DISABLE
353
354
355 #elif (NGX_HAVE_DEVPOLL && !(NGX_TEST_BUILD_DEVPOLL)) \
356 || (NGX_HAVE_EVENTPORT && !(NGX_TEST_BUILD_EVENTPORT))
357
358 #define NGX_READ_EVENT POLLIN
359 #define NGX_WRITE_EVENT POLLOUT
360
361 #define NGX_LEVEL_EVENT 0
362 #define NGX_ONESHOT_EVENT 1
363
364
365 #elif (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
366
367 #define NGX_READ_EVENT (EPOLLIN|EPOLLRDHUP)
368 #define NGX_WRITE_EVENT EPOLLOUT
369
370 #define NGX_LEVEL_EVENT 0
371 #define NGX_CLEAR_EVENT EPOLLET
372 #define NGX_ONESHOT_EVENT 0x70000000
373 #if 0
374 #define NGX_ONESHOT_EVENT EPOLLONESHOT
375 #endif
376
377 #if (NGX_HAVE_EPOLLEXCLUSIVE)
378 #define NGX_EXCLUSIVE_EVENT EPOLLEXCLUSIVE
379 #endif
380
381 #elif (NGX_HAVE_POLL)
382
383 #define NGX_READ_EVENT POLLIN
384 #define NGX_WRITE_EVENT POLLOUT
385
386 #define NGX_LEVEL_EVENT 0
387 #define NGX_ONESHOT_EVENT 1
388
389
390 #else /* select */
391
392 #define NGX_READ_EVENT 0
393 #define NGX_WRITE_EVENT 1
394
395 #define NGX_LEVEL_EVENT 0
396 #define NGX_ONESHOT_EVENT 1
397
398 #endif /* NGX_HAVE_KQUEUE */
399
400
401 #if (NGX_HAVE_IOCP)
402 #define NGX_IOCP_ACCEPT 0
403 #define NGX_IOCP_IO 1
404 #define NGX_IOCP_CONNECT 2
405 #endif
406
407
408 #if (NGX_TEST_BUILD_EPOLL)
409 #define NGX_EXCLUSIVE_EVENT 0
410 #endif
411
412
413 #ifndef NGX_CLEAR_EVENT
414 #define NGX_CLEAR_EVENT 0 /* dummy declaration */
415 #endif
416
417 #if (NGX_HAVE_FSTACK)
418
419 static inline ngx_int_t
ngx_add_event(ngx_event_t * ev,ngx_int_t event,ngx_uint_t flags)420 ngx_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) {
421 if (1 == ev->belong_to_host) {
422 return ngx_ff_host_event_actions.add(ev, event, flags);
423 } else {
424 return ngx_event_actions.add(ev, event, flags);
425 }
426 }
427
428 static inline ngx_int_t
ngx_del_event(ngx_event_t * ev,ngx_int_t event,ngx_uint_t flags)429 ngx_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) {
430 if (1 == ev->belong_to_host) {
431 return ngx_ff_host_event_actions.del(ev, event, flags);
432 } else {
433 return ngx_event_actions.del(ev, event, flags);
434 }
435 }
436
ngx_add_conn(ngx_connection_t * c)437 static inline ngx_int_t ngx_add_conn(ngx_connection_t *c)
438 {
439 return ngx_event_actions.add_conn(c);
440 }
441
ngx_del_conn(ngx_connection_t * c,ngx_uint_t flags)442 static inline ngx_int_t ngx_del_conn(
443 ngx_connection_t *c, ngx_uint_t flags) {
444 return ngx_event_actions.del_conn(c, flags);
445 }
446
ngx_notify(ngx_event_handler_pt handler)447 static inline ngx_int_t ngx_notify(ngx_event_handler_pt handler) {
448 return ngx_event_actions.notify(handler);
449 }
450
ngx_process_events(ngx_cycle_t * cycle,ngx_msec_t timer,ngx_uint_t flags)451 static inline ngx_int_t ngx_process_events(
452 ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
453 {
454 return ngx_event_actions.process_events(cycle, timer, flags);
455 }
456
457 #define ngx_ff_process_host_events ngx_ff_host_event_actions.process_events
458
459 #else
460
461 #define ngx_process_events ngx_event_actions.process_events
462 #define ngx_done_events ngx_event_actions.done
463
464 #define ngx_add_event ngx_event_actions.add
465 #define ngx_del_event ngx_event_actions.del
466 #define ngx_add_conn ngx_event_actions.add_conn
467 #define ngx_del_conn ngx_event_actions.del_conn
468
469 #define ngx_notify ngx_event_actions.notify
470
471 #endif /* NGX_HAVE_FSTACK */
472
473 #define ngx_add_timer ngx_event_add_timer
474 #define ngx_del_timer ngx_event_del_timer
475
476
477 extern ngx_os_io_t ngx_io;
478
479 #define ngx_recv ngx_io.recv
480 #define ngx_recv_chain ngx_io.recv_chain
481 #define ngx_udp_recv ngx_io.udp_recv
482 #define ngx_send ngx_io.send
483 #define ngx_send_chain ngx_io.send_chain
484 #define ngx_udp_send ngx_io.udp_send
485 #define ngx_udp_send_chain ngx_io.udp_send_chain
486
487
488 #define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */
489 #define NGX_EVENT_CONF 0x02000000
490
491
492 typedef struct {
493 ngx_uint_t connections;
494 ngx_uint_t use;
495
496 ngx_flag_t multi_accept;
497 ngx_flag_t accept_mutex;
498
499 ngx_msec_t accept_mutex_delay;
500
501 u_char *name;
502
503 #if (NGX_DEBUG)
504 ngx_array_t debug_connection;
505 #endif
506 } ngx_event_conf_t;
507
508
509 typedef struct {
510 ngx_str_t *name;
511
512 void *(*create_conf)(ngx_cycle_t *cycle);
513 char *(*init_conf)(ngx_cycle_t *cycle, void *conf);
514
515 ngx_event_actions_t actions;
516 } ngx_event_module_t;
517
518
519 extern ngx_atomic_t *ngx_connection_counter;
520
521 extern ngx_atomic_t *ngx_accept_mutex_ptr;
522 extern ngx_shmtx_t ngx_accept_mutex;
523 extern ngx_uint_t ngx_use_accept_mutex;
524 extern ngx_uint_t ngx_accept_events;
525 extern ngx_uint_t ngx_accept_mutex_held;
526 extern ngx_msec_t ngx_accept_mutex_delay;
527 extern ngx_int_t ngx_accept_disabled;
528
529
530 #if (NGX_STAT_STUB)
531
532 extern ngx_atomic_t *ngx_stat_accepted;
533 extern ngx_atomic_t *ngx_stat_handled;
534 extern ngx_atomic_t *ngx_stat_requests;
535 extern ngx_atomic_t *ngx_stat_active;
536 extern ngx_atomic_t *ngx_stat_reading;
537 extern ngx_atomic_t *ngx_stat_writing;
538 extern ngx_atomic_t *ngx_stat_waiting;
539
540 #endif
541
542
543 #define NGX_UPDATE_TIME 1
544 #define NGX_POST_EVENTS 2
545
546
547 extern sig_atomic_t ngx_event_timer_alarm;
548 extern ngx_uint_t ngx_event_flags;
549 extern ngx_module_t ngx_events_module;
550 extern ngx_module_t ngx_event_core_module;
551
552
553 #define ngx_event_get_conf(conf_ctx, module) \
554 (*(ngx_get_conf(conf_ctx, ngx_events_module))) [module.ctx_index]
555
556
557
558 void ngx_event_accept(ngx_event_t *ev);
559 #if !(NGX_WIN32)
560 void ngx_event_recvmsg(ngx_event_t *ev);
561 void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
562 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
563 #endif
564 void ngx_delete_udp_connection(void *data);
565 ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle);
566 ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
567 u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len);
568 #if (NGX_DEBUG)
569 void ngx_debug_accepted_connection(ngx_event_conf_t *ecf, ngx_connection_t *c);
570 #endif
571
572
573 void ngx_process_events_and_timers(ngx_cycle_t *cycle);
574 ngx_int_t ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags);
575 ngx_int_t ngx_handle_write_event(ngx_event_t *wev, size_t lowat);
576
577
578 #if (NGX_WIN32)
579 void ngx_event_acceptex(ngx_event_t *ev);
580 ngx_int_t ngx_event_post_acceptex(ngx_listening_t *ls, ngx_uint_t n);
581 u_char *ngx_acceptex_log_error(ngx_log_t *log, u_char *buf, size_t len);
582 #endif
583
584
585 ngx_int_t ngx_send_lowat(ngx_connection_t *c, size_t lowat);
586
587
588 /* used in ngx_log_debugX() */
589 #define ngx_event_ident(p) ((ngx_connection_t *) (p))->fd
590
591
592 #include <ngx_event_timer.h>
593 #include <ngx_event_posted.h>
594
595 #if (NGX_WIN32)
596 #include <ngx_iocp_module.h>
597 #endif
598
599
600 #endif /* _NGX_EVENT_H_INCLUDED_ */
601