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.55 by pcg, Thu Apr 1 02:29:05 2004 UTC vs.
Revision 1.59 by root, Mon Jul 19 01:32:27 2004 UTC

1#define PERL_NO_GET_CONTEXT
2
1#include "EXTERN.h" 3#include "EXTERN.h"
2#include "perl.h" 4#include "perl.h"
3#include "XSUB.h" 5#include "XSUB.h"
4 6
5#include "patchlevel.h" 7#include "patchlevel.h"
63# define LOCK 0 65# define LOCK 0
64# define UNLOCK 0 66# define UNLOCK 0
65#endif 67#endif
66 68
67static struct CoroAPI coroapi; 69static struct CoroAPI coroapi;
70static AV *main_mainstack; /* used to differentiate between $main and others */
71static HV *coro_state_stash;
72static SV *ucoro_state_sv;
73static U32 ucoro_state_hash;
74static SV *coro_mortal; /* will be freed after next transfer */
68 75
69/* this is actually not only the c stack but also c registers etc... */ 76/* this is actually not only the c stack but also c registers etc... */
70typedef struct { 77typedef struct {
71 int refcnt; /* pointer reference counter */ 78 int refcnt; /* pointer reference counter */
72 int usecnt; /* shared by how many coroutines */ 79 int usecnt; /* shared by how many coroutines */
130}; 137};
131 138
132typedef struct coro *Coro__State; 139typedef struct coro *Coro__State;
133typedef struct coro *Coro__State_or_hashref; 140typedef struct coro *Coro__State_or_hashref;
134 141
135static AV *main_mainstack; /* used to differentiate between $main and others */
136static HV *coro_state_stash;
137static SV *ucoro_state_sv;
138static U32 ucoro_state_hash;
139static SV *coro_mortal; /* will be freed after next transfer */
140
141/* mostly copied from op.c:cv_clone2 */ 142/* mostly copied from op.c:cv_clone2 */
142STATIC AV * 143STATIC AV *
143clone_padlist (AV *protopadlist) 144clone_padlist (pTHX_ AV *protopadlist)
144{ 145{
145 AV *av; 146 AV *av;
146 I32 ix; 147 I32 ix;
147 AV *protopad_name = (AV *) * av_fetch (protopadlist, 0, FALSE); 148 AV *protopad_name = (AV *) * av_fetch (protopadlist, 0, FALSE);
148 AV *protopad = (AV *) * av_fetch (protopadlist, 1, FALSE); 149 AV *protopad = (AV *) * av_fetch (protopadlist, 1, FALSE);
237 238
238 return newpadlist; 239 return newpadlist;
239} 240}
240 241
241STATIC void 242STATIC void
242free_padlist (AV *padlist) 243free_padlist (pTHX_ AV *padlist)
243{ 244{
244 /* may be during global destruction */ 245 /* may be during global destruction */
245 if (SvREFCNT (padlist)) 246 if (SvREFCNT (padlist))
246 { 247 {
247 I32 i = AvFILLp (padlist); 248 I32 i = AvFILLp (padlist);
268 AV *padlist; 269 AV *padlist;
269 AV *av = (AV *)mg->mg_obj; 270 AV *av = (AV *)mg->mg_obj;
270 271
271 /* casting is fun. */ 272 /* casting is fun. */
272 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av))) 273 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
273 free_padlist (padlist); 274 free_padlist (aTHX_ padlist);
274} 275}
275 276
276#define PERL_MAGIC_coro PERL_MAGIC_ext 277#define PERL_MAGIC_coro PERL_MAGIC_ext
277 278
278static MGVTBL vtbl_coro = {0, 0, 0, 0, coro_cv_free}; 279static MGVTBL vtbl_coro = {0, 0, 0, 0, coro_cv_free};
279 280
280/* the next two functions merely cache the padlists */ 281/* the next two functions merely cache the padlists */
281STATIC void 282STATIC void
282get_padlist (CV *cv) 283get_padlist (pTHX_ CV *cv)
283{ 284{
284 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro); 285 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
285 286
286 if (mg && AvFILLp ((AV *)mg->mg_obj) >= 0) 287 if (mg && AvFILLp ((AV *)mg->mg_obj) >= 0)
287 CvPADLIST (cv) = (AV *)av_pop ((AV *)mg->mg_obj); 288 CvPADLIST (cv) = (AV *)av_pop ((AV *)mg->mg_obj);
288 else 289 else
289 CvPADLIST (cv) = clone_padlist (CvPADLIST (cv)); 290 CvPADLIST (cv) = clone_padlist (aTHX_ CvPADLIST (cv));
290} 291}
291 292
292STATIC void 293STATIC void
293put_padlist (CV *cv) 294put_padlist (pTHX_ CV *cv)
294{ 295{
295 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro); 296 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
296 297
297 if (!mg) 298 if (!mg)
298 { 299 {
360 { 361 {
361 AV *padlist = (AV *)POPs; 362 AV *padlist = (AV *)POPs;
362 363
363 if (padlist) 364 if (padlist)
364 { 365 {
365 put_padlist (cv); /* mark this padlist as available */ 366 put_padlist (aTHX_ cv); /* mark this padlist as available */
366 CvPADLIST(cv) = padlist; 367 CvPADLIST(cv) = padlist;
367 } 368 }
368 369
369 ++CvDEPTH(cv); 370 ++CvDEPTH(cv);
370 } 371 }
410 } 411 }
411 412
412 PUSHs ((SV *)CvPADLIST(cv)); 413 PUSHs ((SV *)CvPADLIST(cv));
413 PUSHs ((SV *)cv); 414 PUSHs ((SV *)cv);
414 415
415 get_padlist (cv); /* this is a monster */ 416 get_padlist (aTHX_ cv); /* this is a monster */
416 } 417 }
417 } 418 }
418#ifdef CXt_FORMAT 419#ifdef CXt_FORMAT
419 else if (CxTYPE(cx) == CXt_FORMAT) 420 else if (CxTYPE(cx) == CXt_FORMAT)
420 { 421 {
531 /* is this ugly, I ask? */ 532 /* is this ugly, I ask? */
532 LEAVE_SCOPE (0); 533 LEAVE_SCOPE (0);
533 534
534 /* sure it is, but more important: is it correct?? :/ */ 535 /* sure it is, but more important: is it correct?? :/ */
535 FREETMPS; 536 FREETMPS;
537
538 /*POPSTACK_TO (PL_mainstack);*//*D*//*use*/
536 } 539 }
537 540
538 while (PL_curstackinfo->si_next) 541 while (PL_curstackinfo->si_next)
539 PL_curstackinfo = PL_curstackinfo->si_next; 542 PL_curstackinfo = PL_curstackinfo->si_next;
540 543
541 while (PL_curstackinfo) 544 while (PL_curstackinfo)
542 { 545 {
543 PERL_SI *p = PL_curstackinfo->si_prev; 546 PERL_SI *p = PL_curstackinfo->si_prev;
544 547
545 { 548 { /*D*//*remove*/
546 dSP; 549 dSP;
547 SWITCHSTACK (PL_curstack, PL_curstackinfo->si_stack); 550 SWITCHSTACK (PL_curstack, PL_curstackinfo->si_stack);
548 PUTBACK; /* possibly superfluous */ 551 PUTBACK; /* possibly superfluous */
549 } 552 }
550 553
551 if (!IN_DESTRUCT) 554 if (!IN_DESTRUCT)
552 { 555 {
553 dounwind(-1); 556 dounwind (-1);/*D*//*remove*/
554 SvREFCNT_dec(PL_curstackinfo->si_stack); 557 SvREFCNT_dec (PL_curstackinfo->si_stack);
555 } 558 }
556 559
557 Safefree(PL_curstackinfo->si_cxstack); 560 Safefree (PL_curstackinfo->si_cxstack);
558 Safefree(PL_curstackinfo); 561 Safefree (PL_curstackinfo);
559 PL_curstackinfo = p; 562 PL_curstackinfo = p;
560 } 563 }
561 564
562 Safefree(PL_tmps_stack); 565 Safefree (PL_tmps_stack);
563 Safefree(PL_markstack); 566 Safefree (PL_markstack);
564 Safefree(PL_scopestack); 567 Safefree (PL_scopestack);
565 Safefree(PL_savestack); 568 Safefree (PL_savestack);
566 Safefree(PL_retstack); 569 Safefree (PL_retstack);
567} 570}
568 571
569static void 572static void
570allocate_stack (Coro__State ctx, int alloc) 573allocate_stack (Coro__State ctx, int alloc)
571{ 574{
625setup_coro (void *arg) 628setup_coro (void *arg)
626{ 629{
627 /* 630 /*
628 * emulate part of the perl startup here. 631 * emulate part of the perl startup here.
629 */ 632 */
633 dTHX;
630 dSP; 634 dSP;
631 Coro__State ctx = (Coro__State)arg; 635 Coro__State ctx = (Coro__State)arg;
632 SV *sub_init = (SV *)get_cv (SUB_INIT, FALSE); 636 SV *sub_init = (SV *)get_cv (SUB_INIT, FALSE);
633 637
634 coro_init_stacks (aTHX); 638 coro_init_stacks (aTHX);
683continue_coro (void *arg) 687continue_coro (void *arg)
684{ 688{
685 /* 689 /*
686 * this is a _very_ stripped down perl interpreter ;) 690 * this is a _very_ stripped down perl interpreter ;)
687 */ 691 */
692 dTHX;
688 Coro__State ctx = (Coro__State)arg; 693 Coro__State ctx = (Coro__State)arg;
689 JMPENV coro_start_env; 694 JMPENV coro_start_env;
690 695
691 PL_top_env = &ctx->start_env; 696 PL_top_env = &ctx->start_env;
692 697
825api_transfer(pTHX_ SV *prev, SV *next, int flags) 830api_transfer(pTHX_ SV *prev, SV *next, int flags)
826{ 831{
827 SV_CORO (prev, "Coro::transfer"); 832 SV_CORO (prev, "Coro::transfer");
828 SV_CORO (next, "Coro::transfer"); 833 SV_CORO (next, "Coro::transfer");
829 834
830 transfer(aTHX_ SvSTATE(prev), SvSTATE(next), flags); 835 transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags);
831} 836}
832 837
833/** Coro ********************************************************************/ 838/** Coro ********************************************************************/
834 839
835#define PRIO_MAX 3 840#define PRIO_MAX 3
843static GV *coro_current, *coro_idle; 848static GV *coro_current, *coro_idle;
844static AV *coro_ready[PRIO_MAX-PRIO_MIN+1]; 849static AV *coro_ready[PRIO_MAX-PRIO_MIN+1];
845static int coro_nready; 850static int coro_nready;
846 851
847static void 852static void
848coro_enq (SV *sv) 853coro_enq (pTHX_ SV *sv)
849{ 854{
850 if (SvTYPE (sv) == SVt_PVHV) 855 if (SvTYPE (sv) == SVt_PVHV)
851 { 856 {
852 SV **xprio = hv_fetch ((HV *)sv, "prio", 4, 0); 857 SV **xprio = hv_fetch ((HV *)sv, "prio", 4, 0);
853 int prio = xprio ? SvIV (*xprio) : PRIO_NORMAL; 858 int prio = xprio ? SvIV (*xprio) : PRIO_NORMAL;
864 869
865 croak ("Coro::ready tried to enqueue something that is not a coroutine"); 870 croak ("Coro::ready tried to enqueue something that is not a coroutine");
866} 871}
867 872
868static SV * 873static SV *
869coro_deq (int min_prio) 874coro_deq (pTHX_ int min_prio)
870{ 875{
871 int prio = PRIO_MAX - PRIO_MIN; 876 int prio = PRIO_MAX - PRIO_MIN;
872 877
873 min_prio -= PRIO_MIN; 878 min_prio -= PRIO_MIN;
874 if (min_prio < 0) 879 if (min_prio < 0)
885} 890}
886 891
887static void 892static void
888api_ready (SV *coro) 893api_ready (SV *coro)
889{ 894{
895 dTHX;
896
890 if (SvROK (coro)) 897 if (SvROK (coro))
891 coro = SvRV (coro); 898 coro = SvRV (coro);
892 899
893 LOCK; 900 LOCK;
894 coro_enq (SvREFCNT_inc (coro)); 901 coro_enq (aTHX_ SvREFCNT_inc (coro));
895 UNLOCK; 902 UNLOCK;
896} 903}
897 904
898static void 905static void
899api_schedule (void) 906api_schedule (void)
900{ 907{
908 dTHX;
909
901 SV *prev, *next; 910 SV *prev, *next;
902 911
903 LOCK; 912 LOCK;
904 913
905 prev = SvRV (GvSV (coro_current)); 914 prev = SvRV (GvSV (coro_current));
906 next = coro_deq (PRIO_MIN); 915 next = coro_deq (aTHX_ PRIO_MIN);
907 916
908 if (!next) 917 if (!next)
909 next = SvREFCNT_inc (SvRV (GvSV (coro_idle))); 918 next = SvREFCNT_inc (SvRV (GvSV (coro_idle)));
910 919
911 /* free this only after the transfer */ 920 /* free this only after the transfer */
923} 932}
924 933
925static void 934static void
926api_cede (void) 935api_cede (void)
927{ 936{
937 dTHX;
938
928 LOCK; 939 LOCK;
929 coro_enq (SvREFCNT_inc (SvRV (GvSV (coro_current)))); 940 coro_enq (aTHX_ SvREFCNT_inc (SvRV (GvSV (coro_current))));
930 UNLOCK; 941 UNLOCK;
931 942
932 api_schedule (); 943 api_schedule ();
933} 944}
934 945
968 croak ("Coro::State::_newprocess expects an arrayref"); 979 croak ("Coro::State::_newprocess expects an arrayref");
969 980
970 Newz (0, coro, 1, struct coro); 981 Newz (0, coro, 1, struct coro);
971 982
972 coro->args = (AV *)SvREFCNT_inc (SvRV (args)); 983 coro->args = (AV *)SvREFCNT_inc (SvRV (args));
973 coro->mainstack = 0; /* actual work is done inside transfer */ 984 /*coro->mainstack = 0; *//*actual work is done inside transfer */
974 coro->stack = 0; 985 /*coro->stack = 0;*/
975 986
976 /* same as JMPENV_BOOTSTRAP */ 987 /* same as JMPENV_BOOTSTRAP */
977 /* we might be able to recycle start_env, but safe is safe */ 988 /* we might be able to recycle start_env, but safe is safe */
978 //Zero(&coro->start_env, 1, JMPENV); 989 /*Zero(&coro->start_env, 1, JMPENV);*/
979 coro->start_env.je_ret = -1; 990 coro->start_env.je_ret = -1;
980 coro->start_env.je_mustcatch = TRUE; 991 coro->start_env.je_mustcatch = TRUE;
981 992
982 RETVAL = coro; 993 RETVAL = coro;
983 OUTPUT: 994 OUTPUT:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines