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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines