… | |
… | |
33 | # define BOOT_PAGESIZE (void)0 |
33 | # define BOOT_PAGESIZE (void)0 |
34 | #endif |
34 | #endif |
35 | |
35 | |
36 | #if USE_VALGRIND |
36 | #if USE_VALGRIND |
37 | # include <valgrind/valgrind.h> |
37 | # include <valgrind/valgrind.h> |
|
|
38 | # define REGISTER_STACK(cctx,start,end) (cctx)->valgrind_id = VALGRIND_STACK_REGISTER ((start), (end)) |
|
|
39 | #else |
|
|
40 | # define REGISTER_STACK(cctx,start,end) |
38 | #endif |
41 | #endif |
39 | |
42 | |
40 | /* the maximum number of idle cctx that will be pooled */ |
43 | /* the maximum number of idle cctx that will be pooled */ |
41 | #define MAX_IDLE_CCTX 8 |
44 | #define MAX_IDLE_CCTX 8 |
42 | |
45 | |
… | |
… | |
135 | typedef struct coro_cctx { |
138 | typedef struct coro_cctx { |
136 | struct coro_cctx *next; |
139 | struct coro_cctx *next; |
137 | |
140 | |
138 | /* the stack */ |
141 | /* the stack */ |
139 | void *sptr; |
142 | void *sptr; |
140 | long ssize; /* positive == mmap, otherwise malloc */ |
143 | ssize_t ssize; /* positive == mmap, otherwise malloc */ |
141 | |
144 | |
142 | /* cpu state */ |
145 | /* cpu state */ |
143 | void *idle_sp; /* sp of top-level transfer/schedule/cede call */ |
146 | void *idle_sp; /* sp of top-level transfer/schedule/cede call */ |
144 | JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */ |
147 | JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */ |
145 | JMPENV *top_env; |
148 | JMPENV *top_env; |
… | |
… | |
362 | CvPADLIST (cv) = (AV *)POPs; |
365 | CvPADLIST (cv) = (AV *)POPs; |
363 | } |
366 | } |
364 | |
367 | |
365 | PUTBACK; |
368 | PUTBACK; |
366 | } |
369 | } |
|
|
370 | assert (!PL_comppad || AvARRAY (PL_comppad));//D |
367 | } |
371 | } |
368 | |
372 | |
369 | static void |
373 | static void |
370 | save_perl (Coro__State c) |
374 | save_perl (Coro__State c) |
371 | { |
375 | { |
|
|
376 | assert (!PL_comppad || AvARRAY (PL_comppad));//D |
372 | { |
377 | { |
373 | dSP; |
378 | dSP; |
374 | I32 cxix = cxstack_ix; |
379 | I32 cxix = cxstack_ix; |
375 | PERL_CONTEXT *ccstk = cxstack; |
380 | PERL_CONTEXT *ccstk = cxstack; |
376 | PERL_SI *top_si = PL_curstackinfo; |
381 | PERL_SI *top_si = PL_curstackinfo; |
… | |
… | |
535 | |
540 | |
536 | coro_init_stacks (); |
541 | coro_init_stacks (); |
537 | |
542 | |
538 | PL_curcop = &PL_compiling; |
543 | PL_curcop = &PL_compiling; |
539 | PL_in_eval = EVAL_NULL; |
544 | PL_in_eval = EVAL_NULL; |
|
|
545 | PL_comppad = 0; |
540 | PL_curpm = 0; |
546 | PL_curpm = 0; |
541 | PL_localizing = 0; |
547 | PL_localizing = 0; |
542 | PL_dirty = 0; |
548 | PL_dirty = 0; |
543 | PL_restartop = 0; |
549 | PL_restartop = 0; |
544 | |
550 | |
… | |
… | |
630 | |
636 | |
631 | cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; |
637 | cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; |
632 | /* mmap supposedly does allocate-on-write for us */ |
638 | /* mmap supposedly does allocate-on-write for us */ |
633 | cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); |
639 | cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); |
634 | |
640 | |
635 | if (cctx->sptr == (void *)-1) |
641 | if (cctx->sptr != (void *)-1) |
636 | { |
|
|
637 | perror ("FATAL: unable to mmap stack for coroutine"); |
|
|
638 | _exit (EXIT_FAILURE); |
|
|
639 | } |
642 | { |
640 | |
|
|
641 | # if STACKGUARD |
643 | # if STACKGUARD |
642 | mprotect (cctx->sptr, STACKGUARD * PAGESIZE, PROT_NONE); |
644 | mprotect (cctx->sptr, STACKGUARD * PAGESIZE, PROT_NONE); |
643 | # endif |
645 | # endif |
644 | |
646 | REGISTER_STACK ( |
645 | #else |
647 | cctx, |
646 | |
|
|
647 | cctx->ssize = STACKSIZE * (long)sizeof (long); |
|
|
648 | New (0, cctx->sptr, STACKSIZE, long); |
|
|
649 | |
|
|
650 | if (!cctx->sptr) |
|
|
651 | { |
|
|
652 | perror ("FATAL: unable to malloc stack for coroutine"); |
|
|
653 | _exit (EXIT_FAILURE); |
|
|
654 | } |
|
|
655 | |
|
|
656 | #endif |
|
|
657 | |
|
|
658 | #if USE_VALGRIND |
|
|
659 | cctx->valgrind_id = VALGRIND_STACK_REGISTER ( |
|
|
660 | STACKGUARD * PAGESIZE + (char *)cctx->sptr, |
648 | STACKGUARD * PAGESIZE + (char *)cctx->sptr, |
661 | cctx->ssize + (char *)cctx->sptr |
649 | cctx->ssize + (char *)cctx->sptr |
662 | ); |
650 | ); |
663 | #endif |
|
|
664 | |
651 | |
665 | coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, cctx->ssize); |
652 | coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, cctx->ssize); |
|
|
653 | } |
|
|
654 | else |
|
|
655 | #endif |
|
|
656 | { |
|
|
657 | cctx->ssize = -STACKSIZE * (long)sizeof (long); |
|
|
658 | New (0, cctx->sptr, STACKSIZE, long); |
|
|
659 | |
|
|
660 | if (!cctx->sptr) |
|
|
661 | { |
|
|
662 | perror ("FATAL: unable to allocate stack for coroutine"); |
|
|
663 | _exit (EXIT_FAILURE); |
|
|
664 | } |
|
|
665 | |
|
|
666 | REGISTER_STACK ( |
|
|
667 | cctx, |
|
|
668 | (char *)cctx->sptr, |
|
|
669 | (char *)cctx->sptr - cctx->ssize |
|
|
670 | ); |
|
|
671 | |
|
|
672 | coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, -cctx->ssize); |
|
|
673 | } |
666 | |
674 | |
667 | return cctx; |
675 | return cctx; |
668 | } |
676 | } |
669 | |
677 | |
670 | static void |
678 | static void |
… | |
… | |
678 | #if USE_VALGRIND |
686 | #if USE_VALGRIND |
679 | VALGRIND_STACK_DEREGISTER (cctx->valgrind_id); |
687 | VALGRIND_STACK_DEREGISTER (cctx->valgrind_id); |
680 | #endif |
688 | #endif |
681 | |
689 | |
682 | #if HAVE_MMAP |
690 | #if HAVE_MMAP |
|
|
691 | if (cctx->ssize > 0) |
683 | munmap (cctx->sptr, cctx->ssize); |
692 | munmap (cctx->sptr, cctx->ssize); |
684 | #else |
693 | else |
|
|
694 | #endif |
685 | Safefree (cctx->sptr); |
695 | Safefree (cctx->sptr); |
686 | #endif |
|
|
687 | |
696 | |
688 | Safefree (cctx); |
697 | Safefree (cctx); |
689 | } |
698 | } |
690 | |
699 | |
691 | static coro_cctx * |
700 | static coro_cctx * |
… | |
… | |
838 | coro->flags |= CF_DESTROYED; |
847 | coro->flags |= CF_DESTROYED; |
839 | |
848 | |
840 | if (coro->flags & CF_READY) |
849 | if (coro->flags & CF_READY) |
841 | { |
850 | { |
842 | /* reduce nready, as destroying a ready coro effectively unreadies it */ |
851 | /* reduce nready, as destroying a ready coro effectively unreadies it */ |
843 | /* alternative: look through all ready queues and remove it */ |
852 | /* alternative: look through all ready queues and remove the coro */ |
844 | LOCK; |
853 | LOCK; |
845 | --coro_nready; |
854 | --coro_nready; |
846 | UNLOCK; |
855 | UNLOCK; |
847 | } |
856 | } |
848 | else |
857 | else |
849 | coro->flags |= CF_READY; /* make sure it is NOT put into the readyqueue */ |
858 | coro->flags |= CF_READY; /* make sure it is NOT put into the readyqueue */ |
850 | |
859 | |
851 | if (coro->mainstack && coro->mainstack != main_mainstack) |
860 | if (coro->mainstack && coro->mainstack != main_mainstack) |
852 | { |
861 | { |
|
|
862 | struct coro temp; |
|
|
863 | |
853 | assert (!(coro->flags & CF_RUNNING)); |
864 | assert (!(coro->flags & CF_RUNNING)); |
854 | |
865 | |
855 | struct coro temp; |
|
|
856 | Zero (&temp, 1, struct coro); |
866 | Zero (&temp, 1, struct coro); |
857 | temp.save = CORO_SAVE_ALL; |
867 | temp.save = CORO_SAVE_ALL; |
858 | |
868 | |
859 | if (coro->flags & CF_RUNNING) |
869 | if (coro->flags & CF_RUNNING) |
860 | croak ("FATAL: tried to destroy currently running coroutine"); |
870 | croak ("FATAL: tried to destroy currently running coroutine"); |
… | |
… | |
1021 | |
1031 | |
1022 | for (;;) |
1032 | for (;;) |
1023 | { |
1033 | { |
1024 | LOCK; |
1034 | LOCK; |
1025 | next_sv = coro_deq (PRIO_MIN); |
1035 | next_sv = coro_deq (PRIO_MIN); |
1026 | UNLOCK; |
|
|
1027 | |
1036 | |
1028 | /* nothing to schedule: call the idle handler */ |
1037 | /* nothing to schedule: call the idle handler */ |
1029 | if (!next_sv) |
1038 | if (!next_sv) |
1030 | { |
1039 | { |
1031 | dSP; |
1040 | dSP; |
|
|
1041 | UNLOCK; |
1032 | |
1042 | |
1033 | ENTER; |
1043 | ENTER; |
1034 | SAVETMPS; |
1044 | SAVETMPS; |
1035 | |
1045 | |
1036 | PUSHMARK (SP); |
1046 | PUSHMARK (SP); |
… | |
… | |
1045 | ta->next = SvSTATE (next_sv); |
1055 | ta->next = SvSTATE (next_sv); |
1046 | |
1056 | |
1047 | /* cannot transfer to destroyed coros, skip and look for next */ |
1057 | /* cannot transfer to destroyed coros, skip and look for next */ |
1048 | if (ta->next->flags & CF_DESTROYED) |
1058 | if (ta->next->flags & CF_DESTROYED) |
1049 | { |
1059 | { |
|
|
1060 | UNLOCK; |
1050 | SvREFCNT_dec (next_sv); |
1061 | SvREFCNT_dec (next_sv); |
1051 | /* coro_nready is already taken care of by destroy */ |
1062 | /* coro_nready is already taken care of by destroy */ |
1052 | continue; |
1063 | continue; |
1053 | } |
1064 | } |
1054 | |
1065 | |
1055 | LOCK; |
|
|
1056 | --coro_nready; |
1066 | --coro_nready; |
1057 | UNLOCK; |
1067 | UNLOCK; |
1058 | break; |
1068 | break; |
1059 | } |
1069 | } |
1060 | |
1070 | |