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.210 by root, Wed Oct 10 03:24:40 2007 UTC vs.
Revision 1.212 by root, Wed Oct 10 04:21:33 2007 UTC

131#else 131#else
132# define LOCK (void)0 132# define LOCK (void)0
133# define UNLOCK (void)0 133# define UNLOCK (void)0
134#endif 134#endif
135 135
136#define strpair(const) const, sizeof (const) - 1
137
138/* helper storage struct for Coro::AIO */ 136/* helper storage struct for Coro::AIO */
139struct io_state 137struct io_state
140{ 138{
141 int errorno; 139 int errorno;
142 I32 laststype; 140 I32 laststype;
161/* async_pool helper stuff */ 159/* async_pool helper stuff */
162static SV *sv_pool_rss; 160static SV *sv_pool_rss;
163static SV *sv_pool_size; 161static SV *sv_pool_size;
164static AV *av_async_pool; 162static AV *av_async_pool;
165 163
166static struct coro_cctx *cctx_first[3]; /* index by GIMME_V type, void, scalar, array */ 164static struct coro_cctx *cctx_first;
167static int cctx_count, cctx_idle[3]; 165static int cctx_count, cctx_idle;
168 166
169enum { 167enum {
170 CC_MAPPED = 0x01, 168 CC_MAPPED = 0x01,
171 CC_NOREUSE = 0x02, /* throw this away after tracing */ 169 CC_NOREUSE = 0x02, /* throw this away after tracing */
172 CC_TRACE = 0x04, 170 CC_TRACE = 0x04,
217 215
218/* this is a structure representing a perl-level coroutine */ 216/* this is a structure representing a perl-level coroutine */
219struct coro { 217struct coro {
220 /* the c coroutine allocated to this perl coroutine, if any */ 218 /* the c coroutine allocated to this perl coroutine, if any */
221 coro_cctx *cctx; 219 coro_cctx *cctx;
222 int gimme;
223 220
224 /* process data */ 221 /* process data */
225 AV *mainstack; 222 AV *mainstack;
226 perl_slots *slot; /* basically the saved sp */ 223 perl_slots *slot; /* basically the saved sp */
227 224
454 451
455 #define VAR(name,type) PL_ ## name = slot->name; 452 #define VAR(name,type) PL_ ## name = slot->name;
456 # include "state.h" 453 # include "state.h"
457 #undef VAR 454 #undef VAR
458 455
459 /*hv_store (hv_sig, strpair ("__DIE__" ), SvREFCNT_inc (sv_diehook ), 0);*/ 456 /*hv_store (hv_sig, "__DIE__" , sizeof ("__DIE__" ) - 1, SvREFCNT_inc (sv_diehook ), 0);*/
460 /*hv_store (hv_sig, strpair ("__WARN__"), SvREFCNT_inc (sv_warnhook), 0);*/ 457 /*hv_store (hv_sig, "__WARN__", sizeof ("__WARN__") - 1, SvREFCNT_inc (sv_warnhook), 0);*/
461 458
462 { 459 {
463 dSP; 460 dSP;
464 461
465 CV *cv; 462 CV *cv;
688 PL_curpm = 0; 685 PL_curpm = 0;
689 PL_curpad = 0; 686 PL_curpad = 0;
690 PL_localizing = 0; 687 PL_localizing = 0;
691 PL_dirty = 0; 688 PL_dirty = 0;
692 PL_restartop = 0; 689 PL_restartop = 0;
693 PL_diehook = 0; hv_store (hv_sig, strpair ("__DIE__" ), SvREFCNT_inc (sv_diehook ), 0); 690 PL_diehook = 0; hv_store (hv_sig, "__DIE__" , sizeof ("__DIE__" ) - 1, SvREFCNT_inc (sv_diehook ), 0);
694 PL_warnhook = 0; hv_store (hv_sig, strpair ("__WARN__"), SvREFCNT_inc (sv_warnhook), 0); 691 PL_warnhook = 0; hv_store (hv_sig, "__WARN__", sizeof ("__WARN__") - 1, SvREFCNT_inc (sv_warnhook), 0);
695 692
696 GvSV (PL_defgv) = newSV (0); 693 GvSV (PL_defgv) = newSV (0);
697 GvAV (PL_defgv) = coro->args; coro->args = 0; 694 GvAV (PL_defgv) = coro->args; coro->args = 0;
698 GvSV (PL_errgv) = newSV (0); 695 GvSV (PL_errgv) = newSV (0);
699 GvSV (irsgv) = newSVpvn ("\n", 1); sv_magic (GvSV (irsgv), (SV *)irsgv, PERL_MAGIC_sv, "/", 0); 696 GvSV (irsgv) = newSVpvn ("\n", 1); sv_magic (GvSV (irsgv), (SV *)irsgv, PERL_MAGIC_sv, "/", 0);
712 XPUSHs (sv_2mortal (av_shift (GvAV (PL_defgv)))); 709 XPUSHs (sv_2mortal (av_shift (GvAV (PL_defgv))));
713 PUTBACK; 710 PUTBACK;
714 PL_op = (OP *)&myop; 711 PL_op = (OP *)&myop;
715 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX); 712 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
716 SPAGAIN; 713 SPAGAIN;
717
718 /*
719 * now its very tricky. the "tail" of the next transfer might end up
720 * either in a new cctx, or an existing one.
721 * in case of an existing one we have to take care of whatever
722 * entersub and transfer do to the perl stack.
723 */
724 ENTER;
725 EXTEND (SP, 4);
726 PUSHs ((SV *)0); /* items */
727 PUSHs ((SV *)0); /* ix, set_stacklevel */
728 PUSHs ((SV *)(sp - PL_stack_base + 1)); /* ax */
729 PUSHs ((SV *)0); /* again */
730 PUTBACK;
731 } 714 }
732 715
733 /* this newly created coroutine might be run on an existing cctx which most 716 /* this newly created coroutine might be run on an existing cctx which most
734 * likely was suspended in set_stacklevel, called from entersub. 717 * likely was suspended in set_stacklevel, called from entersub.
735 * set_stacklevl doesn't do anything on return, but entersub does LEAVE, 718 * set_stacklevl doesn't do anything on return, but entersub does LEAVE,
827 PUSHMARK (SP); 810 PUSHMARK (SP);
828 PUSHs (&PL_sv_no); 811 PUSHs (&PL_sv_no);
829 PUSHs (fullname); 812 PUSHs (fullname);
830 PUSHs (sv_2mortal (newRV_noinc ((SV *)av))); 813 PUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
831 PUTBACK; 814 PUTBACK;
832 cb = hv_fetch ((HV *)SvRV (coro_current), strpair ("_trace_sub_cb"), 0); 815 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0);
833 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 816 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
834 SPAGAIN; 817 SPAGAIN;
835 FREETMPS; 818 FREETMPS;
836 LEAVE; 819 LEAVE;
837 PL_runops = runops_trace; 820 PL_runops = runops_trace;
866 PUSHMARK (SP); 849 PUSHMARK (SP);
867 PUSHs (&PL_sv_yes); 850 PUSHs (&PL_sv_yes);
868 PUSHs (fullname); 851 PUSHs (fullname);
869 PUSHs (cx->blk_sub.hasargs ? sv_2mortal (newRV_inc ((SV *)cx->blk_sub.argarray)) : &PL_sv_undef); 852 PUSHs (cx->blk_sub.hasargs ? sv_2mortal (newRV_inc ((SV *)cx->blk_sub.argarray)) : &PL_sv_undef);
870 PUTBACK; 853 PUTBACK;
871 cb = hv_fetch ((HV *)SvRV (coro_current), strpair ("_trace_sub_cb"), 0); 854 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0);
872 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 855 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
873 SPAGAIN; 856 SPAGAIN;
874 FREETMPS; 857 FREETMPS;
875 LEAVE; 858 LEAVE;
876 PL_runops = runops_trace; 859 PL_runops = runops_trace;
890 PL_runops = RUNOPS_DEFAULT; 873 PL_runops = RUNOPS_DEFAULT;
891 PUSHMARK (SP); 874 PUSHMARK (SP);
892 PUSHs (sv_2mortal (newSVpv (OutCopFILE (oldcop), 0))); 875 PUSHs (sv_2mortal (newSVpv (OutCopFILE (oldcop), 0)));
893 PUSHs (sv_2mortal (newSViv (CopLINE (oldcop)))); 876 PUSHs (sv_2mortal (newSViv (CopLINE (oldcop))));
894 PUTBACK; 877 PUTBACK;
895 cb = hv_fetch ((HV *)SvRV (coro_current), strpair ("_trace_line_cb"), 0); 878 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_line_cb", sizeof ("_trace_line_cb") - 1, 0);
896 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 879 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
897 SPAGAIN; 880 SPAGAIN;
898 FREETMPS; 881 FREETMPS;
899 LEAVE; 882 LEAVE;
900 PL_runops = runops_trace; 883 PL_runops = runops_trace;
1039 1022
1040/* wether this cctx should be destructed */ 1023/* wether this cctx should be destructed */
1041#define CCTX_EXPIRED(cctx) ((cctx)->ssize < coro_stacksize || ((cctx)->flags & CC_NOREUSE)) 1024#define CCTX_EXPIRED(cctx) ((cctx)->ssize < coro_stacksize || ((cctx)->flags & CC_NOREUSE))
1042 1025
1043static coro_cctx * 1026static coro_cctx *
1044cctx_get (pTHX_ int gimme) 1027cctx_get (pTHX)
1045{ 1028{
1046 while (expect_true (cctx_first[gimme])) 1029 while (expect_true (cctx_first))
1047 { 1030 {
1048 coro_cctx *cctx = cctx_first[gimme]; 1031 coro_cctx *cctx = cctx_first;
1049 cctx_first[gimme] = cctx->next; 1032 cctx_first = cctx->next;
1050 --cctx_idle[gimme]; 1033 --cctx_idle;
1051 1034
1052 if (expect_true (!CCTX_EXPIRED (cctx))) 1035 if (expect_true (!CCTX_EXPIRED (cctx)))
1053 return cctx; 1036 return cctx;
1054 1037
1055 cctx_destroy (cctx); 1038 cctx_destroy (cctx);
1056 } 1039 }
1057 1040
1058 assert (!gimme);
1059 return cctx_new (); 1041 return cctx_new ();
1060} 1042}
1061 1043
1062static void 1044static void
1063cctx_put (coro_cctx *cctx, int gimme) 1045cctx_put (coro_cctx *cctx)
1064{ 1046{
1065 /* free another cctx if overlimit */ 1047 /* free another cctx if overlimit */
1066 if (expect_false (cctx_idle[gimme] >= MAX_IDLE_CCTX)) 1048 if (expect_false (cctx_idle >= MAX_IDLE_CCTX))
1067 { 1049 {
1068 coro_cctx *first = cctx_first[gimme]; 1050 coro_cctx *first = cctx_first;
1069 cctx_first[gimme] = first->next; 1051 cctx_first = first->next;
1070 --cctx_idle[gimme]; 1052 --cctx_idle;
1071 1053
1072 cctx_destroy (first); 1054 cctx_destroy (first);
1073 } 1055 }
1074 1056
1075 ++cctx_idle[gimme]; 1057 ++cctx_idle;
1076 cctx->next = cctx_first[gimme]; 1058 cctx->next = cctx_first;
1077 cctx_first[gimme] = cctx; 1059 cctx_first = cctx;
1078} 1060}
1079 1061
1080/** coroutine switching *****************************************************/ 1062/** coroutine switching *****************************************************/
1081 1063
1082static void 1064static void
1161 1143
1162 /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get */ 1144 /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get */
1163 /* without this the next cctx_get might destroy the prev__cctx while still in use */ 1145 /* without this the next cctx_get might destroy the prev__cctx while still in use */
1164 if (expect_false (CCTX_EXPIRED (prev__cctx))) 1146 if (expect_false (CCTX_EXPIRED (prev__cctx)))
1165 if (!next->cctx) 1147 if (!next->cctx)
1166 next->cctx = cctx_get (aTHX_ next->gimme); 1148 next->cctx = cctx_get (aTHX);
1167 1149
1168 cctx_put (prev__cctx, prev->gimme); 1150 cctx_put (prev__cctx);
1169 } 1151 }
1170 1152
1171 ++next->usecount; 1153 ++next->usecount;
1172 1154
1173 if (expect_true (!next->cctx)) 1155 if (expect_true (!next->cctx))
1174 next->cctx = cctx_get (aTHX_ next->gimme); 1156 next->cctx = cctx_get (aTHX);
1175 1157
1176 if (expect_false (prev__cctx != next->cctx)) 1158 if (expect_false (prev__cctx != next->cctx))
1177 { 1159 {
1178 prev__cctx->top_env = PL_top_env; 1160 prev__cctx->top_env = PL_top_env;
1179 PL_top_env = next->cctx->top_env; 1161 PL_top_env = next->cctx->top_env;
1528 1510
1529 hv_sig = coro_get_hv ("SIG", TRUE); 1511 hv_sig = coro_get_hv ("SIG", TRUE);
1530 sv_diehook = coro_get_sv ("Coro::State::DIEHOOK" , TRUE); 1512 sv_diehook = coro_get_sv ("Coro::State::DIEHOOK" , TRUE);
1531 sv_warnhook = coro_get_sv ("Coro::State::WARNHOOK", TRUE); 1513 sv_warnhook = coro_get_sv ("Coro::State::WARNHOOK", TRUE);
1532 1514
1533 if (!PL_diehook ) hv_store (hv_sig, strpair ("__DIE__" ), SvREFCNT_inc (sv_diehook ), 0); 1515 if (!PL_diehook ) hv_store (hv_sig, "__DIE__" , sizeof ("__DIE__" ) - 1, SvREFCNT_inc (sv_diehook ), 0);
1534 if (!PL_warnhook) hv_store (hv_sig, strpair ("__WARN__"), SvREFCNT_inc (sv_warnhook), 0); 1516 if (!PL_warnhook) hv_store (hv_sig, "__WARN__", sizeof ("__WARN__") - 1, SvREFCNT_inc (sv_warnhook), 0);
1535 1517
1536 coro_state_stash = gv_stashpv ("Coro::State", TRUE); 1518 coro_state_stash = gv_stashpv ("Coro::State", TRUE);
1537 1519
1538 newCONSTSUB (coro_state_stash, "CC_TRACE" , newSViv (CC_TRACE)); 1520 newCONSTSUB (coro_state_stash, "CC_TRACE" , newSViv (CC_TRACE));
1539 newCONSTSUB (coro_state_stash, "CC_TRACE_SUB" , newSViv (CC_TRACE_SUB)); 1521 newCONSTSUB (coro_state_stash, "CC_TRACE_SUB" , newSViv (CC_TRACE_SUB));
1661 RETVAL 1643 RETVAL
1662 1644
1663int 1645int
1664cctx_idle () 1646cctx_idle ()
1665 CODE: 1647 CODE:
1666 RETVAL = cctx_idle[0] + cctx_idle[1] + cctx_idle[2]; 1648 RETVAL = cctx_idle;
1667 OUTPUT: 1649 OUTPUT:
1668 RETVAL 1650 RETVAL
1669 1651
1670void 1652void
1671list () 1653list ()
1705 eval_sv (coderef, 0); 1687 eval_sv (coderef, 0);
1706 else 1688 else
1707 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 1689 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1708 1690
1709 POPSTACK; 1691 POPSTACK;
1692 SPAGAIN;
1710 FREETMPS; 1693 FREETMPS;
1711 LEAVE; 1694 LEAVE;
1712 PUTBACK; 1695 PUTBACK;
1713 } 1696 }
1714 1697
1868 CODE: 1851 CODE:
1869{ 1852{
1870 struct coro *coro = SvSTATE (coro_current); 1853 struct coro *coro = SvSTATE (coro_current);
1871 HV *hv = (HV *)SvRV (coro_current); 1854 HV *hv = (HV *)SvRV (coro_current);
1872 AV *defav = GvAV (PL_defgv); 1855 AV *defav = GvAV (PL_defgv);
1873 SV *invoke = hv_delete (hv, strpair ("_invoke"), 0); 1856 SV *invoke = hv_delete (hv, "_invoke", sizeof ("_invoke") - 1, 0);
1874 AV *invoke_av; 1857 AV *invoke_av;
1875 int i, len; 1858 int i, len;
1876 1859
1877 if (!invoke) 1860 if (!invoke)
1878 croak ("\3async_pool terminate\2\n"); 1861 croak ("\3async_pool terminate\2\n");
1879 1862
1880 SvREFCNT_dec (coro->saved_deffh); 1863 SvREFCNT_dec (coro->saved_deffh);
1881 coro->saved_deffh = SvREFCNT_inc ((SV *)PL_defoutgv); 1864 coro->saved_deffh = SvREFCNT_inc ((SV *)PL_defoutgv);
1882 1865
1883 hv_store (hv, "desc", sizeof ("desc") - 1, 1866 hv_store (hv, "desc", sizeof ("desc") - 1,
1884 newSVpvn (strpair ("[async_pool]")), 0); 1867 newSVpvn ("[async_pool]", sizeof ("[async_pool]") - 1), 0);
1885 1868
1886 invoke_av = (AV *)SvRV (invoke); 1869 invoke_av = (AV *)SvRV (invoke);
1887 len = av_len (invoke_av); 1870 len = av_len (invoke_av);
1888 1871
1889 sv_setsv (cb, AvARRAY (invoke_av)[0]); 1872 sv_setsv (cb, AvARRAY (invoke_av)[0]);
1912 if (coro_rss (aTHX_ coro) > SvIV (sv_pool_rss) 1895 if (coro_rss (aTHX_ coro) > SvIV (sv_pool_rss)
1913 || av_len (av_async_pool) + 1 >= SvIV (sv_pool_size)) 1896 || av_len (av_async_pool) + 1 >= SvIV (sv_pool_size))
1914 croak ("\3async_pool terminate\2\n"); 1897 croak ("\3async_pool terminate\2\n");
1915 1898
1916 av_clear (GvAV (PL_defgv)); 1899 av_clear (GvAV (PL_defgv));
1917 hv_store ((HV *)SvRV (coro_current), strpair ("desc"), 1900 hv_store ((HV *)SvRV (coro_current), "desc", sizeof ("desc") - 1,
1918 newSVpvn (strpair ("[async_pool idle]")), 0); 1901 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0);
1919 1902
1920 coro->prio = 0; 1903 coro->prio = 0;
1921 1904
1922 if (coro->cctx && (coro->cctx->flags & CC_TRACE)) 1905 if (coro->cctx && (coro->cctx->flags & CC_TRACE))
1923 api_trace (coro_current, 0); 1906 api_trace (coro_current, 0);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines