… | |
… | |
140 | |
140 | |
141 | static GV *irsgv; /* $/ */ |
141 | static GV *irsgv; /* $/ */ |
142 | static GV *stdoutgv; /* *STDOUT */ |
142 | static GV *stdoutgv; /* *STDOUT */ |
143 | static SV *rv_diehook; |
143 | static SV *rv_diehook; |
144 | static SV *rv_warnhook; |
144 | static SV *rv_warnhook; |
145 | static HV *hv_sig; /* %SIG */ |
|
|
146 | |
145 | |
147 | /* async_pool helper stuff */ |
146 | /* async_pool helper stuff */ |
148 | static SV *sv_pool_rss; |
147 | static SV *sv_pool_rss; |
149 | static SV *sv_pool_size; |
148 | static SV *sv_pool_size; |
150 | static SV *sv_async_pool_idle; /* description string */ |
149 | static SV *sv_async_pool_idle; /* description string */ |
… | |
… | |
709 | tmp.sv_u = a->sv_u; a->sv_u = b->sv_u; b->sv_u = tmp.sv_u; |
708 | tmp.sv_u = a->sv_u; a->sv_u = b->sv_u; b->sv_u = tmp.sv_u; |
710 | |
709 | |
711 | /* if SvANY points to the head, we need to adjust the pointers, |
710 | /* if SvANY points to the head, we need to adjust the pointers, |
712 | * as the pointer for a still points to b, and maybe vice versa. |
711 | * as the pointer for a still points to b, and maybe vice versa. |
713 | */ |
712 | */ |
714 | #define svany_in_head(type) \ |
713 | U32 svany_in_head_set = (1 << SVt_NULL) | (1 << SVt_BIND) | (1 << SVt_IV) | (1 << SVt_RV); |
715 | (((1 << SVt_NULL) | (1 << SVt_BIND) | (1 << SVt_IV) | (1 << SVt_RV)) & (1 << (type))) |
714 | #if NVSIZE <= IVSIZE && PERL_VERSION_ATLEAST(5,22,0) |
|
|
715 | svany_in_head_set |= 1 << SVt_NV; |
|
|
716 | #endif |
|
|
717 | |
|
|
718 | #define svany_in_head(type) (svany_in_head_set & (1 << (type))) |
716 | |
719 | |
717 | if (svany_in_head (SvTYPE (a))) |
720 | if (svany_in_head (SvTYPE (a))) |
718 | SvANY (a) = (void *)((PTRV)SvANY (a) - (PTRV)b + (PTRV)a); |
721 | SvANY (a) = (void *)((PTRV)SvANY (a) - (PTRV)b + (PTRV)a); |
719 | |
722 | |
720 | if (svany_in_head (SvTYPE (b))) |
723 | if (svany_in_head (SvTYPE (b))) |
… | |
… | |
723 | #endif |
726 | #endif |
724 | } |
727 | } |
725 | |
728 | |
726 | /* swap sv heads, at least logically */ |
729 | /* swap sv heads, at least logically */ |
727 | static void |
730 | static void |
728 | swap_svs (pTHX_ Coro__State c) |
731 | swap_svs_enter (pTHX_ Coro__State c) |
729 | { |
732 | { |
730 | int i; |
733 | int i; |
731 | |
734 | |
732 | for (i = 0; i <= AvFILLp (c->swap_sv); i += 2) |
735 | for (i = 0; i <= AvFILLp (c->swap_sv); i += 2) |
733 | swap_sv (AvARRAY (c->swap_sv)[i], AvARRAY (c->swap_sv)[i + 1]); |
736 | swap_sv (AvARRAY (c->swap_sv)[i], AvARRAY (c->swap_sv)[i + 1]); |
734 | } |
737 | } |
735 | |
738 | |
|
|
739 | static void |
|
|
740 | swap_svs_leave (pTHX_ Coro__State c) |
|
|
741 | { |
|
|
742 | int i; |
|
|
743 | |
|
|
744 | for (i = AvFILLp (c->swap_sv) - 1; i >= 0; i -= 2) |
|
|
745 | swap_sv (AvARRAY (c->swap_sv)[i], AvARRAY (c->swap_sv)[i + 1]); |
|
|
746 | } |
|
|
747 | |
736 | #define SWAP_SVS(coro) \ |
748 | #define SWAP_SVS_ENTER(coro) \ |
737 | if (ecb_expect_false ((coro)->swap_sv)) \ |
749 | if (ecb_expect_false ((coro)->swap_sv)) \ |
738 | swap_svs (aTHX_ (coro)) |
750 | swap_svs_enter (aTHX_ (coro)) |
|
|
751 | |
|
|
752 | #define SWAP_SVS_LEAVE(coro) \ |
|
|
753 | if (ecb_expect_false ((coro)->swap_sv)) \ |
|
|
754 | swap_svs_leave (aTHX_ (coro)) |
739 | |
755 | |
740 | static void |
756 | static void |
741 | on_enterleave_call (pTHX_ SV *cb); |
757 | on_enterleave_call (pTHX_ SV *cb); |
742 | |
758 | |
743 | static void |
759 | static void |
… | |
… | |
796 | |
812 | |
797 | for (i = 0; i <= AvFILLp (c->on_enter_xs); i += 2) |
813 | for (i = 0; i <= AvFILLp (c->on_enter_xs); i += 2) |
798 | ((coro_enterleave_hook)AvARRAY (c->on_enter_xs)[i]) (aTHX_ AvARRAY (c->on_enter_xs)[i + 1]); |
814 | ((coro_enterleave_hook)AvARRAY (c->on_enter_xs)[i]) (aTHX_ AvARRAY (c->on_enter_xs)[i + 1]); |
799 | } |
815 | } |
800 | |
816 | |
801 | SWAP_SVS (c); |
817 | SWAP_SVS_ENTER (c); |
802 | } |
818 | } |
803 | |
819 | |
804 | static void |
820 | static void |
805 | save_perl (pTHX_ Coro__State c) |
821 | save_perl (pTHX_ Coro__State c) |
806 | { |
822 | { |
807 | SWAP_SVS (c); |
823 | SWAP_SVS_LEAVE (c); |
808 | |
824 | |
809 | if (ecb_expect_false (c->on_leave_xs)) |
825 | if (ecb_expect_false (c->on_leave_xs)) |
810 | { |
826 | { |
811 | int i; |
827 | int i; |
812 | |
828 | |
… | |
… | |
1214 | PL_op = (OP *)&init_perl_op; |
1230 | PL_op = (OP *)&init_perl_op; |
1215 | |
1231 | |
1216 | /* copy throw, in case it was set before init_perl */ |
1232 | /* copy throw, in case it was set before init_perl */ |
1217 | CORO_THROW = coro->except; |
1233 | CORO_THROW = coro->except; |
1218 | |
1234 | |
1219 | SWAP_SVS (coro); |
1235 | SWAP_SVS_ENTER (coro); |
1220 | |
1236 | |
1221 | if (ecb_expect_false (enable_times)) |
1237 | if (ecb_expect_false (enable_times)) |
1222 | { |
1238 | { |
1223 | coro_times_update (); |
1239 | coro_times_update (); |
1224 | coro_times_sub (coro); |
1240 | coro_times_sub (coro); |
… | |
… | |
1262 | /* this will cause transfer_check to croak on block*/ |
1278 | /* this will cause transfer_check to croak on block*/ |
1263 | SvRV_set (coro_current, (SV *)coro->hv); |
1279 | SvRV_set (coro_current, (SV *)coro->hv); |
1264 | |
1280 | |
1265 | load_perl (aTHX_ coro); |
1281 | load_perl (aTHX_ coro); |
1266 | |
1282 | |
|
|
1283 | /* restore swapped sv's */ |
|
|
1284 | SWAP_SVS_LEAVE (coro); |
|
|
1285 | |
1267 | coro_unwind_stacks (aTHX); |
1286 | coro_unwind_stacks (aTHX); |
1268 | |
|
|
1269 | /* restore swapped sv's */ |
|
|
1270 | SWAP_SVS (coro); |
|
|
1271 | |
1287 | |
1272 | coro_destruct_stacks (aTHX); |
1288 | coro_destruct_stacks (aTHX); |
1273 | |
1289 | |
1274 | /* now save some sv's to be free'd later */ |
1290 | /* now save some sv's to be free'd later */ |
1275 | svf [0] = GvSV (PL_defgv); |
1291 | svf [0] = GvSV (PL_defgv); |
… | |
… | |
2410 | else |
2426 | else |
2411 | { |
2427 | { |
2412 | av_clear (GvAV (PL_defgv)); |
2428 | av_clear (GvAV (PL_defgv)); |
2413 | hv_store (hv, "desc", sizeof ("desc") - 1, SvREFCNT_inc_NN (sv_async_pool_idle), 0); |
2429 | hv_store (hv, "desc", sizeof ("desc") - 1, SvREFCNT_inc_NN (sv_async_pool_idle), 0); |
2414 | |
2430 | |
|
|
2431 | if (ecb_expect_false (coro->swap_sv)) |
|
|
2432 | { |
|
|
2433 | swap_svs_leave (coro); |
|
|
2434 | SvREFCNT_dec_NN (coro->swap_sv); |
|
|
2435 | coro->swap_sv = 0; |
|
|
2436 | } |
|
|
2437 | |
2415 | coro->prio = 0; |
2438 | coro->prio = 0; |
2416 | |
2439 | |
2417 | if (coro->cctx && (coro->cctx->flags & CC_TRACE)) |
2440 | if (ecb_expect_false (coro->cctx) && ecb_expect_false (coro->cctx->flags & CC_TRACE)) |
2418 | api_trace (aTHX_ coro_current, 0); |
2441 | api_trace (aTHX_ coro_current, 0); |
2419 | |
2442 | |
2420 | frame->prepare = prepare_schedule; |
2443 | frame->prepare = prepare_schedule; |
2421 | av_push (av_async_pool, SvREFCNT_inc (hv)); |
2444 | av_push (av_async_pool, SvREFCNT_inc (hv)); |
2422 | } |
2445 | } |
… | |
… | |
2878 | |
2901 | |
2879 | for (i = AvFILLp (av) - 1; i >= 0; i -= 2) |
2902 | for (i = AvFILLp (av) - 1; i >= 0; i -= 2) |
2880 | if (AvARRAY (av)[i] == (SV *)hook) |
2903 | if (AvARRAY (av)[i] == (SV *)hook) |
2881 | { |
2904 | { |
2882 | if (execute) |
2905 | if (execute) |
2883 | hook ((void *)AvARRAY (av)[i + 1]); |
2906 | hook (aTHX_ (void *)AvARRAY (av)[i + 1]); |
2884 | |
2907 | |
2885 | memmove (AvARRAY (av) + i, AvARRAY (av) + i + 2, AvFILLp (av) - i - 1); |
2908 | memmove (AvARRAY (av) + i, AvARRAY (av) + i + 2, AvFILLp (av) - i - 1); |
2886 | av_pop (av); |
2909 | av_pop (av); |
2887 | av_pop (av); |
2910 | av_pop (av); |
2888 | break; |
2911 | break; |
… | |
… | |
2900 | { |
2923 | { |
2901 | struct coro *coro = SvSTATE (coro_sv); |
2924 | struct coro *coro = SvSTATE (coro_sv); |
2902 | |
2925 | |
2903 | if (SvSTATE_current == coro) |
2926 | if (SvSTATE_current == coro) |
2904 | if (enter) |
2927 | if (enter) |
2905 | enter (aTHX enter_arg); |
2928 | enter (aTHX_ enter_arg); |
2906 | |
2929 | |
2907 | enterleave_hook_xs (aTHX_ coro, &coro->on_enter_xs, enter, enter_arg); |
2930 | enterleave_hook_xs (aTHX_ coro, &coro->on_enter_xs, enter, enter_arg); |
2908 | enterleave_hook_xs (aTHX_ coro, &coro->on_leave_xs, leave, leave_arg); |
2931 | enterleave_hook_xs (aTHX_ coro, &coro->on_leave_xs, leave, leave_arg); |
2909 | } |
2932 | } |
2910 | |
2933 | |
… | |
… | |
3600 | |
3623 | |
3601 | orig_sigelem_get = PL_vtbl_sigelem.svt_get; PL_vtbl_sigelem.svt_get = coro_sigelem_get; |
3624 | orig_sigelem_get = PL_vtbl_sigelem.svt_get; PL_vtbl_sigelem.svt_get = coro_sigelem_get; |
3602 | orig_sigelem_set = PL_vtbl_sigelem.svt_set; PL_vtbl_sigelem.svt_set = coro_sigelem_set; |
3625 | orig_sigelem_set = PL_vtbl_sigelem.svt_set; PL_vtbl_sigelem.svt_set = coro_sigelem_set; |
3603 | orig_sigelem_clr = PL_vtbl_sigelem.svt_clear; PL_vtbl_sigelem.svt_clear = coro_sigelem_clr; |
3626 | orig_sigelem_clr = PL_vtbl_sigelem.svt_clear; PL_vtbl_sigelem.svt_clear = coro_sigelem_clr; |
3604 | |
3627 | |
3605 | hv_sig = coro_get_hv (aTHX_ "SIG", TRUE); |
|
|
3606 | rv_diehook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::diehook" , 0, SVt_PVCV)); |
3628 | rv_diehook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::diehook" , 0, SVt_PVCV)); |
3607 | rv_warnhook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::warnhook", 0, SVt_PVCV)); |
3629 | rv_warnhook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::warnhook", 0, SVt_PVCV)); |
3608 | |
3630 | |
3609 | coro_state_stash = gv_stashpv ("Coro::State", TRUE); |
3631 | coro_state_stash = gv_stashpv ("Coro::State", TRUE); |
3610 | |
3632 | |
… | |
… | |
3916 | if (ecb_expect_false (current == self)) |
3938 | if (ecb_expect_false (current == self)) |
3917 | coro_times_sub (SvSTATE (coro_current)); |
3939 | coro_times_sub (SvSTATE (coro_current)); |
3918 | } |
3940 | } |
3919 | |
3941 | |
3920 | void |
3942 | void |
3921 | swap_sv (Coro::State coro, SV *sv, SV *swapsv) |
3943 | swap_sv (Coro::State coro, SV *sva, SV *svb) |
3922 | CODE: |
3944 | CODE: |
3923 | { |
3945 | { |
3924 | struct coro *current = SvSTATE_current; |
3946 | struct coro *current = SvSTATE_current; |
|
|
3947 | AV *swap_sv; |
|
|
3948 | int i; |
|
|
3949 | |
|
|
3950 | sva = SvRV (sva); |
|
|
3951 | svb = SvRV (svb); |
3925 | |
3952 | |
3926 | if (current == coro) |
3953 | if (current == coro) |
3927 | SWAP_SVS (current); |
3954 | SWAP_SVS_LEAVE (current); |
3928 | |
3955 | |
3929 | if (!coro->swap_sv) |
3956 | if (!coro->swap_sv) |
3930 | coro->swap_sv = newAV (); |
3957 | coro->swap_sv = newAV (); |
3931 | |
3958 | |
|
|
3959 | swap_sv = coro->swap_sv; |
|
|
3960 | |
|
|
3961 | for (i = AvFILLp (swap_sv) - 1; i >= 0; i -= 2) |
|
|
3962 | { |
|
|
3963 | SV *a = AvARRAY (swap_sv)[i ]; |
|
|
3964 | SV *b = AvARRAY (swap_sv)[i + 1]; |
|
|
3965 | |
|
|
3966 | if (a == sva && b == svb) |
|
|
3967 | { |
|
|
3968 | SvREFCNT_dec_NN (a); |
|
|
3969 | SvREFCNT_dec_NN (b); |
|
|
3970 | |
|
|
3971 | for (; i <= AvFILLp (swap_sv) - 2; i++) |
|
|
3972 | AvARRAY (swap_sv)[i] = AvARRAY (swap_sv)[i + 2]; |
|
|
3973 | |
|
|
3974 | AvFILLp (swap_sv) -= 2; |
|
|
3975 | |
|
|
3976 | goto removed; |
|
|
3977 | } |
|
|
3978 | } |
|
|
3979 | |
3932 | av_push (coro->swap_sv, SvREFCNT_inc_NN (SvRV (sv ))); |
3980 | av_push (swap_sv, SvREFCNT_inc_NN (sva)); |
3933 | av_push (coro->swap_sv, SvREFCNT_inc_NN (SvRV (swapsv))); |
3981 | av_push (swap_sv, SvREFCNT_inc_NN (svb)); |
|
|
3982 | |
|
|
3983 | removed: |
3934 | |
3984 | |
3935 | if (current == coro) |
3985 | if (current == coro) |
3936 | SWAP_SVS (current); |
3986 | SWAP_SVS_ENTER (current); |
3937 | } |
3987 | } |
3938 | |
3988 | |
3939 | |
3989 | |
3940 | MODULE = Coro::State PACKAGE = Coro |
3990 | MODULE = Coro::State PACKAGE = Coro |
3941 | |
3991 | |
3942 | BOOT: |
3992 | BOOT: |
3943 | { |
3993 | { |
|
|
3994 | if (SVt_LAST > 32) |
|
|
3995 | croak ("Coro internal error: SVt_LAST > 32, swap_sv might need adjustment"); |
|
|
3996 | |
3944 | sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE); |
3997 | sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE); |
3945 | sv_pool_size = coro_get_sv (aTHX_ "Coro::POOL_SIZE" , TRUE); |
3998 | sv_pool_size = coro_get_sv (aTHX_ "Coro::POOL_SIZE" , TRUE); |
3946 | cv_coro_run = get_cv ( "Coro::_coro_run" , GV_ADD); |
3999 | cv_coro_run = get_cv ( "Coro::_coro_run" , GV_ADD); |
3947 | coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current); |
4000 | coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current); |
3948 | av_async_pool = coro_get_av (aTHX_ "Coro::async_pool", TRUE); |
4001 | av_async_pool = coro_get_av (aTHX_ "Coro::async_pool", TRUE); |
… | |
… | |
4252 | RETVAL = newSVsv (AvARRAY ((AV *)SvRV (self))[0]); |
4305 | RETVAL = newSVsv (AvARRAY ((AV *)SvRV (self))[0]); |
4253 | OUTPUT: |
4306 | OUTPUT: |
4254 | RETVAL |
4307 | RETVAL |
4255 | |
4308 | |
4256 | void |
4309 | void |
4257 | up (SV *self, int adjust = 1) |
4310 | up (SV *self) |
4258 | ALIAS: |
|
|
4259 | adjust = 1 |
|
|
4260 | CODE: |
4311 | CODE: |
|
|
4312 | coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), 1); |
|
|
4313 | |
|
|
4314 | void |
|
|
4315 | adjust (SV *self, int adjust) |
|
|
4316 | CODE: |
4261 | coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1); |
4317 | coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), adjust); |
4262 | |
4318 | |
4263 | void |
4319 | void |
4264 | down (...) |
4320 | down (...) |
4265 | CODE: |
4321 | CODE: |
4266 | CORO_EXECUTE_SLF_XS (slf_init_semaphore_down); |
4322 | CORO_EXECUTE_SLF_XS (slf_init_semaphore_down); |