ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/State.xs
Revision: 1.21
Committed: Sat Aug 11 19:59:19 2001 UTC (22 years, 9 months ago) by root
Branch: MAIN
Changes since 1.20: +64 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5 root 1.13 #include "libcoro/coro.c"
6    
7 root 1.20 #include <signal.h>
8    
9 root 1.13 #ifdef HAVE_MMAP
10     # include <unistd.h>
11     # include <sys/mman.h>
12 root 1.16 # ifndef MAP_ANON
13     # ifdef MAP_ANONYMOUS
14     # define MAP_ANON MAP_ANONYMOUS
15     # else
16     # undef HAVE_MMAP
17     # endif
18     # endif
19 root 1.3 #endif
20    
21 root 1.7 #define MAY_FLUSH /* increases codesize */
22    
23 root 1.15 /* perl-related */
24 root 1.12 #define TRANSFER_SAVE_DEFAV 0x00000001
25     #define TRANSFER_SAVE_DEFSV 0x00000002
26     #define TRANSFER_SAVE_ERRSV 0x00000004
27 root 1.15 /* c-related */
28 root 1.13 #define TRANSFER_SAVE_CCTXT 0x00000008
29 root 1.15 #ifdef CORO_LAZY_STACK
30     # define TRANSFER_LAZY_STACK 0x00000010
31     #else
32     # define TRANSFER_LAZY_STACK 0x00000000
33     #endif
34 root 1.7
35 root 1.15 #define TRANSFER_SAVE_ALL (TRANSFER_SAVE_DEFAV|TRANSFER_SAVE_DEFSV \
36     |TRANSFER_SAVE_ERRSV|TRANSFER_SAVE_CCTXT)
37 root 1.7
38 root 1.14 #define SUB_INIT "Coro::State::initialize"
39     #define UCORO_STATE "_coro_state"
40    
41 root 1.15 /* The next macro should delcare a variable stacklevel that contains and approximation
42     * to the current C stack pointer. It's property is that it changes with each call
43     * and should be unique. */
44     #define dSTACKLEVEL void *stacklevel = &stacklevel
45    
46     #define labs(l) ((l) >= 0 ? (l) : -(l))
47    
48     /* this is actually not only the c stack but also c registers etc... */
49     typedef struct {
50     int refcnt; /* pointer reference counter */
51     int usecnt; /* shared by how many coroutines */
52     int gencnt; /* generation counter */
53    
54     coro_context cctx;
55    
56     void *sptr;
57     long ssize; /* positive == mmap, otherwise malloc */
58     } coro_stack;
59    
60 root 1.1 struct coro {
61 root 1.13 /* the optional C context */
62 root 1.15 coro_stack *stack;
63     void *cursp;
64     int gencnt;
65 root 1.13
66 root 1.7 /* optionally saved, might be zero */
67 root 1.3 AV *defav;
68 root 1.7 SV *defsv;
69     SV *errsv;
70 root 1.1
71 root 1.7 /* saved global state not related to stacks */
72     U8 dowarn;
73 root 1.19 I32 in_eval;
74 root 1.7
75     /* the stacks and related info (callchain etc..) */
76 root 1.1 PERL_SI *curstackinfo;
77     AV *curstack;
78     AV *mainstack;
79     SV **stack_sp;
80     OP *op;
81     SV **curpad;
82     SV **stack_base;
83     SV **stack_max;
84     SV **tmps_stack;
85     I32 tmps_floor;
86     I32 tmps_ix;
87     I32 tmps_max;
88     I32 *markstack;
89     I32 *markstack_ptr;
90     I32 *markstack_max;
91     I32 *scopestack;
92     I32 scopestack_ix;
93     I32 scopestack_max;
94     ANY *savestack;
95     I32 savestack_ix;
96     I32 savestack_max;
97     OP **retstack;
98     I32 retstack_ix;
99     I32 retstack_max;
100     COP *curcop;
101 root 1.13 JMPENV *top_env;
102 root 1.1
103 root 1.7 /* data associated with this coroutine (initial args) */
104 root 1.3 AV *args;
105 root 1.1 };
106    
107     typedef struct coro *Coro__State;
108     typedef struct coro *Coro__State_or_hashref;
109    
110 root 1.12 static AV *main_mainstack; /* used to differentiate between $main and others */
111 root 1.13 static HV *coro_state_stash;
112 root 1.14 static SV *ucoro_state_sv;
113     static U32 ucoro_state_hash;
114 root 1.3 static HV *padlist_cache;
115    
116 root 1.21 /* for Coro.pm */
117     static GV *coro_current, *coro_idle;
118     static AV *coro_ready;
119    
120 root 1.3 /* mostly copied from op.c:cv_clone2 */
121     STATIC AV *
122     clone_padlist (AV *protopadlist)
123     {
124     AV *av;
125     I32 ix;
126     AV *protopad_name = (AV *) * av_fetch (protopadlist, 0, FALSE);
127     AV *protopad = (AV *) * av_fetch (protopadlist, 1, FALSE);
128     SV **pname = AvARRAY (protopad_name);
129     SV **ppad = AvARRAY (protopad);
130     I32 fname = AvFILLp (protopad_name);
131     I32 fpad = AvFILLp (protopad);
132     AV *newpadlist, *newpad_name, *newpad;
133     SV **npad;
134    
135     newpad_name = newAV ();
136     for (ix = fname; ix >= 0; ix--)
137     av_store (newpad_name, ix, SvREFCNT_inc (pname[ix]));
138    
139     newpad = newAV ();
140     av_fill (newpad, AvFILLp (protopad));
141     npad = AvARRAY (newpad);
142    
143     newpadlist = newAV ();
144     AvREAL_off (newpadlist);
145     av_store (newpadlist, 0, (SV *) newpad_name);
146     av_store (newpadlist, 1, (SV *) newpad);
147    
148     av = newAV (); /* will be @_ */
149     av_extend (av, 0);
150     av_store (newpad, 0, (SV *) av);
151     AvFLAGS (av) = AVf_REIFY;
152    
153     for (ix = fpad; ix > 0; ix--)
154     {
155     SV *namesv = (ix <= fname) ? pname[ix] : Nullsv;
156     if (namesv && namesv != &PL_sv_undef)
157     {
158     char *name = SvPVX (namesv); /* XXX */
159     if (SvFLAGS (namesv) & SVf_FAKE || *name == '&')
160     { /* lexical from outside? */
161     npad[ix] = SvREFCNT_inc (ppad[ix]);
162     }
163     else
164     { /* our own lexical */
165     SV *sv;
166     if (*name == '&')
167     sv = SvREFCNT_inc (ppad[ix]);
168     else if (*name == '@')
169     sv = (SV *) newAV ();
170     else if (*name == '%')
171     sv = (SV *) newHV ();
172     else
173     sv = NEWSV (0, 0);
174     if (!SvPADBUSY (sv))
175     SvPADMY_on (sv);
176     npad[ix] = sv;
177     }
178     }
179     else if (IS_PADGV (ppad[ix]) || IS_PADCONST (ppad[ix]))
180     {
181     npad[ix] = SvREFCNT_inc (ppad[ix]);
182     }
183     else
184     {
185     SV *sv = NEWSV (0, 0);
186     SvPADTMP_on (sv);
187     npad[ix] = sv;
188     }
189     }
190    
191 root 1.7 #if 0 /* return -ENOTUNDERSTOOD */
192 root 1.3 /* Now that vars are all in place, clone nested closures. */
193    
194     for (ix = fpad; ix > 0; ix--) {
195     SV* namesv = (ix <= fname) ? pname[ix] : Nullsv;
196     if (namesv
197     && namesv != &PL_sv_undef
198     && !(SvFLAGS(namesv) & SVf_FAKE)
199     && *SvPVX(namesv) == '&'
200     && CvCLONE(ppad[ix]))
201     {
202     CV *kid = cv_clone((CV*)ppad[ix]);
203     SvREFCNT_dec(ppad[ix]);
204     CvCLONE_on(kid);
205     SvPADMY_on(kid);
206     npad[ix] = (SV*)kid;
207     }
208     }
209     #endif
210    
211     return newpadlist;
212     }
213    
214 root 1.7 #ifdef MAY_FLUSH
215 root 1.3 STATIC AV *
216     free_padlist (AV *padlist)
217     {
218     /* may be during global destruction */
219     if (SvREFCNT(padlist))
220     {
221     I32 i = AvFILLp(padlist);
222     while (i >= 0)
223     {
224     SV **svp = av_fetch(padlist, i--, FALSE);
225     SV *sv = svp ? *svp : Nullsv;
226     if (sv)
227     SvREFCNT_dec(sv);
228     }
229    
230     SvREFCNT_dec((SV*)padlist);
231     }
232     }
233 root 1.7 #endif
234 root 1.3
235 root 1.7 /* the next two functions merely cache the padlists */
236 root 1.4 STATIC void
237     get_padlist (CV *cv)
238 root 1.3 {
239 root 1.4 SV **he = hv_fetch (padlist_cache, (void *)&cv, sizeof (CV *), 0);
240    
241     if (he && AvFILLp ((AV *)*he) >= 0)
242     CvPADLIST (cv) = (AV *)av_pop ((AV *)*he);
243     else
244     CvPADLIST (cv) = clone_padlist (CvPADLIST (cv));
245     }
246    
247     STATIC void
248     put_padlist (CV *cv)
249     {
250     SV **he = hv_fetch (padlist_cache, (void *)&cv, sizeof (CV *), 1);
251    
252     if (SvTYPE (*he) != SVt_PVAV)
253     {
254     SvREFCNT_dec (*he);
255     *he = (SV *)newAV ();
256     }
257    
258     av_push ((AV *)*he, (SV *)CvPADLIST (cv));
259 root 1.3 }
260    
261 root 1.7 #ifdef MAY_FLUSH
262     STATIC void
263     flush_padlist_cache ()
264     {
265     HV *hv = padlist_cache;
266     padlist_cache = newHV ();
267    
268     if (hv_iterinit (hv))
269     {
270     HE *he;
271     AV *padlist;
272    
273     while (!!(he = hv_iternext (hv)))
274     {
275     AV *av = (AV *)HeVAL(he);
276    
277     /* casting is fun. */
278     while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
279     free_padlist (padlist);
280     }
281     }
282    
283     SvREFCNT_dec (hv);
284     }
285     #endif
286    
287     #define SB do {
288     #define SE } while (0)
289    
290 root 1.13 #define LOAD(state) SB load_state(aTHX_ (state)); SPAGAIN; SE
291     #define SAVE(state,flags) SB PUTBACK; save_state(aTHX_ (state),(flags)); SE
292 root 1.7
293     #define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); SE
294    
295     static void
296     load_state(pTHX_ Coro__State c)
297     {
298     PL_dowarn = c->dowarn;
299 root 1.19 PL_in_eval = c->in_eval;
300 root 1.7
301     PL_curstackinfo = c->curstackinfo;
302     PL_curstack = c->curstack;
303     PL_mainstack = c->mainstack;
304     PL_stack_sp = c->stack_sp;
305     PL_op = c->op;
306     PL_curpad = c->curpad;
307     PL_stack_base = c->stack_base;
308     PL_stack_max = c->stack_max;
309     PL_tmps_stack = c->tmps_stack;
310     PL_tmps_floor = c->tmps_floor;
311     PL_tmps_ix = c->tmps_ix;
312     PL_tmps_max = c->tmps_max;
313     PL_markstack = c->markstack;
314     PL_markstack_ptr = c->markstack_ptr;
315     PL_markstack_max = c->markstack_max;
316     PL_scopestack = c->scopestack;
317     PL_scopestack_ix = c->scopestack_ix;
318     PL_scopestack_max = c->scopestack_max;
319     PL_savestack = c->savestack;
320     PL_savestack_ix = c->savestack_ix;
321     PL_savestack_max = c->savestack_max;
322     PL_retstack = c->retstack;
323     PL_retstack_ix = c->retstack_ix;
324     PL_retstack_max = c->retstack_max;
325     PL_curcop = c->curcop;
326 root 1.13 PL_top_env = c->top_env;
327 root 1.7
328     if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav);
329     if (c->defsv) REPLACE_SV (DEFSV , c->defsv);
330     if (c->errsv) REPLACE_SV (ERRSV , c->errsv);
331    
332     {
333     dSP;
334     CV *cv;
335    
336     /* now do the ugly restore mess */
337     while ((cv = (CV *)POPs))
338     {
339     AV *padlist = (AV *)POPs;
340    
341     if (padlist)
342     {
343     put_padlist (cv); /* mark this padlist as available */
344     CvPADLIST(cv) = padlist;
345     #ifdef USE_THREADS
346     /*CvOWNER(cv) = (struct perl_thread *)POPs;*/
347     #endif
348     }
349    
350     ++CvDEPTH(cv);
351     }
352    
353     PUTBACK;
354     }
355     }
356    
357 root 1.3 static void
358 root 1.7 save_state(pTHX_ Coro__State c, int flags)
359 root 1.3 {
360     {
361     dSP;
362     I32 cxix = cxstack_ix;
363 root 1.11 PERL_CONTEXT *ccstk = cxstack;
364 root 1.3 PERL_SI *top_si = PL_curstackinfo;
365    
366     /*
367     * the worst thing you can imagine happens first - we have to save
368     * (and reinitialize) all cv's in the whole callchain :(
369     */
370    
371     PUSHs (Nullsv);
372     /* this loop was inspired by pp_caller */
373     for (;;)
374     {
375 root 1.11 do
376 root 1.3 {
377 root 1.4 PERL_CONTEXT *cx = &ccstk[cxix--];
378 root 1.3
379     if (CxTYPE(cx) == CXt_SUB)
380     {
381     CV *cv = cx->blk_sub.cv;
382     if (CvDEPTH(cv))
383     {
384     #ifdef USE_THREADS
385 root 1.7 /*XPUSHs ((SV *)CvOWNER(cv));*/
386     /*CvOWNER(cv) = 0;*/
387     /*error must unlock this cv etc.. etc...*/
388 root 1.3 #endif
389 root 1.7 EXTEND (SP, CvDEPTH(cv)*2);
390    
391     while (--CvDEPTH(cv))
392     {
393     /* this tells the restore code to increment CvDEPTH */
394     PUSHs (Nullsv);
395     PUSHs ((SV *)cv);
396     }
397    
398 root 1.3 PUSHs ((SV *)CvPADLIST(cv));
399     PUSHs ((SV *)cv);
400    
401 root 1.7 get_padlist (cv); /* this is a monster */
402 root 1.3 }
403     }
404     else if (CxTYPE(cx) == CXt_FORMAT)
405     {
406     /* I never used formats, so how should I know how these are implemented? */
407     /* my bold guess is as a simple, plain sub... */
408     croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats");
409     }
410     }
411 root 1.7 while (cxix >= 0);
412 root 1.3
413     if (top_si->si_type == PERLSI_MAIN)
414     break;
415    
416     top_si = top_si->si_prev;
417     ccstk = top_si->si_cxstack;
418     cxix = top_si->si_cxix;
419     }
420    
421     PUTBACK;
422     }
423    
424 root 1.12 c->defav = flags & TRANSFER_SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0;
425     c->defsv = flags & TRANSFER_SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0;
426     c->errsv = flags & TRANSFER_SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0;
427 root 1.7
428 root 1.11 /* I have not the slightest idea of why av_reify is necessary */
429     /* but if it's missing the defav contents magically get replaced sometimes */
430     if (c->defav)
431     av_reify (c->defav);
432    
433 root 1.3 c->dowarn = PL_dowarn;
434 root 1.19 c->in_eval = PL_in_eval;
435 root 1.7
436 root 1.3 c->curstackinfo = PL_curstackinfo;
437     c->curstack = PL_curstack;
438     c->mainstack = PL_mainstack;
439     c->stack_sp = PL_stack_sp;
440     c->op = PL_op;
441     c->curpad = PL_curpad;
442     c->stack_base = PL_stack_base;
443     c->stack_max = PL_stack_max;
444     c->tmps_stack = PL_tmps_stack;
445     c->tmps_floor = PL_tmps_floor;
446     c->tmps_ix = PL_tmps_ix;
447     c->tmps_max = PL_tmps_max;
448     c->markstack = PL_markstack;
449     c->markstack_ptr = PL_markstack_ptr;
450     c->markstack_max = PL_markstack_max;
451     c->scopestack = PL_scopestack;
452     c->scopestack_ix = PL_scopestack_ix;
453     c->scopestack_max = PL_scopestack_max;
454     c->savestack = PL_savestack;
455     c->savestack_ix = PL_savestack_ix;
456     c->savestack_max = PL_savestack_max;
457     c->retstack = PL_retstack;
458     c->retstack_ix = PL_retstack_ix;
459     c->retstack_max = PL_retstack_max;
460     c->curcop = PL_curcop;
461 root 1.13 c->top_env = PL_top_env;
462     }
463    
464     /*
465     * allocate various perl stacks. This is an exact copy
466     * of perl.c:init_stacks, except that it uses less memory
467     * on the assumption that coroutines do not usually need
468     * a lot of stackspace.
469     */
470     STATIC void
471     coro_init_stacks (pTHX)
472     {
473     PL_curstackinfo = new_stackinfo(96, 1024/sizeof(PERL_CONTEXT) - 1);
474     PL_curstackinfo->si_type = PERLSI_MAIN;
475     PL_curstack = PL_curstackinfo->si_stack;
476     PL_mainstack = PL_curstack; /* remember in case we switch stacks */
477    
478     PL_stack_base = AvARRAY(PL_curstack);
479     PL_stack_sp = PL_stack_base;
480     PL_stack_max = PL_stack_base + AvMAX(PL_curstack);
481    
482 root 1.15 New(50,PL_tmps_stack,96,SV*);
483 root 1.13 PL_tmps_floor = -1;
484     PL_tmps_ix = -1;
485 root 1.15 PL_tmps_max = 96;
486 root 1.13
487 root 1.15 New(54,PL_markstack,16,I32);
488 root 1.13 PL_markstack_ptr = PL_markstack;
489 root 1.15 PL_markstack_max = PL_markstack + 16;
490 root 1.13
491     SET_MARK_OFFSET;
492    
493 root 1.15 New(54,PL_scopestack,16,I32);
494 root 1.13 PL_scopestack_ix = 0;
495 root 1.15 PL_scopestack_max = 16;
496 root 1.13
497 root 1.15 New(54,PL_savestack,96,ANY);
498 root 1.13 PL_savestack_ix = 0;
499 root 1.15 PL_savestack_max = 96;
500 root 1.13
501     New(54,PL_retstack,8,OP*);
502     PL_retstack_ix = 0;
503     PL_retstack_max = 8;
504 root 1.3 }
505 root 1.1
506 root 1.7 /*
507     * destroy the stacks, the callchain etc...
508     * still there is a memleak of 128 bytes...
509     */
510 root 1.1 STATIC void
511 root 1.4 destroy_stacks(pTHX)
512 root 1.1 {
513 root 1.4 /* is this ugly, I ask? */
514     while (PL_scopestack_ix)
515     LEAVE;
516    
517 root 1.7 /* sure it is, but more important: is it correct?? :/ */
518     while (PL_tmps_ix > PL_tmps_floor) /* should only ever be one iteration */
519     FREETMPS;
520    
521 root 1.4 while (PL_curstackinfo->si_next)
522     PL_curstackinfo = PL_curstackinfo->si_next;
523    
524     while (PL_curstackinfo)
525     {
526     PERL_SI *p = PL_curstackinfo->si_prev;
527    
528 root 1.7 {
529     dSP;
530     SWITCHSTACK (PL_curstack, PL_curstackinfo->si_stack);
531     PUTBACK; /* possibly superfluous */
532     }
533    
534     dounwind(-1);
535    
536 root 1.4 SvREFCNT_dec(PL_curstackinfo->si_stack);
537     Safefree(PL_curstackinfo->si_cxstack);
538     Safefree(PL_curstackinfo);
539     PL_curstackinfo = p;
540     }
541    
542     Safefree(PL_tmps_stack);
543     Safefree(PL_markstack);
544     Safefree(PL_scopestack);
545     Safefree(PL_savestack);
546     Safefree(PL_retstack);
547 root 1.1 }
548    
549 root 1.13 static void
550 root 1.15 allocate_stack (Coro__State ctx, int alloc)
551 root 1.13 {
552 root 1.15 coro_stack *stack;
553    
554     New (0, stack, 1, coro_stack);
555    
556     stack->refcnt = 1;
557     stack->usecnt = 1;
558     stack->gencnt = ctx->gencnt = 0;
559     if (alloc)
560     {
561 root 1.16 #ifdef HAVE_MMAP
562 root 1.17 stack->ssize = 128 * 1024 * sizeof (long); /* mmap should do allocate-on-write for us */
563 root 1.15 stack->sptr = mmap (0, stack->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
564     if (stack->sptr == (void *)-1)
565 root 1.13 #endif
566 root 1.15 {
567     /*FIXME*//*D*//* reasonable stack size! */
568     stack->ssize = -4096 * sizeof (long);
569     New (0, stack->sptr, 4096, long);
570     }
571 root 1.13 }
572 root 1.15 else
573     stack->sptr = 0;
574    
575     ctx->stack = stack;
576 root 1.13 }
577    
578     static void
579     deallocate_stack (Coro__State ctx)
580     {
581 root 1.15 coro_stack *stack = ctx->stack;
582    
583     ctx->stack = 0;
584    
585     if (stack)
586     {
587     if (!--stack->refcnt)
588     {
589 root 1.13 #ifdef HAVE_MMAP
590 root 1.15 if (stack->ssize > 0 && stack->sptr)
591     munmap (stack->sptr, stack->ssize);
592     else
593 root 1.13 #else
594 root 1.15 Safefree (stack->sptr);
595 root 1.13 #endif
596 root 1.15 Safefree (stack);
597     }
598     else if (ctx->gencnt == stack->gencnt)
599     --stack->usecnt;
600     }
601 root 1.13 }
602    
603     static void
604     setup_coro (void *arg)
605     {
606     /*
607     * emulate part of the perl startup here.
608     */
609     dSP;
610     Coro__State ctx = (Coro__State)arg;
611     SV *sub_init = (SV*)get_cv(SUB_INIT, FALSE);
612    
613     coro_init_stacks (aTHX);
614     /*PL_curcop = 0;*/
615 root 1.19 /*PL_in_eval = PL_in_eval;*/ /* inherit */
616 root 1.13 SvREFCNT_dec (GvAV (PL_defgv));
617     GvAV (PL_defgv) = ctx->args;
618    
619 root 1.19 SPAGAIN;
620    
621 root 1.15 if (ctx->stack)
622 root 1.13 {
623 root 1.15 ctx->cursp = 0;
624    
625 root 1.13 PUSHMARK(SP);
626     PUTBACK;
627 root 1.19 (void) call_sv (sub_init, G_VOID|G_NOARGS|G_EVAL);
628    
629     if (SvTRUE (ERRSV))
630     croak (NULL);
631     else
632     croak ("FATAL: CCTXT coroutine returned!");
633 root 1.13 }
634     else
635     {
636     UNOP myop;
637    
638     PL_op = (OP *)&myop;
639    
640     Zero(&myop, 1, UNOP);
641     myop.op_next = Nullop;
642     myop.op_flags = OPf_WANT_VOID;
643    
644     PUSHMARK(SP);
645     XPUSHs (sub_init);
646     /*
647     * the next line is slightly wrong, as PL_op->op_next
648     * is actually being executed so we skip the first op.
649     * that doesn't matter, though, since it is only
650     * pp_nextstate and we never return...
651     * ah yes, and I don't care anyways ;)
652     */
653     PUTBACK;
654     PL_op = pp_entersub();
655     SPAGAIN;
656    
657     ENTER; /* necessary e.g. for dounwind */
658     }
659     }
660    
661 root 1.15 static void
662     continue_coro (void *arg)
663     {
664     /*
665     * this is a _very_ stripped down perl interpreter ;)
666     */
667     Coro__State ctx = (Coro__State)arg;
668    
669 root 1.19 /*FIXME*//* must set up top_env here */
670 root 1.15 ctx->cursp = 0;
671     PL_op = PL_op->op_next;
672     CALLRUNOPS(aTHX);
673 root 1.19
674 root 1.15 abort ();
675     }
676    
677 root 1.8 STATIC void
678     transfer(pTHX_ struct coro *prev, struct coro *next, int flags)
679     {
680     dSP;
681 root 1.15 dSTACKLEVEL;
682 root 1.8
683     if (prev != next)
684     {
685     if (next->mainstack)
686     {
687     SAVE (prev, flags);
688     LOAD (next);
689 root 1.13
690 root 1.8 /* mark this state as in-use */
691     next->mainstack = 0;
692     next->tmps_ix = -2;
693 root 1.13
694 root 1.15 /* stacklevel changed? if yes, grab the stack for us! */
695 root 1.13 if (flags & TRANSFER_SAVE_CCTXT)
696     {
697 root 1.15 if (!prev->stack)
698     allocate_stack (prev, 0);
699     else if (prev->cursp != stacklevel
700     && prev->stack->usecnt > 1)
701     {
702     prev->gencnt = ++prev->stack->gencnt;
703     prev->stack->usecnt = 1;
704     }
705 root 1.13
706 root 1.15 /* has our stack been invalidated? */
707     if (next->stack && next->stack->gencnt != next->gencnt)
708     {
709     deallocate_stack (next);
710     allocate_stack (next, 1);
711     coro_create (&(next->stack->cctx),
712     continue_coro, (void *)next,
713     next->stack->sptr, labs (next->stack->ssize));
714     }
715 root 1.13
716 root 1.15 coro_transfer (&(prev->stack->cctx), &(next->stack->cctx));
717 root 1.13 }
718    
719 root 1.8 }
720     else if (next->tmps_ix == -2)
721 root 1.13 croak ("tried to transfer to running coroutine");
722 root 1.8 else
723     {
724     SAVE (prev, -1); /* first get rid of the old state */
725    
726 root 1.13 if (flags & TRANSFER_SAVE_CCTXT)
727     {
728 root 1.15 if (!prev->stack)
729     allocate_stack (prev, 0);
730    
731     if (prev->stack->sptr && flags & TRANSFER_LAZY_STACK)
732     {
733     setup_coro (next);
734    
735     prev->stack->refcnt++;
736     prev->stack->usecnt++;
737     next->stack = prev->stack;
738     next->gencnt = prev->gencnt;
739     }
740     else
741 root 1.13 {
742 root 1.15 allocate_stack (next, 1);
743     coro_create (&(next->stack->cctx),
744 root 1.13 setup_coro, (void *)next,
745 root 1.15 next->stack->sptr, labs (next->stack->ssize));
746     coro_transfer (&(prev->stack->cctx), &(next->stack->cctx));
747 root 1.13 }
748     }
749     else
750     setup_coro (next);
751 root 1.8 }
752     }
753 root 1.15
754     next->cursp = stacklevel;
755 root 1.8 }
756 root 1.3
757 root 1.21 static struct coro *
758     sv_to_coro (SV *arg, const char *funcname, const char *varname)
759     {
760     if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVHV)
761     {
762     HE *he = hv_fetch_ent((HV *)SvRV(arg), ucoro_state_sv, 0, ucoro_state_hash);
763    
764     if (!he)
765     croak ("%s() -- %s is a hashref but lacks the " UCORO_STATE " key", funcname, varname);
766    
767     arg = HeVAL(he);
768     }
769    
770     /* must also be changed inside Coro::Cont::yield */
771     if (SvROK(arg) && SvSTASH(SvRV(arg)) == coro_state_stash)
772     return (struct coro *) SvIV((SV*)SvRV(arg));
773     else
774     croak ("%s() -- %s is not (and contains not) a Coro::State object", funcname, varname);
775     }
776    
777 root 1.3 MODULE = Coro::State PACKAGE = Coro::State
778 root 1.1
779     PROTOTYPES: ENABLE
780    
781 root 1.3 BOOT:
782 root 1.11 { /* {} necessary for stoopid perl-5.6.x */
783 root 1.14 ucoro_state_sv = newSVpv (UCORO_STATE, sizeof(UCORO_STATE) - 1);
784     PERL_HASH(ucoro_state_hash, UCORO_STATE, sizeof(UCORO_STATE) - 1);
785     coro_state_stash = gv_stashpv ("Coro::State", TRUE);
786 root 1.7
787 root 1.13 newCONSTSUB (coro_state_stash, "SAVE_DEFAV", newSViv (TRANSFER_SAVE_DEFAV));
788     newCONSTSUB (coro_state_stash, "SAVE_DEFSV", newSViv (TRANSFER_SAVE_DEFSV));
789     newCONSTSUB (coro_state_stash, "SAVE_ERRSV", newSViv (TRANSFER_SAVE_ERRSV));
790     newCONSTSUB (coro_state_stash, "SAVE_CCTXT", newSViv (TRANSFER_SAVE_CCTXT));
791 root 1.7
792 root 1.3 if (!padlist_cache)
793     padlist_cache = newHV ();
794 root 1.12
795     main_mainstack = PL_mainstack;
796 root 1.9 }
797 root 1.3
798 root 1.1 Coro::State
799 root 1.3 _newprocess(args)
800     SV * args
801     PROTOTYPE: $
802 root 1.1 CODE:
803     Coro__State coro;
804 root 1.3
805     if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV)
806 root 1.7 croak ("Coro::State::_newprocess expects an arrayref");
807 root 1.1
808     New (0, coro, 1, struct coro);
809    
810 root 1.13 coro->args = (AV *)SvREFCNT_inc (SvRV (args));
811 root 1.1 coro->mainstack = 0; /* actual work is done inside transfer */
812 root 1.15 coro->stack = 0;
813 root 1.1
814     RETVAL = coro;
815     OUTPUT:
816     RETVAL
817    
818     void
819 root 1.21 transfer(prev, next, flags)
820 root 1.3 Coro::State_or_hashref prev
821     Coro::State_or_hashref next
822 root 1.7 int flags
823 root 1.8 PROTOTYPE: @
824 root 1.1 CODE:
825 root 1.20 PUTBACK;
826 root 1.8 transfer (aTHX_ prev, next, flags);
827 root 1.20 SPAGAIN;
828 root 1.1
829     void
830     DESTROY(coro)
831 root 1.3 Coro::State coro
832 root 1.1 CODE:
833    
834 root 1.12 if (coro->mainstack && coro->mainstack != main_mainstack)
835 root 1.1 {
836     struct coro temp;
837    
838 root 1.12 SAVE(aTHX_ (&temp), TRANSFER_SAVE_ALL);
839 root 1.3 LOAD(aTHX_ coro);
840 root 1.1
841 root 1.13 destroy_stacks (aTHX);
842 root 1.1
843 root 1.7 LOAD((&temp)); /* this will get rid of defsv etc.. */
844 root 1.13
845     coro->mainstack = 0;
846     }
847    
848 root 1.15 deallocate_stack (coro);
849 root 1.1
850     Safefree (coro);
851 root 1.12
852 root 1.7 void
853     flush()
854     CODE:
855     #ifdef MAY_FLUSH
856     flush_padlist_cache ();
857 root 1.20 #endif
858    
859     void
860     _exit(code)
861     int code
862     PROTOTYPE: $
863     CODE:
864     #if defined(__GLIBC__) || _POSIX_C_SOURCE
865     _exit (code);
866     #else
867     signal (SIGTERM, SIG_DFL);
868     raise (SIGTERM);
869     exit (code);
870 root 1.7 #endif
871 root 1.1
872 root 1.8 MODULE = Coro::State PACKAGE = Coro::Cont
873    
874 root 1.21 # this is slightly dirty (should expose a c-level api)
875 root 1.8
876     void
877 root 1.13 yield(...)
878 root 1.8 PROTOTYPE: @
879     CODE:
880     static SV *returnstk;
881     SV *sv;
882     AV *defav = GvAV (PL_defgv);
883     struct coro *prev, *next;
884    
885     if (!returnstk)
886     returnstk = SvRV (get_sv ("Coro::Cont::return", FALSE));
887    
888 root 1.11 /* set up @_ -- ugly */
889 root 1.8 av_clear (defav);
890     av_fill (defav, items - 1);
891     while (items--)
892     av_store (defav, items, SvREFCNT_inc (ST(items)));
893    
894     mg_get (returnstk); /* isn't documentation wrong for mg_get? */
895     sv = av_pop ((AV *)SvRV (returnstk));
896     prev = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 0, 0)));
897     next = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0)));
898     SvREFCNT_dec (sv);
899 root 1.13
900     transfer(aTHX_ prev, next, 0);
901 root 1.1
902 root 1.21 MODULE = Coro::State PACKAGE = Coro
903    
904     # this is slightly dirty (should expose a c-level api)
905    
906     BOOT:
907     {
908     coro_current = gv_fetchpv ("Coro::current", TRUE, SVt_PV);
909     coro_ready = newAV ();
910     coro_idle = gv_fetchpv ("Coro::idle" , TRUE, SVt_PV);
911     }
912    
913     void
914     ready(self)
915     SV * self
916     CODE:
917     av_push (coro_ready, SvREFCNT_inc (self));
918    
919     void
920     schedule(...)
921     ALIAS:
922     cede = 1
923     CODE:
924     SV *prev = GvSV (coro_current);
925     SV *next = av_shift (coro_ready);
926    
927     if (next == &PL_sv_undef)
928     next = SvREFCNT_inc (GvSV (coro_idle));
929    
930     if (ix)
931     av_push (coro_ready, SvREFCNT_inc (prev));
932    
933     GvSV (coro_current) = SvREFCNT_inc (next);
934     transfer (sv_to_coro (prev, "Coro::schedule", "current coroutine"),
935     sv_to_coro (next, "Coro::schedule", "next coroutine"),
936     TRANSFER_SAVE_ALL | TRANSFER_LAZY_STACK);
937     SvREFCNT_dec (next);
938     SvREFCNT_dec (prev);
939