1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #ifndef _NXT_EVENT_ENGINE_H_INCLUDED_ 8 #define _NXT_EVENT_ENGINE_H_INCLUDED_ 9 10 /* 11 * An event interface is kernel interface such as kqueue, epoll, etc. 12 * intended to get event notifications about file descriptor state, 13 * signals, etc. 14 */ 15 16 #define NXT_FILE_EVENTS 1 17 #define NXT_NO_FILE_EVENTS 0 18 19 #define NXT_SIGNAL_EVENTS 1 20 #define NXT_NO_SIGNAL_EVENTS 0 21 22 23 typedef struct { 24 25 /* The canonical event set name. */ 26 const char *name; 27 28 /* 29 * Create an event set. The mchanges argument is a maximum number of 30 * changes to send to the kernel. The mevents argument is a maximum 31 * number of events to retrieve from the kernel at once, if underlying 32 * event facility supports batch operations. 33 */ 34 nxt_int_t (*create)(nxt_event_engine_t *engine, 35 nxt_uint_t mchanges, nxt_uint_t mevents); 36 37 /* Close and free an event set. */ 38 void (*free)(nxt_event_engine_t *engine); 39 40 /* 41 * Add a file descriptor to an event set and enable the most 42 * effective read and write event notification method provided 43 * by underlying event facility. 44 */ 45 void (*enable)(nxt_event_engine_t *engine, 46 nxt_fd_event_t *ev); 47 48 /* Disable file descriptor event notifications. */ 49 void (*disable)(nxt_event_engine_t *engine, 50 nxt_fd_event_t *ev); 51 52 /* 53 * Delete a file descriptor from an event set. A possible usage 54 * is a moving of the file descriptor from one event set to another. 55 */ 56 void (*delete)(nxt_event_engine_t *engine, 57 nxt_fd_event_t *ev); 58 59 /* 60 * Delete a file descriptor from an event set before closing the 61 * file descriptor. The most event facilities such as Linux epoll, 62 * BSD kqueue, Solaris event ports, AIX pollset, and HP-UX /dev/poll 63 * delete a file descriptor automatically on the file descriptor close. 64 * Some facilities such as Solaris /dev/poll require to delete a file 65 * descriptor explicitly. 66 */ 67 nxt_bool_t (*close)(nxt_event_engine_t *engine, 68 nxt_fd_event_t *ev); 69 70 /* 71 * Add a file descriptor to an event set and enable the most effective 72 * read event notification method provided by underlying event facility. 73 */ 74 void (*enable_read)(nxt_event_engine_t *engine, 75 nxt_fd_event_t *ev); 76 77 /* 78 * Add a file descriptor to an event set and enable the most effective 79 * write event notification method provided by underlying event facility. 80 */ 81 void (*enable_write)(nxt_event_engine_t *engine, 82 nxt_fd_event_t *ev); 83 84 /* Disable file descriptor read event notifications. */ 85 void (*disable_read)(nxt_event_engine_t *engine, 86 nxt_fd_event_t *ev); 87 88 /* Disable file descriptor write event notifications. */ 89 void (*disable_write)(nxt_event_engine_t *engine, 90 nxt_fd_event_t *ev); 91 92 /* Block file descriptor read event notifications. */ 93 void (*block_read)(nxt_event_engine_t *engine, 94 nxt_fd_event_t *ev); 95 96 /* Block file descriptor write event notifications. */ 97 void (*block_write)(nxt_event_engine_t *engine, 98 nxt_fd_event_t *ev); 99 100 /* 101 * Add a file descriptor to an event set and enable an oneshot 102 * read event notification method. 103 */ 104 void (*oneshot_read)(nxt_event_engine_t *engine, 105 nxt_fd_event_t *ev); 106 107 /* 108 * Add a file descriptor to an event set and enable an oneshot 109 * write event notification method. 110 */ 111 void (*oneshot_write)(nxt_event_engine_t *engine, 112 nxt_fd_event_t *ev); 113 114 /* 115 * Add a listening socket descriptor to an event set and enable 116 * a level-triggered read event notification method. 117 */ 118 void (*enable_accept)(nxt_event_engine_t *engine, 119 nxt_fd_event_t *ev); 120 121 /* 122 * Add a file to an event set and enable a file change notification 123 * events. 124 */ 125 void (*enable_file)(nxt_event_engine_t *engine, 126 nxt_file_event_t *ev); 127 128 /* 129 * Delete a file from an event set before closing the file descriptor. 130 */ 131 void (*close_file)(nxt_event_engine_t *engine, 132 nxt_file_event_t *ev); 133 134 /* 135 * Enable post event notifications and set a post handler to handle 136 * the zero signal. 137 */ 138 nxt_int_t (*enable_post)(nxt_event_engine_t *engine, 139 nxt_work_handler_t handler); 140 141 /* 142 * Signal an event set. If a signal number is non-zero then 143 * a signal handler added to the event set is called. This is 144 * a way to route Unix signals to an event engine if underlying 145 * event facility does not support signal events. 146 * 147 * If a signal number is zero, then the post_handler of the event 148 * set is called. This has no relation to Unix signals but is 149 * a way to wake up the event set to process works posted to 150 * the event engine locked work queue. 151 */ 152 void (*signal)(nxt_event_engine_t *engine, 153 nxt_uint_t signo); 154 155 /* Poll an event set for new event notifications. */ 156 void (*poll)(nxt_event_engine_t *engine, 157 nxt_msec_t timeout); 158 159 /* I/O operations suitable to underlying event facility. */ 160 nxt_conn_io_t *io; 161 162 /* True if an event facility supports file change event notifications. */ 163 uint8_t file_support; /* 1 bit */ 164 165 /* True if an event facility supports signal event notifications. */ 166 uint8_t signal_support; /* 1 bit */ 167 } nxt_event_interface_t; 168 169 170 #if (NXT_HAVE_KQUEUE) 171 172 typedef struct { 173 int fd; 174 int nchanges; 175 int mchanges; 176 int mevents; 177 nxt_pid_t pid; 178 179 nxt_work_handler_t post_handler; 180 181 struct kevent *changes; 182 struct kevent *events; 183 } nxt_kqueue_engine_t; 184 185 extern const nxt_event_interface_t nxt_kqueue_engine; 186 187 #endif 188 189 190 #if (NXT_HAVE_EPOLL) 191 192 typedef struct { 193 int op; 194 struct epoll_event event; 195 } nxt_epoll_change_t; 196 197 198 typedef struct { 199 int fd; 200 uint32_t mode; 201 nxt_uint_t nchanges; 202 nxt_uint_t mchanges; 203 int mevents; 204 205 uint8_t error; /* 1 bit */ 206 207 nxt_epoll_change_t *changes; 208 struct epoll_event *events; 209 210 #if (NXT_HAVE_EVENTFD) 211 nxt_work_handler_t post_handler; 212 nxt_fd_event_t eventfd; 213 uint32_t neventfd; 214 #endif 215 216 #if (NXT_HAVE_SIGNALFD) 217 nxt_fd_event_t signalfd; 218 #endif 219 } nxt_epoll_engine_t; 220 221 222 extern const nxt_event_interface_t nxt_epoll_edge_engine; 223 extern const nxt_event_interface_t nxt_epoll_level_engine; 224 225 #endif 226 227 228 #if (NXT_HAVE_EVENTPORT) 229 230 typedef struct { 231 int events; 232 nxt_fd_event_t *event; 233 } nxt_eventport_change_t; 234 235 236 typedef struct { 237 int fd; 238 nxt_uint_t nchanges; 239 nxt_uint_t mchanges; 240 u_int mevents; 241 242 nxt_eventport_change_t *changes; 243 port_event_t *events; 244 245 nxt_work_handler_t post_handler; 246 nxt_work_handler_t signal_handler; 247 } nxt_eventport_engine_t; 248 249 extern const nxt_event_interface_t nxt_eventport_engine; 250 251 #endif 252 253 254 #if (NXT_HAVE_DEVPOLL) 255 256 typedef struct { 257 uint8_t op; 258 short events; 259 nxt_fd_event_t *event; 260 } nxt_devpoll_change_t; 261 262 263 typedef struct { 264 int fd; 265 int nchanges; 266 int mchanges; 267 int mevents; 268 269 nxt_devpoll_change_t *changes; 270 struct pollfd *write_changes; 271 struct pollfd *events; 272 nxt_lvlhsh_t fd_hash; 273 } nxt_devpoll_engine_t; 274 275 extern const nxt_event_interface_t nxt_devpoll_engine; 276 277 #endif 278 279 280 #if (NXT_HAVE_POLLSET) 281 282 typedef struct { 283 uint8_t op; 284 uint8_t cmd; 285 short events; 286 nxt_fd_event_t *event; 287 } nxt_pollset_change_t; 288 289 290 typedef struct { 291 pollset_t ps; 292 int nchanges; 293 int mchanges; 294 int mevents; 295 296 nxt_pollset_change_t *changes; 297 struct poll_ctl *write_changes; 298 struct pollfd *events; 299 nxt_lvlhsh_t fd_hash; 300 } nxt_pollset_engine_t; 301 302 extern const nxt_event_interface_t nxt_pollset_engine; 303 304 #endif 305 306 307 typedef struct { 308 uint8_t op; 309 short events; 310 nxt_fd_event_t *event; 311 } nxt_poll_change_t; 312 313 314 typedef struct { 315 nxt_uint_t max_nfds; 316 nxt_uint_t nfds; 317 318 nxt_uint_t nchanges; 319 nxt_uint_t mchanges; 320 321 nxt_poll_change_t *changes; 322 struct pollfd *set; 323 324 nxt_lvlhsh_t fd_hash; 325 } nxt_poll_engine_t; 326 327 extern const nxt_event_interface_t nxt_poll_engine; 328 329 330 typedef struct { 331 int nfds; 332 uint32_t update_nfds; /* 1 bit */ 333 334 nxt_fd_event_t **events; 335 336 fd_set main_read_fd_set; 337 fd_set main_write_fd_set; 338 fd_set work_read_fd_set; 339 fd_set work_write_fd_set; 340 } nxt_select_engine_t; 341 342 extern const nxt_event_interface_t nxt_select_engine; 343 344 345 nxt_int_t nxt_fd_event_hash_add(nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd, 346 nxt_fd_event_t *ev); 347 void *nxt_fd_event_hash_get(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, 348 nxt_fd_t fd); 349 void nxt_fd_event_hash_delete(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, 350 nxt_fd_t fd, nxt_bool_t ignore); 351 void nxt_fd_event_hash_destroy(nxt_lvlhsh_t *lvlhsh); 352 353 354 #define nxt_fd_event_disable(engine, ev) \ 355 (engine)->event.disable(engine, ev) 356 357 358 #define nxt_fd_event_delete(engine, ev) \ 359 (engine)->event.delete(engine, ev) 360 361 362 #define nxt_fd_event_close(engine, ev) \ 363 (engine)->event.close(engine, ev) 364 365 366 #define nxt_fd_event_enable_read(engine, ev) \ 367 (engine)->event.enable_read(engine, ev) 368 369 370 #define nxt_fd_event_enable_write(engine, ev) \ 371 (engine)->event.enable_write(engine, ev) 372 373 374 #define nxt_fd_event_disable_read(engine, ev) \ 375 (engine)->event.disable_read(engine, ev) 376 377 378 #define nxt_fd_event_disable_write(engine, ev) \ 379 (engine)->event.disable_write(engine, ev) 380 381 382 #define nxt_fd_event_block_read(engine, ev) \ 383 do { \ 384 if (nxt_fd_event_is_active((ev)->read)) { \ 385 (engine)->event.block_read(engine, ev); \ 386 } \ 387 } while (0) 388 389 390 #define nxt_fd_event_block_write(engine, ev) \ 391 do { \ 392 if (nxt_fd_event_is_active((ev)->write)) { \ 393 (engine)->event.block_write(engine, ev); \ 394 } \ 395 } while (0) 396 397 398 #define nxt_fd_event_oneshot_read(engine, ev) \ 399 (engine)->event.oneshot_read(engine, ev) 400 401 402 #define nxt_fd_event_oneshot_write(engine, ev) \ 403 (engine)->event.oneshot_write(engine, ev) 404 405 406 #define nxt_fd_event_enable_accept(engine, ev) \ 407 (engine)->event.enable_accept(engine, ev) 408 409 410 #define NXT_ENGINE_FIBERS 1 411 412 413 typedef struct { 414 nxt_fd_t fds[2]; 415 nxt_fd_event_t event; 416 } nxt_event_engine_pipe_t; 417 418 419 struct nxt_event_engine_s { 420 nxt_task_t task; 421 422 union { 423 nxt_poll_engine_t poll; 424 nxt_select_engine_t select; 425 426 #if (NXT_HAVE_KQUEUE) 427 nxt_kqueue_engine_t kqueue; 428 #endif 429 #if (NXT_HAVE_EPOLL) 430 nxt_epoll_engine_t epoll; 431 #endif 432 #if (NXT_HAVE_EVENTPORT) 433 nxt_eventport_engine_t eventport; 434 #endif 435 #if (NXT_HAVE_DEVPOLL) 436 nxt_devpoll_engine_t devpoll; 437 #endif 438 #if (NXT_HAVE_POLLSET) 439 nxt_pollset_engine_t pollset; 440 #endif 441 } u; 442 443 nxt_timers_t timers; 444 445 nxt_work_queue_cache_t work_queue_cache; 446 nxt_work_queue_t *current_work_queue; 447 nxt_work_queue_t fast_work_queue; 448 nxt_work_queue_t accept_work_queue; 449 nxt_work_queue_t read_work_queue; 450 nxt_work_queue_t socket_work_queue; 451 nxt_work_queue_t connect_work_queue; 452 nxt_work_queue_t write_work_queue; 453 nxt_work_queue_t shutdown_work_queue; 454 nxt_work_queue_t close_work_queue; 455 456 nxt_locked_work_queue_t locked_work_queue; 457 458 nxt_event_interface_t event; 459 460 /* 461 * A pipe to pass event signals to the engine, if the engine's 462 * underlying event facility does not support user events. 463 */ 464 nxt_event_engine_pipe_t *pipe; 465 466 nxt_event_signals_t *signals; 467 468 nxt_fiber_main_t *fibers; 469 470 /* The engine ID, the main engine has ID 0. */ 471 uint32_t id; 472 473 uint8_t shutdown; /* 1 bit */ 474 475 uint32_t batch; 476 uint32_t connections; 477 uint32_t max_connections; 478 479 nxt_port_t *port; 480 nxt_mp_t *mem_pool; 481 nxt_queue_t joints; 482 nxt_queue_t listen_connections; 483 nxt_queue_t idle_connections; 484 nxt_array_t *mem_cache; 485 486 nxt_queue_link_t link; 487 // STUB: router link 488 nxt_queue_link_t link0; 489 }; 490 491 492 NXT_EXPORT nxt_event_engine_t *nxt_event_engine_create(nxt_task_t *task, 493 const nxt_event_interface_t *interface, const nxt_sig_event_t *signals, 494 nxt_uint_t flags, nxt_uint_t batch); 495 NXT_EXPORT nxt_int_t nxt_event_engine_change(nxt_event_engine_t *engine, 496 const nxt_event_interface_t *interface, nxt_uint_t batch); 497 NXT_EXPORT void nxt_event_engine_free(nxt_event_engine_t *engine); 498 NXT_EXPORT void nxt_event_engine_start(nxt_event_engine_t *engine); 499 500 NXT_EXPORT void nxt_event_engine_post(nxt_event_engine_t *engine, 501 nxt_work_t *work); 502 NXT_EXPORT void nxt_event_engine_signal(nxt_event_engine_t *engine, 503 nxt_uint_t signo); 504 505 #define NXT_EVENT_ENGINE_NO_MEM_HINT 255 506 507 void *nxt_event_engine_mem_alloc(nxt_event_engine_t *engine, uint8_t *hint, 508 size_t size); 509 void nxt_event_engine_mem_free(nxt_event_engine_t *engine, uint8_t hint, 510 void *p, size_t size); 511 void *nxt_event_engine_buf_mem_alloc(nxt_event_engine_t *engine, size_t size); 512 void nxt_event_engine_buf_mem_free(nxt_event_engine_t *engine, nxt_buf_t *b); 513 void nxt_event_engine_buf_mem_completion(nxt_task_t *task, void *obj, 514 void *data); 515 516 517 nxt_inline nxt_event_engine_t * 518 nxt_thread_event_engine(void) 519 { 520 nxt_thread_t *thr; 521 522 thr = nxt_thread(); 523 return thr->engine; 524 } 525 526 #if (NXT_DEBUG) 527 528 NXT_EXPORT void nxt_event_engine_thread_adopt(nxt_event_engine_t *engine); 529 530 #else 531 532 #define nxt_event_engine_thread_adopt(_engine) 533 534 #endif 535 536 537 #endif /* _NXT_EVENT_ENGINE_H_INCLUDED_ */ 538