ioloop-epoll.c revision dfacd2bdce28523f1f100aa2d811a22b90339098
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen/*
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen * Linux epoll() based ioloop handler.
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen *
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen *
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen * This library is free software; you can redistribute it and/or modify
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen * it under the terms of the GNU Lesser General Public License as published
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen * by the Free Software Foundation; either version 2 of the License, or
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen * (at your option) any later version.
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen/* @UNSAFE: whole file */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen#include "lib.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "array.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "fd-close-on-exec.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "ioloop-internal.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#ifdef IOLOOP_EPOLL
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include <sys/epoll.h>
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include <unistd.h>
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#define INITIAL_EPOLL_EVENTS 128
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenenum {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen EPOLL_LIST_INPUT,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen EPOLL_LIST_OUTPUT,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen EPOLL_LIST_ERROR,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen EPOLL_IOS_PER_FD
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen};
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstruct ioloop_handler_context {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int epfd;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int events_size, events_pos;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct epoll_event *events;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen unsigned int idx_size;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen array_t ARRAY_DEFINE(fd_index, struct io_list *);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen};
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstruct io_list {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct io *ios[EPOLL_IOS_PER_FD];
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen};
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenvoid io_loop_handler_init(struct ioloop *ioloop)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct ioloop_handler_context *ctx;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ioloop->handler_context = ctx =
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen p_new(ioloop->pool, struct ioloop_handler_context, 1);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->events_pos = 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->events_size = INITIAL_EPOLL_EVENTS;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->events = p_new(ioloop->pool, struct epoll_event,
bda9a6d9b021c122a01a85cb3cee2f996263d8f0Timo Sirainen ctx->events_size);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->idx_size = INITIAL_EPOLL_EVENTS;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ARRAY_CREATE(&ctx->fd_index, ioloop->pool,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct io_list *, ctx->idx_size);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->epfd = epoll_create(INITIAL_EPOLL_EVENTS);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ctx->epfd < 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_fatal("epoll_create(): %m");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen fd_close_on_exec(ctx->epfd, TRUE);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenvoid io_loop_handler_deinit(struct ioloop *ioloop)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (close(ctx->epfd) < 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_error("close(epoll) failed: %m");
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen array_free(&ioloop->handler_context->fd_index);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen p_free(ioloop->pool, ioloop->handler_context->events);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen p_free(ioloop->pool, ioloop->handler_context);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#define IO_EPOLL_ERROR (EPOLLERR | EPOLLHUP)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#define IO_EPOLL_INPUT (EPOLLIN | EPOLLPRI | IO_EPOLL_ERROR)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#define IO_EPOLL_OUTPUT (EPOLLOUT | IO_EPOLL_ERROR)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic int epoll_event_mask(struct io_list *list)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int events = 0, i;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct io *io;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen io = list->ios[i];
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (io == NULL)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen continue;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (io->condition & IO_READ)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen events |= IO_EPOLL_INPUT;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (io->condition & IO_WRITE)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen events |= IO_EPOLL_OUTPUT;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (io->condition & IO_ERROR)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen events |= IO_EPOLL_ERROR;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return events;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic bool iolist_add(struct io_list *list, struct io *io)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int i, idx;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if ((io->condition & IO_READ) != 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen idx = EPOLL_LIST_INPUT;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else if ((io->condition & IO_WRITE) != 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen idx = EPOLL_LIST_OUTPUT;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else if ((io->condition & IO_ERROR) != 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen idx = EPOLL_LIST_ERROR;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_unreached();
dcd50ecbfe796bd76f2d63483c534cc0e4e94164Timo Sirainen }
dcd50ecbfe796bd76f2d63483c534cc0e4e94164Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_assert(list->ios[idx] == NULL);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen list->ios[idx] = io;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* check if this was the first one */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (i != idx && list->ios[i] != NULL)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return FALSE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic bool iolist_del(struct io_list *list, struct io *io)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen bool last = TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int i;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (list->ios[i] != NULL) {
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen if (list->ios[i] == io)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen list->ios[i] = NULL;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen last = FALSE;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen }
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen }
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return last;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen}
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenvoid io_loop_handle_add(struct ioloop *ioloop, struct io *io)
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct io_list **list;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen struct epoll_event event;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int ret, op, fd = io->fd;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen bool first;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen list = array_idx_modifyable(&ctx->fd_index, fd);
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen if (*list == NULL)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen *list = p_new(ioloop->pool, struct io_list, 1);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen first = iolist_add(*list, io);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen event.data.ptr = *list;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen event.events = epoll_event_mask(*list);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen op = first ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen ret = epoll_ctl(ctx->epfd, op, fd, &event);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ret < 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_fatal("io_loop_handle_add: epoll_ctl(%d, %d): %m", op, fd);
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ctx->events_pos >= ctx->events_size) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->events_size = nearest_power(ctx->events_size + 1);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen p_free(ioloop->pool, ctx->events);
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen ctx->events = p_new(ioloop->pool, struct epoll_event,
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen ctx->events_size);
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen }
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen ctx->events_pos++;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen}
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainenvoid io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen{
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct io_list **list;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen struct epoll_event event;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen int ret, op;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen bool last;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen list = array_idx_modifyable(&ctx->fd_index, io->fd);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen last = iolist_del(*list, io);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen event.data.ptr = *list;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen event.events = epoll_event_mask(*list);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen op = last ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen ret = epoll_ctl(ctx->epfd, op, io->fd, &event);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (ret < 0 && errno != EBADF) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_fatal("io_loop_handle_remove: epoll_ctl(%d, %d): %m",
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen op, io->fd);
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen }
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen ctx->events_pos--;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenvoid io_loop_handler_run(struct ioloop *ioloop)
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct epoll_event *event;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen struct io_list *list;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct io *io;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct timeval tv;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen unsigned int t_id;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int msecs, ret, i;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen bool call;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* get the time left for next timeout task */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen msecs = io_loop_get_wait_time(ioloop->timeouts, &tv, NULL);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen ret = epoll_wait(ctx->epfd, ctx->events, ctx->events_size, msecs);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ret < 0 && errno != EINTR)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_fatal("epoll_wait(): %m");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* execute timeout handlers */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen io_loop_handle_timeouts(ioloop);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ret <= 0 || !ioloop->running) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* No events */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen event = ctx->events;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen while (ret-- > 0) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen list = event->data.ptr;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen io = list->ios[i];
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (io == NULL)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen continue;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen call = FALSE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if ((event->events & (EPOLLHUP | EPOLLERR)) != 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen call = TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else if ((io->condition & IO_READ) != 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen call = (event->events & EPOLLIN) != 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else if ((io->condition & IO_WRITE) != 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen call = (event->events & EPOLLOUT) != 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else if ((io->condition & IO_ERROR) != 0)
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen call = (event->events & IO_EPOLL_ERROR) != 0;
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen if (call) {
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen t_id = t_push();
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen io->callback(io->context);
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen if (t_pop() != t_id) {
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen i_panic("Leaked a t_pop() call in "
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen "I/O handler %p",
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen (void *)io->callback);
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen }
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen }
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen }
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen event++;
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen }
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen}
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen#endif /* IOLOOP_EPOLL */
75bf6f49f6b8ee403f26a609d5c0c726a3262c54Timo Sirainen