mirror of /home/gitosis/repositories/libowfat.git
Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat
https://www.fefe.de/libowfat/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.2 KiB
170 lines
4.2 KiB
#define _GNU_SOURCE |
|
#include <errno.h> |
|
#define my_extern |
|
#include "io_internal.h" |
|
#undef my_extern |
|
#include "byte.h" |
|
#ifdef HAVE_SIGIO |
|
#include <signal.h> |
|
#include <fcntl.h> |
|
#endif |
|
#include <sys/types.h> |
|
#include <fcntl.h> |
|
|
|
#ifdef HAVE_KQUEUE |
|
#include <sys/event.h> |
|
#endif |
|
#ifdef HAVE_EPOLL |
|
#include <inttypes.h> |
|
#include <sys/epoll.h> |
|
#endif |
|
#include <unistd.h> |
|
#ifdef HAVE_DEVPOLL |
|
#include <sys/types.h> |
|
#include <sys/socket.h> |
|
#include <sys/devpoll.h> |
|
#endif |
|
|
|
#ifdef __dietlibc__ |
|
#include <sys/atomic.h> |
|
#else |
|
#define __CAS(ptr,oldval,newval) __sync_val_compare_and_swap(ptr,oldval,newval) |
|
#endif |
|
|
|
#ifdef __MINGW32__ |
|
#include <stdio.h> |
|
extern HANDLE io_comport; |
|
#endif |
|
iarray io_fds; |
|
static int io_fds_inited; |
|
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; |
|
#endif |
|
#if defined(HAVE_SIGIO) |
|
long alt_firstread, alt_firstwrite; |
|
long alt_curread, alt_curwrite; |
|
#endif |
|
|
|
/* put d on internal data structure, return 1 on success, 0 on error */ |
|
static io_entry* io_fd_internal(int64 d,int flags) { |
|
io_entry* e; |
|
#ifndef __MINGW32__ |
|
long r; |
|
if ((flags&(IO_FD_BLOCK|IO_FD_NONBLOCK))==0) { |
|
if ((r=fcntl(d,F_GETFL,0)) == -1) |
|
return 0; /* file descriptor not open */ |
|
} else |
|
if (flags&IO_FD_NONBLOCK) |
|
r=O_NDELAY; |
|
else |
|
r=0; |
|
#endif |
|
/* Problem: we might be the first to use io_fds. We need to make sure |
|
* we are the only ones to initialize it. So set io_fds_inited to 2 |
|
* and not to 1. We know we are done when it is 1. We know we need |
|
* to do something when it is 0. We know somebody else is doing it |
|
* when it is 2. */ |
|
if (__CAS(&io_fds_inited,0,2)==0) { |
|
iarray_init(&io_fds,sizeof(io_entry)); |
|
io_fds_inited=1; |
|
} else |
|
do { asm("" : : : "memory"); } while (io_fds_inited!=1); |
|
if (!(e=iarray_allocate(&io_fds,d))) return 0; |
|
if (e->inuse) return e; |
|
byte_zero(e,sizeof(io_entry)); |
|
e->inuse=1; |
|
e->next_defer=-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=alt_curread=alt_curwrite=-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; |
|
fprintf(stderr,"Initialized completion port: %p\n",io_comport); |
|
} else { |
|
fprintf(stderr,"ARGH! Could not init completion port!\n"); |
|
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) { |
|
fprintf(stderr,"Queueing %p at completion port %p...",d,io_comport); |
|
if (CreateIoCompletionPort((HANDLE)d,io_comport,(ULONG_PTR)d,0)==0) { |
|
fprintf(stderr," failed!\n"); |
|
errno=EBADF; |
|
return 0; |
|
} |
|
fprintf(stderr," OK!\n"); |
|
} |
|
#endif |
|
return e; |
|
} |
|
|
|
int io_fd(int64 d) { |
|
io_entry* e=io_fd_internal(d,0); |
|
return !!e; |
|
} |
|
|
|
int io_fd_canwrite(int64 d) { |
|
io_entry* e=io_fd_internal(d,0); |
|
if (e) e->canwrite=1; |
|
return !!e; |
|
} |
|
|
|
int io_fd_flags(int64 d,int flags) { |
|
io_entry* e=io_fd_internal(d,flags); |
|
if (e && (flags&IO_FD_CANWRITE)) e->canwrite=1; |
|
return !!e; |
|
}
|
|
|