IO-AIO

 view release on metacpan or  search on metacpan

AIO.xs  view on Meta::CPAN

      || fcntl (pipefd [0], F_SETFD, FD_CLOEXEC) < 0
#endif
      || close (pipefd [1]) < 0
    )
      croak ("IO::AIO: unable to create dummy pipe for aio_close");

    close_fd = pipefd [0];
  }

  reinit ();
}

void
reinit ()
	PROTOTYPE:

void
max_poll_reqs (unsigned int nreqs)
	PROTOTYPE: $
        CODE:
        eio_set_max_poll_reqs (nreqs);

void
max_poll_time (double nseconds)
	PROTOTYPE: $
        CODE:
        eio_set_max_poll_time (nseconds);

void
min_parallel (unsigned int nthreads)
	PROTOTYPE: $
        CODE:
        eio_set_min_parallel (nthreads);

void
max_parallel (unsigned int nthreads)
	PROTOTYPE: $
        CODE:
        eio_set_max_parallel (nthreads);

void
max_idle (unsigned int nthreads)
	PROTOTYPE: $
        CODE:
        eio_set_max_idle (nthreads);

void
idle_timeout (unsigned int seconds)
	PROTOTYPE: $
        CODE:
        eio_set_idle_timeout (seconds);

void
max_outstanding (unsigned int maxreqs)
	PROTOTYPE: $
        CODE:
        max_outstanding = maxreqs;

void
aio_wd (SV8 *pathname, SV *callback = &PL_sv_undef)
	PPCODE:
{
        dREQ;

        req->type = EIO_WD_OPEN;
        req_set_path1 (req, pathname);

        REQ_SEND;
}

void
aio_open (SV8 *pathname, int flags, int mode, SV *callback = &PL_sv_undef)
	PPCODE:
{
        dREQ;

        req->type = EIO_OPEN;
        req_set_path1 (req, pathname);
        req->int1 = flags;
        req->int2 = mode;

        REQ_SEND;
}

void
aio_fsync (SV *fh, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_fsync     = EIO_FSYNC
           aio_fdatasync = EIO_FDATASYNC
           aio_syncfs    = EIO_SYNCFS
	PPCODE:
{
	int fd = s_fileno_croak (fh, 0);
        dREQ;

        req->type = ix;
        req->sv1  = newSVsv (fh);
        req->int1 = fd;

        REQ_SEND;
}

void
aio_sync_file_range (SV *fh, off_t offset, size_t nbytes, UV flags, SV *callback = &PL_sv_undef)
	PPCODE:
{
	int fd = s_fileno_croak (fh, 0);
        dREQ;

        req->type = EIO_SYNC_FILE_RANGE;
        req->sv1  = newSVsv (fh);
        req->int1 = fd;
        req->offs = offset;
        req->size = nbytes;
        req->int2 = flags;

        REQ_SEND;
}

void
aio_allocate (SV *fh, int mode, off_t offset, size_t len, SV *callback = &PL_sv_undef)
	PPCODE:
{
	int fd = s_fileno_croak (fh, 0);
        dREQ;

        req->type = EIO_FALLOCATE;
        req->sv1  = newSVsv (fh);
        req->int1 = fd;
        req->int2 = mode;
        req->offs = offset;
        req->size = len;

        REQ_SEND;
}

void
aio_close (SV *fh, SV *callback = &PL_sv_undef)
	PPCODE:
{
	int fd = s_fileno_croak (fh, 0);
        dREQ;
#if 0
        /* partially duplicate logic in s_fileno */
	SvGETMAGIC (fh);

	if (SvROK (fh))
	  {
	    fh = SvRV (fh);
	    SvGETMAGIC (fh);
	  }

        if (SvTYPE (fh) == SVt_PVGV)
          {
            /* perl filehandle */
            PerlIOUnix_refcnt_inc (fd);
            do_close ((GV *)fh, 1);

            req->type = EIO_CLOSE;
            req->int1 = fd;
            /*req->sv2  = newSVsv (fh);*/ /* since we stole the fd, no need to keep the fh */
          }
        else
#endif
          {
            /* fd number */
            req->type = EIO_DUP2;
            req->int1 = close_fd;
            req->sv2  = newSVsv (fh);
            req->int2 = fd;
          }

        REQ_SEND;
}

void
aio_seek (SV *fh, SV *offset, int whence, SV *callback = &PL_sv_undef)
        PPCODE:
{
        int fd = s_fileno_croak (fh, 0);
        dREQ;

        req->type = EIO_SEEK;
        req->sv1  = newSVsv (fh);
        req->int1 = fd;
        req->offs = SvVAL64 (offset);
        req->int2 = whence;

        REQ_SEND;
}

void
aio_read (SV *fh, SV *offset, SV *length, SV8 *data, IV dataoffset, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_read  = EIO_READ
           aio_write = EIO_WRITE
        PPCODE:
{
        STRLEN svlen;
        int fd = s_fileno_croak (fh, ix == EIO_WRITE);
        char *svptr = SvPVbyte (data, svlen);
        UV len = SvUV (length);

        if (dataoffset < 0)
          dataoffset += svlen;

        if (dataoffset < 0 || dataoffset > svlen)
          croak ("dataoffset outside of data scalar");

        if (ix == EIO_WRITE)
          {
            /* write: check length and adjust. */
            if (!SvOK (length) || len + dataoffset > svlen)
              len = svlen - dataoffset;
          }
        else
          {
            /* read: check type and grow scalar as necessary */
            if (!SvPOK (data) || SvLEN (data) >= SvCUR (data))
              svptr = sv_grow (data, len + dataoffset + 1);
            else if (SvCUR (data) < len + dataoffset)
              croak ("length + dataoffset outside of scalar, and cannot grow");
          }

        {
          dREQ;

          req->type = ix;
          req->sv1  = newSVsv (fh);
          req->int1 = fd;
          req->offs = SvOK (offset) ? SvVAL64 (offset) : -1;
          req->size = len;
          req->sv2  = SvREFCNT_inc (data);
          req->ptr2 = (char *)svptr + dataoffset;
          req->stroffset = dataoffset;

          if (!SvREADONLY (data))
            {
              SvREADONLY_on (data);
              req->flags |= FLAG_SV2_RO_OFF;
            }

          REQ_SEND;
        }
}

void
aio_ioctl (SV *fh, unsigned long request, SV8 *arg, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_ioctl = EIO_IOCTL
           aio_fcntl = EIO_FCNTL
        PPCODE:
{
        int fd = s_fileno_croak (fh, 0);
        char *svptr;

        if (SvPOK (arg) || !SvNIOK (arg))
          {
            STRLEN svlen;
            /* perl uses IOCPARM_LEN for fcntl, so we do, too */
#ifdef IOCPARM_LEN
            STRLEN need = IOCPARM_LEN (request);
#else
            STRLEN need = 256;
#endif

            if (svlen < need)
              svptr = SvGROW (arg, need);
          }
        else
          svptr = (char *)SvIV (arg);

        {
          dREQ;

          req->type = ix;
          req->sv1  = newSVsv (fh);
          req->int1 = fd;
          req->int2 = (long)request;
          req->sv2  = SvREFCNT_inc (arg);
          req->ptr2 = svptr;

          REQ_SEND;
        }
}

void
aio_readlink (SV8 *pathname, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_readlink = EIO_READLINK
           aio_realpath = EIO_REALPATH
        PPCODE:
{
        dREQ;

        req->type = ix;
        req_set_path1 (req, pathname);

        REQ_SEND;
}

void
aio_sendfile (SV *out_fh, SV *in_fh, off_t in_offset, size_t length, SV *callback = &PL_sv_undef)
        PPCODE:
{
	int ifd = s_fileno_croak (in_fh , 0);
	int ofd = s_fileno_croak (out_fh, 1);
	dREQ;

        req->type = EIO_SENDFILE;
        req->sv1  = newSVsv (out_fh);
        req->int1 = ofd;
        req->sv2  = newSVsv (in_fh);
        req->int2 = ifd;
        req->offs = in_offset;
        req->size = length;

        REQ_SEND;
}

void
aio_readahead (SV *fh, off_t offset, size_t length, SV *callback = &PL_sv_undef)
        PPCODE:
{
	int fd = s_fileno_croak (fh, 0);
	dREQ;

        req->type = EIO_READAHEAD;
        req->sv1  = newSVsv (fh);
        req->int1 = fd;
        req->offs = offset;
        req->size = length;

        REQ_SEND;
}

void
aio_stat (SV8 *fh_or_path, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_stat    = EIO_STAT
           aio_lstat   = EIO_LSTAT
           aio_statvfs = EIO_STATVFS
	PPCODE:
{
	dREQ;

        req_set_fh_or_path (req, ix, ix == EIO_STATVFS ? EIO_FSTATVFS : EIO_FSTAT, fh_or_path);

        REQ_SEND;
}

void
st_xtime ()
	ALIAS:
           st_atime = 0x01
           st_mtime = 0x02
           st_ctime = 0x04
           st_btime = 0x08
           st_xtime = 0x0f
	PPCODE:
        EXTEND (SP, 4);
        if (ix & 0x01) PUSHs (newSVnv (PL_statcache.st_atime + 1e-9 * ATIMENSEC));
        if (ix & 0x02) PUSHs (newSVnv (PL_statcache.st_mtime + 1e-9 * MTIMENSEC));
        if (ix & 0x04) PUSHs (newSVnv (PL_statcache.st_ctime + 1e-9 * CTIMENSEC));
        if (ix & 0x08) PUSHs (newSVnv (BTIMESEC              + 1e-9 * BTIMENSEC));

void
st_xtimensec ()
	ALIAS:
           st_atimensec = 0x01
           st_mtimensec = 0x02
           st_ctimensec = 0x04
           st_btimensec = 0x08
           st_xtimensec = 0x0f
           st_btimesec  = 0x10
           st_gen       = 0x20
	PPCODE:
        EXTEND (SP, 4);
        if (ix & 0x01) PUSHs (newSViv (ATIMENSEC));
        if (ix & 0x02) PUSHs (newSViv (MTIMENSEC));
        if (ix & 0x04) PUSHs (newSViv (CTIMENSEC));
        if (ix & 0x08) PUSHs (newSViv (BTIMENSEC));
        if (ix & 0x10) PUSHs (newSVuv (BTIMESEC));
        if (ix & 0x20) PUSHs (newSVuv (ST_GEN));

UV
major (UV dev)
	ALIAS:
        minor = 1
	CODE:
        RETVAL = ix ? minor (dev) : major (dev);
	OUTPUT:
        RETVAL

UV
makedev (UV maj, UV min)
	CODE:
        RETVAL = makedev (maj, min);
	OUTPUT:
        RETVAL

void
aio_utime (SV8 *fh_or_path, SV *atime, SV *mtime, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;

        req->nv1 = SvOK (atime) ? SvNV (atime) : -1.;
        req->nv2 = SvOK (mtime) ? SvNV (mtime) : -1.;
        req_set_fh_or_path (req, EIO_UTIME, EIO_FUTIME, fh_or_path);

        REQ_SEND;
}

void
aio_truncate (SV8 *fh_or_path, SV *offset, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;

        req->offs = SvOK (offset) ? SvVAL64 (offset) : -1;
        req_set_fh_or_path (req, EIO_TRUNCATE, EIO_FTRUNCATE, fh_or_path);

        REQ_SEND;
}

void
aio_chmod (SV8 *fh_or_path, int mode, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;

        req->int2 = mode;
        req_set_fh_or_path (req, EIO_CHMOD, EIO_FCHMOD, fh_or_path);

        REQ_SEND;
}

void
aio_chown (SV8 *fh_or_path, SV *uid, SV *gid, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;

        req->int2 = SvOK (uid) ? SvIV (uid) : -1;
        req->int3 = SvOK (gid) ? SvIV (gid) : -1;
        req_set_fh_or_path (req, EIO_CHOWN, EIO_FCHOWN, fh_or_path);

        REQ_SEND;
}

void
aio_readdirx (SV8 *pathname, IV flags, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;
	
        req->type = EIO_READDIR;
        req->int1 = flags | EIO_READDIR_DENTS | EIO_READDIR_CUSTOM1;

        if (flags & EIO_READDIR_DENTS)
          req->int1 |= EIO_READDIR_CUSTOM2;

        req_set_path1 (req, pathname);

	REQ_SEND;
}

void
aio_mkdir (SV8 *pathname, int mode, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;

        req->type = EIO_MKDIR;
        req->int2 = mode;
        req_set_path1 (req, pathname);

        REQ_SEND;
}

void
aio_unlink (SV8 *pathname, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_unlink  = EIO_UNLINK
           aio_rmdir   = EIO_RMDIR
           aio_readdir = EIO_READDIR
	PPCODE:
{
	dREQ;
	
        req->type = ix;
        req_set_path1 (req, pathname);

	REQ_SEND;
}

void
aio_link (SV8 *oldpath, SV8 *newpath, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_link    = EIO_LINK
           aio_symlink = EIO_SYMLINK
           aio_rename  = EIO_RENAME
	PPCODE:
{
        eio_wd wd2 = 0;
	dREQ;
	
        req->type = ix;
        req_set_path1 (req, oldpath);
        req_set_path (newpath, &req->sv2, &req->sv4, &wd2, &req->ptr2);
        req->int3 = (long)wd2;
	
	REQ_SEND;
}

void
aio_rename2 (SV8 *oldpath, SV8 *newpath, int flags = 0, SV *callback = &PL_sv_undef)
	PPCODE:
{
        eio_wd wd2 = 0;
	dREQ;
	
        req->type = EIO_RENAME;
        req_set_path1 (req, oldpath);
        req_set_path (newpath, &req->sv2, &req->sv4, &wd2, &req->ptr2);
        req->int2 = flags;
        req->int3 = (long)wd2;
	
	REQ_SEND;
}

void
aio_mknod (SV8 *pathname, int mode, UV dev, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;
	
        req->type = EIO_MKNOD;
        req->int2 = (mode_t)mode;
        req->offs = dev;
        req_set_path1 (req, pathname);
	
	REQ_SEND;
}

void
aio_mtouch (SV8 *data, IV offset = 0, SV *length = &PL_sv_undef, int flags = -1, SV *callback = &PL_sv_undef)
        ALIAS:
           aio_mtouch = EIO_MTOUCH
           aio_msync  = EIO_MSYNC
        PPCODE:
{
        STRLEN svlen;
        char *svptr = SvPVbyte (data, svlen);
        UV len = SvUV (length);

        if (flags < 0)
          flags = ix == EIO_MSYNC ? EIO_MS_SYNC : 0;

        if (offset < 0)
          offset += svlen;

        if (offset < 0 || offset > svlen)
          croak ("offset outside of scalar");

        if (!SvOK (length) || len + offset > svlen)
          len = svlen - offset;

        {
          dREQ;

          req->type = ix;
          req->sv2  = SvREFCNT_inc (data);
          req->ptr2 = (char *)svptr + offset;
          req->size = len;
          req->int1 = flags;

          REQ_SEND;
        }
}

void
aio_mlock (SV8 *data, IV offset = 0, SV *length = &PL_sv_undef, SV *callback = &PL_sv_undef)
        PPCODE:
{
        STRLEN svlen;
        char *svptr = SvPVbyte (data, svlen);
        UV len = SvUV (length);

        if (offset < 0)
          offset += svlen;

        if (offset < 0 || offset > svlen)
          croak ("offset outside of scalar");

        if (!SvOK (length) || len + offset > svlen)
          len = svlen - offset;

        {
          dREQ;

          req->type = EIO_MLOCK;
          req->sv2  = SvREFCNT_inc (data);
          req->ptr2 = (char *)svptr + offset;
          req->size = len;

          REQ_SEND;
        }
}

void
aio_mlockall (IV flags, SV *callback = &PL_sv_undef)
        PPCODE:
{
        dREQ;

        req->type = EIO_MLOCKALL;
        req->int1 = flags;

        REQ_SEND;
}

void
aio_fiemap (SV *fh, off_t start, SV *length, U32 flags, SV *count, SV *callback = &PL_sv_undef)
        PPCODE:
{
	int fd = s_fileno_croak (fh, 0);
	dREQ;

        req->type = EIO_CUSTOM;
        req->sv1  = newSVsv (fh);
        req->int1 = fd;

        req->feed = fiemap;
#if HAVE_FIEMAP
        /* keep our fingers crossed that the next two types are 64 bit */
        req->offs = start;
        req->size = SvOK (length) ? SvVAL64 (length) : ~0ULL;
        req->int2 = flags;
        req->int3 = SvOK (count) ? SvIV (count) : -1;
#endif

	REQ_SEND;
}

void
aio_slurp (SV *pathname, off_t offset, UV length, SV8 *data, SV *callback = &PL_sv_undef)
        PPCODE:
{
        char *svptr = 0;

        sv_clear_foreign (data);

        if (length) /* known length, directly read into scalar */
          {
            if (!SvPOK (data) || SvLEN (data) >= SvCUR (data))
              svptr = sv_grow (data, length + 1);
            else if (SvCUR (data) < length)
              croak ("length outside of scalar, and cannot grow");
            else
              svptr = SvPVbyte_nolen (data);
          }

        {
          dREQ;

          req->type = EIO_SLURP;
          req_set_path1 (req, pathname);
          req->offs = offset;
          req->size = length;
          req->sv2  = SvREFCNT_inc (data);
          req->ptr2 = svptr;

          if (!SvREADONLY (data))
            {
              SvREADONLY_on (data);
              req->flags |= FLAG_SV2_RO_OFF;
            }

          REQ_SEND;
        }
}

void
aio_busy (double delay, SV *callback = &PL_sv_undef)
	PPCODE:
{
	dREQ;

        req->type = EIO_BUSY;
        req->nv1  = delay < 0. ? 0. : delay;

	REQ_SEND;
}

void
aio_group (SV *callback = &PL_sv_undef)
        PPCODE:
{
	dREQ;

        req->type = EIO_GROUP;

        PUTBACK;
        req_submit (req);
        SPAGAIN;

        XPUSHs (req_sv (req, aio_grp_stash));
}

void
aio_nop (SV *callback = &PL_sv_undef)
	ALIAS:
           aio_nop  = EIO_NOP
           aio_sync = EIO_SYNC
	PPCODE:
{
	dREQ;

        req->type = ix;

	REQ_SEND;
}

int
aioreq_pri (int pri = NO_INIT)
	CODE:
	RETVAL = next_pri;
	if (items > 0)
	  {
	    if (pri < EIO_PRI_MIN) pri = EIO_PRI_MIN;
	    if (pri > EIO_PRI_MAX) pri = EIO_PRI_MAX;
	    next_pri = pri;
	  }
	OUTPUT:
	RETVAL

void
aioreq_nice (int nice = 0)
	CODE:
	nice = next_pri - nice;
	if (nice < EIO_PRI_MIN) nice = EIO_PRI_MIN;
	if (nice > EIO_PRI_MAX) nice = EIO_PRI_MAX;
	next_pri = nice;

void
flush ()
	CODE:
        while (eio_nreqs ())
          {
            poll_wait ();
            poll_cb ();
          }

int
poll ()
	CODE:
        poll_wait ();
        RETVAL = poll_cb ();
	OUTPUT:
	RETVAL

int
poll_fileno ()
	CODE:
        RETVAL = s_epipe_fd (&respipe);
	OUTPUT:
	RETVAL

int
poll_cb (...)
	PROTOTYPE:
	CODE:
        RETVAL = poll_cb ();
	OUTPUT:
	RETVAL

void
poll_wait ()
	CODE:
        poll_wait ();

int
nreqs ()
	CODE:
        RETVAL = eio_nreqs ();
	OUTPUT:
	RETVAL

int
nready ()
	CODE:
        RETVAL = eio_nready ();
	OUTPUT:
	RETVAL

int
npending ()
	CODE:
        RETVAL = eio_npending ();
	OUTPUT:
	RETVAL

int
nthreads ()
	CODE:
        RETVAL = eio_nthreads ();
	OUTPUT:
	RETVAL

int
fadvise (aio_rfd fh, off_t offset, off_t length, IV advice)
        CODE:
        RETVAL = posix_fadvise (fh, offset, length, advice);
	OUTPUT:
        RETVAL

IV
sendfile (aio_wfd ofh, aio_rfd ifh, off_t offset, size_t count)
        CODE:
        RETVAL = eio_sendfile_sync (ofh, ifh, offset, count);
	OUTPUT:
        RETVAL

void
mmap (SV *scalar, STRLEN length, int prot, int flags, SV *fh = &PL_sv_undef, off_t offset = 0)
	PPCODE:
        sv_clear_foreign (scalar);
{
        int fd = SvOK (fh) ? s_fileno_croak (fh, flags & PROT_WRITE) : -1;
        void *addr = (void *)mmap (0, length, prot, flags, fd, offset);
	if (addr == (void *)-1)
	  XSRETURN_NO;

        sv_set_foreign (scalar, &mmap_vtbl, addr, length);

	if (!(prot & PROT_WRITE))
	  SvREADONLY_on (scalar);

        XSRETURN_YES;
}

void
munmap (SV *scalar)
	CODE:
        sv_clear_foreign (scalar);

SV *
mremap (SV *scalar, STRLEN new_length, int flags = MREMAP_MAYMOVE, IV new_address = 0)
	CODE:
{
        MAGIC *mg = mg_findext (scalar, FOREIGN_MAGIC, &mmap_vtbl);
        void *new;

        if (!mg || SvPVX (scalar) != mg->mg_ptr)
          croak ("IO::AIO::mremap: scalar not mapped by IO::AIO::mmap or improperly modified");

        new = mremap (mg->mg_ptr, (size_t)mg->mg_obj, new_length, flags, (void *)new_address);

        RETVAL = &PL_sv_no;

        if (new != (void *)-1)
          {
            RETVAL = new == (void *)mg->mg_ptr
              ? newSVpvn ("0 but true", 10)
              : &PL_sv_yes;

            mg->mg_ptr = (char *)new;
            mg->mg_obj = (SV *)new_length;

            SvPVX (scalar) = mg->mg_ptr;
            SvCUR_set (scalar, new_length);
          }
}
	OUTPUT:
        RETVAL

int
madvise (SV *scalar, IV offset = 0, SV *length = &PL_sv_undef, IV advice_or_prot)
	ALIAS:
        mprotect = 1
        CODE:
{
	STRLEN svlen;
	void *addr = SvPVbyte (scalar, svlen);
        STRLEN len = SvUV (length);

AIO.xs  view on Meta::CPAN

#endif
	OUTPUT:
        RETVAL

NV
stx_atime ()
	PROTOTYPE:
        ALIAS:
        stx_atime      = STATX_OFFSET_atime
        stx_btime      = STATX_OFFSET_btime
        stx_ctime      = STATX_OFFSET_ctime
        stx_mtime      = STATX_OFFSET_mtime
	CODE:
#if HAVE_STATX
        struct statx_timestamp *ts = (struct statx_timestamp *)((char *)&stx + ix);
        RETVAL = ts->tv_sec + ts->tv_nsec * 1e-9;
#else
	XSRETURN_UNDEF;
#endif
	OUTPUT:
        RETVAL

VAL64
stx_atimesec ()
	PROTOTYPE:
        ALIAS:
        stx_atimesec   = STATX_OFFSET_atime
        stx_btimesec   = STATX_OFFSET_btime
        stx_ctimesec   = STATX_OFFSET_ctime
        stx_mtimesec   = STATX_OFFSET_mtime
	CODE:
#if HAVE_STATX
        struct statx_timestamp *ts = (struct statx_timestamp *)((char *)&stx + ix);
        RETVAL = ts->tv_sec;
#else
	XSRETURN_UNDEF;
#endif
	OUTPUT:
        RETVAL

U32
stx_atimensec ()
	PROTOTYPE:
        ALIAS:
        stx_atimensec  = STATX_OFFSET_atime
        stx_btimensec  = STATX_OFFSET_btime
        stx_ctimensec  = STATX_OFFSET_ctime
        stx_mtimensec  = STATX_OFFSET_mtime
	CODE:
#if HAVE_STATX
        struct statx_timestamp *ts = (struct statx_timestamp *)((char *)&stx + ix);
        RETVAL = ts->tv_nsec;
#else
        RETVAL = 0;
#endif
	OUTPUT:
        RETVAL

void
accept4 (aio_rfd rfh, SV *sockaddr, int salen, int flags)
	PPCODE:
{
        SV *retval;
#if HAVE_ACCEPT4
        socklen_t salen_ = salen ? salen + 1 : 0;

        if (salen)
          {
            sv_upgrade (sockaddr, SVt_PV);
            sv_grow (sockaddr, salen_);
          }
        
        int res = accept4 (rfh, salen ? (struct sockaddr *)SvPVX (sockaddr) : 0, salen ? &salen_ : 0, flags);
        
        retval = newmortalFH (res, O_RDWR);

        if (res >= 0 && salen > 0)
          {
            if (salen_ > salen + 1)
              salen_ = salen + 1;

            SvPOK_only (sockaddr);
            SvCUR_set (sockaddr, salen_);
          }
#else
        errno = ENOSYS;
        retval = &PL_sv_undef;
#endif
        XPUSHs (retval);
}

ssize_t
splice (aio_rfd rfh, SV *off_in, aio_wfd wfh, SV *off_out, size_t length, unsigned int flags)
        CODE:
{
#if HAVE_LINUX_SPLICE
	loff_t off_in_, off_out_;
        RETVAL = splice (
          rfh, SvOK (off_in ) ? (off_in_  = SvVAL64 (off_in )), &off_in_  : 0,
          wfh, SvOK (off_out) ? (off_out_ = SvVAL64 (off_out)), &off_out_ : 0,
          length, flags
        );
#else
        RETVAL = EIO_ENOSYS ();
#endif
}
	OUTPUT:
        RETVAL

ssize_t
tee (aio_rfd rfh, aio_wfd wfh, size_t length, unsigned int flags)
        CODE:
#if HAVE_LINUX_SPLICE
        RETVAL = tee (rfh, wfh, length, flags);
#else
        RETVAL = EIO_ENOSYS ();
#endif
	OUTPUT:
        RETVAL

int
pipesize (aio_rfd rfh, int new_size = -1)
	PROTOTYPE: $;$
        CODE:
#if defined(F_SETPIPE_SZ) && defined(F_GETPIPE_SZ)
        if (new_size >= 0)
          RETVAL = fcntl (rfh, F_SETPIPE_SZ, new_size);
        else
          RETVAL = fcntl (rfh, F_GETPIPE_SZ);
#else
        errno = ENOSYS;
        RETVAL = -1;
#endif
        OUTPUT:
        RETVAL

void
pipe2 (int flags = 0)
	PROTOTYPE: ;$
        PPCODE:
{
	int fd[2];
        int res;

        if (flags)
#if HAVE_PIPE2
          res = pipe2 (fd, flags);
#else
          res = (errno = ENOSYS, -1);
#endif
        else
          res = pipe (fd);

        if (!res)
          {
            EXTEND (SP, 2);
            PUSHs (newmortalFH (fd[0], O_RDONLY));
            PUSHs (newmortalFH (fd[1], O_WRONLY));
          }
}

void
pidfd_open (int pid, unsigned int flags = 0)
	PPCODE:
{
        /*GENDEF0_SYSCALL(pidfd_open,434)*/
        int fd = syscall (SYS_pidfd_open, pid, flags);
        XPUSHs (newmortalFH (fd, O_RDWR));
}

int
pidfd_send_signal (SV *pidfh, int sig, SV *siginfo = &PL_sv_undef, unsigned int flags = 0)
	PPCODE:
{
	int res;
#if HAVE_SIGINFO_T
	siginfo_t si = { 0 };

        if (SvOK (siginfo))
          {
            HV *hv;
            SV **svp;

            if (!SvROK (siginfo) || SvTYPE (SvRV (siginfo)) != SVt_PVHV)
              croak ("siginfo argument must be a hashref with 'code', 'pid', 'uid' and 'value_int' or 'value_ptr' members, caught");

            hv = (HV *)SvRV (siginfo);

            if ((svp = hv_fetchs (hv, "code"     , 0))) si.si_code            =         SvIV (*svp);
            if ((svp = hv_fetchs (hv, "pid"      , 0))) si.si_pid             =         SvIV (*svp);
            if ((svp = hv_fetchs (hv, "uid"      , 0))) si.si_uid             =         SvIV (*svp);
            if ((svp = hv_fetchs (hv, "value_int", 0))) si.si_value.sival_int =         SvIV (*svp);
            if ((svp = hv_fetchs (hv, "value_ptr", 0))) si.si_value.sival_ptr = (void *)SvIV (*svp);
          }

        /*GENDEF0_SYSCALL(pidfd_send_signal,424)*/
        res = syscall (SYS_pidfd_send_signal, s_fileno_croak (pidfh, 0), sig, SvOK (siginfo) ? &si : 0, flags);
#else
        res = (errno = ENOSYS, -1);
#endif

        XPUSHs (sv_2mortal (newSViv (res)));
}

void
pidfd_getfd (SV *pidfh, int targetfd, unsigned int flags = 0)
	PPCODE:
{
        /*GENDEF0_SYSCALL(pidfd_getfd,438)*/
        int fd = syscall (SYS_pidfd_getfd, s_fileno_croak (pidfh, 0), targetfd, flags);
        XPUSHs (newmortalFH (fd, O_RDWR));
}

void
eventfd (unsigned int initval = 0, int flags = 0)
	PPCODE:
{
	int fd;
#if HAVE_EVENTFD
        fd = eventfd (initval, flags);
#else
        fd = (errno = ENOSYS, -1);
#endif
	
        XPUSHs (newmortalFH (fd, O_RDWR));
}

void
timerfd_create (int clockid, int flags = 0)
	PPCODE:
{
	int fd;
#if HAVE_TIMERFD
        fd = timerfd_create (clockid, flags);
#else
        fd = (errno = ENOSYS, -1);
#endif
	
        XPUSHs (newmortalFH (fd, O_RDWR));
}

void
timerfd_settime (SV *fh, int flags, NV interval, NV value)
	PPCODE:
{
        int fd = s_fileno_croak (fh, 0);
#if HAVE_TIMERFD
	int res;
        struct itimerspec its, ots;

        ts_set (&its.it_interval, interval);
        ts_set (&its.it_value   , value);
        res = timerfd_settime (fd, flags, &its, &ots);

        if (!res)
          {
            EXTEND (SP, 2);
            PUSHs (newSVnv (ts_get (&ots.it_interval)));
            PUSHs (newSVnv (ts_get (&ots.it_value)));
          }
#else
        errno = ENOSYS;
#endif
}

void
timerfd_gettime (SV *fh)
	PPCODE:
{
        int fd = s_fileno_croak (fh, 0);
#if HAVE_TIMERFD
	int res;
        struct itimerspec ots;
        res = timerfd_gettime (fd, &ots);

        if (!res)
          {
            EXTEND (SP, 2);
            PUSHs (newSVnv (ts_get (&ots.it_interval)));
            PUSHs (newSVnv (ts_get (&ots.it_value)));
          }
#else
        errno = ENOSYS;
#endif
}

void
memfd_create (octet_string pathname, int flags = 0)
	PPCODE:
{
	int fd;
#if HAVE_MEMFD_CREATE
        fd = memfd_create (pathname, flags);
#else
        fd = (errno = ENOSYS, -1);
#endif
	
        XPUSHs (newmortalFH (fd, O_RDWR));
}

int
fexecve (SV *fh, SV *args, SV *envs = &PL_sv_undef)
	CODE:
{
	int fd = PerlIO_fileno (IoIFP (sv_2io (fh)));
        char **envp, **argv;
        argv = extract_stringvec (args, "IO::AIO::fexecve: args must be an array of strings");
        if (!SvOK (envs))
          {
            extern char **environ;
            envp = environ;
          }
        else
          envp = extract_stringvec (envs, "IO::AIO::fexecve: envs must be an array of strings");
#if HAVE_FEXECVE
          RETVAL = fexecve (fd, argv, envp);
#else
          RETVAL = (errno = ENOSYS, -1);
#endif
}
	OUTPUT: RETVAL

int
mount (octet_string special, octet_string path, octet_string fstype, UV flags = 0, octet_string_ornull data = 0)
	CODE:
#if HAVE_MOUNT
          RETVAL = mount (special, path, fstype, flags, data);
#else
          RETVAL = (errno = ENOSYS, -1);
#endif
        OUTPUT: RETVAL

int
umount (octet_string path, int flags = 0)
	CODE:
        if (flags)
#if HAVE_UMOUNT2
          RETVAL = umount2 (path, flags);
#else
          RETVAL = (errno = ENOSYS, -1);
#endif
        else
#if HAVE_UMOUNT
          RETVAL = umount (path);
#else
          RETVAL = (errno = ENOSYS, -1);
#endif
        OUTPUT: RETVAL

AIO.xs  view on Meta::CPAN

                  rl.rlim_max &= ~bit; /* too high, remove bit again */
              }

            /* now, raise the soft limit to the max permitted */
            if (0 == getrlimit (RLIMIT_NOFILE, &rl))
              {
                rl.rlim_cur = rl.rlim_max;
                if (0 == setrlimit (RLIMIT_NOFILE, &rl))
                  errno = EPERM;
              }
	  }
#endif
        fail:
        XSRETURN_UNDEF;
}

void _on_next_submit (SV *cb)
	CODE:
        SvREFCNT_dec (on_next_submit);
        on_next_submit = SvOK (cb) ? newSVsv (cb) : 0;

PROTOTYPES: DISABLE

MODULE = IO::AIO                PACKAGE = IO::AIO::WD

BOOT:
{
  newCONSTSUB (aio_stash, "CWD"       , newSVaio_wd (EIO_CWD       ));
  newCONSTSUB (aio_stash, "INVALID_WD", newSVaio_wd (EIO_INVALID_WD));
}

void
DESTROY (SV *self)
	CODE:
{
	aio_wd wd = SvAIO_WD (self);
#if HAVE_AT
        {
          SV *callback = &PL_sv_undef;
          dREQ; /* clobbers next_pri :/ */
          next_pri = req->pri; /* restore next_pri */
          req->pri = EIO_PRI_MAX; /* better use max. priority to conserve fds */
          req->type = EIO_WD_CLOSE;
          req->wd = wd;
          REQ_SEND;
        }
#else
        eio_wd_close_sync (wd);
#endif
}

MODULE = IO::AIO                PACKAGE = IO::AIO::REQ

void
cancel (aio_req_ornot req)
	CODE:
        eio_cancel (req);

void
cb (aio_req_ornot req, SV *callback = NO_INIT)
	PPCODE:
{
        if (GIMME_V != G_VOID)
          XPUSHs (req->callback ? sv_2mortal (newRV_inc (req->callback)) : &PL_sv_undef);

        if (items > 1)
          {
            SV *cb_cv = get_cb (callback);

            SvREFCNT_dec (req->callback);
            req->callback = SvREFCNT_inc (cb_cv);
          }
}

MODULE = IO::AIO                PACKAGE = IO::AIO::GRP

void
add (aio_req grp, ...)
        PPCODE:
{
	int i;

        if (grp->int1 == 2)
          croak ("cannot add requests to IO::AIO::GRP after the group finished");

	for (i = 1; i < items; ++i )
          {
            aio_req req;

            if (GIMME_V != G_VOID)
              XPUSHs (sv_2mortal (newSVsv (ST (i))));

            req = SvAIO_REQ (ST (i));

            if (req)
              eio_grp_add (grp, req);
          }
}

void
cancel_subs (aio_req_ornot req)
	CODE:
        req_cancel_subs (req);

void
result (aio_req grp, ...)
        CODE:
{
        int i;
        AV *av;

        grp->errorno = errno;

        av = newAV ();
        av_extend (av, items - 1);

        for (i = 1; i < items; ++i )
          av_push (av, newSVsv (ST (i)));

        SvREFCNT_dec (grp->sv1);
        grp->sv1 = (SV *)av;
}

void
errno (aio_req grp, int errorno = errno)
        CODE:
        grp->errorno = errorno;

void
limit (aio_req grp, int limit)
	CODE:
        eio_grp_limit (grp, limit);

void
feed (aio_req grp, SV *callback = &PL_sv_undef)
	CODE:
{
        SvREFCNT_dec (grp->sv2);
        grp->sv2  = newSVsv (callback);



( run in 1.371 second using v1.01-cache-2.11-cpan-71847e10f99 )