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 nxt_epoll_change_t *changes; 206 struct epoll_event *events; 207 208 #if (NXT_HAVE_EVENTFD) 209 nxt_work_handler_t post_handler; 210 nxt_fd_event_t eventfd; 211 uint32_t neventfd; 212 #endif 213 214 #if (NXT_HAVE_SIGNALFD) 215 nxt_fd_event_t signalfd; 216 #endif 217 } nxt_epoll_engine_t; 218 219 220 extern const nxt_event_interface_t nxt_epoll_edge_engine; 221 extern const nxt_event_interface_t nxt_epoll_level_engine; 222 223 #endif 224 225 226 #if (NXT_HAVE_EVENTPORT) 227 228 typedef struct { 229 int events; 230 nxt_fd_event_t *event; 231 } nxt_eventport_change_t; 232 233 234 typedef struct { 235 int fd; 236 nxt_uint_t nchanges; 237 nxt_uint_t mchanges; 238 u_int mevents; 239 240 nxt_eventport_change_t *changes; 241 port_event_t *events; 242 243 nxt_work_handler_t post_handler; 244 nxt_work_handler_t signal_handler; 245 } nxt_eventport_engine_t; 246 247 extern const nxt_event_interface_t nxt_eventport_engine; 248 249 #endif 250 251 252 #if (NXT_HAVE_DEVPOLL) 253 254 typedef struct { 255 uint8_t op; 256 short events; 257 nxt_fd_event_t *event; 258 } nxt_devpoll_change_t; 259 260 261 typedef struct { 262 int fd; 263 int nchanges; 264 int mchanges; 265 int mevents; 266 267 nxt_devpoll_change_t *changes; 268 struct pollfd *write_changes; 269 struct pollfd *events; 270 nxt_lvlhsh_t fd_hash; 271 } nxt_devpoll_engine_t; 272 273 extern const nxt_event_interface_t nxt_devpoll_engine; 274 275 #endif 276 277 278 #if (NXT_HAVE_POLLSET) 279 280 typedef struct { 281 uint8_t op; 282 uint8_t cmd; 283 short events; 284 nxt_fd_event_t *event; 285 } nxt_pollset_change_t; 286 287 288 typedef struct { 289 pollset_t ps; 290 int nchanges; 291 int mchanges; 292 int mevents; 293 294 nxt_pollset_change_t *changes; 295 struct poll_ctl *write_changes; 296 struct pollfd *events; 297 nxt_lvlhsh_t fd_hash; 298 } nxt_pollset_engine_t; 299 300 extern const nxt_event_interface_t nxt_pollset_engine; 301 302 #endif 303 304 305 typedef struct { 306 uint8_t op; 307 short events; 308 nxt_fd_event_t *event; 309 } nxt_poll_change_t; 310 311 312 typedef struct { 313 nxt_uint_t max_nfds; 314 nxt_uint_t nfds; 315 316 nxt_uint_t nchanges; 317 nxt_uint_t mchanges; 318 319 nxt_poll_change_t *changes; 320 struct pollfd *set; 321 322 nxt_lvlhsh_t fd_hash; 323 } nxt_poll_engine_t; 324 325 extern const nxt_event_interface_t nxt_poll_engine; 326 327 328 typedef struct { 329 int nfds; 330 uint32_t update_nfds; /* 1 bit */ 331 332 nxt_fd_event_t **events; 333 334 fd_set main_read_fd_set; 335 fd_set main_write_fd_set; 336 fd_set work_read_fd_set; 337 fd_set work_write_fd_set; 338 } nxt_select_engine_t; 339 340 extern const nxt_event_interface_t nxt_select_engine; 341 342 343 nxt_int_t nxt_fd_event_hash_add(nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd, 344 nxt_fd_event_t *ev); 345 void *nxt_fd_event_hash_get(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, 346 nxt_fd_t fd); 347 void nxt_fd_event_hash_delete(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, 348 nxt_fd_t fd, nxt_bool_t ignore); 349 void nxt_fd_event_hash_destroy(nxt_lvlhsh_t *lvlhsh); 350 351 352 #define \ 353 nxt_fd_event_disable(engine, ev) \ 354 (engine)->event.disable(engine, ev) 355 356 357 #define \ 358 nxt_fd_event_delete(engine, ev) \ 359 (engine)->event.delete(engine, ev) 360 361 362 #define \ 363 nxt_fd_event_close(engine, ev) \ 364 (engine)->event.close(engine, ev) 365 366 367 #define \ 368 nxt_fd_event_enable_read(engine, ev) \ 369 (engine)->event.enable_read(engine, ev) 370 371 372 #define \ 373 nxt_fd_event_enable_write(engine, ev) \ 374 (engine)->event.enable_write(engine, ev) 375 376 377 #define \ 378 nxt_fd_event_disable_read(engine, ev) \ 379 (engine)->event.disable_read(engine, ev) 380 381 382 #define \ 383 nxt_fd_event_disable_write(engine, ev) \ 384 (engine)->event.disable_write(engine, ev) 385 386 387 #define \ 388 nxt_fd_event_block_read(engine, ev) \ 389 do { \ 390 if (nxt_fd_event_is_active((ev)->read)) { \ 391 (engine)->event.block_read(engine, ev); \ 392 } \ 393 } while (0) 394 395 396 #define \ 397 nxt_fd_event_block_write(engine, ev) \ 398 do { \ 399 if (nxt_fd_event_is_active((ev)->write)) { \ 400 (engine)->event.block_write(engine, ev); \ 401 } \ 402 } while (0) 403 404 405 #define \ 406 nxt_fd_event_oneshot_read(engine, ev) \ 407 (engine)->event.oneshot_read(engine, ev) 408 409 410 #define \ 411 nxt_fd_event_oneshot_write(engine, ev) \ 412 (engine)->event.oneshot_write(engine, ev) 413 414 415 #define \ 416 nxt_fd_event_enable_accept(engine, ev) \ 417 (engine)->event.enable_accept(engine, ev) 418 419 420 #define NXT_ENGINE_FIBERS 1 421 422 423 typedef struct { 424 nxt_fd_t fds[2]; 425 nxt_fd_event_t event; 426 } nxt_event_engine_pipe_t; 427 428 429 struct nxt_event_engine_s { 430 nxt_task_t task; 431 432 union { 433 nxt_poll_engine_t poll; 434 nxt_select_engine_t select; 435 436 #if (NXT_HAVE_KQUEUE) 437 nxt_kqueue_engine_t kqueue; 438 #endif 439 #if (NXT_HAVE_EPOLL) 440 nxt_epoll_engine_t epoll; 441 #endif 442 #if (NXT_HAVE_EVENTPORT) 443 nxt_eventport_engine_t eventport; 444 #endif 445 #if (NXT_HAVE_DEVPOLL) 446 nxt_devpoll_engine_t devpoll; 447 #endif 448 #if (NXT_HAVE_POLLSET) 449 nxt_pollset_engine_t pollset; 450 #endif 451 } u; 452 453 nxt_timers_t timers; 454 455 nxt_work_queue_cache_t work_queue_cache; 456 nxt_work_queue_t *current_work_queue; 457 nxt_work_queue_t fast_work_queue; 458 nxt_work_queue_t accept_work_queue; 459 nxt_work_queue_t read_work_queue; 460 nxt_work_queue_t socket_work_queue; 461 nxt_work_queue_t connect_work_queue; 462 nxt_work_queue_t write_work_queue; 463 nxt_work_queue_t shutdown_work_queue; 464 nxt_work_queue_t close_work_queue; 465 466 nxt_locked_work_queue_t locked_work_queue; 467 468 nxt_event_interface_t event; 469 470 /* 471 * A pipe to pass event signals to the engine, if the engine's 472 * underlying event facility does not support user events. 473 */ 474 nxt_event_engine_pipe_t *pipe; 475 476 nxt_event_signals_t *signals; 477 478 nxt_fiber_main_t *fibers; 479 480 /* The engine ID, the main engine has ID 0. */ 481 uint32_t id; 482 483 uint8_t shutdown; /* 1 bit */ 484 485 uint32_t batch; 486 uint32_t connections; 487 uint32_t max_connections; 488 489 nxt_port_t *port; 490 nxt_mp_t *mem_pool; 491 nxt_queue_t joints; 492 nxt_queue_t listen_connections; 493 nxt_queue_t idle_connections; 494 nxt_lvlhsh_t requests; /* req_id to nxt_req_conn_link_t */ 495 496 nxt_queue_link_t link; 497 // STUB: router link 498 nxt_queue_link_t link0; 499 }; 500 501 502 NXT_EXPORT nxt_event_engine_t *nxt_event_engine_create(nxt_task_t *task, 503 const nxt_event_interface_t *interface, const nxt_sig_event_t *signals, 504 nxt_uint_t flags, nxt_uint_t batch); 505 NXT_EXPORT nxt_int_t nxt_event_engine_change(nxt_event_engine_t *engine, 506 const nxt_event_interface_t *interface, nxt_uint_t batch); 507 NXT_EXPORT void nxt_event_engine_free(nxt_event_engine_t *engine); 508 NXT_EXPORT void nxt_event_engine_start(nxt_event_engine_t *engine); 509 510 NXT_EXPORT void nxt_event_engine_post(nxt_event_engine_t *engine, 511 nxt_work_t *work); 512 NXT_EXPORT void nxt_event_engine_signal(nxt_event_engine_t *engine, 513 nxt_uint_t signo); 514 515 NXT_EXPORT void nxt_event_engine_request_add(nxt_event_engine_t *engine, 516 nxt_req_conn_link_t *rc); 517 NXT_EXPORT nxt_req_conn_link_t *nxt_event_engine_request_find( 518 nxt_event_engine_t *engine, nxt_req_id_t req_id); 519 NXT_EXPORT void nxt_event_engine_request_remove(nxt_event_engine_t *engine, 520 nxt_req_conn_link_t *rc); 521 NXT_EXPORT nxt_req_conn_link_t *nxt_event_engine_request_find_remove( 522 nxt_event_engine_t *engine, nxt_req_id_t req_id); 523 524 525 nxt_inline nxt_event_engine_t * 526 nxt_thread_event_engine(void) 527 { 528 nxt_thread_t *thr; 529 530 thr = nxt_thread(); 531 return thr->engine; 532 } 533 534 535 #endif /* _NXT_EVENT_ENGINE_H_INCLUDED_ */ 536