ioloop-kqueue.c revision ac042a14c663acdc16e98946ed22d53c3bfbd4fa
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen * BSD kqueue() based ioloop handler.
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen * Copyright (c) 2005 Vaclav Haisman <v.haisman@sh.cvut.cz>
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen * This library is free software; you can redistribute it and/or modify
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen * it under the terms of the GNU Lesser General Public License as published
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen * by the Free Software Foundation; either version 2 of the License, or
1c4f8e4c4e5f3a5f05692a2d5c57f96a5b612f3dTimo Sirainen * (at your option) any later version.
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen/* @UNSAFE: whole file */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenvoid io_loop_handler_init(struct ioloop *ioloop)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen p_new(ioloop->pool, struct ioloop_handler_context, 1);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen ctx->evbuf = p_new(ioloop->pool, struct kevent, ctx->evbuf_size);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen ctx->fds = p_new(ioloop->pool, struct fdrecord, ctx->fds_size);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenvoid io_loop_handler_deinit(struct ioloop *ioloop)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen p_free(ioloop->pool, ioloop->handler_context->evbuf);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen p_free(ioloop->pool, ioloop->handler_context->fds);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen p_free(ioloop->pool, ioloop->handler_context);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenvoid io_loop_handle_add(struct ioloop *ioloop, struct io *io)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct kevent ev = { fd, 0, EV_ADD | EV_EOF, 0, 0, NULL };
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen enum io_condition condition = io->condition & MASK;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen /* grow ctx->fds array if necessary */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen ctx->fds_size = nearest_power((unsigned int)fd+1);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen i_assert(ctx->fds_size < (size_t)-1 / sizeof(int));
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sizeof(struct fdrecord) * (ctx->fds_size - old_size));
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenvoid io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct kevent ev = { fd, 0, EV_DELETE, 0, 0, NULL };
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen const enum io_condition condition = io->condition & MASK;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if ((fds[fd].mode & (IO_READ | IO_ERROR)) == 0)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if ((fds[fd].mode & (IO_WRITE | IO_ERROR)) == 0)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenvoid io_loop_handler_run(struct ioloop *ioloop)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ioloop_handler_context *ctx = ioloop->handler_context;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen unsigned int t_id;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen /* get the time left for next timeout task */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen msecs = io_loop_get_wait_time(ioloop->timeouts, &tv, NULL);
1c4f8e4c4e5f3a5f05692a2d5c57f96a5b612f3dTimo Sirainen /* wait for events */
1c4f8e4c4e5f3a5f05692a2d5c57f96a5b612f3dTimo Sirainen ret = kevent (ctx->kq, NULL, 0, ctx->evbuf, ctx->evbuf_size, &ts);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen /* execute timeout handlers */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen /* no I/O events */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen /* loop through all received events */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen for (i = 0; i < ret; ++i) {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen i_assert(ctx->evbuf[i].ident < ctx->fds_size);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if ((ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR) &&
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct io *errio = ctx->fds[ctx->evbuf[i].ident].errio;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen " in I/O handler %p",
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen " in I/O handler %p",