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.469 by root, Fri Jul 14 02:43:50 2017 UTC vs.
Revision 1.481 by root, Thu Aug 19 22:43:02 2021 UTC

2#define USE_NO_MINGW_SETJMP_TWO_ARGS 2#define USE_NO_MINGW_SETJMP_TWO_ARGS
3 3
4#define NDEBUG 1 /* perl usually disables NDEBUG later */ 4#define NDEBUG 1 /* perl usually disables NDEBUG later */
5 5
6#include "libcoro/coro.c" 6#include "libcoro/coro.c"
7
8#if CORO_UCONTEXT
9 #define CORO_BACKEND "ucontext"
10#elif CORO_SJLJ
11 #define CORO_BACKEND "sjlj"
12#elif CORO_LINUX
13 #define CORO_BACKEND "linux"
14#elif CORO_LOSER
15 #define CORO_BACKEND "loser"
16#elif CORO_FIBER
17 #define CORO_BACKEND "fiber"
18#elif CORO_IRIX
19 #define CORO_BACKEND "irix"
20#elif CORO_ASM
21 #define CORO_BACKEND "asm"
22#elif CORO_PTHREAD
23 #define CORO_BACKEND "pthread"
24#else
25 #define CORO_BACKEND "unknown"
26#endif
7 27
8#define PERL_NO_GET_CONTEXT 28#define PERL_NO_GET_CONTEXT
9#define PERL_EXT 29#define PERL_EXT
10 30
11#include "EXTERN.h" 31#include "EXTERN.h"
116# define CORO_CLOCK_MONOTONIC 1 136# define CORO_CLOCK_MONOTONIC 1
117# define CORO_CLOCK_THREAD_CPUTIME_ID 3 137# define CORO_CLOCK_THREAD_CPUTIME_ID 3
118# endif 138# endif
119#endif 139#endif
120 140
141/* one off bugfix for perl 5.22 */
142#if PERL_VERSION_ATLEAST(5,22,0) && !PERL_VERSION_ATLEAST(5,24,0)
143# undef PadlistNAMES
144# define PadlistNAMES(pl) *((PADNAMELIST **)PadlistARRAY (pl))
145#endif
146
121#if PERL_VERSION_ATLEAST(5,24,0) 147#if PERL_VERSION_ATLEAST(5,24,0)
122# define SUB_ARGARRAY PL_curpad[0] 148# define SUB_ARGARRAY PL_curpad[0]
123#else 149#else
124# define SUB_ARGARRAY (SV *)cx->blk_sub.argarray 150# define SUB_ARGARRAY (SV *)cx->blk_sub.argarray
125#endif 151#endif
126 152
127/* perl usually suppressed asserts. for debugging, we sometimes force it to be on */ 153/* perl usually suppresses asserts. for debugging, we sometimes force it to be on */
128#if 0 154#if 0
129# undef NDEBUG 155# undef NDEBUG
130# include <assert.h> 156# include <assert.h>
131#endif 157#endif
132 158
257 int usecount; /* number of transfers to this coro */ 283 int usecount; /* number of transfers to this coro */
258 284
259 /* coro process data */ 285 /* coro process data */
260 int prio; 286 int prio;
261 SV *except; /* exception to be thrown */ 287 SV *except; /* exception to be thrown */
262 SV *rouse_cb; /* last rouse callback */ 288 SV *rouse_cb; /* most recently created rouse callback */
263 AV *on_destroy; /* callbacks or coros to notify on destroy */ 289 AV *on_destroy; /* callbacks or coros to notify on destroy */
264 AV *status; /* the exit status list */ 290 AV *status; /* the exit status list */
265 291
266 /* async_pool */ 292 /* async_pool */
267 SV *saved_deffh; 293 SV *saved_deffh;
1216 myop.op_next = Nullop; 1242 myop.op_next = Nullop;
1217 myop.op_type = OP_ENTERSUB; 1243 myop.op_type = OP_ENTERSUB;
1218 myop.op_flags = OPf_WANT_VOID; 1244 myop.op_flags = OPf_WANT_VOID;
1219 1245
1220 PUSHMARK (SP); 1246 PUSHMARK (SP);
1221 PUSHs ((SV *)coro->startcv); 1247 XPUSHs ((SV *)coro->startcv);
1222 PUTBACK; 1248 PUTBACK;
1223 PL_op = (OP *)&myop; 1249 PL_op = (OP *)&myop;
1224 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX); 1250 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
1225 } 1251 }
1226 1252
1283 1309
1284 assert (("FATAL: tried to destroy currently running coroutine", coro->mainstack != PL_mainstack)); 1310 assert (("FATAL: tried to destroy currently running coroutine", coro->mainstack != PL_mainstack));
1285 1311
1286 save_perl (aTHX_ current); 1312 save_perl (aTHX_ current);
1287 1313
1288 /* this will cause transfer_check to croak on block*/ 1314 /* this will cause transfer_check to croak on block */
1289 SvRV_set (coro_current, (SV *)coro->hv); 1315 SvRV_set (coro_current, (SV *)coro->hv);
1290 1316
1291 load_perl (aTHX_ coro); 1317 load_perl (aTHX_ coro);
1292 1318
1293 /* restore swapped sv's */ 1319 /* restore swapped sv's */
1374 av_push (av, SvREFCNT_inc_NN (*bot++)); 1400 av_push (av, SvREFCNT_inc_NN (*bot++));
1375 1401
1376 PL_runops = RUNOPS_DEFAULT; 1402 PL_runops = RUNOPS_DEFAULT;
1377 ENTER; 1403 ENTER;
1378 SAVETMPS; 1404 SAVETMPS;
1405 PUSHMARK (SP);
1379 EXTEND (SP, 3); 1406 EXTEND (SP, 3);
1380 PUSHMARK (SP);
1381 PUSHs (&PL_sv_no); 1407 PUSHs (&PL_sv_no);
1382 PUSHs (fullname); 1408 PUSHs (fullname);
1383 PUSHs (sv_2mortal (newRV_noinc ((SV *)av))); 1409 PUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
1384 PUTBACK; 1410 PUTBACK;
1385 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0); 1411 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0);
1412 gv_efullname3 (fullname, gv, 0); 1438 gv_efullname3 (fullname, gv, 0);
1413 1439
1414 PL_runops = RUNOPS_DEFAULT; 1440 PL_runops = RUNOPS_DEFAULT;
1415 ENTER; 1441 ENTER;
1416 SAVETMPS; 1442 SAVETMPS;
1443 PUSHMARK (SP);
1417 EXTEND (SP, 3); 1444 EXTEND (SP, 3);
1418 PUSHMARK (SP);
1419 PUSHs (&PL_sv_yes); 1445 PUSHs (&PL_sv_yes);
1420 PUSHs (fullname); 1446 PUSHs (fullname);
1421 PUSHs (CxHASARGS (cx) ? sv_2mortal (newRV_inc (SUB_ARGARRAY)) : &PL_sv_undef); 1447 PUSHs (CxHASARGS (cx) ? sv_2mortal (newRV_inc (SUB_ARGARRAY)) : &PL_sv_undef);
1422 PUTBACK; 1448 PUTBACK;
1423 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0); 1449 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0);
1436 dSP; 1462 dSP;
1437 1463
1438 PL_runops = RUNOPS_DEFAULT; 1464 PL_runops = RUNOPS_DEFAULT;
1439 ENTER; 1465 ENTER;
1440 SAVETMPS; 1466 SAVETMPS;
1441 EXTEND (SP, 3);
1442 PL_runops = RUNOPS_DEFAULT;
1443 PUSHMARK (SP); 1467 PUSHMARK (SP);
1468 EXTEND (SP, 2);
1444 PUSHs (sv_2mortal (newSVpv (OutCopFILE (oldcop), 0))); 1469 PUSHs (sv_2mortal (newSVpv (OutCopFILE (oldcop), 0)));
1445 PUSHs (sv_2mortal (newSViv (CopLINE (oldcop)))); 1470 PUSHs (sv_2mortal (newSViv (CopLINE (oldcop))));
1446 PUTBACK; 1471 PUTBACK;
1447 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_line_cb", sizeof ("_trace_line_cb") - 1, 0); 1472 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_line_cb", sizeof ("_trace_line_cb") - 1, 0);
1448 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 1473 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1819 1844
1820static int 1845static int
1821coro_state_free (pTHX_ SV *sv, MAGIC *mg) 1846coro_state_free (pTHX_ SV *sv, MAGIC *mg)
1822{ 1847{
1823 struct coro *coro = (struct coro *)mg->mg_ptr; 1848 struct coro *coro = (struct coro *)mg->mg_ptr;
1849
1850 coro_state_destroy (aTHX_ coro);
1824 mg->mg_ptr = 0; 1851 mg->mg_ptr = 0;
1825 1852
1826 coro_state_destroy (aTHX_ coro);
1827 SvREFCNT_dec (coro->on_destroy); 1853 SvREFCNT_dec (coro->on_destroy);
1828 SvREFCNT_dec (coro->status); 1854 SvREFCNT_dec (coro->status);
1829 1855
1830 Safefree (coro); 1856 Safefree (coro);
1831 1857
1834 1860
1835static int ecb_cold 1861static int ecb_cold
1836coro_state_dup (pTHX_ MAGIC *mg, CLONE_PARAMS *params) 1862coro_state_dup (pTHX_ MAGIC *mg, CLONE_PARAMS *params)
1837{ 1863{
1838 /* called when perl clones the current process the slow way (windows process emulation) */ 1864 /* called when perl clones the current process the slow way (windows process emulation) */
1839 /* WE SIMply nuke the pointers in the copy, causing perl to croak */ 1865 /* we simply nuke the pointers in the copy, causing perl to croak */
1840 mg->mg_ptr = 0; 1866 mg->mg_ptr = 0;
1841 mg->mg_virtual = 0; 1867 mg->mg_virtual = 0;
1842 1868
1843 return 0; 1869 return 0;
1844} 1870}
2366safe_cancel (pTHX_ struct coro *coro, SV **arg, int items) 2392safe_cancel (pTHX_ struct coro *coro, SV **arg, int items)
2367{ 2393{
2368 if (coro->cctx) 2394 if (coro->cctx)
2369 croak ("coro inside C callback, unable to cancel at this time, caught"); 2395 croak ("coro inside C callback, unable to cancel at this time, caught");
2370 2396
2371 if (coro->flags & CF_NEW) 2397 if (coro->flags & (CF_NEW | CF_ZOMBIE))
2372 { 2398 {
2373 coro_set_status (aTHX_ coro, arg, items); 2399 coro_set_status (aTHX_ coro, arg, items);
2374 coro_state_destroy (aTHX_ coro); 2400 coro_state_destroy (aTHX_ coro);
2375 } 2401 }
2376 else 2402 else
2456 2482
2457 if (ecb_expect_false (coro->cctx) && ecb_expect_false (coro->cctx->flags & CC_TRACE)) 2483 if (ecb_expect_false (coro->cctx) && ecb_expect_false (coro->cctx->flags & CC_TRACE))
2458 api_trace (aTHX_ coro_current, 0); 2484 api_trace (aTHX_ coro_current, 0);
2459 2485
2460 frame->prepare = prepare_schedule; 2486 frame->prepare = prepare_schedule;
2461 av_push (av_async_pool, SvREFCNT_inc (hv)); 2487 av_push (av_async_pool, SvREFCNT_inc_NN (hv));
2462 } 2488 }
2463 } 2489 }
2464 else 2490 else
2465 { 2491 {
2466 /* first iteration, simply fall through */ 2492 /* first iteration, simply fall through */
2479static void 2505static void
2480coro_rouse_callback (pTHX_ CV *cv) 2506coro_rouse_callback (pTHX_ CV *cv)
2481{ 2507{
2482 dXSARGS; 2508 dXSARGS;
2483 SV *data = (SV *)S_GENSUB_ARG; 2509 SV *data = (SV *)S_GENSUB_ARG;
2510 SV *coro = SvRV (data);
2484 2511
2512 /* data starts being either undef or a coro, and is replaced by the results when done */
2485 if (SvTYPE (SvRV (data)) != SVt_PVAV) 2513 if (SvTYPE (coro) != SVt_PVAV)
2486 { 2514 {
2487 /* first call, set args */ 2515 /* first call, set args */
2488 SV *coro = SvRV (data);
2489 AV *av = newAV ();
2490 2516
2491 SvRV_set (data, (SV *)av); 2517 assert (&ST (0) < &ST (1)); /* ensure the stack is in the order we expect it to be */
2518 SvRV_set (data, (SV *)av_make (items, &ST (0))); /* av_make copies the SVs */
2492 2519
2493 /* better take a full copy of the arguments */ 2520 if (coro != &PL_sv_undef)
2494 while (items--) 2521 {
2495 av_store (av, items, newSVsv (ST (items)));
2496
2497 api_ready (aTHX_ coro); 2522 api_ready (aTHX_ coro);
2498 SvREFCNT_dec (coro); 2523 SvREFCNT_dec_NN (coro);
2524 }
2499 } 2525 }
2500 2526
2501 XSRETURN_EMPTY; 2527 XSRETURN_EMPTY;
2502} 2528}
2503 2529
2520 2546
2521 EXTEND (SP, AvFILLp (av) + 1); 2547 EXTEND (SP, AvFILLp (av) + 1);
2522 for (i = 0; i <= AvFILLp (av); ++i) 2548 for (i = 0; i <= AvFILLp (av); ++i)
2523 PUSHs (sv_2mortal (AvARRAY (av)[i])); 2549 PUSHs (sv_2mortal (AvARRAY (av)[i]));
2524 2550
2525 /* we have stolen the elements, so set length to zero and free */ 2551 /* we have stolen the elements, make it unreal and free */
2526 AvFILLp (av) = -1; 2552 AvREAL_off (av);
2527 av_undef (av); 2553 av_undef (av);
2528 2554
2529 PUTBACK; 2555 PUTBACK;
2530 } 2556 }
2531 2557
2556 croak ("Coro::rouse_wait called with illegal callback argument,"); 2582 croak ("Coro::rouse_wait called with illegal callback argument,");
2557 2583
2558 { 2584 {
2559 CV *cv = (CV *)SvRV (cb); /* for S_GENSUB_ARG */ 2585 CV *cv = (CV *)SvRV (cb); /* for S_GENSUB_ARG */
2560 SV *data = (SV *)S_GENSUB_ARG; 2586 SV *data = (SV *)S_GENSUB_ARG;
2587 int data_ready = SvTYPE (SvRV (data)) == SVt_PVAV;
2588
2589 /* if there is no data, we need to store the current coro in the reference so we can be woken up */
2590 if (!data_ready)
2591 if (SvRV (data) != &PL_sv_undef)
2592 croak ("Coro::rouse_wait was called on a calback that is already being waited for - only one thread can wait for a rouse callback, caught");
2593 else
2594 SvRV_set (data, SvREFCNT_inc_NN (SvRV (coro_current)));
2561 2595
2562 frame->data = (void *)data; 2596 frame->data = (void *)data;
2563 frame->prepare = SvTYPE (SvRV (data)) == SVt_PVAV ? prepare_nop : prepare_schedule; 2597 frame->prepare = data_ready ? prepare_nop : prepare_schedule;
2564 frame->check = slf_check_rouse_wait; 2598 frame->check = slf_check_rouse_wait;
2565 } 2599 }
2566} 2600}
2567 2601
2568static SV * 2602static SV *
2569coro_new_rouse_cb (pTHX) 2603coro_new_rouse_cb (pTHX)
2570{ 2604{
2571 HV *hv = (HV *)SvRV (coro_current); 2605 HV *hv = (HV *)SvRV (coro_current);
2572 struct coro *coro = SvSTATE_hv (hv); 2606 struct coro *coro = SvSTATE_hv (hv);
2573 SV *data = newRV_inc ((SV *)hv); 2607 SV *data = newRV_noinc (&PL_sv_undef);
2574 SV *cb = s_gensub (aTHX_ coro_rouse_callback, (void *)data); 2608 SV *cb = s_gensub (aTHX_ coro_rouse_callback, (void *)data);
2575 2609
2576 sv_magicext (SvRV (cb), data, CORO_MAGIC_type_rouse, 0, 0, 0); 2610 sv_magicext (SvRV (cb), data, CORO_MAGIC_type_rouse, 0, 0, 0);
2577 SvREFCNT_dec (data); /* magicext increases the refcount */ 2611 SvREFCNT_dec_NN (data); /* magicext increases the refcount */
2578 2612
2579 SvREFCNT_dec (coro->rouse_cb); 2613 SvREFCNT_dec (coro->rouse_cb);
2580 coro->rouse_cb = SvREFCNT_inc_NN (cb); 2614 coro->rouse_cb = SvREFCNT_inc_NN (cb);
2581 2615
2582 return cb; 2616 return cb;
3589 save = POPs; save_ptr = SvPVbyte (save, save_len); 3623 save = POPs; save_ptr = SvPVbyte (save, save_len);
3590 load = POPs; load_ptr = SvPVbyte (load, load_len); 3624 load = POPs; load_ptr = SvPVbyte (load, load_len);
3591 3625
3592 map_len = load_len + save_len + 16; 3626 map_len = load_len + save_len + 16;
3593 3627
3594 map_base = mmap (0, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
3595
3596 if (map_base == (char *)MAP_FAILED)
3597 map_base = mmap (0, map_len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 3628 map_base = mmap (0, map_len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
3598 3629
3599 assert (("Coro: unable to mmap jit code page, cannot continue.", map_base != (char *)MAP_FAILED)); 3630 assert (("Coro: unable to mmap jit code page, cannot continue.", map_base != (char *)MAP_FAILED));
3600 3631
3601 load_perl_slots = (load_save_perl_slots_type)map_base; 3632 load_perl_slots = (load_save_perl_slots_type)map_base;
3602 memcpy (map_base, load_ptr, load_len); 3633 memcpy (load_perl_slots, load_ptr, load_len);
3603 3634
3604 map_base += (load_len + 15) & ~15;
3605
3606 save_perl_slots = (load_save_perl_slots_type)map_base; 3635 save_perl_slots = (load_save_perl_slots_type)(map_base + ((load_len + 15) & ~15));
3607 memcpy (map_base, save_ptr, save_len); 3636 memcpy (save_perl_slots, save_ptr, save_len);
3608 3637
3609 /* we are good citizens and try to make the page read-only, so the evil evil */ 3638 /* we are good citizens and try to make the page read-only, so the evil evil */
3610 /* hackers might have it a bit more difficult */ 3639 /* hackers might have it a bit more difficult */
3640 /* we do this in two steps, to potentially appease some security frameworks */
3641 mprotect (map_base, map_len, PROT_READ);
3611 mprotect (map_base, map_len, PROT_READ | PROT_EXEC); 3642 mprotect (map_base, map_len, PROT_READ | PROT_EXEC);
3612 3643
3613 PUTBACK; 3644 PUTBACK;
3614 eval_pv ("undef &Coro::State::_jit", 1); 3645 eval_pv ("undef &Coro::State::_jit", 1);
3615} 3646}
3669 rv_diehook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::diehook" , 0, SVt_PVCV)); 3700 rv_diehook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::diehook" , 0, SVt_PVCV));
3670 rv_warnhook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::warnhook", 0, SVt_PVCV)); 3701 rv_warnhook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::warnhook", 0, SVt_PVCV));
3671 3702
3672 coro_state_stash = gv_stashpv ("Coro::State", TRUE); 3703 coro_state_stash = gv_stashpv ("Coro::State", TRUE);
3673 3704
3705 newCONSTSUB (coro_state_stash, "BACKEND", newSVpv (CORO_BACKEND, 0)); /* undocumented */
3706
3674 newCONSTSUB (coro_state_stash, "CC_TRACE" , newSViv (CC_TRACE)); 3707 newCONSTSUB (coro_state_stash, "CC_TRACE" , newSViv (CC_TRACE));
3675 newCONSTSUB (coro_state_stash, "CC_TRACE_SUB" , newSViv (CC_TRACE_SUB)); 3708 newCONSTSUB (coro_state_stash, "CC_TRACE_SUB" , newSViv (CC_TRACE_SUB));
3676 newCONSTSUB (coro_state_stash, "CC_TRACE_LINE", newSViv (CC_TRACE_LINE)); 3709 newCONSTSUB (coro_state_stash, "CC_TRACE_LINE", newSViv (CC_TRACE_LINE));
3677 newCONSTSUB (coro_state_stash, "CC_TRACE_ALL" , newSViv (CC_TRACE_ALL)); 3710 newCONSTSUB (coro_state_stash, "CC_TRACE_ALL" , newSViv (CC_TRACE_ALL));
3678 3711
3802call (Coro::State coro, SV *coderef) 3835call (Coro::State coro, SV *coderef)
3803 ALIAS: 3836 ALIAS:
3804 eval = 1 3837 eval = 1
3805 CODE: 3838 CODE:
3806{ 3839{
3840 struct coro *current = SvSTATE_current;
3841
3807 if (coro->mainstack && ((coro->flags & CF_RUNNING) || coro->slot)) 3842 if ((coro == current) || (coro->mainstack && ((coro->flags & CF_RUNNING) || coro->slot)))
3808 { 3843 {
3809 struct coro *current = SvSTATE_current;
3810 struct CoroSLF slf_save; 3844 struct CoroSLF slf_save;
3811 3845
3812 if (current != coro) 3846 if (current != coro)
3813 { 3847 {
3814 PUTBACK; 3848 PUTBACK;
4073 coroapi.enterleave_hook = api_enterleave_hook; 4107 coroapi.enterleave_hook = api_enterleave_hook;
4074 coroapi.enterleave_unhook = api_enterleave_unhook; 4108 coroapi.enterleave_unhook = api_enterleave_unhook;
4075 coroapi.enterleave_scope_hook = api_enterleave_scope_hook; 4109 coroapi.enterleave_scope_hook = api_enterleave_scope_hook;
4076 4110
4077 /*GCoroAPI = &coroapi;*/ 4111 /*GCoroAPI = &coroapi;*/
4078 sv_setiv (sv, (IV)&coroapi); 4112 sv_setiv (sv, PTR2IV (&coroapi));
4079 SvREADONLY_on (sv); 4113 SvREADONLY_on (sv);
4080 } 4114 }
4081} 4115}
4082 4116
4083SV * 4117SV *

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines