… | |
… | |
65 | * and should be unique. */ |
65 | * and should be unique. */ |
66 | #define dSTACKLEVEL int stacklevel |
66 | #define dSTACKLEVEL int stacklevel |
67 | #define STACKLEVEL ((void *)&stacklevel) |
67 | #define STACKLEVEL ((void *)&stacklevel) |
68 | |
68 | |
69 | #define IN_DESTRUCT (PL_main_cv == Nullcv) |
69 | #define IN_DESTRUCT (PL_main_cv == Nullcv) |
70 | |
|
|
71 | #define labs(l) ((l) >= 0 ? (l) : -(l)) |
|
|
72 | |
70 | |
73 | #include "CoroAPI.h" |
71 | #include "CoroAPI.h" |
74 | |
72 | |
75 | #define TRANSFER_SET_STACKLEVEL 0x8bfbfbfb /* magic cookie */ |
73 | #define TRANSFER_SET_STACKLEVEL 0x8bfbfbfb /* magic cookie */ |
76 | |
74 | |
… | |
… | |
585 | { |
583 | { |
586 | /* |
584 | /* |
587 | * this is a _very_ stripped down perl interpreter ;) |
585 | * this is a _very_ stripped down perl interpreter ;) |
588 | */ |
586 | */ |
589 | dTHX; |
587 | dTHX; |
|
|
588 | int ret; |
590 | |
589 | |
591 | UNLOCK; |
590 | UNLOCK; |
592 | |
591 | |
593 | PL_top_env = &PL_start_env; |
592 | PL_top_env = &PL_start_env; |
594 | |
593 | |
… | |
… | |
596 | sv_setiv (get_sv ("Coro::State::cctx_restartop", FALSE), PTR2IV (PL_op)); |
595 | sv_setiv (get_sv ("Coro::State::cctx_restartop", FALSE), PTR2IV (PL_op)); |
597 | |
596 | |
598 | /* continue at cctx_init, without entersub */ |
597 | /* continue at cctx_init, without entersub */ |
599 | PL_restartop = CvSTART (get_cv ("Coro::State::cctx_init", FALSE)); |
598 | PL_restartop = CvSTART (get_cv ("Coro::State::cctx_init", FALSE)); |
600 | |
599 | |
601 | /* somebody will hit me for both perl_run and PL_restart_op */ |
600 | /* somebody will hit me for both perl_run and PL_restartop */ |
602 | perl_run (aTHX_ PERL_GET_CONTEXT); |
601 | ret = perl_run (aTHX_ PERL_GET_CONTEXT); |
|
|
602 | printf ("ret %d\n", ret);//D |
603 | |
603 | |
|
|
604 | fputs ("FATAL: C coroutine fell over the edge of the world, aborting.\n", stderr); |
604 | abort (); |
605 | abort (); |
605 | } |
606 | } |
606 | |
607 | |
607 | static coro_stack * |
608 | static coro_stack * |
608 | stack_new () |
609 | stack_new () |
… | |
… | |
611 | |
612 | |
612 | New (0, stack, 1, coro_stack); |
613 | New (0, stack, 1, coro_stack); |
613 | |
614 | |
614 | #if HAVE_MMAP |
615 | #if HAVE_MMAP |
615 | |
616 | |
616 | stack->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; /* mmap should do allocate-on-write for us */ |
617 | stack->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; |
|
|
618 | /* mmap suppsedly does allocate-on-write for us */ |
617 | stack->sptr = mmap (0, stack->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); |
619 | stack->sptr = mmap (0, stack->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); |
618 | |
620 | |
619 | if (stack->sptr == (void *)-1) |
621 | if (stack->sptr == (void *)-1) |
620 | { |
622 | { |
621 | perror ("FATAL: unable to mmap stack for coroutine"); |
623 | perror ("FATAL: unable to mmap stack for coroutine"); |
622 | _exit (EXIT_FAILURE); |
624 | _exit (EXIT_FAILURE); |
623 | } |
625 | } |
624 | |
626 | |
|
|
627 | # if STACKGUARD |
625 | mprotect (stack->sptr, STACKGUARD * PAGESIZE, PROT_NONE); |
628 | mprotect (stack->sptr, STACKGUARD * PAGESIZE, PROT_NONE); |
|
|
629 | # endif |
626 | |
630 | |
627 | #else |
631 | #else |
628 | |
632 | |
629 | stack->ssize = STACKSIZE * (long)sizeof (long); |
633 | stack->ssize = STACKSIZE * (long)sizeof (long); |
630 | New (0, stack->sptr, STACKSIZE, long); |
634 | New (0, stack->sptr, STACKSIZE, long); |
… | |
… | |
731 | |
735 | |
732 | if (prev__stack != next->stack) |
736 | if (prev__stack != next->stack) |
733 | { |
737 | { |
734 | prev__stack->top_env = PL_top_env; |
738 | prev__stack->top_env = PL_top_env; |
735 | PL_top_env = next->stack->top_env; |
739 | PL_top_env = next->stack->top_env; |
|
|
740 | printf ("stacksw %p %p\n", prev__stack->idle_sp, next->stack->idle_sp);//D |
736 | coro_transfer (&prev__stack->cctx, &next->stack->cctx); |
741 | coro_transfer (&prev__stack->cctx, &next->stack->cctx); |
737 | } |
742 | } |
738 | |
743 | |
739 | free_coro_mortal (); |
744 | free_coro_mortal (); |
740 | |
745 | |
… | |
… | |
1034 | } |
1039 | } |
1035 | OUTPUT: |
1040 | OUTPUT: |
1036 | RETVAL |
1041 | RETVAL |
1037 | |
1042 | |
1038 | void |
1043 | void |
1039 | transfer (...) |
1044 | _set_stacklevel (...) |
1040 | ALIAS: |
1045 | ALIAS: |
1041 | Coro::schedule = 1 |
1046 | Coro::State::transfer = 1 |
1042 | Coro::cede = 2 |
1047 | Coro::schedule = 2 |
1043 | _set_stacklevel = 3 |
1048 | Coro::cede = 3 |
|
|
1049 | Coro::Cont::yield = 4 |
1044 | CODE: |
1050 | CODE: |
1045 | { |
1051 | { |
1046 | struct transfer_args ta; |
1052 | struct transfer_args ta; |
1047 | |
1053 | |
1048 | switch (ix) |
1054 | switch (ix) |
1049 | { |
1055 | { |
1050 | case 0: |
1056 | case 0: |
1051 | if (items != 3) |
|
|
1052 | croak ("Coro::State::transfer(prev,next,flags) expects three arguments, not %d", items); |
|
|
1053 | |
|
|
1054 | prepare_transfer (&ta, ST (0), ST (1), SvIV (ST (2))); |
|
|
1055 | break; |
|
|
1056 | |
|
|
1057 | case 1: |
|
|
1058 | prepare_schedule (&ta); |
|
|
1059 | break; |
|
|
1060 | |
|
|
1061 | case 2: |
|
|
1062 | prepare_cede (&ta); |
|
|
1063 | break; |
|
|
1064 | |
|
|
1065 | case 3: |
|
|
1066 | ta.prev = (struct coro *)INT2PTR (coro_stack *, SvIV (ST (0))); |
1057 | ta.prev = (struct coro *)INT2PTR (coro_stack *, SvIV (ST (0))); |
1067 | ta.next = 0; |
1058 | ta.next = 0; |
1068 | ta.flags = TRANSFER_SET_STACKLEVEL; |
1059 | ta.flags = TRANSFER_SET_STACKLEVEL; |
1069 | break; |
1060 | break; |
|
|
1061 | |
|
|
1062 | case 1: |
|
|
1063 | if (items != 3) |
|
|
1064 | croak ("Coro::State::transfer(prev,next,flags) expects three arguments, not %d", items); |
|
|
1065 | |
|
|
1066 | prepare_transfer (&ta, ST (0), ST (1), SvIV (ST (2))); |
|
|
1067 | break; |
|
|
1068 | |
|
|
1069 | case 2: |
|
|
1070 | prepare_schedule (&ta); |
|
|
1071 | break; |
|
|
1072 | |
|
|
1073 | case 3: |
|
|
1074 | prepare_cede (&ta); |
|
|
1075 | break; |
|
|
1076 | |
|
|
1077 | case 4: |
|
|
1078 | { |
|
|
1079 | SV *yieldstack; |
|
|
1080 | SV *sv; |
|
|
1081 | AV *defav = GvAV (PL_defgv); |
|
|
1082 | |
|
|
1083 | yieldstack = *hv_fetch ( |
|
|
1084 | (HV *)SvRV (GvSV (coro_current)), |
|
|
1085 | "yieldstack", sizeof ("yieldstack") - 1, |
|
|
1086 | 0 |
|
|
1087 | ); |
|
|
1088 | |
|
|
1089 | /* set up @_ -- ugly */ |
|
|
1090 | av_clear (defav); |
|
|
1091 | av_fill (defav, items - 1); |
|
|
1092 | while (items--) |
|
|
1093 | av_store (defav, items, SvREFCNT_inc (ST(items))); |
|
|
1094 | |
|
|
1095 | sv = av_pop ((AV *)SvRV (yieldstack)); |
|
|
1096 | ta.prev = SvSTATE (*av_fetch ((AV *)SvRV (sv), 0, 0)); |
|
|
1097 | ta.next = SvSTATE (*av_fetch ((AV *)SvRV (sv), 1, 0)); |
|
|
1098 | ta.flags = 0; |
|
|
1099 | SvREFCNT_dec (sv); |
|
|
1100 | } |
|
|
1101 | break; |
|
|
1102 | |
1070 | } |
1103 | } |
1071 | |
1104 | |
1072 | TRANSFER (ta); |
1105 | TRANSFER (ta); |
1073 | } |
1106 | } |
1074 | |
1107 | |
… | |
… | |
1094 | _exit (code) |
1127 | _exit (code) |
1095 | int code |
1128 | int code |
1096 | PROTOTYPE: $ |
1129 | PROTOTYPE: $ |
1097 | CODE: |
1130 | CODE: |
1098 | _exit (code); |
1131 | _exit (code); |
1099 | |
|
|
1100 | MODULE = Coro::State PACKAGE = Coro::Cont |
|
|
1101 | |
|
|
1102 | void |
|
|
1103 | yield (...) |
|
|
1104 | PROTOTYPE: @ |
|
|
1105 | CODE: |
|
|
1106 | { |
|
|
1107 | SV *yieldstack; |
|
|
1108 | SV *sv; |
|
|
1109 | AV *defav = GvAV (PL_defgv); |
|
|
1110 | struct coro *prev, *next; |
|
|
1111 | |
|
|
1112 | yieldstack = *hv_fetch ( |
|
|
1113 | (HV *)SvRV (GvSV (coro_current)), |
|
|
1114 | "yieldstack", sizeof ("yieldstack") - 1, |
|
|
1115 | 0 |
|
|
1116 | ); |
|
|
1117 | |
|
|
1118 | /* set up @_ -- ugly */ |
|
|
1119 | av_clear (defav); |
|
|
1120 | av_fill (defav, items - 1); |
|
|
1121 | while (items--) |
|
|
1122 | av_store (defav, items, SvREFCNT_inc (ST(items))); |
|
|
1123 | |
|
|
1124 | sv = av_pop ((AV *)SvRV (yieldstack)); |
|
|
1125 | prev = SvSTATE (*av_fetch ((AV *)SvRV (sv), 0, 0)); |
|
|
1126 | next = SvSTATE (*av_fetch ((AV *)SvRV (sv), 1, 0)); |
|
|
1127 | SvREFCNT_dec (sv); |
|
|
1128 | |
|
|
1129 | coro_state_transfer (aTHX_ prev, next, 0); |
|
|
1130 | } |
|
|
1131 | |
1132 | |
1132 | MODULE = Coro::State PACKAGE = Coro |
1133 | MODULE = Coro::State PACKAGE = Coro |
1133 | |
1134 | |
1134 | BOOT: |
1135 | BOOT: |
1135 | { |
1136 | { |