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.3 by root, Tue Jul 17 00:24:15 2001 UTC vs.
Revision 1.68 by root, Mon Dec 12 20:28:30 2005 UTC

1#define PERL_NO_GET_CONTEXT
2
3#include "libcoro/coro.c"
4
1#include "EXTERN.h" 5#include "EXTERN.h"
2#include "perl.h" 6#include "perl.h"
3#include "XSUB.h" 7#include "XSUB.h"
4 8
5#if 0 9#include "patchlevel.h"
6# define CHK(x) (void *)0 10
11#if PERL_VERSION < 6
12# ifndef PL_ppaddr
13# define PL_ppaddr ppaddr
14# endif
15# ifndef call_sv
16# define call_sv perl_call_sv
17# endif
18# ifndef get_sv
19# define get_sv perl_get_sv
20# endif
21# ifndef get_cv
22# define get_cv perl_get_cv
23# endif
24# ifndef IS_PADGV
25# define IS_PADGV(v) 0
26# endif
27# ifndef IS_PADCONST
28# define IS_PADCONST(v) 0
29# endif
30#endif
31
32#include <signal.h>
33
34#ifdef HAVE_MMAP
35# include <unistd.h>
36# include <sys/mman.h>
37# ifndef MAP_ANONYMOUS
38# ifdef MAP_ANON
39# define MAP_ANONYMOUS MAP_ANON
40# else
41# undef HAVE_MMAP
42# endif
43# endif
44#endif
45
46#define SUB_INIT "Coro::State::initialize"
47#define UCORO_STATE "_coro_state"
48
49/* The next macro should declare a variable stacklevel that contains and approximation
50 * to the current C stack pointer. Its property is that it changes with each call
51 * and should be unique. */
52#define dSTACKLEVEL void *stacklevel = &stacklevel
53
54#define IN_DESTRUCT (PL_main_cv == Nullcv)
55
56#define labs(l) ((l) >= 0 ? (l) : -(l))
57
58#include "CoroAPI.h"
59
60#ifdef USE_ITHREADS
61static perl_mutex coro_mutex;
62# define LOCK do { MUTEX_LOCK (&coro_mutex); } while (0)
63# define UNLOCK do { MUTEX_UNLOCK (&coro_mutex); } while (0)
7#else 64#else
8# define CHK(x) if (!(x)) croak("FATAL, CHK: " #x) 65# define LOCK 0
66# define UNLOCK 0
9#endif 67#endif
10 68
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 */
75
76/* this is actually not only the c stack but also c registers etc... */
77typedef struct {
78 int refcnt; /* pointer reference counter */
79 int usecnt; /* shared by how many coroutines */
80 int gencnt; /* generation counter */
81
82 coro_context cctx;
83
84 void *sptr;
85 long ssize; /* positive == mmap, otherwise malloc */
86} coro_stack;
87
11struct coro { 88struct coro {
89 /* the top-level JMPENV for each coroutine, needed to catch dies. */
90 JMPENV start_env;
91
92 /* the optional C context */
93 coro_stack *stack;
94 void *cursp;
95 int gencnt;
96
97 /* optionally saved, might be zero */
98 AV *defav;
99 SV *defsv;
100 SV *errsv;
101
102 /* saved global state not related to stacks */
12 U8 dowarn; 103 U8 dowarn;
13 AV *defav; 104 I32 in_eval;
14 105
106 /* the stacks and related info (callchain etc..) */
15 PERL_SI *curstackinfo; 107 PERL_SI *curstackinfo;
16 AV *curstack; 108 AV *curstack;
17 AV *mainstack; 109 AV *mainstack;
18 SV **stack_sp; 110 SV **stack_sp;
19 OP *op; 111 OP *op;
20 SV **curpad; 112 SV **curpad;
113 AV *comppad;
114 CV *compcv;
21 SV **stack_base; 115 SV **stack_base;
22 SV **stack_max; 116 SV **stack_max;
23 SV **tmps_stack; 117 SV **tmps_stack;
24 I32 tmps_floor; 118 I32 tmps_floor;
25 I32 tmps_ix; 119 I32 tmps_ix;
34 I32 savestack_ix; 128 I32 savestack_ix;
35 I32 savestack_max; 129 I32 savestack_max;
36 OP **retstack; 130 OP **retstack;
37 I32 retstack_ix; 131 I32 retstack_ix;
38 I32 retstack_max; 132 I32 retstack_max;
133 PMOP *curpm;
39 COP *curcop; 134 COP *curcop;
135 JMPENV *top_env;
40 136
137 /* data associated with this coroutine (initial args) */
41 AV *args; 138 AV *args;
42}; 139};
43 140
44typedef struct coro *Coro__State; 141typedef struct coro *Coro__State;
45typedef struct coro *Coro__State_or_hashref; 142typedef struct coro *Coro__State_or_hashref;
46 143
47static HV *padlist_cache;
48
49/* mostly copied from op.c:cv_clone2 */ 144/* mostly copied from op.c:cv_clone2 */
50STATIC AV * 145STATIC AV *
51clone_padlist (AV *protopadlist) 146clone_padlist (pTHX_ AV *protopadlist)
52{ 147{
53 AV *av; 148 AV *av;
54 I32 ix; 149 I32 ix;
55 AV *protopad_name = (AV *) * av_fetch (protopadlist, 0, FALSE); 150 AV *protopad_name = (AV *) * av_fetch (protopadlist, 0, FALSE);
56 AV *protopad = (AV *) * av_fetch (protopadlist, 1, FALSE); 151 AV *protopad = (AV *) * av_fetch (protopadlist, 1, FALSE);
80 AvFLAGS (av) = AVf_REIFY; 175 AvFLAGS (av) = AVf_REIFY;
81 176
82 for (ix = fpad; ix > 0; ix--) 177 for (ix = fpad; ix > 0; ix--)
83 { 178 {
84 SV *namesv = (ix <= fname) ? pname[ix] : Nullsv; 179 SV *namesv = (ix <= fname) ? pname[ix] : Nullsv;
180
85 if (namesv && namesv != &PL_sv_undef) 181 if (namesv && namesv != &PL_sv_undef)
86 { 182 {
87 char *name = SvPVX (namesv); /* XXX */ 183 char *name = SvPVX (namesv); /* XXX */
184
88 if (SvFLAGS (namesv) & SVf_FAKE || *name == '&') 185 if (SvFLAGS (namesv) & SVf_FAKE || *name == '&')
89 { /* lexical from outside? */ 186 { /* lexical from outside? */
90 npad[ix] = SvREFCNT_inc (ppad[ix]); 187 npad[ix] = SvREFCNT_inc (ppad[ix]);
91 } 188 }
92 else 189 else
98 sv = (SV *) newAV (); 195 sv = (SV *) newAV ();
99 else if (*name == '%') 196 else if (*name == '%')
100 sv = (SV *) newHV (); 197 sv = (SV *) newHV ();
101 else 198 else
102 sv = NEWSV (0, 0); 199 sv = NEWSV (0, 0);
200
201#ifdef SvPADBUSY
103 if (!SvPADBUSY (sv)) 202 if (!SvPADBUSY (sv))
203#endif
104 SvPADMY_on (sv); 204 SvPADMY_on (sv);
205
105 npad[ix] = sv; 206 npad[ix] = sv;
106 } 207 }
107 } 208 }
108 else if (IS_PADGV (ppad[ix]) || IS_PADCONST (ppad[ix])) 209 else if (IS_PADGV (ppad[ix]) || IS_PADCONST (ppad[ix]))
109 { 210 {
115 SvPADTMP_on (sv); 216 SvPADTMP_on (sv);
116 npad[ix] = sv; 217 npad[ix] = sv;
117 } 218 }
118 } 219 }
119 220
120#if 0 /* NONOTUNDERSTOOD */ 221#if 0 /* return -ENOTUNDERSTOOD */
121 /* Now that vars are all in place, clone nested closures. */ 222 /* Now that vars are all in place, clone nested closures. */
122 223
123 for (ix = fpad; ix > 0; ix--) { 224 for (ix = fpad; ix > 0; ix--) {
124 SV* namesv = (ix <= fname) ? pname[ix] : Nullsv; 225 SV* namesv = (ix <= fname) ? pname[ix] : Nullsv;
125 if (namesv 226 if (namesv
138#endif 239#endif
139 240
140 return newpadlist; 241 return newpadlist;
141} 242}
142 243
143STATIC AV * 244STATIC void
144free_padlist (AV *padlist) 245free_padlist (pTHX_ AV *padlist)
145{ 246{
146 /* may be during global destruction */ 247 /* may be during global destruction */
147 if (SvREFCNT(padlist)) 248 if (SvREFCNT (padlist))
148 { 249 {
149 I32 i = AvFILLp(padlist); 250 I32 i = AvFILLp (padlist);
150 while (i >= 0) 251 while (i >= 0)
151 { 252 {
152 SV **svp = av_fetch(padlist, i--, FALSE); 253 SV **svp = av_fetch (padlist, i--, FALSE);
153 SV *sv = svp ? *svp : Nullsv;
154 if (sv) 254 if (svp)
255 {
256 SV *sv;
257 while (&PL_sv_undef != (sv = av_pop ((AV *)*svp)))
155 SvREFCNT_dec(sv); 258 SvREFCNT_dec (sv);
259
260 SvREFCNT_dec (*svp);
261 }
156 } 262 }
157 263
158 SvREFCNT_dec((SV*)padlist); 264 SvREFCNT_dec ((SV*)padlist);
265 }
266}
267
268STATIC int
269coro_cv_free (pTHX_ SV *sv, MAGIC *mg)
270{
271 AV *padlist;
272 AV *av = (AV *)mg->mg_obj;
273
274 /* casting is fun. */
275 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
276 free_padlist (aTHX_ padlist);
277
278 SvREFCNT_dec (av);
279}
280
281#define PERL_MAGIC_coro PERL_MAGIC_ext
282
283static MGVTBL vtbl_coro = {0, 0, 0, 0, coro_cv_free};
284
285/* the next two functions merely cache the padlists */
286STATIC void
287get_padlist (pTHX_ CV *cv)
288{
289 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
290
291 if (mg && AvFILLp ((AV *)mg->mg_obj) >= 0)
292 CvPADLIST (cv) = (AV *)av_pop ((AV *)mg->mg_obj);
293 else
294 CvPADLIST (cv) = clone_padlist (aTHX_ CvPADLIST (cv));
295}
296
297STATIC void
298put_padlist (pTHX_ CV *cv)
299{
300 MAGIC *mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
301
302 if (!mg)
303 {
304 sv_magic ((SV *)cv, 0, PERL_MAGIC_coro, 0, 0);
305 mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
306 mg->mg_virtual = &vtbl_coro;
307 mg->mg_obj = (SV *)newAV ();
308 }
309
310 av_push ((AV *)mg->mg_obj, (SV *)CvPADLIST (cv));
311}
312
313#define SB do {
314#define SE } while (0)
315
316#define LOAD(state) load_state(aTHX_ (state));
317#define SAVE(state,flags) save_state(aTHX_ (state),(flags));
318
319#define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); (val) = 0; SE
320
321static void
322load_state(pTHX_ Coro__State c)
323{
324 PL_dowarn = c->dowarn;
325 PL_in_eval = c->in_eval;
326
327 PL_curstackinfo = c->curstackinfo;
328 PL_curstack = c->curstack;
329 PL_mainstack = c->mainstack;
330 PL_stack_sp = c->stack_sp;
331 PL_op = c->op;
332 PL_curpad = c->curpad;
333 PL_comppad = c->comppad;
334 PL_compcv = c->compcv;
335 PL_stack_base = c->stack_base;
336 PL_stack_max = c->stack_max;
337 PL_tmps_stack = c->tmps_stack;
338 PL_tmps_floor = c->tmps_floor;
339 PL_tmps_ix = c->tmps_ix;
340 PL_tmps_max = c->tmps_max;
341 PL_markstack = c->markstack;
342 PL_markstack_ptr = c->markstack_ptr;
343 PL_markstack_max = c->markstack_max;
344 PL_scopestack = c->scopestack;
345 PL_scopestack_ix = c->scopestack_ix;
346 PL_scopestack_max = c->scopestack_max;
347 PL_savestack = c->savestack;
348 PL_savestack_ix = c->savestack_ix;
349 PL_savestack_max = c->savestack_max;
350 PL_retstack = c->retstack;
351 PL_retstack_ix = c->retstack_ix;
352 PL_retstack_max = c->retstack_max;
353 PL_curpm = c->curpm;
354 PL_curcop = c->curcop;
355 PL_top_env = c->top_env;
356
357 if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav);
358 if (c->defsv) REPLACE_SV (DEFSV , c->defsv);
359 if (c->errsv) REPLACE_SV (ERRSV , c->errsv);
360
361 {
362 dSP;
363 CV *cv;
364
365 /* now do the ugly restore mess */
366 while ((cv = (CV *)POPs))
367 {
368 AV *padlist = (AV *)POPs;
369
370 if (padlist)
371 {
372 put_padlist (aTHX_ cv); /* mark this padlist as available */
373 CvPADLIST(cv) = padlist;
374 }
375
376 ++CvDEPTH(cv);
377 }
378
379 PUTBACK;
159 } 380 }
160} 381}
161 382
162STATIC AV *
163unuse_padlist (AV *padlist)
164{
165 free_padlist (padlist);
166}
167
168static void 383static void
169SAVE(pTHX_ Coro__State c) 384save_state(pTHX_ Coro__State c, int flags)
170{ 385{
171 { 386 {
172 dSP; 387 dSP;
173 I32 cxix = cxstack_ix; 388 I32 cxix = cxstack_ix;
389 PERL_CONTEXT *ccstk = cxstack;
174 PERL_SI *top_si = PL_curstackinfo; 390 PERL_SI *top_si = PL_curstackinfo;
175 PERL_CONTEXT *ccstk = cxstack;
176 391
177 /* 392 /*
178 * the worst thing you can imagine happens first - we have to save 393 * the worst thing you can imagine happens first - we have to save
179 * (and reinitialize) all cv's in the whole callchain :( 394 * (and reinitialize) all cv's in the whole callchain :(
180 */ 395 */
183 /* this loop was inspired by pp_caller */ 398 /* this loop was inspired by pp_caller */
184 for (;;) 399 for (;;)
185 { 400 {
186 while (cxix >= 0) 401 while (cxix >= 0)
187 { 402 {
188 PERL_CONTEXT *cx = &ccstk[--cxix]; 403 PERL_CONTEXT *cx = &ccstk[cxix--];
189 404
190 if (CxTYPE(cx) == CXt_SUB) 405 if (CxTYPE(cx) == CXt_SUB)
191 { 406 {
192 CV *cv = cx->blk_sub.cv; 407 CV *cv = cx->blk_sub.cv;
193 if (CvDEPTH(cv)) 408 if (CvDEPTH(cv))
194 { 409 {
195#ifdef USE_THREADS
196 XPUSHs ((SV *)CvOWNER(cv));
197#endif
198 EXTEND (SP, 3); 410 EXTEND (SP, CvDEPTH(cv)*2);
411
412 while (--CvDEPTH(cv))
413 {
414 /* this tells the restore code to increment CvDEPTH */
415 PUSHs (Nullsv);
199 PUSHs ((SV *)CvDEPTH(cv)); 416 PUSHs ((SV *)cv);
417 }
418
200 PUSHs ((SV *)CvPADLIST(cv)); 419 PUSHs ((SV *)CvPADLIST(cv));
201 PUSHs ((SV *)cv); 420 PUSHs ((SV *)cv);
202 421
203 CvPADLIST(cv) = clone_padlist (CvPADLIST(cv)); 422 get_padlist (aTHX_ cv); /* this is a monster */
204
205 CvDEPTH(cv) = 0;
206#ifdef USE_THREADS
207 CvOWNER(cv) = 0;
208 error must unlock this cv etc.. etc...
209 if you are here wondering about this error message then
210 the reason is that it will not work as advertised yet
211#endif
212 } 423 }
213 } 424 }
425#ifdef CXt_FORMAT
214 else if (CxTYPE(cx) == CXt_FORMAT) 426 else if (CxTYPE(cx) == CXt_FORMAT)
215 { 427 {
216 /* I never used formats, so how should I know how these are implemented? */ 428 /* I never used formats, so how should I know how these are implemented? */
217 /* my bold guess is as a simple, plain sub... */ 429 /* my bold guess is as a simple, plain sub... */
218 croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats"); 430 croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats");
219 } 431 }
432#endif
220 } 433 }
221 434
222 if (top_si->si_type == PERLSI_MAIN) 435 if (top_si->si_type == PERLSI_MAIN)
223 break; 436 break;
224 437
228 } 441 }
229 442
230 PUTBACK; 443 PUTBACK;
231 } 444 }
232 445
446 c->defav = flags & TRANSFER_SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0;
447 c->defsv = flags & TRANSFER_SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0;
448 c->errsv = flags & TRANSFER_SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0;
449
233 c->dowarn = PL_dowarn; 450 c->dowarn = PL_dowarn;
234 c->defav = GvAV (PL_defgv); 451 c->in_eval = PL_in_eval;
452
235 c->curstackinfo = PL_curstackinfo; 453 c->curstackinfo = PL_curstackinfo;
236 c->curstack = PL_curstack; 454 c->curstack = PL_curstack;
237 c->mainstack = PL_mainstack; 455 c->mainstack = PL_mainstack;
238 c->stack_sp = PL_stack_sp; 456 c->stack_sp = PL_stack_sp;
239 c->op = PL_op; 457 c->op = PL_op;
240 c->curpad = PL_curpad; 458 c->curpad = PL_curpad;
459 c->comppad = PL_comppad;
460 c->compcv = PL_compcv;
241 c->stack_base = PL_stack_base; 461 c->stack_base = PL_stack_base;
242 c->stack_max = PL_stack_max; 462 c->stack_max = PL_stack_max;
243 c->tmps_stack = PL_tmps_stack; 463 c->tmps_stack = PL_tmps_stack;
244 c->tmps_floor = PL_tmps_floor; 464 c->tmps_floor = PL_tmps_floor;
245 c->tmps_ix = PL_tmps_ix; 465 c->tmps_ix = PL_tmps_ix;
254 c->savestack_ix = PL_savestack_ix; 474 c->savestack_ix = PL_savestack_ix;
255 c->savestack_max = PL_savestack_max; 475 c->savestack_max = PL_savestack_max;
256 c->retstack = PL_retstack; 476 c->retstack = PL_retstack;
257 c->retstack_ix = PL_retstack_ix; 477 c->retstack_ix = PL_retstack_ix;
258 c->retstack_max = PL_retstack_max; 478 c->retstack_max = PL_retstack_max;
479 c->curpm = PL_curpm;
259 c->curcop = PL_curcop; 480 c->curcop = PL_curcop;
481 c->top_env = PL_top_env;
482}
483
484/*
485 * allocate various perl stacks. This is an exact copy
486 * of perl.c:init_stacks, except that it uses less memory
487 * on the (sometimes correct) assumption that coroutines do
488 * not usually need a lot of stackspace.
489 */
490STATIC void
491coro_init_stacks (pTHX)
492{
493 LOCK;
494
495 PL_curstackinfo = new_stackinfo(96, 1024/sizeof(PERL_CONTEXT) - 1);
496 PL_curstackinfo->si_type = PERLSI_MAIN;
497 PL_curstack = PL_curstackinfo->si_stack;
498 PL_mainstack = PL_curstack; /* remember in case we switch stacks */
499
500 PL_stack_base = AvARRAY(PL_curstack);
501 PL_stack_sp = PL_stack_base;
502 PL_stack_max = PL_stack_base + AvMAX(PL_curstack);
503
504 New(50,PL_tmps_stack,96,SV*);
505 PL_tmps_floor = -1;
506 PL_tmps_ix = -1;
507 PL_tmps_max = 96;
508
509 New(54,PL_markstack,16,I32);
510 PL_markstack_ptr = PL_markstack;
511 PL_markstack_max = PL_markstack + 16;
512
513#ifdef SET_MARK_OFFSET
514 SET_MARK_OFFSET;
515#endif
516
517 New(54,PL_scopestack,16,I32);
518 PL_scopestack_ix = 0;
519 PL_scopestack_max = 16;
520
521 New(54,PL_savestack,96,ANY);
522 PL_savestack_ix = 0;
523 PL_savestack_max = 96;
524
525 New(54,PL_retstack,8,OP*);
526 PL_retstack_ix = 0;
527 PL_retstack_max = 8;
528
529 UNLOCK;
530}
531
532/*
533 * destroy the stacks, the callchain etc...
534 */
535STATIC void
536destroy_stacks(pTHX)
537{
538 if (!IN_DESTRUCT)
539 {
540 /* is this ugly, I ask? */
541 LEAVE_SCOPE (0);
542
543 /* sure it is, but more important: is it correct?? :/ */
544 FREETMPS;
545
546 /*POPSTACK_TO (PL_mainstack);*//*D*//*use*/
547 }
548
549 while (PL_curstackinfo->si_next)
550 PL_curstackinfo = PL_curstackinfo->si_next;
551
552 while (PL_curstackinfo)
553 {
554 PERL_SI *p = PL_curstackinfo->si_prev;
555
556 { /*D*//*remove*/
557 dSP;
558 SWITCHSTACK (PL_curstack, PL_curstackinfo->si_stack);
559 PUTBACK; /* possibly superfluous */
560 }
561
562 if (!IN_DESTRUCT)
563 {
564 dounwind (-1);/*D*//*remove*/
565 SvREFCNT_dec (PL_curstackinfo->si_stack);
566 }
567
568 Safefree (PL_curstackinfo->si_cxstack);
569 Safefree (PL_curstackinfo);
570 PL_curstackinfo = p;
571 }
572
573 Safefree (PL_tmps_stack);
574 Safefree (PL_markstack);
575 Safefree (PL_scopestack);
576 Safefree (PL_savestack);
577 Safefree (PL_retstack);
260} 578}
261 579
262static void 580static void
263LOAD(pTHX_ Coro__State c) 581allocate_stack (Coro__State ctx, int alloc)
264{ 582{
265 PL_dowarn = c->dowarn; 583 coro_stack *stack;
266 GvAV (PL_defgv) = c->defav;
267 PL_curstackinfo = c->curstackinfo;
268 PL_curstack = c->curstack;
269 PL_mainstack = c->mainstack;
270 PL_stack_sp = c->stack_sp;
271 PL_op = c->op;
272 PL_curpad = c->curpad;
273 PL_stack_base = c->stack_base;
274 PL_stack_max = c->stack_max;
275 PL_tmps_stack = c->tmps_stack;
276 PL_tmps_floor = c->tmps_floor;
277 PL_tmps_ix = c->tmps_ix;
278 PL_tmps_max = c->tmps_max;
279 PL_markstack = c->markstack;
280 PL_markstack_ptr = c->markstack_ptr;
281 PL_markstack_max = c->markstack_max;
282 PL_scopestack = c->scopestack;
283 PL_scopestack_ix = c->scopestack_ix;
284 PL_scopestack_max = c->scopestack_max;
285 PL_savestack = c->savestack;
286 PL_savestack_ix = c->savestack_ix;
287 PL_savestack_max = c->savestack_max;
288 PL_retstack = c->retstack;
289 PL_retstack_ix = c->retstack_ix;
290 PL_retstack_max = c->retstack_max;
291 PL_curcop = c->curcop;
292 584
585 New (0, stack, 1, coro_stack);
586
587 stack->refcnt = 1;
588 stack->usecnt = 1;
589 stack->gencnt = ctx->gencnt = 0;
590
591 if (alloc)
293 { 592 {
593#if HAVE_MMAP
594 stack->ssize = STACKSIZE * sizeof (long); /* mmap should do allocate-on-write for us */
595 stack->sptr = mmap (0, stack->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
596 if (stack->sptr == (void *)-1)
597#endif
598 {
599 /*FIXME*//*D*//* reasonable stack size! */
600 stack->ssize = - (STACKSIZE * sizeof (long));
601 New (0, stack->sptr, STACKSIZE, long);
602 }
603 }
604 else
605 stack->sptr = 0;
606
607 ctx->stack = stack;
608}
609
610static void
611deallocate_stack (Coro__State ctx)
612{
613 coro_stack *stack = ctx->stack;
614
615 ctx->stack = 0;
616
617 if (stack)
618 {
619 if (!--stack->refcnt)
620 {
621#ifdef HAVE_MMAP
622 if (stack->ssize > 0 && stack->sptr)
623 munmap (stack->sptr, stack->ssize);
624 else
625#endif
626 Safefree (stack->sptr);
627
628 Safefree (stack);
629 }
630 else if (ctx->gencnt == stack->gencnt)
631 --stack->usecnt;
632 }
633}
634
635static void
636setup_coro (void *arg)
637{
638 /*
639 * emulate part of the perl startup here.
640 */
641 dTHX;
294 dSP; 642 dSP;
295 CV *cv; 643 Coro__State ctx = (Coro__State)arg;
644 SV *sub_init = (SV *)get_cv (SUB_INIT, FALSE);
296 645
297 /* now do the ugly restore mess */ 646 coro_init_stacks (aTHX);
298 while ((cv = (CV *)POPs)) 647 /*PL_curcop = 0;*/
648 /*PL_in_eval = PL_in_eval;*/ /* inherit */
649 SvREFCNT_dec (GvAV (PL_defgv));
650 GvAV (PL_defgv) = ctx->args; ctx->args = 0;
651
652 SPAGAIN;
653
654 if (ctx->stack)
655 {
656 ctx->cursp = 0;
657
658 PUSHMARK(SP);
659 PUTBACK;
660 (void) call_sv (sub_init, G_VOID|G_NOARGS|G_EVAL);
661
662 if (SvTRUE (ERRSV))
663 croak (NULL);
664 else
665 croak ("FATAL: CCTXT coroutine returned!");
666 }
667 else
668 {
669 UNOP myop;
670
671 PL_op = (OP *)&myop;
672
673 Zero(&myop, 1, UNOP);
674 myop.op_next = Nullop;
675 myop.op_flags = OPf_WANT_VOID;
676
677 PUSHMARK(SP);
678 XPUSHs (sub_init);
679 /*
680 * the next line is slightly wrong, as PL_op->op_next
681 * is actually being executed so we skip the first op.
682 * that doesn't matter, though, since it is only
683 * pp_nextstate and we never return...
684 * ah yes, and I don't care anyways ;)
685 */
686 PUTBACK;
687 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
688 SPAGAIN;
689
690 ENTER; /* necessary e.g. for dounwind */
691 }
692}
693
694static void
695continue_coro (void *arg)
696{
697 /*
698 * this is a _very_ stripped down perl interpreter ;)
699 */
700 dTHX;
701 Coro__State ctx = (Coro__State)arg;
702 JMPENV coro_start_env;
703
704 PL_top_env = &ctx->start_env;
705
706 ctx->cursp = 0;
707 PL_op = PL_op->op_next;
708 CALLRUNOPS(aTHX);
709
710 abort ();
711}
712
713STATIC void
714transfer (pTHX_ struct coro *prev, struct coro *next, int flags)
715{
716 dSTACKLEVEL;
717
718 if (prev != next)
719 {
720 if (next->mainstack)
721 {
722 LOCK;
723 SAVE (prev, flags);
724 LOAD (next);
725 UNLOCK;
726
727 /* mark this state as in-use */
728 next->mainstack = 0;
729 next->tmps_ix = -2;
730
731 /* stacklevel changed? if yes, grab the stack for us! */
732 if (flags & TRANSFER_SAVE_CCTXT)
733 {
734 if (!prev->stack)
735 allocate_stack (prev, 0);
736 else if (prev->cursp != stacklevel
737 && prev->stack->usecnt > 1)
738 {
739 prev->gencnt = ++prev->stack->gencnt;
740 prev->stack->usecnt = 1;
741 }
742
743 /* has our stack been invalidated? */
744 if (next->stack && next->stack->gencnt != next->gencnt)
745 {
746 deallocate_stack (next);
747 allocate_stack (next, 1);
748 coro_create (&(next->stack->cctx),
749 continue_coro, (void *)next,
750 next->stack->sptr, labs (next->stack->ssize));
751 }
752
753 coro_transfer (&(prev->stack->cctx), &(next->stack->cctx));
754 prev->cursp = stacklevel;
755 /* don't add any code here */
756 }
757 else
758 next->cursp = stacklevel;
759 }
760 else if (next->tmps_ix == -2)
761 croak ("tried to transfer to running coroutine");
762 else
763 {
764 LOCK;
765 SAVE (prev, -1); /* first get rid of the old state */
766 UNLOCK;
767
768 if (flags & TRANSFER_SAVE_CCTXT)
769 {
770 if (!prev->stack)
771 allocate_stack (prev, 0);
772
773 if (prev->stack->sptr && flags & TRANSFER_LAZY_STACK)
774 {
775 PL_top_env = &next->start_env;
776
777 setup_coro (next);
778 next->cursp = stacklevel;
779
780 prev->stack->refcnt++;
781 prev->stack->usecnt++;
782 next->stack = prev->stack;
783 next->gencnt = prev->gencnt;
784 }
785 else
786 {
787 assert (!next->stack);
788 allocate_stack (next, 1);
789 coro_create (&(next->stack->cctx),
790 setup_coro, (void *)next,
791 next->stack->sptr, labs (next->stack->ssize));
792 coro_transfer (&(prev->stack->cctx), &(next->stack->cctx));
793 prev->cursp = stacklevel;
794 /* don't add any code here */
795 }
796 }
797 else
798 {
799 setup_coro (next);
800 next->cursp = stacklevel;
801 }
802 }
803 }
804
805 LOCK;
806 if (coro_mortal)
807 {
808 SvREFCNT_dec (coro_mortal);
809 coro_mortal = 0;
810 }
811 UNLOCK;
812}
813
814#define SV_CORO(sv,func) \
815 do { \
816 if (SvROK (sv)) \
817 sv = SvRV (sv); \
818 \
819 if (SvTYPE (sv) == SVt_PVHV) \
820 { \
821 HE *he = hv_fetch_ent ((HV *)sv, ucoro_state_sv, 0, ucoro_state_hash); \
822 \
823 if (!he) \
824 croak ("%s() -- %s is a hashref but lacks the " UCORO_STATE " key", func, # sv); \
825 \
826 (sv) = SvRV (HeVAL(he)); \
827 } \
828 \
829 /* must also be changed inside Coro::Cont::yield */ \
830 if (!SvOBJECT (sv) || SvSTASH (sv) != coro_state_stash) \
831 croak ("%s() -- %s is not (and contains not) a Coro::State object", func, # sv); \
832 \
833 } while(0)
834
835#define SvSTATE(sv) (struct coro *)SvIV (sv)
836
837static void
838api_transfer(pTHX_ SV *prev, SV *next, int flags)
839{
840 SV_CORO (prev, "Coro::transfer");
841 SV_CORO (next, "Coro::transfer");
842
843 transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags);
844}
845
846/** Coro ********************************************************************/
847
848#define PRIO_MAX 3
849#define PRIO_HIGH 1
850#define PRIO_NORMAL 0
851#define PRIO_LOW -1
852#define PRIO_IDLE -3
853#define PRIO_MIN -4
854
855/* for Coro.pm */
856static GV *coro_current, *coro_idle;
857static AV *coro_ready[PRIO_MAX-PRIO_MIN+1];
858static int coro_nready;
859
860static void
861coro_enq (pTHX_ SV *sv)
862{
863 if (SvTYPE (sv) == SVt_PVHV)
864 {
865 SV **xprio = hv_fetch ((HV *)sv, "prio", 4, 0);
866 int prio = xprio ? SvIV (*xprio) : PRIO_NORMAL;
867
868 prio = prio > PRIO_MAX ? PRIO_MAX
869 : prio < PRIO_MIN ? PRIO_MIN
870 : prio;
871
872 av_push (coro_ready [prio - PRIO_MIN], sv);
873 coro_nready++;
874
875 return;
876 }
877
878 croak ("Coro::ready tried to enqueue something that is not a coroutine");
879}
880
881static SV *
882coro_deq (pTHX_ int min_prio)
883{
884 int prio = PRIO_MAX - PRIO_MIN;
885
886 min_prio -= PRIO_MIN;
887 if (min_prio < 0)
888 min_prio = 0;
889
890 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; )
891 if (av_len (coro_ready[prio]) >= 0)
299 { 892 {
300 AV *padlist = (AV *)POPs; 893 coro_nready--;
894 return av_shift (coro_ready[prio]);
895 }
301 896
302 unuse_padlist (CvPADLIST(cv)); 897 return 0;
303 CvPADLIST(cv) = padlist; 898}
304 CvDEPTH(cv) = (I32)POPs;
305 899
900static void
901api_ready (SV *coro)
902{
903 dTHX;
904
905 if (SvROK (coro))
906 coro = SvRV (coro);
907
908 LOCK;
909 coro_enq (aTHX_ SvREFCNT_inc (coro));
910 UNLOCK;
911}
912
913static void
914api_schedule (void)
915{
916 dTHX;
917
918 SV *prev, *next;
919
920 LOCK;
921
922 prev = SvRV (GvSV (coro_current));
923 next = coro_deq (aTHX_ PRIO_MIN);
924
925 if (!next)
926 next = SvREFCNT_inc (SvRV (GvSV (coro_idle)));
927
928 /* free this only after the transfer */
929 coro_mortal = prev;
930 SV_CORO (prev, "Coro::schedule");
931
932 SvRV (GvSV (coro_current)) = next;
933
934 SV_CORO (next, "Coro::schedule");
935
936 UNLOCK;
937
938 transfer (aTHX_ SvSTATE (prev), SvSTATE (next),
939 TRANSFER_SAVE_ALL | TRANSFER_LAZY_STACK);
940}
941
942static void
943api_cede (void)
944{
945 dTHX;
946
947 LOCK;
948 coro_enq (aTHX_ SvREFCNT_inc (SvRV (GvSV (coro_current))));
949 UNLOCK;
950
951 api_schedule ();
952}
953
954MODULE = Coro::State PACKAGE = Coro::State
955
956PROTOTYPES: ENABLE
957
958BOOT:
959{ /* {} necessary for stoopid perl-5.6.x */
306#ifdef USE_THREADS 960#ifdef USE_ITHREADS
307 CvOWNER(cv) = (struct perl_thread *)POPs; 961 MUTEX_INIT (&coro_mutex);
308 error does not work either
309#endif 962#endif
310 }
311 963
312 PUTBACK; 964 ucoro_state_sv = newSVpv (UCORO_STATE, sizeof(UCORO_STATE) - 1);
313 } 965 PERL_HASH(ucoro_state_hash, UCORO_STATE, sizeof(UCORO_STATE) - 1);
314} 966 coro_state_stash = gv_stashpv ("Coro::State", TRUE);
315 967
316/* this is an EXACT copy of S_nuke_stacks in perl.c, which is unfortunately static */ 968 newCONSTSUB (coro_state_stash, "SAVE_DEFAV", newSViv (TRANSFER_SAVE_DEFAV));
317STATIC void 969 newCONSTSUB (coro_state_stash, "SAVE_DEFSV", newSViv (TRANSFER_SAVE_DEFSV));
318S_nuke_stacks(pTHX) 970 newCONSTSUB (coro_state_stash, "SAVE_ERRSV", newSViv (TRANSFER_SAVE_ERRSV));
319{ 971 newCONSTSUB (coro_state_stash, "SAVE_CCTXT", newSViv (TRANSFER_SAVE_CCTXT));
320 while (PL_curstackinfo->si_next)
321 PL_curstackinfo = PL_curstackinfo->si_next;
322 while (PL_curstackinfo) {
323 PERL_SI *p = PL_curstackinfo->si_prev;
324 /* curstackinfo->si_stack got nuked by sv_free_arenas() */
325 Safefree(PL_curstackinfo->si_cxstack);
326 Safefree(PL_curstackinfo);
327 PL_curstackinfo = p;
328 }
329 Safefree(PL_tmps_stack);
330 Safefree(PL_markstack);
331 Safefree(PL_scopestack);
332 Safefree(PL_savestack);
333 Safefree(PL_retstack);
334}
335 972
336#define SUB_INIT "Coro::State::_newcoro" 973 main_mainstack = PL_mainstack;
337 974
338MODULE = Coro::State PACKAGE = Coro::State 975 coroapi.ver = CORO_API_VERSION;
339 976 coroapi.transfer = api_transfer;
340PROTOTYPES: ENABLE 977}
341
342BOOT:
343 if (!padlist_cache)
344 padlist_cache = newHV ();
345 978
346Coro::State 979Coro::State
347_newprocess(args) 980_newprocess(args)
348 SV * args 981 SV * args
349 PROTOTYPE: $ 982 PROTOTYPE: $
350 CODE: 983 CODE:
351 Coro__State coro; 984 Coro__State coro;
352 985
353 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV) 986 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV)
354 croak ("Coro::State::newprocess expects an arrayref"); 987 croak ("Coro::State::_newprocess expects an arrayref");
355 988
356 New (0, coro, 1, struct coro); 989 Newz (0, coro, 1, struct coro);
357 990
358 coro->mainstack = 0; /* actual work is done inside transfer */
359 coro->args = (AV *)SvREFCNT_inc (SvRV (args)); 991 coro->args = (AV *)SvREFCNT_inc (SvRV (args));
992 /*coro->mainstack = 0; *//*actual work is done inside transfer */
993 /*coro->stack = 0;*/
994
995 /* same as JMPENV_BOOTSTRAP */
996 /* we might be able to recycle start_env, but safe is safe */
997 /*Zero(&coro->start_env, 1, JMPENV);*/
998 coro->start_env.je_ret = -1;
999 coro->start_env.je_mustcatch = TRUE;
360 1000
361 RETVAL = coro; 1001 RETVAL = coro;
362 OUTPUT: 1002 OUTPUT:
363 RETVAL 1003 RETVAL
364 1004
365void 1005void
366transfer(prev,next) 1006transfer(prev, next, flags)
367 Coro::State_or_hashref prev 1007 SV *prev
368 Coro::State_or_hashref next 1008 SV *next
1009 int flags
1010 PROTOTYPE: @
369 CODE: 1011 CODE:
370
371 if (prev != next)
372 {
373 PUTBACK; 1012 PUTBACK;
374 SAVE (aTHX_ prev); 1013 SV_CORO (next, "Coro::transfer");
375 1014 SV_CORO (prev, "Coro::transfer");
376 /* 1015 transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags);
377 * this could be done in newprocess which would lead to
378 * extremely elegant and fast (just PUTBACK/SAVE/LOAD/SPAGAIN)
379 * code here, but lazy allocation of stacks has also
380 * some virtues and the overhead of the if() is nil.
381 */
382 if (next->mainstack)
383 {
384 LOAD (aTHX_ next);
385 next->mainstack = 0; /* unnecessary but much cleaner */
386 SPAGAIN; 1016 SPAGAIN;
387 }
388 else
389 {
390 /*
391 * emulate part of the perl startup here.
392 */
393 UNOP myop;
394
395 init_stacks ();
396 PL_op = (OP *)&myop;
397 /*PL_curcop = 0;*/
398 GvAV (PL_defgv) = (SV *)SvREFCNT_inc (next->args);
399
400 SPAGAIN;
401 Zero(&myop, 1, UNOP);
402 myop.op_next = Nullop;
403 myop.op_flags = OPf_WANT_VOID;
404
405 PUSHMARK(SP);
406 XPUSHs ((SV*)get_cv(SUB_INIT, TRUE));
407 PUTBACK;
408 /*
409 * the next line is slightly wrong, as PL_op->op_next
410 * is actually being executed so we skip the first op.
411 * that doesn't matter, though, since it is only
412 * pp_nextstate and we never return...
413 */
414 PL_op = Perl_pp_entersub(aTHX);
415 SPAGAIN;
416
417 ENTER;
418 }
419 }
420 1017
421void 1018void
422DESTROY(coro) 1019DESTROY(coro)
423 Coro::State coro 1020 Coro::State coro
424 CODE: 1021 CODE:
425 1022
426 if (coro->mainstack) 1023 if (coro->mainstack && coro->mainstack != main_mainstack)
427 { 1024 {
428 struct coro temp; 1025 struct coro temp;
429 1026
430 PUTBACK; 1027 PUTBACK;
431 SAVE(aTHX_ (&temp)); 1028 SAVE (aTHX_ (&temp), TRANSFER_SAVE_ALL);
432 LOAD(aTHX_ coro); 1029 LOAD (aTHX_ coro);
433
434 S_nuke_stacks ();
435 SvREFCNT_dec ((SV *)GvAV (PL_defgv));
436
437 LOAD((&temp));
438 SPAGAIN; 1030 SPAGAIN;
1031
1032 destroy_stacks (aTHX);
1033
1034 LOAD ((&temp)); /* this will get rid of defsv etc.. */
1035 SPAGAIN;
1036
1037 coro->mainstack = 0;
439 } 1038 }
440 1039
1040 deallocate_stack (coro);
441 SvREFCNT_dec (coro->args); 1041 SvREFCNT_dec (coro->args);
442 Safefree (coro); 1042 Safefree (coro);
443 1043
1044void
1045_exit(code)
1046 int code
1047 PROTOTYPE: $
1048 CODE:
1049 _exit (code);
444 1050
1051MODULE = Coro::State PACKAGE = Coro::Cont
1052
1053# this is slightly dirty (should expose a c-level api)
1054
1055void
1056yield(...)
1057 PROTOTYPE: @
1058 CODE:
1059 SV *yieldstack;
1060 SV *sv;
1061 AV *defav = GvAV (PL_defgv);
1062 struct coro *prev, *next;
1063
1064 yieldstack = *hv_fetch (
1065 (HV *)SvRV (GvSV (coro_current)),
1066 "yieldstack", sizeof ("yieldstack") - 1,
1067 0
1068 );
1069
1070 /* set up @_ -- ugly */
1071 av_clear (defav);
1072 av_fill (defav, items - 1);
1073 while (items--)
1074 av_store (defav, items, SvREFCNT_inc (ST(items)));
1075
1076 sv = av_pop ((AV *)SvRV (yieldstack));
1077 prev = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 0, 0)));
1078 next = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0)));
1079 SvREFCNT_dec (sv);
1080
1081 transfer (aTHX_ prev, next, 0);
1082
1083MODULE = Coro::State PACKAGE = Coro
1084
1085# this is slightly dirty (should expose a c-level api)
1086
1087BOOT:
1088{
1089 int i;
1090 HV *stash = gv_stashpv ("Coro", TRUE);
1091
1092 newCONSTSUB (stash, "PRIO_MAX", newSViv (PRIO_MAX));
1093 newCONSTSUB (stash, "PRIO_HIGH", newSViv (PRIO_HIGH));
1094 newCONSTSUB (stash, "PRIO_NORMAL", newSViv (PRIO_NORMAL));
1095 newCONSTSUB (stash, "PRIO_LOW", newSViv (PRIO_LOW));
1096 newCONSTSUB (stash, "PRIO_IDLE", newSViv (PRIO_IDLE));
1097 newCONSTSUB (stash, "PRIO_MIN", newSViv (PRIO_MIN));
1098
1099 coro_current = gv_fetchpv ("Coro::current", TRUE, SVt_PV);
1100 coro_idle = gv_fetchpv ("Coro::idle" , TRUE, SVt_PV);
1101
1102 for (i = PRIO_MAX - PRIO_MIN + 1; i--; )
1103 coro_ready[i] = newAV ();
1104
1105 {
1106 SV *sv = perl_get_sv("Coro::API", 1);
1107
1108 coroapi.schedule = api_schedule;
1109 coroapi.cede = api_cede;
1110 coroapi.ready = api_ready;
1111 coroapi.nready = &coro_nready;
1112 coroapi.current = coro_current;
1113
1114 GCoroAPI = &coroapi;
1115 sv_setiv(sv, (IV)&coroapi);
1116 SvREADONLY_on(sv);
1117 }
1118}
1119
1120#if !PERL_MICRO
1121
1122void
1123ready(self)
1124 SV * self
1125 PROTOTYPE: $
1126 CODE:
1127 api_ready (self);
1128
1129#endif
1130
1131int
1132nready(...)
1133 PROTOTYPE:
1134 CODE:
1135 RETVAL = coro_nready;
1136 OUTPUT:
1137 RETVAL
1138
1139void
1140schedule(...)
1141 PROTOTYPE:
1142 CODE:
1143 api_schedule ();
1144
1145void
1146cede(...)
1147 PROTOTYPE:
1148 CODE:
1149 api_cede ();
1150

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines