ioloop-epoll.c revision c8920d5f3df9663668ccd6412218eb28008f4e9a
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2004-2016 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen#include "lib.h"
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen#include "array.h"
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen#include "fd-close-on-exec.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "ioloop-private.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "ioloop-iolist.h"
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen#ifdef IOLOOP_EPOLL
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen
82fb1ead38f4e1197993adb2f9c12e26531e9c92Timo Sirainen#include <sys/epoll.h>
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainen#include <unistd.h>
2f7c73483ff5474a74a83a646f82e1b60f687680Aki Tuomi
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainenstruct ioloop_handler_context {
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen int epfd;
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainen unsigned int deleted_count;
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainen ARRAY(struct io_list *) fd_index;
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen ARRAY(struct epoll_event) events;
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen};
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainen
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainenvoid io_loop_handler_init(struct ioloop *ioloop, unsigned int initial_fd_count)
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct ioloop_handler_context *ctx;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ioloop->handler_context = ctx = i_new(struct ioloop_handler_context, 1);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
7fa573e6ea36024f618492e7d3649a69c1b41028Timo Sirainen i_array_init(&ctx->events, initial_fd_count);
7fa573e6ea36024f618492e7d3649a69c1b41028Timo Sirainen i_array_init(&ctx->fd_index, initial_fd_count);
7fa573e6ea36024f618492e7d3649a69c1b41028Timo Sirainen
5a9e240ebf8d0daaf029973973b52e415148070bTimo Sirainen ctx->epfd = epoll_create(initial_fd_count);
5a9e240ebf8d0daaf029973973b52e415148070bTimo Sirainen if (ctx->epfd < 0) {
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen if (errno != EMFILE)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("epoll_create(): %m");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen else {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("epoll_create(): %m (you may need to increase "
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "/proc/sys/fs/epoll/max_user_instances)");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen }
a05fec120ecd8c4ed6331c42100cba42adf22893Stephan Bosch fd_close_on_exec(ctx->epfd, TRUE);
a05fec120ecd8c4ed6331c42100cba42adf22893Stephan Bosch}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid io_loop_handler_deinit(struct ioloop *ioloop)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen struct io_list **list;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen unsigned int i, count;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch list = array_get_modifiable(&ctx->fd_index, &count);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch for (i = 0; i < count; i++)
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch i_free(list[i]);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch if (close(ctx->epfd) < 0)
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch i_error("close(epoll) failed: %m");
8ac6623677005256bf99ab33a2ed98c69c1d656cStephan Bosch array_free(&ioloop->handler_context->fd_index);
f32d0295c90ed810889504cdfa5e1a25a415f65fStephan Bosch array_free(&ioloop->handler_context->events);
04eb0abcf8f8b0c014499b5c5bae89484553613fStephan Bosch i_free(ioloop->handler_context);
04eb0abcf8f8b0c014499b5c5bae89484553613fStephan Bosch}
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch#define IO_EPOLL_ERROR (EPOLLERR | EPOLLHUP)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#define IO_EPOLL_INPUT (EPOLLIN | EPOLLPRI | IO_EPOLL_ERROR)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#define IO_EPOLL_OUTPUT (EPOLLOUT | IO_EPOLL_ERROR)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenstatic int epoll_event_mask(struct io_list *list)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen int events = 0, i;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen struct io_file *io;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
529944a3554da75c2e6231a25fe489d815519b22Stephan Bosch io = list->ios[i];
f32d0295c90ed810889504cdfa5e1a25a415f65fStephan Bosch
8ac6623677005256bf99ab33a2ed98c69c1d656cStephan Bosch if (io == NULL)
f32d0295c90ed810889504cdfa5e1a25a415f65fStephan Bosch continue;
04eb0abcf8f8b0c014499b5c5bae89484553613fStephan Bosch
04eb0abcf8f8b0c014499b5c5bae89484553613fStephan Bosch if (io->io.condition & IO_READ)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen events |= IO_EPOLL_INPUT;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (io->io.condition & IO_WRITE)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen events |= IO_EPOLL_OUTPUT;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (io->io.condition & IO_ERROR)
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch events |= IO_EPOLL_ERROR;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen return events;
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen}
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainenvoid io_loop_handle_add(struct io_file *io)
6303191abcb37164f435ccdc56e9dbddf1288851Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct ioloop_handler_context *ctx = io->io.ioloop->handler_context;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct io_list **list;
fd3d068169c6ec587c9c446f2ee45560a444334aTimo Sirainen struct epoll_event event;
fd3d068169c6ec587c9c446f2ee45560a444334aTimo Sirainen int op;
fd3d068169c6ec587c9c446f2ee45560a444334aTimo Sirainen bool first;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen list = array_idx_modifiable(&ctx->fd_index, io->fd);
6d24551e169c0808695db35d7a228f1970a84c75Timo Sirainen if (*list == NULL)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen *list = i_new(struct io_list, 1);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen first = ioloop_iolist_add(*list, io);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen memset(&event, 0, sizeof(event));
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen event.data.ptr = *list;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen event.events = epoll_event_mask(*list);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen op = first ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (errno == EPERM && op == EPOLL_CTL_ADD) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen i_panic("epoll_ctl(add, %d) failed: %m "
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen "(fd doesn't support epoll%s)", io->fd,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen io->fd != STDIN_FILENO ? "" :
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen " - instead of '<file', try 'cat file|'");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
46ec792dd4ccf6c34706c4774228301fafde6aa9Timo Sirainen i_panic("epoll_ctl(%s, %d) failed: %m",
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen op == EPOLL_CTL_ADD ? "add" : "mod", io->fd);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (first) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* allow epoll_wait() to return the maximum number of events
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen by keeping space allocated for each file descriptor */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ctx->deleted_count > 0)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen ctx->deleted_count--;
2b96880f2d789d125aff6a95eaa7b51f558a6a1cTimo Sirainen else
ae797f3368ebb86e7786ca25d7c9c703f672b9f5Timo Sirainen array_append_zero(&ctx->events);
ae797f3368ebb86e7786ca25d7c9c703f672b9f5Timo Sirainen }
edfdc577ffe7408fd6463eb9dba11260d380ab53Timo Sirainen}
b84eff65e25ae86dfd6f798386577209b94838c6Timo Sirainen
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainenvoid io_loop_handle_remove(struct io_file *io, bool closed)
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen{
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen struct ioloop_handler_context *ctx = io->io.ioloop->handler_context;
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen struct io_list **list;
97db4761382024093f441e4bc78ba8b6a056504dTimo Sirainen struct epoll_event event;
b045b66988bfbaa2795791e42ee724fae6f0db1cAki Tuomi int op;
b045b66988bfbaa2795791e42ee724fae6f0db1cAki Tuomi bool last;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen list = array_idx_modifiable(&ctx->fd_index, io->fd);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen last = ioloop_iolist_del(*list, io);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (!closed) {
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen memset(&event, 0, sizeof(event));
64e244defe74f513ce94f33d000a048ddbe2ea23Timo Sirainen event.data.ptr = *list;
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen event.events = epoll_event_mask(*list);
325d17cdbb7a338f7c413788f5e8e42d2e80a7f8Timo Sirainen
009217abb57a24a4076092e8e4e165545747839eStephan Bosch op = last ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
97db4761382024093f441e4bc78ba8b6a056504dTimo Sirainen const char *errstr = t_strdup_printf(
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen "epoll_ctl(%s, %d) failed: %m",
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen op == EPOLL_CTL_DEL ? "del" : "mod", io->fd);
fe791e96fdf796f7d8997ee0515b163dc5eddd72Aki Tuomi if (errno == EBADF)
b6fbc235f981b10333403e2fd6d333fd351c7a3cAki Tuomi i_panic("%s", errstr);
b6fbc235f981b10333403e2fd6d333fd351c7a3cAki Tuomi else
a8dac1be6a0c3adbbce5887ca395f418194c6c06Aki Tuomi i_error("%s", errstr);
53f97800b16ab3a8d263c5331132dec1e8fea9a0Aki Tuomi }
bf72c930996df0691932fb1143f360d260f27a06Timo Sirainen }
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen if (last) {
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen /* since we're not freeing memory in any case, just increase
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen deleted counter so next handle_add() can just decrease it
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen insteading of appending to the events array */
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen ctx->deleted_count++;
5a9e240ebf8d0daaf029973973b52e415148070bTimo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_free(io);
bbba7d0fce1b6ce5baa2d7ef946eb1b63e2ab518Timo Sirainen}
bbba7d0fce1b6ce5baa2d7ef946eb1b63e2ab518Timo Sirainen
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainenvoid io_loop_handler_run_internal(struct ioloop *ioloop)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen struct epoll_event *events;
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen const struct epoll_event *event;
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen struct io_list *list;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct io_file *io;
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen struct timeval tv;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen unsigned int events_count;
a75907609d7c410c9e17beedfafbf28b4439fa8aTimo Sirainen int msecs, ret, i, j;
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen bool call;
aebfda1f6e3a924c31e8f54237b81fabf4b2264cTimo Sirainen
2dfd08e8aa16dfcc975d8a62bc8d20b2ef849d71Timo Sirainen /* get the time left for next timeout task */
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen msecs = io_loop_get_wait_time(ioloop, &tv);
38cb3d139aefb7c65919cf4aba5ded7b5fd50e6fTimo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen events = array_get_modifiable(&ctx->events, &events_count);
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen if (ioloop->io_files != NULL && events_count > ctx->deleted_count) {
bf72c930996df0691932fb1143f360d260f27a06Timo Sirainen ret = epoll_wait(ctx->epfd, events, events_count, msecs);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ret < 0 && errno != EINTR)
843640f0ca224bb9999acb290bca5f76037ab984Timo Sirainen i_fatal("epoll_wait(): %m");
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch } else {
087939d3fa9c4056419386c9d6c81f147de534cdTimo Sirainen /* no I/Os, but we should have some timeouts.
02ccba3d3be96444abd15b5254864c9151bbeb30Timo Sirainen just wait for them. */
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen if (msecs < 0)
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen i_panic("BUG: No IOs or timeouts set. Not waiting for infinity.");
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen usleep(msecs*1000);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen ret = 0;
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen }
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen /* execute timeout handlers */
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen io_loop_handle_timeouts(ioloop);
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen
ec9429535e925610513bd6bfde6729e273082ccbTimo Sirainen if (!ioloop->running)
ec9429535e925610513bd6bfde6729e273082ccbTimo Sirainen return;
ec9429535e925610513bd6bfde6729e273082ccbTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen for (i = 0; i < ret; i++) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* io_loop_handle_add() may cause events array reallocation,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen so we have use array_idx() */
1a1159e589def1e32b7dc25397f15146672ef73eTimo Sirainen event = array_idx(&ctx->events, i);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen list = event->data.ptr;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen for (j = 0; j < IOLOOP_IOLIST_IOS_PER_FD; j++) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen io = list->ios[j];
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (io == NULL)
56af9dd10e7e6caeaca64395bad3f882b28ecdffTimo Sirainen continue;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen call = FALSE;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if ((event->events & (EPOLLHUP | EPOLLERR)) != 0)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen call = TRUE;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen else if ((io->io.condition & IO_READ) != 0)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen call = (event->events & EPOLLIN) != 0;
6d24551e169c0808695db35d7a228f1970a84c75Timo Sirainen else if ((io->io.condition & IO_WRITE) != 0)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen call = (event->events & EPOLLOUT) != 0;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen else if ((io->io.condition & IO_ERROR) != 0)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen call = (event->events & IO_EPOLL_ERROR) != 0;
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen if (call)
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen io_loop_call_io(&io->io);
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen }
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen }
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen}
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen#endif /* IOLOOP_EPOLL */
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen