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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines