ioloop-epoll.c revision 637f9883a385abb03fd1211e79cc68df696cc387
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch * Linux epoll() based ioloop handler.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch * This software is released under the MIT license.
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid io_loop_handler_init(struct ioloop *ioloop, unsigned int initial_fd_count)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ioloop->handler_context = ctx = i_new(struct ioloop_handler_context, 1);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_array_init(&ctx->fd_index, initial_fd_count);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_fatal("epoll_create(): %m (you may need to increase "
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid io_loop_handler_deinit(struct ioloop *ioloop)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct ioloop_handler_context *ctx = ioloop->handler_context;
c6494255de7b934281dd052960fd8ab5aa48e79eTimo Sirainen unsigned int i, count;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch list = array_get_modifiable(&ctx->fd_index, &count);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch for (i = 0; i < count; i++)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch array_free(&ioloop->handler_context->fd_index);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#define IO_EPOLL_INPUT (EPOLLIN | EPOLLPRI | IO_EPOLL_ERROR)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#define IO_EPOLL_OUTPUT (EPOLLOUT | IO_EPOLL_ERROR)
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int epoll_event_mask(struct io_list *list)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct ioloop_handler_context *ctx = io->io.ioloop->handler_context;
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen list = array_idx_modifiable(&ctx->fd_index, io->fd);
6bc9fb43cc1ac24693d030a6cbfa43bc7cbc82cbTimo Sirainen if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen " - instead of '<file', try 'cat file|'");
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch /* allow epoll_wait() to return the maximum number of events
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch by keeping space allocated for each file descriptor */
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid io_loop_handle_remove(struct io_file *io, bool closed)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct ioloop_handler_context *ctx = io->io.ioloop->handler_context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch list = array_idx_modifiable(&ctx->fd_index, io->fd);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch /* since we're not freeing memory in any case, just increase
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch deleted counter so next handle_add() can just decrease it
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch insteading of appending to the events array */
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Boschvoid io_loop_handler_run(struct ioloop *ioloop)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch struct ioloop_handler_context *ctx = ioloop->handler_context;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch /* get the time left for next timeout task */
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen events = array_get_modifiable(&ctx->events, &events_count);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch ret = epoll_wait(ctx->epfd, events, events_count, msecs);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch /* no I/Os, but we should have some timeouts.
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch just wait for them. */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* execute timeout handlers */
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen for (i = 0; i < ret; i++) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* io_loop_handle_add() may cause events array reallocation,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch so we have use array_idx() */
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen for (j = 0; j < IOLOOP_IOLIST_IOS_PER_FD; j++) {
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen if ((event->events & (EPOLLHUP | EPOLLERR)) != 0)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#endif /* IOLOOP_EPOLL */