ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/State.xs
(Generate patch)

Comparing Coro/Coro/State.xs (file contents):
Revision 1.263 by root, Wed Nov 12 04:49:06 2008 UTC vs.
Revision 1.271 by root, Fri Nov 14 07:35:32 2008 UTC

116# define CORO_PREFER_PERL_FUNCTIONS 0 116# define CORO_PREFER_PERL_FUNCTIONS 0
117#endif 117#endif
118 118
119/* The next macros try to return the current stack pointer, in an as 119/* The next macros try to return the current stack pointer, in an as
120 * portable way as possible. */ 120 * portable way as possible. */
121#define dSTACKLEVEL volatile char stacklevel 121#if __GNUC__ >= 4
122#define STACKLEVEL ((void *)&stacklevel) 122# define dSTACKLEVEL void *stacklevel = __builtin_frame_address (0)
123#else
124# define dSTACKLEVEL volatile void *stacklevel = (volatile void *)&stacklevel
125#endif
123 126
124#define IN_DESTRUCT (PL_main_cv == Nullcv) 127#define IN_DESTRUCT (PL_main_cv == Nullcv)
125 128
126#if __GNUC__ >= 3 129#if __GNUC__ >= 3
127# define attribute(x) __attribute__(x) 130# define attribute(x) __attribute__(x)
128# define BARRIER __asm__ __volatile__ ("" : : : "memory")
129# define expect(expr,value) __builtin_expect ((expr),(value)) 131# define expect(expr,value) __builtin_expect ((expr),(value))
130# define INLINE static inline 132# define INLINE static inline
131#else 133#else
132# define attribute(x) 134# define attribute(x)
133# define BARRIER
134# define expect(expr,value) (expr) 135# define expect(expr,value) (expr)
135# define INLINE static 136# define INLINE static
136#endif 137#endif
137 138
138#define expect_false(expr) expect ((expr) != 0, 0) 139#define expect_false(expr) expect ((expr) != 0, 0)
298 299
299/* for Coro.pm */ 300/* for Coro.pm */
300static SV *coro_current; 301static SV *coro_current;
301static SV *coro_readyhook; 302static SV *coro_readyhook;
302static AV *coro_ready [PRIO_MAX - PRIO_MIN + 1]; 303static AV *coro_ready [PRIO_MAX - PRIO_MIN + 1];
303static int coro_nready;
304static struct coro *coro_first; 304static struct coro *coro_first;
305#define coro_nready coroapi.nready
305 306
306/** lowlevel stuff **********************************************************/ 307/** lowlevel stuff **********************************************************/
307 308
308static SV * 309static SV *
309coro_get_sv (pTHX_ const char *name, int create) 310coro_get_sv (pTHX_ const char *name, int create)
713 } 714 }
714 715
715 return rss; 716 return rss;
716} 717}
717 718
719/** set stacklevel support **************************************************/
720
721/* we sometimes need to create the effect of pp_slf calling us */
722#define SLF_HEAD (void)0
723/* we sometimes need to create the effect of leaving via pp_slf */
724#define SLF_TAIL slf_tail (aTHX)
725
726INLINE void
727slf_tail (pTHX)
728{
729 dSP;
730 SV **bot = SP;
731
732 int gimme = GIMME_V;
733
734 /* make sure we put something on the stack in scalar context */
735 if (gimme == G_SCALAR)
736 {
737 if (sp == bot)
738 XPUSHs (&PL_sv_undef);
739
740 SP = bot + 1;
741 }
742
743 PUTBACK;
744}
745
718/** coroutine stack handling ************************************************/ 746/** coroutine stack handling ************************************************/
719 747
720static int (*orig_sigelem_get) (pTHX_ SV *sv, MAGIC *mg); 748static int (*orig_sigelem_get) (pTHX_ SV *sv, MAGIC *mg);
721static int (*orig_sigelem_set) (pTHX_ SV *sv, MAGIC *mg); 749static int (*orig_sigelem_set) (pTHX_ SV *sv, MAGIC *mg);
722static int (*orig_sigelem_clr) (pTHX_ SV *sv, MAGIC *mg); 750static int (*orig_sigelem_clr) (pTHX_ SV *sv, MAGIC *mg);
725#ifndef MgPV_nolen_const 753#ifndef MgPV_nolen_const
726#define MgPV_nolen_const(mg) (((((int)(mg)->mg_len)) == HEf_SVKEY) ? \ 754#define MgPV_nolen_const(mg) (((((int)(mg)->mg_len)) == HEf_SVKEY) ? \
727 SvPV_nolen((SV*)((mg)->mg_ptr)) : \ 755 SvPV_nolen((SV*)((mg)->mg_ptr)) : \
728 (const char*)(mg)->mg_ptr) 756 (const char*)(mg)->mg_ptr)
729#endif 757#endif
730
731/* we sometimes need to create the effect of entersub calling us */
732#define ENTERSUB_HEAD ENTER; SAVETMPS
733/* we somtimes need to create the effect of leaving via entersub */
734#define ENTERSUB_TAIL LEAVE
735 758
736/* 759/*
737 * This overrides the default magic get method of %SIG elements. 760 * This overrides the default magic get method of %SIG elements.
738 * The original one doesn't provide for reading back of PL_diehook/PL_warnhook 761 * The original one doesn't provide for reading back of PL_diehook/PL_warnhook
739 * and instead of tryign to save and restore the hash elements, we just provide 762 * and instead of tryign to save and restore the hash elements, we just provide
859 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX); 882 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
860 SPAGAIN; 883 SPAGAIN;
861 } 884 }
862 885
863 /* this newly created coroutine might be run on an existing cctx which most 886 /* this newly created coroutine might be run on an existing cctx which most
864 * likely was suspended in set_stacklevel, called from entersub. 887 * likely was suspended in set_stacklevel, called from pp_set_stacklevel,
865 * set_stacklevel doesn't do anything on return, but entersub does LEAVE, 888 * so we have to emulate entering pp_set_stacklevel here.
866 * so we ENTER here for symmetry.
867 */ 889 */
868 ENTERSUB_HEAD; 890 SLF_HEAD;
869} 891}
870 892
871static void 893static void
872coro_destruct (pTHX_ struct coro *coro) 894coro_destruct (pTHX_ struct coro *coro)
873{ 895{
1078INLINE void 1100INLINE void
1079transfer_tail (pTHX) 1101transfer_tail (pTHX)
1080{ 1102{
1081 struct coro *next = (struct coro *)transfer_next; 1103 struct coro *next = (struct coro *)transfer_next;
1082 assert (!(transfer_next = 0)); /* just used for the side effect when asserts are enabled */ 1104 assert (!(transfer_next = 0)); /* just used for the side effect when asserts are enabled */
1083 assert (("FATAL: transfer_next was zero in transfer_tail (please report)", next)); 1105 assert (("FATAL: next coroutine was zero in transfer_tail (please report)", next));
1084 1106
1085 free_coro_mortal (aTHX); 1107 free_coro_mortal (aTHX);
1086 UNLOCK; 1108 UNLOCK;
1087 1109
1088 if (expect_false (next->throw)) 1110 if (expect_false (next->throw))
1107# endif 1129# endif
1108#endif 1130#endif
1109 { 1131 {
1110 dTHX; 1132 dTHX;
1111 1133
1112 /* entersub called ENTER, but we never 'returned', undo that here */ 1134 /* we are the alternative tail to pp_set_stacklevel */
1113 ENTERSUB_TAIL; 1135 /* so do the same things here */
1136 SLF_TAIL;
1114 1137
1115 /* we now skip the entersub that did lead to transfer() */ 1138 /* we now skip the op that did lead to transfer() */
1116 PL_op = PL_op->op_next; 1139 PL_op = PL_op->op_next;
1117 1140
1118 /* inject a fake subroutine call to cctx_init */ 1141 /* inject a fake subroutine call to cctx_init */
1119 cctx_prepare (aTHX_ (coro_cctx *)arg); 1142 cctx_prepare (aTHX_ (coro_cctx *)arg);
1120 1143
1192 cctx->ssize = cctx_stacksize * (long)sizeof (long); 1215 cctx->ssize = cctx_stacksize * (long)sizeof (long);
1193 New (0, cctx->sptr, cctx_stacksize, long); 1216 New (0, cctx->sptr, cctx_stacksize, long);
1194 1217
1195 if (!cctx->sptr) 1218 if (!cctx->sptr)
1196 { 1219 {
1197 perror ("FATAL: unable to allocate stack for coroutine"); 1220 perror ("FATAL: unable to allocate stack for coroutine, exiting.");
1198 _exit (EXIT_FAILURE); 1221 _exit (EXIT_FAILURE);
1199 } 1222 }
1200 1223
1201 stack_start = cctx->sptr; 1224 stack_start = cctx->sptr;
1202 stack_size = cctx->ssize; 1225 stack_size = cctx->ssize;
1309 dSTACKLEVEL; 1332 dSTACKLEVEL;
1310 1333
1311 /* sometimes transfer is only called to set idle_sp */ 1334 /* sometimes transfer is only called to set idle_sp */
1312 if (expect_false (!next)) 1335 if (expect_false (!next))
1313 { 1336 {
1314 ((coro_cctx *)prev)->idle_sp = STACKLEVEL; 1337 ((coro_cctx *)prev)->idle_sp = stacklevel;
1315 assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */ 1338 assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */
1316 } 1339 }
1317 else if (expect_true (prev != next)) 1340 else if (expect_true (prev != next))
1318 { 1341 {
1319 coro_cctx *prev__cctx; 1342 coro_cctx *prev__cctx;
1346 1369
1347 prev__cctx = prev->cctx; 1370 prev__cctx = prev->cctx;
1348 1371
1349 /* possibly untie and reuse the cctx */ 1372 /* possibly untie and reuse the cctx */
1350 if (expect_true ( 1373 if (expect_true (
1351 prev__cctx->idle_sp == STACKLEVEL 1374 prev__cctx->idle_sp == stacklevel
1352 && !(prev__cctx->flags & CC_TRACE) 1375 && !(prev__cctx->flags & CC_TRACE)
1353 && !force_cctx 1376 && !force_cctx
1354 )) 1377 ))
1355 { 1378 {
1356 /* I assume that STACKLEVEL is a stronger indicator than PL_top_env changes */ 1379 /* I assume that stacklevel is a stronger indicator than PL_top_env changes */
1357 assert (("FATAL: current top_env must equal previous top_env in Coro (please report)", PL_top_env == prev__cctx->idle_te)); 1380 assert (("FATAL: current top_env must equal previous top_env in Coro (please report)", PL_top_env == prev__cctx->idle_te));
1358 1381
1359 prev->cctx = 0; 1382 prev->cctx = 0;
1360 1383
1361 /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get */ 1384 /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get */
1482 ta->next = SvSTATE (next_sv); 1505 ta->next = SvSTATE (next_sv);
1483 TRANSFER_CHECK (*ta); 1506 TRANSFER_CHECK (*ta);
1484} 1507}
1485 1508
1486static void 1509static void
1487api_transfer (SV *prev_sv, SV *next_sv) 1510api_transfer (pTHX_ SV *prev_sv, SV *next_sv)
1488{ 1511{
1489 dTHX;
1490 struct transfer_args ta; 1512 struct transfer_args ta;
1491 1513
1492 prepare_transfer (aTHX_ &ta, prev_sv, next_sv); 1514 prepare_transfer (aTHX_ &ta, prev_sv, next_sv);
1493 TRANSFER (ta, 1); 1515 TRANSFER (ta, 1);
1494} 1516}
1512 1534
1513 return 0; 1535 return 0;
1514} 1536}
1515 1537
1516static int 1538static int
1517api_ready (SV *coro_sv) 1539api_ready (pTHX_ SV *coro_sv)
1518{ 1540{
1519 dTHX;
1520 struct coro *coro; 1541 struct coro *coro;
1521 SV *sv_hook; 1542 SV *sv_hook;
1522 void (*xs_hook)(void); 1543 void (*xs_hook)(void);
1523 1544
1524 if (SvROK (coro_sv)) 1545 if (SvROK (coro_sv))
1562 1583
1563 return 1; 1584 return 1;
1564} 1585}
1565 1586
1566static int 1587static int
1567api_is_ready (SV *coro_sv) 1588api_is_ready (pTHX_ SV *coro_sv)
1568{ 1589{
1569 dTHX;
1570
1571 return !!(SvSTATE (coro_sv)->flags & CF_READY); 1590 return !!(SvSTATE (coro_sv)->flags & CF_READY);
1572} 1591}
1573 1592
1574INLINE void 1593INLINE void
1575prepare_schedule (pTHX_ struct transfer_args *ta) 1594prepare_schedule (pTHX_ struct transfer_args *ta)
1631} 1650}
1632 1651
1633INLINE void 1652INLINE void
1634prepare_cede (pTHX_ struct transfer_args *ta) 1653prepare_cede (pTHX_ struct transfer_args *ta)
1635{ 1654{
1636 api_ready (coro_current); 1655 api_ready (aTHX_ coro_current);
1637 prepare_schedule (aTHX_ ta); 1656 prepare_schedule (aTHX_ ta);
1638} 1657}
1639 1658
1659static void
1660prepare_cede_notself (pTHX_ struct transfer_args *ta)
1661{
1662 SV *prev = SvRV (coro_current);
1663
1664 if (coro_nready)
1665 {
1666 prepare_schedule (aTHX_ ta);
1667 api_ready (aTHX_ prev);
1668 }
1669 else
1670 ta->prev = ta->next = SvSTATE (prev);
1671}
1672
1673static void
1674api_schedule (pTHX)
1675{
1676 struct transfer_args ta;
1677
1678 prepare_schedule (aTHX_ &ta);
1679 TRANSFER (ta, 1);
1680}
1681
1640static int 1682static int
1641prepare_cede_notself (pTHX_ struct transfer_args *ta) 1683api_cede (pTHX)
1642{ 1684{
1643 if (coro_nready) 1685 struct transfer_args ta;
1644 { 1686
1645 SV *prev = SvRV (coro_current);
1646 prepare_schedule (aTHX_ ta); 1687 prepare_cede (aTHX_ &ta);
1647 api_ready (prev); 1688
1689 if (expect_true (ta.prev != ta.next))
1690 {
1691 TRANSFER (ta, 1);
1648 return 1; 1692 return 1;
1649 } 1693 }
1650 else 1694 else
1651 return 0; 1695 return 0;
1652} 1696}
1653 1697
1654static void
1655api_schedule (void)
1656{
1657 dTHX;
1658 struct transfer_args ta;
1659
1660 prepare_schedule (aTHX_ &ta);
1661 TRANSFER (ta, 1);
1662}
1663
1664static int 1698static int
1665api_cede (void) 1699api_cede_notself (pTHX)
1666{ 1700{
1667 dTHX; 1701 if (coro_nready)
1702 {
1668 struct transfer_args ta; 1703 struct transfer_args ta;
1669 1704
1670 prepare_cede (aTHX_ &ta); 1705 prepare_cede_notself (aTHX_ &ta);
1671
1672 if (expect_true (ta.prev != ta.next))
1673 {
1674 TRANSFER (ta, 1); 1706 TRANSFER (ta, 1);
1675 return 1; 1707 return 1;
1676 } 1708 }
1677 else 1709 else
1678 return 0; 1710 return 0;
1679} 1711}
1680 1712
1681static int
1682api_cede_notself (void)
1683{
1684 dTHX;
1685 struct transfer_args ta;
1686
1687 if (prepare_cede_notself (aTHX_ &ta))
1688 {
1689 TRANSFER (ta, 1);
1690 return 1;
1691 }
1692 else
1693 return 0;
1694}
1695
1696static void 1713static void
1697api_trace (SV *coro_sv, int flags) 1714api_trace (pTHX_ SV *coro_sv, int flags)
1698{ 1715{
1699 dTHX;
1700 struct coro *coro = SvSTATE (coro_sv); 1716 struct coro *coro = SvSTATE (coro_sv);
1701 1717
1702 if (flags & CC_TRACE) 1718 if (flags & CC_TRACE)
1703 { 1719 {
1704 if (!coro->cctx) 1720 if (!coro->cctx)
1771 PerlIOCede *self = PerlIOSelf (f, PerlIOCede); 1787 PerlIOCede *self = PerlIOSelf (f, PerlIOCede);
1772 double now = nvtime (); 1788 double now = nvtime ();
1773 1789
1774 if (now >= self->next) 1790 if (now >= self->next)
1775 { 1791 {
1776 api_cede (); 1792 api_cede (aTHX);
1777 self->next = now + self->every; 1793 self->next = now + self->every;
1778 } 1794 }
1779 1795
1780 return PerlIOBuf_flush (aTHX_ f); 1796 return PerlIOBuf_flush (aTHX_ f);
1781} 1797}
1810 PerlIOBuf_get_ptr, 1826 PerlIOBuf_get_ptr,
1811 PerlIOBuf_get_cnt, 1827 PerlIOBuf_get_cnt,
1812 PerlIOBuf_set_ptrcnt, 1828 PerlIOBuf_set_ptrcnt,
1813}; 1829};
1814 1830
1831/*****************************************************************************/
1832
1833static const CV *slf_cv; /* for quick consistency check */
1834
1835static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */
1836static SV *slf_arg0;
1837static SV *slf_arg1;
1838
1839/* this restores the stack in the case we patched the entersub, to */
1840/* recreate the stack frame as perl will on following calls */
1841/* since entersub cleared the stack */
1842static OP *
1843pp_restore (pTHX)
1844{
1845 dSP;
1846
1847 PUSHMARK (SP);
1848
1849 EXTEND (SP, 3);
1850 if (slf_arg0) PUSHs (sv_2mortal (slf_arg0));
1851 if (slf_arg1) PUSHs (sv_2mortal (slf_arg1));
1852 PUSHs ((SV *)CvGV (slf_cv));
1853
1854 RETURNOP (slf_restore.op_first);
1855}
1856
1857#define OPpENTERSUB_SLF 15 /* the part of op_private entersub hopefully doesn't use */
1858
1859enum {
1860 CORO_SLF_CUSTOM = 0,
1861 CORO_SLF_SET_STACKLEVEL = 1,
1862 CORO_SLF_TRANSFER = 2
1863};
1864
1865/* declare prototype */
1866XS(XS_Coro__State__set_stacklevel);
1867
1868/*
1869 * these not obviously related functions are all rolled into one
1870 * function to increase chances that they all will call transfer with the same
1871 * stack offset
1872 * SLF stands for "schedule-like-function".
1873 */
1874static OP *
1875pp_slf (pTHX)
1876{
1877 dSP;
1878 struct transfer_args ta;
1879 SV **arg = PL_stack_base + TOPMARK + 1;
1880 int items = SP - arg; /* args without function object */
1881 int ix = PL_op->op_private & OPpENTERSUB_SLF;
1882 struct CoroSLF *slf = 0;
1883 SV *gv = *sp;
1884
1885 /* do a quick consistency check on the "function" object, and if it isn't */
1886 /* for us, divert to the real entersub */
1887 if (SvTYPE (gv) != SVt_PVGV || CvXSUB (GvCV (gv)) != XS_Coro__State__set_stacklevel)
1888 return PL_ppaddr[OP_ENTERSUB](aTHX);
1889
1890 /* pop args */
1891 SP = PL_stack_base + POPMARK;
1892
1893 if (!(PL_op->op_flags & OPf_STACKED))
1894 {
1895 /* ampersand-form of call, use @_ instead of stack */
1896 AV *av = GvAV (PL_defgv);
1897 arg = AvARRAY (av);
1898 items = AvFILLp (av) + 1;
1899 }
1900
1901 PUTBACK;
1902
1903 if (!ix)
1904 {
1905 slf = (struct CoroSLF *)CvXSUBANY (GvCV (gv)).any_ptr;
1906 ix = slf->prepare (aTHX_ arg, items);
1907 }
1908
1909 switch (ix)
1910 {
1911 case CORO_SLF_SET_STACKLEVEL:
1912 prepare_set_stacklevel (&ta, (struct coro_cctx *)SvIV (arg [0]));
1913 break;
1914
1915 case CORO_SLF_TRANSFER:
1916 if (items != 2)
1917 croak ("Coro::State::transfer (prev, next) expects two arguments, not %d.", items);
1918
1919 prepare_transfer (aTHX_ &ta, arg [0], arg [1]);
1920 break;
1921
1922 case CORO_SLF_SCHEDULE:
1923 prepare_schedule (aTHX_ &ta);
1924 break;
1925
1926 case CORO_SLF_CEDE:
1927 prepare_cede (aTHX_ &ta);
1928 break;
1929
1930 case CORO_SLF_CEDE_NOTSELF:
1931 prepare_cede_notself (aTHX_ &ta);
1932 break;
1933
1934 default:
1935 abort ();
1936 }
1937
1938 do
1939 TRANSFER (ta, 0);
1940 while (slf && slf->check (aTHX));
1941
1942 SPAGAIN;
1943
1944 PUTBACK;
1945 SLF_TAIL;
1946 SPAGAIN;
1947 RETURN;
1948}
1949
1950static void
1951coro_slf_patch (pTHX_ CV *cv, int ix, SV **args, int items)
1952{
1953 assert (("FATAL: SLF call recursion in Coro module (please report)", PL_op->op_ppaddr != pp_slf));
1954
1955 assert (("FATAL: SLF call with illegal CV value", CvGV (cv)));
1956 slf_cv = cv;
1957
1958 /* we patch the op, and then re-run the whole call */
1959 /* we have to put the same argument on the stack for this to work */
1960 /* and this will be done by pp_restore */
1961 slf_restore.op_next = (OP *)&slf_restore;
1962 slf_restore.op_type = OP_NULL;
1963 slf_restore.op_ppaddr = pp_restore;
1964 slf_restore.op_first = PL_op;
1965
1966 slf_arg0 = items > 0 ? SvREFCNT_inc (args [0]) : 0;
1967 slf_arg1 = items > 1 ? SvREFCNT_inc (args [1]) : 0;
1968
1969 PL_op->op_ppaddr = pp_slf;
1970 PL_op->op_private = PL_op->op_private & ~OPpENTERSUB_SLF | ix; /* we potentially share our private flags with entersub */
1971
1972 PL_op = (OP *)&slf_restore;
1973}
1974
1975static void
1976api_execute_slf (pTHX_ CV *cv, const struct CoroSLF *slf, SV **arg, int items)
1977{
1978 CvXSUBANY (cv).any_ptr = (void *)slf;
1979 coro_slf_patch (aTHX_ cv, CORO_SLF_CUSTOM, arg, items);
1980}
1815 1981
1816MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ 1982MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_
1817 1983
1818PROTOTYPES: DISABLE 1984PROTOTYPES: DISABLE
1819 1985
1849 main_top_env = PL_top_env; 2015 main_top_env = PL_top_env;
1850 2016
1851 while (main_top_env->je_prev) 2017 while (main_top_env->je_prev)
1852 main_top_env = main_top_env->je_prev; 2018 main_top_env = main_top_env->je_prev;
1853 2019
1854 coroapi.ver = CORO_API_VERSION; 2020 coroapi.ver = CORO_API_VERSION;
1855 coroapi.rev = CORO_API_REVISION; 2021 coroapi.rev = CORO_API_REVISION;
1856 coroapi.transfer = api_transfer; 2022 coroapi.transfer = api_transfer;
2023 coroapi.execute_slf = api_execute_slf;
1857 2024
1858 { 2025 {
1859 SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0); 2026 SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1860 2027
1861 if (!svp) croak ("Time::HiRes is required"); 2028 if (!svp) croak ("Time::HiRes is required");
1894 av_push (coro->args, newSVsv (ST (i))); 2061 av_push (coro->args, newSVsv (ST (i)));
1895} 2062}
1896 OUTPUT: 2063 OUTPUT:
1897 RETVAL 2064 RETVAL
1898 2065
1899# these not obviously related functions are all rolled into the same xs
1900# function to increase chances that they all will call transfer with the same
1901# stack offset
1902void 2066void
1903_set_stacklevel (...) 2067_set_stacklevel (...)
1904 ALIAS: 2068 ALIAS:
2069 _set_stacklevel = CORO_SLF_SET_STACKLEVEL
1905 Coro::State::transfer = 1 2070 Coro::State::transfer = CORO_SLF_TRANSFER
1906 Coro::schedule = 2 2071 Coro::schedule = CORO_SLF_SCHEDULE
1907 Coro::cede = 3 2072 Coro::cede = CORO_SLF_CEDE
1908 Coro::cede_notself = 4 2073 Coro::cede_notself = CORO_SLF_CEDE_NOTSELF
1909 CODE: 2074 CODE:
1910{ 2075 coro_slf_patch (aTHX_ cv, ix, &ST (0), items);
1911 struct transfer_args ta;
1912
1913 PUTBACK;
1914 switch (ix)
1915 {
1916 case 0:
1917 prepare_set_stacklevel (&ta, (struct coro_cctx *)SvIV (ST (0)));
1918 break;
1919
1920 case 1:
1921 if (items != 2)
1922 croak ("Coro::State::transfer (prev, next) expects two arguments, not %d", items);
1923
1924 prepare_transfer (aTHX_ &ta, ST (0), ST (1));
1925 break;
1926
1927 case 2:
1928 prepare_schedule (aTHX_ &ta);
1929 break;
1930
1931 case 3:
1932 prepare_cede (aTHX_ &ta);
1933 break;
1934
1935 case 4:
1936 if (!prepare_cede_notself (aTHX_ &ta))
1937 XSRETURN_EMPTY;
1938
1939 break;
1940 }
1941 SPAGAIN;
1942
1943 BARRIER;
1944 PUTBACK;
1945 TRANSFER (ta, 0);
1946 SPAGAIN; /* might be the sp of a different coroutine now */
1947 /* be extra careful not to ever do anything after TRANSFER */
1948}
1949 2076
1950bool 2077bool
1951_destroy (SV *coro_sv) 2078_destroy (SV *coro_sv)
1952 CODE: 2079 CODE:
1953 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv)); 2080 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv));
2071 SvREFCNT_dec (self->throw); 2198 SvREFCNT_dec (self->throw);
2072 self->throw = SvOK (throw) ? newSVsv (throw) : 0; 2199 self->throw = SvOK (throw) ? newSVsv (throw) : 0;
2073 2200
2074void 2201void
2075api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) 2202api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
2203 C_ARGS: aTHX_ coro, flags
2076 2204
2077SV * 2205SV *
2078has_cctx (Coro::State coro) 2206has_cctx (Coro::State coro)
2079 PROTOTYPE: $ 2207 PROTOTYPE: $
2080 CODE: 2208 CODE:
2157 coroapi.schedule = api_schedule; 2285 coroapi.schedule = api_schedule;
2158 coroapi.cede = api_cede; 2286 coroapi.cede = api_cede;
2159 coroapi.cede_notself = api_cede_notself; 2287 coroapi.cede_notself = api_cede_notself;
2160 coroapi.ready = api_ready; 2288 coroapi.ready = api_ready;
2161 coroapi.is_ready = api_is_ready; 2289 coroapi.is_ready = api_is_ready;
2162 coroapi.nready = &coro_nready; 2290 coroapi.nready = coro_nready;
2163 coroapi.current = coro_current; 2291 coroapi.current = coro_current;
2164 2292
2165 GCoroAPI = &coroapi; 2293 GCoroAPI = &coroapi;
2166 sv_setiv (sv, (IV)&coroapi); 2294 sv_setiv (sv, (IV)&coroapi);
2167 SvREADONLY_on (sv); 2295 SvREADONLY_on (sv);
2208 2336
2209SV * 2337SV *
2210ready (SV *self) 2338ready (SV *self)
2211 PROTOTYPE: $ 2339 PROTOTYPE: $
2212 CODE: 2340 CODE:
2213 RETVAL = boolSV (api_ready (self)); 2341 RETVAL = boolSV (api_ready (aTHX_ self));
2214 OUTPUT: 2342 OUTPUT:
2215 RETVAL 2343 RETVAL
2216 2344
2217int 2345int
2218nready (...) 2346nready (...)
2288 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0); 2416 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0);
2289 2417
2290 coro->prio = 0; 2418 coro->prio = 0;
2291 2419
2292 if (coro->cctx && (coro->cctx->flags & CC_TRACE)) 2420 if (coro->cctx && (coro->cctx->flags & CC_TRACE))
2293 api_trace (coro_current, 0); 2421 api_trace (aTHX_ coro_current, 0);
2294 2422
2295 av_push (av_async_pool, newSVsv (coro_current)); 2423 av_push (av_async_pool, newSVsv (coro_current));
2296} 2424}
2297 2425
2298#if 0 2426#if 0
2370 2498
2371 av_push (av, data_sv); 2499 av_push (av, data_sv);
2372 2500
2373 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av))); 2501 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
2374 2502
2375 api_ready (self); 2503 api_ready (aTHX_ self);
2376} 2504}
2377 2505
2378void 2506void
2379_set_state (SV *state) 2507_set_state (SV *state)
2380 PROTOTYPE: $ 2508 PROTOTYPE: $
2405 PROTOTYPE: @ 2533 PROTOTYPE: @
2406 CODE: 2534 CODE:
2407{ 2535{
2408 static int incede; 2536 static int incede;
2409 2537
2410 api_cede_notself (); 2538 api_cede_notself (aTHX);
2411 2539
2412 ++incede; 2540 ++incede;
2413 while (coro_nready >= incede && api_cede ()) 2541 while (coro_nready >= incede && api_cede (aTHX))
2414 ; 2542 ;
2415 2543
2416 sv_setsv (sv_activity, &PL_sv_undef); 2544 sv_setsv (sv_activity, &PL_sv_undef);
2417 if (coro_nready >= incede) 2545 if (coro_nready >= incede)
2418 { 2546 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines