[dovecot-cvs] dovecot/src/lib Makefile.am, 1.62.2.1, 1.62.2.2 ioloop-epoll.c, 1.11.2.1, 1.11.2.2 ioloop-internal.h, 1.16, 1.16.2.1 ioloop-iolist.c, NONE, 1.1.2.1 ioloop-iolist.h, NONE, 1.1.2.1 ioloop-kqueue.c, 1.4.2.1, 1.4.2.2 ioloop-notify-kqueue.c, 1.3, 1.3.2.1 ioloop-poll.c, 1.32, 1.32.2.1
cras at dovecot.org
cras at dovecot.org
Wed Aug 16 18:54:59 EEST 2006
- Previous message: [dovecot-cvs] dovecot configure.in,1.303,1.304
- Next message: [dovecot-cvs] dovecot/src/lib Makefile.am, 1.65, 1.66 ioloop-epoll.c, 1.13, 1.14 ioloop-internal.h, 1.16, 1.17 ioloop-iolist.c, 1.1, 1.2 ioloop-iolist.h, 1.1, 1.2 ioloop-kqueue.c, 1.5, 1.6 ioloop-notify-kqueue.c, 1.3, 1.4 ioloop-poll.c, 1.32, 1.33
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /var/lib/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv9264
Modified Files:
Tag: branch_1_0
Makefile.am ioloop-epoll.c ioloop-internal.h ioloop-kqueue.c
ioloop-notify-kqueue.c ioloop-poll.c
Added Files:
Tag: branch_1_0
ioloop-iolist.c ioloop-iolist.h
Log Message:
Rewrote much of the kqueue code. It didn't work correctly if there were both
input and output I/O handlers added for the same file descriptor. The code
works now very much like epoll code. Did also several cleanups.
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.62.2.1
retrieving revision 1.62.2.2
diff -u -d -r1.62.2.1 -r1.62.2.2
--- Makefile.am 17 Jun 2006 16:24:54 -0000 1.62.2.1
+++ Makefile.am 16 Aug 2006 15:54:56 -0000 1.62.2.2
@@ -32,6 +32,7 @@
istream-mmap.c \
istream-seekable.c \
ioloop.c \
+ ioloop-iolist.c \
ioloop-notify-none.c \
ioloop-notify-dn.c \
ioloop-notify-inotify.c \
@@ -114,6 +115,7 @@
istream-internal.h \
istream-seekable.h \
ioloop.h \
+ ioloop-iolist.h \
ioloop-internal.h \
lib.h \
lib-signals.h \
Index: ioloop-epoll.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-epoll.c,v
retrieving revision 1.11.2.1
retrieving revision 1.11.2.2
diff -u -d -r1.11.2.1 -r1.11.2.2
--- ioloop-epoll.c 16 Jun 2006 10:38:27 -0000 1.11.2.1
+++ ioloop-epoll.c 16 Aug 2006 15:54:56 -0000 1.11.2.2
@@ -6,39 +6,23 @@
* This software is released under the MIT license.
*/
-/* @UNSAFE: whole file */
-
#include "lib.h"
#include "array.h"
#include "fd-close-on-exec.h"
#include "ioloop-internal.h"
+#include "ioloop-iolist.h"
#ifdef IOLOOP_EPOLL
#include <sys/epoll.h>
#include <unistd.h>
-#define INITIAL_EPOLL_EVENTS 128
-
-enum {
- EPOLL_LIST_INPUT,
- EPOLL_LIST_OUTPUT,
- EPOLL_LIST_ERROR,
-
- EPOLL_IOS_PER_FD
-};
-
struct ioloop_handler_context {
int epfd;
- int events_size, events_pos;
- struct epoll_event *events;
- unsigned int idx_size;
+ unsigned int deleted_count;
array_t ARRAY_DEFINE(fd_index, struct io_list *);
-};
-
-struct io_list {
- struct io *ios[EPOLL_IOS_PER_FD];
+ array_t ARRAY_DEFINE(events, struct epoll_event);
};
void io_loop_handler_init(struct ioloop *ioloop)
@@ -48,16 +32,12 @@
ioloop->handler_context = ctx =
p_new(ioloop->pool, struct ioloop_handler_context, 1);
- ctx->events_pos = 0;
- ctx->events_size = INITIAL_EPOLL_EVENTS;
- ctx->events = p_new(ioloop->pool, struct epoll_event,
- ctx->events_size);
-
- ctx->idx_size = INITIAL_EPOLL_EVENTS;
+ ARRAY_CREATE(&ctx->events, ioloop->pool, struct epoll_event,
+ IOLOOP_INITIAL_FD_COUNT);
ARRAY_CREATE(&ctx->fd_index, ioloop->pool,
- struct io_list *, ctx->idx_size);
+ struct io_list *, IOLOOP_INITIAL_FD_COUNT);
- ctx->epfd = epoll_create(INITIAL_EPOLL_EVENTS);
+ ctx->epfd = epoll_create(IOLOOP_INITIAL_FD_COUNT);
if (ctx->epfd < 0)
i_fatal("epoll_create(): %m");
fd_close_on_exec(ctx->epfd, TRUE);
@@ -70,7 +50,7 @@
if (close(ctx->epfd) < 0)
i_error("close(epoll) failed: %m");
array_free(&ioloop->handler_context->fd_index);
- p_free(ioloop->pool, ioloop->handler_context->events);
+ array_free(&ioloop->handler_context->events);
p_free(ioloop->pool, ioloop->handler_context);
}
@@ -83,7 +63,7 @@
int events = 0, i;
struct io *io;
- for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
+ for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
io = list->ios[i];
if (io == NULL)
@@ -100,80 +80,38 @@
return events;
}
-static bool iolist_add(struct io_list *list, struct io *io)
-{
- int i, idx;
-
- if ((io->condition & IO_READ) != 0)
- idx = EPOLL_LIST_INPUT;
- else if ((io->condition & IO_WRITE) != 0)
- idx = EPOLL_LIST_OUTPUT;
- else if ((io->condition & IO_ERROR) != 0)
- idx = EPOLL_LIST_ERROR;
- else {
- i_unreached();
- }
-
- i_assert(list->ios[idx] == NULL);
- list->ios[idx] = io;
-
- /* check if this was the first one */
- for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
- if (i != idx && list->ios[i] != NULL)
- return FALSE;
- }
-
- return TRUE;
-}
-
-static bool iolist_del(struct io_list *list, struct io *io)
-{
- bool last = TRUE;
- int i;
-
- for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
- if (list->ios[i] != NULL) {
- if (list->ios[i] == io)
- list->ios[i] = NULL;
- else
- last = FALSE;
- }
- }
- return last;
-}
-
void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct io_list **list;
struct epoll_event event;
- int ret, op, fd = io->fd;
+ int op;
bool first;
- list = array_idx_modifyable(&ctx->fd_index, fd);
+ list = array_idx_modifyable(&ctx->fd_index, io->fd);
if (*list == NULL)
*list = p_new(ioloop->pool, struct io_list, 1);
- first = iolist_add(*list, io);
+ first = ioloop_iolist_add(*list, io);
event.data.ptr = *list;
event.events = epoll_event_mask(*list);
op = first ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
- ret = epoll_ctl(ctx->epfd, op, fd, &event);
- if (ret < 0)
- i_fatal("io_loop_handle_add: epoll_ctl(%d, %d): %m", op, fd);
-
- if (ctx->events_pos >= ctx->events_size) {
- ctx->events_size = nearest_power(ctx->events_size + 1);
-
- p_free(ioloop->pool, ctx->events);
- ctx->events = p_new(ioloop->pool, struct epoll_event,
- ctx->events_size);
+ if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
+ i_fatal("io_loop_handle_add: epoll_ctl(%d, %d): %m",
+ op, io->fd);
}
- ctx->events_pos++;
+ if (first) {
+ /* allow epoll_wait() to return the maximum number of events
+ by keeping space allocated for each file descriptor */
+ if (ctx->deleted_count > 0)
+ ctx->deleted_count--;
+ else
+ (void)array_append_space(&ctx->events);
+ }
}
void io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
@@ -181,24 +119,28 @@
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct io_list **list;
struct epoll_event event;
- int ret, op;
+ int op;
bool last;
list = array_idx_modifyable(&ctx->fd_index, io->fd);
- last = iolist_del(*list, io);
+ last = ioloop_iolist_del(*list, io);
event.data.ptr = *list;
event.events = epoll_event_mask(*list);
op = last ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
- ret = epoll_ctl(ctx->epfd, op, io->fd, &event);
- if (ret < 0 && errno != EBADF) {
- i_fatal("io_loop_handle_remove: epoll_ctl(%d, %d): %m",
+ if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
+ i_error("io_loop_handle_remove: epoll_ctl(%d, %d): %m",
op, io->fd);
}
- ctx->events_pos--;
+ if (last) {
+ /* since we're not freeing memory in any case, just increase
+ deleted counter so next handle_add() can just decrease it
+ insteading of appending to the events array */
+ ctx->deleted_count++;
+ }
}
void io_loop_handler_run(struct ioloop *ioloop)
@@ -208,14 +150,15 @@
struct io_list *list;
struct io *io;
struct timeval tv;
- unsigned int t_id;
+ unsigned int events_count, t_id;
int msecs, ret, i;
bool call;
/* get the time left for next timeout task */
msecs = io_loop_get_wait_time(ioloop->timeouts, &tv, NULL);
- ret = epoll_wait(ctx->epfd, ctx->events, ctx->events_size, msecs);
+ event = array_get_modifyable(&ctx->events, &events_count);
+ ret = epoll_wait(ctx->epfd, event, events_count, msecs);
if (ret < 0 && errno != EINTR)
i_fatal("epoll_wait(): %m");
@@ -227,11 +170,10 @@
return;
}
- event = ctx->events;
while (ret-- > 0) {
list = event->data.ptr;
- for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
+ for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
io = list->ios[i];
if (io == NULL)
continue;
Index: ioloop-internal.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-internal.h,v
retrieving revision 1.16
retrieving revision 1.16.2.1
diff -u -d -r1.16 -r1.16.2.1
--- ioloop-internal.h 29 Jan 2006 10:55:22 -0000 1.16
+++ ioloop-internal.h 16 Aug 2006 15:54:56 -0000 1.16.2.1
@@ -3,6 +3,10 @@
#include "ioloop.h"
+#ifndef IOLOOP_INITIAL_FD_COUNT
+# define IOLOOP_INITIAL_FD_COUNT 128
+#endif
+
struct ioloop {
struct ioloop *prev;
--- NEW FILE: ioloop-iolist.c ---
/*
* Copyright (c) 2004 Andrey Panin <pazke at donpac.ru>
*
* This software is released under the MIT license.
*/
#include "lib.h"
#include "ioloop-internal.h"
#include "ioloop-iolist.h"
bool ioloop_iolist_add(struct io_list *list, struct io *io)
{
int i, idx;
if ((io->condition & IO_READ) != 0)
idx = IOLOOP_IOLIST_INPUT;
else if ((io->condition & IO_WRITE) != 0)
idx = IOLOOP_IOLIST_OUTPUT;
else if ((io->condition & IO_ERROR) != 0)
idx = IOLOOP_IOLIST_ERROR;
else {
i_unreached();
}
i_assert(list->ios[idx] == NULL);
list->ios[idx] = io;
/* check if this was the first one */
for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
if (i != idx && list->ios[i] != NULL)
return FALSE;
}
return TRUE;
}
bool ioloop_iolist_del(struct io_list *list, struct io *io)
{
bool last = TRUE;
int i;
for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
if (list->ios[i] != NULL) {
if (list->ios[i] == io)
list->ios[i] = NULL;
else
last = FALSE;
}
}
return last;
}
--- NEW FILE: ioloop-iolist.h ---
#ifndef __IOLOOP_IOLIST_H
#define __IOLOOP_IOLIST_H
enum {
IOLOOP_IOLIST_INPUT,
IOLOOP_IOLIST_OUTPUT,
IOLOOP_IOLIST_ERROR,
IOLOOP_IOLIST_IOS_PER_FD
};
struct io_list {
struct io *ios[IOLOOP_IOLIST_IOS_PER_FD];
};
bool ioloop_iolist_add(struct io_list *list, struct io *io);
bool ioloop_iolist_del(struct io_list *list, struct io *io);
#endif
Index: ioloop-kqueue.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-kqueue.c,v
retrieving revision 1.4.2.1
retrieving revision 1.4.2.2
diff -u -d -r1.4.2.1 -r1.4.2.2
--- ioloop-kqueue.c 10 May 2006 15:48:04 -0000 1.4.2.1
+++ ioloop-kqueue.c 16 Aug 2006 15:54:56 -0000 1.4.2.2
@@ -9,38 +9,27 @@
* (at your option) any later version.
*/
-/* @UNSAFE: whole file */
-
#include "lib.h"
#ifdef IOLOOP_KQUEUE
+#include "array.h"
#include "fd-close-on-exec.h"
#include "ioloop-internal.h"
+#include "ioloop-iolist.h"
+
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
-#ifndef INITIAL_BUF_SIZE
-# define INITIAL_BUF_SIZE 128
-#endif
-
-#define MASK (IO_READ | IO_WRITE | IO_ERROR)
-
struct ioloop_handler_context {
int kq;
- size_t evbuf_size;
- struct kevent *evbuf;
-
- size_t fds_size;
- struct fdrecord *fds;
-};
-struct fdrecord {
- struct io *errio;
- enum io_condition mode;
+ unsigned int deleted_count;
+ array_t ARRAY_DEFINE(fd_index, struct io_list *);
+ array_t ARRAY_DEFINE(events, struct kevent);
};
void io_loop_handler_init(struct ioloop *ioloop)
@@ -50,117 +39,119 @@
ioloop->handler_context = ctx =
p_new(ioloop->pool, struct ioloop_handler_context, 1);
- ctx->evbuf_size = INITIAL_BUF_SIZE;
- ctx->evbuf = p_new(ioloop->pool, struct kevent, ctx->evbuf_size);
ctx->kq = kqueue();
if (ctx->kq < 0)
i_fatal("kqueue() in io_loop_handler_init() failed: %m");
fd_close_on_exec(ctx->kq, TRUE);
- ctx->fds_size = INITIAL_BUF_SIZE;
- ctx->fds = p_new(ioloop->pool, struct fdrecord, ctx->fds_size);
+ ARRAY_CREATE(&ctx->events, ioloop->pool, struct kevent,
+ IOLOOP_INITIAL_FD_COUNT);
+ ARRAY_CREATE(&ctx->fd_index, ioloop->pool,
+ struct io_list *, IOLOOP_INITIAL_FD_COUNT);
}
void io_loop_handler_deinit(struct ioloop *ioloop)
{
if (close(ioloop->handler_context->kq) < 0)
i_error("close(kqueue) in io_loop_handler_deinit() failed: %m");
- p_free(ioloop->pool, ioloop->handler_context->evbuf);
- p_free(ioloop->pool, ioloop->handler_context->fds);
+ array_free(&ioloop->handler_context->fd_index);
+ array_free(&ioloop->handler_context->events);
p_free(ioloop->pool, ioloop->handler_context);
}
-void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
+static int io_filter(struct io *io)
{
- struct ioloop_handler_context *ctx = ioloop->handler_context;
- const int fd = io->fd;
- struct kevent ev = { fd, 0, EV_ADD, 0, 0, NULL };
- enum io_condition condition = io->condition & MASK;
-
- i_assert(io->callback != NULL);
+ int filter = 0;
- /* grow ctx->fds array if necessary */
- if ((size_t)fd >= ctx->fds_size) {
- size_t old_size = ctx->fds_size;
+ if ((io->condition & (IO_READ | IO_ERROR)) != 0)
+ filter |= EVFILT_READ;
+ if ((io->condition & (IO_WRITE | IO_ERROR)) != 0)
+ filter |= EVFILT_WRITE;
- ctx->fds_size = nearest_power((unsigned int)fd+1);
- i_assert(ctx->fds_size < (size_t)-1 / sizeof(int));
+ return filter;
+}
- ctx->fds = p_realloc(ioloop->pool, ctx->fds,
- sizeof(struct fdrecord) * old_size,
- sizeof(struct fdrecord) * ctx->fds_size);
- memset(ctx->fds + old_size, 0,
- sizeof(struct fdrecord) * (ctx->fds_size - old_size));
- }
+static int io_list_filter(struct io_list *list)
+{
+ int filter = 0, i;
+ struct io *io;
- if (condition & (IO_READ | IO_WRITE))
- ev.udata = io;
- if (condition & IO_ERROR)
- ctx->fds[fd].errio = io;
+ for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
+ io = list->ios[i];
- if (condition & (IO_READ | IO_ERROR)) {
- ctx->fds[fd].mode |= condition;
- ev.filter = EVFILT_READ;
- if (!(condition & ~IO_ERROR))
- ev.flags |= EV_CLEAR;
- if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
- i_error("kevent(%d) in io_loop_handle_add() failed: %m",
- fd);
- }
+ if (io == NULL)
+ continue;
+
+ if ((io->condition & (IO_READ | IO_ERROR)) != 0)
+ filter |= EVFILT_READ;
+ if ((io->condition & (IO_WRITE | IO_ERROR)) != 0)
+ filter |= EVFILT_WRITE;
}
- if (condition & (IO_WRITE | IO_ERROR)) {
- ctx->fds[fd].mode |= condition;
- ev.filter = EVFILT_WRITE;
- if (!(condition & ~IO_ERROR))
- ev.flags |= EV_CLEAR;
- if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
- i_error("kevent(%d) in io_loop_handle_add() failed: %m",
- fd);
- }
+
+ return filter;
+}
+
+void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
+{
+ struct ioloop_handler_context *ctx = ioloop->handler_context;
+ struct io_list **list;
+ struct kevent ev;
+ bool first;
+
+ list = array_idx_modifyable(&ctx->fd_index, io->fd);
+ if (*list == NULL)
+ *list = p_new(ioloop->pool, struct io_list, 1);
+
+ first = ioloop_iolist_add(*list, io);
+
+ EV_SET(ev, io->fd, io_filter(io), EV_ADD, 0, 0, *list);
+ if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
+ i_fatal("kevent(EV_ADD, %d) failed: %m", io->fd);
+
+ if (first) {
+ /* allow kevent() to return the maximum number of events
+ by keeping space allocated for each file descriptor */
+ if (ctx->deleted_count > 0)
+ ctx->deleted_count--;
+ else
+ (void)array_append_space(&ctx->events);
}
}
void io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
- const int fd = io->fd;
- struct kevent ev = { fd, 0, EV_DELETE, 0, 0, NULL };
- struct fdrecord *const fds = ctx->fds;
- const enum io_condition condition = io->condition & MASK;
+ struct io_list **list;
+ struct kevent ev;
+ int filter;
+ bool last;
+
+ list = array_idx_modifyable(&ctx->fd_index, io->fd);
+ last = ioloop_iolist_del(*list, io);
- i_assert((size_t)fd < ctx->fds_size);
+ filter = io_filter(io) & ~io_list_filter(*list);
+ EV_SET(ev, io->fd, filter, EV_DELETE, 0, 0, *list);
+ if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
+ i_error("kevent(EV_DELETE, %d) failed: %m", io->fd);
- if (condition & IO_ERROR)
- fds[fd].errio = NULL;
- if (condition & (IO_READ | IO_ERROR)) {
- ev.filter = EVFILT_READ;
- fds[fd].mode &= ~condition;
- if ((fds[fd].mode & (IO_READ | IO_ERROR)) == 0) {
- if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
- i_error("kevent(%d) in io_loop_handle_remove "
- "failed: %m", fd);
- }
- }
- }
- if (condition & (IO_WRITE | IO_ERROR)) {
- ev.filter = EVFILT_WRITE;
- fds[fd].mode &= ~condition;
- if ((fds[fd].mode & (IO_WRITE | IO_ERROR)) == 0) {
- if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
- i_error("kevent(%d) in io_loop_handle_remove "
- "failed: %m", fd);
- }
- }
+ if (last) {
+ /* since we're not freeing memory in any case, just increase
+ deleted counter so next handle_add() can just decrease it
+ insteading of appending to the events array */
+ ctx->deleted_count++;
}
}
void io_loop_handler_run(struct ioloop *ioloop)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
+ struct kevent *event;
struct timeval tv;
struct timespec ts;
- unsigned int t_id;
+ struct io_list *list;
+ unsigned int events_count, t_id;
int msecs, ret, i;
+ bool call, called;
/* get the time left for next timeout task */
msecs = io_loop_get_wait_time(ioloop->timeouts, &tv, NULL);
@@ -168,7 +159,8 @@
ts.tv_nsec = tv.tv_usec * 1000;
/* wait for events */
- ret = kevent (ctx->kq, NULL, 0, ctx->evbuf, ctx->evbuf_size, &ts);
+ event = array_get_modifyable(&ctx->events, &events_count);
+ ret = kevent (ctx->kq, NULL, 0, event, events_count, &ts);
if (ret < 0 && errno != EINTR)
i_fatal("kevent(): %m");
@@ -180,49 +172,52 @@
return;
}
- i_assert((size_t)ret <= ctx->evbuf_size);
-
/* loop through all received events */
- for (i = 0; i < ret; ++i) {
- struct io *io = ctx->evbuf[i].udata;
+ while (ret-- > 0) {
+ list = (void *)event->udata;
- i_assert(ctx->evbuf[i].ident < ctx->fds_size);
- if ((ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR) &&
- (ctx->evbuf[i].flags & (EV_EOF | EV_ERROR))) {
- struct io *errio = ctx->fds[ctx->evbuf[i].ident].errio;
+ called = FALSE;
+ for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
+ struct io *io = list->ios[i];
+ if (io == NULL)
+ continue;
- t_id = t_push();
- errio->callback(errio->context);
- if (t_pop() != t_id) {
- i_panic("Leaked a t_pop() call"
- " in I/O handler %p",
- (void *)errio->callback);
- }
- } else if (ctx->fds[ctx->evbuf[i].ident].mode
- & (IO_WRITE | IO_READ)) {
- t_id = t_push();
- io->callback(io->context);
- if (t_pop() != t_id) {
- i_panic("Leaked a t_pop() call"
- " in I/O handler %p",
- (void *)io->callback);
+ call = FALSE;
+ if ((event->flags & EV_ERROR) != 0) {
+ errno = event->data;
+ i_error("kevent(): invalid fd %d callback "
+ "%p: %m", io->fd, (void *)io->callback);
+ } else if ((event->flags & EV_EOF) != 0)
+ call = TRUE;
+ else if ((io->condition & IO_READ) != 0)
+ call = (event->filter & EVFILT_READ) != 0;
+ else if ((io->condition & IO_WRITE) != 0)
+ call = (event->filter & EVFILT_WRITE) != 0;
+
+ if (call) {
+ called = TRUE;
+ t_id = t_push();
+ io->callback(io->context);
+ if (t_pop() != t_id) {
+ i_panic("Leaked a t_pop() call in "
+ "I/O handler %p",
+ (void *)io->callback);
+ }
}
- } else if (ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR) {
- /*
- NO-OP. If the handle is registered only for
- IO_ERROR, then we can get readable/writable event
- but no IO_READ | IO_WRITE set.
- */
- } else
- i_panic("Unrecognized event: kevent {.ident = %u,"
- " .filter = 0x%04x,"
- " .flags = 0x%04x,"
- " .fflags = 0x%08x,"
- " .data = 0x%08x}\n"
- "mode: 0x%x04x", ctx->evbuf[i].ident,
- ctx->evbuf[i].filter, ctx->evbuf[i].flags,
- ctx->evbuf[i].fflags, ctx->evbuf[i].data,
- ctx->fds[ctx->evbuf[i].ident].mode);
+ }
+ if (!called) {
+ i_panic("Unrecognized event: kevent "
+ "{.ident = %d,"
+ " .filter = 0x%04x,"
+ " .flags = 0x%04x,"
+ " .fflags = 0x%08x,"
+ " .data = 0x%08llx}, io filter = %x",
+ event->ident,
+ event->filter, event->flags,
+ event->fflags, (unsigned long long)event->data,
+ io_list_filter(list));
+ }
+ event++;
}
}
Index: ioloop-notify-kqueue.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-notify-kqueue.c,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -d -r1.3 -r1.3.2.1
--- ioloop-notify-kqueue.c 29 Jan 2006 10:55:22 -0000 1.3
+++ ioloop-notify-kqueue.c 16 Aug 2006 15:54:56 -0000 1.3.2.1
@@ -33,13 +33,22 @@
struct ioloop_notify_handler_context *ctx = context;
struct io *io;
struct kevent ev;
+ struct timespec ts;
if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
i_fatal("gettimeofday() failed: %m");
ioloop_time = ioloop_timeval.tv_sec;
- if (kevent(ctx->kq, NULL, 0, &ev, 1, 0) < 0)
- i_fatal("kevent() failed: %m");
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+
+ ret = kevent(ctx->kq, NULL, 0, &ev, 1, &ts);
+ if (ret <= 0) {
+ if (ret == 0 || errno == EINTR)
+ return;
+
+ i_fatal("kevent(notify) failed: %m");
+ }
io = ev.udata;
io->callback(io->context);
}
@@ -52,7 +61,7 @@
p_new(ioloop->pool, struct ioloop_notify_handler_context, 1);
ctx->kq = kqueue();
if (ctx->kq < 0)
- i_fatal("kqueue() in io_loop_notify_handler_init() failed: %m");
+ i_fatal("kqueue(notify) failed: %m");
fd_close_on_exec(ctx->kq, TRUE);
}
@@ -73,18 +82,15 @@
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- struct kevent ev = { -1, EVFILT_VNODE, EV_ADD,
- NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND
- | NOTE_REVOKE, 0, NULL };
+ struct kevent ev;
struct io *io;
int fd;
struct stat sb;
- i_assert(callback != NULL);
-
fd = open(path, O_RDONLY);
if (fd == -1) {
- i_error("open(%s) for kq notify failed: %m", path);
+ if (errno != ENOENT)
+ i_error("open(%s) for kq notify failed: %m", path);
return NULL;
}
@@ -103,10 +109,12 @@
io->fd = fd;
io->callback = callback;
io->context = context;
- ev.ident = fd;
- ev.udata = io;
+
+ EV_SET(ev, fd, EVFILT_VNODE, EV_ADD,
+ NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_REVOKE, 0, io);
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
i_error("kevent(%d, %s) for notify failed: %m", fd, path);
+ (void)close(fd);
p_free(ioloop->pool, io);
return NULL;
}
@@ -123,14 +131,15 @@
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- struct kevent ev = { io->fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL };
+ struct kevent ev;
i_assert((io->condition & IO_NOTIFY) != 0);
+ EV_SET(ev, io->fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
if (kevent(ctx->kq, &ev, 1, NULL, 0, 0) < 0)
i_error("kevent(%d) for notify remove failed: %m", io->fd);
if (close(io->fd) < 0)
- i_error("close(%d) failed: %m", io->fd);
+ i_error("close(%d) for notify remove failed: %m", io->fd);
}
#endif
Index: ioloop-poll.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-poll.c,v
retrieving revision 1.32
retrieving revision 1.32.2.1
diff -u -d -r1.32 -r1.32.2.1
--- ioloop-poll.c 29 Jan 2006 12:21:06 -0000 1.32
+++ ioloop-poll.c 16 Aug 2006 15:54:56 -0000 1.32.2.1
@@ -10,10 +10,6 @@
#include <fcntl.h>
#include <sys/poll.h>
-#ifndef INITIAL_POLL_FDS
-# define INITIAL_POLL_FDS 128
-#endif
-
struct ioloop_handler_context {
unsigned int fds_count, fds_pos;
struct pollfd *fds;
@@ -28,10 +24,10 @@
ioloop->handler_context = ctx =
p_new(ioloop->pool, struct ioloop_handler_context, 1);
- ctx->fds_count = INITIAL_POLL_FDS;
+ ctx->fds_count = IOLOOP_INITIAL_FD_COUNT;
ctx->fds = p_new(ioloop->pool, struct pollfd, ctx->fds_count);
- ctx->idx_count = INITIAL_POLL_FDS;
+ ctx->idx_count = IOLOOP_INITIAL_FD_COUNT;
ctx->fd_index = p_new(ioloop->pool, int, ctx->idx_count);
memset(ctx->fd_index, 0xff, sizeof(int) * ctx->idx_count);
}
- Previous message: [dovecot-cvs] dovecot configure.in,1.303,1.304
- Next message: [dovecot-cvs] dovecot/src/lib Makefile.am, 1.65, 1.66 ioloop-epoll.c, 1.13, 1.14 ioloop-internal.h, 1.16, 1.17 ioloop-iolist.c, 1.1, 1.2 ioloop-iolist.h, 1.1, 1.2 ioloop-kqueue.c, 1.5, 1.6 ioloop-notify-kqueue.c, 1.3, 1.4 ioloop-poll.c, 1.32, 1.33
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list