#POLL
#####
SV*
poll (poll_list, s_timeout)
SV* poll_list;
double s_timeout;
INIT:
int sz=sizeof(struct pollfd);
int count;
int ret;
CODE:
if(SvOK(poll_list) && SvPOK(poll_list)){
count=SvCUR(poll_list)/sz; //Number of items in array
//TODO: croak if not fully divisible
ret=poll((struct pollfd *)SvPVX(poll_list), count, (int)s_timeout*1000);
}
else {
//Used for timeout only
ret=poll(NULL,0,(int)s_timeout*1000);
}
//TODO: need to process EAGAIN and INT somehow
if(ret<0){
RETVAL=&PL_sv_undef;
}
else{
RETVAL=newSViv(ret);
}
//No length of list is required as we use the smallest multiple of sizeof(struct pollfd) which will fit in the poll list
OUTPUT:
RETVAL
poll_list
#if defined(IO_FD_OS_DARWIN) || defined(IO_FD_OS_BSD)
SV *
kqueue()
INIT:
int ret;
CODE:
ret=kqueue();
if(ret<0){
RETVAL=&PL_sv_undef;
}
else{
RETVAL=newSViv(ret);
}
OUTPUT:
RETVAL
SV *
kevent(kq, change_list, event_list, timeout)
int kq;
SV * change_list;
SV * event_list;
SV * timeout;
INIT:
int ret;
int ncl, nel;
KEVENT_S *cl, *el;
struct timespec tspec;
double tout;
CODE:
//Calcuate from current length
ncl=SvCUR(change_list)/sizeof(KEVENT_S);
//Calculate from available length
nel=SvLEN(event_list)/sizeof(KEVENT_S);
cl=(KEVENT_S *)SvPVX(change_list);
el=(KEVENT_S *)SvPVX(event_list);
//fprintf(stderr, "change list len: %d, event list available: %d\n", ncl, nel);
if(SvOK(timeout)&& SvNIOK(timeout)){
tout=SvNV(timeout);
tspec.tv_sec=tout;
tspec.tv_nsec=1e9*(tout-tspec.tv_sec);
#if defined(IO_FD_OS_DARWIN)
ret=KEVENT (kq, cl, ncl, el, nel, 0, &tspec);
#endif
#if defined(IO_FD_OS_BSD)
ret=KEVENT(kq, cl, ncl, el, nel, &tspec);
//}
#endif
}
else {
#if defined(IO_FD_OS_DARWIN)
ret=KEVENT(kq,cl,ncl, el, nel,0, NULL);
#endif
#if defined(IO_FD_OS_BSD)
ret=KEVENT(kq,cl,ncl, el, nel, NULL);
#endif
}
if(ret<0){
SvCUR_set(event_list,0);
RETVAL=&PL_sv_undef;
}
else {
SvCUR_set(event_list,sizeof(KEVENT_S)*ret);
RETVAL=newSViv(ret);
}
OUTPUT:
RETVAL
event_list
SV *
pack_kevent(ident,filter,flags,fflags,data,udata, ...)
unsigned long ident;
I16 filter;
U16 flags;
U32 fflags;
long data;
SV *udata;
INIT:
KEVENT_S *e;
CODE:
RETVAL=newSV(sizeof(KEVENT_S));
e=(KEVENT_S *)SvPVX(RETVAL);
e->ident=ident;
e->filter=filter;
e->flags=flags;
e->fflags=fflags;
e->data=data;
#if defined(IO_FD_OS_DARWIN)
e->udata=(uint64_t)SvRV(udata);
#endif
#if defined(IO_FD_OS_BSD)
e->udata=(void *)SvRV(udata);
#endif
SvCUR_set(RETVAL,sizeof(KEVENT_S));
SvPOK_on(RETVAL);
//Pack
OUTPUT:
RETVAL
#endif
SV *
clock_gettime_monotonic()
INIT:
struct timespec tp;
int ret;
CODE:
ret=clock_gettime(CLOCK_MONOTONIC, &tp);
if(ret<0){
RETVAL=&PL_sv_undef;
}
else{
RETVAL=newSVnv(tp.tv_sec + tp.tv_nsec * 1e-9);
}
OUTPUT:
RETVAL
long
sv_to_pointer(sv)
SV *sv
INIT:
CODE:
//TODO: Increase the ref count of input sv
RETVAL=(long)SvRV(sv);
OUTPUT:
RETVAL
SV *
pointer_to_sv(pointer)
long pointer;
INIT:
CODE:
//TODO: check valid. decrement ref count;
RETVAL=newRV((SV*)pointer);
OUTPUT:
RETVAL
SV *
SV(size)
int size
CODE:
RETVAL=newSV(size);
//SvPOK_on(RETVAL);
SvPVCLEAR(RETVAL);
OUTPUT:
RETVAL
#SELECT
#######
SV*
select(readvec, writevec, errorvec, tout)
SV* readvec
SV* writevec
SV* errorvec
#Perl timeout is in fractional seconds
SV* tout
INIT:
fd_set *r;
fd_set *w;
fd_set *e;
struct timeval timeout;
int size=sizeof(fd_set)+1;
double tval;
int ret;
int nfds=0;
int bit_string_size=129;
int tmp;
CODE:
//Ensure the vector can fit a fd_set
//TODO: Need to make sure its null filled too
//
if(SvOK(readvec)){
r=(fd_set *)SvGROW(readvec,bit_string_size);
tmp=SvCUR(readvec);
Zero(((char *)r)+tmp,bit_string_size-tmp,1);
nfds=tmp;
}
else {
r=NULL;
}
if(SvOK(writevec)){
w=(fd_set *)SvGROW(writevec,bit_string_size);
tmp=SvCUR(writevec);
Zero(((char *)w)+tmp,bit_string_size-tmp,1);
nfds=tmp>nfds?tmp:nfds;
}
else {
w=NULL;
}
if(SvOK(errorvec)){
e=(fd_set *)SvGROW(errorvec,bit_string_size);
tmp=SvCUR(errorvec);
Zero(((char *)e)+tmp, bit_string_size-tmp,1);
nfds=tmp>nfds?tmp:nfds;
}
else {
e=NULL;
}
nfds*=8; //convert string (byte) length to bit length
//This length has an implicit +1 for select call
//Clamp the nfds to 1024
if(nfds>1024){
//TODO: Need to show an error here?
nfds=1024;
}
//TODO: handle EAGAIN and EINT
//nfds++;
//fprintf(stderr, "Number of fds for select: %d\n", nfds);
if(SvOK(tout) && (SvNOK(tout) || SvIOK(tout))){
//Timeout value provided in fractional seconds
tval=SvNV(tout);
timeout.tv_sec=(unsigned int ) tval;
tval-=timeout.tv_sec;
tval*=1000000;
timeout.tv_usec=(unsigned int) tval;
//fprintf(stderr, "select with %fs timeout....\n", tval);
ret=select(nfds,r,w,e,&timeout);
//fprintf(stderr, "Returned number of fds %d\n", ret);
}
else{
//Timeout is not a number
//printf(stderr, "select with null timeout....\n");
ret=select(nfds,r,w,e, NULL);
}
if(ret<0){
//Undef on error
RETVAL=&PL_sv_undef;
}
else{
//0 on timeout expired
//>0 number of found fds to test
RETVAL=newSViv(ret);
}
OUTPUT:
RETVAL
readvec
writevec
errorvec