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.136 by root, Fri Jan 12 01:05:55 2007 UTC

1#include "libcoro/coro.c"
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#include <stdio.h>
10#include <errno.h>
11#include <assert.h>
12
13#ifdef HAVE_MMAP
14# include <unistd.h>
15# include <sys/mman.h>
16# ifndef MAP_ANONYMOUS
17# ifdef MAP_ANON
18# define MAP_ANONYMOUS MAP_ANON
19# else
20# undef HAVE_MMAP
21# endif
22# endif
23# include <limits.h>
24# ifndef PAGESIZE
25# define PAGESIZE pagesize
26# define BOOT_PAGESIZE pagesize = sysconf (_SC_PAGESIZE)
27static long pagesize;
28# else
29# define BOOT_PAGESIZE (void)0
30# endif
7#else 31#else
8# define CHK(x) if (!(x)) croak("FATAL, CHK: " #x) 32# define PAGESIZE 0
33# define BOOT_PAGESIZE (void)0
34#endif
35
36#if USE_VALGRIND
37# include <valgrind/valgrind.h>
38#endif
39
40/* the maximum number of idle cctx that will be pooled */
41#define MAX_IDLE_CCTX 8
42
43#define PERL_VERSION_ATLEAST(a,b,c) \
44 (PERL_REVISION > (a) \
45 || (PERL_REVISION == (a) \
46 && (PERL_VERSION > (b) \
47 || (PERL_VERSION == (b) && PERLSUBVERSION >= (c)))))
48
49#if !PERL_VERSION_ATLEAST (5,6,0)
50# ifndef PL_ppaddr
51# define PL_ppaddr ppaddr
9#endif 52# endif
53# ifndef call_sv
54# define call_sv perl_call_sv
55# endif
56# ifndef get_sv
57# define get_sv perl_get_sv
58# endif
59# ifndef get_cv
60# define get_cv perl_get_cv
61# endif
62# ifndef IS_PADGV
63# define IS_PADGV(v) 0
64# endif
65# ifndef IS_PADCONST
66# define IS_PADCONST(v) 0
67# endif
68#endif
10 69
70/* 5.8.7 */
71#ifndef SvRV_set
72# define SvRV_set(s,v) SvRV(s) = (v)
73#endif
74
75#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64
76# undef STACKGUARD
77#endif
78
79#ifndef STACKGUARD
80# define STACKGUARD 0
81#endif
82
83/* prefer perl internal functions over our own? */
84#ifndef PREFER_PERL_FUNCTIONS
85# define PREFER_PERL_FUNCTIONS 0
86#endif
87
88/* The next macro should declare a variable stacklevel that contains and approximation
89 * to the current C stack pointer. Its property is that it changes with each call
90 * and should be unique. */
91#define dSTACKLEVEL int stacklevel
92#define STACKLEVEL ((void *)&stacklevel)
93
94#define IN_DESTRUCT (PL_main_cv == Nullcv)
95
96#if __GNUC__ >= 3
97# define attribute(x) __attribute__(x)
98# define BARRIER __asm__ __volatile__ ("" : : : "memory")
99#else
100# define attribute(x)
101# define BARRIER
102#endif
103
104#define NOINLINE attribute ((noinline))
105
106#include "CoroAPI.h"
107
108#ifdef USE_ITHREADS
109static perl_mutex coro_mutex;
110# define LOCK do { MUTEX_LOCK (&coro_mutex); } while (0)
111# define UNLOCK do { MUTEX_UNLOCK (&coro_mutex); } while (0)
112#else
113# define LOCK (void)0
114# define UNLOCK (void)0
115#endif
116
117/* helper storage struct for Coro::AIO */
118struct io_state
119{
120 int errorno;
121 I32 laststype;
122 int laststatval;
123 Stat_t statcache;
124};
125
126static struct CoroAPI coroapi;
127static AV *main_mainstack; /* used to differentiate between $main and others */
128static HV *coro_state_stash, *coro_stash;
129static SV *coro_mortal; /* will be freed after next transfer */
130
131static struct coro_cctx *cctx_first;
132static int cctx_count, cctx_idle;
133
134/* this is a structure representing a c-level coroutine */
135typedef struct coro_cctx {
136 struct coro_cctx *next;
137
138 /* the stack */
139 void *sptr;
140 long ssize; /* positive == mmap, otherwise malloc */
141
142 /* cpu state */
143 void *idle_sp; /* sp of top-level transfer/schedule/cede call */
144 JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */
145 JMPENV *top_env;
146 coro_context cctx;
147
148 int inuse;
149
150#if USE_VALGRIND
151 int valgrind_id;
152#endif
153} coro_cctx;
154
155enum {
156 CF_RUNNING = 0x0001, /* coroutine is running */
157 CF_READY = 0x0002, /* coroutine is ready */
158 CF_NEW = 0x0004, /* has never been switched to */
159 CF_DESTROYED = 0x0008, /* coroutine data has been freed */
160};
161
162/* this is a structure representing a perl-level coroutine */
11struct coro { 163struct coro {
12 U8 dowarn; 164 /* the c coroutine allocated to this perl coroutine, if any */
13 AV *defav; 165 coro_cctx *cctx;
166
167 /* data associated with this coroutine (initial args) */
168 AV *args;
169 int refcnt;
170 int save; /* CORO_SAVE flags */
171 int flags; /* CF_ flags */
172
173 /* optionally saved, might be zero */
174 AV *defav; /* @_ */
175 SV *defsv; /* $_ */
176 SV *errsv; /* $@ */
177 SV *irssv; /* $/ */
178 SV *irssv_sv; /* real $/ cache */
14 179
15 PERL_SI *curstackinfo; 180#define VAR(name,type) type name;
16 AV *curstack; 181# include "state.h"
17 AV *mainstack; 182#undef VAR
18 SV **stack_sp;
19 OP *op;
20 SV **curpad;
21 SV **stack_base;
22 SV **stack_max;
23 SV **tmps_stack;
24 I32 tmps_floor;
25 I32 tmps_ix;
26 I32 tmps_max;
27 I32 *markstack;
28 I32 *markstack_ptr;
29 I32 *markstack_max;
30 I32 *scopestack;
31 I32 scopestack_ix;
32 I32 scopestack_max;
33 ANY *savestack;
34 I32 savestack_ix;
35 I32 savestack_max;
36 OP **retstack;
37 I32 retstack_ix;
38 I32 retstack_max;
39 COP *curcop;
40 183
41 AV *args; 184 /* coro process data */
185 int prio;
42}; 186};
43 187
44typedef struct coro *Coro__State; 188typedef struct coro *Coro__State;
45typedef struct coro *Coro__State_or_hashref; 189typedef struct coro *Coro__State_or_hashref;
46 190
47static HV *padlist_cache; 191static AV *
48 192coro_clone_padlist (CV *cv)
49/* mostly copied from op.c:cv_clone2 */
50STATIC AV *
51clone_padlist (AV *protopadlist)
52{ 193{
53 AV *av; 194 AV *padlist = CvPADLIST (cv);
54 I32 ix;
55 AV *protopad_name = (AV *) * av_fetch (protopadlist, 0, FALSE);
56 AV *protopad = (AV *) * av_fetch (protopadlist, 1, FALSE);
57 SV **pname = AvARRAY (protopad_name);
58 SV **ppad = AvARRAY (protopad);
59 I32 fname = AvFILLp (protopad_name);
60 I32 fpad = AvFILLp (protopad);
61 AV *newpadlist, *newpad_name, *newpad; 195 AV *newpadlist, *newpad;
62 SV **npad;
63
64 newpad_name = newAV ();
65 for (ix = fname; ix >= 0; ix--)
66 av_store (newpad_name, ix, SvREFCNT_inc (pname[ix]));
67
68 newpad = newAV ();
69 av_fill (newpad, AvFILLp (protopad));
70 npad = AvARRAY (newpad);
71 196
72 newpadlist = newAV (); 197 newpadlist = newAV ();
73 AvREAL_off (newpadlist); 198 AvREAL_off (newpadlist);
74 av_store (newpadlist, 0, (SV *) newpad_name); 199#if PERL_VERSION_ATLEAST (5,9,0)
200 Perl_pad_push (aTHX_ padlist, AvFILLp (padlist) + 1);
201#else
202 Perl_pad_push (aTHX_ padlist, AvFILLp (padlist) + 1, 1);
203#endif
204 newpad = (AV *)AvARRAY (padlist)[AvFILLp (padlist)];
205 --AvFILLp (padlist);
206
207 av_store (newpadlist, 0, SvREFCNT_inc (*av_fetch (padlist, 0, FALSE)));
75 av_store (newpadlist, 1, (SV *) newpad); 208 av_store (newpadlist, 1, (SV *)newpad);
76 209
77 av = newAV (); /* will be @_ */ 210 return newpadlist;
78 av_extend (av, 0); 211}
79 av_store (newpad, 0, (SV *) av);
80 AvFLAGS (av) = AVf_REIFY;
81 212
82 for (ix = fpad; ix > 0; ix--) 213static void
214free_padlist (AV *padlist)
215{
216 /* may be during global destruction */
217 if (SvREFCNT (padlist))
83 { 218 {
84 SV *namesv = (ix <= fname) ? pname[ix] : Nullsv; 219 I32 i = AvFILLp (padlist);
85 if (namesv && namesv != &PL_sv_undef) 220 while (i >= 0)
86 { 221 {
87 char *name = SvPVX (namesv); /* XXX */ 222 SV **svp = av_fetch (padlist, i--, FALSE);
88 if (SvFLAGS (namesv) & SVf_FAKE || *name == '&') 223 if (svp)
89 { /* lexical from outside? */
90 npad[ix] = SvREFCNT_inc (ppad[ix]);
91 } 224 {
92 else
93 { /* our own lexical */
94 SV *sv; 225 SV *sv;
95 if (*name == '&') 226 while (&PL_sv_undef != (sv = av_pop ((AV *)*svp)))
96 sv = SvREFCNT_inc (ppad[ix]); 227 SvREFCNT_dec (sv);
97 else if (*name == '@') 228
98 sv = (SV *) newAV (); 229 SvREFCNT_dec (*svp);
99 else if (*name == '%')
100 sv = (SV *) newHV ();
101 else
102 sv = NEWSV (0, 0);
103 if (!SvPADBUSY (sv))
104 SvPADMY_on (sv);
105 npad[ix] = sv;
106 } 230 }
107 } 231 }
108 else if (IS_PADGV (ppad[ix]) || IS_PADCONST (ppad[ix])) 232
109 { 233 SvREFCNT_dec ((SV*)padlist);
110 npad[ix] = SvREFCNT_inc (ppad[ix]); 234 }
111 } 235}
236
237static int
238coro_cv_free (pTHX_ SV *sv, MAGIC *mg)
239{
240 AV *padlist;
241 AV *av = (AV *)mg->mg_obj;
242
243 /* casting is fun. */
244 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
245 free_padlist (padlist);
246
247 SvREFCNT_dec (av);
248
249 return 0;
250}
251
252#define PERL_MAGIC_coro PERL_MAGIC_ext
253
254static MGVTBL vtbl_coro = {0, 0, 0, 0, coro_cv_free};
255
256#define CORO_MAGIC(cv) \
257 SvMAGIC (cv) \
258 ? SvMAGIC (cv)->mg_type == PERL_MAGIC_coro \
259 ? SvMAGIC (cv) \
260 : mg_find ((SV *)cv, PERL_MAGIC_coro) \
261 : 0
262
263/* the next two functions merely cache the padlists */
264static void
265get_padlist (CV *cv)
266{
267 MAGIC *mg = CORO_MAGIC (cv);
268 AV *av;
269
270 if (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0)
271 CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--];
272 else
273 {
274#if PREFER_PERL_FUNCTIONS
275 /* this is probably cleaner, but also slower? */
276 CV *cp = Perl_cv_clone (cv);
277 CvPADLIST (cv) = CvPADLIST (cp);
278 CvPADLIST (cp) = 0;
279 SvREFCNT_dec (cp);
280#else
281 CvPADLIST (cv) = coro_clone_padlist (cv);
282#endif
283 }
284}
285
286static void
287put_padlist (CV *cv)
288{
289 MAGIC *mg = CORO_MAGIC (cv);
290 AV *av;
291
292 if (!mg)
293 {
294 sv_magic ((SV *)cv, 0, PERL_MAGIC_coro, 0, 0);
295 mg = mg_find ((SV *)cv, PERL_MAGIC_coro);
296 mg->mg_virtual = &vtbl_coro;
297 mg->mg_obj = (SV *)newAV ();
298 }
299
300 av = (AV *)mg->mg_obj;
301
302 if (AvFILLp (av) >= AvMAX (av))
303 av_extend (av, AvMAX (av) + 1);
304
305 AvARRAY (av)[++AvFILLp (av)] = (SV *)CvPADLIST (cv);
306}
307
308#define SB do {
309#define SE } while (0)
310
311#define REPLACE_SV(sv,val) SB SvREFCNT_dec (sv); (sv) = (val); (val) = 0; SE
312
313static void
314load_perl (Coro__State c)
315{
316#define VAR(name,type) PL_ ## name = c->name;
317# include "state.h"
318#undef VAR
319
320 if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav);
321 if (c->defsv) REPLACE_SV (DEFSV , c->defsv);
322 if (c->errsv) REPLACE_SV (ERRSV , c->errsv);
323 if (c->irssv)
324 {
325 if (c->irssv == PL_rs || sv_eq (PL_rs, c->irssv))
326 SvREFCNT_dec (c->irssv);
112 else 327 else
113 { 328 {
114 SV *sv = NEWSV (0, 0); 329 REPLACE_SV (PL_rs, c->irssv);
115 SvPADTMP_on (sv); 330 if (!c->irssv_sv) c->irssv_sv = get_sv ("/", 0);
116 npad[ix] = sv; 331 sv_setsv (c->irssv_sv, PL_rs);
117 } 332 }
118 } 333 }
119 334
120#if 0 /* NONOTUNDERSTOOD */ 335 {
121 /* Now that vars are all in place, clone nested closures. */ 336 dSP;
337 CV *cv;
122 338
123 for (ix = fpad; ix > 0; ix--) { 339 /* now do the ugly restore mess */
124 SV* namesv = (ix <= fname) ? pname[ix] : Nullsv; 340 while ((cv = (CV *)POPs))
125 if (namesv
126 && namesv != &PL_sv_undef
127 && !(SvFLAGS(namesv) & SVf_FAKE)
128 && *SvPVX(namesv) == '&'
129 && CvCLONE(ppad[ix]))
130 { 341 {
131 CV *kid = cv_clone((CV*)ppad[ix]); 342 put_padlist (cv); /* mark this padlist as available */
132 SvREFCNT_dec(ppad[ix]); 343 CvDEPTH (cv) = PTR2IV (POPs);
133 CvCLONE_on(kid); 344 CvPADLIST (cv) = (AV *)POPs;
134 SvPADMY_on(kid);
135 npad[ix] = (SV*)kid;
136 } 345 }
137 }
138#endif
139 346
140 return newpadlist; 347 PUTBACK;
141}
142
143STATIC AV *
144free_padlist (AV *padlist)
145{
146 /* may be during global destruction */
147 if (SvREFCNT(padlist))
148 {
149 I32 i = AvFILLp(padlist);
150 while (i >= 0)
151 {
152 SV **svp = av_fetch(padlist, i--, FALSE);
153 SV *sv = svp ? *svp : Nullsv;
154 if (sv)
155 SvREFCNT_dec(sv);
156 }
157
158 SvREFCNT_dec((SV*)padlist);
159 } 348 }
160} 349}
161 350
162STATIC AV *
163unuse_padlist (AV *padlist)
164{
165 free_padlist (padlist);
166}
167
168static void 351static void
169SAVE(pTHX_ Coro__State c) 352save_perl (Coro__State c)
170{ 353{
171 { 354 {
172 dSP; 355 dSP;
173 I32 cxix = cxstack_ix; 356 I32 cxix = cxstack_ix;
357 PERL_CONTEXT *ccstk = cxstack;
174 PERL_SI *top_si = PL_curstackinfo; 358 PERL_SI *top_si = PL_curstackinfo;
175 PERL_CONTEXT *ccstk = cxstack;
176 359
177 /* 360 /*
178 * the worst thing you can imagine happens first - we have to save 361 * the worst thing you can imagine happens first - we have to save
179 * (and reinitialize) all cv's in the whole callchain :( 362 * (and reinitialize) all cv's in the whole callchain :(
180 */ 363 */
181 364
365 EXTEND (SP, 3 + 1);
182 PUSHs (Nullsv); 366 PUSHs (Nullsv);
183 /* this loop was inspired by pp_caller */ 367 /* this loop was inspired by pp_caller */
184 for (;;) 368 for (;;)
185 { 369 {
186 while (cxix >= 0) 370 while (cxix >= 0)
187 { 371 {
188 PERL_CONTEXT *cx = &ccstk[--cxix]; 372 PERL_CONTEXT *cx = &ccstk[cxix--];
189 373
190 if (CxTYPE(cx) == CXt_SUB) 374 if (CxTYPE (cx) == CXt_SUB)
191 { 375 {
192 CV *cv = cx->blk_sub.cv; 376 CV *cv = cx->blk_sub.cv;
377
193 if (CvDEPTH(cv)) 378 if (CvDEPTH (cv))
194 { 379 {
195#ifdef USE_THREADS
196 XPUSHs ((SV *)CvOWNER(cv));
197#endif
198 EXTEND (SP, 3); 380 EXTEND (SP, 3);
199 PUSHs ((SV *)CvDEPTH(cv));
200 PUSHs ((SV *)CvPADLIST(cv)); 381 PUSHs ((SV *)CvPADLIST (cv));
382 PUSHs (INT2PTR (SV *, CvDEPTH (cv)));
201 PUSHs ((SV *)cv); 383 PUSHs ((SV *)cv);
202 384
203 CvPADLIST(cv) = clone_padlist (CvPADLIST(cv));
204
205 CvDEPTH(cv) = 0; 385 CvDEPTH (cv) = 0;
206#ifdef USE_THREADS 386 get_padlist (cv);
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 } 387 }
213 }
214 else if (CxTYPE(cx) == CXt_FORMAT)
215 {
216 /* I never used formats, so how should I know how these are implemented? */
217 /* my bold guess is as a simple, plain sub... */
218 croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats");
219 } 388 }
220 } 389 }
221 390
222 if (top_si->si_type == PERLSI_MAIN) 391 if (top_si->si_type == PERLSI_MAIN)
223 break; 392 break;
228 } 397 }
229 398
230 PUTBACK; 399 PUTBACK;
231 } 400 }
232 401
233 c->dowarn = PL_dowarn; 402 c->defav = c->save & CORO_SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0;
234 c->defav = GvAV (PL_defgv); 403 c->defsv = c->save & CORO_SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0;
235 c->curstackinfo = PL_curstackinfo; 404 c->errsv = c->save & CORO_SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0;
236 c->curstack = PL_curstack; 405 c->irssv = c->save & CORO_SAVE_IRSSV ? SvREFCNT_inc (PL_rs) : 0;
237 c->mainstack = PL_mainstack; 406
238 c->stack_sp = PL_stack_sp; 407#define VAR(name,type)c->name = PL_ ## name;
239 c->op = PL_op; 408# include "state.h"
240 c->curpad = PL_curpad; 409#undef VAR
410}
411
412/*
413 * allocate various perl stacks. This is an exact copy
414 * of perl.c:init_stacks, except that it uses less memory
415 * on the (sometimes correct) assumption that coroutines do
416 * not usually need a lot of stackspace.
417 */
418#if PREFER_PERL_FUNCTIONS
419# define coro_init_stacks init_stacks
420#else
421static void
422coro_init_stacks ()
423{
424 PL_curstackinfo = new_stackinfo(128, 1024/sizeof(PERL_CONTEXT));
425 PL_curstackinfo->si_type = PERLSI_MAIN;
426 PL_curstack = PL_curstackinfo->si_stack;
427 PL_mainstack = PL_curstack; /* remember in case we switch stacks */
428
429 PL_stack_base = AvARRAY(PL_curstack);
241 c->stack_base = PL_stack_base; 430 PL_stack_sp = PL_stack_base;
242 c->stack_max = PL_stack_max; 431 PL_stack_max = PL_stack_base + AvMAX(PL_curstack);
243 c->tmps_stack = PL_tmps_stack;
244 c->tmps_floor = PL_tmps_floor;
245 c->tmps_ix = PL_tmps_ix;
246 c->tmps_max = PL_tmps_max;
247 c->markstack = PL_markstack;
248 c->markstack_ptr = PL_markstack_ptr;
249 c->markstack_max = PL_markstack_max;
250 c->scopestack = PL_scopestack;
251 c->scopestack_ix = PL_scopestack_ix;
252 c->scopestack_max = PL_scopestack_max;
253 c->savestack = PL_savestack;
254 c->savestack_ix = PL_savestack_ix;
255 c->savestack_max = PL_savestack_max;
256 c->retstack = PL_retstack;
257 c->retstack_ix = PL_retstack_ix;
258 c->retstack_max = PL_retstack_max;
259 c->curcop = PL_curcop;
260}
261 432
262static void 433 New(50,PL_tmps_stack,128,SV*);
263LOAD(pTHX_ Coro__State c) 434 PL_tmps_floor = -1;
264{ 435 PL_tmps_ix = -1;
265 PL_dowarn = c->dowarn; 436 PL_tmps_max = 128;
266 GvAV (PL_defgv) = c->defav; 437
267 PL_curstackinfo = c->curstackinfo; 438 New(54,PL_markstack,32,I32);
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; 439 PL_markstack_ptr = PL_markstack;
281 PL_markstack_max = c->markstack_max; 440 PL_markstack_max = PL_markstack + 32;
282 PL_scopestack = c->scopestack; 441
283 PL_scopestack_ix = c->scopestack_ix; 442#ifdef SET_MARK_OFFSET
284 PL_scopestack_max = c->scopestack_max; 443 SET_MARK_OFFSET;
285 PL_savestack = c->savestack; 444#endif
286 PL_savestack_ix = c->savestack_ix; 445
287 PL_savestack_max = c->savestack_max; 446 New(54,PL_scopestack,32,I32);
288 PL_retstack = c->retstack; 447 PL_scopestack_ix = 0;
289 PL_retstack_ix = c->retstack_ix; 448 PL_scopestack_max = 32;
290 PL_retstack_max = c->retstack_max; 449
291 PL_curcop = c->curcop; 450 New(54,PL_savestack,64,ANY);
451 PL_savestack_ix = 0;
452 PL_savestack_max = 64;
453
454#if !PERL_VERSION_ATLEAST (5,9,0)
455 New(54,PL_retstack,16,OP*);
456 PL_retstack_ix = 0;
457 PL_retstack_max = 16;
458#endif
459}
460#endif
461
462/*
463 * destroy the stacks, the callchain etc...
464 */
465static void
466coro_destroy_stacks ()
467{
468 if (!IN_DESTRUCT)
469 {
470 /* restore all saved variables and stuff */
471 LEAVE_SCOPE (0);
472 assert (PL_tmps_floor == -1);
473
474 /* free all temporaries */
475 FREETMPS;
476 assert (PL_tmps_ix == -1);
477
478 /* unwind all extra stacks */
479 POPSTACK_TO (PL_mainstack);
480
481 /* unwind main stack */
482 dounwind (-1);
483 }
484
485 while (PL_curstackinfo->si_next)
486 PL_curstackinfo = PL_curstackinfo->si_next;
487
488 while (PL_curstackinfo)
489 {
490 PERL_SI *p = PL_curstackinfo->si_prev;
491
492 if (!IN_DESTRUCT)
493 SvREFCNT_dec (PL_curstackinfo->si_stack);
494
495 Safefree (PL_curstackinfo->si_cxstack);
496 Safefree (PL_curstackinfo);
497 PL_curstackinfo = p;
498 }
499
500 Safefree (PL_tmps_stack);
501 Safefree (PL_markstack);
502 Safefree (PL_scopestack);
503 Safefree (PL_savestack);
504#if !PERL_VERSION_ATLEAST (5,9,0)
505 Safefree (PL_retstack);
506#endif
507}
508
509static void
510setup_coro (struct coro *coro)
511{
512 /*
513 * emulate part of the perl startup here.
514 */
515
516 coro_init_stacks ();
517
518 PL_curcop = &PL_compiling;
519 PL_in_eval = EVAL_NULL;
520 PL_curpm = 0;
521 PL_localizing = 0;
522 PL_dirty = 0;
523 PL_restartop = 0;
292 524
293 { 525 {
294 dSP; 526 dSP;
295 CV *cv; 527 LOGOP myop;
296 528
297 /* now do the ugly restore mess */ 529 SvREFCNT_dec (GvAV (PL_defgv));
298 while ((cv = (CV *)POPs)) 530 GvAV (PL_defgv) = coro->args; coro->args = 0;
531
532 Zero (&myop, 1, LOGOP);
533 myop.op_next = Nullop;
534 myop.op_flags = OPf_WANT_VOID;
535
536 PUSHMARK (SP);
537 XPUSHs ((SV *)get_cv ("Coro::State::_coro_init", FALSE));
538 PUTBACK;
539 PL_op = (OP *)&myop;
540 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
541 SPAGAIN;
542 }
543
544 ENTER; /* necessary e.g. for dounwind */
545}
546
547static void
548free_coro_mortal ()
549{
550 if (coro_mortal)
551 {
552 SvREFCNT_dec (coro_mortal);
553 coro_mortal = 0;
554 }
555}
556
557/* inject a fake call to Coro::State::_cctx_init into the execution */
558static void NOINLINE
559prepare_cctx (coro_cctx *cctx)
560{
561 dSP;
562 LOGOP myop;
563
564 Zero (&myop, 1, LOGOP);
565 myop.op_next = PL_op;
566 myop.op_flags = OPf_WANT_VOID | OPf_STACKED;
567
568 PUSHMARK (SP);
569 EXTEND (SP, 2);
570 PUSHs (sv_2mortal (newSViv (PTR2IV (cctx))));
571 PUSHs ((SV *)get_cv ("Coro::State::_cctx_init", FALSE));
572 PUTBACK;
573 PL_op = (OP *)&myop;
574 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
575 SPAGAIN;
576}
577
578static void
579coro_run (void *arg)
580{
581 /* coro_run is the alternative tail of transfer(), so unlock here. */
582 UNLOCK;
583
584 /*
585 * this is a _very_ stripped down perl interpreter ;)
586 */
587 PL_top_env = &PL_start_env;
588
589 /* inject call to cctx_init */
590 prepare_cctx ((coro_cctx *)arg);
591
592 /* somebody will hit me for both perl_run and PL_restartop */
593 PL_restartop = PL_op;
594 perl_run (PL_curinterp);
595
596 fputs ("FATAL: C coroutine fell over the edge of the world, aborting. Did you call exit in a coroutine?\n", stderr);
597 abort ();
598}
599
600static coro_cctx *
601cctx_new ()
602{
603 coro_cctx *cctx;
604
605 ++cctx_count;
606
607 Newz (0, cctx, 1, coro_cctx);
608
609#if HAVE_MMAP
610
611 cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE;
612 /* mmap supposedly does allocate-on-write for us */
613 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
614
615 if (cctx->sptr == (void *)-1)
616 {
617 perror ("FATAL: unable to mmap stack for coroutine");
618 _exit (EXIT_FAILURE);
619 }
620
621# if STACKGUARD
622 mprotect (cctx->sptr, STACKGUARD * PAGESIZE, PROT_NONE);
623# endif
624
625#else
626
627 cctx->ssize = STACKSIZE * (long)sizeof (long);
628 New (0, cctx->sptr, STACKSIZE, long);
629
630 if (!cctx->sptr)
631 {
632 perror ("FATAL: unable to malloc stack for coroutine");
633 _exit (EXIT_FAILURE);
634 }
635
636#endif
637
638#if USE_VALGRIND
639 cctx->valgrind_id = VALGRIND_STACK_REGISTER (
640 STACKGUARD * PAGESIZE + (char *)cctx->sptr,
641 cctx->ssize + (char *)cctx->sptr
642 );
643#endif
644
645 coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, cctx->ssize);
646
647 return cctx;
648}
649
650static void
651cctx_destroy (coro_cctx *cctx)
652{
653 if (!cctx)
654 return;
655
656 --cctx_count;
657
658#if USE_VALGRIND
659 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id);
660#endif
661
662#if HAVE_MMAP
663 munmap (cctx->sptr, cctx->ssize);
664#else
665 Safefree (cctx->sptr);
666#endif
667
668 Safefree (cctx);
669}
670
671static coro_cctx *
672cctx_get ()
673{
674 coro_cctx *cctx;
675
676 if (cctx_first)
677 {
678 cctx = cctx_first;
679 cctx_first = cctx->next;
680 --cctx_idle;
681 }
682 else
683 {
684 cctx = cctx_new ();
685 PL_op = PL_op->op_next;
686 }
687
688 return cctx;
689}
690
691static void
692cctx_put (coro_cctx *cctx)
693{
694 /* free another cctx if overlimit */
695 if (cctx_idle >= MAX_IDLE_CCTX)
696 {
697 coro_cctx *first = cctx_first;
698 cctx_first = first->next;
699 --cctx_idle;
700
701 assert (!first->inuse);
702 cctx_destroy (first);
703 }
704
705 ++cctx_idle;
706 cctx->next = cctx_first;
707 cctx_first = cctx;
708}
709
710/* never call directly, always through the coro_state_transfer global variable */
711static void NOINLINE
712transfer (struct coro *prev, struct coro *next)
713{
714 dSTACKLEVEL;
715
716 /* sometimes transfer is only called to set idle_sp */
717 if (!next)
718 {
719 ((coro_cctx *)prev)->idle_sp = STACKLEVEL;
720 assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */
721 }
722 else if (prev != next)
723 {
724 coro_cctx *prev__cctx;
725
726 if (prev->flags & CF_NEW)
727 {
728 /* create a new empty context */
729 Newz (0, prev->cctx, 1, coro_cctx);
730 prev->cctx->inuse = 1;
731 prev->flags &= ~CF_NEW;
732 prev->flags |= CF_RUNNING;
733 }
734
735 /*TODO: must not croak here */
736 if (!prev->flags & CF_RUNNING)
737 croak ("Coro::State::transfer called with non-running prev Coro::State, but can only transfer from running states");
738
739 if (next->flags & CF_RUNNING)
740 croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states");
741
742 if (next->flags & CF_DESTROYED)
743 croak ("Coro::State::transfer called with destroyed next Coro::State, but can only transfer to inactive states");
744
745 prev->flags &= ~CF_RUNNING;
746 next->flags |= CF_RUNNING;
747
748 LOCK;
749
750 if (next->flags & CF_NEW)
751 {
752 /* need to start coroutine */
753 next->flags &= ~CF_NEW;
754 /* first get rid of the old state */
755 save_perl (prev);
756 /* setup coroutine call */
757 setup_coro (next);
758 /* need a new stack */
759 assert (!next->cctx);
760 }
761 else
762 {
763 /* coroutine already started */
764 save_perl (prev);
765 load_perl (next);
766 }
767
768 prev__cctx = prev->cctx;
769
770 /* possibly "free" the cctx */
771 if (prev__cctx->idle_sp == STACKLEVEL)
772 {
773 /* I assume that STACKLEVEL is a stronger indicator than PL_top_env changes */
774 assert (("ERROR: current top_env must equal previous top_env", PL_top_env == prev__cctx->idle_te));
775
776 prev->cctx = 0;
777
778 cctx_put (prev__cctx);
779 prev__cctx->inuse = 0;
780 }
781
782 if (!next->cctx)
783 {
784 next->cctx = cctx_get ();
785 assert (!next->cctx->inuse);
786 next->cctx->inuse = 1;
787 }
788
789 if (prev__cctx != next->cctx)
790 {
791 prev__cctx->top_env = PL_top_env;
792 PL_top_env = next->cctx->top_env;
793 coro_transfer (&prev__cctx->cctx, &next->cctx->cctx);
794 }
795
796 free_coro_mortal ();
797 UNLOCK;
798 }
799}
800
801struct transfer_args
802{
803 struct coro *prev, *next;
804};
805
806#define TRANSFER(ta) transfer ((ta).prev, (ta).next)
807
808static int
809coro_state_destroy (struct coro *coro)
810{
811 if (coro->flags & CF_DESTROYED)
812 return 0;
813
814 coro->flags |= CF_DESTROYED;
815
816 if (coro->mainstack && coro->mainstack != main_mainstack)
817 {
818 assert (!(coro->flags & CF_RUNNING));
819
820 struct coro temp;
821 Zero (&temp, 1, struct coro);
822 temp.save = CORO_SAVE_ALL;
823
824 if (coro->flags & CF_RUNNING)
825 croak ("FATAL: tried to destroy currently running coroutine");
826
827 save_perl (&temp);
828 load_perl (coro);
829
830 coro_destroy_stacks ();
831
832 load_perl (&temp); /* this will get rid of defsv etc.. */
833
834 coro->mainstack = 0;
835 }
836
837 cctx_destroy (coro->cctx);
838 SvREFCNT_dec (coro->args);
839
840 return 1;
841}
842
843static int
844coro_state_free (pTHX_ SV *sv, MAGIC *mg)
845{
846 struct coro *coro = (struct coro *)mg->mg_ptr;
847 mg->mg_ptr = 0;
848
849 if (--coro->refcnt < 0)
850 {
851 coro_state_destroy (coro);
852 Safefree (coro);
853 }
854
855 return 0;
856}
857
858static int
859coro_state_dup (pTHX_ MAGIC *mg, CLONE_PARAMS *params)
860{
861 struct coro *coro = (struct coro *)mg->mg_ptr;
862
863 ++coro->refcnt;
864
865 return 0;
866}
867
868static MGVTBL coro_state_vtbl = {
869 0, 0, 0, 0,
870 coro_state_free,
871 0,
872#ifdef MGf_DUP
873 coro_state_dup,
874#else
875# define MGf_DUP 0
876#endif
877};
878
879static struct coro *
880SvSTATE (SV *coro)
881{
882 HV *stash;
883 MAGIC *mg;
884
885 if (SvROK (coro))
886 coro = SvRV (coro);
887
888 stash = SvSTASH (coro);
889 if (stash != coro_stash && stash != coro_state_stash)
890 {
891 /* very slow, but rare, check */
892 if (!sv_derived_from (sv_2mortal (newRV_inc (coro)), "Coro::State"))
893 croak ("Coro::State object required");
894 }
895
896 mg = SvMAGIC (coro);
897 assert (mg->mg_type == PERL_MAGIC_ext);
898 return (struct coro *)mg->mg_ptr;
899}
900
901static void
902prepare_transfer (struct transfer_args *ta, SV *prev_sv, SV *next_sv)
903{
904 ta->prev = SvSTATE (prev_sv);
905 ta->next = SvSTATE (next_sv);
906}
907
908static void
909api_transfer (SV *prev_sv, SV *next_sv)
910{
911 struct transfer_args ta;
912
913 prepare_transfer (&ta, prev_sv, next_sv);
914 TRANSFER (ta);
915}
916
917static int
918api_save (SV *coro_sv, int new_save)
919{
920 struct coro *coro = SvSTATE (coro_sv);
921 int old_save = coro->save;
922
923 if (new_save >= 0)
924 coro->save = new_save;
925
926 return old_save;
927}
928
929/** Coro ********************************************************************/
930
931#define PRIO_MAX 3
932#define PRIO_HIGH 1
933#define PRIO_NORMAL 0
934#define PRIO_LOW -1
935#define PRIO_IDLE -3
936#define PRIO_MIN -4
937
938/* for Coro.pm */
939static SV *coro_current;
940static AV *coro_ready [PRIO_MAX-PRIO_MIN+1];
941static int coro_nready;
942
943static void
944coro_enq (SV *coro_sv)
945{
946 av_push (coro_ready [SvSTATE (coro_sv)->prio - PRIO_MIN], coro_sv);
947 coro_nready++;
948}
949
950static SV *
951coro_deq (int min_prio)
952{
953 int prio = PRIO_MAX - PRIO_MIN;
954
955 min_prio -= PRIO_MIN;
956 if (min_prio < 0)
957 min_prio = 0;
958
959 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; )
960 if (AvFILLp (coro_ready [prio]) >= 0)
299 { 961 {
300 AV *padlist = (AV *)POPs; 962 coro_nready--;
301 963 return av_shift (coro_ready [prio]);
302 unuse_padlist (CvPADLIST(cv));
303 CvPADLIST(cv) = padlist;
304 CvDEPTH(cv) = (I32)POPs;
305
306#ifdef USE_THREADS
307 CvOWNER(cv) = (struct perl_thread *)POPs;
308 error does not work either
309#endif
310 } 964 }
311 965
312 PUTBACK; 966 return 0;
313 }
314} 967}
315 968
316/* this is an EXACT copy of S_nuke_stacks in perl.c, which is unfortunately static */ 969static int
317STATIC void 970api_ready (SV *coro_sv)
318S_nuke_stacks(pTHX)
319{ 971{
320 while (PL_curstackinfo->si_next) 972 struct coro *coro;
321 PL_curstackinfo = PL_curstackinfo->si_next; 973
322 while (PL_curstackinfo) { 974 if (SvROK (coro_sv))
323 PERL_SI *p = PL_curstackinfo->si_prev; 975 coro_sv = SvRV (coro_sv);
324 /* curstackinfo->si_stack got nuked by sv_free_arenas() */ 976
325 Safefree(PL_curstackinfo->si_cxstack); 977 coro = SvSTATE (coro_sv);
326 Safefree(PL_curstackinfo); 978
327 PL_curstackinfo = p; 979 if (coro->flags & CF_READY)
980 return 0;
981
982 coro->flags |= CF_READY;
983
984 LOCK;
985 coro_enq (SvREFCNT_inc (coro_sv));
986 UNLOCK;
987
988 return 1;
989}
990
991static int
992api_is_ready (SV *coro_sv)
993{
994 return !!(SvSTATE (coro_sv)->flags & CF_READY);
995}
996
997static void
998prepare_schedule (struct transfer_args *ta)
999{
1000 SV *prev_sv, *next_sv;
1001
1002 for (;;)
328 } 1003 {
329 Safefree(PL_tmps_stack); 1004 LOCK;
330 Safefree(PL_markstack); 1005 next_sv = coro_deq (PRIO_MIN);
331 Safefree(PL_scopestack); 1006 UNLOCK;
332 Safefree(PL_savestack);
333 Safefree(PL_retstack);
334}
335 1007
336#define SUB_INIT "Coro::State::_newcoro" 1008 /* nothing to schedule: call the idle handler */
1009 if (!next_sv)
1010 {
1011 dSP;
1012
1013 ENTER;
1014 SAVETMPS;
1015
1016 PUSHMARK (SP);
1017 PUTBACK;
1018 call_sv (get_sv ("Coro::idle", FALSE), G_DISCARD);
1019
1020 FREETMPS;
1021 LEAVE;
1022 continue;
1023 }
1024
1025 ta->next = SvSTATE (next_sv);
1026
1027 /* cannot transfer to destroyed coros, skip and look for next */
1028 if (ta->next->flags & CF_DESTROYED)
1029 {
1030 SvREFCNT_dec (next_sv);
1031 continue;
1032 }
1033
1034 break;
1035 }
1036
1037 /* free this only after the transfer */
1038 prev_sv = SvRV (coro_current);
1039 SvRV_set (coro_current, next_sv);
1040 ta->prev = SvSTATE (prev_sv);
1041
1042 assert (ta->next->flags & CF_READY);
1043 ta->next->flags &= ~CF_READY;
1044
1045 LOCK;
1046 free_coro_mortal ();
1047 coro_mortal = prev_sv;
1048 UNLOCK;
1049}
1050
1051static void
1052prepare_cede (struct transfer_args *ta)
1053{
1054 api_ready (coro_current);
1055 prepare_schedule (ta);
1056}
1057
1058static int
1059prepare_cede_notself (struct transfer_args *ta)
1060{
1061 if (coro_nready)
1062 {
1063 SV *prev = SvRV (coro_current);
1064 prepare_schedule (ta);
1065 api_ready (prev);
1066 return 1;
1067 }
1068 else
1069 return 0;
1070}
1071
1072static void
1073api_schedule (void)
1074{
1075 struct transfer_args ta;
1076
1077 prepare_schedule (&ta);
1078 TRANSFER (ta);
1079}
1080
1081static int
1082api_cede (void)
1083{
1084 struct transfer_args ta;
1085
1086 prepare_cede (&ta);
1087
1088 if (ta.prev != ta.next)
1089 {
1090 TRANSFER (ta);
1091 return 1;
1092 }
1093 else
1094 return 0;
1095}
1096
1097static int
1098api_cede_notself (void)
1099{
1100 struct transfer_args ta;
1101
1102 if (prepare_cede_notself (&ta))
1103 {
1104 TRANSFER (ta);
1105 return 1;
1106 }
1107 else
1108 return 0;
1109}
337 1110
338MODULE = Coro::State PACKAGE = Coro::State 1111MODULE = Coro::State PACKAGE = Coro::State
339 1112
340PROTOTYPES: ENABLE 1113PROTOTYPES: DISABLE
341 1114
342BOOT: 1115BOOT:
343 if (!padlist_cache) 1116{
344 padlist_cache = newHV (); 1117#ifdef USE_ITHREADS
1118 MUTEX_INIT (&coro_mutex);
1119#endif
1120 BOOT_PAGESIZE;
345 1121
346Coro::State 1122 coro_state_stash = gv_stashpv ("Coro::State", TRUE);
347_newprocess(args) 1123
348 SV * args 1124 newCONSTSUB (coro_state_stash, "SAVE_DEFAV", newSViv (CORO_SAVE_DEFAV));
349 PROTOTYPE: $ 1125 newCONSTSUB (coro_state_stash, "SAVE_DEFSV", newSViv (CORO_SAVE_DEFSV));
1126 newCONSTSUB (coro_state_stash, "SAVE_ERRSV", newSViv (CORO_SAVE_ERRSV));
1127 newCONSTSUB (coro_state_stash, "SAVE_IRSSV", newSViv (CORO_SAVE_IRSSV));
1128 newCONSTSUB (coro_state_stash, "SAVE_ALL", newSViv (CORO_SAVE_ALL));
1129
1130 main_mainstack = PL_mainstack;
1131
1132 coroapi.ver = CORO_API_VERSION;
1133 coroapi.transfer = api_transfer;
1134
1135 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL));
1136}
1137
1138SV *
1139new (char *klass, ...)
350 CODE: 1140 CODE:
351 Coro__State coro; 1141{
1142 struct coro *coro;
1143 HV *hv;
1144 int i;
352 1145
353 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV)
354 croak ("Coro::State::newprocess expects an arrayref");
355
356 New (0, coro, 1, struct coro); 1146 Newz (0, coro, 1, struct coro);
1147 coro->args = newAV ();
1148 coro->save = CORO_SAVE_ALL;
1149 coro->flags = CF_NEW;
357 1150
358 coro->mainstack = 0; /* actual work is done inside transfer */ 1151 hv = newHV ();
359 coro->args = (AV *)SvREFCNT_inc (SvRV (args)); 1152 sv_magicext ((SV *)hv, 0, PERL_MAGIC_ext, &coro_state_vtbl, (char *)coro, 0)->mg_flags |= MGf_DUP;
1153 RETVAL = sv_bless (newRV_noinc ((SV *)hv), gv_stashpv (klass, 1));
360 1154
361 RETVAL = coro; 1155 for (i = 1; i < items; i++)
1156 av_push (coro->args, newSVsv (ST (i)));
1157}
362 OUTPUT: 1158 OUTPUT:
363 RETVAL 1159 RETVAL
364 1160
1161int
1162save (SV *coro, int new_save = -1)
1163 CODE:
1164 RETVAL = api_save (coro, new_save);
1165 OUTPUT:
1166 RETVAL
1167
365void 1168void
366transfer(prev,next) 1169_set_stacklevel (...)
367 Coro::State_or_hashref prev 1170 ALIAS:
368 Coro::State_or_hashref next 1171 Coro::State::transfer = 1
1172 Coro::schedule = 2
1173 Coro::cede = 3
1174 Coro::cede_notself = 4
369 CODE: 1175 CODE:
1176{
1177 struct transfer_args ta;
370 1178
371 if (prev != next) 1179 switch (ix)
372 { 1180 {
373 PUTBACK;
374 SAVE (aTHX_ prev);
375
376 /*
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;
387 }
388 else 1181 case 0:
1182 ta.prev = (struct coro *)INT2PTR (coro_cctx *, SvIV (ST (0)));
1183 ta.next = 0;
389 { 1184 break;
390 /*
391 * emulate part of the perl startup here.
392 */
393 UNOP myop;
394 1185
395 init_stacks (); 1186 case 1:
396 PL_op = (OP *)&myop; 1187 if (items != 2)
397 /*PL_curcop = 0;*/ 1188 croak ("Coro::State::transfer (prev,next) expects two arguments, not %d", items);
398 GvAV (PL_defgv) = (SV *)SvREFCNT_inc (next->args);
399 1189
400 SPAGAIN; 1190 prepare_transfer (&ta, ST (0), ST (1));
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 } 1191 break;
1192
1193 case 2:
1194 prepare_schedule (&ta);
1195 break;
1196
1197 case 3:
1198 prepare_cede (&ta);
1199 break;
1200
1201 case 4:
1202 if (!prepare_cede_notself (&ta))
1203 XSRETURN_EMPTY;
1204
1205 break;
419 } 1206 }
420 1207
1208 BARRIER;
1209 TRANSFER (ta);
1210
1211 if (GIMME_V != G_VOID && ta.next != ta.prev)
1212 XSRETURN_YES;
1213}
1214
1215bool
1216_destroy (SV *coro_sv)
1217 CODE:
1218 RETVAL = coro_state_destroy (SvSTATE (coro_sv));
1219 OUTPUT:
1220 RETVAL
1221
421void 1222void
422DESTROY(coro) 1223_exit (code)
423 Coro::State coro 1224 int code
1225 PROTOTYPE: $
1226 CODE:
1227 _exit (code);
1228
1229int
1230cctx_count ()
1231 CODE:
1232 RETVAL = cctx_count;
1233 OUTPUT:
1234 RETVAL
1235
1236int
1237cctx_idle ()
1238 CODE:
1239 RETVAL = cctx_idle;
1240 OUTPUT:
1241 RETVAL
1242
1243MODULE = Coro::State PACKAGE = Coro
1244
1245BOOT:
1246{
1247 int i;
1248
1249 coro_stash = gv_stashpv ("Coro", TRUE);
1250
1251 newCONSTSUB (coro_stash, "PRIO_MAX", newSViv (PRIO_MAX));
1252 newCONSTSUB (coro_stash, "PRIO_HIGH", newSViv (PRIO_HIGH));
1253 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (PRIO_NORMAL));
1254 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (PRIO_LOW));
1255 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (PRIO_IDLE));
1256 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (PRIO_MIN));
1257
1258 coro_current = get_sv ("Coro::current", FALSE);
1259 SvREADONLY_on (coro_current);
1260
1261 for (i = PRIO_MAX - PRIO_MIN + 1; i--; )
1262 coro_ready[i] = newAV ();
1263
1264 {
1265 SV *sv = perl_get_sv("Coro::API", 1);
1266
1267 coroapi.schedule = api_schedule;
1268 coroapi.save = api_save;
1269 coroapi.cede = api_cede;
1270 coroapi.cede_notself = api_cede_notself;
1271 coroapi.ready = api_ready;
1272 coroapi.is_ready = api_is_ready;
1273 coroapi.nready = &coro_nready;
1274 coroapi.current = coro_current;
1275
1276 GCoroAPI = &coroapi;
1277 sv_setiv (sv, (IV)&coroapi);
1278 SvREADONLY_on (sv);
1279 }
1280}
1281
1282void
1283_set_current (SV *current)
1284 PROTOTYPE: $
1285 CODE:
1286 SvREFCNT_dec (SvRV (coro_current));
1287 SvRV_set (coro_current, SvREFCNT_inc (SvRV (current)));
1288
1289int
1290prio (Coro::State coro, int newprio = 0)
1291 ALIAS:
1292 nice = 1
424 CODE: 1293 CODE:
1294{
1295 RETVAL = coro->prio;
425 1296
426 if (coro->mainstack) 1297 if (items > 1)
427 { 1298 {
428 struct coro temp; 1299 if (ix)
1300 newprio = coro->prio - newprio;
429 1301
430 PUTBACK; 1302 if (newprio < PRIO_MIN) newprio = PRIO_MIN;
431 SAVE(aTHX_ (&temp)); 1303 if (newprio > PRIO_MAX) newprio = PRIO_MAX;
432 LOAD(aTHX_ coro);
433 1304
434 S_nuke_stacks (); 1305 coro->prio = newprio;
435 SvREFCNT_dec ((SV *)GvAV (PL_defgv));
436
437 LOAD((&temp));
438 SPAGAIN;
439 } 1306 }
1307}
1308 OUTPUT:
1309 RETVAL
440 1310
441 SvREFCNT_dec (coro->args); 1311SV *
442 Safefree (coro); 1312ready (SV *self)
1313 PROTOTYPE: $
1314 CODE:
1315 RETVAL = boolSV (api_ready (self));
1316 OUTPUT:
1317 RETVAL
443 1318
1319SV *
1320is_ready (SV *self)
1321 PROTOTYPE: $
1322 CODE:
1323 RETVAL = boolSV (api_is_ready (self));
1324 OUTPUT:
1325 RETVAL
444 1326
1327int
1328nready (...)
1329 PROTOTYPE:
1330 CODE:
1331 RETVAL = coro_nready;
1332 OUTPUT:
1333 RETVAL
1334
1335MODULE = Coro::State PACKAGE = Coro::AIO
1336
1337SV *
1338_get_state ()
1339 CODE:
1340{
1341 struct io_state *data;
1342
1343 RETVAL = newSV (sizeof (struct io_state));
1344 data = (struct io_state *)SvPVX (RETVAL);
1345 SvCUR_set (RETVAL, sizeof (struct io_state));
1346 SvPOK_only (RETVAL);
1347
1348 data->errorno = errno;
1349 data->laststype = PL_laststype;
1350 data->laststatval = PL_laststatval;
1351 data->statcache = PL_statcache;
1352}
1353 OUTPUT:
1354 RETVAL
1355
1356void
1357_set_state (char *data_)
1358 PROTOTYPE: $
1359 CODE:
1360{
1361 struct io_state *data = (void *)data_;
1362
1363 errno = data->errorno;
1364 PL_laststype = data->laststype;
1365 PL_laststatval = data->laststatval;
1366 PL_statcache = data->statcache;
1367}
1368

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines