--- IO-AIO/AIO.xs 2011/09/27 02:16:49 1.198 +++ IO-AIO/AIO.xs 2011/10/04 18:22:37 1.206 @@ -343,20 +343,23 @@ static void req_destroy (aio_req req); static void req_cancel (aio_req req); -static void want_poll (void) +static void +want_poll (void) { /* write a dummy byte to the pipe so fh becomes ready */ s_epipe_signal (&respipe); } -static void done_poll (void) +static void +done_poll (void) { /* read any signals sent by the worker threads */ s_epipe_drain (&respipe); } /* must be called at most once */ -static SV *req_sv (aio_req req, HV *stash) +static SV * +req_sv (aio_req req, HV *stash) { if (!req->self) { @@ -370,14 +373,16 @@ static SV * newSVaio_wd (aio_wd wd) { - return sv_bless (newRV_noinc (newSViv ((long)wd)), aio_wd_stash); + return sv_bless (newRV_noinc (newSViv ((IV)wd)), aio_wd_stash); } -static aio_req SvAIO_REQ (SV *sv) +static aio_req +SvAIO_REQ (SV *sv) { MAGIC *mg; if (!SvROK (sv) + /* for speed reasons, we do not verify that SvROK actually has a stash ptr */ || (SvSTASH (SvRV (sv)) != aio_grp_stash && SvSTASH (SvRV (sv)) != aio_req_stash && !sv_derived_from (sv, "IO::AIO::REQ"))) @@ -388,17 +393,19 @@ return mg ? (aio_req)mg->mg_ptr : 0; } -static aio_wd SvAIO_WD (SV *sv) +static aio_wd +SvAIO_WD (SV *sv) { if (!SvROK (sv) - || SvSTASH (SvRV (sv)) != aio_wd_stash - || SvTYPE (SvRV (sv)) != SVt_PVMG) + || SvTYPE (SvRV (sv)) != SVt_PVMG + || SvSTASH (SvRV (sv)) != aio_wd_stash) croak ("IO::AIO: expected a working directory object as returned by aio_wd"); return (aio_wd)(long)SvIVX (SvRV (sv)); } -static void aio_grp_feed (aio_req grp) +static void +aio_grp_feed (aio_req grp) { if (grp->sv2 && SvOK (grp->sv2)) { @@ -416,7 +423,8 @@ } } -static void req_submit (eio_req *req) +static void +req_submit (eio_req *req) { eio_submit (req); @@ -433,7 +441,8 @@ } } -static int req_invoke (eio_req *req) +static int +req_invoke (eio_req *req) { if (req->flags & FLAG_SV2_RO_OFF) SvREADONLY_off (req->sv2); @@ -465,7 +474,7 @@ switch (req->type) { case EIO_WD_OPEN: - PUSHs (sv_2mortal (newSVaio_wd (req->wd))); + PUSHs (req->result ? &PL_sv_undef : sv_2mortal (newSVaio_wd (req->wd))); break; case EIO_READDIR: @@ -668,7 +677,8 @@ return !!SvTRUE (ERRSV); } -static void req_destroy (aio_req req) +static void +req_destroy (aio_req req) { if (req->self) { @@ -682,10 +692,11 @@ SvREFCNT_dec (req->sv4); SvREFCNT_dec (req->callback); - Safefree (req); + free (req); } -static void req_cancel_subs (aio_req grp) +static void +req_cancel_subs (aio_req grp) { if (grp->type != EIO_GROUP) return; @@ -696,13 +707,15 @@ eio_grp_cancel (grp); } -static void create_respipe (void) +static void ecb_cold +create_respipe (void) { if (s_epipe_renew (&respipe)) croak ("IO::AIO: unable to initialize result pipe"); } -static void poll_wait (void) +static void +poll_wait (void) { while (eio_nreqs ()) { @@ -721,7 +734,8 @@ } } -static int poll_cb (void) +static int +poll_cb (void) { for (;;) { @@ -764,7 +778,8 @@ #define MMAP_MAGIC PERL_MAGIC_ext -static int mmap_free (pTHX_ SV *sv, MAGIC *mg) +static int ecb_cold +mmap_free (pTHX_ SV *sv, MAGIC *mg) { int old_errno = errno; munmap (mg->mg_ptr, (size_t)mg->mg_obj); @@ -790,26 +805,35 @@ /*****************************************************************************/ -static SV * get_cb (SV *cb_sv) +static SV * +get_cb (SV *cb_sv) { SvGETMAGIC (cb_sv); return SvOK (cb_sv) ? s_get_cv_croak (cb_sv) : 0; } +static aio_req ecb_noinline +dreq (SV *callback) +{ + SV *cb_cv; + aio_req req; + int req_pri = next_pri; + next_pri = EIO_PRI_DEFAULT; + + cb_cv = get_cb (callback); + + req = calloc (sizeof (*req), 1); + if (!req) + croak ("out of memory during eio_req allocation"); + + req->callback = SvREFCNT_inc (cb_cv); + req->pri = req_pri; + + return req; +} + #define dREQ \ - SV *cb_cv; \ - aio_req req; \ - int req_pri = next_pri; \ - next_pri = EIO_PRI_DEFAULT; \ - \ - cb_cv = get_cb (callback); \ - \ - Newz (0, req, 1, eio_req); \ - if (!req) \ - croak ("out of memory during eio_req allocation"); \ - \ - req->callback = SvREFCNT_inc (cb_cv); \ - req->pri = req_pri + aio_req req = dreq (callback); \ #define REQ_SEND \ PUTBACK; \ @@ -819,40 +843,49 @@ if (GIMME_V != G_VOID) \ XPUSHs (req_sv (req, aio_req_stash)); -static void +ecb_inline void req_set_path (aio_req req, SV *path, SV **wdsv, SV **pathsv, eio_wd *wd, void **ptr) { if (expect_false (SvROK (path))) { - AV *av = (AV *)SvRV (path); + SV *rv = SvRV (path); SV *wdob; - if (SvTYPE (av) != SVt_PVAV || AvFILLp (av) != 1) - croak ("IO::AIO: pathname arguments must be specified as strings or [wd, path] arrayrefs"); - - path = AvARRAY (av)[1]; - wdob = AvARRAY (av)[0]; + if (SvTYPE (rv) == SVt_PVAV && AvFILLp (rv) == 1) + { + path = AvARRAY (rv)[1]; + wdob = AvARRAY (rv)[0]; - if (SvOK (wdob)) + if (SvOK (wdob)) + { + *wd = SvAIO_WD (wdob); + *wdsv = SvREFCNT_inc_NN (SvRV (wdob)); + } + else + *wd = EIO_INVALID_WD; + } + else if (SvTYPE (rv) == SVt_PVMG && SvSTASH (rv) == aio_wd_stash) { - *wd = SvAIO_WD (wdob); - *wdsv = SvREFCNT_inc_NN (SvRV (wdob)); + *wd = (aio_wd)(long)SvIVX (rv); + *wdsv = SvREFCNT_inc_NN (rv); + *ptr = "."; + return; /* path set to "." */ } else - *wd = EIO_INVALID_WD; + croak ("IO::AIO: pathname arguments must be specified as a string, an IO::AIO::WD object or a [IO::AIO::WD, path] pair"); } *pathsv = newSVsv (path); *ptr = SvPVbyte_nolen (*pathsv); } -static void +static void ecb_noinline req_set_path1 (aio_req req, SV *path) { req_set_path (req, path, &req->sv1, &req->sv3, &req->wd, &req->ptr1); } -static void +static void ecb_noinline req_set_fh_or_path (aio_req req, int type_path, int type_fh, SV *fh_or_path) { SV *rv = SvROK (fh_or_path) ? SvRV (fh_or_path) : fh_or_path; @@ -872,9 +905,10 @@ req_set_path1 (req, fh_or_path); break; } - } +XS(boot_IO__AIO) ecb_cold; + MODULE = IO::AIO PACKAGE = IO::AIO PROTOTYPES: ENABLE @@ -1282,8 +1316,8 @@ { dREQ; - req->sv1 = newSVsv (fh_or_path); req_set_fh_or_path (req, ix, ix == EIO_STATVFS ? EIO_FSTATVFS : EIO_FSTAT, fh_or_path); + REQ_SEND; } @@ -1330,9 +1364,6 @@ void aio_chmod (SV8 *fh_or_path, int mode, SV *callback=&PL_sv_undef) - ALIAS: - aio_chmod = EIO_CHMOD - aio_mkdir = EIO_MKDIR PPCODE: { dREQ; @@ -1374,6 +1405,19 @@ } 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 @@ -1398,7 +1442,7 @@ PPCODE: { dREQ; - eio_wd wd2; + eio_wd wd2 = 0; req->type = ix; req_set_path1 (req, oldpath); @@ -1763,11 +1807,15 @@ { aio_wd wd = SvAIO_WD (self); #if HAVE_AT - SV *callback = &PL_sv_undef; - dREQ; /* clobbers next_pri :/ */ - req->type = EIO_WD_CLOSE; - req->wd = wd; - REQ_SEND; + { + 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