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.46 by pcg, Wed Nov 5 20:02:46 2003 UTC vs.
Revision 1.53 by pcg, Sat Feb 14 12:39:41 2004 UTC

38# else 38# else
39# undef HAVE_MMAP 39# undef HAVE_MMAP
40# endif 40# endif
41# endif 41# endif
42#endif 42#endif
43
44#define MAY_FLUSH /* increases codesize and is rarely used */
45 43
46#define SUB_INIT "Coro::State::initialize" 44#define SUB_INIT "Coro::State::initialize"
47#define UCORO_STATE "_coro_state" 45#define UCORO_STATE "_coro_state"
48 46
49/* The next macro should declare a variable stacklevel that contains and approximation 47/* The next macro should declare a variable stacklevel that contains and approximation
184 sv = (SV *) newAV (); 182 sv = (SV *) newAV ();
185 else if (*name == '%') 183 else if (*name == '%')
186 sv = (SV *) newHV (); 184 sv = (SV *) newHV ();
187 else 185 else
188 sv = NEWSV (0, 0); 186 sv = NEWSV (0, 0);
187#ifdef SvPADBUSY
189 if (!SvPADBUSY (sv)) 188 if (!SvPADBUSY (sv))
189#endif
190 SvPADMY_on (sv); 190 SvPADMY_on (sv);
191 npad[ix] = sv; 191 npad[ix] = sv;
192 } 192 }
193 } 193 }
194 else if (IS_PADGV (ppad[ix]) || IS_PADCONST (ppad[ix])) 194 else if (IS_PADGV (ppad[ix]) || IS_PADCONST (ppad[ix]))
224#endif 224#endif
225 225
226 return newpadlist; 226 return newpadlist;
227} 227}
228 228
229#ifdef MAY_FLUSH
230STATIC void 229STATIC void
231free_padlist (AV *padlist) 230free_padlist (AV *padlist)
232{ 231{
233 /* may be during global destruction */ 232 /* may be during global destruction */
234 if (SvREFCNT(padlist)) 233 if (SvREFCNT (padlist))
235 { 234 {
236 I32 i = AvFILLp(padlist); 235 I32 i = AvFILLp (padlist);
237 while (i >= 0) 236 while (i >= 0)
238 { 237 {
239 SV **svp = av_fetch(padlist, i--, FALSE); 238 SV **svp = av_fetch (padlist, i--, FALSE);
240 SV *sv = svp ? *svp : Nullsv;
241 if (sv) 239 if (svp)
240 {
241 SV *sv;
242 while (&PL_sv_undef != (sv = av_pop ((AV *)*svp)))
242 SvREFCNT_dec(sv); 243 SvREFCNT_dec (sv);
244
245 SvREFCNT_dec (*svp);
246 }
243 } 247 }
244 248
245 SvREFCNT_dec((SV*)padlist); 249 SvREFCNT_dec ((SV*)padlist);
246 } 250 }
247} 251}
248#endif 252
253STATIC int
254coro_cv_free (SV *sv, MAGIC *mg)
255{
256 AV *padlist;
257 AV *av = (AV *)mg->mg_obj;
258
259 /* casting is fun. */
260 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
261 free_padlist (padlist);
262}
263
264#define PERL_MAGIC_coro PERL_MAGIC_ext
265
266static MGVTBL vtbl_coro = {0, 0, 0, 0, coro_cv_free};
249 267
250/* the next two functions merely cache the padlists */ 268/* the next two functions merely cache the padlists */
251STATIC void 269STATIC void
252get_padlist (CV *cv) 270get_padlist (CV *cv)
253{ 271{
254 SV **he = hv_fetch (padlist_cache, (void *)&cv, sizeof (CV *), 0); 272 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
255 273
256 if (he && AvFILLp ((AV *)*he) >= 0) 274 if (mg && AvFILLp ((AV *)mg->mg_obj) >= 0)
257 CvPADLIST (cv) = (AV *)av_pop ((AV *)*he); 275 CvPADLIST (cv) = (AV *)av_pop ((AV *)mg->mg_obj);
258 else 276 else
259 CvPADLIST (cv) = clone_padlist (CvPADLIST (cv)); 277 CvPADLIST (cv) = clone_padlist (CvPADLIST (cv));
260} 278}
261 279
262STATIC void 280STATIC void
263put_padlist (CV *cv) 281put_padlist (CV *cv)
264{ 282{
265 SV **he = hv_fetch (padlist_cache, (void *)&cv, sizeof (CV *), 1); 283 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
266 284
267 if (SvTYPE (*he) != SVt_PVAV) 285 if (!mg)
268 { 286 {
269 SvREFCNT_dec (*he); 287 sv_magic ((SV *)cv, 0, PERL_MAGIC_coro, 0, 0);
288 mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
289 mg->mg_virtual = &vtbl_coro;
270 *he = (SV *)newAV (); 290 mg->mg_obj = (SV *)newAV ();
271 } 291 }
272 292
273 av_push ((AV *)*he, (SV *)CvPADLIST (cv)); 293 av_push ((AV *)mg->mg_obj, (SV *)CvPADLIST (cv));
274} 294}
275
276#ifdef MAY_FLUSH
277STATIC void
278flush_padlist_cache ()
279{
280 HV *hv = padlist_cache;
281 padlist_cache = newHV ();
282
283 if (hv_iterinit (hv))
284 {
285 HE *he;
286 AV *padlist;
287
288 while (!!(he = hv_iternext (hv)))
289 {
290 AV *av = (AV *)HeVAL(he);
291
292 /* casting is fun. */
293 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
294 free_padlist (padlist);
295 }
296 }
297
298 SvREFCNT_dec (hv);
299}
300#endif
301 295
302#define SB do { 296#define SB do {
303#define SE } while (0) 297#define SE } while (0)
304 298
305#define LOAD(state) load_state(aTHX_ (state)); 299#define LOAD(state) load_state(aTHX_ (state));
306#define SAVE(state,flags) save_state(aTHX_ (state),(flags)); 300#define SAVE(state,flags) save_state(aTHX_ (state),(flags));
307 301
308#define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); SE 302#define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); (val) = 0; SE
309 303
310static void 304static void
311load_state(pTHX_ Coro__State c) 305load_state(pTHX_ Coro__State c)
312{ 306{
313 PL_dowarn = c->dowarn; 307 PL_dowarn = c->dowarn;
475} 469}
476 470
477/* 471/*
478 * allocate various perl stacks. This is an exact copy 472 * allocate various perl stacks. This is an exact copy
479 * of perl.c:init_stacks, except that it uses less memory 473 * of perl.c:init_stacks, except that it uses less memory
480 * on the assumption that coroutines do not usually need 474 * on the (sometimes correct) assumption that coroutines do
481 * a lot of stackspace. 475 * not usually need a lot of stackspace.
482 */ 476 */
483STATIC void 477STATIC void
484coro_init_stacks (pTHX) 478coro_init_stacks (pTHX)
485{ 479{
486 PL_curstackinfo = new_stackinfo(96, 1024/sizeof(PERL_CONTEXT) - 1); 480 PL_curstackinfo = new_stackinfo(96, 1024/sizeof(PERL_CONTEXT) - 1);
518 PL_retstack_max = 8; 512 PL_retstack_max = 8;
519} 513}
520 514
521/* 515/*
522 * destroy the stacks, the callchain etc... 516 * destroy the stacks, the callchain etc...
523 * still there is a memleak of 128 bytes...
524 */ 517 */
525STATIC void 518STATIC void
526destroy_stacks(pTHX) 519destroy_stacks(pTHX)
527{ 520{
528 if (!IN_DESTRUCT) 521 if (!IN_DESTRUCT)
529 { 522 {
530 /* is this ugly, I ask? */ 523 /* is this ugly, I ask? */
531 while (PL_scopestack_ix) 524 LEAVE_SCOPE (0);
532 LEAVE;
533 525
534 /* sure it is, but more important: is it correct?? :/ */ 526 /* sure it is, but more important: is it correct?? :/ */
535 while (PL_tmps_ix > PL_tmps_floor) /* should only ever be one iteration */
536 FREETMPS; 527 FREETMPS;
537 } 528 }
538 529
539 while (PL_curstackinfo->si_next) 530 while (PL_curstackinfo->si_next)
540 PL_curstackinfo = PL_curstackinfo->si_next; 531 PL_curstackinfo = PL_curstackinfo->si_next;
541 532
578 stack->usecnt = 1; 569 stack->usecnt = 1;
579 stack->gencnt = ctx->gencnt = 0; 570 stack->gencnt = ctx->gencnt = 0;
580 if (alloc) 571 if (alloc)
581 { 572 {
582#if HAVE_MMAP 573#if HAVE_MMAP
583 stack->ssize = 128 * 1024 * sizeof (long); /* mmap should do allocate-on-write for us */ 574 stack->ssize = 16384 * sizeof (long); /* mmap should do allocate-on-write for us */
584 stack->sptr = mmap (0, stack->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 575 stack->sptr = mmap (0, stack->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
585 if (stack->sptr == (void *)-1) 576 if (stack->sptr == (void *)-1)
586#endif 577#endif
587 { 578 {
588 /*FIXME*//*D*//* reasonable stack size! */ 579 /*FIXME*//*D*//* reasonable stack size! */
589 stack->ssize = -4096 * sizeof (long); 580 stack->ssize = - (8192 * sizeof (long));
590 New (0, stack->sptr, 4096, long); 581 New (0, stack->sptr, 8192, long);
591 } 582 }
592 } 583 }
593 else 584 else
594 stack->sptr = 0; 585 stack->sptr = 0;
595 586
609 { 600 {
610#ifdef HAVE_MMAP 601#ifdef HAVE_MMAP
611 if (stack->ssize > 0 && stack->sptr) 602 if (stack->ssize > 0 && stack->sptr)
612 munmap (stack->sptr, stack->ssize); 603 munmap (stack->sptr, stack->ssize);
613 else 604 else
614#else 605#endif
615 Safefree (stack->sptr); 606 Safefree (stack->sptr);
616#endif 607
617 Safefree (stack); 608 Safefree (stack);
618 } 609 }
619 else if (ctx->gencnt == stack->gencnt) 610 else if (ctx->gencnt == stack->gencnt)
620 --stack->usecnt; 611 --stack->usecnt;
621 } 612 }
627 /* 618 /*
628 * emulate part of the perl startup here. 619 * emulate part of the perl startup here.
629 */ 620 */
630 dSP; 621 dSP;
631 Coro__State ctx = (Coro__State)arg; 622 Coro__State ctx = (Coro__State)arg;
632 SV *sub_init = (SV*)get_cv(SUB_INIT, FALSE); 623 SV *sub_init = (SV *)get_cv (SUB_INIT, FALSE);
633 624
634 coro_init_stacks (aTHX); 625 coro_init_stacks (aTHX);
635 /*PL_curcop = 0;*/ 626 /*PL_curcop = 0;*/
636 /*PL_in_eval = PL_in_eval;*/ /* inherit */ 627 /*PL_in_eval = PL_in_eval;*/ /* inherit */
637 SvREFCNT_dec (GvAV (PL_defgv)); 628 SvREFCNT_dec (GvAV (PL_defgv));
638 GvAV (PL_defgv) = ctx->args; 629 GvAV (PL_defgv) = ctx->args; ctx->args = 0;
639 630
640 SPAGAIN; 631 SPAGAIN;
641 632
642 if (ctx->stack) 633 if (ctx->stack)
643 { 634 {
765 next->stack = prev->stack; 756 next->stack = prev->stack;
766 next->gencnt = prev->gencnt; 757 next->gencnt = prev->gencnt;
767 } 758 }
768 else 759 else
769 { 760 {
761 assert (!next->stack);
770 allocate_stack (next, 1); 762 allocate_stack (next, 1);
771 coro_create (&(next->stack->cctx), 763 coro_create (&(next->stack->cctx),
772 setup_coro, (void *)next, 764 setup_coro, (void *)next,
773 next->stack->sptr, labs (next->stack->ssize)); 765 next->stack->sptr, labs (next->stack->ssize));
774 coro_transfer (&(prev->stack->cctx), &(next->stack->cctx)); 766 coro_transfer (&(prev->stack->cctx), &(next->stack->cctx));
952 Coro__State coro; 944 Coro__State coro;
953 945
954 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV) 946 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV)
955 croak ("Coro::State::_newprocess expects an arrayref"); 947 croak ("Coro::State::_newprocess expects an arrayref");
956 948
957 New (0, coro, 1, struct coro); 949 Newz (0, coro, 1, struct coro);
958 950
959 coro->args = (AV *)SvREFCNT_inc (SvRV (args)); 951 coro->args = (AV *)SvREFCNT_inc (SvRV (args));
960 coro->mainstack = 0; /* actual work is done inside transfer */ 952 coro->mainstack = 0; /* actual work is done inside transfer */
961 coro->stack = 0; 953 coro->stack = 0;
962 954
963 /* same as JMPENV_BOOTSTRAP */ 955 /* same as JMPENV_BOOTSTRAP */
964 /* we might be able to recycle start_env, but safe is safe */ 956 /* we might be able to recycle start_env, but safe is safe */
965 Zero(&coro->start_env, 1, JMPENV); 957 //Zero(&coro->start_env, 1, JMPENV);
966 coro->start_env.je_ret = -1; 958 coro->start_env.je_ret = -1;
967 coro->start_env.je_mustcatch = TRUE; 959 coro->start_env.je_mustcatch = TRUE;
968 960
969 RETVAL = coro; 961 RETVAL = coro;
970 OUTPUT: 962 OUTPUT:
1004 996
1005 coro->mainstack = 0; 997 coro->mainstack = 0;
1006 } 998 }
1007 999
1008 deallocate_stack (coro); 1000 deallocate_stack (coro);
1009 1001 SvREFCNT_dec (coro->args);
1010 Safefree (coro); 1002 Safefree (coro);
1011
1012void
1013flush()
1014 CODE:
1015#ifdef MAY_FLUSH
1016 flush_padlist_cache ();
1017#endif
1018 1003
1019void 1004void
1020_exit(code) 1005_exit(code)
1021 int code 1006 int code
1022 PROTOTYPE: $ 1007 PROTOTYPE: $
1023 CODE: 1008 CODE:
1024#if defined(__GLIBC__) || _POSIX_C_SOURCE
1025 _exit (code); 1009 _exit (code);
1026#else
1027 signal (SIGTERM, SIG_DFL);
1028 raise (SIGTERM);
1029 exit (code);
1030#endif
1031 1010
1032MODULE = Coro::State PACKAGE = Coro::Cont 1011MODULE = Coro::State PACKAGE = Coro::Cont
1033 1012
1034# this is slightly dirty (should expose a c-level api) 1013# this is slightly dirty (should expose a c-level api)
1035 1014
1094 sv_setiv(sv, (IV)&coroapi); 1073 sv_setiv(sv, (IV)&coroapi);
1095 SvREADONLY_on(sv); 1074 SvREADONLY_on(sv);
1096 } 1075 }
1097} 1076}
1098 1077
1078#if !PERL_MICRO
1079
1099void 1080void
1100ready(self) 1081ready(self)
1101 SV * self 1082 SV * self
1102 PROTOTYPE: $ 1083 PROTOTYPE: $
1103 CODE: 1084 CODE:
1104 api_ready (self); 1085 api_ready (self);
1086
1087#endif
1105 1088
1106int 1089int
1107nready(...) 1090nready(...)
1108 PROTOTYPE: 1091 PROTOTYPE:
1109 CODE: 1092 CODE:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines