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.141 by root, Mon Jan 22 18:45:17 2007 UTC vs.
Revision 1.145 by root, Mon Mar 12 21:40:14 2007 UTC

31#else 31#else
32# define PAGESIZE 0 32# define PAGESIZE 0
33# define BOOT_PAGESIZE (void)0 33# define BOOT_PAGESIZE (void)0
34#endif 34#endif
35 35
36#if USE_VALGRIND 36#if CORO_USE_VALGRIND
37# include <valgrind/valgrind.h> 37# include <valgrind/valgrind.h>
38# define REGISTER_STACK(cctx,start,end) (cctx)->valgrind_id = VALGRIND_STACK_REGISTER ((start), (end)) 38# define REGISTER_STACK(cctx,start,end) (cctx)->valgrind_id = VALGRIND_STACK_REGISTER ((start), (end))
39#else 39#else
40# define REGISTER_STACK(cctx,start,end) 40# define REGISTER_STACK(cctx,start,end)
41#endif 41#endif
74#ifndef SvRV_set 74#ifndef SvRV_set
75# define SvRV_set(s,v) SvRV(s) = (v) 75# define SvRV_set(s,v) SvRV(s) = (v)
76#endif 76#endif
77 77
78#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64 78#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64
79# undef STACKGUARD 79# undef CORO_STACKGUARD
80#endif 80#endif
81 81
82#ifndef STACKGUARD 82#ifndef CORO_STACKGUARD
83# define STACKGUARD 0 83# define CORO_STACKGUARD 0
84#endif 84#endif
85 85
86/* prefer perl internal functions over our own? */ 86/* prefer perl internal functions over our own? */
87#ifndef PREFER_PERL_FUNCTIONS 87#ifndef CORO_PREFER_PERL_FUNCTIONS
88# define PREFER_PERL_FUNCTIONS 0 88# define CORO_PREFER_PERL_FUNCTIONS 0
89#endif 89#endif
90 90
91/* The next macro should declare a variable stacklevel that contains and approximation 91/* The next macro should declare a variable stacklevel that contains and approximation
92 * to the current C stack pointer. Its property is that it changes with each call 92 * to the current C stack pointer. Its property is that it changes with each call
93 * and should be unique. */ 93 * and should be unique. */
124 I32 laststype; 124 I32 laststype;
125 int laststatval; 125 int laststatval;
126 Stat_t statcache; 126 Stat_t statcache;
127}; 127};
128 128
129static size_t coro_stacksize = CORO_STACKSIZE;
129static struct CoroAPI coroapi; 130static struct CoroAPI coroapi;
130static AV *main_mainstack; /* used to differentiate between $main and others */ 131static AV *main_mainstack; /* used to differentiate between $main and others */
131static HV *coro_state_stash, *coro_stash; 132static HV *coro_state_stash, *coro_stash;
132static SV *coro_mortal; /* will be freed after next transfer */ 133static SV *coro_mortal; /* will be freed after next transfer */
133 134
138typedef struct coro_cctx { 139typedef struct coro_cctx {
139 struct coro_cctx *next; 140 struct coro_cctx *next;
140 141
141 /* the stack */ 142 /* the stack */
142 void *sptr; 143 void *sptr;
143 ssize_t ssize; /* positive == mmap, otherwise malloc */ 144 size_t ssize;
144 145
145 /* cpu state */ 146 /* cpu state */
146 void *idle_sp; /* sp of top-level transfer/schedule/cede call */ 147 void *idle_sp; /* sp of top-level transfer/schedule/cede call */
147 JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */ 148 JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */
148 JMPENV *top_env; 149 JMPENV *top_env;
149 coro_context cctx; 150 coro_context cctx;
150 151
151 int inuse;
152
153#if USE_VALGRIND 152#if CORO_USE_VALGRIND
154 int valgrind_id; 153 int valgrind_id;
155#endif 154#endif
155 char inuse, mapped;
156} coro_cctx; 156} coro_cctx;
157 157
158enum { 158enum {
159 CF_RUNNING = 0x0001, /* coroutine is running */ 159 CF_RUNNING = 0x0001, /* coroutine is running */
160 CF_READY = 0x0002, /* coroutine is ready */ 160 CF_READY = 0x0002, /* coroutine is ready */
288 288
289 if (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0) 289 if (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0)
290 CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--]; 290 CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--];
291 else 291 else
292 { 292 {
293#if PREFER_PERL_FUNCTIONS 293#if CORO_PREFER_PERL_FUNCTIONS
294 /* this is probably cleaner, but also slower? */ 294 /* this is probably cleaner, but also slower? */
295 CV *cp = Perl_cv_clone (cv); 295 CV *cp = Perl_cv_clone (cv);
296 CvPADLIST (cv) = CvPADLIST (cp); 296 CvPADLIST (cv) = CvPADLIST (cp);
297 CvPADLIST (cp) = 0; 297 CvPADLIST (cp) = 0;
298 SvREFCNT_dec (cp); 298 SvREFCNT_dec (cp);
365 CvPADLIST (cv) = (AV *)POPs; 365 CvPADLIST (cv) = (AV *)POPs;
366 } 366 }
367 367
368 PUTBACK; 368 PUTBACK;
369 } 369 }
370 assert (!PL_comppad || AvARRAY (PL_comppad));//D
370} 371}
371 372
372static void 373static void
373save_perl (Coro__State c) 374save_perl (Coro__State c)
374{ 375{
376 assert (!PL_comppad || AvARRAY (PL_comppad));//D
375 { 377 {
376 dSP; 378 dSP;
377 I32 cxix = cxstack_ix; 379 I32 cxix = cxstack_ix;
378 PERL_CONTEXT *ccstk = cxstack; 380 PERL_CONTEXT *ccstk = cxstack;
379 PERL_SI *top_si = PL_curstackinfo; 381 PERL_SI *top_si = PL_curstackinfo;
434 * allocate various perl stacks. This is an exact copy 436 * allocate various perl stacks. This is an exact copy
435 * of perl.c:init_stacks, except that it uses less memory 437 * of perl.c:init_stacks, except that it uses less memory
436 * on the (sometimes correct) assumption that coroutines do 438 * on the (sometimes correct) assumption that coroutines do
437 * not usually need a lot of stackspace. 439 * not usually need a lot of stackspace.
438 */ 440 */
439#if PREFER_PERL_FUNCTIONS 441#if CORO_PREFER_PERL_FUNCTIONS
440# define coro_init_stacks init_stacks 442# define coro_init_stacks init_stacks
441#else 443#else
442static void 444static void
443coro_init_stacks () 445coro_init_stacks ()
444{ 446{
538 540
539 coro_init_stacks (); 541 coro_init_stacks ();
540 542
541 PL_curcop = &PL_compiling; 543 PL_curcop = &PL_compiling;
542 PL_in_eval = EVAL_NULL; 544 PL_in_eval = EVAL_NULL;
545 PL_comppad = 0;
543 PL_curpm = 0; 546 PL_curpm = 0;
544 PL_localizing = 0; 547 PL_localizing = 0;
545 PL_dirty = 0; 548 PL_dirty = 0;
546 PL_restartop = 0; 549 PL_restartop = 0;
547 550
622 625
623static coro_cctx * 626static coro_cctx *
624cctx_new () 627cctx_new ()
625{ 628{
626 coro_cctx *cctx; 629 coro_cctx *cctx;
630 void *stack_start;
631 size_t stack_size;
627 632
628 ++cctx_count; 633 ++cctx_count;
629 634
630 Newz (0, cctx, 1, coro_cctx); 635 Newz (0, cctx, 1, coro_cctx);
631 636
632#if HAVE_MMAP 637#if HAVE_MMAP
633 638
634 cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; 639 cctx->ssize = ((coro_stacksize * sizeof (long) + PAGESIZE - 1) / PAGESIZE + CORO_STACKGUARD) * PAGESIZE;
635 /* mmap supposedly does allocate-on-write for us */ 640 /* mmap supposedly does allocate-on-write for us */
636 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 641 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
637 642
638 if (cctx->sptr != (void *)-1) 643 if (cctx->sptr != (void *)-1)
639 { 644 {
640# if STACKGUARD 645# if CORO_STACKGUARD
641 mprotect (cctx->sptr, STACKGUARD * PAGESIZE, PROT_NONE); 646 mprotect (cctx->sptr, CORO_STACKGUARD * PAGESIZE, PROT_NONE);
642# endif 647# endif
643 REGISTER_STACK (
644 cctx,
645 STACKGUARD * PAGESIZE + (char *)cctx->sptr, 648 stack_start = CORO_STACKGUARD * PAGESIZE + (char *)cctx->sptr;
646 cctx->ssize + (char *)cctx->sptr 649 stack_size = cctx->ssize - CORO_STACKGUARD * PAGESIZE;
647 ); 650 cctx->mapped = 1;
648
649 coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, cctx->ssize);
650 } 651 }
651 else 652 else
652#endif 653#endif
653 { 654 {
654 cctx->ssize = -STACKSIZE * (long)sizeof (long); 655 cctx->ssize = coro_stacksize * (long)sizeof (long);
655 New (0, cctx->sptr, STACKSIZE, long); 656 New (0, cctx->sptr, coro_stacksize, long);
656 657
657 if (!cctx->sptr) 658 if (!cctx->sptr)
658 { 659 {
659 perror ("FATAL: unable to allocate stack for coroutine"); 660 perror ("FATAL: unable to allocate stack for coroutine");
660 _exit (EXIT_FAILURE); 661 _exit (EXIT_FAILURE);
661 } 662 }
662 663
663 REGISTER_STACK ( 664 stack_start = cctx->sptr;
664 cctx, 665 stack_size = cctx->ssize;
665 (char *)cctx->sptr, 666 }
666 (char *)cctx->sptr - cctx->ssize
667 );
668 667
668 REGISTER_STACK (cctx, (char *)stack_start, (char *)stack_start + stack_size);
669 coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, -cctx->ssize); 669 coro_create (&cctx->cctx, coro_run, (void *)cctx, stack_start, stack_size);
670 }
671 670
672 return cctx; 671 return cctx;
673} 672}
674 673
675static void 674static void
678 if (!cctx) 677 if (!cctx)
679 return; 678 return;
680 679
681 --cctx_count; 680 --cctx_count;
682 681
683#if USE_VALGRIND 682#if CORO_USE_VALGRIND
684 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id); 683 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id);
685#endif 684#endif
686 685
687#if HAVE_MMAP 686#if HAVE_MMAP
688 if (cctx->ssize > 0) 687 if (cctx->mapped)
689 munmap (cctx->sptr, cctx->ssize); 688 munmap (cctx->sptr, cctx->ssize);
690 else 689 else
691#endif 690#endif
692 Safefree (cctx->sptr); 691 Safefree (cctx->sptr);
693 692
695} 694}
696 695
697static coro_cctx * 696static coro_cctx *
698cctx_get () 697cctx_get ()
699{ 698{
700 coro_cctx *cctx;
701
702 if (cctx_first) 699 while (cctx_first)
703 { 700 {
704 cctx = cctx_first; 701 coro_cctx *cctx = cctx_first;
705 cctx_first = cctx->next; 702 cctx_first = cctx->next;
706 --cctx_idle; 703 --cctx_idle;
704
705 if (cctx->ssize >= coro_stacksize)
706 return cctx;
707
708 cctx_destroy (cctx);
707 } 709 }
708 else 710
709 {
710 cctx = cctx_new ();
711 PL_op = PL_op->op_next; 711 PL_op = PL_op->op_next;
712 }
713
714 return cctx; 712 return cctx_new ();
715} 713}
716 714
717static void 715static void
718cctx_put (coro_cctx *cctx) 716cctx_put (coro_cctx *cctx)
719{ 717{
933 /* very slow, but rare, check */ 931 /* very slow, but rare, check */
934 if (!sv_derived_from (sv_2mortal (newRV_inc (coro)), "Coro::State")) 932 if (!sv_derived_from (sv_2mortal (newRV_inc (coro)), "Coro::State"))
935 croak ("Coro::State object required"); 933 croak ("Coro::State object required");
936 } 934 }
937 935
938 mg = SvMAGIC (coro); 936 mg = CORO_MAGIC (coro);
939 assert (mg->mg_type == PERL_MAGIC_ext);
940 return (struct coro *)mg->mg_ptr; 937 return (struct coro *)mg->mg_ptr;
941} 938}
942 939
943static void 940static void
944prepare_transfer (struct transfer_args *ta, SV *prev_sv, SV *next_sv) 941prepare_transfer (struct transfer_args *ta, SV *prev_sv, SV *next_sv)
1256 PROTOTYPE: $ 1253 PROTOTYPE: $
1257 CODE: 1254 CODE:
1258 _exit (code); 1255 _exit (code);
1259 1256
1260int 1257int
1258cctx_stacksize (int new_stacksize = 0)
1259 CODE:
1260 RETVAL = coro_stacksize;
1261 if (new_stacksize)
1262 coro_stacksize = new_stacksize;
1263 OUTPUT:
1264 RETVAL
1265
1266int
1261cctx_count () 1267cctx_count ()
1262 CODE: 1268 CODE:
1263 RETVAL = cctx_count; 1269 RETVAL = cctx_count;
1264 OUTPUT: 1270 OUTPUT:
1265 RETVAL 1271 RETVAL

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines