--- IO-AIO/AIO.xs 2017/09/22 05:20:39 1.250 +++ IO-AIO/AIO.xs 2018/01/06 01:04:42 1.251 @@ -173,6 +173,97 @@ /*****************************************************************************/ +#if !_POSIX_MAPPED_FILES +# define mmap(addr,length,prot,flags,fd,offs) EIO_ENOSYS () +# define munmap(addr,length) EIO_ENOSYS () +#endif + +#if !_POSIX_MEMORY_PROTECTION +# define mprotect(addr,len,prot) EIO_ENOSYS () +#endif + +#define FOREIGN_MAGIC PERL_MAGIC_ext + +static int ecb_cold +mmap_free (pTHX_ SV *sv, MAGIC *mg) +{ + int old_errno = errno; + munmap (mg->mg_ptr, (size_t)mg->mg_obj); + errno = old_errno; + + mg->mg_obj = 0; /* just in case */ + + SvREADONLY_off (sv); + + if (SvPVX (sv) != mg->mg_ptr) + croak ("ERROR: IO::AIO::mmap-mapped scalar changed location, detected"); + + SvCUR_set (sv, 0); + SvPVX (sv) = 0; + SvOK_off (sv); + + return 0; +} + +static MGVTBL mmap_vtbl = { + 0, 0, 0, 0, mmap_free +}; + +static int ecb_cold +sysfree_free (pTHX_ SV *sv, MAGIC *mg) +{ + free (mg->mg_ptr); + mg->mg_obj = 0; /* just in case */ + + SvREADONLY_off (sv); + + if (SvPVX (sv) != mg->mg_ptr) + croak ("ERROR: IO::AIO mapped scalar changed location, detected"); + + SvCUR_set (sv, 0); + SvPVX (sv) = 0; + SvOK_off (sv); + + return 0; +} + +static MGVTBL sysfree_vtbl = { + 0, 0, 0, 0, sysfree_free +}; + +/*****************************************************************************/ + +/* helper: set scalar to foreign ptr with custom free */ +static void +sv_set_foreign (SV *sv, const MGVTBL *const vtbl, void *addr, IV length) +{ + sv_force_normal (sv); + + /* we store the length in mg_obj, as namlen is I32 :/ */ + sv_magicext (sv, 0, FOREIGN_MAGIC, vtbl, (char *)addr, 0) + ->mg_obj = (SV *)length; + + SvUPGRADE (sv, SVt_PV); /* nop... */ + + if (SvLEN (sv)) + Safefree (SvPVX (sv)); + + SvPVX (sv) = (char *)addr; + SvCUR_set (sv, length); + SvLEN_set (sv, 0); + SvPOK_only (sv); +} + +static void +sv_clear_foreign (SV *sv) +{ + /* todo: iterate over magic and only free ours, but of course */ + /* the perl5porters will call that (correct) behaviour buggy */ + sv_unmagic (sv, FOREIGN_MAGIC); +} + +/*****************************************************************************/ + static void fiemap (eio_req *req) { @@ -599,6 +690,24 @@ } break; + case EIO_SLURP: + { + if (req->result >= 0) + { + /* if length was originally not known, we steal the malloc'ed memory */ + if (req->flags & EIO_FLAG_PTR2_FREE) + { + req->flags &= ~EIO_FLAG_PTR2_FREE; + sv_set_foreign (req->sv2, &sysfree_vtbl, req->ptr2, req->result); + } + else + SvCUR_set (req->sv2, req->result); + } + + PUSHs (sv_result); + } + break; + case EIO_CUSTOM: if (req->feed == fiemap) { @@ -754,44 +863,6 @@ /*****************************************************************************/ -#if !_POSIX_MAPPED_FILES -# define mmap(addr,length,prot,flags,fd,offs) EIO_ENOSYS () -# define munmap(addr,length) EIO_ENOSYS () -#endif - -#if !_POSIX_MEMORY_PROTECTION -# define mprotect(addr,len,prot) EIO_ENOSYS () -#endif - -#define MMAP_MAGIC PERL_MAGIC_ext - -static int ecb_cold -mmap_free (pTHX_ SV *sv, MAGIC *mg) -{ - int old_errno = errno; - munmap (mg->mg_ptr, (size_t)mg->mg_obj); - errno = old_errno; - - mg->mg_obj = 0; /* just in case */ - - SvREADONLY_off (sv); - - if (SvPVX (sv) != mg->mg_ptr) - croak ("ERROR: IO::AIO::mmap-mapped scalar changed location, detected"); - - SvCUR_set (sv, 0); - SvPVX (sv) = 0; - SvOK_off (sv); - - return 0; -} - -static MGVTBL mmap_vtbl = { - 0, 0, 0, 0, mmap_free -}; - -/*****************************************************************************/ - static SV * get_cb (SV *cb_sv) { @@ -1346,7 +1417,7 @@ { /* read: check type and grow scalar as necessary */ if (!SvPOK (data) || SvLEN (data) >= SvCUR (data)) - svptr = sv_grow (data, len + dataoffset + 1); + svptr = sv_grow (data, len + dataoffset); else if (SvCUR (data) < len + dataoffset) croak ("length + dataoffset outside of scalar, and cannot grow"); } @@ -1740,6 +1811,44 @@ } 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); + 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: { @@ -1883,39 +1992,25 @@ void mmap (SV *scalar, STRLEN length, int prot, int flags, SV *fh = &PL_sv_undef, off_t offset = 0) PPCODE: - sv_unmagic (scalar, MMAP_MAGIC); + 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_force_normal (scalar); - - /* we store the length in mg_obj, as namlen is I32 :/ */ - sv_magicext (scalar, 0, MMAP_MAGIC, &mmap_vtbl, (char *)addr, 0) - ->mg_obj = (SV *)length; - - SvUPGRADE (scalar, SVt_PV); /* nop... */ + sv_set_foreign (scalar, &mmap_vtbl, addr, length); if (!(prot & PROT_WRITE)) SvREADONLY_on (scalar); - if (SvLEN (scalar)) - Safefree (SvPVX (scalar)); - - SvPVX (scalar) = (char *)addr; - SvCUR_set (scalar, length); - SvLEN_set (scalar, 0); - SvPOK_only (scalar); - XSRETURN_YES; } void munmap (SV *scalar) CODE: - sv_unmagic (scalar, MMAP_MAGIC); + sv_clear_foreign (scalar); int madvise (SV *scalar, STRLEN offset = 0, SV *length = &PL_sv_undef, IV advice_or_prot)