… | |
… | |
166 | static struct CoroAPI coroapi; |
166 | static struct CoroAPI coroapi; |
167 | static AV *main_mainstack; /* used to differentiate between $main and others */ |
167 | static AV *main_mainstack; /* used to differentiate between $main and others */ |
168 | static JMPENV *main_top_env; |
168 | static JMPENV *main_top_env; |
169 | static HV *coro_state_stash, *coro_stash; |
169 | static HV *coro_state_stash, *coro_stash; |
170 | static volatile SV *coro_mortal; /* will be freed/thrown after next transfer */ |
170 | static volatile SV *coro_mortal; /* will be freed/thrown after next transfer */ |
171 | static volatile struct coro *transfer_next; |
|
|
172 | |
171 | |
173 | static GV *irsgv; /* $/ */ |
172 | static GV *irsgv; /* $/ */ |
174 | static GV *stdoutgv; /* *STDOUT */ |
173 | static GV *stdoutgv; /* *STDOUT */ |
175 | static SV *rv_diehook; |
174 | static SV *rv_diehook; |
176 | static SV *rv_warnhook; |
175 | static SV *rv_warnhook; |
… | |
… | |
389 | static MGVTBL coro_cv_vtbl = { |
388 | static MGVTBL coro_cv_vtbl = { |
390 | 0, 0, 0, 0, |
389 | 0, 0, 0, 0, |
391 | coro_cv_free |
390 | coro_cv_free |
392 | }; |
391 | }; |
393 | |
392 | |
394 | #define CORO_MAGIC(sv, type) \ |
393 | #define CORO_MAGIC(sv, type) \ |
395 | SvMAGIC (sv) \ |
394 | expect_true (SvMAGIC (sv)) \ |
396 | ? SvMAGIC (sv)->mg_type == type \ |
395 | ? expect_true (SvMAGIC (sv)->mg_type == type) \ |
397 | ? SvMAGIC (sv) \ |
396 | ? SvMAGIC (sv) \ |
398 | : mg_find (sv, type) \ |
397 | : mg_find (sv, type) \ |
399 | : 0 |
398 | : 0 |
400 | |
399 | |
401 | #define CORO_MAGIC_cv(cv) CORO_MAGIC (((SV *)(cv)), CORO_MAGIC_type_cv) |
400 | #define CORO_MAGIC_cv(cv) CORO_MAGIC (((SV *)(cv)), CORO_MAGIC_type_cv) |
402 | #define CORO_MAGIC_state(sv) CORO_MAGIC (((SV *)(sv)), CORO_MAGIC_type_state) |
401 | #define CORO_MAGIC_state(sv) CORO_MAGIC (((SV *)(sv)), CORO_MAGIC_type_state) |
403 | |
402 | |
… | |
… | |
424 | mg = CORO_MAGIC_state (coro); |
423 | mg = CORO_MAGIC_state (coro); |
425 | return (struct coro *)mg->mg_ptr; |
424 | return (struct coro *)mg->mg_ptr; |
426 | } |
425 | } |
427 | |
426 | |
428 | #define SvSTATE(sv) SvSTATE_ (aTHX_ (sv)) |
427 | #define SvSTATE(sv) SvSTATE_ (aTHX_ (sv)) |
|
|
428 | |
|
|
429 | /* fastert than SvSTATE, but expects a coroutine hv */ |
|
|
430 | INLINE struct coro * |
|
|
431 | SvSTATE_hv (SV *sv) |
|
|
432 | { |
|
|
433 | MAGIC *mg = expect_true (SvMAGIC (sv)->mg_type == CORO_MAGIC_type_state) |
|
|
434 | ? SvMAGIC (sv) |
|
|
435 | : mg_find (sv, CORO_MAGIC_type_state); |
|
|
436 | |
|
|
437 | return (struct coro *)mg->mg_ptr; |
|
|
438 | } |
|
|
439 | |
|
|
440 | #define SvSTATE_current SvSTATE_hv (SvRV (coro_current)) |
429 | |
441 | |
430 | /* the next two functions merely cache the padlists */ |
442 | /* the next two functions merely cache the padlists */ |
431 | static void |
443 | static void |
432 | get_padlist (pTHX_ CV *cv) |
444 | get_padlist (pTHX_ CV *cv) |
433 | { |
445 | { |
… | |
… | |
915 | static int |
927 | static int |
916 | runops_trace (pTHX) |
928 | runops_trace (pTHX) |
917 | { |
929 | { |
918 | COP *oldcop = 0; |
930 | COP *oldcop = 0; |
919 | int oldcxix = -2; |
931 | int oldcxix = -2; |
920 | struct coro *coro = SvSTATE (coro_current); /* trace cctx is tied to specific coro */ |
932 | struct coro *coro = SvSTATE_current; /* trace cctx is tied to specific coro */ |
921 | coro_cctx *cctx = coro->cctx; |
933 | coro_cctx *cctx = coro->cctx; |
922 | |
934 | |
923 | while ((PL_op = CALL_FPTR (PL_op->op_ppaddr) (aTHX))) |
935 | while ((PL_op = CALL_FPTR (PL_op->op_ppaddr) (aTHX))) |
924 | { |
936 | { |
925 | PERL_ASYNC_CHECK (); |
937 | PERL_ASYNC_CHECK (); |
… | |
… | |
1074 | |
1086 | |
1075 | /* the tail of transfer: execute stuff we can only do after a transfer */ |
1087 | /* the tail of transfer: execute stuff we can only do after a transfer */ |
1076 | INLINE void |
1088 | INLINE void |
1077 | transfer_tail (pTHX) |
1089 | transfer_tail (pTHX) |
1078 | { |
1090 | { |
1079 | struct coro *next = (struct coro *)transfer_next; |
|
|
1080 | assert (!(transfer_next = 0)); /* just used for the side effect when asserts are enabled */ |
|
|
1081 | assert (("FATAL: next coroutine was zero in transfer_tail (please report)", next)); |
|
|
1082 | |
|
|
1083 | free_coro_mortal (aTHX); |
1091 | free_coro_mortal (aTHX); |
1084 | |
|
|
1085 | if (expect_false (next->throw)) |
|
|
1086 | { |
|
|
1087 | SV *exception = sv_2mortal (next->throw); |
|
|
1088 | |
|
|
1089 | next->throw = 0; |
|
|
1090 | sv_setsv (ERRSV, exception); |
|
|
1091 | croak (0); |
|
|
1092 | } |
|
|
1093 | } |
1092 | } |
1094 | |
1093 | |
1095 | /* |
1094 | /* |
1096 | * this is a _very_ stripped down perl interpreter ;) |
1095 | * this is a _very_ stripped down perl interpreter ;) |
1097 | */ |
1096 | */ |
… | |
… | |
1112 | |
1111 | |
1113 | /* inject a fake subroutine call to cctx_init */ |
1112 | /* inject a fake subroutine call to cctx_init */ |
1114 | cctx_prepare (aTHX_ (coro_cctx *)arg); |
1113 | cctx_prepare (aTHX_ (coro_cctx *)arg); |
1115 | |
1114 | |
1116 | /* cctx_run is the alternative tail of transfer() */ |
1115 | /* cctx_run is the alternative tail of transfer() */ |
1117 | /* TODO: throwing an exception here might be deadly, VERIFY */ |
|
|
1118 | transfer_tail (aTHX); |
1116 | transfer_tail (aTHX); |
1119 | |
1117 | |
1120 | /* somebody or something will hit me for both perl_run and PL_restartop */ |
1118 | /* somebody or something will hit me for both perl_run and PL_restartop */ |
1121 | PL_restartop = PL_op; |
1119 | PL_restartop = PL_op; |
1122 | perl_run (PL_curinterp); |
1120 | perl_run (PL_curinterp); |
… | |
… | |
1364 | ++next->usecount; |
1362 | ++next->usecount; |
1365 | |
1363 | |
1366 | if (expect_true (!next->cctx)) |
1364 | if (expect_true (!next->cctx)) |
1367 | next->cctx = cctx_get (aTHX); |
1365 | next->cctx = cctx_get (aTHX); |
1368 | |
1366 | |
1369 | assert (("FATAL: transfer_next already nonzero in Coro (please report)", !transfer_next)); |
|
|
1370 | transfer_next = next; |
|
|
1371 | |
|
|
1372 | if (expect_false (prev__cctx != next->cctx)) |
1367 | if (expect_false (prev__cctx != next->cctx)) |
1373 | { |
1368 | { |
1374 | prev__cctx->top_env = PL_top_env; |
1369 | prev__cctx->top_env = PL_top_env; |
1375 | PL_top_env = next->cctx->top_env; |
1370 | PL_top_env = next->cctx->top_env; |
1376 | coro_transfer (&prev__cctx->cctx, &next->cctx->cctx); |
1371 | coro_transfer (&prev__cctx->cctx, &next->cctx->cctx); |
… | |
… | |
1486 | TRANSFER (ta, 1); |
1481 | TRANSFER (ta, 1); |
1487 | } |
1482 | } |
1488 | |
1483 | |
1489 | /** Coro ********************************************************************/ |
1484 | /** Coro ********************************************************************/ |
1490 | |
1485 | |
1491 | static void |
1486 | INLINE void |
1492 | coro_enq (pTHX_ SV *coro_sv) |
1487 | coro_enq (pTHX_ struct coro *coro) |
1493 | { |
1488 | { |
1494 | av_push (coro_ready [SvSTATE (coro_sv)->prio - PRIO_MIN], coro_sv); |
1489 | av_push (coro_ready [coro->prio - PRIO_MIN], SvREFCNT_inc_NN (coro->hv)); |
1495 | } |
1490 | } |
1496 | |
1491 | |
1497 | static SV * |
1492 | INLINE SV * |
1498 | coro_deq (pTHX) |
1493 | coro_deq (pTHX) |
1499 | { |
1494 | { |
1500 | int prio; |
1495 | int prio; |
1501 | |
1496 | |
1502 | for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= 0; ) |
1497 | for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= 0; ) |
… | |
… | |
1524 | coro->flags |= CF_READY; |
1519 | coro->flags |= CF_READY; |
1525 | |
1520 | |
1526 | sv_hook = coro_nready ? 0 : coro_readyhook; |
1521 | sv_hook = coro_nready ? 0 : coro_readyhook; |
1527 | xs_hook = coro_nready ? 0 : coroapi.readyhook; |
1522 | xs_hook = coro_nready ? 0 : coroapi.readyhook; |
1528 | |
1523 | |
1529 | coro_enq (aTHX_ SvREFCNT_inc_NN (coro_sv)); |
1524 | coro_enq (aTHX_ coro); |
1530 | ++coro_nready; |
1525 | ++coro_nready; |
1531 | |
1526 | |
1532 | if (sv_hook) |
1527 | if (sv_hook) |
1533 | { |
1528 | { |
1534 | dSP; |
1529 | dSP; |
… | |
… | |
1582 | FREETMPS; |
1577 | FREETMPS; |
1583 | LEAVE; |
1578 | LEAVE; |
1584 | continue; |
1579 | continue; |
1585 | } |
1580 | } |
1586 | |
1581 | |
1587 | ta->next = SvSTATE (next_sv); |
1582 | ta->next = SvSTATE_hv (next_sv); |
1588 | |
1583 | |
1589 | /* cannot transfer to destroyed coros, skip and look for next */ |
1584 | /* cannot transfer to destroyed coros, skip and look for next */ |
1590 | if (expect_false (ta->next->flags & CF_DESTROYED)) |
1585 | if (expect_false (ta->next->flags & CF_DESTROYED)) |
1591 | { |
1586 | { |
1592 | SvREFCNT_dec (next_sv); |
1587 | SvREFCNT_dec (next_sv); |
… | |
… | |
1598 | break; |
1593 | break; |
1599 | } |
1594 | } |
1600 | |
1595 | |
1601 | /* free this only after the transfer */ |
1596 | /* free this only after the transfer */ |
1602 | prev_sv = SvRV (coro_current); |
1597 | prev_sv = SvRV (coro_current); |
1603 | ta->prev = SvSTATE (prev_sv); |
1598 | ta->prev = SvSTATE_hv (prev_sv); |
1604 | TRANSFER_CHECK (*ta); |
1599 | TRANSFER_CHECK (*ta); |
1605 | assert (("FATAL: next coroutine isn't marked as ready in Coro (please report)", ta->next->flags & CF_READY)); |
1600 | assert (("FATAL: next coroutine isn't marked as ready in Coro (please report)", ta->next->flags & CF_READY)); |
1606 | ta->next->flags &= ~CF_READY; |
1601 | ta->next->flags &= ~CF_READY; |
1607 | SvRV_set (coro_current, next_sv); |
1602 | SvRV_set (coro_current, next_sv); |
1608 | |
1603 | |
… | |
… | |
1771 | PerlIOBuf_set_ptrcnt, |
1766 | PerlIOBuf_set_ptrcnt, |
1772 | }; |
1767 | }; |
1773 | |
1768 | |
1774 | /*****************************************************************************/ |
1769 | /*****************************************************************************/ |
1775 | |
1770 | |
1776 | static const CV *slf_cv; /* for quick consistency check */ |
|
|
1777 | |
|
|
1778 | static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */ |
1771 | static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */ |
|
|
1772 | static const CV *slf_cv; |
1779 | static SV *slf_arg0; |
1773 | static SV *slf_arg0; |
1780 | static SV *slf_arg1; |
1774 | static SV *slf_arg1; |
1781 | static SV *slf_arg2; |
1775 | static SV *slf_arg2; |
|
|
1776 | static I32 slf_ax; /* top of stack, for restore */ |
1782 | |
1777 | |
1783 | /* this restores the stack in the case we patched the entersub, to */ |
1778 | /* this restores the stack in the case we patched the entersub, to */ |
1784 | /* recreate the stack frame as perl will on following calls */ |
1779 | /* recreate the stack frame as perl will on following calls */ |
1785 | /* since entersub cleared the stack */ |
1780 | /* since entersub cleared the stack */ |
1786 | static OP * |
1781 | static OP * |
1787 | pp_restore (pTHX) |
1782 | pp_restore (pTHX) |
1788 | { |
1783 | { |
1789 | dSP; |
1784 | SV **SP = PL_stack_base + slf_ax; |
1790 | |
1785 | |
1791 | PUSHMARK (SP); |
1786 | PUSHMARK (SP); |
1792 | |
1787 | |
1793 | EXTEND (SP, 3); |
1788 | EXTEND (SP, 3); |
1794 | if (slf_arg0) PUSHs (sv_2mortal (slf_arg0)); |
1789 | if (slf_arg0) PUSHs (sv_2mortal (slf_arg0)); |
… | |
… | |
1819 | slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta) |
1814 | slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta) |
1820 | { |
1815 | { |
1821 | SV **arg = (SV **)slf_frame.data; |
1816 | SV **arg = (SV **)slf_frame.data; |
1822 | |
1817 | |
1823 | prepare_transfer (aTHX_ ta, arg [0], arg [1]); |
1818 | prepare_transfer (aTHX_ ta, arg [0], arg [1]); |
|
|
1819 | |
|
|
1820 | /* if the destination has ->throw set, then copy it */ |
|
|
1821 | /* into the current coro's throw slot, so it will be raised */ |
|
|
1822 | /* after the schedule */ |
|
|
1823 | if (expect_false (ta->next->throw)) |
|
|
1824 | { |
|
|
1825 | struct coro *coro = SvSTATE_current; |
|
|
1826 | SvREFCNT_dec (coro->throw); |
|
|
1827 | coro->throw = ta->next->throw; |
|
|
1828 | ta->next->throw = 0; |
|
|
1829 | } |
1824 | } |
1830 | } |
1825 | |
1831 | |
1826 | static void |
1832 | static void |
1827 | slf_init_transfer (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) |
1833 | slf_init_transfer (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) |
1828 | { |
1834 | { |
… | |
… | |
1883 | /* do a quick consistency check on the "function" object, and if it isn't */ |
1889 | /* do a quick consistency check on the "function" object, and if it isn't */ |
1884 | /* for us, divert to the real entersub */ |
1890 | /* for us, divert to the real entersub */ |
1885 | if (SvTYPE (gv) != SVt_PVGV || !(CvFLAGS (GvCV (gv)) & CVf_SLF)) |
1891 | if (SvTYPE (gv) != SVt_PVGV || !(CvFLAGS (GvCV (gv)) & CVf_SLF)) |
1886 | return PL_ppaddr[OP_ENTERSUB](aTHX); |
1892 | return PL_ppaddr[OP_ENTERSUB](aTHX); |
1887 | |
1893 | |
1888 | /* pop args */ |
|
|
1889 | SP = PL_stack_base + POPMARK; |
|
|
1890 | |
|
|
1891 | if (!(PL_op->op_flags & OPf_STACKED)) |
1894 | if (!(PL_op->op_flags & OPf_STACKED)) |
1892 | { |
1895 | { |
1893 | /* ampersand-form of call, use @_ instead of stack */ |
1896 | /* ampersand-form of call, use @_ instead of stack */ |
1894 | AV *av = GvAV (PL_defgv); |
1897 | AV *av = GvAV (PL_defgv); |
1895 | arg = AvARRAY (av); |
1898 | arg = AvARRAY (av); |
1896 | items = AvFILLp (av) + 1; |
1899 | items = AvFILLp (av) + 1; |
1897 | } |
1900 | } |
1898 | |
1901 | |
1899 | PUTBACK; |
|
|
1900 | |
|
|
1901 | /* now call the init function, which needs to set up slf_frame */ |
1902 | /* now call the init function, which needs to set up slf_frame */ |
1902 | ((coro_slf_cb)CvXSUBANY (GvCV (gv)).any_ptr) |
1903 | ((coro_slf_cb)CvXSUBANY (GvCV (gv)).any_ptr) |
1903 | (aTHX_ &slf_frame, GvCV (gv), arg, items); |
1904 | (aTHX_ &slf_frame, GvCV (gv), arg, items); |
|
|
1905 | |
|
|
1906 | /* pop args */ |
|
|
1907 | SP = PL_stack_base + POPMARK; |
|
|
1908 | |
|
|
1909 | PUTBACK; |
1904 | } |
1910 | } |
1905 | |
1911 | |
1906 | /* now that we have a slf_frame, interpret it! */ |
1912 | /* now that we have a slf_frame, interpret it! */ |
1907 | /* we use a callback system not to make the code needlessly */ |
1913 | /* we use a callback system not to make the code needlessly */ |
1908 | /* complicated, but so we can run multiple perl coros from one cctx */ |
1914 | /* complicated, but so we can run multiple perl coros from one cctx */ |
… | |
… | |
1935 | } |
1941 | } |
1936 | |
1942 | |
1937 | PUTBACK; |
1943 | PUTBACK; |
1938 | } |
1944 | } |
1939 | |
1945 | |
|
|
1946 | { |
|
|
1947 | struct coro *coro = SvSTATE_current; |
|
|
1948 | |
|
|
1949 | if (expect_false (coro->throw)) |
|
|
1950 | { |
|
|
1951 | SV *exception = sv_2mortal (coro->throw); |
|
|
1952 | |
|
|
1953 | coro->throw = 0; |
|
|
1954 | sv_setsv (ERRSV, exception); |
|
|
1955 | croak (0); |
|
|
1956 | } |
|
|
1957 | } |
|
|
1958 | |
1940 | return NORMAL; |
1959 | return NORMAL; |
1941 | } |
1960 | } |
1942 | |
1961 | |
1943 | static void |
1962 | static void |
1944 | api_execute_slf (pTHX_ CV *cv, coro_slf_cb init_cb, SV **arg, int items) |
1963 | api_execute_slf (pTHX_ CV *cv, coro_slf_cb init_cb, I32 ax) |
1945 | { |
1964 | { |
|
|
1965 | SV **arg = PL_stack_base + ax; |
|
|
1966 | int items = PL_stack_sp - arg + 1; |
|
|
1967 | |
1946 | assert (("FATAL: SLF call with illegal CV value", !CvANON (cv))); |
1968 | assert (("FATAL: SLF call with illegal CV value", !CvANON (cv))); |
1947 | |
1969 | |
1948 | if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB] |
1970 | if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB] |
1949 | && PL_op->op_ppaddr != pp_slf) |
1971 | && PL_op->op_ppaddr != pp_slf) |
1950 | croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught"); |
1972 | croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught"); |
1951 | |
1973 | |
|
|
1974 | #if 0 |
1952 | if (items > 3) |
1975 | if (items > 3) |
1953 | croak ("Coro only supports up to three arguments to SLF functions currently (not %d), caught", items); |
1976 | croak ("Coro only supports up to three arguments to SLF functions currently (not %d), caught", items); |
|
|
1977 | #endif |
1954 | |
1978 | |
1955 | CvFLAGS (cv) |= CVf_SLF; |
1979 | CvFLAGS (cv) |= CVf_SLF; |
1956 | CvXSUBANY (cv).any_ptr = (void *)init_cb; |
1980 | CvXSUBANY (cv).any_ptr = (void *)init_cb; |
1957 | slf_cv = cv; |
1981 | slf_cv = cv; |
1958 | |
1982 | |
1959 | /* we patch the op, and then re-run the whole call */ |
1983 | /* we patch the op, and then re-run the whole call */ |
1960 | /* we have to put the same argument on the stack for this to work */ |
1984 | /* we have to put the same argument on the stack for this to work */ |
1961 | /* and this will be done by pp_restore */ |
1985 | /* and this will be done by pp_restore */ |
1962 | slf_restore.op_next = (OP *)&slf_restore; |
1986 | slf_restore.op_next = (OP *)&slf_restore; |
1963 | slf_restore.op_type = OP_CUSTOM; |
1987 | slf_restore.op_type = OP_CUSTOM; |
1964 | slf_restore.op_ppaddr = pp_restore; |
1988 | slf_restore.op_ppaddr = pp_restore; |
1965 | slf_restore.op_first = PL_op; |
1989 | slf_restore.op_first = PL_op; |
1966 | |
1990 | |
|
|
1991 | slf_ax = ax - 1; /* undo the ax++ inside dAXMARK */ |
1967 | slf_arg0 = items > 0 ? SvREFCNT_inc (arg [0]) : 0; |
1992 | slf_arg0 = items > 0 ? SvREFCNT_inc (arg [0]) : 0; |
1968 | slf_arg1 = items > 1 ? SvREFCNT_inc (arg [1]) : 0; |
1993 | slf_arg1 = items > 1 ? SvREFCNT_inc (arg [1]) : 0; |
1969 | slf_arg2 = items > 2 ? SvREFCNT_inc (arg [2]) : 0; |
1994 | slf_arg2 = items > 2 ? SvREFCNT_inc (arg [2]) : 0; |
1970 | |
1995 | |
1971 | PL_op->op_ppaddr = pp_slf; |
1996 | PL_op->op_ppaddr = pp_slf; |
|
|
1997 | PL_op->op_type = OP_CUSTOM; /* maybe we should leave it at entersub? */ |
1972 | |
1998 | |
1973 | PL_op = (OP *)&slf_restore; |
1999 | PL_op = (OP *)&slf_restore; |
1974 | } |
2000 | } |
1975 | |
2001 | |
1976 | /*****************************************************************************/ |
2002 | /*****************************************************************************/ |
1977 | |
2003 | |
1978 | static void |
2004 | static void |
1979 | coro_semaphore_adjust (AV *av, int adjust) |
2005 | coro_semaphore_adjust (pTHX_ AV *av, IV adjust) |
1980 | { |
2006 | { |
1981 | SV *count_sv = AvARRAY (av)[0]; |
2007 | SV *count_sv = AvARRAY (av)[0]; |
1982 | IV count = SvIVX (count_sv); |
2008 | IV count = SvIVX (count_sv); |
1983 | |
2009 | |
1984 | count += adjust; |
2010 | count += adjust; |
1985 | SvIVX (count_sv) = count; |
2011 | SvIVX (count_sv) = count; |
1986 | |
2012 | |
1987 | /* now wake up as many waiters as possible */ |
2013 | /* now wake up as many waiters as are expected to lock */ |
1988 | while (count > 0 && AvFILLp (av) >= count) |
2014 | while (count > 0 && AvFILLp (av) > 0) |
1989 | { |
2015 | { |
1990 | SV *cb; |
2016 | SV *cb; |
1991 | |
2017 | |
1992 | /* swap first two elements so we can shift a waiter */ |
2018 | /* swap first two elements so we can shift a waiter */ |
1993 | AvARRAY (av)[0] = AvARRAY (av)[1]; |
2019 | AvARRAY (av)[0] = AvARRAY (av)[1]; |
… | |
… | |
2006 | } |
2032 | } |
2007 | |
2033 | |
2008 | static void |
2034 | static void |
2009 | coro_semaphore_on_destroy (pTHX_ struct coro *coro) |
2035 | coro_semaphore_on_destroy (pTHX_ struct coro *coro) |
2010 | { |
2036 | { |
2011 | /* call $sem->adjust (0) to possibly wake up some waiters */ |
2037 | /* call $sem->adjust (0) to possibly wake up some other waiters */ |
2012 | coro_semaphore_adjust ((AV *)coro->slf_frame.data, 0); |
2038 | coro_semaphore_adjust (aTHX_ (AV *)coro->slf_frame.data, 0); |
2013 | } |
2039 | } |
2014 | |
2040 | |
2015 | static int |
2041 | static int |
2016 | slf_check_semaphore_down (pTHX_ struct CoroSLF *frame) |
2042 | slf_check_semaphore_down (pTHX_ struct CoroSLF *frame) |
2017 | { |
2043 | { |
2018 | AV *av = (AV *)frame->data; |
2044 | AV *av = (AV *)frame->data; |
2019 | SV *count_sv = AvARRAY (av)[0]; |
2045 | SV *count_sv = AvARRAY (av)[0]; |
2020 | |
2046 | |
2021 | if (SvIVX (count_sv) > 0) |
2047 | if (SvIVX (count_sv) > 0) |
2022 | { |
2048 | { |
2023 | SvSTATE (coro_current)->on_destroy = 0; |
2049 | SvSTATE_current->on_destroy = 0; |
2024 | SvIVX (count_sv) = SvIVX (count_sv) - 1; |
2050 | SvIVX (count_sv) = SvIVX (count_sv) - 1; |
2025 | return 0; |
2051 | return 0; |
2026 | } |
2052 | } |
2027 | else |
2053 | else |
2028 | { |
2054 | { |
… | |
… | |
2047 | |
2073 | |
2048 | if (SvIVX (AvARRAY (av)[0]) > 0) |
2074 | if (SvIVX (AvARRAY (av)[0]) > 0) |
2049 | { |
2075 | { |
2050 | frame->data = (void *)av; |
2076 | frame->data = (void *)av; |
2051 | frame->prepare = prepare_nop; |
2077 | frame->prepare = prepare_nop; |
|
|
2078 | SvSTATE_current->on_destroy = coro_semaphore_on_destroy; |
2052 | } |
2079 | } |
2053 | else |
2080 | else |
2054 | { |
2081 | { |
2055 | av_push (av, SvREFCNT_inc (SvRV (coro_current))); |
2082 | av_push (av, SvREFCNT_inc (SvRV (coro_current))); |
2056 | |
2083 | |
2057 | frame->data = (void *)sv_2mortal (SvREFCNT_inc ((SV *)av)); |
2084 | frame->data = (void *)sv_2mortal (SvREFCNT_inc ((SV *)av)); |
2058 | frame->prepare = prepare_schedule; |
2085 | frame->prepare = prepare_schedule; |
2059 | |
2086 | |
2060 | /* to avoid race conditions when a woken-up coro gets terminated */ |
2087 | /* to avoid race conditions when a woken-up coro gets terminated */ |
2061 | /* we arrange for a temporary on_destroy that calls adjust (0) */ |
2088 | /* we arrange for a temporary on_destroy that calls adjust (0) */ |
|
|
2089 | assert (!SvSTATE_current->on_destroy);//D |
2062 | SvSTATE (coro_current)->on_destroy = coro_semaphore_on_destroy; |
2090 | SvSTATE_current->on_destroy = coro_semaphore_on_destroy; |
2063 | } |
2091 | } |
2064 | |
2092 | |
2065 | frame->check = slf_check_semaphore_down; |
2093 | frame->check = slf_check_semaphore_down; |
2066 | |
2094 | |
2067 | } |
2095 | } |
… | |
… | |
2095 | PROTOTYPES: DISABLE |
2123 | PROTOTYPES: DISABLE |
2096 | |
2124 | |
2097 | BOOT: |
2125 | BOOT: |
2098 | { |
2126 | { |
2099 | #ifdef USE_ITHREADS |
2127 | #ifdef USE_ITHREADS |
2100 | MUTEX_INIT (&coro_lock); |
|
|
2101 | # if CORO_PTHREAD |
2128 | # if CORO_PTHREAD |
2102 | coro_thx = PERL_GET_CONTEXT; |
2129 | coro_thx = PERL_GET_CONTEXT; |
2103 | # endif |
2130 | # endif |
2104 | #endif |
2131 | #endif |
2105 | BOOT_PAGESIZE; |
2132 | BOOT_PAGESIZE; |
… | |
… | |
2194 | RETVAL |
2221 | RETVAL |
2195 | |
2222 | |
2196 | void |
2223 | void |
2197 | _set_stacklevel (...) |
2224 | _set_stacklevel (...) |
2198 | CODE: |
2225 | CODE: |
2199 | api_execute_slf (aTHX_ cv, slf_init_set_stacklevel, &ST (0), items); |
2226 | CORO_EXECUTE_SLF_XS (slf_init_set_stacklevel); |
2200 | |
2227 | |
2201 | void |
2228 | void |
2202 | transfer (...) |
2229 | transfer (...) |
2203 | PROTOTYPE: $$ |
2230 | PROTOTYPE: $$ |
2204 | CODE: |
2231 | CODE: |
2205 | api_execute_slf (aTHX_ cv, slf_init_transfer, &ST (0), items); |
2232 | CORO_EXECUTE_SLF_XS (slf_init_transfer); |
2206 | |
2233 | |
2207 | bool |
2234 | bool |
2208 | _destroy (SV *coro_sv) |
2235 | _destroy (SV *coro_sv) |
2209 | CODE: |
2236 | CODE: |
2210 | RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv)); |
2237 | RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv)); |
… | |
… | |
2370 | |
2397 | |
2371 | void |
2398 | void |
2372 | force_cctx () |
2399 | force_cctx () |
2373 | PROTOTYPE: |
2400 | PROTOTYPE: |
2374 | CODE: |
2401 | CODE: |
2375 | struct coro *coro = SvSTATE (coro_current); |
|
|
2376 | coro->cctx->idle_sp = 0; |
2402 | SvSTATE_current->cctx->idle_sp = 0; |
2377 | |
2403 | |
2378 | void |
2404 | void |
2379 | swap_defsv (Coro::State self) |
2405 | swap_defsv (Coro::State self) |
2380 | PROTOTYPE: $ |
2406 | PROTOTYPE: $ |
2381 | ALIAS: |
2407 | ALIAS: |
… | |
… | |
2434 | } |
2460 | } |
2435 | |
2461 | |
2436 | void |
2462 | void |
2437 | schedule (...) |
2463 | schedule (...) |
2438 | CODE: |
2464 | CODE: |
2439 | api_execute_slf (aTHX_ cv, slf_init_schedule, &ST (0), 0); |
2465 | CORO_EXECUTE_SLF_XS (slf_init_schedule); |
2440 | |
2466 | |
2441 | void |
2467 | void |
2442 | cede (...) |
2468 | cede (...) |
2443 | CODE: |
2469 | CODE: |
2444 | api_execute_slf (aTHX_ cv, slf_init_cede, &ST (0), 0); |
2470 | CORO_EXECUTE_SLF_XS (slf_init_cede); |
2445 | |
2471 | |
2446 | void |
2472 | void |
2447 | cede_notself (...) |
2473 | cede_notself (...) |
2448 | CODE: |
2474 | CODE: |
2449 | api_execute_slf (aTHX_ cv, slf_init_cede_notself, &ST (0), 0); |
2475 | CORO_EXECUTE_SLF_XS (slf_init_cede_notself); |
2450 | |
2476 | |
2451 | void |
2477 | void |
2452 | _set_current (SV *current) |
2478 | _set_current (SV *current) |
2453 | PROTOTYPE: $ |
2479 | PROTOTYPE: $ |
2454 | CODE: |
2480 | CODE: |
… | |
… | |
2504 | # for async_pool speedup |
2530 | # for async_pool speedup |
2505 | void |
2531 | void |
2506 | _pool_1 (SV *cb) |
2532 | _pool_1 (SV *cb) |
2507 | CODE: |
2533 | CODE: |
2508 | { |
2534 | { |
2509 | struct coro *coro = SvSTATE (coro_current); |
|
|
2510 | HV *hv = (HV *)SvRV (coro_current); |
2535 | HV *hv = (HV *)SvRV (coro_current); |
|
|
2536 | struct coro *coro = SvSTATE_hv ((SV *)hv); |
2511 | AV *defav = GvAV (PL_defgv); |
2537 | AV *defav = GvAV (PL_defgv); |
2512 | SV *invoke = hv_delete (hv, "_invoke", sizeof ("_invoke") - 1, 0); |
2538 | SV *invoke = hv_delete (hv, "_invoke", sizeof ("_invoke") - 1, 0); |
2513 | AV *invoke_av; |
2539 | AV *invoke_av; |
2514 | int i, len; |
2540 | int i, len; |
2515 | |
2541 | |
… | |
… | |
2542 | |
2568 | |
2543 | void |
2569 | void |
2544 | _pool_2 (SV *cb) |
2570 | _pool_2 (SV *cb) |
2545 | CODE: |
2571 | CODE: |
2546 | { |
2572 | { |
2547 | struct coro *coro = SvSTATE (coro_current); |
2573 | struct coro *coro = SvSTATE_current; |
2548 | |
2574 | |
2549 | sv_setsv (cb, &PL_sv_undef); |
2575 | sv_setsv (cb, &PL_sv_undef); |
2550 | |
2576 | |
2551 | SvREFCNT_dec ((SV *)PL_defoutgv); PL_defoutgv = (GV *)coro->saved_deffh; |
2577 | SvREFCNT_dec ((SV *)PL_defoutgv); PL_defoutgv = (GV *)coro->saved_deffh; |
2552 | coro->saved_deffh = 0; |
2578 | coro->saved_deffh = 0; |
… | |
… | |
2684 | void |
2710 | void |
2685 | up (SV *self, int adjust = 1) |
2711 | up (SV *self, int adjust = 1) |
2686 | ALIAS: |
2712 | ALIAS: |
2687 | adjust = 1 |
2713 | adjust = 1 |
2688 | CODE: |
2714 | CODE: |
2689 | coro_semaphore_adjust ((AV *)SvRV (self), ix ? adjust : 1); |
2715 | coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1); |
2690 | |
2716 | |
2691 | void |
2717 | void |
2692 | down (SV *self) |
2718 | down (SV *self) |
2693 | CODE: |
2719 | CODE: |
2694 | api_execute_slf (aTHX_ cv, slf_init_semaphore_down, &ST (0), 1); |
2720 | CORO_EXECUTE_SLF_XS (slf_init_semaphore_down); |
2695 | |
2721 | |
2696 | void |
2722 | void |
2697 | try (SV *self) |
2723 | try (SV *self) |
2698 | PPCODE: |
2724 | PPCODE: |
2699 | { |
2725 | { |