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.289 by root, Mon Nov 17 08:25:06 2008 UTC vs.
Revision 1.290 by root, Tue Nov 18 05:51:38 2008 UTC

152# endif 152# endif
153#endif 153#endif
154 154
155static double (*nvtime)(); /* so why doesn't it take void? */ 155static double (*nvtime)(); /* so why doesn't it take void? */
156 156
157/* we hijack an hopefully unused CV flag for our purposes */
158#define CVf_SLF 0x4000
159static OP *pp_slf (pTHX);
160
157static U32 cctx_gen; 161static U32 cctx_gen;
158static size_t cctx_stacksize = CORO_STACKSIZE; 162static size_t cctx_stacksize = CORO_STACKSIZE;
159static struct CoroAPI coroapi; 163static struct CoroAPI coroapi;
160static AV *main_mainstack; /* used to differentiate between $main and others */ 164static AV *main_mainstack; /* used to differentiate between $main and others */
161static JMPENV *main_top_env; 165static JMPENV *main_top_env;
814slf_check_nop (pTHX_ struct CoroSLF *frame) 818slf_check_nop (pTHX_ struct CoroSLF *frame)
815{ 819{
816 return 0; 820 return 0;
817} 821}
818 822
823static UNOP coro_setup_op;
824
819static void NOINLINE /* noinline to keep it out of the transfer fast path */ 825static void NOINLINE /* noinline to keep it out of the transfer fast path */
820coro_setup (pTHX_ struct coro *coro) 826coro_setup (pTHX_ struct coro *coro)
821{ 827{
822 /* 828 /*
823 * emulate part of the perl startup here. 829 * emulate part of the perl startup here.
868 * likely was suspended in pp_slf, so we have to emulate entering pp_slf here. 874 * likely was suspended in pp_slf, so we have to emulate entering pp_slf here.
869 */ 875 */
870 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */ 876 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */
871 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */ 877 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */
872 878
879 /* and we have to provide the pp_slf op in any case, so pp_slf can skip it */
880 coro_setup_op.op_type = OP_CUSTOM;
881 coro_setup_op.op_ppaddr = pp_slf;
882 coro_setup_op.op_next = PL_op;
883
884 PL_op = (OP *)&coro_setup_op;
885
886 /* copy throw, in case it was set before coro_setup */
873 coro_throw = coro->throw; 887 coro_throw = coro->throw;
874} 888}
875 889
876static void 890static void
877coro_destruct (pTHX_ struct coro *coro) 891coro_destruct (pTHX_ struct coro *coro)
1041 1055
1042 TAINT_NOT; 1056 TAINT_NOT;
1043 return 0; 1057 return 0;
1044} 1058}
1045 1059
1060static struct coro_cctx *cctx_ssl_cctx;
1061static struct CoroSLF cctx_ssl_frame;
1062
1046static void 1063static void
1047prepare_set_stacklevel (struct coro_transfer_args *ta, struct coro_cctx *cctx) 1064slf_prepare_set_stacklevel (pTHX_ struct coro_transfer_args *ta)
1048{ 1065{
1049 ta->prev = (struct coro *)cctx; 1066 ta->prev = (struct coro *)cctx_ssl_cctx;
1050 ta->next = 0; 1067 ta->next = 0;
1051} 1068}
1052 1069
1053/* inject a fake call to Coro::State::_cctx_init into the execution */ 1070static int
1054/* _cctx_init should be careful, as it could be called at almost any time */ 1071slf_check_set_stacklevel (pTHX_ struct CoroSLF *frame)
1055/* during execution of a perl program */ 1072{
1056/* also initialises PL_top_env */ 1073 *frame = cctx_ssl_frame;
1074
1075 return 0;
1076}
1077
1078/* initialises PL_top_env and injects a pseudo-slf-call to sett he stacklevel */
1057static void NOINLINE 1079static void NOINLINE
1058cctx_prepare (pTHX_ coro_cctx *cctx) 1080cctx_prepare (pTHX_ coro_cctx *cctx)
1059{ 1081{
1060 dSP;
1061 UNOP myop;
1062
1063 PL_top_env = &PL_start_env; 1082 PL_top_env = &PL_start_env;
1064 1083
1065 if (cctx->flags & CC_TRACE) 1084 if (cctx->flags & CC_TRACE)
1066 PL_runops = runops_trace; 1085 PL_runops = runops_trace;
1067 1086
1068 Zero (&myop, 1, UNOP); 1087 /* we already must be in an SLF call, there is no other valid way
1069 myop.op_next = PL_op; 1088 * that can lead to creation of a new cctx */
1070 myop.op_flags = OPf_WANT_VOID | OPf_STACKED; 1089 assert (("FATAL: can't prepare slf-less cctx in Coro module (please report)",
1090 slf_frame.prepare && PL_op->op_ppaddr == pp_slf));
1071 1091
1072 PUSHMARK (SP); 1092 cctx_ssl_cctx = cctx;
1073 EXTEND (SP, 2); 1093 cctx_ssl_frame = slf_frame;
1074 PUSHs (sv_2mortal (newSViv ((IV)cctx))); 1094
1075 PUSHs ((SV *)get_cv ("Coro::State::_cctx_init", FALSE)); 1095 slf_frame.prepare = slf_prepare_set_stacklevel;
1076 PUTBACK; 1096 slf_frame.check = slf_check_set_stacklevel;
1077 PL_op = (OP *)&myop;
1078 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
1079 SPAGAIN;
1080} 1097}
1081 1098
1082/* the tail of transfer: execute stuff we can only do after a transfer */ 1099/* the tail of transfer: execute stuff we can only do after a transfer */
1083INLINE void 1100INLINE void
1084transfer_tail (pTHX) 1101transfer_tail (pTHX)
1528 ENTER; 1545 ENTER;
1529 SAVETMPS; 1546 SAVETMPS;
1530 1547
1531 PUSHMARK (SP); 1548 PUSHMARK (SP);
1532 PUTBACK; 1549 PUTBACK;
1533 call_sv (sv_hook, G_DISCARD); 1550 call_sv (sv_hook, G_VOID | G_DISCARD);
1534 SPAGAIN;
1535 1551
1536 FREETMPS; 1552 FREETMPS;
1537 LEAVE; 1553 LEAVE;
1538 } 1554 }
1539 1555
1566 ENTER; 1582 ENTER;
1567 SAVETMPS; 1583 SAVETMPS;
1568 1584
1569 PUSHMARK (SP); 1585 PUSHMARK (SP);
1570 PUTBACK; 1586 PUTBACK;
1571 call_sv (get_sv ("Coro::idle", FALSE), G_DISCARD); 1587 call_sv (get_sv ("Coro::idle", FALSE), G_VOID | G_DISCARD);
1572 SPAGAIN;
1573 1588
1574 FREETMPS; 1589 FREETMPS;
1575 LEAVE; 1590 LEAVE;
1576 continue; 1591 continue;
1577 } 1592 }
1717 1732
1718 RETURNOP (slf_restore.op_first); 1733 RETURNOP (slf_restore.op_first);
1719} 1734}
1720 1735
1721static void 1736static void
1722slf_prepare_set_stacklevel (pTHX_ struct coro_transfer_args *ta)
1723{
1724 prepare_set_stacklevel (ta, (struct coro_cctx *)slf_frame.data);
1725}
1726
1727static void
1728slf_init_set_stacklevel (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1729{
1730 assert (("FATAL: set_stacklevel needs the coro cctx as sole argument", items == 1));
1731
1732 frame->prepare = slf_prepare_set_stacklevel;
1733 frame->check = slf_check_nop;
1734 frame->data = (void *)SvIV (arg [0]);
1735}
1736
1737static void
1738slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta) 1737slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta)
1739{ 1738{
1740 SV **arg = (SV **)slf_frame.data; 1739 SV **arg = (SV **)slf_frame.data;
1741 1740
1742 prepare_transfer (aTHX_ ta, arg [0], arg [1]); 1741 prepare_transfer (aTHX_ ta, arg [0], arg [1]);
1771slf_init_cede_notself (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 1770slf_init_cede_notself (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1772{ 1771{
1773 frame->prepare = prepare_cede_notself; 1772 frame->prepare = prepare_cede_notself;
1774 frame->check = slf_check_nop; 1773 frame->check = slf_check_nop;
1775} 1774}
1776
1777/* we hijack an hopefully unused CV flag for our purposes */
1778#define CVf_SLF 0x4000
1779 1775
1780/* 1776/*
1781 * these not obviously related functions are all rolled into one 1777 * these not obviously related functions are all rolled into one
1782 * function to increase chances that they all will call transfer with the same 1778 * function to increase chances that they all will call transfer with the same
1783 * stack offset 1779 * stack offset
1840 while (slf_frame.check (aTHX_ &slf_frame)); 1836 while (slf_frame.check (aTHX_ &slf_frame));
1841 1837
1842 slf_frame.prepare = 0; /* invalidate the frame, we are done processing it */ 1838 slf_frame.prepare = 0; /* invalidate the frame, we are done processing it */
1843 1839
1844 /* return value handling - mostly like entersub */ 1840 /* return value handling - mostly like entersub */
1845 {
1846 dSP;
1847 SV **bot = PL_stack_base + checkmark;
1848 int gimme = GIMME_V;
1849
1850 /* make sure we put something on the stack in scalar context */ 1841 /* make sure we put something on the stack in scalar context */
1851 if (gimme == G_SCALAR) 1842 if (GIMME_V == G_SCALAR)
1852 { 1843 {
1853 if (sp == bot) 1844 dSP;
1854 XPUSHs (&PL_sv_undef); 1845 SV **bot = PL_stack_base + checkmark;
1855 1846
1847 if (sp == bot) /* too few, push undef */
1848 bot [1] = &PL_sv_undef;
1849 else if (sp != bot + 1) /* too many, take last one */
1850 bot [1] = *sp;
1851
1856 SP = bot + 1; 1852 SP = bot + 1;
1857 }
1858 1853
1859 PUTBACK; 1854 PUTBACK;
1860 } 1855 }
1861 1856
1862 /* exception handling */ 1857 /* exception handling */
1863 if (expect_false (coro_throw)) 1858 if (expect_false (coro_throw))
1864 { 1859 {
1865 SV *exception = sv_2mortal (coro_throw); 1860 SV *exception = sv_2mortal (coro_throw);
2378} 2373}
2379 OUTPUT: 2374 OUTPUT:
2380 RETVAL 2375 RETVAL
2381 2376
2382void 2377void
2383_set_stacklevel (...)
2384 CODE:
2385 CORO_EXECUTE_SLF_XS (slf_init_set_stacklevel);
2386
2387void
2388transfer (...) 2378transfer (...)
2389 PROTOTYPE: $$ 2379 PROTOTYPE: $$
2390 CODE: 2380 CODE:
2391 CORO_EXECUTE_SLF_XS (slf_init_transfer); 2381 CORO_EXECUTE_SLF_XS (slf_init_transfer);
2392 2382
2841 else 2831 else
2842 { 2832 {
2843 int i; 2833 int i;
2844 EXTEND (SP, AvFILLp (av) + 1 - 1); 2834 EXTEND (SP, AvFILLp (av) + 1 - 1);
2845 for (i = 1; i <= AvFILLp (av); ++i) 2835 for (i = 1; i <= AvFILLp (av); ++i)
2846 PUSHs (newSVsv (AvARRAY (av)[i])); 2836 PUSHs (sv_2mortal (newRV_inc (AvARRAY (av)[i])));
2847 } 2837 }
2848} 2838}
2849 2839
2850 2840
2851MODULE = Coro::State PACKAGE = Coro::AnyEvent 2841MODULE = Coro::State PACKAGE = Coro::AnyEvent
2868 sv_setsv (sv_activity, &PL_sv_undef); 2858 sv_setsv (sv_activity, &PL_sv_undef);
2869 if (coro_nready >= incede) 2859 if (coro_nready >= incede)
2870 { 2860 {
2871 PUSHMARK (SP); 2861 PUSHMARK (SP);
2872 PUTBACK; 2862 PUTBACK;
2873 call_pv ("Coro::AnyEvent::_activity", G_DISCARD | G_EVAL); 2863 call_pv ("Coro::AnyEvent::_activity", G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
2874 SPAGAIN;
2875 } 2864 }
2876 2865
2877 --incede; 2866 --incede;
2878} 2867}
2879 2868

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines