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