ioloop-epoll.c revision 20a3870db4f78717574ee94bca1512994391b2ab
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen * Linux epoll() based ioloop handler.
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
65988f5a8abed57e9894fec77105941e046d3490Timo Sirainen * This software is released under the MIT license.
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainenvoid io_loop_handler_init(struct ioloop *ioloop)
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen ioloop->handler_context = ctx = i_new(struct ioloop_handler_context, 1);
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen i_array_init(&ctx->events, IOLOOP_INITIAL_FD_COUNT);
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen i_array_init(&ctx->fd_index, IOLOOP_INITIAL_FD_COUNT);
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen ctx->epfd = epoll_create(IOLOOP_INITIAL_FD_COUNT);
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainenvoid io_loop_handler_deinit(struct ioloop *ioloop)
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen unsigned int i, count;
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen list = array_get_modifiable(&ctx->fd_index, &count);
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen for (i = 0; i < count; i++)
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen array_free(&ioloop->handler_context->fd_index);
f923659c0e5298263d80622c99f4dc4132b4675bTimo Sirainen#define IO_EPOLL_INPUT (EPOLLIN | EPOLLPRI | IO_EPOLL_ERROR)
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen#define IO_EPOLL_OUTPUT (EPOLLOUT | IO_EPOLL_ERROR)
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainenstatic int epoll_event_mask(struct io_list *list)
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
fab050cbfdf3da692441d2e2fb4b2a4c6ac9e0daTimo Sirainenvoid io_loop_handle_add(struct ioloop *ioloop, struct io_file *io)
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
2a3fc652e13a574ca14ff2405b5c29a59232db49Timo Sirainen list = array_idx_modifiable(&ctx->fd_index, io->fd);
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen i_fatal("io_loop_handle_add: epoll_ctl(%d, %d): %m",
812ac1e2570c600a086c09b24d250224a822a97dTimo Sirainen /* allow epoll_wait() to return the maximum number of events
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen by keeping space allocated for each file descriptor */
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainenvoid io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io)
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen list = array_idx_modifiable(&ctx->fd_index, io->fd);
bc2d4f1c18222a3bd2a6b2b8b5f6abb560a865b3Timo Sirainen if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
a93de780c3b78cfaace287026e468f3c3e34683aTimo Sirainen i_error("io_loop_handle_remove: epoll_ctl(%d, %d): %m",
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen /* since we're not freeing memory in any case, just increase
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen deleted counter so next handle_add() can just decrease it
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen insteading of appending to the events array */
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainenvoid io_loop_handler_run(struct ioloop *ioloop)
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen /* get the time left for next timeout task */
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen msecs = io_loop_get_wait_time(ioloop, &tv, NULL);
bc2d4f1c18222a3bd2a6b2b8b5f6abb560a865b3Timo Sirainen events = array_get_modifiable(&ctx->events, &events_count);
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen ret = epoll_wait(ctx->epfd, events, events_count, msecs);
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen /* execute timeout handlers */
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen for (i = 0; i < ret; i++) {
for (j = 0; j < IOLOOP_IOLIST_IOS_PER_FD; j++) {
if (call) {