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.4 by root, Tue Jul 17 02:21:56 2001 UTC vs.
Revision 1.61 by root, Tue Aug 10 01:56:30 2004 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines