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.265 by root, Fri Nov 14 02:42:26 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)
296 299
297/* for Coro.pm */ 300/* for Coro.pm */
298static SV *coro_current; 301static SV *coro_current;
299static SV *coro_readyhook; 302static SV *coro_readyhook;
300static AV *coro_ready [PRIO_MAX - PRIO_MIN + 1]; 303static AV *coro_ready [PRIO_MAX - PRIO_MIN + 1];
301static int coro_nready;
302static struct coro *coro_first; 304static struct coro *coro_first;
305#define coro_nready coroapi.nready
303 306
304/** lowlevel stuff **********************************************************/ 307/** lowlevel stuff **********************************************************/
305 308
306static SV * 309static SV *
307coro_get_sv (pTHX_ const char *name, int create) 310coro_get_sv (pTHX_ const char *name, int create)
713 return rss; 716 return rss;
714} 717}
715 718
716/** set stacklevel support **************************************************/ 719/** set stacklevel support **************************************************/
717 720
718/* we sometimes need to create the effect of pp_set_stacklevel calling us */ 721/* we sometimes need to create the effect of pp_slf calling us */
719#define SSL_HEAD (void)0 722#define SLF_HEAD (void)0
720/* we somtimes need to create the effect of leaving via pp_set_stacklevel */ 723/* we sometimes need to create the effect of leaving via pp_slf */
721#define SSL_TAIL set_stacklevel_tail (aTHX) 724#define SLF_TAIL slf_tail (aTHX)
722 725
723INLINE void 726INLINE void
724set_stacklevel_tail (pTHX) 727slf_tail (pTHX)
725{ 728{
726 dSP; 729 dSP;
730 SV **bot = SP;
731
727 int gimme = GIMME_V; 732 int gimme = GIMME_V;
728 733
734 /* make sure we put something on the stack in scalar context */
729 if (gimme == G_SCALAR) 735 if (gimme == G_SCALAR)
736 {
737 if (sp == bot)
730 XPUSHs (&PL_sv_undef); 738 XPUSHs (&PL_sv_undef);
739
740 SP = bot + 1;
741 }
731 742
732 PUTBACK; 743 PUTBACK;
733} 744}
734 745
735/** coroutine stack handling ************************************************/ 746/** coroutine stack handling ************************************************/
874 885
875 /* 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
876 * likely was suspended in set_stacklevel, called from pp_set_stacklevel, 887 * likely was suspended in set_stacklevel, called from pp_set_stacklevel,
877 * so we have to emulate entering pp_set_stacklevel here. 888 * so we have to emulate entering pp_set_stacklevel here.
878 */ 889 */
879 SSL_HEAD; 890 SLF_HEAD;
880} 891}
881 892
882static void 893static void
883coro_destruct (pTHX_ struct coro *coro) 894coro_destruct (pTHX_ struct coro *coro)
884{ 895{
1120 { 1131 {
1121 dTHX; 1132 dTHX;
1122 1133
1123 /* we are the alternative tail to pp_set_stacklevel */ 1134 /* we are the alternative tail to pp_set_stacklevel */
1124 /* so do the same things here */ 1135 /* so do the same things here */
1125 SSL_TAIL; 1136 SLF_TAIL;
1126 1137
1127 /* we now skip the op that did lead to transfer() */ 1138 /* we now skip the op that did lead to transfer() */
1128 PL_op = PL_op->op_next; 1139 PL_op = PL_op->op_next;
1129 1140
1130 /* inject a fake subroutine call to cctx_init */ 1141 /* inject a fake subroutine call to cctx_init */
1321 dSTACKLEVEL; 1332 dSTACKLEVEL;
1322 1333
1323 /* sometimes transfer is only called to set idle_sp */ 1334 /* sometimes transfer is only called to set idle_sp */
1324 if (expect_false (!next)) 1335 if (expect_false (!next))
1325 { 1336 {
1326 ((coro_cctx *)prev)->idle_sp = STACKLEVEL; 1337 ((coro_cctx *)prev)->idle_sp = stacklevel;
1327 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 */
1328 } 1339 }
1329 else if (expect_true (prev != next)) 1340 else if (expect_true (prev != next))
1330 { 1341 {
1331 coro_cctx *prev__cctx; 1342 coro_cctx *prev__cctx;
1358 1369
1359 prev__cctx = prev->cctx; 1370 prev__cctx = prev->cctx;
1360 1371
1361 /* possibly untie and reuse the cctx */ 1372 /* possibly untie and reuse the cctx */
1362 if (expect_true ( 1373 if (expect_true (
1363 prev__cctx->idle_sp == STACKLEVEL 1374 prev__cctx->idle_sp == stacklevel
1364 && !(prev__cctx->flags & CC_TRACE) 1375 && !(prev__cctx->flags & CC_TRACE)
1365 && !force_cctx 1376 && !force_cctx
1366 )) 1377 ))
1367 { 1378 {
1368 /* 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 */
1369 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));
1370 1381
1371 prev->cctx = 0; 1382 prev->cctx = 0;
1372 1383
1373 /* 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 */
1494 ta->next = SvSTATE (next_sv); 1505 ta->next = SvSTATE (next_sv);
1495 TRANSFER_CHECK (*ta); 1506 TRANSFER_CHECK (*ta);
1496} 1507}
1497 1508
1498static void 1509static void
1499api_transfer (SV *prev_sv, SV *next_sv) 1510api_transfer (pTHX_ SV *prev_sv, SV *next_sv)
1500{ 1511{
1501 dTHX;
1502 struct transfer_args ta; 1512 struct transfer_args ta;
1503 1513
1504 prepare_transfer (aTHX_ &ta, prev_sv, next_sv); 1514 prepare_transfer (aTHX_ &ta, prev_sv, next_sv);
1505 TRANSFER (ta, 1); 1515 TRANSFER (ta, 1);
1506} 1516}
1524 1534
1525 return 0; 1535 return 0;
1526} 1536}
1527 1537
1528static int 1538static int
1529api_ready (SV *coro_sv) 1539api_ready (pTHX_ SV *coro_sv)
1530{ 1540{
1531 dTHX;
1532 struct coro *coro; 1541 struct coro *coro;
1533 SV *sv_hook; 1542 SV *sv_hook;
1534 void (*xs_hook)(void); 1543 void (*xs_hook)(void);
1535 1544
1536 if (SvROK (coro_sv)) 1545 if (SvROK (coro_sv))
1574 1583
1575 return 1; 1584 return 1;
1576} 1585}
1577 1586
1578static int 1587static int
1579api_is_ready (SV *coro_sv) 1588api_is_ready (pTHX_ SV *coro_sv)
1580{ 1589{
1581 dTHX;
1582
1583 return !!(SvSTATE (coro_sv)->flags & CF_READY); 1590 return !!(SvSTATE (coro_sv)->flags & CF_READY);
1584} 1591}
1585 1592
1586INLINE void 1593INLINE void
1587prepare_schedule (pTHX_ struct transfer_args *ta) 1594prepare_schedule (pTHX_ struct transfer_args *ta)
1643} 1650}
1644 1651
1645INLINE void 1652INLINE void
1646prepare_cede (pTHX_ struct transfer_args *ta) 1653prepare_cede (pTHX_ struct transfer_args *ta)
1647{ 1654{
1648 api_ready (coro_current); 1655 api_ready (aTHX_ coro_current);
1649 prepare_schedule (aTHX_ ta); 1656 prepare_schedule (aTHX_ ta);
1650} 1657}
1651 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
1652static int 1682static int
1653prepare_cede_notself (pTHX_ struct transfer_args *ta) 1683api_cede (pTHX)
1654{ 1684{
1655 if (coro_nready) 1685 struct transfer_args ta;
1656 { 1686
1657 SV *prev = SvRV (coro_current);
1658 prepare_schedule (aTHX_ ta); 1687 prepare_cede (aTHX_ &ta);
1659 api_ready (prev); 1688
1689 if (expect_true (ta.prev != ta.next))
1690 {
1691 TRANSFER (ta, 1);
1660 return 1; 1692 return 1;
1661 } 1693 }
1662 else 1694 else
1663 return 0; 1695 return 0;
1664} 1696}
1665 1697
1666static void
1667api_schedule (void)
1668{
1669 dTHX;
1670 struct transfer_args ta;
1671
1672 prepare_schedule (aTHX_ &ta);
1673 TRANSFER (ta, 1);
1674}
1675
1676static int 1698static int
1677api_cede (void) 1699api_cede_notself (pTHX)
1678{ 1700{
1679 dTHX; 1701 if (coro_nready)
1702 {
1680 struct transfer_args ta; 1703 struct transfer_args ta;
1681 1704
1682 prepare_cede (aTHX_ &ta); 1705 prepare_cede_notself (aTHX_ &ta);
1683
1684 if (expect_true (ta.prev != ta.next))
1685 {
1686 TRANSFER (ta, 1); 1706 TRANSFER (ta, 1);
1687 return 1; 1707 return 1;
1688 } 1708 }
1689 else 1709 else
1690 return 0; 1710 return 0;
1691} 1711}
1692 1712
1693static int
1694api_cede_notself (void)
1695{
1696 dTHX;
1697 struct transfer_args ta;
1698
1699 if (prepare_cede_notself (aTHX_ &ta))
1700 {
1701 TRANSFER (ta, 1);
1702 return 1;
1703 }
1704 else
1705 return 0;
1706}
1707
1708static void 1713static void
1709api_trace (SV *coro_sv, int flags) 1714api_trace (pTHX_ SV *coro_sv, int flags)
1710{ 1715{
1711 dTHX;
1712 struct coro *coro = SvSTATE (coro_sv); 1716 struct coro *coro = SvSTATE (coro_sv);
1713 1717
1714 if (flags & CC_TRACE) 1718 if (flags & CC_TRACE)
1715 { 1719 {
1716 if (!coro->cctx) 1720 if (!coro->cctx)
1783 PerlIOCede *self = PerlIOSelf (f, PerlIOCede); 1787 PerlIOCede *self = PerlIOSelf (f, PerlIOCede);
1784 double now = nvtime (); 1788 double now = nvtime ();
1785 1789
1786 if (now >= self->next) 1790 if (now >= self->next)
1787 { 1791 {
1788 api_cede (); 1792 api_cede (aTHX);
1789 self->next = now + self->every; 1793 self->next = now + self->every;
1790 } 1794 }
1791 1795
1792 return PerlIOBuf_flush (aTHX_ f); 1796 return PerlIOBuf_flush (aTHX_ f);
1793} 1797}
1824 PerlIOBuf_set_ptrcnt, 1828 PerlIOBuf_set_ptrcnt,
1825}; 1829};
1826 1830
1827/*****************************************************************************/ 1831/*****************************************************************************/
1828 1832
1829static const CV *ssl_cv; /* for quick consistency check */ 1833static const CV *slf_cv; /* for quick consistency check */
1830 1834
1831static UNOP ssl_restore; /* restore stack as entersub did, for first-re-run */ 1835static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */
1832static SV *ssl_arg0; 1836static SV *slf_arg0;
1833static SV *ssl_arg1; 1837static SV *slf_arg1;
1834 1838
1835/* this restores the stack in the case we patched the entersub, to */ 1839/* this restores the stack in the case we patched the entersub, to */
1836/* recreate the stack frame as perl will on following calls */ 1840/* recreate the stack frame as perl will on following calls */
1837/* since entersub cleared the stack */ 1841/* since entersub cleared the stack */
1838static OP * 1842static OP *
1841 dSP; 1845 dSP;
1842 1846
1843 PUSHMARK (SP); 1847 PUSHMARK (SP);
1844 1848
1845 EXTEND (SP, 3); 1849 EXTEND (SP, 3);
1846 if (ssl_arg0) PUSHs (sv_2mortal (ssl_arg0)), ssl_arg0 = 0; 1850 if (slf_arg0) PUSHs (sv_2mortal (slf_arg0));
1847 if (ssl_arg1) PUSHs (sv_2mortal (ssl_arg1)), ssl_arg1 = 0; 1851 if (slf_arg1) PUSHs (sv_2mortal (slf_arg1));
1848 PUSHs ((SV *)CvGV (ssl_cv)); 1852 PUSHs ((SV *)CvGV (slf_cv));
1849 1853
1850 RETURNOP (ssl_restore.op_first); 1854 RETURNOP (slf_restore.op_first);
1851} 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};
1852 1864
1853/* declare prototype */ 1865/* declare prototype */
1854XS(XS_Coro__State__set_stacklevel); 1866XS(XS_Coro__State__set_stacklevel);
1855 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 */
1856static OP * 1874static OP *
1857pp_set_stacklevel (pTHX) 1875pp_slf (pTHX)
1858{ 1876{
1859 dSP; 1877 dSP;
1860 struct transfer_args ta; 1878 struct transfer_args ta;
1861 SV **arg = PL_stack_base + TOPMARK + 1; 1879 SV **arg = PL_stack_base + TOPMARK + 1;
1862 int items = SP - arg; /* args without function object */ 1880 int items = SP - arg; /* args without function object */
1881 int ix = PL_op->op_private & OPpENTERSUB_SLF;
1882 struct CoroSLF *slf = 0;
1863 1883
1864 /* do a quick consistency check on the "function" object, and if it isn't */ 1884 /* do a quick consistency check on the "function" object, and if it isn't */
1865 /* for us, divert to the real entersub */ 1885 /* for us, divert to the real entersub */
1866 if (SvTYPE (*sp) != SVt_PVGV || CvXSUB (GvCV (*sp)) != XS_Coro__State__set_stacklevel) 1886 if (SvTYPE (*sp) != SVt_PVGV || CvXSUB (GvCV (*sp)) != XS_Coro__State__set_stacklevel)
1867 return PL_ppaddr[OP_ENTERSUB](aTHX); 1887 return PL_ppaddr[OP_ENTERSUB](aTHX);
1876 arg = AvARRAY (av); 1896 arg = AvARRAY (av);
1877 items = AvFILLp (av) + 1; 1897 items = AvFILLp (av) + 1;
1878 } 1898 }
1879 1899
1880 PUTBACK; 1900 PUTBACK;
1881 switch (PL_op->op_private & 7) 1901
1902 if (!ix)
1903 {
1904 slf = (struct CoroSLF *)CvSTART (GvCV (*sp));
1905 ix = slf->prepare (aTHX_ arg, items);
1882 { 1906 }
1883 case 0: 1907
1908 switch (ix)
1909 {
1910 case CORO_SLF_SET_STACKLEVEL:
1884 prepare_set_stacklevel (&ta, (struct coro_cctx *)SvIV (arg [0])); 1911 prepare_set_stacklevel (&ta, (struct coro_cctx *)SvIV (arg [0]));
1885 break; 1912 break;
1886 1913
1887 case 1: 1914 case CORO_SLF_TRANSFER:
1888 if (items != 2) 1915 if (items != 2)
1889 croak ("Coro::State::transfer (prev, next) expects two arguments, not %d.", items); 1916 croak ("Coro::State::transfer (prev, next) expects two arguments, not %d.", items);
1890 1917
1891 prepare_transfer (aTHX_ &ta, arg [0], arg [1]); 1918 prepare_transfer (aTHX_ &ta, arg [0], arg [1]);
1892 break; 1919 break;
1893 1920
1894 case 2: 1921 case CORO_SLF_SCHEDULE:
1895 prepare_schedule (aTHX_ &ta); 1922 prepare_schedule (aTHX_ &ta);
1896 break; 1923 break;
1897 1924
1898 case 3: 1925 case CORO_SLF_CEDE:
1899 prepare_cede (aTHX_ &ta); 1926 prepare_cede (aTHX_ &ta);
1900 break; 1927 break;
1901 1928
1902 case 4: 1929 case CORO_SLF_CEDE_NOTSELF:
1903 if (!prepare_cede_notself (aTHX_ &ta)) 1930 prepare_cede_notself (aTHX_ &ta);
1904 goto skip;
1905
1906 break; 1931 break;
1907 }
1908 1932
1933 default:
1934 abort ();
1935 }
1936
1937 do
1909 TRANSFER (ta, 0); 1938 TRANSFER (ta, 0);
1939 while (slf && slf->check (aTHX));
1940
1910 SPAGAIN; 1941 SPAGAIN;
1911 1942
1912skip:
1913 PUTBACK; 1943 PUTBACK;
1914 SSL_TAIL; 1944 SLF_TAIL;
1915 SPAGAIN; 1945 SPAGAIN;
1916 RETURN; 1946 RETURN;
1917} 1947}
1918 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}
1973
1919MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ 1974MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_
1920 1975
1921PROTOTYPES: DISABLE 1976PROTOTYPES: DISABLE
1922
1923# these not obviously related functions are all rolled into the same xs
1924# function to increase chances that they all will call transfer with the same
1925# stack offset
1926void
1927_set_stacklevel (...)
1928 ALIAS:
1929 Coro::State::transfer = 1
1930 Coro::schedule = 2
1931 Coro::cede = 3
1932 Coro::cede_notself = 4
1933 CODE:
1934{
1935 assert (("FATAL: ssl call recursion in Coro module (please report)", PL_op->op_ppaddr != pp_set_stacklevel));
1936
1937 /* we patch the op, and then re-run the whole call */
1938 /* we have to put some dummy argument on the stack for this to work */
1939 /* TODO: walk back the opcode chain (but how?), nuke the pp_gv etc. */
1940 ssl_restore.op_next = (OP *)&ssl_restore;
1941 ssl_restore.op_type = OP_NULL;
1942 ssl_restore.op_ppaddr = pp_restore;
1943 ssl_restore.op_first = PL_op;
1944
1945 ssl_arg0 = items > 0 ? SvREFCNT_inc (ST (0)) : 0;
1946 ssl_arg1 = items > 1 ? SvREFCNT_inc (ST (1)) : 0;
1947
1948 PL_op->op_ppaddr = pp_set_stacklevel;
1949 PL_op->op_private = PL_op->op_private & ~7 | ix; /* we potentially share our private flags with entersub */
1950
1951 PL_op = (OP *)&ssl_restore;
1952}
1953 1977
1954BOOT: 1978BOOT:
1955{ 1979{
1956#ifdef USE_ITHREADS 1980#ifdef USE_ITHREADS
1957 MUTEX_INIT (&coro_lock); 1981 MUTEX_INIT (&coro_lock);
1959 coro_thx = PERL_GET_CONTEXT; 1983 coro_thx = PERL_GET_CONTEXT;
1960# endif 1984# endif
1961#endif 1985#endif
1962 BOOT_PAGESIZE; 1986 BOOT_PAGESIZE;
1963 1987
1964 ssl_cv = get_cv ("Coro::State::_set_stacklevel", 0);
1965
1966 irsgv = gv_fetchpv ("/" , GV_ADD|GV_NOTQUAL, SVt_PV); 1988 irsgv = gv_fetchpv ("/" , GV_ADD|GV_NOTQUAL, SVt_PV);
1967 stdoutgv = gv_fetchpv ("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO); 1989 stdoutgv = gv_fetchpv ("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO);
1968 1990
1969 orig_sigelem_get = PL_vtbl_sigelem.svt_get; PL_vtbl_sigelem.svt_get = coro_sigelem_get; 1991 orig_sigelem_get = PL_vtbl_sigelem.svt_get; PL_vtbl_sigelem.svt_get = coro_sigelem_get;
1970 orig_sigelem_set = PL_vtbl_sigelem.svt_set; PL_vtbl_sigelem.svt_set = coro_sigelem_set; 1992 orig_sigelem_set = PL_vtbl_sigelem.svt_set; PL_vtbl_sigelem.svt_set = coro_sigelem_set;
2029 for (i = 1; i < items; i++) 2051 for (i = 1; i < items; i++)
2030 av_push (coro->args, newSVsv (ST (i))); 2052 av_push (coro->args, newSVsv (ST (i)));
2031} 2053}
2032 OUTPUT: 2054 OUTPUT:
2033 RETVAL 2055 RETVAL
2056
2057void
2058_set_stacklevel (...)
2059 ALIAS:
2060 _set_stacklevel = CORO_SLF_SET_STACKLEVEL
2061 Coro::State::transfer = CORO_SLF_TRANSFER
2062 Coro::schedule = CORO_SLF_SCHEDULE
2063 Coro::cede = CORO_SLF_CEDE
2064 Coro::cede_notself = CORO_SLF_CEDE_NOTSELF
2065 CODE:
2066 coro_slf_patch (aTHX_ cv, ix, &ST (0), items);
2034 2067
2035bool 2068bool
2036_destroy (SV *coro_sv) 2069_destroy (SV *coro_sv)
2037 CODE: 2070 CODE:
2038 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv)); 2071 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv));
2156 SvREFCNT_dec (self->throw); 2189 SvREFCNT_dec (self->throw);
2157 self->throw = SvOK (throw) ? newSVsv (throw) : 0; 2190 self->throw = SvOK (throw) ? newSVsv (throw) : 0;
2158 2191
2159void 2192void
2160api_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
2161 2195
2162SV * 2196SV *
2163has_cctx (Coro::State coro) 2197has_cctx (Coro::State coro)
2164 PROTOTYPE: $ 2198 PROTOTYPE: $
2165 CODE: 2199 CODE:
2242 coroapi.schedule = api_schedule; 2276 coroapi.schedule = api_schedule;
2243 coroapi.cede = api_cede; 2277 coroapi.cede = api_cede;
2244 coroapi.cede_notself = api_cede_notself; 2278 coroapi.cede_notself = api_cede_notself;
2245 coroapi.ready = api_ready; 2279 coroapi.ready = api_ready;
2246 coroapi.is_ready = api_is_ready; 2280 coroapi.is_ready = api_is_ready;
2247 coroapi.nready = &coro_nready; 2281 coroapi.nready = coro_nready;
2248 coroapi.current = coro_current; 2282 coroapi.current = coro_current;
2249 2283
2250 GCoroAPI = &coroapi; 2284 GCoroAPI = &coroapi;
2251 sv_setiv (sv, (IV)&coroapi); 2285 sv_setiv (sv, (IV)&coroapi);
2252 SvREADONLY_on (sv); 2286 SvREADONLY_on (sv);
2293 2327
2294SV * 2328SV *
2295ready (SV *self) 2329ready (SV *self)
2296 PROTOTYPE: $ 2330 PROTOTYPE: $
2297 CODE: 2331 CODE:
2298 RETVAL = boolSV (api_ready (self)); 2332 RETVAL = boolSV (api_ready (aTHX_ self));
2299 OUTPUT: 2333 OUTPUT:
2300 RETVAL 2334 RETVAL
2301 2335
2302int 2336int
2303nready (...) 2337nready (...)
2373 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0); 2407 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0);
2374 2408
2375 coro->prio = 0; 2409 coro->prio = 0;
2376 2410
2377 if (coro->cctx && (coro->cctx->flags & CC_TRACE)) 2411 if (coro->cctx && (coro->cctx->flags & CC_TRACE))
2378 api_trace (coro_current, 0); 2412 api_trace (aTHX_ coro_current, 0);
2379 2413
2380 av_push (av_async_pool, newSVsv (coro_current)); 2414 av_push (av_async_pool, newSVsv (coro_current));
2381} 2415}
2382 2416
2383#if 0 2417#if 0
2455 2489
2456 av_push (av, data_sv); 2490 av_push (av, data_sv);
2457 2491
2458 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av))); 2492 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
2459 2493
2460 api_ready (self); 2494 api_ready (aTHX_ self);
2461} 2495}
2462 2496
2463void 2497void
2464_set_state (SV *state) 2498_set_state (SV *state)
2465 PROTOTYPE: $ 2499 PROTOTYPE: $
2490 PROTOTYPE: @ 2524 PROTOTYPE: @
2491 CODE: 2525 CODE:
2492{ 2526{
2493 static int incede; 2527 static int incede;
2494 2528
2495 api_cede_notself (); 2529 api_cede_notself (aTHX);
2496 2530
2497 ++incede; 2531 ++incede;
2498 while (coro_nready >= incede && api_cede ()) 2532 while (coro_nready >= incede && api_cede (aTHX))
2499 ; 2533 ;
2500 2534
2501 sv_setsv (sv_activity, &PL_sv_undef); 2535 sv_setsv (sv_activity, &PL_sv_undef);
2502 if (coro_nready >= incede) 2536 if (coro_nready >= incede)
2503 { 2537 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines