ioloop-epoll.c revision a912d084eb8024ce35462c9fd2d50b86b13d8d33
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Linux epoll() based ioloop handler.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * This library is free software; you can redistribute it and/or modify
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * it under the terms of the GNU Lesser General Public License as published
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * by the Free Software Foundation; either version 2 of the License, or
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * (at your option) any later version.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* @UNSAFE: whole file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid io_loop_handler_init(struct ioloop *ioloop)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_new(ioloop->pool, struct ioloop_handler_context, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->events = p_new(ioloop->pool, struct epoll_event,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->fd_index = p_new(ioloop->pool, struct io_list *, ctx->idx_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->epfd = epoll_create(INITIAL_EPOLL_EVENTS);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid io_loop_handler_deinit(struct ioloop *ioloop)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen p_free(ioloop->pool, ioloop->handler_context->events);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen p_free(ioloop->pool, ioloop->handler_context->fd_index);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen p_free(ioloop->pool, ioloop->handler_context);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen#define IO_EPOLL_INPUT (EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP)
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen#define IO_EPOLL_OUTPUT (EPOLLOUT | EPOLLERR | EPOLLHUP)
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainenstatic int epoll_event_mask(struct io_list *list)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int iolist_add(struct io_list *list, struct io *io)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(list->ios[EPOLL_LIST_INPUT] == NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(list->ios[EPOLL_LIST_OUTPUT] == NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int iolist_del(struct io_list *list, struct io *io)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid io_loop_handle_add(struct ioloop *ioloop, struct io *io)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* grow the fd -> iolist array */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->idx_size = nearest_power((unsigned int) fd+1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(ctx->idx_size < (size_t)-1 / sizeof(int));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->fd_index = p_realloc(ioloop->pool, ctx->fd_index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sizeof(int) * old_size,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->events_size = nearest_power(ctx->events_size + 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->events = p_new(ioloop->pool, struct epoll_event,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = epoll_ctl(ctx->epfd, op, io->fd, &event);
unsigned int t_id;
while (ret-- > 0) {
for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
if (call) {
event++;