diff --git a/GNUmakefile b/GNUmakefile index c2c0d8c..8b54f64 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -60,7 +60,7 @@ $(DNS_OBJS): dns.h stralloc.h taia.h tai.h uint64.h iopause.h $(CASE_OBJS): case.h $(ARRAY_OBJS): uint64.h array.h $(MULT_OBJS): uint64.h uint32.h uint16.h safemult.h -$(IO_OBJS): uint64.h array.h io.h io_internal.h taia.h tai.h +$(IO_OBJS): uint64.h array.h io.h io_internal.h taia.h tai.h haveepoll.h havekqueue.h iopause.o: select.h openreadclose.o readclose.o: readclose.h diff --git a/io/io_fd.c b/io/io_fd.c index 5969a35..5ed8d8e 100644 --- a/io/io_fd.c +++ b/io/io_fd.c @@ -2,6 +2,12 @@ #include #include "io_internal.h" +#ifdef HAVE_KQUEUE +#include +#endif +#ifdef HAVE_EPOLL +#include +#endif /* put d on internal data structure, return 1 on success, 0 on error */ int io_fd(int64 d) { @@ -13,5 +19,17 @@ int io_fd(int64 d) { e->inuse=1; if (r&O_NDELAY) e->nonblock=1; e->next_read=e->next_write=-1; + if (io_waitmode==UNDECIDED) { +#if defined(HAVE_EPOLL) + io_master=epoll_create(1000); + if (io_master!=-1) io_waitmode=EPOLL; +#endif +#if defined(HAVE_KQUEUE) + if (io_waitmode==POLL) { /* who knows, maybe someone supports both one day */ + io_master=kqueue(); + if (io_master!=-1) io_waitmode=KQUEUE; + } +#endif + } return 1; } diff --git a/io/io_wantread.c b/io/io_wantread.c index c136514..0993be9 100644 --- a/io/io_wantread.c +++ b/io/io_wantread.c @@ -2,10 +2,38 @@ #include #include #include "io_internal.h" +#ifdef HAVE_KQUEUE +#include +#include +#include +#endif +#ifdef HAVE_EPOLL +#include +#endif void io_wantread(int64 d) { + int newfd; io_entry* e=array_get(&io_fds,sizeof(io_entry),d); if (!e) return; - if (!e->wantread && !e->wantwrite) ++io_wanted_fds; + newfd=(!e->wantread && !e->wantwrite); + io_wanted_fds+=newfd; +#ifdef HAVE_EPOLL + if (io_waitmode==EPOLL) { + struct epoll_event x; + x.events=EPOLLIN; + if (e->wantwrite) x.events|=EPOLLOUT; + x.data.fd=d; + epoll_ctl(io_master,newfd?EPOLL_CTL_ADD:EPOLL_CTL_MOD,d,&x); + } +#endif +#ifdef HAVE_KQUEUE + if (io_waitmode==KQUEUE) { + struct kevent kev; + struct timespec ts; + EV_SET(&kev, d, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0); + ts.tv_sec=0; ts.tv_nsec=0; + kevent(io_master,&kev,1,0,0,&ts); + } +#endif e->wantread=1; } diff --git a/io/io_wantwrite.c b/io/io_wantwrite.c index 127b4c5..2bcb0e3 100644 --- a/io/io_wantwrite.c +++ b/io/io_wantwrite.c @@ -2,10 +2,38 @@ #include #include #include "io_internal.h" +#ifdef HAVE_KQUEUE +#include +#include +#include +#endif +#ifdef HAVE_EPOLL +#include +#endif void io_wantwrite(int64 d) { + int newfd; io_entry* e=array_get(&io_fds,sizeof(io_entry),d); if (!e) return; - if (!e->wantread && !e->wantwrite) ++io_wanted_fds; + newfd=(!e->wantread && !e->wantwrite); + io_wanted_fds+=newfd; +#ifdef HAVE_EPOLL + if (io_waitmode==EPOLL) { + struct epoll_event x; + x.events=EPOLLOUT; + if (e->wantread) x.events|=EPOLLIN; + x.data.fd=d; + epoll_ctl(io_master,newfd?EPOLL_CTL_ADD:EPOLL_CTL_MOD,d,&x); + } +#endif +#ifdef HAVE_KQUEUE + if (io_waitmode==KQUEUE) { + struct kevent kev; + struct timespec ts; + EV_SET(&kev, d, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, 0); + ts.tv_sec=0; ts.tv_nsec=0; + kevent(io_master,&kev,1,0,0,&ts); + } +#endif e->wantwrite=1; } diff --git a/io_internal.h b/io_internal.h index ba75b11..64fedf4 100644 --- a/io_internal.h +++ b/io_internal.h @@ -1,5 +1,7 @@ #include "io.h" #include "array.h" +#include "haveepoll.h" +#include "havekqueue.h" typedef struct { unsigned int wantread:1; @@ -20,4 +22,19 @@ array io_pollfds; unsigned long first_readable; unsigned long first_writeable; +enum { + UNDECIDED, + POLL +#ifdef HAVE_KQUEUE + ,KQUEUE +#endif +#ifdef HAVE_EPOLL + ,EPOLL +#endif +} io_waitmode; + +#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) +int io_master; +#endif + int64 io_waituntil2(int64 milliseconds);