This commit is contained in:
Florian Westphal 2006-09-16 14:49:26 +00:00
parent e426c131c7
commit f6e729443e
1 changed files with 103 additions and 68 deletions

View File

@ -12,7 +12,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: io.c,v 1.16 2006/07/23 23:11:44 alex Exp $";
static char UNUSED id[] = "$Id: io.c,v 1.17 2006/09/16 14:49:26 fw Exp $";
#include <assert.h>
#include <stdlib.h>
@ -44,8 +44,8 @@ typedef struct {
#define IO_USE_KQUEUE 1
# else
#define IO_USE_SELECT 1
#endif
#endif
# endif /* HAVE_KQUEUE */
#endif /* HAVE_EPOLL_CREATE */
static bool library_initialized;
@ -98,40 +98,10 @@ io_event_get(int fd)
}
bool
io_library_init(unsigned int eventsize)
#ifdef IO_USE_SELECT
static bool
io_library_init_select(unsigned int eventsize)
{
#if defined(IO_USE_EPOLL) || defined(IO_USE_KQUEUE)
bool ret;
#endif
#ifdef IO_USE_EPOLL
int ecreate_hint = (int)eventsize;
if (ecreate_hint <= 0)
ecreate_hint = 128;
#endif
if (library_initialized)
return true;
#ifdef IO_USE_SELECT
#ifdef FD_SETSIZE
if (eventsize >= FD_SETSIZE)
eventsize = FD_SETSIZE - 1;
#endif
#endif
if ((eventsize > 0) && !array_alloc(&io_events, sizeof(io_event), (size_t)eventsize))
eventsize = 0;
#ifdef IO_USE_EPOLL
io_masterfd = epoll_create(ecreate_hint);
Log(LOG_INFO,
"IO subsystem: epoll (hint size %d, initial maxfd %u, masterfd %d).",
ecreate_hint, eventsize, io_masterfd);
ret = io_masterfd >= 0;
if (ret) library_initialized = true;
return ret;
#endif
#ifdef IO_USE_SELECT
Log(LOG_INFO, "IO subsystem: select (initial maxfd %u).",
eventsize);
FD_ZERO(&readers);
@ -144,14 +114,38 @@ io_library_init(unsigned int eventsize)
Conf_MaxConnections = FD_SETSIZE - 1;
}
#else
Log(LOG_WARNING,
"FD_SETSIZE undefined, don't know how many descriptors select() can handle on your platform ...");
#endif /* FD_SETSIZE */
library_initialized = true;
return true;
}
#endif /* SELECT */
#ifdef IO_USE_EPOLL
static bool
io_library_init_epoll(unsigned int eventsize)
{
bool ret;
int ecreate_hint = (int)eventsize;
if (ecreate_hint <= 0)
ecreate_hint = 128;
io_masterfd = epoll_create(ecreate_hint);
Log(LOG_INFO,
"IO subsystem: epoll (hint size %d, initial maxfd %u, masterfd %d).",
ecreate_hint, eventsize, io_masterfd);
ret = io_masterfd >= 0;
if (ret) library_initialized = true;
return ret;
}
#endif
#ifdef IO_USE_KQUEUE
static bool
io_library_init_kqueue(unsigned int eventsize)
{
bool ret;
io_masterfd = kqueue();
Log(LOG_INFO,
@ -159,8 +153,35 @@ io_library_init(unsigned int eventsize)
eventsize, io_masterfd);
ret = io_masterfd >= 0;
if (ret) library_initialized = true;
return ret;
}
#endif
bool
io_library_init(unsigned int eventsize)
{
if (library_initialized)
return true;
#ifdef IO_USE_SELECT
#ifndef FD_SETSIZE
Log(LOG_WARNING,
"FD_SETSIZE undefined, don't know how many descriptors select() can handle on your platform ...");
#else
if (eventsize >= FD_SETSIZE)
eventsize = FD_SETSIZE - 1;
#endif /* FD_SETSIZE */
#endif /* IO_USE_SELECT */
if ((eventsize > 0) && !array_alloc(&io_events, sizeof(io_event), (size_t)eventsize))
eventsize = 0;
#ifdef IO_USE_EPOLL
return io_library_init_epoll(eventsize);
#endif
#ifdef IO_USE_KQUEUE
return io_library_init_kqueue(eventsize);
#endif
#ifdef IO_USE_SELECT
return io_library_init_select(eventsize);
#endif
}
@ -171,11 +192,14 @@ io_library_shutdown(void)
#ifdef IO_USE_SELECT
FD_ZERO(&readers);
FD_ZERO(&writers);
#else
close(io_masterfd); /* kqueue, epoll */
#endif
#ifdef IO_USE_EPOLL
close(io_masterfd);
io_masterfd = -1;
#endif
#ifdef IO_USE_KQUEUE
close(io_masterfd);
io_masterfd = -1;
array_free(&io_evcache);
#endif
library_initialized = false;
@ -201,18 +225,14 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short))
io_event *i;
assert(fd >= 0);
#ifdef IO_USE_SELECT
#ifdef FD_SETSIZE
#if defined(IO_USE_SELECT) || defined(FD_SETSIZE)
if (fd >= FD_SETSIZE) {
Log(LOG_ERR,
"fd %d exceeds FD_SETSIZE (%u) (select can't handle more file descriptors)",
fd, FD_SETSIZE);
return false;
}
#endif /* FD_SETSIZE */
#endif /* IO_USE_SELECT */
#endif
i = (io_event *) array_alloc(&io_events, sizeof(io_event), (size_t) fd);
if (!i) {
Log(LOG_WARNING,
@ -260,7 +280,7 @@ io_event_kqueue_commit_cache(void)
struct kevent *events;
bool ret;
int len = (int) array_length(&io_evcache, sizeof (struct kevent));
if (!len) /* nothing to do */
return true;
@ -293,7 +313,7 @@ io_event_change_kqueue(int fd, short what, const int action)
ret = array_catb(&io_evcache, (char*) &kev, sizeof (kev));
if (!ret)
ret = kevent(io_masterfd, &kev,1, NULL, 0, NULL) == 0;
}
}
if (ret && (what & IO_WANTWRITE)) {
EV_SET(&kev, fd, EVFILT_WRITE, action, 0, 0, 0);
@ -327,7 +347,6 @@ io_event_add(int fd, short what)
#ifdef IO_USE_KQUEUE
return io_event_change_kqueue(fd, what, EV_ADD | EV_ENABLE);
#endif
#ifdef IO_USE_SELECT
if (fd > select_maxfd)
select_maxfd = fd;
@ -358,22 +377,35 @@ io_setnonblock(int fd)
}
#ifdef IO_USE_SELECT
static void
io_close_select(int fd)
{
io_event *i;
FD_CLR(fd, &writers);
FD_CLR(fd, &readers);
i = io_event_get(fd);
if (!i) return;
if (fd == select_maxfd) {
while (select_maxfd>0) {
--select_maxfd; /* find largest fd */
i = io_event_get(select_maxfd);
if (i && i->callback) break;
}
}
}
#else
static inline void io_close_select(int UNUSED x) { /* NOTHING */ }
#endif
bool
io_close(int fd)
{
io_event *i;
#ifdef IO_USE_SELECT
FD_CLR(fd, &writers);
FD_CLR(fd, &readers);
if (fd == select_maxfd) {
while (select_maxfd>0) {
--select_maxfd; /* find largest fd */
i = io_event_get(select_maxfd);
if (i && i->callback) break;
}
}
#endif
i = io_event_get(fd);
#ifdef IO_USE_KQUEUE
if (array_length(&io_evcache, sizeof (struct kevent))) /* pending data in cache? */
@ -385,8 +417,11 @@ io_close(int fd)
if (i) {
io_event_change_kqueue(fd, i->what, EV_DELETE);
io_event_kqueue_commit_cache();
}
}
#endif
io_close_select(fd);
#ifdef IO_USE_EPOLL
io_event_change_epoll(fd, 0, EPOLL_CTL_DEL);
#endif
@ -516,7 +551,7 @@ io_dispatch_kqueue(struct timeval *tv)
int newevents_len;
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
do {
newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
@ -541,10 +576,10 @@ io_dispatch_kqueue(struct timeval *tv)
#ifdef DEBUG
LogDebug("kev.flag has EV_EOF set, setting IO_ERROR",
kev[i].filter, kev[i].ident);
#endif
#endif
io_docallback((int)kev[i].ident, IO_ERROR);
continue;
}
}
switch (kev[i].filter) {
case EVFILT_READ:
@ -597,9 +632,9 @@ io_docallback(int fd, short what)
#endif
i = io_event_get(fd);
if (i->callback) { /* callback might be NULL if a previous callback function
if (i->callback) { /* callback might be NULL if a previous callback function
called io_close on this fd */
i->callback(fd, (what & IO_ERROR) ? i->what : what);
}
}
/* if error indicator is set, we return the event(s) that were registered */
}