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.137 by root, Sun Jan 14 20:47:53 2007 UTC vs.
Revision 1.142 by root, Tue Feb 13 19:21:29 2007 UTC

33# define BOOT_PAGESIZE (void)0 33# define BOOT_PAGESIZE (void)0
34#endif 34#endif
35 35
36#if USE_VALGRIND 36#if 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))
39#else
40# define REGISTER_STACK(cctx,start,end)
38#endif 41#endif
39 42
40/* the maximum number of idle cctx that will be pooled */ 43/* the maximum number of idle cctx that will be pooled */
41#define MAX_IDLE_CCTX 8 44#define MAX_IDLE_CCTX 8
42 45
135typedef struct coro_cctx { 138typedef struct coro_cctx {
136 struct coro_cctx *next; 139 struct coro_cctx *next;
137 140
138 /* the stack */ 141 /* the stack */
139 void *sptr; 142 void *sptr;
140 long ssize; /* positive == mmap, otherwise malloc */ 143 ssize_t ssize; /* positive == mmap, otherwise malloc */
141 144
142 /* cpu state */ 145 /* cpu state */
143 void *idle_sp; /* sp of top-level transfer/schedule/cede call */ 146 void *idle_sp; /* sp of top-level transfer/schedule/cede call */
144 JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */ 147 JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */
145 JMPENV *top_env; 148 JMPENV *top_env;
362 CvPADLIST (cv) = (AV *)POPs; 365 CvPADLIST (cv) = (AV *)POPs;
363 } 366 }
364 367
365 PUTBACK; 368 PUTBACK;
366 } 369 }
370 assert (!PL_comppad || AvARRAY (PL_comppad));//D
367} 371}
368 372
369static void 373static void
370save_perl (Coro__State c) 374save_perl (Coro__State c)
371{ 375{
376 assert (!PL_comppad || AvARRAY (PL_comppad));//D
372 { 377 {
373 dSP; 378 dSP;
374 I32 cxix = cxstack_ix; 379 I32 cxix = cxstack_ix;
375 PERL_CONTEXT *ccstk = cxstack; 380 PERL_CONTEXT *ccstk = cxstack;
376 PERL_SI *top_si = PL_curstackinfo; 381 PERL_SI *top_si = PL_curstackinfo;
535 540
536 coro_init_stacks (); 541 coro_init_stacks ();
537 542
538 PL_curcop = &PL_compiling; 543 PL_curcop = &PL_compiling;
539 PL_in_eval = EVAL_NULL; 544 PL_in_eval = EVAL_NULL;
545 PL_comppad = 0;
540 PL_curpm = 0; 546 PL_curpm = 0;
541 PL_localizing = 0; 547 PL_localizing = 0;
542 PL_dirty = 0; 548 PL_dirty = 0;
543 PL_restartop = 0; 549 PL_restartop = 0;
544 550
630 636
631 cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; 637 cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE;
632 /* mmap supposedly does allocate-on-write for us */ 638 /* mmap supposedly does allocate-on-write for us */
633 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 639 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
634 640
635 if (cctx->sptr == (void *)-1) 641 if (cctx->sptr != (void *)-1)
636 {
637 perror ("FATAL: unable to mmap stack for coroutine");
638 _exit (EXIT_FAILURE);
639 } 642 {
640
641# if STACKGUARD 643# if STACKGUARD
642 mprotect (cctx->sptr, STACKGUARD * PAGESIZE, PROT_NONE); 644 mprotect (cctx->sptr, STACKGUARD * PAGESIZE, PROT_NONE);
643# endif 645# endif
644 646 REGISTER_STACK (
645#else 647 cctx,
646
647 cctx->ssize = STACKSIZE * (long)sizeof (long);
648 New (0, cctx->sptr, STACKSIZE, long);
649
650 if (!cctx->sptr)
651 {
652 perror ("FATAL: unable to malloc stack for coroutine");
653 _exit (EXIT_FAILURE);
654 }
655
656#endif
657
658#if USE_VALGRIND
659 cctx->valgrind_id = VALGRIND_STACK_REGISTER (
660 STACKGUARD * PAGESIZE + (char *)cctx->sptr, 648 STACKGUARD * PAGESIZE + (char *)cctx->sptr,
661 cctx->ssize + (char *)cctx->sptr 649 cctx->ssize + (char *)cctx->sptr
662 ); 650 );
663#endif
664 651
665 coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, cctx->ssize); 652 coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, cctx->ssize);
653 }
654 else
655#endif
656 {
657 cctx->ssize = -STACKSIZE * (long)sizeof (long);
658 New (0, cctx->sptr, STACKSIZE, long);
659
660 if (!cctx->sptr)
661 {
662 perror ("FATAL: unable to allocate stack for coroutine");
663 _exit (EXIT_FAILURE);
664 }
665
666 REGISTER_STACK (
667 cctx,
668 (char *)cctx->sptr,
669 (char *)cctx->sptr - cctx->ssize
670 );
671
672 coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, -cctx->ssize);
673 }
666 674
667 return cctx; 675 return cctx;
668} 676}
669 677
670static void 678static void
678#if USE_VALGRIND 686#if USE_VALGRIND
679 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id); 687 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id);
680#endif 688#endif
681 689
682#if HAVE_MMAP 690#if HAVE_MMAP
691 if (cctx->ssize > 0)
683 munmap (cctx->sptr, cctx->ssize); 692 munmap (cctx->sptr, cctx->ssize);
684#else 693 else
694#endif
685 Safefree (cctx->sptr); 695 Safefree (cctx->sptr);
686#endif
687 696
688 Safefree (cctx); 697 Safefree (cctx);
689} 698}
690 699
691static coro_cctx * 700static coro_cctx *
838 coro->flags |= CF_DESTROYED; 847 coro->flags |= CF_DESTROYED;
839 848
840 if (coro->flags & CF_READY) 849 if (coro->flags & CF_READY)
841 { 850 {
842 /* reduce nready, as destroying a ready coro effectively unreadies it */ 851 /* reduce nready, as destroying a ready coro effectively unreadies it */
843 /* alternative: look through all ready queues and remove it */ 852 /* alternative: look through all ready queues and remove the coro */
844 LOCK; 853 LOCK;
845 --coro_nready; 854 --coro_nready;
846 UNLOCK; 855 UNLOCK;
847 } 856 }
848 else 857 else
849 coro->flags |= CF_READY; /* make sure it is NOT put into the readyqueue */ 858 coro->flags |= CF_READY; /* make sure it is NOT put into the readyqueue */
850 859
851 if (coro->mainstack && coro->mainstack != main_mainstack) 860 if (coro->mainstack && coro->mainstack != main_mainstack)
852 { 861 {
862 struct coro temp;
863
853 assert (!(coro->flags & CF_RUNNING)); 864 assert (!(coro->flags & CF_RUNNING));
854 865
855 struct coro temp;
856 Zero (&temp, 1, struct coro); 866 Zero (&temp, 1, struct coro);
857 temp.save = CORO_SAVE_ALL; 867 temp.save = CORO_SAVE_ALL;
858 868
859 if (coro->flags & CF_RUNNING) 869 if (coro->flags & CF_RUNNING)
860 croak ("FATAL: tried to destroy currently running coroutine"); 870 croak ("FATAL: tried to destroy currently running coroutine");
1021 1031
1022 for (;;) 1032 for (;;)
1023 { 1033 {
1024 LOCK; 1034 LOCK;
1025 next_sv = coro_deq (PRIO_MIN); 1035 next_sv = coro_deq (PRIO_MIN);
1026 UNLOCK;
1027 1036
1028 /* nothing to schedule: call the idle handler */ 1037 /* nothing to schedule: call the idle handler */
1029 if (!next_sv) 1038 if (!next_sv)
1030 { 1039 {
1031 dSP; 1040 dSP;
1041 UNLOCK;
1032 1042
1033 ENTER; 1043 ENTER;
1034 SAVETMPS; 1044 SAVETMPS;
1035 1045
1036 PUSHMARK (SP); 1046 PUSHMARK (SP);
1045 ta->next = SvSTATE (next_sv); 1055 ta->next = SvSTATE (next_sv);
1046 1056
1047 /* cannot transfer to destroyed coros, skip and look for next */ 1057 /* cannot transfer to destroyed coros, skip and look for next */
1048 if (ta->next->flags & CF_DESTROYED) 1058 if (ta->next->flags & CF_DESTROYED)
1049 { 1059 {
1060 UNLOCK;
1050 SvREFCNT_dec (next_sv); 1061 SvREFCNT_dec (next_sv);
1051 /* coro_nready is already taken care of by destroy */ 1062 /* coro_nready is already taken care of by destroy */
1052 continue; 1063 continue;
1053 } 1064 }
1054 1065
1055 LOCK;
1056 --coro_nready; 1066 --coro_nready;
1057 UNLOCK; 1067 UNLOCK;
1058 break; 1068 break;
1059 } 1069 }
1060 1070

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines