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.270 by root, Fri Nov 14 07:22:11 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
1884 /* do a quick consistency check on the "function" object, and if it isn't */
1885 /* for us, divert to the real entersub */
1886 if (SvTYPE (*sp) != SVt_PVGV || CvXSUB (GvCV (*sp)) != XS_Coro__State__set_stacklevel)
1887 return PL_ppaddr[OP_ENTERSUB](aTHX);
1888
1889 /* pop args */
1890 SP = PL_stack_base + POPMARK;
1891
1892 if (!(PL_op->op_flags & OPf_STACKED))
1893 {
1894 /* ampersand-form of call, use @_ instead of stack */
1895 AV *av = GvAV (PL_defgv);
1896 arg = AvARRAY (av);
1897 items = AvFILLp (av) + 1;
1898 }
1899
1900 PUTBACK;
1901
1902 if (!ix)
1903 {
1904 slf = (struct CoroSLF *)CvSTART (GvCV (*sp));
1905 ix = slf->prepare (aTHX_ arg, items);
1906 }
1907
1908 switch (ix)
1909 {
1910 case CORO_SLF_SET_STACKLEVEL:
1911 prepare_set_stacklevel (&ta, (struct coro_cctx *)SvIV (arg [0]));
1912 break;
1913
1914 case CORO_SLF_TRANSFER:
1915 if (items != 2)
1916 croak ("Coro::State::transfer (prev, next) expects two arguments, not %d.", items);
1917
1918 prepare_transfer (aTHX_ &ta, arg [0], arg [1]);
1919 break;
1920
1921 case CORO_SLF_SCHEDULE:
1922 prepare_schedule (aTHX_ &ta);
1923 break;
1924
1925 case CORO_SLF_CEDE:
1926 prepare_cede (aTHX_ &ta);
1927 break;
1928
1929 case CORO_SLF_CEDE_NOTSELF:
1930 prepare_cede_notself (aTHX_ &ta);
1931 break;
1932
1933 default:
1934 abort ();
1935 }
1936
1937 do
1938 TRANSFER (ta, 0);
1939 while (slf && slf->check (aTHX));
1940
1941 SPAGAIN;
1942
1943 PUTBACK;
1944 SLF_TAIL;
1945 SPAGAIN;
1946 RETURN;
1947}
1948
1949static void
1950coro_slf_patch (pTHX_ CV *cv, int ix, SV **args, int items)
1951{
1952 assert (("FATAL: SLF call recursion in Coro module (please report)", PL_op->op_ppaddr != pp_slf));
1953
1954 assert (("FATAL: SLF call with illegal CV value", CvGV (cv)));
1955 slf_cv = cv;
1956
1957 /* we patch the op, and then re-run the whole call */
1958 /* we have to put the same argument on the stack for this to work */
1959 /* and this will be done by pp_restore */
1960 slf_restore.op_next = (OP *)&slf_restore;
1961 slf_restore.op_type = OP_NULL;
1962 slf_restore.op_ppaddr = pp_restore;
1963 slf_restore.op_first = PL_op;
1964
1965 slf_arg0 = items > 0 ? SvREFCNT_inc (args [0]) : 0;
1966 slf_arg1 = items > 1 ? SvREFCNT_inc (args [1]) : 0;
1967
1968 PL_op->op_ppaddr = pp_slf;
1969 PL_op->op_private = PL_op->op_private & ~OPpENTERSUB_SLF | ix; /* we potentially share our private flags with entersub */
1970
1971 PL_op = (OP *)&slf_restore;
1972}
1815 1973
1816MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ 1974MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_
1817 1975
1818PROTOTYPES: DISABLE 1976PROTOTYPES: DISABLE
1819 1977
1894 av_push (coro->args, newSVsv (ST (i))); 2052 av_push (coro->args, newSVsv (ST (i)));
1895} 2053}
1896 OUTPUT: 2054 OUTPUT:
1897 RETVAL 2055 RETVAL
1898 2056
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 2057void
1903_set_stacklevel (...) 2058_set_stacklevel (...)
1904 ALIAS: 2059 ALIAS:
2060 _set_stacklevel = CORO_SLF_SET_STACKLEVEL
1905 Coro::State::transfer = 1 2061 Coro::State::transfer = CORO_SLF_TRANSFER
1906 Coro::schedule = 2 2062 Coro::schedule = CORO_SLF_SCHEDULE
1907 Coro::cede = 3 2063 Coro::cede = CORO_SLF_CEDE
1908 Coro::cede_notself = 4 2064 Coro::cede_notself = CORO_SLF_CEDE_NOTSELF
1909 CODE: 2065 CODE:
1910{ 2066 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 2067
1950bool 2068bool
1951_destroy (SV *coro_sv) 2069_destroy (SV *coro_sv)
1952 CODE: 2070 CODE:
1953 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv)); 2071 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv));
2071 SvREFCNT_dec (self->throw); 2189 SvREFCNT_dec (self->throw);
2072 self->throw = SvOK (throw) ? newSVsv (throw) : 0; 2190 self->throw = SvOK (throw) ? newSVsv (throw) : 0;
2073 2191
2074void 2192void
2075api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) 2193api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
2194 C_ARGS: aTHX_ coro, flags
2076 2195
2077SV * 2196SV *
2078has_cctx (Coro::State coro) 2197has_cctx (Coro::State coro)
2079 PROTOTYPE: $ 2198 PROTOTYPE: $
2080 CODE: 2199 CODE:
2157 coroapi.schedule = api_schedule; 2276 coroapi.schedule = api_schedule;
2158 coroapi.cede = api_cede; 2277 coroapi.cede = api_cede;
2159 coroapi.cede_notself = api_cede_notself; 2278 coroapi.cede_notself = api_cede_notself;
2160 coroapi.ready = api_ready; 2279 coroapi.ready = api_ready;
2161 coroapi.is_ready = api_is_ready; 2280 coroapi.is_ready = api_is_ready;
2162 coroapi.nready = &coro_nready; 2281 coroapi.nready = coro_nready;
2163 coroapi.current = coro_current; 2282 coroapi.current = coro_current;
2164 2283
2165 GCoroAPI = &coroapi; 2284 GCoroAPI = &coroapi;
2166 sv_setiv (sv, (IV)&coroapi); 2285 sv_setiv (sv, (IV)&coroapi);
2167 SvREADONLY_on (sv); 2286 SvREADONLY_on (sv);
2208 2327
2209SV * 2328SV *
2210ready (SV *self) 2329ready (SV *self)
2211 PROTOTYPE: $ 2330 PROTOTYPE: $
2212 CODE: 2331 CODE:
2213 RETVAL = boolSV (api_ready (self)); 2332 RETVAL = boolSV (api_ready (aTHX_ self));
2214 OUTPUT: 2333 OUTPUT:
2215 RETVAL 2334 RETVAL
2216 2335
2217int 2336int
2218nready (...) 2337nready (...)
2288 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0); 2407 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0);
2289 2408
2290 coro->prio = 0; 2409 coro->prio = 0;
2291 2410
2292 if (coro->cctx && (coro->cctx->flags & CC_TRACE)) 2411 if (coro->cctx && (coro->cctx->flags & CC_TRACE))
2293 api_trace (coro_current, 0); 2412 api_trace (aTHX_ coro_current, 0);
2294 2413
2295 av_push (av_async_pool, newSVsv (coro_current)); 2414 av_push (av_async_pool, newSVsv (coro_current));
2296} 2415}
2297 2416
2298#if 0 2417#if 0
2370 2489
2371 av_push (av, data_sv); 2490 av_push (av, data_sv);
2372 2491
2373 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av))); 2492 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
2374 2493
2375 api_ready (self); 2494 api_ready (aTHX_ self);
2376} 2495}
2377 2496
2378void 2497void
2379_set_state (SV *state) 2498_set_state (SV *state)
2380 PROTOTYPE: $ 2499 PROTOTYPE: $
2405 PROTOTYPE: @ 2524 PROTOTYPE: @
2406 CODE: 2525 CODE:
2407{ 2526{
2408 static int incede; 2527 static int incede;
2409 2528
2410 api_cede_notself (); 2529 api_cede_notself (aTHX);
2411 2530
2412 ++incede; 2531 ++incede;
2413 while (coro_nready >= incede && api_cede ()) 2532 while (coro_nready >= incede && api_cede (aTHX))
2414 ; 2533 ;
2415 2534
2416 sv_setsv (sv_activity, &PL_sv_undef); 2535 sv_setsv (sv_activity, &PL_sv_undef);
2417 if (coro_nready >= incede) 2536 if (coro_nready >= incede)
2418 { 2537 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines