#define _GNU_SOURCE #include #define extern #include "io_internal.h" #undef extern #include "byte.h" #ifdef HAVE_SIGIO #include #include #endif #include #include #ifdef HAVE_KQUEUE #include #endif #ifdef HAVE_EPOLL #include #include #endif #include #ifdef HAVE_DEVPOLL #include #include #include #endif #ifdef __MINGW32__ extern HANDLE io_comport; #endif array io_fds; uint64 io_wanted_fds; array io_pollfds; enum __io_waitmode io_waitmode; #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) || defined(HAVE_DEVPOLL) int io_master; #endif #if defined(HAVE_SIGIO) int io_signum; sigset_t io_ss; long alt_firstread; long alt_firstwrite; #endif /* put d on internal data structure, return 1 on success, 0 on error */ int io_fd(int64 d) { io_entry* e; #ifndef __MINGW32__ long r; if ((r=fcntl(d,F_GETFL,0)) == -1) return 0; /* file descriptor not open */ #endif if (!(e=array_allocate(&io_fds,sizeof(io_entry),d))) return 0; if (e->inuse) return 1; byte_zero(e,sizeof(io_entry)); e->inuse=1; #ifdef __MINGW32__ e->mh=0; #else if (r&O_NDELAY) e->nonblock=1; #endif e->next_read=e->next_write=-1; if (io_waitmode==UNDECIDED) { first_readable=first_writeable=-1; #if defined(HAVE_EPOLL) io_master=epoll_create(1000); if (io_master!=-1) io_waitmode=EPOLL; #endif #if defined(HAVE_KQUEUE) if (io_waitmode==UNDECIDED) { /* who knows, maybe someone supports both one day */ io_master=kqueue(); if (io_master!=-1) io_waitmode=KQUEUE; } #endif #if defined(HAVE_DEVPOLL) if (io_waitmode==UNDECIDED) { io_master=open("/dev/poll",O_RDWR); if (io_master!=-1) io_waitmode=DEVPOLL; } #endif #if defined(HAVE_SIGIO) alt_firstread=alt_firstwrite=-1; if (io_waitmode==UNDECIDED) { io_signum=SIGRTMIN+1; if (sigemptyset(&io_ss)==0 && sigaddset(&io_ss,io_signum)==0 && sigaddset(&io_ss,SIGIO)==0 && sigprocmask(SIG_BLOCK,&io_ss,0)==0) io_waitmode=_SIGIO; } #endif #ifdef __MINGW32__ io_comport=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0); if (io_comport) { io_waitmode=COMPLETIONPORT; } else { errno=EINVAL; return 0; } #endif } #if defined(HAVE_SIGIO) if (io_waitmode==_SIGIO) { fcntl(d,F_SETOWN,getpid()); fcntl(d,F_SETSIG,io_signum); #if defined(O_ONESIGFD) && defined(F_SETAUXFL) fcntl(d, F_SETAUXFL, O_ONESIGFD); #endif fcntl(d,F_SETFL,fcntl(d,F_GETFL)|O_NONBLOCK|O_ASYNC); } #endif #ifdef __MINGW32__ if (io_comport) { if (CreateIoCompletionPort((HANDLE)d,io_comport,(ULONG_PTR)d,0)==0) { errno=EBADF; return 0; } } #endif return 1; }