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.283 by root, Sun Nov 16 11:12:57 2008 UTC vs.
Revision 1.286 by root, Mon Nov 17 04:19:49 2008 UTC

241/* this is a structure representing a perl-level coroutine */ 241/* this is a structure representing a perl-level coroutine */
242struct coro { 242struct coro {
243 /* the C coroutine allocated to this perl coroutine, if any */ 243 /* the C coroutine allocated to this perl coroutine, if any */
244 coro_cctx *cctx; 244 coro_cctx *cctx;
245 245
246 /* process data */ 246 /* state data */
247 struct CoroSLF slf_frame; /* saved slf frame */ 247 struct CoroSLF slf_frame; /* saved slf frame */
248 AV *mainstack; 248 AV *mainstack;
249 perl_slots *slot; /* basically the saved sp */ 249 perl_slots *slot; /* basically the saved sp */
250 250
251 AV *args; /* data associated with this coroutine (initial args) */ 251 AV *args; /* data associated with this coroutine (initial args) */
269}; 269};
270 270
271typedef struct coro *Coro__State; 271typedef struct coro *Coro__State;
272typedef struct coro *Coro__State_or_hashref; 272typedef struct coro *Coro__State_or_hashref;
273 273
274/* the following variables are effectively part of the perl context */
275/* and get copied between struct coro and these variables */
276/* the mainr easonw e don't support windows process emulation */
274static struct CoroSLF slf_frame; /* the current slf frame */ 277static struct CoroSLF slf_frame; /* the current slf frame */
278static SV *coro_throw;
275 279
276/** Coro ********************************************************************/ 280/** Coro ********************************************************************/
277 281
278#define PRIO_MAX 3 282#define PRIO_MAX 3
279#define PRIO_HIGH 1 283#define PRIO_HIGH 1
513 } 517 }
514 518
515 PUTBACK; 519 PUTBACK;
516 } 520 }
517 521
518 slf_frame = c->slf_frame; 522 slf_frame = c->slf_frame;
523 coro_throw = c->throw;
519} 524}
520 525
521static void 526static void
522save_perl (pTHX_ Coro__State c) 527save_perl (pTHX_ Coro__State c)
523{ 528{
529 c->throw = coro_throw;
524 c->slf_frame = slf_frame; 530 c->slf_frame = slf_frame;
525 531
526 { 532 {
527 dSP; 533 dSP;
528 I32 cxix = cxstack_ix; 534 I32 cxix = cxstack_ix;
821slf_check_nop (pTHX_ struct CoroSLF *frame) 827slf_check_nop (pTHX_ struct CoroSLF *frame)
822{ 828{
823 return 0; 829 return 0;
824} 830}
825 831
826static void 832static void NOINLINE /* noinline to keep it out of the transfer fast path */
827coro_setup (pTHX_ struct coro *coro) 833coro_setup (pTHX_ struct coro *coro)
828{ 834{
829 /* 835 /*
830 * emulate part of the perl startup here. 836 * emulate part of the perl startup here.
831 */ 837 */
874 /* this newly created coroutine might be run on an existing cctx which most 880 /* this newly created coroutine might be run on an existing cctx which most
875 * likely was suspended in pp_slf, so we have to emulate entering pp_slf here. 881 * likely was suspended in pp_slf, so we have to emulate entering pp_slf here.
876 */ 882 */
877 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */ 883 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */
878 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */ 884 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */
885
886 coro_throw = coro->throw;
879} 887}
880 888
881static void 889static void
882coro_destruct (pTHX_ struct coro *coro) 890coro_destruct (pTHX_ struct coro *coro)
883{ 891{
907 915
908 SvREFCNT_dec (PL_diehook); 916 SvREFCNT_dec (PL_diehook);
909 SvREFCNT_dec (PL_warnhook); 917 SvREFCNT_dec (PL_warnhook);
910 918
911 SvREFCNT_dec (coro->saved_deffh); 919 SvREFCNT_dec (coro->saved_deffh);
912 SvREFCNT_dec (coro->throw); 920 SvREFCNT_dec (coro_throw);
913 921
914 coro_destruct_stacks (aTHX); 922 coro_destruct_stacks (aTHX);
915} 923}
916 924
917INLINE void 925INLINE void
1276/** coroutine switching *****************************************************/ 1284/** coroutine switching *****************************************************/
1277 1285
1278static void 1286static void
1279transfer_check (pTHX_ struct coro *prev, struct coro *next) 1287transfer_check (pTHX_ struct coro *prev, struct coro *next)
1280{ 1288{
1289 /* TODO: throwing up here is considered harmful */
1290
1281 if (expect_true (prev != next)) 1291 if (expect_true (prev != next))
1282 { 1292 {
1283 if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW)))) 1293 if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW))))
1284 croak ("Coro::State::transfer called with non-running/new prev Coro::State, but can only transfer from running or new states,"); 1294 croak ("Coro::State::transfer called with non-running/new prev Coro::State, but can only transfer from running or new states,");
1285 1295
1295#endif 1305#endif
1296 } 1306 }
1297} 1307}
1298 1308
1299/* always use the TRANSFER macro */ 1309/* always use the TRANSFER macro */
1300static void NOINLINE 1310static void NOINLINE /* noinline so we have a fixed stackframe */
1301transfer (pTHX_ struct coro *prev, struct coro *next, int force_cctx) 1311transfer (pTHX_ struct coro *prev, struct coro *next, int force_cctx)
1302{ 1312{
1303 dSTACKLEVEL; 1313 dSTACKLEVEL;
1304 1314
1305 /* sometimes transfer is only called to set idle_sp */ 1315 /* sometimes transfer is only called to set idle_sp */
1766 PerlIOBuf_set_ptrcnt, 1776 PerlIOBuf_set_ptrcnt,
1767}; 1777};
1768 1778
1769/*****************************************************************************/ 1779/*****************************************************************************/
1770 1780
1771static const CV *slf_cv; /* for quick consistency check */
1772
1773static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */ 1781static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */
1782static const CV *slf_cv;
1774static SV *slf_arg0; 1783static SV **slf_argv;
1775static SV *slf_arg1; 1784static int slf_argc, slf_arga; /* count, allocated */
1776static SV *slf_arg2; 1785static I32 slf_ax; /* top of stack, for restore */
1777 1786
1778/* this restores the stack in the case we patched the entersub, to */ 1787/* this restores the stack in the case we patched the entersub, to */
1779/* recreate the stack frame as perl will on following calls */ 1788/* recreate the stack frame as perl will on following calls */
1780/* since entersub cleared the stack */ 1789/* since entersub cleared the stack */
1781static OP * 1790static OP *
1782pp_restore (pTHX) 1791pp_restore (pTHX)
1783{ 1792{
1784 dSP; 1793 int i;
1794 SV **SP = PL_stack_base + slf_ax;
1785 1795
1786 PUSHMARK (SP); 1796 PUSHMARK (SP);
1787 1797
1788 EXTEND (SP, 3); 1798 EXTEND (SP, slf_argc + 1);
1799
1800 for (i = 0; i < slf_argc; ++i)
1789 if (slf_arg0) PUSHs (sv_2mortal (slf_arg0)); 1801 PUSHs (sv_2mortal (slf_argv [i]));
1790 if (slf_arg1) PUSHs (sv_2mortal (slf_arg1)); 1802
1791 if (slf_arg2) PUSHs (sv_2mortal (slf_arg2));
1792 PUSHs ((SV *)CvGV (slf_cv)); 1803 PUSHs ((SV *)CvGV (slf_cv));
1793 1804
1794 RETURNOP (slf_restore.op_first); 1805 RETURNOP (slf_restore.op_first);
1795} 1806}
1796 1807
1814slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta) 1825slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta)
1815{ 1826{
1816 SV **arg = (SV **)slf_frame.data; 1827 SV **arg = (SV **)slf_frame.data;
1817 1828
1818 prepare_transfer (aTHX_ ta, arg [0], arg [1]); 1829 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 }
1830} 1830}
1831 1831
1832static void 1832static void
1833slf_init_transfer (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 1833slf_init_transfer (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1834{ 1834{
1897 AV *av = GvAV (PL_defgv); 1897 AV *av = GvAV (PL_defgv);
1898 arg = AvARRAY (av); 1898 arg = AvARRAY (av);
1899 items = AvFILLp (av) + 1; 1899 items = AvFILLp (av) + 1;
1900 } 1900 }
1901 1901
1902 PUTBACK;
1903
1904 /* 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 */
1905 ((coro_slf_cb)CvXSUBANY (GvCV (gv)).any_ptr) 1903 ((coro_slf_cb)CvXSUBANY (GvCV (gv)).any_ptr)
1906 (aTHX_ &slf_frame, GvCV (gv), arg, items); 1904 (aTHX_ &slf_frame, GvCV (gv), arg, items);
1907 1905
1908 /* pop args */ 1906 /* pop args */
1924 1922
1925 checkmark = PL_stack_sp - PL_stack_base; 1923 checkmark = PL_stack_sp - PL_stack_base;
1926 } 1924 }
1927 while (slf_frame.check (aTHX_ &slf_frame)); 1925 while (slf_frame.check (aTHX_ &slf_frame));
1928 1926
1927 slf_frame.prepare = 0; /* invalidate the frame, we are done processing it */
1928
1929 /* return value handling - mostly like entersub */
1929 { 1930 {
1930 dSP; 1931 dSP;
1931 SV **bot = PL_stack_base + checkmark; 1932 SV **bot = PL_stack_base + checkmark;
1932 int gimme = GIMME_V; 1933 int gimme = GIMME_V;
1933
1934 slf_frame.prepare = 0; /* invalidate the frame, so it gets initialised again next time */
1935 1934
1936 /* make sure we put something on the stack in scalar context */ 1935 /* make sure we put something on the stack in scalar context */
1937 if (gimme == G_SCALAR) 1936 if (gimme == G_SCALAR)
1938 { 1937 {
1939 if (sp == bot) 1938 if (sp == bot)
1943 } 1942 }
1944 1943
1945 PUTBACK; 1944 PUTBACK;
1946 } 1945 }
1947 1946
1948 { 1947 /* exception handling */
1949 struct coro *coro = SvSTATE_current;
1950
1951 if (expect_false (coro->throw)) 1948 if (expect_false (coro_throw))
1952 { 1949 {
1953 SV *exception = sv_2mortal (coro->throw); 1950 SV *exception = sv_2mortal (coro_throw);
1954 1951
1955 coro->throw = 0; 1952 coro_throw = 0;
1956 sv_setsv (ERRSV, exception); 1953 sv_setsv (ERRSV, exception);
1957 croak (0); 1954 croak (0);
1958 } 1955 }
1959 }
1960 1956
1961 return NORMAL; 1957 return NORMAL;
1962} 1958}
1963 1959
1964static void 1960static void
1965api_execute_slf (pTHX_ CV *cv, coro_slf_cb init_cb, SV **arg, int items) 1961api_execute_slf (pTHX_ CV *cv, coro_slf_cb init_cb, I32 ax)
1966{ 1962{
1963 int i;
1964 SV **arg = PL_stack_base + ax;
1965 int items = PL_stack_sp - arg + 1;
1966
1967 assert (("FATAL: SLF call with illegal CV value", !CvANON (cv))); 1967 assert (("FATAL: SLF call with illegal CV value", !CvANON (cv)));
1968 1968
1969 if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB] 1969 if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB]
1970 && PL_op->op_ppaddr != pp_slf) 1970 && PL_op->op_ppaddr != pp_slf)
1971 croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught"); 1971 croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught");
1972 1972
1973 if (items > 3)
1974 croak ("Coro only supports up to three arguments to SLF functions currently (not %d), caught", items);
1975
1976 CvFLAGS (cv) |= CVf_SLF; 1973 CvFLAGS (cv) |= CVf_SLF;
1977 CvXSUBANY (cv).any_ptr = (void *)init_cb; 1974 CvXSUBANY (cv).any_ptr = (void *)init_cb;
1978 slf_cv = cv; 1975 slf_cv = cv;
1979 1976
1980 /* we patch the op, and then re-run the whole call */ 1977 /* we patch the op, and then re-run the whole call */
1981 /* we have to put the same argument on the stack for this to work */ 1978 /* we have to put the same argument on the stack for this to work */
1982 /* and this will be done by pp_restore */ 1979 /* and this will be done by pp_restore */
1983 slf_restore.op_next = (OP *)&slf_restore; 1980 slf_restore.op_next = (OP *)&slf_restore;
1984 slf_restore.op_type = OP_CUSTOM; 1981 slf_restore.op_type = OP_CUSTOM;
1985 slf_restore.op_ppaddr = pp_restore; 1982 slf_restore.op_ppaddr = pp_restore;
1986 slf_restore.op_first = PL_op; 1983 slf_restore.op_first = PL_op;
1987 1984
1988 slf_arg0 = items > 0 ? SvREFCNT_inc (arg [0]) : 0; 1985 slf_ax = ax - 1; /* undo the ax++ inside dAXMARK */
1989 slf_arg1 = items > 1 ? SvREFCNT_inc (arg [1]) : 0; 1986
1990 slf_arg2 = items > 2 ? SvREFCNT_inc (arg [2]) : 0; 1987 if (PL_op->op_flags & OPf_STACKED)
1988 {
1989 if (items > slf_arga)
1990 {
1991 slf_arga = items;
1992 free (slf_argv);
1993 slf_argv = malloc (slf_arga * sizeof (SV *));
1994 }
1995
1996 slf_argc = items;
1997
1998 for (i = 0; i < items; ++i)
1999 slf_argv [i] = SvREFCNT_inc (arg [i]);
2000 }
2001 else
2002 slf_argc = 0;
1991 2003
1992 PL_op->op_ppaddr = pp_slf; 2004 PL_op->op_ppaddr = pp_slf;
2005 PL_op->op_type = OP_CUSTOM; /* maybe we should leave it at entersub? */
1993 2006
1994 PL_op = (OP *)&slf_restore; 2007 PL_op = (OP *)&slf_restore;
1995} 2008}
1996 2009
1997/*****************************************************************************/ 2010/*****************************************************************************/
2216 RETVAL 2229 RETVAL
2217 2230
2218void 2231void
2219_set_stacklevel (...) 2232_set_stacklevel (...)
2220 CODE: 2233 CODE:
2221 api_execute_slf (aTHX_ cv, slf_init_set_stacklevel, &ST (0), items); 2234 CORO_EXECUTE_SLF_XS (slf_init_set_stacklevel);
2222 2235
2223void 2236void
2224transfer (...) 2237transfer (...)
2225 PROTOTYPE: $$ 2238 PROTOTYPE: $$
2226 CODE: 2239 CODE:
2227 api_execute_slf (aTHX_ cv, slf_init_transfer, &ST (0), items); 2240 CORO_EXECUTE_SLF_XS (slf_init_transfer);
2228 2241
2229bool 2242bool
2230_destroy (SV *coro_sv) 2243_destroy (SV *coro_sv)
2231 CODE: 2244 CODE:
2232 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv)); 2245 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv));
2350 2363
2351void 2364void
2352throw (Coro::State self, SV *throw = &PL_sv_undef) 2365throw (Coro::State self, SV *throw = &PL_sv_undef)
2353 PROTOTYPE: $;$ 2366 PROTOTYPE: $;$
2354 CODE: 2367 CODE:
2368{
2369 struct coro *current = SvSTATE_current;
2370 SV **throwp = self == current ? &coro_throw : &self->throw;
2355 SvREFCNT_dec (self->throw); 2371 SvREFCNT_dec (*throwp);
2356 self->throw = SvOK (throw) ? newSVsv (throw) : 0; 2372 *throwp = SvOK (throw) ? newSVsv (throw) : 0;
2373}
2357 2374
2358void 2375void
2359api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) 2376api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
2360 PROTOTYPE: $;$ 2377 PROTOTYPE: $;$
2361 C_ARGS: aTHX_ coro, flags 2378 C_ARGS: aTHX_ coro, flags
2455} 2472}
2456 2473
2457void 2474void
2458schedule (...) 2475schedule (...)
2459 CODE: 2476 CODE:
2460 api_execute_slf (aTHX_ cv, slf_init_schedule, &ST (0), 0); 2477 CORO_EXECUTE_SLF_XS (slf_init_schedule);
2461 2478
2462void 2479void
2463cede (...) 2480cede (...)
2464 CODE: 2481 CODE:
2465 api_execute_slf (aTHX_ cv, slf_init_cede, &ST (0), 0); 2482 CORO_EXECUTE_SLF_XS (slf_init_cede);
2466 2483
2467void 2484void
2468cede_notself (...) 2485cede_notself (...)
2469 CODE: 2486 CODE:
2470 api_execute_slf (aTHX_ cv, slf_init_cede_notself, &ST (0), 0); 2487 CORO_EXECUTE_SLF_XS (slf_init_cede_notself);
2471 2488
2472void 2489void
2473_set_current (SV *current) 2490_set_current (SV *current)
2474 PROTOTYPE: $ 2491 PROTOTYPE: $
2475 CODE: 2492 CODE:
2563 2580
2564void 2581void
2565_pool_2 (SV *cb) 2582_pool_2 (SV *cb)
2566 CODE: 2583 CODE:
2567{ 2584{
2568 struct coro *coro = SvSTATE_current; 2585 HV *hv = (HV *)SvRV (coro_current);
2586 struct coro *coro = SvSTATE_hv ((SV *)hv);
2569 2587
2570 sv_setsv (cb, &PL_sv_undef); 2588 sv_setsv (cb, &PL_sv_undef);
2571 2589
2572 SvREFCNT_dec ((SV *)PL_defoutgv); PL_defoutgv = (GV *)coro->saved_deffh; 2590 SvREFCNT_dec ((SV *)PL_defoutgv); PL_defoutgv = (GV *)coro->saved_deffh;
2573 coro->saved_deffh = 0; 2591 coro->saved_deffh = 0;
2580 SvREFCNT_dec (old); 2598 SvREFCNT_dec (old);
2581 croak ("\3async_pool terminate\2\n"); 2599 croak ("\3async_pool terminate\2\n");
2582 } 2600 }
2583 2601
2584 av_clear (GvAV (PL_defgv)); 2602 av_clear (GvAV (PL_defgv));
2585 hv_store ((HV *)SvRV (coro_current), "desc", sizeof ("desc") - 1, 2603 hv_store (hv, "desc", sizeof ("desc") - 1,
2586 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0); 2604 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0);
2587 2605
2588 coro->prio = 0; 2606 coro->prio = 0;
2589 2607
2590 if (coro->cctx && (coro->cctx->flags & CC_TRACE)) 2608 if (coro->cctx && (coro->cctx->flags & CC_TRACE))
2710 coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1); 2728 coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1);
2711 2729
2712void 2730void
2713down (SV *self) 2731down (SV *self)
2714 CODE: 2732 CODE:
2715 api_execute_slf (aTHX_ cv, slf_init_semaphore_down, &ST (0), 1); 2733 CORO_EXECUTE_SLF_XS (slf_init_semaphore_down);
2716 2734
2717void 2735void
2718try (SV *self) 2736try (SV *self)
2719 PPCODE: 2737 PPCODE:
2720{ 2738{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines