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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines