… | |
… | |
4 | #include "perl.h" |
4 | #include "perl.h" |
5 | #include "XSUB.h" |
5 | #include "XSUB.h" |
6 | |
6 | |
7 | #include "patchlevel.h" |
7 | #include "patchlevel.h" |
8 | |
8 | |
9 | #if USE_VALGRIND |
|
|
10 | # include <valgrind/valgrind.h> |
|
|
11 | #endif |
|
|
12 | |
|
|
13 | /* the maximum number of idle cctx that will be pooled */ |
|
|
14 | #define MAX_IDLE_CCTX 8 |
|
|
15 | |
|
|
16 | #define PERL_VERSION_ATLEAST(a,b,c) \ |
|
|
17 | (PERL_REVISION > (a) \ |
|
|
18 | || (PERL_REVISION == (a) \ |
|
|
19 | && (PERL_VERSION > (b) \ |
|
|
20 | || (PERL_VERSION == (b) && PERLSUBVERSION >= (c))))) |
|
|
21 | |
|
|
22 | #if !PERL_VERSION_ATLEAST (5,6,0) |
|
|
23 | # ifndef PL_ppaddr |
|
|
24 | # define PL_ppaddr ppaddr |
|
|
25 | # endif |
|
|
26 | # ifndef call_sv |
|
|
27 | # define call_sv perl_call_sv |
|
|
28 | # endif |
|
|
29 | # ifndef get_sv |
|
|
30 | # define get_sv perl_get_sv |
|
|
31 | # endif |
|
|
32 | # ifndef get_cv |
|
|
33 | # define get_cv perl_get_cv |
|
|
34 | # endif |
|
|
35 | # ifndef IS_PADGV |
|
|
36 | # define IS_PADGV(v) 0 |
|
|
37 | # endif |
|
|
38 | # ifndef IS_PADCONST |
|
|
39 | # define IS_PADCONST(v) 0 |
|
|
40 | # endif |
|
|
41 | #endif |
|
|
42 | |
|
|
43 | #include <stdio.h> |
9 | #include <stdio.h> |
44 | #include <errno.h> |
10 | #include <errno.h> |
45 | |
11 | #include <assert.h> |
46 | #if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64 |
|
|
47 | # undef STACKGUARD |
|
|
48 | #endif |
|
|
49 | |
|
|
50 | #ifndef STACKGUARD |
|
|
51 | # define STACKGUARD 0 |
|
|
52 | #endif |
|
|
53 | |
12 | |
54 | #ifdef HAVE_MMAP |
13 | #ifdef HAVE_MMAP |
55 | # include <unistd.h> |
14 | # include <unistd.h> |
56 | # include <sys/mman.h> |
15 | # include <sys/mman.h> |
57 | # ifndef MAP_ANONYMOUS |
16 | # ifndef MAP_ANONYMOUS |
… | |
… | |
72 | #else |
31 | #else |
73 | # define PAGESIZE 0 |
32 | # define PAGESIZE 0 |
74 | # define BOOT_PAGESIZE (void)0 |
33 | # define BOOT_PAGESIZE (void)0 |
75 | #endif |
34 | #endif |
76 | |
35 | |
|
|
36 | #if USE_VALGRIND |
|
|
37 | # include <valgrind/valgrind.h> |
|
|
38 | #endif |
|
|
39 | |
|
|
40 | /* the maximum number of idle cctx that will be pooled */ |
|
|
41 | #define MAX_IDLE_CCTX 8 |
|
|
42 | |
|
|
43 | #define PERL_VERSION_ATLEAST(a,b,c) \ |
|
|
44 | (PERL_REVISION > (a) \ |
|
|
45 | || (PERL_REVISION == (a) \ |
|
|
46 | && (PERL_VERSION > (b) \ |
|
|
47 | || (PERL_VERSION == (b) && PERLSUBVERSION >= (c))))) |
|
|
48 | |
|
|
49 | #if !PERL_VERSION_ATLEAST (5,6,0) |
|
|
50 | # ifndef PL_ppaddr |
|
|
51 | # define PL_ppaddr ppaddr |
|
|
52 | # endif |
|
|
53 | # ifndef call_sv |
|
|
54 | # define call_sv perl_call_sv |
|
|
55 | # endif |
|
|
56 | # ifndef get_sv |
|
|
57 | # define get_sv perl_get_sv |
|
|
58 | # endif |
|
|
59 | # ifndef get_cv |
|
|
60 | # define get_cv perl_get_cv |
|
|
61 | # endif |
|
|
62 | # ifndef IS_PADGV |
|
|
63 | # define IS_PADGV(v) 0 |
|
|
64 | # endif |
|
|
65 | # ifndef IS_PADCONST |
|
|
66 | # define IS_PADCONST(v) 0 |
|
|
67 | # endif |
|
|
68 | #endif |
|
|
69 | |
|
|
70 | /* 5.8.7 */ |
|
|
71 | #ifndef SvRV_set |
|
|
72 | # define SvRV_set(s,v) SvRV(s) = (v) |
|
|
73 | #endif |
|
|
74 | |
|
|
75 | #if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64 |
|
|
76 | # undef STACKGUARD |
|
|
77 | #endif |
|
|
78 | |
|
|
79 | #ifndef STACKGUARD |
|
|
80 | # define STACKGUARD 0 |
|
|
81 | #endif |
|
|
82 | |
|
|
83 | /* prefer perl internal functions over our own? */ |
|
|
84 | #ifndef PREFER_PERL_FUNCTIONS |
|
|
85 | # define PREFER_PERL_FUNCTIONS 0 |
|
|
86 | #endif |
|
|
87 | |
77 | /* The next macro should declare a variable stacklevel that contains and approximation |
88 | /* The next macro should declare a variable stacklevel that contains and approximation |
78 | * to the current C stack pointer. Its property is that it changes with each call |
89 | * to the current C stack pointer. Its property is that it changes with each call |
79 | * and should be unique. */ |
90 | * and should be unique. */ |
80 | #define dSTACKLEVEL int stacklevel |
91 | #define dSTACKLEVEL int stacklevel |
81 | #define STACKLEVEL ((void *)&stacklevel) |
92 | #define STACKLEVEL ((void *)&stacklevel) |
… | |
… | |
253 | |
264 | |
254 | if (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0) |
265 | if (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0) |
255 | CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--]; |
266 | CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--]; |
256 | else |
267 | else |
257 | { |
268 | { |
258 | #if 0 |
269 | #if PREFER_PERL_FUNCTIONS |
259 | /* this is probably cleaner, but also slower? */ |
270 | /* this is probably cleaner, but also slower? */ |
260 | CV *cp = Perl_cv_clone (cv); |
271 | CV *cp = Perl_cv_clone (cv); |
261 | CvPADLIST (cv) = CvPADLIST (cp); |
272 | CvPADLIST (cv) = CvPADLIST (cp); |
262 | CvPADLIST (cp) = 0; |
273 | CvPADLIST (cp) = 0; |
263 | SvREFCNT_dec (cp); |
274 | SvREFCNT_dec (cp); |
… | |
… | |
344 | /* |
355 | /* |
345 | * the worst thing you can imagine happens first - we have to save |
356 | * the worst thing you can imagine happens first - we have to save |
346 | * (and reinitialize) all cv's in the whole callchain :( |
357 | * (and reinitialize) all cv's in the whole callchain :( |
347 | */ |
358 | */ |
348 | |
359 | |
|
|
360 | EXTEND (SP, 3 + 1); |
349 | PUSHs (Nullsv); |
361 | PUSHs (Nullsv); |
350 | /* this loop was inspired by pp_caller */ |
362 | /* this loop was inspired by pp_caller */ |
351 | for (;;) |
363 | for (;;) |
352 | { |
364 | { |
353 | while (cxix >= 0) |
365 | while (cxix >= 0) |
… | |
… | |
359 | CV *cv = cx->blk_sub.cv; |
371 | CV *cv = cx->blk_sub.cv; |
360 | |
372 | |
361 | if (CvDEPTH (cv)) |
373 | if (CvDEPTH (cv)) |
362 | { |
374 | { |
363 | EXTEND (SP, 3); |
375 | EXTEND (SP, 3); |
364 | |
|
|
365 | PUSHs ((SV *)CvPADLIST (cv)); |
376 | PUSHs ((SV *)CvPADLIST (cv)); |
366 | PUSHs (INT2PTR (SV *, CvDEPTH (cv))); |
377 | PUSHs (INT2PTR (SV *, CvDEPTH (cv))); |
367 | PUSHs ((SV *)cv); |
378 | PUSHs ((SV *)cv); |
368 | |
379 | |
369 | CvDEPTH (cv) = 0; |
380 | CvDEPTH (cv) = 0; |
370 | get_padlist (cv); |
381 | get_padlist (cv); |
371 | } |
382 | } |
372 | } |
383 | } |
373 | #ifdef CXt_FORMAT |
|
|
374 | else if (CxTYPE (cx) == CXt_FORMAT) |
|
|
375 | { |
|
|
376 | /* I never used formats, so how should I know how these are implemented? */ |
|
|
377 | /* my bold guess is as a simple, plain sub... */ |
|
|
378 | croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats"); |
|
|
379 | } |
|
|
380 | #endif |
|
|
381 | } |
384 | } |
382 | |
385 | |
383 | if (top_si->si_type == PERLSI_MAIN) |
386 | if (top_si->si_type == PERLSI_MAIN) |
384 | break; |
387 | break; |
385 | |
388 | |
… | |
… | |
405 | * allocate various perl stacks. This is an exact copy |
408 | * allocate various perl stacks. This is an exact copy |
406 | * of perl.c:init_stacks, except that it uses less memory |
409 | * of perl.c:init_stacks, except that it uses less memory |
407 | * on the (sometimes correct) assumption that coroutines do |
410 | * on the (sometimes correct) assumption that coroutines do |
408 | * not usually need a lot of stackspace. |
411 | * not usually need a lot of stackspace. |
409 | */ |
412 | */ |
|
|
413 | #if PREFER_PERL_FUNCTIONS |
|
|
414 | # define coro_init_stacks init_stacks |
|
|
415 | #else |
410 | static void |
416 | static void |
411 | coro_init_stacks () |
417 | coro_init_stacks () |
412 | { |
418 | { |
413 | PL_curstackinfo = new_stackinfo(128, 1024/sizeof(PERL_CONTEXT)); |
419 | PL_curstackinfo = new_stackinfo(128, 1024/sizeof(PERL_CONTEXT)); |
414 | PL_curstackinfo->si_type = PERLSI_MAIN; |
420 | PL_curstackinfo->si_type = PERLSI_MAIN; |
… | |
… | |
444 | New(54,PL_retstack,16,OP*); |
450 | New(54,PL_retstack,16,OP*); |
445 | PL_retstack_ix = 0; |
451 | PL_retstack_ix = 0; |
446 | PL_retstack_max = 16; |
452 | PL_retstack_max = 16; |
447 | #endif |
453 | #endif |
448 | } |
454 | } |
|
|
455 | #endif |
449 | |
456 | |
450 | /* |
457 | /* |
451 | * destroy the stacks, the callchain etc... |
458 | * destroy the stacks, the callchain etc... |
452 | */ |
459 | */ |
453 | static void |
460 | static void |
454 | coro_destroy_stacks () |
461 | coro_destroy_stacks () |
455 | { |
462 | { |
456 | if (!IN_DESTRUCT) |
463 | if (!IN_DESTRUCT) |
457 | { |
464 | { |
458 | /* is this ugly, I ask? */ |
465 | /* restore all saved variables and stuff */ |
459 | LEAVE_SCOPE (0); |
466 | LEAVE_SCOPE (0); |
|
|
467 | assert (PL_tmps_floor == -1); |
460 | |
468 | |
461 | /* sure it is, but more important: is it correct?? :/ */ |
469 | /* free all temporaries */ |
462 | FREETMPS; |
470 | FREETMPS; |
|
|
471 | assert (PL_tmps_ix == -1); |
463 | |
472 | |
464 | /*POPSTACK_TO (PL_mainstack);*//*D*//*use*/ |
473 | POPSTACK_TO (PL_mainstack); |
465 | } |
474 | } |
466 | |
475 | |
467 | while (PL_curstackinfo->si_next) |
476 | while (PL_curstackinfo->si_next) |
468 | PL_curstackinfo = PL_curstackinfo->si_next; |
477 | PL_curstackinfo = PL_curstackinfo->si_next; |
469 | |
478 | |
470 | while (PL_curstackinfo) |
479 | while (PL_curstackinfo) |
471 | { |
480 | { |
472 | PERL_SI *p = PL_curstackinfo->si_prev; |
481 | PERL_SI *p = PL_curstackinfo->si_prev; |
473 | |
482 | |
474 | { /*D*//*remove*/ |
|
|
475 | dSP; |
|
|
476 | SWITCHSTACK (PL_curstack, PL_curstackinfo->si_stack); |
|
|
477 | PUTBACK; /* possibly superfluous */ |
|
|
478 | } |
|
|
479 | |
|
|
480 | if (!IN_DESTRUCT) |
483 | if (!IN_DESTRUCT) |
481 | { |
|
|
482 | dounwind (-1);/*D*//*remove*/ |
|
|
483 | SvREFCNT_dec (PL_curstackinfo->si_stack); |
484 | SvREFCNT_dec (PL_curstackinfo->si_stack); |
484 | } |
|
|
485 | |
485 | |
486 | Safefree (PL_curstackinfo->si_cxstack); |
486 | Safefree (PL_curstackinfo->si_cxstack); |
487 | Safefree (PL_curstackinfo); |
487 | Safefree (PL_curstackinfo); |
488 | PL_curstackinfo = p; |
488 | PL_curstackinfo = p; |
489 | } |
489 | } |
… | |
… | |
593 | { |
593 | { |
594 | coro_cctx *cctx; |
594 | coro_cctx *cctx; |
595 | |
595 | |
596 | ++cctx_count; |
596 | ++cctx_count; |
597 | |
597 | |
598 | New (0, cctx, 1, coro_cctx); |
598 | Newz (0, cctx, 1, coro_cctx); |
599 | |
599 | |
600 | #if HAVE_MMAP |
600 | #if HAVE_MMAP |
601 | |
601 | |
602 | cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; |
602 | cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; |
603 | /* mmap supposedly does allocate-on-write for us */ |
603 | /* mmap supposedly does allocate-on-write for us */ |
… | |
… | |
704 | { |
704 | { |
705 | dSTACKLEVEL; |
705 | dSTACKLEVEL; |
706 | |
706 | |
707 | /* sometimes transfer is only called to set idle_sp */ |
707 | /* sometimes transfer is only called to set idle_sp */ |
708 | if (!next) |
708 | if (!next) |
|
|
709 | { |
709 | ((coro_cctx *)prev)->idle_sp = STACKLEVEL; |
710 | ((coro_cctx *)prev)->idle_sp = STACKLEVEL; |
|
|
711 | assert (((coro_cctx *)prev)->top_env = PL_top_env); /* just for the side effetc when assert is enabled */ |
|
|
712 | } |
710 | else if (prev != next) |
713 | else if (prev != next) |
711 | { |
714 | { |
712 | coro_cctx *prev__cctx; |
715 | coro_cctx *prev__cctx; |
713 | |
716 | |
714 | if (prev->flags & CF_NEW) |
717 | if (prev->flags & CF_NEW) |
… | |
… | |
739 | /* first get rid of the old state */ |
742 | /* first get rid of the old state */ |
740 | save_perl (prev); |
743 | save_perl (prev); |
741 | /* setup coroutine call */ |
744 | /* setup coroutine call */ |
742 | setup_coro (next); |
745 | setup_coro (next); |
743 | /* need a new stack */ |
746 | /* need a new stack */ |
744 | assert (!next->stack); |
747 | assert (!next->cctx); |
745 | } |
748 | } |
746 | else |
749 | else |
747 | { |
750 | { |
748 | /* coroutine already started */ |
751 | /* coroutine already started */ |
749 | save_perl (prev); |
752 | save_perl (prev); |