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.9 by root, Sat Jul 21 02:49:09 2001 UTC vs.
Revision 1.21 by root, Sat Aug 11 19:59:19 2001 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
2#include "perl.h" 2#include "perl.h"
3#include "XSUB.h" 3#include "XSUB.h"
4 4
5#if 1 5#include "libcoro/coro.c"
6# define CHK(x) (void *)0 6
7#include <signal.h>
8
9#ifdef HAVE_MMAP
10# include <unistd.h>
11# include <sys/mman.h>
12# ifndef MAP_ANON
13# ifdef MAP_ANONYMOUS
14# define MAP_ANON MAP_ANONYMOUS
15# else
16# undef HAVE_MMAP
17# endif
18# endif
19#endif
20
21#define MAY_FLUSH /* increases codesize */
22
23/* perl-related */
24#define TRANSFER_SAVE_DEFAV 0x00000001
25#define TRANSFER_SAVE_DEFSV 0x00000002
26#define TRANSFER_SAVE_ERRSV 0x00000004
27/* c-related */
28#define TRANSFER_SAVE_CCTXT 0x00000008
29#ifdef CORO_LAZY_STACK
30# define TRANSFER_LAZY_STACK 0x00000010
7#else 31#else
8# define CHK(x) if (!(x)) croak("FATAL, CHK: " #x) 32# define TRANSFER_LAZY_STACK 0x00000000
9#endif 33#endif
10 34
11#define MAY_FLUSH /* increases codesize */ 35#define TRANSFER_SAVE_ALL (TRANSFER_SAVE_DEFAV|TRANSFER_SAVE_DEFSV \
36 |TRANSFER_SAVE_ERRSV|TRANSFER_SAVE_CCTXT)
12 37
13#define SUB_INIT "Coro::State::_newcoro" 38#define SUB_INIT "Coro::State::initialize"
39#define UCORO_STATE "_coro_state"
14 40
15#define SAVE_DEFAV 0x00000001 41/* The next macro should delcare a variable stacklevel that contains and approximation
16#define SAVE_DEFSV 0x00000002 42 * to the current C stack pointer. It's property is that it changes with each call
17#define SAVE_ERRSV 0x00000004 43 * and should be unique. */
44#define dSTACKLEVEL void *stacklevel = &stacklevel
18 45
19#define SAVE_ALL -1 46#define labs(l) ((l) >= 0 ? (l) : -(l))
47
48/* this is actually not only the c stack but also c registers etc... */
49typedef struct {
50 int refcnt; /* pointer reference counter */
51 int usecnt; /* shared by how many coroutines */
52 int gencnt; /* generation counter */
53
54 coro_context cctx;
55
56 void *sptr;
57 long ssize; /* positive == mmap, otherwise malloc */
58} coro_stack;
20 59
21struct coro { 60struct coro {
61 /* the optional C context */
62 coro_stack *stack;
63 void *cursp;
64 int gencnt;
65
22 /* optionally saved, might be zero */ 66 /* optionally saved, might be zero */
23 AV *defav; 67 AV *defav;
24 SV *defsv; 68 SV *defsv;
25 SV *errsv; 69 SV *errsv;
26 70
27 /* saved global state not related to stacks */ 71 /* saved global state not related to stacks */
28 U8 dowarn; 72 U8 dowarn;
73 I32 in_eval;
29 74
30 /* the stacks and related info (callchain etc..) */ 75 /* the stacks and related info (callchain etc..) */
31 PERL_SI *curstackinfo; 76 PERL_SI *curstackinfo;
32 AV *curstack; 77 AV *curstack;
33 AV *mainstack; 78 AV *mainstack;
51 I32 savestack_max; 96 I32 savestack_max;
52 OP **retstack; 97 OP **retstack;
53 I32 retstack_ix; 98 I32 retstack_ix;
54 I32 retstack_max; 99 I32 retstack_max;
55 COP *curcop; 100 COP *curcop;
101 JMPENV *top_env;
56 102
57 /* data associated with this coroutine (initial args) */ 103 /* data associated with this coroutine (initial args) */
58 AV *args; 104 AV *args;
59}; 105};
60 106
61typedef struct coro *Coro__State; 107typedef struct coro *Coro__State;
62typedef struct coro *Coro__State_or_hashref; 108typedef struct coro *Coro__State_or_hashref;
63 109
110static AV *main_mainstack; /* used to differentiate between $main and others */
111static HV *coro_state_stash;
112static SV *ucoro_state_sv;
113static U32 ucoro_state_hash;
64static HV *padlist_cache; 114static HV *padlist_cache;
115
116/* for Coro.pm */
117static GV *coro_current, *coro_idle;
118static AV *coro_ready;
65 119
66/* mostly copied from op.c:cv_clone2 */ 120/* mostly copied from op.c:cv_clone2 */
67STATIC AV * 121STATIC AV *
68clone_padlist (AV *protopadlist) 122clone_padlist (AV *protopadlist)
69{ 123{
231#endif 285#endif
232 286
233#define SB do { 287#define SB do {
234#define SE } while (0) 288#define SE } while (0)
235 289
236#define LOAD(state) SB load_state(aTHX_ state); SPAGAIN; SE 290#define LOAD(state) SB load_state(aTHX_ (state)); SPAGAIN; SE
237#define SAVE(state,flags) SB PUTBACK; save_state(aTHX_ state,flags); SE 291#define SAVE(state,flags) SB PUTBACK; save_state(aTHX_ (state),(flags)); SE
238 292
239#define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); SE 293#define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); SE
240 294
241static void 295static void
242load_state(pTHX_ Coro__State c) 296load_state(pTHX_ Coro__State c)
243{ 297{
244 PL_dowarn = c->dowarn; 298 PL_dowarn = c->dowarn;
299 PL_in_eval = c->in_eval;
245 300
246 PL_curstackinfo = c->curstackinfo; 301 PL_curstackinfo = c->curstackinfo;
247 PL_curstack = c->curstack; 302 PL_curstack = c->curstack;
248 PL_mainstack = c->mainstack; 303 PL_mainstack = c->mainstack;
249 PL_stack_sp = c->stack_sp; 304 PL_stack_sp = c->stack_sp;
266 PL_savestack_max = c->savestack_max; 321 PL_savestack_max = c->savestack_max;
267 PL_retstack = c->retstack; 322 PL_retstack = c->retstack;
268 PL_retstack_ix = c->retstack_ix; 323 PL_retstack_ix = c->retstack_ix;
269 PL_retstack_max = c->retstack_max; 324 PL_retstack_max = c->retstack_max;
270 PL_curcop = c->curcop; 325 PL_curcop = c->curcop;
326 PL_top_env = c->top_env;
271 327
272 if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav); 328 if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav);
273 if (c->defsv) REPLACE_SV (DEFSV , c->defsv); 329 if (c->defsv) REPLACE_SV (DEFSV , c->defsv);
274 if (c->errsv) REPLACE_SV (ERRSV , c->errsv); 330 if (c->errsv) REPLACE_SV (ERRSV , c->errsv);
275 331
302save_state(pTHX_ Coro__State c, int flags) 358save_state(pTHX_ Coro__State c, int flags)
303{ 359{
304 { 360 {
305 dSP; 361 dSP;
306 I32 cxix = cxstack_ix; 362 I32 cxix = cxstack_ix;
363 PERL_CONTEXT *ccstk = cxstack;
307 PERL_SI *top_si = PL_curstackinfo; 364 PERL_SI *top_si = PL_curstackinfo;
308 PERL_CONTEXT *ccstk = cxstack;
309 365
310 /* 366 /*
311 * the worst thing you can imagine happens first - we have to save 367 * the worst thing you can imagine happens first - we have to save
312 * (and reinitialize) all cv's in the whole callchain :( 368 * (and reinitialize) all cv's in the whole callchain :(
313 */ 369 */
314 370
315 PUSHs (Nullsv); 371 PUSHs (Nullsv);
316 /* this loop was inspired by pp_caller */ 372 /* this loop was inspired by pp_caller */
317 for (;;) 373 for (;;)
318 { 374 {
319 do 375 do
320 { 376 {
321 PERL_CONTEXT *cx = &ccstk[cxix--]; 377 PERL_CONTEXT *cx = &ccstk[cxix--];
322 378
323 if (CxTYPE(cx) == CXt_SUB) 379 if (CxTYPE(cx) == CXt_SUB)
324 { 380 {
363 } 419 }
364 420
365 PUTBACK; 421 PUTBACK;
366 } 422 }
367 423
368 c->defav = flags & SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0; 424 c->defav = flags & TRANSFER_SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0;
369 c->defsv = flags & SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0; 425 c->defsv = flags & TRANSFER_SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0;
370 c->errsv = flags & SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0; 426 c->errsv = flags & TRANSFER_SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0;
427
428 /* I have not the slightest idea of why av_reify is necessary */
429 /* but if it's missing the defav contents magically get replaced sometimes */
430 if (c->defav)
431 av_reify (c->defav);
371 432
372 c->dowarn = PL_dowarn; 433 c->dowarn = PL_dowarn;
434 c->in_eval = PL_in_eval;
373 435
374 c->curstackinfo = PL_curstackinfo; 436 c->curstackinfo = PL_curstackinfo;
375 c->curstack = PL_curstack; 437 c->curstack = PL_curstack;
376 c->mainstack = PL_mainstack; 438 c->mainstack = PL_mainstack;
377 c->stack_sp = PL_stack_sp; 439 c->stack_sp = PL_stack_sp;
394 c->savestack_max = PL_savestack_max; 456 c->savestack_max = PL_savestack_max;
395 c->retstack = PL_retstack; 457 c->retstack = PL_retstack;
396 c->retstack_ix = PL_retstack_ix; 458 c->retstack_ix = PL_retstack_ix;
397 c->retstack_max = PL_retstack_max; 459 c->retstack_max = PL_retstack_max;
398 c->curcop = PL_curcop; 460 c->curcop = PL_curcop;
461 c->top_env = PL_top_env;
462}
463
464/*
465 * allocate various perl stacks. This is an exact copy
466 * of perl.c:init_stacks, except that it uses less memory
467 * on the assumption that coroutines do not usually need
468 * a lot of stackspace.
469 */
470STATIC void
471coro_init_stacks (pTHX)
472{
473 PL_curstackinfo = new_stackinfo(96, 1024/sizeof(PERL_CONTEXT) - 1);
474 PL_curstackinfo->si_type = PERLSI_MAIN;
475 PL_curstack = PL_curstackinfo->si_stack;
476 PL_mainstack = PL_curstack; /* remember in case we switch stacks */
477
478 PL_stack_base = AvARRAY(PL_curstack);
479 PL_stack_sp = PL_stack_base;
480 PL_stack_max = PL_stack_base + AvMAX(PL_curstack);
481
482 New(50,PL_tmps_stack,96,SV*);
483 PL_tmps_floor = -1;
484 PL_tmps_ix = -1;
485 PL_tmps_max = 96;
486
487 New(54,PL_markstack,16,I32);
488 PL_markstack_ptr = PL_markstack;
489 PL_markstack_max = PL_markstack + 16;
490
491 SET_MARK_OFFSET;
492
493 New(54,PL_scopestack,16,I32);
494 PL_scopestack_ix = 0;
495 PL_scopestack_max = 16;
496
497 New(54,PL_savestack,96,ANY);
498 PL_savestack_ix = 0;
499 PL_savestack_max = 96;
500
501 New(54,PL_retstack,8,OP*);
502 PL_retstack_ix = 0;
503 PL_retstack_max = 8;
399} 504}
400 505
401/* 506/*
402 * destroy the stacks, the callchain etc... 507 * destroy the stacks, the callchain etc...
403 * still there is a memleak of 128 bytes... 508 * still there is a memleak of 128 bytes...
439 Safefree(PL_scopestack); 544 Safefree(PL_scopestack);
440 Safefree(PL_savestack); 545 Safefree(PL_savestack);
441 Safefree(PL_retstack); 546 Safefree(PL_retstack);
442} 547}
443 548
549static void
550allocate_stack (Coro__State ctx, int alloc)
551{
552 coro_stack *stack;
553
554 New (0, stack, 1, coro_stack);
555
556 stack->refcnt = 1;
557 stack->usecnt = 1;
558 stack->gencnt = ctx->gencnt = 0;
559 if (alloc)
560 {
561#ifdef HAVE_MMAP
562 stack->ssize = 128 * 1024 * sizeof (long); /* mmap should do allocate-on-write for us */
563 stack->sptr = mmap (0, stack->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
564 if (stack->sptr == (void *)-1)
565#endif
566 {
567 /*FIXME*//*D*//* reasonable stack size! */
568 stack->ssize = -4096 * sizeof (long);
569 New (0, stack->sptr, 4096, long);
570 }
571 }
572 else
573 stack->sptr = 0;
574
575 ctx->stack = stack;
576}
577
578static void
579deallocate_stack (Coro__State ctx)
580{
581 coro_stack *stack = ctx->stack;
582
583 ctx->stack = 0;
584
585 if (stack)
586 {
587 if (!--stack->refcnt)
588 {
589#ifdef HAVE_MMAP
590 if (stack->ssize > 0 && stack->sptr)
591 munmap (stack->sptr, stack->ssize);
592 else
593#else
594 Safefree (stack->sptr);
595#endif
596 Safefree (stack);
597 }
598 else if (ctx->gencnt == stack->gencnt)
599 --stack->usecnt;
600 }
601}
602
603static void
604setup_coro (void *arg)
605{
606 /*
607 * emulate part of the perl startup here.
608 */
609 dSP;
610 Coro__State ctx = (Coro__State)arg;
611 SV *sub_init = (SV*)get_cv(SUB_INIT, FALSE);
612
613 coro_init_stacks (aTHX);
614 /*PL_curcop = 0;*/
615 /*PL_in_eval = PL_in_eval;*/ /* inherit */
616 SvREFCNT_dec (GvAV (PL_defgv));
617 GvAV (PL_defgv) = ctx->args;
618
619 SPAGAIN;
620
621 if (ctx->stack)
622 {
623 ctx->cursp = 0;
624
625 PUSHMARK(SP);
626 PUTBACK;
627 (void) call_sv (sub_init, G_VOID|G_NOARGS|G_EVAL);
628
629 if (SvTRUE (ERRSV))
630 croak (NULL);
631 else
632 croak ("FATAL: CCTXT coroutine returned!");
633 }
634 else
635 {
636 UNOP myop;
637
638 PL_op = (OP *)&myop;
639
640 Zero(&myop, 1, UNOP);
641 myop.op_next = Nullop;
642 myop.op_flags = OPf_WANT_VOID;
643
644 PUSHMARK(SP);
645 XPUSHs (sub_init);
646 /*
647 * the next line is slightly wrong, as PL_op->op_next
648 * is actually being executed so we skip the first op.
649 * that doesn't matter, though, since it is only
650 * pp_nextstate and we never return...
651 * ah yes, and I don't care anyways ;)
652 */
653 PUTBACK;
654 PL_op = pp_entersub();
655 SPAGAIN;
656
657 ENTER; /* necessary e.g. for dounwind */
658 }
659}
660
661static void
662continue_coro (void *arg)
663{
664 /*
665 * this is a _very_ stripped down perl interpreter ;)
666 */
667 Coro__State ctx = (Coro__State)arg;
668
669 /*FIXME*//* must set up top_env here */
670 ctx->cursp = 0;
671 PL_op = PL_op->op_next;
672 CALLRUNOPS(aTHX);
673
674 abort ();
675}
676
444STATIC void 677STATIC void
445transfer(pTHX_ struct coro *prev, struct coro *next, int flags) 678transfer(pTHX_ struct coro *prev, struct coro *next, int flags)
446{ 679{
447 dSP; 680 dSP;
681 dSTACKLEVEL;
448 682
449 if (prev != next) 683 if (prev != next)
450 { 684 {
451 /*
452 * this could be done in newprocess which would lead to
453 * extremely elegant and fast (just SAVE/LOAD)
454 * code here, but lazy allocation of stacks has also
455 * some virtues and the overhead of the if() is nil.
456 */
457 if (next->mainstack) 685 if (next->mainstack)
458 { 686 {
459 SAVE (prev, flags); 687 SAVE (prev, flags);
460 LOAD (next); 688 LOAD (next);
689
461 /* mark this state as in-use */ 690 /* mark this state as in-use */
462 next->mainstack = 0; 691 next->mainstack = 0;
463 next->tmps_ix = -2; 692 next->tmps_ix = -2;
693
694 /* stacklevel changed? if yes, grab the stack for us! */
695 if (flags & TRANSFER_SAVE_CCTXT)
696 {
697 if (!prev->stack)
698 allocate_stack (prev, 0);
699 else if (prev->cursp != stacklevel
700 && prev->stack->usecnt > 1)
701 {
702 prev->gencnt = ++prev->stack->gencnt;
703 prev->stack->usecnt = 1;
704 }
705
706 /* has our stack been invalidated? */
707 if (next->stack && next->stack->gencnt != next->gencnt)
708 {
709 deallocate_stack (next);
710 allocate_stack (next, 1);
711 coro_create (&(next->stack->cctx),
712 continue_coro, (void *)next,
713 next->stack->sptr, labs (next->stack->ssize));
714 }
715
716 coro_transfer (&(prev->stack->cctx), &(next->stack->cctx));
717 }
718
464 } 719 }
465 else if (next->tmps_ix == -2) 720 else if (next->tmps_ix == -2)
466 {
467 croak ("tried to transfer to running coroutine"); 721 croak ("tried to transfer to running coroutine");
468 }
469 else 722 else
470 { 723 {
471 /*
472 * emulate part of the perl startup here.
473 */
474 UNOP myop;
475
476 SAVE (prev, -1); /* first get rid of the old state */ 724 SAVE (prev, -1); /* first get rid of the old state */
477 725
478 init_stacks (); /* from perl.c */ 726 if (flags & TRANSFER_SAVE_CCTXT)
479 SPAGAIN;
480
481 PL_op = (OP *)&myop;
482 /*PL_curcop = 0;*/
483 SvREFCNT_dec (GvAV (PL_defgv));
484 GvAV (PL_defgv) = next->args;
485
486 Zero(&myop, 1, UNOP);
487 myop.op_next = Nullop;
488 myop.op_flags = OPf_WANT_VOID;
489
490 PUSHMARK(SP);
491 XPUSHs ((SV*)get_cv(SUB_INIT, TRUE));
492 /*
493 * the next line is slightly wrong, as PL_op->op_next
494 * is actually being executed so we skip the first op.
495 * that doesn't matter, though, since it is only
496 * pp_nextstate and we never return...
497 * ah yes, and I don't care anyways ;)
498 */ 727 {
499 PUTBACK; 728 if (!prev->stack)
500 PL_op = pp_entersub(aTHX); 729 allocate_stack (prev, 0);
501 SPAGAIN;
502 730
503 ENTER; /* necessary e.g. for dounwind */ 731 if (prev->stack->sptr && flags & TRANSFER_LAZY_STACK)
732 {
733 setup_coro (next);
734
735 prev->stack->refcnt++;
736 prev->stack->usecnt++;
737 next->stack = prev->stack;
738 next->gencnt = prev->gencnt;
739 }
740 else
741 {
742 allocate_stack (next, 1);
743 coro_create (&(next->stack->cctx),
744 setup_coro, (void *)next,
745 next->stack->sptr, labs (next->stack->ssize));
746 coro_transfer (&(prev->stack->cctx), &(next->stack->cctx));
747 }
748 }
749 else
750 setup_coro (next);
504 } 751 }
505 } 752 }
753
754 next->cursp = stacklevel;
755}
756
757static struct coro *
758sv_to_coro (SV *arg, const char *funcname, const char *varname)
759{
760 if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVHV)
761 {
762 HE *he = hv_fetch_ent((HV *)SvRV(arg), ucoro_state_sv, 0, ucoro_state_hash);
763
764 if (!he)
765 croak ("%s() -- %s is a hashref but lacks the " UCORO_STATE " key", funcname, varname);
766
767 arg = HeVAL(he);
768 }
769
770 /* must also be changed inside Coro::Cont::yield */
771 if (SvROK(arg) && SvSTASH(SvRV(arg)) == coro_state_stash)
772 return (struct coro *) SvIV((SV*)SvRV(arg));
773 else
774 croak ("%s() -- %s is not (and contains not) a Coro::State object", funcname, varname);
506} 775}
507 776
508MODULE = Coro::State PACKAGE = Coro::State 777MODULE = Coro::State PACKAGE = Coro::State
509 778
510PROTOTYPES: ENABLE 779PROTOTYPES: ENABLE
511 780
512BOOT: 781BOOT:
513{ /* {} necessary for stoopid perl-5.6.x */ 782{ /* {} necessary for stoopid perl-5.6.x */
783 ucoro_state_sv = newSVpv (UCORO_STATE, sizeof(UCORO_STATE) - 1);
784 PERL_HASH(ucoro_state_hash, UCORO_STATE, sizeof(UCORO_STATE) - 1);
514 HV * stash = gv_stashpvn("Coro::State", 10, TRUE); 785 coro_state_stash = gv_stashpv ("Coro::State", TRUE);
515 786
516 newCONSTSUB (stash, "SAVE_DEFAV", newSViv (SAVE_DEFAV)); 787 newCONSTSUB (coro_state_stash, "SAVE_DEFAV", newSViv (TRANSFER_SAVE_DEFAV));
517 newCONSTSUB (stash, "SAVE_DEFSV", newSViv (SAVE_DEFSV)); 788 newCONSTSUB (coro_state_stash, "SAVE_DEFSV", newSViv (TRANSFER_SAVE_DEFSV));
518 newCONSTSUB (stash, "SAVE_ERRSV", newSViv (SAVE_ERRSV)); 789 newCONSTSUB (coro_state_stash, "SAVE_ERRSV", newSViv (TRANSFER_SAVE_ERRSV));
790 newCONSTSUB (coro_state_stash, "SAVE_CCTXT", newSViv (TRANSFER_SAVE_CCTXT));
519 791
520 if (!padlist_cache) 792 if (!padlist_cache)
521 padlist_cache = newHV (); 793 padlist_cache = newHV ();
794
795 main_mainstack = PL_mainstack;
522} 796}
523 797
524Coro::State 798Coro::State
525_newprocess(args) 799_newprocess(args)
526 SV * args 800 SV * args
531 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV) 805 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV)
532 croak ("Coro::State::_newprocess expects an arrayref"); 806 croak ("Coro::State::_newprocess expects an arrayref");
533 807
534 New (0, coro, 1, struct coro); 808 New (0, coro, 1, struct coro);
535 809
810 coro->args = (AV *)SvREFCNT_inc (SvRV (args));
536 coro->mainstack = 0; /* actual work is done inside transfer */ 811 coro->mainstack = 0; /* actual work is done inside transfer */
537 coro->args = (AV *)SvREFCNT_inc (SvRV (args)); 812 coro->stack = 0;
538 813
539 RETVAL = coro; 814 RETVAL = coro;
540 OUTPUT: 815 OUTPUT:
541 RETVAL 816 RETVAL
542 817
543void 818void
544transfer(prev, next, flags = SAVE_DEFAV) 819transfer(prev, next, flags)
545 Coro::State_or_hashref prev 820 Coro::State_or_hashref prev
546 Coro::State_or_hashref next 821 Coro::State_or_hashref next
547 int flags 822 int flags
548 PROTOTYPE: @ 823 PROTOTYPE: @
549 CODE: 824 CODE:
550 825 PUTBACK;
551 transfer (aTHX_ prev, next, flags); 826 transfer (aTHX_ prev, next, flags);
827 SPAGAIN;
552 828
553void 829void
554DESTROY(coro) 830DESTROY(coro)
555 Coro::State coro 831 Coro::State coro
556 CODE: 832 CODE:
557 833
558 if (coro->mainstack) 834 if (coro->mainstack && coro->mainstack != main_mainstack)
559 { 835 {
560 struct coro temp; 836 struct coro temp;
561 837
562 SAVE(aTHX_ (&temp), SAVE_ALL); 838 SAVE(aTHX_ (&temp), TRANSFER_SAVE_ALL);
563 LOAD(aTHX_ coro); 839 LOAD(aTHX_ coro);
564 840
565 destroy_stacks (); 841 destroy_stacks (aTHX);
566 842
567 LOAD((&temp)); /* this will get rid of defsv etc.. */ 843 LOAD((&temp)); /* this will get rid of defsv etc.. */
844
845 coro->mainstack = 0;
568 } 846 }
847
848 deallocate_stack (coro);
569 849
570 Safefree (coro); 850 Safefree (coro);
571 851
572void 852void
573flush() 853flush()
574 CODE: 854 CODE:
575#ifdef MAY_FLUSH 855#ifdef MAY_FLUSH
576 flush_padlist_cache (); 856 flush_padlist_cache ();
577#endif 857#endif
578 858
859void
860_exit(code)
861 int code
862 PROTOTYPE: $
863 CODE:
864#if defined(__GLIBC__) || _POSIX_C_SOURCE
865 _exit (code);
866#else
867 signal (SIGTERM, SIG_DFL);
868 raise (SIGTERM);
869 exit (code);
870#endif
871
579MODULE = Coro::State PACKAGE = Coro::Cont 872MODULE = Coro::State PACKAGE = Coro::Cont
580 873
581# this is dirty and should be in it's own .xs 874# this is slightly dirty (should expose a c-level api)
582 875
583void 876void
584result(...) 877yield(...)
585 PROTOTYPE: @ 878 PROTOTYPE: @
586 CODE: 879 CODE:
587 static SV *returnstk; 880 static SV *returnstk;
588 SV *sv; 881 SV *sv;
589 AV *defav = GvAV (PL_defgv); 882 AV *defav = GvAV (PL_defgv);
590 struct coro *prev, *next; 883 struct coro *prev, *next;
591 884
592 if (!returnstk) 885 if (!returnstk)
593 returnstk = SvRV (get_sv ("Coro::Cont::return", FALSE)); 886 returnstk = SvRV (get_sv ("Coro::Cont::return", FALSE));
594 887
595 /* set up @_ */ 888 /* set up @_ -- ugly */
596 av_clear (defav); 889 av_clear (defav);
597 av_fill (defav, items - 1); 890 av_fill (defav, items - 1);
598 while (items--) 891 while (items--)
599 av_store (defav, items, SvREFCNT_inc (ST(items))); 892 av_store (defav, items, SvREFCNT_inc (ST(items)));
600 893
601 mg_get (returnstk); /* isn't documentation wrong for mg_get? */ 894 mg_get (returnstk); /* isn't documentation wrong for mg_get? */
602 sv = av_pop ((AV *)SvRV (returnstk)); 895 sv = av_pop ((AV *)SvRV (returnstk));
603 prev = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 0, 0))); 896 prev = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 0, 0)));
604 next = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0))); 897 next = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0)));
605 SvREFCNT_dec (sv); 898 SvREFCNT_dec (sv);
899
606 transfer(prev, next, 0); 900 transfer(aTHX_ prev, next, 0);
607 901
902MODULE = Coro::State PACKAGE = Coro
903
904# this is slightly dirty (should expose a c-level api)
905
906BOOT:
907{
908 coro_current = gv_fetchpv ("Coro::current", TRUE, SVt_PV);
909 coro_ready = newAV ();
910 coro_idle = gv_fetchpv ("Coro::idle" , TRUE, SVt_PV);
911}
912
913void
914ready(self)
915 SV * self
916 CODE:
917 av_push (coro_ready, SvREFCNT_inc (self));
918
919void
920schedule(...)
921 ALIAS:
922 cede = 1
923 CODE:
924 SV *prev = GvSV (coro_current);
925 SV *next = av_shift (coro_ready);
926
927 if (next == &PL_sv_undef)
928 next = SvREFCNT_inc (GvSV (coro_idle));
929
930 if (ix)
931 av_push (coro_ready, SvREFCNT_inc (prev));
932
933 GvSV (coro_current) = SvREFCNT_inc (next);
934 transfer (sv_to_coro (prev, "Coro::schedule", "current coroutine"),
935 sv_to_coro (next, "Coro::schedule", "next coroutine"),
936 TRANSFER_SAVE_ALL | TRANSFER_LAZY_STACK);
937 SvREFCNT_dec (next);
938 SvREFCNT_dec (prev);
939

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines