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.111 by root, Thu Nov 30 18:21:14 2006 UTC vs.
Revision 1.116 by root, Fri Dec 1 14:01:43 2006 UTC

7#include "patchlevel.h" 7#include "patchlevel.h"
8 8
9#if USE_VALGRIND 9#if USE_VALGRIND
10# include <valgrind/valgrind.h> 10# include <valgrind/valgrind.h>
11#endif 11#endif
12
13/* the maximum number of idle cctx that will be pooled */
14#define MAX_IDLE_CCTX 8
12 15
13#define PERL_VERSION_ATLEAST(a,b,c) \ 16#define PERL_VERSION_ATLEAST(a,b,c) \
14 (PERL_REVISION > (a) \ 17 (PERL_REVISION > (a) \
15 || (PERL_REVISION == (a) \ 18 || (PERL_REVISION == (a) \
16 && (PERL_VERSION > (b) \ 19 && (PERL_VERSION > (b) \
386 * not usually need a lot of stackspace. 389 * not usually need a lot of stackspace.
387 */ 390 */
388static void 391static void
389coro_init_stacks () 392coro_init_stacks ()
390{ 393{
391 PL_curstackinfo = new_stackinfo(96, 1024/sizeof(PERL_CONTEXT) - 1); 394 PL_curstackinfo = new_stackinfo(128, 1024/sizeof(PERL_CONTEXT));
392 PL_curstackinfo->si_type = PERLSI_MAIN; 395 PL_curstackinfo->si_type = PERLSI_MAIN;
393 PL_curstack = PL_curstackinfo->si_stack; 396 PL_curstack = PL_curstackinfo->si_stack;
394 PL_mainstack = PL_curstack; /* remember in case we switch stacks */ 397 PL_mainstack = PL_curstack; /* remember in case we switch stacks */
395 398
396 PL_stack_base = AvARRAY(PL_curstack); 399 PL_stack_base = AvARRAY(PL_curstack);
397 PL_stack_sp = PL_stack_base; 400 PL_stack_sp = PL_stack_base;
398 PL_stack_max = PL_stack_base + AvMAX(PL_curstack); 401 PL_stack_max = PL_stack_base + AvMAX(PL_curstack);
399 402
400 New(50,PL_tmps_stack,96,SV*); 403 New(50,PL_tmps_stack,128,SV*);
401 PL_tmps_floor = -1; 404 PL_tmps_floor = -1;
402 PL_tmps_ix = -1; 405 PL_tmps_ix = -1;
403 PL_tmps_max = 96; 406 PL_tmps_max = 128;
404 407
405 New(54,PL_markstack,16,I32); 408 New(54,PL_markstack,32,I32);
406 PL_markstack_ptr = PL_markstack; 409 PL_markstack_ptr = PL_markstack;
407 PL_markstack_max = PL_markstack + 16; 410 PL_markstack_max = PL_markstack + 32;
408 411
409#ifdef SET_MARK_OFFSET 412#ifdef SET_MARK_OFFSET
410 SET_MARK_OFFSET; 413 SET_MARK_OFFSET;
411#endif 414#endif
412 415
413 New(54,PL_scopestack,16,I32); 416 New(54,PL_scopestack,32,I32);
414 PL_scopestack_ix = 0; 417 PL_scopestack_ix = 0;
415 PL_scopestack_max = 16; 418 PL_scopestack_max = 32;
416 419
417 New(54,PL_savestack,96,ANY); 420 New(54,PL_savestack,64,ANY);
418 PL_savestack_ix = 0; 421 PL_savestack_ix = 0;
419 PL_savestack_max = 96; 422 PL_savestack_max = 64;
420 423
421#if !PERL_VERSION_ATLEAST (5,9,0) 424#if !PERL_VERSION_ATLEAST (5,9,0)
422 New(54,PL_retstack,8,OP*); 425 New(54,PL_retstack,16,OP*);
423 PL_retstack_ix = 0; 426 PL_retstack_ix = 0;
424 PL_retstack_max = 8; 427 PL_retstack_max = 16;
425#endif 428#endif
426} 429}
427 430
428/* 431/*
429 * destroy the stacks, the callchain etc... 432 * destroy the stacks, the callchain etc...
613 616
614 return cctx; 617 return cctx;
615} 618}
616 619
617static void 620static void
618cctx_free (coro_cctx *cctx) 621cctx_destroy (coro_cctx *cctx)
619{ 622{
620 if (!cctx) 623 if (!cctx)
621 return; 624 return;
622 625
623 --cctx_count; 626 --cctx_count;
640{ 643{
641 coro_cctx *cctx; 644 coro_cctx *cctx;
642 645
643 if (cctx_first) 646 if (cctx_first)
644 { 647 {
645 --cctx_idle;
646 cctx = cctx_first; 648 cctx = cctx_first;
647 cctx_first = cctx->next; 649 cctx_first = cctx->next;
650 --cctx_idle;
648 } 651 }
649 else 652 else
650 { 653 {
651 cctx = cctx_new (); 654 cctx = cctx_new ();
652 PL_op = PL_op->op_next; 655 PL_op = PL_op->op_next;
656} 659}
657 660
658static void 661static void
659cctx_put (coro_cctx *cctx) 662cctx_put (coro_cctx *cctx)
660{ 663{
664 /* free another cctx if overlimit */
665 if (cctx_idle >= MAX_IDLE_CCTX)
666 {
667 coro_cctx *first = cctx_first;
668 cctx_first = first->next;
669 --cctx_idle;
670
671 assert (!first->inuse);
672 cctx_destroy (first);
673 }
674
661 ++cctx_idle; 675 ++cctx_idle;
662 cctx->next = cctx_first; 676 cctx->next = cctx_first;
663 cctx_first = cctx; 677 cctx_first = cctx;
664} 678}
665 679
682 Newz (0, prev->cctx, 1, coro_cctx); 696 Newz (0, prev->cctx, 1, coro_cctx);
683 prev->cctx->inuse = 1; 697 prev->cctx->inuse = 1;
684 prev->flags |= CF_RUNNING; 698 prev->flags |= CF_RUNNING;
685 } 699 }
686 700
687 assert ( prev->flags & CF_RUNNING); 701 if (!prev->flags & CF_RUNNING)
702 croak ("Coro::State::transfer called with non-running prev Coro::State, but can only transfer from running states");
703
688 assert (!next->flags & CF_RUNNING); 704 if (next->flags & CF_RUNNING)
705 croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states");
689 706
690 prev->flags &= ~CF_RUNNING; 707 prev->flags &= ~CF_RUNNING;
691 next->flags |= CF_RUNNING; 708 next->flags |= CF_RUNNING;
692 709
693 LOCK; 710 LOCK;
703 /* need to start coroutine */ 720 /* need to start coroutine */
704 /* first get rid of the old state */ 721 /* first get rid of the old state */
705 SAVE (prev, -1); 722 SAVE (prev, -1);
706 /* setup coroutine call */ 723 /* setup coroutine call */
707 setup_coro (next); 724 setup_coro (next);
708 /* need a stack */ 725 /* need a new stack */
709 assert (!next->stack); 726 assert (!next->stack);
710 next->cctx = 0;
711 } 727 }
712 728
713 prev__cctx = prev->cctx; 729 prev__cctx = prev->cctx;
714 730
715 /* possibly "free" the cctx */ 731 /* possibly "free" the cctx */
716 if (prev__cctx->idle_sp == STACKLEVEL) 732 if (prev__cctx->idle_sp == STACKLEVEL)
717 { 733 {
734 /* I assume that STACKLEVEL is a stronger indicator than PL_top_env changes */
718 assert (PL_top_env == prev__cctx->top_env);//D 735 assert (PL_top_env == prev__cctx->top_env);
736
719 cctx_put (prev__cctx); 737 cctx_put (prev__cctx);
720 prev->cctx = 0; 738 prev->cctx = 0;
721 } 739 }
722 740
723 if (!next->cctx) 741 if (!next->cctx)
754coro_state_destroy (struct coro *coro) 772coro_state_destroy (struct coro *coro)
755{ 773{
756 if (coro->refcnt--) 774 if (coro->refcnt--)
757 return; 775 return;
758 776
777 if (coro->flags & CF_RUNNING)
778 croak ("FATAL: tried to destroy currently running coroutine");
779
759 if (coro->mainstack && coro->mainstack != main_mainstack) 780 if (coro->mainstack && coro->mainstack != main_mainstack)
760 { 781 {
761 struct coro temp; 782 struct coro temp;
762 783
763 SAVE ((&temp), TRANSFER_SAVE_ALL); 784 SAVE ((&temp), TRANSFER_SAVE_ALL);
768 LOAD ((&temp)); /* this will get rid of defsv etc.. */ 789 LOAD ((&temp)); /* this will get rid of defsv etc.. */
769 790
770 coro->mainstack = 0; 791 coro->mainstack = 0;
771 } 792 }
772 793
773 cctx_free (coro->cctx); 794 cctx_destroy (coro->cctx);
774 SvREFCNT_dec (coro->args); 795 SvREFCNT_dec (coro->args);
775 Safefree (coro); 796 Safefree (coro);
776} 797}
777 798
778static int 799static int
860static GV *coro_current, *coro_idle; 881static GV *coro_current, *coro_idle;
861static AV *coro_ready [PRIO_MAX-PRIO_MIN+1]; 882static AV *coro_ready [PRIO_MAX-PRIO_MIN+1];
862static int coro_nready; 883static int coro_nready;
863 884
864static void 885static void
865coro_enq (SV *sv) 886coro_enq (SV *coro_sv)
866{ 887{
867 int prio;
868
869 if (SvTYPE (sv) != SVt_PVHV)
870 croak ("Coro::ready tried to enqueue something that is not a coroutine");
871
872 prio = SvSTATE (sv)->prio;
873
874 av_push (coro_ready [prio - PRIO_MIN], sv); 888 av_push (coro_ready [SvSTATE (coro_sv)->prio - PRIO_MIN], coro_sv);
875 coro_nready++; 889 coro_nready++;
876} 890}
877 891
878static SV * 892static SV *
879coro_deq (int min_prio) 893coro_deq (int min_prio)
901 915
902 if (SvROK (coro_sv)) 916 if (SvROK (coro_sv))
903 coro_sv = SvRV (coro_sv); 917 coro_sv = SvRV (coro_sv);
904 918
905 coro = SvSTATE (coro_sv); 919 coro = SvSTATE (coro_sv);
920
906 if (coro->flags & CF_READY) 921 if (coro->flags & CF_READY)
907 return 0; 922 return 0;
923
924 if (coro->flags & CF_RUNNING)
925 croak ("Coro::ready called on currently running coroutine");
908 926
909 coro->flags |= CF_READY; 927 coro->flags |= CF_READY;
910 928
911 LOCK; 929 LOCK;
912 coro_enq (SvREFCNT_inc (coro_sv)); 930 coro_enq (SvREFCNT_inc (coro_sv));
916} 934}
917 935
918static int 936static int
919api_is_ready (SV *coro_sv) 937api_is_ready (SV *coro_sv)
920{ 938{
921 struct coro *coro;
922
923 return !!(SvSTATE (coro_sv)->flags & CF_READY); 939 return !!SvSTATE (coro_sv)->flags & CF_READY;
924} 940}
925 941
926static void 942static void
927prepare_schedule (struct transfer_args *ta) 943prepare_schedule (struct transfer_args *ta)
928{ 944{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines