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.56 by pcg, Thu Apr 1 02:41:05 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 __thread 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 {
625setup_coro (void *arg) 626setup_coro (void *arg)
626{ 627{
627 /* 628 /*
628 * emulate part of the perl startup here. 629 * emulate part of the perl startup here.
629 */ 630 */
631 dTHX;
630 dSP; 632 dSP;
631 Coro__State ctx = (Coro__State)arg; 633 Coro__State ctx = (Coro__State)arg;
632 SV *sub_init = (SV *)get_cv (SUB_INIT, FALSE); 634 SV *sub_init = (SV *)get_cv (SUB_INIT, FALSE);
633 635
634 coro_init_stacks (aTHX); 636 coro_init_stacks (aTHX);
683continue_coro (void *arg) 685continue_coro (void *arg)
684{ 686{
685 /* 687 /*
686 * this is a _very_ stripped down perl interpreter ;) 688 * this is a _very_ stripped down perl interpreter ;)
687 */ 689 */
690 dTHX;
688 Coro__State ctx = (Coro__State)arg; 691 Coro__State ctx = (Coro__State)arg;
689 JMPENV coro_start_env; 692 JMPENV coro_start_env;
690 693
691 PL_top_env = &ctx->start_env; 694 PL_top_env = &ctx->start_env;
692 695
825api_transfer(pTHX_ SV *prev, SV *next, int flags) 828api_transfer(pTHX_ SV *prev, SV *next, int flags)
826{ 829{
827 SV_CORO (prev, "Coro::transfer"); 830 SV_CORO (prev, "Coro::transfer");
828 SV_CORO (next, "Coro::transfer"); 831 SV_CORO (next, "Coro::transfer");
829 832
830 transfer(aTHX_ SvSTATE(prev), SvSTATE(next), flags); 833 transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags);
831} 834}
832 835
833/** Coro ********************************************************************/ 836/** Coro ********************************************************************/
834 837
835#define PRIO_MAX 3 838#define PRIO_MAX 3
843static GV *coro_current, *coro_idle; 846static GV *coro_current, *coro_idle;
844static AV *coro_ready[PRIO_MAX-PRIO_MIN+1]; 847static AV *coro_ready[PRIO_MAX-PRIO_MIN+1];
845static int coro_nready; 848static int coro_nready;
846 849
847static void 850static void
848coro_enq (SV *sv) 851coro_enq (pTHX_ SV *sv)
849{ 852{
850 if (SvTYPE (sv) == SVt_PVHV) 853 if (SvTYPE (sv) == SVt_PVHV)
851 { 854 {
852 SV **xprio = hv_fetch ((HV *)sv, "prio", 4, 0); 855 SV **xprio = hv_fetch ((HV *)sv, "prio", 4, 0);
853 int prio = xprio ? SvIV (*xprio) : PRIO_NORMAL; 856 int prio = xprio ? SvIV (*xprio) : PRIO_NORMAL;
864 867
865 croak ("Coro::ready tried to enqueue something that is not a coroutine"); 868 croak ("Coro::ready tried to enqueue something that is not a coroutine");
866} 869}
867 870
868static SV * 871static SV *
869coro_deq (int min_prio) 872coro_deq (pTHX_ int min_prio)
870{ 873{
871 int prio = PRIO_MAX - PRIO_MIN; 874 int prio = PRIO_MAX - PRIO_MIN;
872 875
873 min_prio -= PRIO_MIN; 876 min_prio -= PRIO_MIN;
874 if (min_prio < 0) 877 if (min_prio < 0)
885} 888}
886 889
887static void 890static void
888api_ready (SV *coro) 891api_ready (SV *coro)
889{ 892{
893 dTHX;
894
890 if (SvROK (coro)) 895 if (SvROK (coro))
891 coro = SvRV (coro); 896 coro = SvRV (coro);
892 897
893 LOCK; 898 LOCK;
894 coro_enq (SvREFCNT_inc (coro)); 899 coro_enq (aTHX_ SvREFCNT_inc (coro));
895 UNLOCK; 900 UNLOCK;
896} 901}
897 902
898static void 903static void
899api_schedule (void) 904api_schedule (void)
900{ 905{
906 dTHX;
907
901 SV *prev, *next; 908 SV *prev, *next;
902 909
903 LOCK; 910 LOCK;
904 911
905 prev = SvRV (GvSV (coro_current)); 912 prev = SvRV (GvSV (coro_current));
906 next = coro_deq (PRIO_MIN); 913 next = coro_deq (aTHX_ PRIO_MIN);
907 914
908 if (!next) 915 if (!next)
909 next = SvREFCNT_inc (SvRV (GvSV (coro_idle))); 916 next = SvREFCNT_inc (SvRV (GvSV (coro_idle)));
910 917
911 /* free this only after the transfer */ 918 /* free this only after the transfer */
923} 930}
924 931
925static void 932static void
926api_cede (void) 933api_cede (void)
927{ 934{
935 dTHX;
936
928 LOCK; 937 LOCK;
929 coro_enq (SvREFCNT_inc (SvRV (GvSV (coro_current)))); 938 coro_enq (aTHX_ SvREFCNT_inc (SvRV (GvSV (coro_current))));
930 UNLOCK; 939 UNLOCK;
931 940
932 api_schedule (); 941 api_schedule ();
933} 942}
934 943

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines