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.6 by root, Tue Jul 17 15:42:28 2001 UTC vs.
Revision 1.325 by root, Sun Nov 23 06:48:45 2008 UTC

1#include "libcoro/coro.c"
2
3#define PERL_NO_GET_CONTEXT
4#define PERL_EXT
5
1#include "EXTERN.h" 6#include "EXTERN.h"
2#include "perl.h" 7#include "perl.h"
3#include "XSUB.h" 8#include "XSUB.h"
9#include "perliol.h"
4 10
5#if 0 11#include "patchlevel.h"
6# define CHK(x) (void *)0 12
13#include <stdio.h>
14#include <errno.h>
15#include <assert.h>
16
17#ifdef WIN32
18# undef setjmp
19# undef longjmp
20# undef _exit
21# define setjmp _setjmp /* deep magic */
7#else 22#else
8# define CHK(x) if (!(x)) croak("FATAL, CHK: " #x) 23# include <inttypes.h> /* most portable stdint.h */
24#endif
25
26#ifdef HAVE_MMAP
27# include <unistd.h>
28# include <sys/mman.h>
29# ifndef MAP_ANONYMOUS
30# ifdef MAP_ANON
31# define MAP_ANONYMOUS MAP_ANON
32# else
33# undef HAVE_MMAP
34# endif
9#endif 35# endif
36# include <limits.h>
37# ifndef PAGESIZE
38# define PAGESIZE pagesize
39# define BOOT_PAGESIZE pagesize = sysconf (_SC_PAGESIZE)
40static long pagesize;
41# else
42# define BOOT_PAGESIZE (void)0
43# endif
44#else
45# define PAGESIZE 0
46# define BOOT_PAGESIZE (void)0
47#endif
10 48
49#if CORO_USE_VALGRIND
50# include <valgrind/valgrind.h>
51#endif
52
53/* the maximum number of idle cctx that will be pooled */
54static int cctx_max_idle = 4;
55
56#define PERL_VERSION_ATLEAST(a,b,c) \
57 (PERL_REVISION > (a) \
58 || (PERL_REVISION == (a) \
59 && (PERL_VERSION > (b) \
60 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))))
61
62#if !PERL_VERSION_ATLEAST (5,6,0)
63# ifndef PL_ppaddr
64# define PL_ppaddr ppaddr
65# endif
66# ifndef call_sv
67# define call_sv perl_call_sv
68# endif
69# ifndef get_sv
70# define get_sv perl_get_sv
71# endif
72# ifndef get_cv
73# define get_cv perl_get_cv
74# endif
75# ifndef IS_PADGV
76# define IS_PADGV(v) 0
77# endif
78# ifndef IS_PADCONST
79# define IS_PADCONST(v) 0
80# endif
81#endif
82
83/* 5.11 */
84#ifndef CxHASARGS
85# define CxHASARGS(cx) (cx)->blk_sub.hasargs
86#endif
87
88/* 5.10.0 */
89#ifndef SvREFCNT_inc_NN
90# define SvREFCNT_inc_NN(sv) SvREFCNT_inc (sv)
91#endif
92
93/* 5.8.8 */
94#ifndef GV_NOTQUAL
95# define GV_NOTQUAL 0
96#endif
97#ifndef newSV
98# define newSV(l) NEWSV(0,l)
99#endif
100#ifndef CvISXSUB_on
101# define CvISXSUB_on(cv) (void)cv
102#endif
103#ifndef CvISXSUB
104# define CvISXSUB(cv) (CvXSUB (cv) ? TRUE : FALSE)
105#endif
106#ifndef Newx
107# define Newx(ptr,nitems,type) New (0,ptr,nitems,type)
108#endif
109
110/* 5.8.7 */
111#ifndef SvRV_set
112# define SvRV_set(s,v) SvRV(s) = (v)
113#endif
114
115#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64
116# undef CORO_STACKGUARD
117#endif
118
119#ifndef CORO_STACKGUARD
120# define CORO_STACKGUARD 0
121#endif
122
123/* prefer perl internal functions over our own? */
124#ifndef CORO_PREFER_PERL_FUNCTIONS
125# define CORO_PREFER_PERL_FUNCTIONS 0
126#endif
127
128/* The next macros try to return the current stack pointer, in an as
129 * portable way as possible. */
130#if __GNUC__ >= 4
131# define dSTACKLEVEL int stacklevel_dummy
132# define STACKLEVEL __builtin_frame_address (0)
133#else
134# define dSTACKLEVEL volatile void *stacklevel
135# define STACKLEVEL ((void *)&stacklevel)
136#endif
137
138#define IN_DESTRUCT (PL_main_cv == Nullcv)
139
140#if __GNUC__ >= 3
141# define attribute(x) __attribute__(x)
142# define expect(expr,value) __builtin_expect ((expr),(value))
143# define INLINE static inline
144#else
145# define attribute(x)
146# define expect(expr,value) (expr)
147# define INLINE static
148#endif
149
150#define expect_false(expr) expect ((expr) != 0, 0)
151#define expect_true(expr) expect ((expr) != 0, 1)
152
153#define NOINLINE attribute ((noinline))
154
155#include "CoroAPI.h"
156#define GCoroAPI (&coroapi) /* very sneaky */
157
158#ifdef USE_ITHREADS
159# if CORO_PTHREAD
160static void *coro_thx;
161# endif
162#endif
163
164static double (*nvtime)(); /* so why doesn't it take void? */
165
166/* we hijack an hopefully unused CV flag for our purposes */
167#define CVf_SLF 0x4000
168static OP *pp_slf (pTHX);
169
170static U32 cctx_gen;
171static size_t cctx_stacksize = CORO_STACKSIZE;
172static struct CoroAPI coroapi;
173static AV *main_mainstack; /* used to differentiate between $main and others */
174static JMPENV *main_top_env;
175static HV *coro_state_stash, *coro_stash;
176static volatile SV *coro_mortal; /* will be freed/thrown after next transfer */
177
178static AV *av_destroy; /* destruction queue */
179static SV *sv_manager; /* the manager coro */
180
181static GV *irsgv; /* $/ */
182static GV *stdoutgv; /* *STDOUT */
183static SV *rv_diehook;
184static SV *rv_warnhook;
185static HV *hv_sig; /* %SIG */
186
187/* async_pool helper stuff */
188static SV *sv_pool_rss;
189static SV *sv_pool_size;
190static SV *sv_async_pool_idle; /* description string */
191static AV *av_async_pool; /* idle pool */
192static SV *sv_Coro; /* class string */
193static CV *cv_pool_handler;
194static CV *cv_coro_state_new;
195
196/* Coro::AnyEvent */
197static SV *sv_activity;
198
199static struct coro_cctx *cctx_first;
200static int cctx_count, cctx_idle;
201
202enum {
203 CC_MAPPED = 0x01,
204 CC_NOREUSE = 0x02, /* throw this away after tracing */
205 CC_TRACE = 0x04,
206 CC_TRACE_SUB = 0x08, /* trace sub calls */
207 CC_TRACE_LINE = 0x10, /* trace each statement */
208 CC_TRACE_ALL = CC_TRACE_SUB | CC_TRACE_LINE,
209};
210
211/* this is a structure representing a c-level coroutine */
212typedef struct coro_cctx
213{
214 struct coro_cctx *next;
215
216 /* the stack */
217 void *sptr;
218 size_t ssize;
219
220 /* cpu state */
221 void *idle_sp; /* sp of top-level transfer/schedule/cede call */
222 JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */
223 JMPENV *top_env;
224 coro_context cctx;
225
226 U32 gen;
227#if CORO_USE_VALGRIND
228 int valgrind_id;
229#endif
230 unsigned char flags;
231} coro_cctx;
232
233coro_cctx *cctx_current; /* the currently running cctx */
234
235/*****************************************************************************/
236
237enum {
238 CF_RUNNING = 0x0001, /* coroutine is running */
239 CF_READY = 0x0002, /* coroutine is ready */
240 CF_NEW = 0x0004, /* has never been switched to */
241 CF_DESTROYED = 0x0008, /* coroutine data has been freed */
242};
243
244/* the structure where most of the perl state is stored, overlaid on the cxstack */
245typedef struct
246{
247 SV *defsv;
248 AV *defav;
249 SV *errsv;
250 SV *irsgv;
251#define VAR(name,type) type name;
252# include "state.h"
253#undef VAR
254} perl_slots;
255
256#define SLOT_COUNT ((sizeof (perl_slots) + sizeof (PERL_CONTEXT) - 1) / sizeof (PERL_CONTEXT))
257
258/* this is a structure representing a perl-level coroutine */
11struct coro { 259struct coro {
12 U8 dowarn; 260 /* the C coroutine allocated to this perl coroutine, if any */
13 AV *defav; 261 coro_cctx *cctx;
14 262
15 PERL_SI *curstackinfo; 263 /* state data */
16 AV *curstack; 264 struct CoroSLF slf_frame; /* saved slf frame */
17 AV *mainstack; 265 AV *mainstack;
18 SV **stack_sp; 266 perl_slots *slot; /* basically the saved 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 267
41 AV *args; 268 CV *startcv; /* the CV to execute */
269 AV *args; /* data associated with this coroutine (initial args) */
270 int refcnt; /* coroutines are refcounted, yes */
271 int flags; /* CF_ flags */
272 HV *hv; /* the perl hash associated with this coro, if any */
273 void (*on_destroy)(pTHX_ struct coro *coro);
274
275 /* statistics */
276 int usecount; /* number of transfers to this coro */
277
278 /* coro process data */
279 int prio;
280 SV *except; /* exception to be thrown */
281 SV *rouse_cb;
282
283 /* async_pool */
284 SV *saved_deffh;
285 SV *invoke_cb;
286 AV *invoke_av;
287
288 /* linked list */
289 struct coro *next, *prev;
42}; 290};
43 291
44typedef struct coro *Coro__State; 292typedef struct coro *Coro__State;
45typedef struct coro *Coro__State_or_hashref; 293typedef struct coro *Coro__State_or_hashref;
46 294
47static HV *padlist_cache; 295/* the following variables are effectively part of the perl context */
296/* and get copied between struct coro and these variables */
297/* the mainr easonw e don't support windows process emulation */
298static struct CoroSLF slf_frame; /* the current slf frame */
48 299
49/* mostly copied from op.c:cv_clone2 */ 300/** Coro ********************************************************************/
50STATIC AV * 301
51clone_padlist (AV *protopadlist) 302#define PRIO_MAX 3
303#define PRIO_HIGH 1
304#define PRIO_NORMAL 0
305#define PRIO_LOW -1
306#define PRIO_IDLE -3
307#define PRIO_MIN -4
308
309/* for Coro.pm */
310static SV *coro_current;
311static SV *coro_readyhook;
312static AV *coro_ready [PRIO_MAX - PRIO_MIN + 1];
313static CV *cv_coro_run, *cv_coro_terminate;
314static struct coro *coro_first;
315#define coro_nready coroapi.nready
316
317/** lowlevel stuff **********************************************************/
318
319static SV *
320coro_get_sv (pTHX_ const char *name, int create)
52{ 321{
53 AV *av; 322#if PERL_VERSION_ATLEAST (5,10,0)
54 I32 ix; 323 /* silence stupid and wrong 5.10 warning that I am unable to switch off */
55 AV *protopad_name = (AV *) * av_fetch (protopadlist, 0, FALSE); 324 get_sv (name, create);
56 AV *protopad = (AV *) * av_fetch (protopadlist, 1, FALSE); 325#endif
57 SV **pname = AvARRAY (protopad_name); 326 return get_sv (name, create);
58 SV **ppad = AvARRAY (protopad); 327}
59 I32 fname = AvFILLp (protopad_name); 328
60 I32 fpad = AvFILLp (protopad); 329static AV *
330coro_get_av (pTHX_ const char *name, int create)
331{
332#if PERL_VERSION_ATLEAST (5,10,0)
333 /* silence stupid and wrong 5.10 warning that I am unable to switch off */
334 get_av (name, create);
335#endif
336 return get_av (name, create);
337}
338
339static HV *
340coro_get_hv (pTHX_ const char *name, int create)
341{
342#if PERL_VERSION_ATLEAST (5,10,0)
343 /* silence stupid and wrong 5.10 warning that I am unable to switch off */
344 get_hv (name, create);
345#endif
346 return get_hv (name, create);
347}
348
349/* may croak */
350INLINE CV *
351coro_sv_2cv (pTHX_ SV *sv)
352{
353 HV *st;
354 GV *gvp;
355 return sv_2cv (sv, &st, &gvp, 0);
356}
357
358static AV *
359coro_derive_padlist (pTHX_ CV *cv)
360{
361 AV *padlist = CvPADLIST (cv);
61 AV *newpadlist, *newpad_name, *newpad; 362 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 363
72 newpadlist = newAV (); 364 newpadlist = newAV ();
73 AvREAL_off (newpadlist); 365 AvREAL_off (newpadlist);
74 av_store (newpadlist, 0, (SV *) newpad_name); 366#if PERL_VERSION_ATLEAST (5,10,0)
367 Perl_pad_push (aTHX_ padlist, AvFILLp (padlist) + 1);
368#else
369 Perl_pad_push (aTHX_ padlist, AvFILLp (padlist) + 1, 1);
370#endif
371 newpad = (AV *)AvARRAY (padlist)[AvFILLp (padlist)];
372 --AvFILLp (padlist);
373
374 av_store (newpadlist, 0, SvREFCNT_inc_NN (*av_fetch (padlist, 0, FALSE)));
75 av_store (newpadlist, 1, (SV *) newpad); 375 av_store (newpadlist, 1, (SV *)newpad);
76 376
77 av = newAV (); /* will be @_ */ 377 return newpadlist;
78 av_extend (av, 0); 378}
79 av_store (newpad, 0, (SV *) av);
80 AvFLAGS (av) = AVf_REIFY;
81 379
82 for (ix = fpad; ix > 0; ix--) 380static void
381free_padlist (pTHX_ AV *padlist)
382{
383 /* may be during global destruction */
384 if (SvREFCNT (padlist))
83 { 385 {
84 SV *namesv = (ix <= fname) ? pname[ix] : Nullsv; 386 I32 i = AvFILLp (padlist);
85 if (namesv && namesv != &PL_sv_undef) 387 while (i >= 0)
86 { 388 {
87 char *name = SvPVX (namesv); /* XXX */ 389 SV **svp = av_fetch (padlist, i--, FALSE);
88 if (SvFLAGS (namesv) & SVf_FAKE || *name == '&') 390 if (svp)
89 { /* lexical from outside? */
90 npad[ix] = SvREFCNT_inc (ppad[ix]);
91 } 391 {
92 else
93 { /* our own lexical */
94 SV *sv; 392 SV *sv;
95 if (*name == '&') 393 while (&PL_sv_undef != (sv = av_pop ((AV *)*svp)))
96 sv = SvREFCNT_inc (ppad[ix]); 394 SvREFCNT_dec (sv);
97 else if (*name == '@') 395
98 sv = (SV *) newAV (); 396 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 } 397 }
107 } 398 }
108 else if (IS_PADGV (ppad[ix]) || IS_PADCONST (ppad[ix]))
109 {
110 npad[ix] = SvREFCNT_inc (ppad[ix]);
111 }
112 else
113 {
114 SV *sv = NEWSV (0, 0);
115 SvPADTMP_on (sv);
116 npad[ix] = sv;
117 }
118 }
119 399
120#if 0 /* NONOTUNDERSTOOD */
121 /* Now that vars are all in place, clone nested closures. */
122
123 for (ix = fpad; ix > 0; ix--) {
124 SV* namesv = (ix <= fname) ? pname[ix] : Nullsv;
125 if (namesv
126 && namesv != &PL_sv_undef
127 && !(SvFLAGS(namesv) & SVf_FAKE)
128 && *SvPVX(namesv) == '&'
129 && CvCLONE(ppad[ix]))
130 {
131 CV *kid = cv_clone((CV*)ppad[ix]);
132 SvREFCNT_dec(ppad[ix]);
133 CvCLONE_on(kid);
134 SvPADMY_on(kid);
135 npad[ix] = (SV*)kid;
136 }
137 }
138#endif
139
140 return newpadlist;
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); 400 SvREFCNT_dec ((SV*)padlist);
401 }
402}
403
404static int
405coro_cv_free (pTHX_ SV *sv, MAGIC *mg)
406{
407 AV *padlist;
408 AV *av = (AV *)mg->mg_obj;
409
410 /* casting is fun. */
411 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
412 free_padlist (aTHX_ padlist);
413
414 SvREFCNT_dec (av); /* sv_magicext increased the refcount */
415
416 return 0;
417}
418
419#define CORO_MAGIC_type_cv 26
420#define CORO_MAGIC_type_state PERL_MAGIC_ext
421
422static MGVTBL coro_cv_vtbl = {
423 0, 0, 0, 0,
424 coro_cv_free
425};
426
427#define CORO_MAGIC_NN(sv, type) \
428 (expect_true (SvMAGIC (sv)->mg_type == type) \
429 ? SvMAGIC (sv) \
430 : mg_find (sv, type))
431
432#define CORO_MAGIC(sv, type) \
433 (expect_true (SvMAGIC (sv)) \
434 ? CORO_MAGIC_NN (sv, type) \
435 : 0)
436
437#define CORO_MAGIC_cv(cv) CORO_MAGIC (((SV *)(cv)), CORO_MAGIC_type_cv)
438#define CORO_MAGIC_state(sv) CORO_MAGIC_NN (((SV *)(sv)), CORO_MAGIC_type_state)
439
440INLINE struct coro *
441SvSTATE_ (pTHX_ SV *coro)
442{
443 HV *stash;
444 MAGIC *mg;
445
446 if (SvROK (coro))
447 coro = SvRV (coro);
448
449 if (expect_false (SvTYPE (coro) != SVt_PVHV))
450 croak ("Coro::State object required");
451
452 stash = SvSTASH (coro);
453 if (expect_false (stash != coro_stash && stash != coro_state_stash))
454 {
455 /* very slow, but rare, check */
456 if (!sv_derived_from (sv_2mortal (newRV_inc (coro)), "Coro::State"))
457 croak ("Coro::State object required");
458 }
459
460 mg = CORO_MAGIC_state (coro);
461 return (struct coro *)mg->mg_ptr;
462}
463
464#define SvSTATE(sv) SvSTATE_ (aTHX_ (sv))
465
466/* faster than SvSTATE, but expects a coroutine hv */
467#define SvSTATE_hv(hv) ((struct coro *)CORO_MAGIC_NN ((SV *)hv, CORO_MAGIC_type_state)->mg_ptr)
468#define SvSTATE_current SvSTATE_hv (SvRV (coro_current))
469
470/* the next two functions merely cache the padlists */
471static void
472get_padlist (pTHX_ CV *cv)
473{
474 MAGIC *mg = CORO_MAGIC_cv (cv);
475 AV *av;
476
477 if (expect_true (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0))
478 CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--];
479 else
480 {
481#if CORO_PREFER_PERL_FUNCTIONS
482 /* this is probably cleaner? but also slower! */
483 /* in practise, it seems to be less stable */
484 CV *cp = Perl_cv_clone (aTHX_ cv);
485 CvPADLIST (cv) = CvPADLIST (cp);
486 CvPADLIST (cp) = 0;
487 SvREFCNT_dec (cp);
488#else
489 CvPADLIST (cv) = coro_derive_padlist (aTHX_ cv);
490#endif
491 }
492}
493
494static void
495put_padlist (pTHX_ CV *cv)
496{
497 MAGIC *mg = CORO_MAGIC_cv (cv);
498 AV *av;
499
500 if (expect_false (!mg))
501 mg = sv_magicext ((SV *)cv, (SV *)newAV (), CORO_MAGIC_type_cv, &coro_cv_vtbl, 0, 0);
502
503 av = (AV *)mg->mg_obj;
504
505 if (expect_false (AvFILLp (av) >= AvMAX (av)))
506 av_extend (av, AvMAX (av) + 1);
507
508 AvARRAY (av)[++AvFILLp (av)] = (SV *)CvPADLIST (cv);
509}
510
511/** load & save, init *******************************************************/
512
513static void
514load_perl (pTHX_ Coro__State c)
515{
516 perl_slots *slot = c->slot;
517 c->slot = 0;
518
519 PL_mainstack = c->mainstack;
520
521 GvSV (PL_defgv) = slot->defsv;
522 GvAV (PL_defgv) = slot->defav;
523 GvSV (PL_errgv) = slot->errsv;
524 GvSV (irsgv) = slot->irsgv;
525
526 #define VAR(name,type) PL_ ## name = slot->name;
527 # include "state.h"
528 #undef VAR
529
530 {
531 dSP;
532
533 CV *cv;
534
535 /* now do the ugly restore mess */
536 while (expect_true (cv = (CV *)POPs))
537 {
538 put_padlist (aTHX_ cv); /* mark this padlist as available */
539 CvDEPTH (cv) = PTR2IV (POPs);
540 CvPADLIST (cv) = (AV *)POPs;
541 }
542
543 PUTBACK;
159 } 544 }
160}
161 545
162/* the next tow functions merely cache the padlists */ 546 slf_frame = c->slf_frame;
163STATIC void 547 CORO_THROW = c->except;
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} 548}
173 549
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 550static void
189save_state(pTHX_ Coro__State c) 551save_perl (pTHX_ Coro__State c)
190{ 552{
553 c->except = CORO_THROW;
554 c->slf_frame = slf_frame;
555
191 { 556 {
192 dSP; 557 dSP;
193 I32 cxix = cxstack_ix; 558 I32 cxix = cxstack_ix;
559 PERL_CONTEXT *ccstk = cxstack;
194 PERL_SI *top_si = PL_curstackinfo; 560 PERL_SI *top_si = PL_curstackinfo;
195 PERL_CONTEXT *ccstk = cxstack;
196 561
197 /* 562 /*
198 * the worst thing you can imagine happens first - we have to save 563 * the worst thing you can imagine happens first - we have to save
199 * (and reinitialize) all cv's in the whole callchain :( 564 * (and reinitialize) all cv's in the whole callchain :(
200 */ 565 */
201 566
202 PUSHs (Nullsv); 567 XPUSHs (Nullsv);
203 /* this loop was inspired by pp_caller */ 568 /* this loop was inspired by pp_caller */
204 for (;;) 569 for (;;)
205 { 570 {
206 while (cxix >= 0) 571 while (expect_true (cxix >= 0))
207 { 572 {
208 PERL_CONTEXT *cx = &ccstk[cxix--]; 573 PERL_CONTEXT *cx = &ccstk[cxix--];
209 574
210 if (CxTYPE(cx) == CXt_SUB) 575 if (expect_true (CxTYPE (cx) == CXt_SUB || CxTYPE (cx) == CXt_FORMAT))
211 { 576 {
212 CV *cv = cx->blk_sub.cv; 577 CV *cv = cx->blk_sub.cv;
578
213 if (CvDEPTH(cv)) 579 if (expect_true (CvDEPTH (cv)))
214 { 580 {
215#ifdef USE_THREADS
216 XPUSHs ((SV *)CvOWNER(cv));
217#endif
218 EXTEND (SP, 3); 581 EXTEND (SP, 3);
219 PUSHs ((SV *)CvDEPTH(cv));
220 PUSHs ((SV *)CvPADLIST(cv)); 582 PUSHs ((SV *)CvPADLIST (cv));
583 PUSHs (INT2PTR (SV *, (IV)CvDEPTH (cv)));
221 PUSHs ((SV *)cv); 584 PUSHs ((SV *)cv);
222 585
223 get_padlist (cv);
224
225 CvDEPTH(cv) = 0; 586 CvDEPTH (cv) = 0;
226#ifdef USE_THREADS 587 get_padlist (aTHX_ cv);
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 } 588 }
233 } 589 }
234 else if (CxTYPE(cx) == CXt_FORMAT) 590 }
591
592 if (expect_true (top_si->si_type == PERLSI_MAIN))
593 break;
594
595 top_si = top_si->si_prev;
596 ccstk = top_si->si_cxstack;
597 cxix = top_si->si_cxix;
598 }
599
600 PUTBACK;
601 }
602
603 /* allocate some space on the context stack for our purposes */
604 /* we manually unroll here, as usually 2 slots is enough */
605 if (SLOT_COUNT >= 1) CXINC;
606 if (SLOT_COUNT >= 2) CXINC;
607 if (SLOT_COUNT >= 3) CXINC;
608 {
609 int i;
610 for (i = 3; i < SLOT_COUNT; ++i)
611 CXINC;
612 }
613 cxstack_ix -= SLOT_COUNT; /* undo allocation */
614
615 c->mainstack = PL_mainstack;
616
617 {
618 perl_slots *slot = c->slot = (perl_slots *)(cxstack + cxstack_ix + 1);
619
620 slot->defav = GvAV (PL_defgv);
621 slot->defsv = DEFSV;
622 slot->errsv = ERRSV;
623 slot->irsgv = GvSV (irsgv);
624
625 #define VAR(name,type) slot->name = PL_ ## name;
626 # include "state.h"
627 #undef VAR
628 }
629}
630
631/*
632 * allocate various perl stacks. This is almost an exact copy
633 * of perl.c:init_stacks, except that it uses less memory
634 * on the (sometimes correct) assumption that coroutines do
635 * not usually need a lot of stackspace.
636 */
637#if CORO_PREFER_PERL_FUNCTIONS
638# define coro_init_stacks(thx) init_stacks ()
639#else
640static void
641coro_init_stacks (pTHX)
642{
643 PL_curstackinfo = new_stackinfo(32, 8);
644 PL_curstackinfo->si_type = PERLSI_MAIN;
645 PL_curstack = PL_curstackinfo->si_stack;
646 PL_mainstack = PL_curstack; /* remember in case we switch stacks */
647
648 PL_stack_base = AvARRAY(PL_curstack);
649 PL_stack_sp = PL_stack_base;
650 PL_stack_max = PL_stack_base + AvMAX(PL_curstack);
651
652 New(50,PL_tmps_stack,32,SV*);
653 PL_tmps_floor = -1;
654 PL_tmps_ix = -1;
655 PL_tmps_max = 32;
656
657 New(54,PL_markstack,16,I32);
658 PL_markstack_ptr = PL_markstack;
659 PL_markstack_max = PL_markstack + 16;
660
661#ifdef SET_MARK_OFFSET
662 SET_MARK_OFFSET;
663#endif
664
665 New(54,PL_scopestack,8,I32);
666 PL_scopestack_ix = 0;
667 PL_scopestack_max = 8;
668
669 New(54,PL_savestack,24,ANY);
670 PL_savestack_ix = 0;
671 PL_savestack_max = 24;
672
673#if !PERL_VERSION_ATLEAST (5,10,0)
674 New(54,PL_retstack,4,OP*);
675 PL_retstack_ix = 0;
676 PL_retstack_max = 4;
677#endif
678}
679#endif
680
681/*
682 * destroy the stacks, the callchain etc...
683 */
684static void
685coro_destruct_stacks (pTHX)
686{
687 while (PL_curstackinfo->si_next)
688 PL_curstackinfo = PL_curstackinfo->si_next;
689
690 while (PL_curstackinfo)
691 {
692 PERL_SI *p = PL_curstackinfo->si_prev;
693
694 if (!IN_DESTRUCT)
695 SvREFCNT_dec (PL_curstackinfo->si_stack);
696
697 Safefree (PL_curstackinfo->si_cxstack);
698 Safefree (PL_curstackinfo);
699 PL_curstackinfo = p;
700 }
701
702 Safefree (PL_tmps_stack);
703 Safefree (PL_markstack);
704 Safefree (PL_scopestack);
705 Safefree (PL_savestack);
706#if !PERL_VERSION_ATLEAST (5,10,0)
707 Safefree (PL_retstack);
708#endif
709}
710
711#define CORO_RSS \
712 rss += sizeof (SYM (curstackinfo)); \
713 rss += (SYM (curstackinfo->si_cxmax) + 1) * sizeof (PERL_CONTEXT); \
714 rss += sizeof (SV) + sizeof (struct xpvav) + (1 + AvMAX (SYM (curstack))) * sizeof (SV *); \
715 rss += SYM (tmps_max) * sizeof (SV *); \
716 rss += (SYM (markstack_max) - SYM (markstack_ptr)) * sizeof (I32); \
717 rss += SYM (scopestack_max) * sizeof (I32); \
718 rss += SYM (savestack_max) * sizeof (ANY);
719
720static size_t
721coro_rss (pTHX_ struct coro *coro)
722{
723 size_t rss = sizeof (*coro);
724
725 if (coro->mainstack)
726 {
727 if (coro->flags & CF_RUNNING)
728 {
729 #define SYM(sym) PL_ ## sym
730 CORO_RSS;
731 #undef SYM
732 }
733 else
734 {
735 #define SYM(sym) coro->slot->sym
736 CORO_RSS;
737 #undef SYM
738 }
739 }
740
741 return rss;
742}
743
744/** coroutine stack handling ************************************************/
745
746static int (*orig_sigelem_get) (pTHX_ SV *sv, MAGIC *mg);
747static int (*orig_sigelem_set) (pTHX_ SV *sv, MAGIC *mg);
748static int (*orig_sigelem_clr) (pTHX_ SV *sv, MAGIC *mg);
749
750/* apparently < 5.8.8 */
751#ifndef MgPV_nolen_const
752#define MgPV_nolen_const(mg) (((((int)(mg)->mg_len)) == HEf_SVKEY) ? \
753 SvPV_nolen((SV*)((mg)->mg_ptr)) : \
754 (const char*)(mg)->mg_ptr)
755#endif
756
757/*
758 * This overrides the default magic get method of %SIG elements.
759 * The original one doesn't provide for reading back of PL_diehook/PL_warnhook
760 * and instead of tryign to save and restore the hash elements, we just provide
761 * readback here.
762 * We only do this when the hook is != 0, as they are often set to 0 temporarily,
763 * not expecting this to actually change the hook. This is a potential problem
764 * when a schedule happens then, but we ignore this.
765 */
766static int
767coro_sigelem_get (pTHX_ SV *sv, MAGIC *mg)
768{
769 const char *s = MgPV_nolen_const (mg);
770
771 if (*s == '_')
772 {
773 SV **svp = 0;
774
775 if (strEQ (s, "__DIE__" )) svp = &PL_diehook;
776 if (strEQ (s, "__WARN__")) svp = &PL_warnhook;
777
778 if (svp)
779 {
780 sv_setsv (sv, *svp ? *svp : &PL_sv_undef);
781 return 0;
782 }
783 }
784
785 return orig_sigelem_get ? orig_sigelem_get (aTHX_ sv, mg) : 0;
786}
787
788static int
789coro_sigelem_clr (pTHX_ SV *sv, MAGIC *mg)
790{
791 const char *s = MgPV_nolen_const (mg);
792
793 if (*s == '_')
794 {
795 SV **svp = 0;
796
797 if (strEQ (s, "__DIE__" )) svp = &PL_diehook;
798 if (strEQ (s, "__WARN__")) svp = &PL_warnhook;
799
800 if (svp)
801 {
802 SV *old = *svp;
803 *svp = 0;
804 SvREFCNT_dec (old);
805 return 0;
806 }
807 }
808
809 return orig_sigelem_clr ? orig_sigelem_clr (aTHX_ sv, mg) : 0;
810}
811
812static int
813coro_sigelem_set (pTHX_ SV *sv, MAGIC *mg)
814{
815 const char *s = MgPV_nolen_const (mg);
816
817 if (*s == '_')
818 {
819 SV **svp = 0;
820
821 if (strEQ (s, "__DIE__" )) svp = &PL_diehook;
822 if (strEQ (s, "__WARN__")) svp = &PL_warnhook;
823
824 if (svp)
825 {
826 SV *old = *svp;
827 *svp = newSVsv (sv);
828 SvREFCNT_dec (old);
829 return 0;
830 }
831 }
832
833 return orig_sigelem_set ? orig_sigelem_set (aTHX_ sv, mg) : 0;
834}
835
836static void
837prepare_nop (pTHX_ struct coro_transfer_args *ta)
838{
839 /* kind of mega-hacky, but works */
840 ta->next = ta->prev = (struct coro *)ta;
841}
842
843static int
844slf_check_nop (pTHX_ struct CoroSLF *frame)
845{
846 return 0;
847}
848
849static int
850slf_check_repeat (pTHX_ struct CoroSLF *frame)
851{
852 return 1;
853}
854
855static UNOP coro_setup_op;
856
857static void NOINLINE /* noinline to keep it out of the transfer fast path */
858coro_setup (pTHX_ struct coro *coro)
859{
860 /*
861 * emulate part of the perl startup here.
862 */
863 coro_init_stacks (aTHX);
864
865 PL_runops = RUNOPS_DEFAULT;
866 PL_curcop = &PL_compiling;
867 PL_in_eval = EVAL_NULL;
868 PL_comppad = 0;
869 PL_curpm = 0;
870 PL_curpad = 0;
871 PL_localizing = 0;
872 PL_dirty = 0;
873 PL_restartop = 0;
874#if PERL_VERSION_ATLEAST (5,10,0)
875 PL_parser = 0;
876#endif
877
878 /* recreate the die/warn hooks */
879 PL_diehook = 0; SvSetMagicSV (*hv_fetch (hv_sig, "__DIE__" , sizeof ("__DIE__" ) - 1, 1), rv_diehook );
880 PL_warnhook = 0; SvSetMagicSV (*hv_fetch (hv_sig, "__WARN__", sizeof ("__WARN__") - 1, 1), rv_warnhook);
881
882 GvSV (PL_defgv) = newSV (0);
883 GvAV (PL_defgv) = coro->args; coro->args = 0;
884 GvSV (PL_errgv) = newSV (0);
885 GvSV (irsgv) = newSVpvn ("\n", 1); sv_magic (GvSV (irsgv), (SV *)irsgv, PERL_MAGIC_sv, "/", 0);
886 PL_rs = newSVsv (GvSV (irsgv));
887 PL_defoutgv = (GV *)SvREFCNT_inc_NN (stdoutgv);
888
889 {
890 dSP;
891 UNOP myop;
892
893 Zero (&myop, 1, UNOP);
894 myop.op_next = Nullop;
895 myop.op_type = OP_ENTERSUB;
896 myop.op_flags = OPf_WANT_VOID;
897
898 PUSHMARK (SP);
899 PUSHs ((SV *)coro->startcv);
900 PUTBACK;
901 PL_op = (OP *)&myop;
902 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
903 }
904
905 /* this newly created coroutine might be run on an existing cctx which most
906 * likely was suspended in pp_slf, so we have to emulate entering pp_slf here.
907 */
908 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */
909 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */
910
911 /* and we have to provide the pp_slf op in any case, so pp_slf can skip it */
912 coro_setup_op.op_next = PL_op;
913 coro_setup_op.op_type = OP_ENTERSUB;
914 coro_setup_op.op_ppaddr = pp_slf;
915 /* no flags etc. required, as an init function won't be called */
916
917 PL_op = (OP *)&coro_setup_op;
918
919 /* copy throw, in case it was set before coro_setup */
920 CORO_THROW = coro->except;
921}
922
923static void
924coro_destruct (pTHX_ struct coro *coro)
925{
926 if (!IN_DESTRUCT)
927 {
928 /* restore all saved variables and stuff */
929 LEAVE_SCOPE (0);
930 assert (PL_tmps_floor == -1);
931
932 /* free all temporaries */
933 FREETMPS;
934 assert (PL_tmps_ix == -1);
935
936 /* unwind all extra stacks */
937 POPSTACK_TO (PL_mainstack);
938
939 /* unwind main stack */
940 dounwind (-1);
941 }
942
943 SvREFCNT_dec (GvSV (PL_defgv));
944 SvREFCNT_dec (GvAV (PL_defgv));
945 SvREFCNT_dec (GvSV (PL_errgv));
946 SvREFCNT_dec (PL_defoutgv);
947 SvREFCNT_dec (PL_rs);
948 SvREFCNT_dec (GvSV (irsgv));
949
950 SvREFCNT_dec (PL_diehook);
951 SvREFCNT_dec (PL_warnhook);
952
953 SvREFCNT_dec (coro->saved_deffh);
954 SvREFCNT_dec (coro->rouse_cb);
955 SvREFCNT_dec (coro->invoke_cb);
956 SvREFCNT_dec (coro->invoke_av);
957
958 coro_destruct_stacks (aTHX);
959}
960
961INLINE void
962free_coro_mortal (pTHX)
963{
964 if (expect_true (coro_mortal))
965 {
966 SvREFCNT_dec (coro_mortal);
967 coro_mortal = 0;
968 }
969}
970
971static int
972runops_trace (pTHX)
973{
974 COP *oldcop = 0;
975 int oldcxix = -2;
976
977 while ((PL_op = CALL_FPTR (PL_op->op_ppaddr) (aTHX)))
978 {
979 PERL_ASYNC_CHECK ();
980
981 if (cctx_current->flags & CC_TRACE_ALL)
982 {
983 if (PL_op->op_type == OP_LEAVESUB && cctx_current->flags & CC_TRACE_SUB)
984 {
985 PERL_CONTEXT *cx = &cxstack[cxstack_ix];
986 SV **bot, **top;
987 AV *av = newAV (); /* return values */
988 SV **cb;
989 dSP;
990
991 GV *gv = CvGV (cx->blk_sub.cv);
992 SV *fullname = sv_2mortal (newSV (0));
993 if (isGV (gv))
994 gv_efullname3 (fullname, gv, 0);
995
996 bot = PL_stack_base + cx->blk_oldsp + 1;
997 top = cx->blk_gimme == G_ARRAY ? SP + 1
998 : cx->blk_gimme == G_SCALAR ? bot + 1
999 : bot;
1000
1001 av_extend (av, top - bot);
1002 while (bot < top)
1003 av_push (av, SvREFCNT_inc_NN (*bot++));
1004
1005 PL_runops = RUNOPS_DEFAULT;
1006 ENTER;
1007 SAVETMPS;
1008 EXTEND (SP, 3);
1009 PUSHMARK (SP);
1010 PUSHs (&PL_sv_no);
1011 PUSHs (fullname);
1012 PUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
1013 PUTBACK;
1014 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0);
1015 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1016 SPAGAIN;
1017 FREETMPS;
1018 LEAVE;
1019 PL_runops = runops_trace;
1020 }
1021
1022 if (oldcop != PL_curcop)
1023 {
1024 oldcop = PL_curcop;
1025
1026 if (PL_curcop != &PL_compiling)
1027 {
1028 SV **cb;
1029
1030 if (oldcxix != cxstack_ix && cctx_current->flags & CC_TRACE_SUB)
1031 {
1032 PERL_CONTEXT *cx = &cxstack[cxstack_ix];
1033
1034 if (CxTYPE (cx) == CXt_SUB && oldcxix < cxstack_ix)
1035 {
1036 dSP;
1037 GV *gv = CvGV (cx->blk_sub.cv);
1038 SV *fullname = sv_2mortal (newSV (0));
1039
1040 if (isGV (gv))
1041 gv_efullname3 (fullname, gv, 0);
1042
1043 PL_runops = RUNOPS_DEFAULT;
1044 ENTER;
1045 SAVETMPS;
1046 EXTEND (SP, 3);
1047 PUSHMARK (SP);
1048 PUSHs (&PL_sv_yes);
1049 PUSHs (fullname);
1050 PUSHs (CxHASARGS (cx) ? sv_2mortal (newRV_inc ((SV *)cx->blk_sub.argarray)) : &PL_sv_undef);
1051 PUTBACK;
1052 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0);
1053 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1054 SPAGAIN;
1055 FREETMPS;
1056 LEAVE;
1057 PL_runops = runops_trace;
1058 }
1059
1060 oldcxix = cxstack_ix;
1061 }
1062
1063 if (cctx_current->flags & CC_TRACE_LINE)
1064 {
1065 dSP;
1066
1067 PL_runops = RUNOPS_DEFAULT;
1068 ENTER;
1069 SAVETMPS;
1070 EXTEND (SP, 3);
1071 PL_runops = RUNOPS_DEFAULT;
1072 PUSHMARK (SP);
1073 PUSHs (sv_2mortal (newSVpv (OutCopFILE (oldcop), 0)));
1074 PUSHs (sv_2mortal (newSViv (CopLINE (oldcop))));
1075 PUTBACK;
1076 cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_line_cb", sizeof ("_trace_line_cb") - 1, 0);
1077 if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1078 SPAGAIN;
1079 FREETMPS;
1080 LEAVE;
1081 PL_runops = runops_trace;
1082 }
1083 }
1084 }
1085 }
1086 }
1087
1088 TAINT_NOT;
1089 return 0;
1090}
1091
1092static struct CoroSLF cctx_ssl_frame;
1093
1094static void
1095slf_prepare_set_stacklevel (pTHX_ struct coro_transfer_args *ta)
1096{
1097 ta->prev = 0;
1098}
1099
1100static int
1101slf_check_set_stacklevel (pTHX_ struct CoroSLF *frame)
1102{
1103 *frame = cctx_ssl_frame;
1104
1105 return frame->check (aTHX_ frame); /* execute the restored frame - there must be one */
1106}
1107
1108/* initialises PL_top_env and injects a pseudo-slf-call to set the stacklevel */
1109static void NOINLINE
1110cctx_prepare (pTHX)
1111{
1112 PL_top_env = &PL_start_env;
1113
1114 if (cctx_current->flags & CC_TRACE)
1115 PL_runops = runops_trace;
1116
1117 /* we already must be executing an SLF op, there is no other valid way
1118 * that can lead to creation of a new cctx */
1119 assert (("FATAL: can't prepare slf-less cctx in Coro module (please report)",
1120 slf_frame.prepare && PL_op->op_ppaddr == pp_slf));
1121
1122 /* we must emulate leaving pp_slf, which is done inside slf_check_set_stacklevel */
1123 cctx_ssl_frame = slf_frame;
1124
1125 slf_frame.prepare = slf_prepare_set_stacklevel;
1126 slf_frame.check = slf_check_set_stacklevel;
1127}
1128
1129/* the tail of transfer: execute stuff we can only do after a transfer */
1130INLINE void
1131transfer_tail (pTHX)
1132{
1133 free_coro_mortal (aTHX);
1134}
1135
1136/*
1137 * this is a _very_ stripped down perl interpreter ;)
1138 */
1139static void
1140cctx_run (void *arg)
1141{
1142#ifdef USE_ITHREADS
1143# if CORO_PTHREAD
1144 PERL_SET_CONTEXT (coro_thx);
1145# endif
1146#endif
1147 {
1148 dTHX;
1149
1150 /* normally we would need to skip the entersub here */
1151 /* not doing so will re-execute it, which is exactly what we want */
1152 /* PL_nop = PL_nop->op_next */
1153
1154 /* inject a fake subroutine call to cctx_init */
1155 cctx_prepare (aTHX);
1156
1157 /* cctx_run is the alternative tail of transfer() */
1158 transfer_tail (aTHX);
1159
1160 /* somebody or something will hit me for both perl_run and PL_restartop */
1161 PL_restartop = PL_op;
1162 perl_run (PL_curinterp);
1163 /*
1164 * Unfortunately, there is no way to get at the return values of the
1165 * coro body here, as perl_run destroys these
1166 */
1167
1168 /*
1169 * If perl-run returns we assume exit() was being called or the coro
1170 * fell off the end, which seems to be the only valid (non-bug)
1171 * reason for perl_run to return. We try to exit by jumping to the
1172 * bootstrap-time "top" top_env, as we cannot restore the "main"
1173 * coroutine as Coro has no such concept
1174 */
1175 PL_top_env = main_top_env;
1176 JMPENV_JUMP (2); /* I do not feel well about the hardcoded 2 at all */
1177 }
1178}
1179
1180static coro_cctx *
1181cctx_new ()
1182{
1183 coro_cctx *cctx;
1184
1185 ++cctx_count;
1186 New (0, cctx, 1, coro_cctx);
1187
1188 cctx->gen = cctx_gen;
1189 cctx->flags = 0;
1190 cctx->idle_sp = 0; /* can be accessed by transfer between cctx_run and set_stacklevel, on throw */
1191
1192 return cctx;
1193}
1194
1195/* create a new cctx only suitable as source */
1196static coro_cctx *
1197cctx_new_empty ()
1198{
1199 coro_cctx *cctx = cctx_new ();
1200
1201 cctx->sptr = 0;
1202 coro_create (&cctx->cctx, 0, 0, 0, 0);
1203
1204 return cctx;
1205}
1206
1207/* create a new cctx suitable as destination/running a perl interpreter */
1208static coro_cctx *
1209cctx_new_run ()
1210{
1211 coro_cctx *cctx = cctx_new ();
1212 void *stack_start;
1213 size_t stack_size;
1214
1215#if HAVE_MMAP
1216 cctx->ssize = ((cctx_stacksize * sizeof (long) + PAGESIZE - 1) / PAGESIZE + CORO_STACKGUARD) * PAGESIZE;
1217 /* mmap supposedly does allocate-on-write for us */
1218 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
1219
1220 if (cctx->sptr != (void *)-1)
1221 {
1222 #if CORO_STACKGUARD
1223 mprotect (cctx->sptr, CORO_STACKGUARD * PAGESIZE, PROT_NONE);
1224 #endif
1225 stack_start = (char *)cctx->sptr + CORO_STACKGUARD * PAGESIZE;
1226 stack_size = cctx->ssize - CORO_STACKGUARD * PAGESIZE;
1227 cctx->flags |= CC_MAPPED;
1228 }
1229 else
1230#endif
1231 {
1232 cctx->ssize = cctx_stacksize * (long)sizeof (long);
1233 New (0, cctx->sptr, cctx_stacksize, long);
1234
1235 if (!cctx->sptr)
1236 {
1237 perror ("FATAL: unable to allocate stack for coroutine, exiting.");
1238 _exit (EXIT_FAILURE);
1239 }
1240
1241 stack_start = cctx->sptr;
1242 stack_size = cctx->ssize;
1243 }
1244
1245 #if CORO_USE_VALGRIND
1246 cctx->valgrind_id = VALGRIND_STACK_REGISTER ((char *)stack_start, (char *)stack_start + stack_size);
1247 #endif
1248
1249 coro_create (&cctx->cctx, cctx_run, (void *)cctx, stack_start, stack_size);
1250
1251 return cctx;
1252}
1253
1254static void
1255cctx_destroy (coro_cctx *cctx)
1256{
1257 if (!cctx)
1258 return;
1259
1260 assert (cctx != cctx_current);//D temporary
1261
1262 --cctx_count;
1263 coro_destroy (&cctx->cctx);
1264
1265 /* coro_transfer creates new, empty cctx's */
1266 if (cctx->sptr)
1267 {
1268 #if CORO_USE_VALGRIND
1269 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id);
1270 #endif
1271
1272#if HAVE_MMAP
1273 if (cctx->flags & CC_MAPPED)
1274 munmap (cctx->sptr, cctx->ssize);
1275 else
1276#endif
1277 Safefree (cctx->sptr);
1278 }
1279
1280 Safefree (cctx);
1281}
1282
1283/* wether this cctx should be destructed */
1284#define CCTX_EXPIRED(cctx) ((cctx)->gen != cctx_gen || ((cctx)->flags & CC_NOREUSE))
1285
1286static coro_cctx *
1287cctx_get (pTHX)
1288{
1289 while (expect_true (cctx_first))
1290 {
1291 coro_cctx *cctx = cctx_first;
1292 cctx_first = cctx->next;
1293 --cctx_idle;
1294
1295 if (expect_true (!CCTX_EXPIRED (cctx)))
1296 return cctx;
1297
1298 cctx_destroy (cctx);
1299 }
1300
1301 return cctx_new_run ();
1302}
1303
1304static void
1305cctx_put (coro_cctx *cctx)
1306{
1307 assert (("FATAL: cctx_put called on non-initialised cctx in Coro (please report)", cctx->sptr));
1308
1309 /* free another cctx if overlimit */
1310 if (expect_false (cctx_idle >= cctx_max_idle))
1311 {
1312 coro_cctx *first = cctx_first;
1313 cctx_first = first->next;
1314 --cctx_idle;
1315
1316 cctx_destroy (first);
1317 }
1318
1319 ++cctx_idle;
1320 cctx->next = cctx_first;
1321 cctx_first = cctx;
1322}
1323
1324/** coroutine switching *****************************************************/
1325
1326static void
1327transfer_check (pTHX_ struct coro *prev, struct coro *next)
1328{
1329 /* TODO: throwing up here is considered harmful */
1330
1331 if (expect_true (prev != next))
1332 {
1333 if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW))))
1334 croak ("Coro::State::transfer called with a suspended prev Coro::State, but can only transfer from running or new states,");
1335
1336 if (expect_false (next->flags & CF_RUNNING))
1337 croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states,");
1338
1339 if (expect_false (next->flags & CF_DESTROYED))
1340 croak ("Coro::State::transfer called with destroyed next Coro::State, but can only transfer to inactive states,");
1341
1342#if !PERL_VERSION_ATLEAST (5,10,0)
1343 if (expect_false (PL_lex_state != LEX_NOTPARSING))
1344 croak ("Coro::State::transfer called while parsing, but this is not supported in your perl version,");
1345#endif
1346 }
1347}
1348
1349/* always use the TRANSFER macro */
1350static void NOINLINE /* noinline so we have a fixed stackframe */
1351transfer (pTHX_ struct coro *prev, struct coro *next, int force_cctx)
1352{
1353 dSTACKLEVEL;
1354
1355 /* sometimes transfer is only called to set idle_sp */
1356 if (expect_false (!prev))
1357 {
1358 cctx_current->idle_sp = STACKLEVEL;
1359 assert (cctx_current->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */
1360 }
1361 else if (expect_true (prev != next))
1362 {
1363 coro_cctx *cctx_prev;
1364
1365 if (expect_false (prev->flags & CF_NEW))
1366 {
1367 /* create a new empty/source context */
1368 prev->flags &= ~CF_NEW;
1369 prev->flags |= CF_RUNNING;
1370 }
1371
1372 prev->flags &= ~CF_RUNNING;
1373 next->flags |= CF_RUNNING;
1374
1375 /* first get rid of the old state */
1376 save_perl (aTHX_ prev);
1377
1378 if (expect_false (next->flags & CF_NEW))
1379 {
1380 /* need to start coroutine */
1381 next->flags &= ~CF_NEW;
1382 /* setup coroutine call */
1383 coro_setup (aTHX_ next);
1384 }
1385 else
1386 load_perl (aTHX_ next);
1387
1388 assert (!prev->cctx);//D temporary
1389
1390 /* possibly untie and reuse the cctx */
1391 if (expect_true (
1392 cctx_current->idle_sp == STACKLEVEL
1393 && !(cctx_current->flags & CC_TRACE)
1394 && !force_cctx
1395 ))
1396 {
1397 /* I assume that stacklevel is a stronger indicator than PL_top_env changes */
1398 assert (("FATAL: current top_env must equal previous top_env in Coro (please report)", PL_top_env == cctx_current->idle_te));
1399
1400 /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get. */
1401 /* without this the next cctx_get might destroy the running cctx while still in use */
1402 if (expect_false (CCTX_EXPIRED (cctx_current)))
1403 if (expect_true (!next->cctx))
1404 next->cctx = cctx_get (aTHX);
1405
1406 cctx_put (cctx_current);
1407 }
1408 else
1409 prev->cctx = cctx_current;
1410
1411 ++next->usecount;
1412
1413 cctx_prev = cctx_current;
1414 cctx_current = expect_false (next->cctx) ? next->cctx : cctx_get (aTHX);
1415
1416 next->cctx = 0;
1417
1418 if (expect_false (cctx_prev != cctx_current))
1419 {
1420 cctx_prev->top_env = PL_top_env;
1421 PL_top_env = cctx_current->top_env;
1422 coro_transfer (&cctx_prev->cctx, &cctx_current->cctx);
1423 }
1424
1425 transfer_tail (aTHX);
1426 }
1427}
1428
1429#define TRANSFER(ta, force_cctx) transfer (aTHX_ (ta).prev, (ta).next, (force_cctx))
1430#define TRANSFER_CHECK(ta) transfer_check (aTHX_ (ta).prev, (ta).next)
1431
1432/** high level stuff ********************************************************/
1433
1434static int
1435coro_state_destroy (pTHX_ struct coro *coro)
1436{
1437 if (coro->flags & CF_DESTROYED)
1438 return 0;
1439
1440 if (coro->on_destroy)
1441 coro->on_destroy (aTHX_ coro);
1442
1443 coro->flags |= CF_DESTROYED;
1444
1445 if (coro->flags & CF_READY)
1446 {
1447 /* reduce nready, as destroying a ready coro effectively unreadies it */
1448 /* alternative: look through all ready queues and remove the coro */
1449 --coro_nready;
1450 }
1451 else
1452 coro->flags |= CF_READY; /* make sure it is NOT put into the readyqueue */
1453
1454 if (coro->mainstack && coro->mainstack != main_mainstack)
1455 {
1456 struct coro temp;
1457
1458 assert (("FATAL: tried to destroy currently running coroutine (please report)", !(coro->flags & CF_RUNNING)));
1459
1460 save_perl (aTHX_ &temp);
1461 load_perl (aTHX_ coro);
1462
1463 coro_destruct (aTHX_ coro);
1464
1465 load_perl (aTHX_ &temp);
1466
1467 coro->slot = 0;
1468 }
1469
1470 cctx_destroy (coro->cctx);
1471 SvREFCNT_dec (coro->startcv);
1472 SvREFCNT_dec (coro->args);
1473 SvREFCNT_dec (CORO_THROW);
1474
1475 if (coro->next) coro->next->prev = coro->prev;
1476 if (coro->prev) coro->prev->next = coro->next;
1477 if (coro == coro_first) coro_first = coro->next;
1478
1479 return 1;
1480}
1481
1482static int
1483coro_state_free (pTHX_ SV *sv, MAGIC *mg)
1484{
1485 struct coro *coro = (struct coro *)mg->mg_ptr;
1486 mg->mg_ptr = 0;
1487
1488 coro->hv = 0;
1489
1490 if (--coro->refcnt < 0)
1491 {
1492 coro_state_destroy (aTHX_ coro);
1493 Safefree (coro);
1494 }
1495
1496 return 0;
1497}
1498
1499static int
1500coro_state_dup (pTHX_ MAGIC *mg, CLONE_PARAMS *params)
1501{
1502 struct coro *coro = (struct coro *)mg->mg_ptr;
1503
1504 ++coro->refcnt;
1505
1506 return 0;
1507}
1508
1509static MGVTBL coro_state_vtbl = {
1510 0, 0, 0, 0,
1511 coro_state_free,
1512 0,
1513#ifdef MGf_DUP
1514 coro_state_dup,
1515#else
1516# define MGf_DUP 0
1517#endif
1518};
1519
1520static void
1521prepare_transfer (pTHX_ struct coro_transfer_args *ta, SV *prev_sv, SV *next_sv)
1522{
1523 ta->prev = SvSTATE (prev_sv);
1524 ta->next = SvSTATE (next_sv);
1525 TRANSFER_CHECK (*ta);
1526}
1527
1528static void
1529api_transfer (pTHX_ SV *prev_sv, SV *next_sv)
1530{
1531 struct coro_transfer_args ta;
1532
1533 prepare_transfer (aTHX_ &ta, prev_sv, next_sv);
1534 TRANSFER (ta, 1);
1535}
1536
1537/*****************************************************************************/
1538/* gensub: simple closure generation utility */
1539
1540#define GENSUB_ARG CvXSUBANY (cv).any_ptr
1541
1542/* create a closure from XS, returns a code reference */
1543/* the arg can be accessed via GENSUB_ARG from the callback */
1544/* the callback must use dXSARGS/XSRETURN */
1545static SV *
1546gensub (pTHX_ void (*xsub)(pTHX_ CV *), void *arg)
1547{
1548 CV *cv = (CV *)newSV (0);
1549
1550 sv_upgrade ((SV *)cv, SVt_PVCV);
1551
1552 CvANON_on (cv);
1553 CvISXSUB_on (cv);
1554 CvXSUB (cv) = xsub;
1555 GENSUB_ARG = arg;
1556
1557 return newRV_noinc ((SV *)cv);
1558}
1559
1560/** Coro ********************************************************************/
1561
1562INLINE void
1563coro_enq (pTHX_ struct coro *coro)
1564{
1565 av_push (coro_ready [coro->prio - PRIO_MIN], SvREFCNT_inc_NN (coro->hv));
1566}
1567
1568INLINE SV *
1569coro_deq (pTHX)
1570{
1571 int prio;
1572
1573 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= 0; )
1574 if (AvFILLp (coro_ready [prio]) >= 0)
1575 return av_shift (coro_ready [prio]);
1576
1577 return 0;
1578}
1579
1580static int
1581api_ready (pTHX_ SV *coro_sv)
1582{
1583 struct coro *coro;
1584 SV *sv_hook;
1585 void (*xs_hook)(void);
1586
1587 if (SvROK (coro_sv))
1588 coro_sv = SvRV (coro_sv);
1589
1590 coro = SvSTATE (coro_sv);
1591
1592 if (coro->flags & CF_READY)
1593 return 0;
1594
1595 coro->flags |= CF_READY;
1596
1597 sv_hook = coro_nready ? 0 : coro_readyhook;
1598 xs_hook = coro_nready ? 0 : coroapi.readyhook;
1599
1600 coro_enq (aTHX_ coro);
1601 ++coro_nready;
1602
1603 if (sv_hook)
1604 {
1605 dSP;
1606
1607 ENTER;
1608 SAVETMPS;
1609
1610 PUSHMARK (SP);
1611 PUTBACK;
1612 call_sv (sv_hook, G_VOID | G_DISCARD);
1613
1614 FREETMPS;
1615 LEAVE;
1616 }
1617
1618 if (xs_hook)
1619 xs_hook ();
1620
1621 return 1;
1622}
1623
1624static int
1625api_is_ready (pTHX_ SV *coro_sv)
1626{
1627 return !!(SvSTATE (coro_sv)->flags & CF_READY);
1628}
1629
1630/* expects to own a reference to next->hv */
1631INLINE void
1632prepare_schedule_to (pTHX_ struct coro_transfer_args *ta, struct coro *next)
1633{
1634 SV *prev_sv = SvRV (coro_current);
1635
1636 ta->prev = SvSTATE_hv (prev_sv);
1637 ta->next = next;
1638
1639 TRANSFER_CHECK (*ta);
1640
1641 SvRV_set (coro_current, (SV *)next->hv);
1642
1643 free_coro_mortal (aTHX);
1644 coro_mortal = prev_sv;
1645}
1646
1647static void
1648prepare_schedule (pTHX_ struct coro_transfer_args *ta)
1649{
1650 for (;;)
1651 {
1652 SV *next_sv = coro_deq (aTHX);
1653
1654 if (expect_true (next_sv))
1655 {
1656 struct coro *next = SvSTATE_hv (next_sv);
1657
1658 /* cannot transfer to destroyed coros, skip and look for next */
1659 if (expect_false (next->flags & CF_DESTROYED))
1660 SvREFCNT_dec (next_sv); /* coro_nready has already been taken care of by destroy */
1661 else
1662 {
1663 next->flags &= ~CF_READY;
1664 --coro_nready;
1665
1666 prepare_schedule_to (aTHX_ ta, next);
1667 break;
1668 }
1669 }
1670 else
1671 {
1672 /* nothing to schedule: call the idle handler */
1673 dSP;
1674
1675 ENTER;
1676 SAVETMPS;
1677
1678 PUSHMARK (SP);
1679 PUTBACK;
1680 call_sv (get_sv ("Coro::idle", FALSE), G_VOID | G_DISCARD);
1681
1682 FREETMPS;
1683 LEAVE;
1684 }
1685 }
1686}
1687
1688INLINE void
1689prepare_cede (pTHX_ struct coro_transfer_args *ta)
1690{
1691 api_ready (aTHX_ coro_current);
1692 prepare_schedule (aTHX_ ta);
1693}
1694
1695INLINE void
1696prepare_cede_notself (pTHX_ struct coro_transfer_args *ta)
1697{
1698 SV *prev = SvRV (coro_current);
1699
1700 if (coro_nready)
1701 {
1702 prepare_schedule (aTHX_ ta);
1703 api_ready (aTHX_ prev);
1704 }
1705 else
1706 prepare_nop (aTHX_ ta);
1707}
1708
1709static void
1710api_schedule (pTHX)
1711{
1712 struct coro_transfer_args ta;
1713
1714 prepare_schedule (aTHX_ &ta);
1715 TRANSFER (ta, 1);
1716}
1717
1718static void
1719api_schedule_to (pTHX_ SV *coro_sv)
1720{
1721 struct coro_transfer_args ta;
1722 struct coro *next = SvSTATE (coro_sv);
1723
1724 SvREFCNT_inc_NN (coro_sv);
1725 prepare_schedule_to (aTHX_ &ta, next);
1726}
1727
1728static int
1729api_cede (pTHX)
1730{
1731 struct coro_transfer_args ta;
1732
1733 prepare_cede (aTHX_ &ta);
1734
1735 if (expect_true (ta.prev != ta.next))
1736 {
1737 TRANSFER (ta, 1);
1738 return 1;
1739 }
1740 else
1741 return 0;
1742}
1743
1744static int
1745api_cede_notself (pTHX)
1746{
1747 if (coro_nready)
1748 {
1749 struct coro_transfer_args ta;
1750
1751 prepare_cede_notself (aTHX_ &ta);
1752 TRANSFER (ta, 1);
1753 return 1;
1754 }
1755 else
1756 return 0;
1757}
1758
1759static void
1760api_trace (pTHX_ SV *coro_sv, int flags)
1761{
1762 struct coro *coro = SvSTATE (coro_sv);
1763
1764 if (coro->flags & CF_RUNNING)
1765 croak ("cannot enable tracing on a running coroutine, caught");
1766
1767 if (flags & CC_TRACE)
1768 {
1769 if (!coro->cctx)
1770 coro->cctx = cctx_new_run ();
1771 else if (!(coro->cctx->flags & CC_TRACE))
1772 croak ("cannot enable tracing on coroutine with custom stack, caught");
1773
1774 coro->cctx->flags |= CC_NOREUSE | (flags & (CC_TRACE | CC_TRACE_ALL));
1775 }
1776 else if (coro->cctx && coro->cctx->flags & CC_TRACE)
1777 {
1778 coro->cctx->flags &= ~(CC_TRACE | CC_TRACE_ALL);
1779
1780 if (coro->flags & CF_RUNNING)
1781 PL_runops = RUNOPS_DEFAULT;
1782 else
1783 coro->slot->runops = RUNOPS_DEFAULT;
1784 }
1785}
1786
1787static void
1788coro_call_on_destroy (pTHX_ struct coro *coro)
1789{
1790 SV **on_destroyp = hv_fetch (coro->hv, "_on_destroy", sizeof ("_on_destroy") - 1, 0);
1791 SV **statusp = hv_fetch (coro->hv, "_status", sizeof ("_status") - 1, 0);
1792
1793 if (on_destroyp)
1794 {
1795 AV *on_destroy = (AV *)SvRV (*on_destroyp);
1796
1797 while (AvFILLp (on_destroy) >= 0)
1798 {
1799 dSP; /* don't disturb outer sp */
1800 SV *cb = av_pop (on_destroy);
1801
1802 PUSHMARK (SP);
1803
1804 if (statusp)
1805 {
1806 int i;
1807 AV *status = (AV *)SvRV (*statusp);
1808 EXTEND (SP, AvFILLp (status) + 1);
1809
1810 for (i = 0; i <= AvFILLp (status); ++i)
1811 PUSHs (AvARRAY (status)[i]);
1812 }
1813
1814 PUTBACK;
1815 call_sv (sv_2mortal (cb), G_VOID | G_DISCARD);
1816 }
1817 }
1818}
1819
1820static void
1821slf_init_terminate (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1822{
1823 int i;
1824 HV *hv = (HV *)SvRV (coro_current);
1825 AV *av = newAV ();
1826
1827 av_extend (av, items - 1);
1828 for (i = 0; i < items; ++i)
1829 av_push (av, SvREFCNT_inc_NN (arg [i]));
1830
1831 hv_store (hv, "_status", sizeof ("_status") - 1, newRV_noinc ((SV *)av), 0);
1832
1833 av_push (av_destroy, (SV *)newRV_inc ((SV *)hv)); /* RVinc for perl */
1834 api_ready (aTHX_ sv_manager);
1835
1836 frame->prepare = prepare_schedule;
1837 frame->check = slf_check_repeat;
1838}
1839
1840/*****************************************************************************/
1841/* async pool handler */
1842
1843static int
1844slf_check_pool_handler (pTHX_ struct CoroSLF *frame)
1845{
1846 HV *hv = (HV *)SvRV (coro_current);
1847 struct coro *coro = (struct coro *)frame->data;
1848
1849 if (!coro->invoke_cb)
1850 return 1; /* loop till we have invoke */
1851 else
1852 {
1853 hv_store (hv, "desc", sizeof ("desc") - 1,
1854 newSVpvn ("[async_pool]", sizeof ("[async_pool]") - 1), 0);
1855
1856 coro->saved_deffh = SvREFCNT_inc_NN ((SV *)PL_defoutgv);
1857
1858 {
1859 dSP;
1860 XPUSHs (sv_2mortal (coro->invoke_cb)); coro->invoke_cb = 0;
1861 PUTBACK;
1862 }
1863
1864 SvREFCNT_dec (GvAV (PL_defgv));
1865 GvAV (PL_defgv) = coro->invoke_av;
1866 coro->invoke_av = 0;
1867
1868 return 0;
1869 }
1870}
1871
1872static void
1873slf_init_pool_handler (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1874{
1875 HV *hv = (HV *)SvRV (coro_current);
1876 struct coro *coro = SvSTATE_hv ((SV *)hv);
1877
1878 if (expect_true (coro->saved_deffh))
1879 {
1880 /* subsequent iteration */
1881 SvREFCNT_dec ((SV *)PL_defoutgv); PL_defoutgv = (GV *)coro->saved_deffh;
1882 coro->saved_deffh = 0;
1883
1884 if (coro_rss (aTHX_ coro) > SvUV (sv_pool_rss)
1885 || av_len (av_async_pool) + 1 >= SvIV (sv_pool_size))
1886 {
1887 coro->invoke_cb = SvREFCNT_inc_NN ((SV *)cv_coro_terminate);
1888 coro->invoke_av = newAV ();
1889
1890 frame->prepare = prepare_nop;
1891 }
1892 else
1893 {
1894 av_clear (GvAV (PL_defgv));
1895 hv_store (hv, "desc", sizeof ("desc") - 1, SvREFCNT_inc_NN (sv_async_pool_idle), 0);
1896
1897 coro->prio = 0;
1898
1899 if (coro->cctx && (coro->cctx->flags & CC_TRACE))
1900 api_trace (aTHX_ coro_current, 0);
1901
1902 frame->prepare = prepare_schedule;
1903 av_push (av_async_pool, SvREFCNT_inc (hv));
1904 }
1905 }
1906 else
1907 {
1908 /* first iteration, simply fall through */
1909 frame->prepare = prepare_nop;
1910 }
1911
1912 frame->check = slf_check_pool_handler;
1913 frame->data = (void *)coro;
1914}
1915
1916/*****************************************************************************/
1917/* rouse callback */
1918
1919#define CORO_MAGIC_type_rouse PERL_MAGIC_ext
1920
1921static void
1922coro_rouse_callback (pTHX_ CV *cv)
1923{
1924 dXSARGS;
1925 SV *data = (SV *)GENSUB_ARG;
1926
1927 if (SvTYPE (SvRV (data)) != SVt_PVAV)
1928 {
1929 /* first call, set args */
1930 AV *av = newAV ();
1931 SV *coro = SvRV (data);
1932
1933 SvRV_set (data, (SV *)av);
1934 api_ready (aTHX_ coro);
1935 SvREFCNT_dec (coro);
1936
1937 /* better take a full copy of the arguments */
1938 while (items--)
1939 av_store (av, items, newSVsv (ST (items)));
1940 }
1941
1942 XSRETURN_EMPTY;
1943}
1944
1945static int
1946slf_check_rouse_wait (pTHX_ struct CoroSLF *frame)
1947{
1948 SV *data = (SV *)frame->data;
1949
1950 if (CORO_THROW)
1951 return 0;
1952
1953 if (SvTYPE (SvRV (data)) != SVt_PVAV)
1954 return 1;
1955
1956 /* now push all results on the stack */
1957 {
1958 dSP;
1959 AV *av = (AV *)SvRV (data);
1960 int i;
1961
1962 EXTEND (SP, AvFILLp (av) + 1);
1963 for (i = 0; i <= AvFILLp (av); ++i)
1964 PUSHs (sv_2mortal (AvARRAY (av)[i]));
1965
1966 /* we have stolen the elements, so ste length to zero and free */
1967 AvFILLp (av) = -1;
1968 av_undef (av);
1969
1970 PUTBACK;
1971 }
1972
1973 return 0;
1974}
1975
1976static void
1977slf_init_rouse_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1978{
1979 SV *cb;
1980
1981 if (items)
1982 cb = arg [0];
1983 else
1984 {
1985 struct coro *coro = SvSTATE_current;
1986
1987 if (!coro->rouse_cb)
1988 croak ("Coro::rouse_wait called without rouse callback, and no default rouse callback found either,");
1989
1990 cb = sv_2mortal (coro->rouse_cb);
1991 coro->rouse_cb = 0;
1992 }
1993
1994 if (!SvROK (cb)
1995 || SvTYPE (SvRV (cb)) != SVt_PVCV
1996 || CvXSUB ((CV *)SvRV (cb)) != coro_rouse_callback)
1997 croak ("Coro::rouse_wait called with illegal callback argument,");
1998
1999 {
2000 CV *cv = (CV *)SvRV (cb); /* for GENSUB_ARG */
2001 SV *data = (SV *)GENSUB_ARG;
2002
2003 frame->data = (void *)data;
2004 frame->prepare = SvTYPE (SvRV (data)) == SVt_PVAV ? prepare_nop : prepare_schedule;
2005 frame->check = slf_check_rouse_wait;
2006 }
2007}
2008
2009static SV *
2010coro_new_rouse_cb (pTHX)
2011{
2012 HV *hv = (HV *)SvRV (coro_current);
2013 struct coro *coro = SvSTATE_hv (hv);
2014 SV *data = newRV_inc ((SV *)hv);
2015 SV *cb = gensub (aTHX_ coro_rouse_callback, (void *)data);
2016
2017 sv_magicext (SvRV (cb), data, CORO_MAGIC_type_rouse, 0, 0, 0);
2018 SvREFCNT_dec (data); /* magicext increases the refcount */
2019
2020 SvREFCNT_dec (coro->rouse_cb);
2021 coro->rouse_cb = SvREFCNT_inc_NN (cb);
2022
2023 return cb;
2024}
2025
2026/*****************************************************************************/
2027/* schedule-like-function opcode (SLF) */
2028
2029static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */
2030static const CV *slf_cv;
2031static SV **slf_argv;
2032static int slf_argc, slf_arga; /* count, allocated */
2033static I32 slf_ax; /* top of stack, for restore */
2034
2035/* this restores the stack in the case we patched the entersub, to */
2036/* recreate the stack frame as perl will on following calls */
2037/* since entersub cleared the stack */
2038static OP *
2039pp_restore (pTHX)
2040{
2041 int i;
2042 SV **SP = PL_stack_base + slf_ax;
2043
2044 PUSHMARK (SP);
2045
2046 EXTEND (SP, slf_argc + 1);
2047
2048 for (i = 0; i < slf_argc; ++i)
2049 PUSHs (sv_2mortal (slf_argv [i]));
2050
2051 PUSHs ((SV *)CvGV (slf_cv));
2052
2053 RETURNOP (slf_restore.op_first);
2054}
2055
2056static void
2057slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta)
2058{
2059 SV **arg = (SV **)slf_frame.data;
2060
2061 prepare_transfer (aTHX_ ta, arg [0], arg [1]);
2062}
2063
2064static void
2065slf_init_transfer (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2066{
2067 if (items != 2)
2068 croak ("Coro::State::transfer (prev, next) expects two arguments, not %d,", items);
2069
2070 frame->prepare = slf_prepare_transfer;
2071 frame->check = slf_check_nop;
2072 frame->data = (void *)arg; /* let's hope it will stay valid */
2073}
2074
2075static void
2076slf_init_schedule (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2077{
2078 frame->prepare = prepare_schedule;
2079 frame->check = slf_check_nop;
2080}
2081
2082static void
2083slf_prepare_schedule_to (pTHX_ struct coro_transfer_args *ta)
2084{
2085 struct coro *next = (struct coro *)slf_frame.data;
2086
2087 SvREFCNT_inc_NN (next->hv);
2088 prepare_schedule_to (aTHX_ ta, next);
2089}
2090
2091static void
2092slf_init_schedule_to (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2093{
2094 if (!items)
2095 croak ("Coro::schedule_to expects a coroutine argument, caught");
2096
2097 frame->data = (void *)SvSTATE (arg [0]);
2098 frame->prepare = slf_prepare_schedule_to;
2099 frame->check = slf_check_nop;
2100}
2101
2102static void
2103slf_init_cede_to (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2104{
2105 api_ready (aTHX_ SvRV (coro_current));
2106
2107 slf_init_schedule_to (aTHX_ frame, cv, arg, items);
2108}
2109
2110static void
2111slf_init_cede (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2112{
2113 frame->prepare = prepare_cede;
2114 frame->check = slf_check_nop;
2115}
2116
2117static void
2118slf_init_cede_notself (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2119{
2120 frame->prepare = prepare_cede_notself;
2121 frame->check = slf_check_nop;
2122}
2123
2124/*
2125 * these not obviously related functions are all rolled into one
2126 * function to increase chances that they all will call transfer with the same
2127 * stack offset
2128 * SLF stands for "schedule-like-function".
2129 */
2130static OP *
2131pp_slf (pTHX)
2132{
2133 I32 checkmark; /* mark SP to see how many elements check has pushed */
2134
2135 /* set up the slf frame, unless it has already been set-up */
2136 /* the latter happens when a new coro has been started */
2137 /* or when a new cctx was attached to an existing coroutine */
2138 if (expect_true (!slf_frame.prepare))
2139 {
2140 /* first iteration */
2141 dSP;
2142 SV **arg = PL_stack_base + TOPMARK + 1;
2143 int items = SP - arg; /* args without function object */
2144 SV *gv = *sp;
2145
2146 /* do a quick consistency check on the "function" object, and if it isn't */
2147 /* for us, divert to the real entersub */
2148 if (SvTYPE (gv) != SVt_PVGV
2149 || !GvCV (gv)
2150 || !(CvFLAGS (GvCV (gv)) & CVf_SLF))
2151 return PL_ppaddr[OP_ENTERSUB](aTHX);
2152
2153 if (!(PL_op->op_flags & OPf_STACKED))
2154 {
2155 /* ampersand-form of call, use @_ instead of stack */
2156 AV *av = GvAV (PL_defgv);
2157 arg = AvARRAY (av);
2158 items = AvFILLp (av) + 1;
2159 }
2160
2161 /* now call the init function, which needs to set up slf_frame */
2162 ((coro_slf_cb)CvXSUBANY (GvCV (gv)).any_ptr)
2163 (aTHX_ &slf_frame, GvCV (gv), arg, items);
2164
2165 /* pop args */
2166 SP = PL_stack_base + POPMARK;
2167
2168 PUTBACK;
2169 }
2170
2171 /* now that we have a slf_frame, interpret it! */
2172 /* we use a callback system not to make the code needlessly */
2173 /* complicated, but so we can run multiple perl coros from one cctx */
2174
2175 do
2176 {
2177 struct coro_transfer_args ta;
2178
2179 slf_frame.prepare (aTHX_ &ta);
2180 TRANSFER (ta, 0);
2181
2182 checkmark = PL_stack_sp - PL_stack_base;
2183 }
2184 while (slf_frame.check (aTHX_ &slf_frame));
2185
2186 slf_frame.prepare = 0; /* invalidate the frame, we are done processing it */
2187
2188 /* exception handling */
2189 if (expect_false (CORO_THROW))
2190 {
2191 SV *exception = sv_2mortal (CORO_THROW);
2192
2193 CORO_THROW = 0;
2194 sv_setsv (ERRSV, exception);
2195 croak (0);
2196 }
2197
2198 /* return value handling - mostly like entersub */
2199 /* make sure we put something on the stack in scalar context */
2200 if (GIMME_V == G_SCALAR)
2201 {
2202 dSP;
2203 SV **bot = PL_stack_base + checkmark;
2204
2205 if (sp == bot) /* too few, push undef */
2206 bot [1] = &PL_sv_undef;
2207 else if (sp != bot + 1) /* too many, take last one */
2208 bot [1] = *sp;
2209
2210 SP = bot + 1;
2211
2212 PUTBACK;
2213 }
2214
2215 return NORMAL;
2216}
2217
2218static void
2219api_execute_slf (pTHX_ CV *cv, coro_slf_cb init_cb, I32 ax)
2220{
2221 int i;
2222 SV **arg = PL_stack_base + ax;
2223 int items = PL_stack_sp - arg + 1;
2224
2225 assert (("FATAL: SLF call with illegal CV value", !CvANON (cv)));
2226
2227 if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB]
2228 && PL_op->op_ppaddr != pp_slf)
2229 croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught");
2230
2231 CvFLAGS (cv) |= CVf_SLF;
2232 CvXSUBANY (cv).any_ptr = (void *)init_cb;
2233 slf_cv = cv;
2234
2235 /* we patch the op, and then re-run the whole call */
2236 /* we have to put the same argument on the stack for this to work */
2237 /* and this will be done by pp_restore */
2238 slf_restore.op_next = (OP *)&slf_restore;
2239 slf_restore.op_type = OP_CUSTOM;
2240 slf_restore.op_ppaddr = pp_restore;
2241 slf_restore.op_first = PL_op;
2242
2243 slf_ax = ax - 1; /* undo the ax++ inside dAXMARK */
2244
2245 if (PL_op->op_flags & OPf_STACKED)
2246 {
2247 if (items > slf_arga)
2248 {
2249 slf_arga = items;
2250 free (slf_argv);
2251 slf_argv = malloc (slf_arga * sizeof (SV *));
2252 }
2253
2254 slf_argc = items;
2255
2256 for (i = 0; i < items; ++i)
2257 slf_argv [i] = SvREFCNT_inc (arg [i]);
2258 }
2259 else
2260 slf_argc = 0;
2261
2262 PL_op->op_ppaddr = pp_slf;
2263 /*PL_op->op_type = OP_CUSTOM; /* we do behave like entersub still */
2264
2265 PL_op = (OP *)&slf_restore;
2266}
2267
2268/*****************************************************************************/
2269/* PerlIO::cede */
2270
2271typedef struct
2272{
2273 PerlIOBuf base;
2274 NV next, every;
2275} PerlIOCede;
2276
2277static IV
2278PerlIOCede_pushed (pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
2279{
2280 PerlIOCede *self = PerlIOSelf (f, PerlIOCede);
2281
2282 self->every = SvCUR (arg) ? SvNV (arg) : 0.01;
2283 self->next = nvtime () + self->every;
2284
2285 return PerlIOBuf_pushed (aTHX_ f, mode, Nullsv, tab);
2286}
2287
2288static SV *
2289PerlIOCede_getarg (pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
2290{
2291 PerlIOCede *self = PerlIOSelf (f, PerlIOCede);
2292
2293 return newSVnv (self->every);
2294}
2295
2296static IV
2297PerlIOCede_flush (pTHX_ PerlIO *f)
2298{
2299 PerlIOCede *self = PerlIOSelf (f, PerlIOCede);
2300 double now = nvtime ();
2301
2302 if (now >= self->next)
2303 {
2304 api_cede (aTHX);
2305 self->next = now + self->every;
2306 }
2307
2308 return PerlIOBuf_flush (aTHX_ f);
2309}
2310
2311static PerlIO_funcs PerlIO_cede =
2312{
2313 sizeof(PerlIO_funcs),
2314 "cede",
2315 sizeof(PerlIOCede),
2316 PERLIO_K_DESTRUCT | PERLIO_K_RAW,
2317 PerlIOCede_pushed,
2318 PerlIOBuf_popped,
2319 PerlIOBuf_open,
2320 PerlIOBase_binmode,
2321 PerlIOCede_getarg,
2322 PerlIOBase_fileno,
2323 PerlIOBuf_dup,
2324 PerlIOBuf_read,
2325 PerlIOBuf_unread,
2326 PerlIOBuf_write,
2327 PerlIOBuf_seek,
2328 PerlIOBuf_tell,
2329 PerlIOBuf_close,
2330 PerlIOCede_flush,
2331 PerlIOBuf_fill,
2332 PerlIOBase_eof,
2333 PerlIOBase_error,
2334 PerlIOBase_clearerr,
2335 PerlIOBase_setlinebuf,
2336 PerlIOBuf_get_base,
2337 PerlIOBuf_bufsiz,
2338 PerlIOBuf_get_ptr,
2339 PerlIOBuf_get_cnt,
2340 PerlIOBuf_set_ptrcnt,
2341};
2342
2343/*****************************************************************************/
2344/* Coro::Semaphore & Coro::Signal */
2345
2346static SV *
2347coro_waitarray_new (pTHX_ int count)
2348{
2349 /* a semaphore contains a counter IV in $sem->[0] and any waiters after that */
2350 AV *av = newAV ();
2351 SV **ary;
2352
2353 /* unfortunately, building manually saves memory */
2354 Newx (ary, 2, SV *);
2355 AvALLOC (av) = ary;
2356 /*AvARRAY (av) = ary;*/
2357 SvPVX ((SV *)av) = (char *)ary; /* 5.8.8 needs this syntax instead of AvARRAY = ary */
2358 AvMAX (av) = 1;
2359 AvFILLp (av) = 0;
2360 ary [0] = newSViv (count);
2361
2362 return newRV_noinc ((SV *)av);
2363}
2364
2365/* semaphore */
2366
2367static void
2368coro_semaphore_adjust (pTHX_ AV *av, IV adjust)
2369{
2370 SV *count_sv = AvARRAY (av)[0];
2371 IV count = SvIVX (count_sv);
2372
2373 count += adjust;
2374 SvIVX (count_sv) = count;
2375
2376 /* now wake up as many waiters as are expected to lock */
2377 while (count > 0 && AvFILLp (av) > 0)
2378 {
2379 SV *cb;
2380
2381 /* swap first two elements so we can shift a waiter */
2382 AvARRAY (av)[0] = AvARRAY (av)[1];
2383 AvARRAY (av)[1] = count_sv;
2384 cb = av_shift (av);
2385
2386 if (SvOBJECT (cb))
2387 {
2388 api_ready (aTHX_ cb);
2389 --count;
2390 }
2391 else if (SvTYPE (cb) == SVt_PVCV)
2392 {
2393 dSP;
2394 PUSHMARK (SP);
2395 XPUSHs (sv_2mortal (newRV_inc ((SV *)av)));
2396 PUTBACK;
2397 call_sv (cb, G_VOID | G_DISCARD | G_EVAL | G_KEEPERR);
2398 }
2399
2400 SvREFCNT_dec (cb);
2401 }
2402}
2403
2404static void
2405coro_semaphore_on_destroy (pTHX_ struct coro *coro)
2406{
2407 /* call $sem->adjust (0) to possibly wake up some other waiters */
2408 coro_semaphore_adjust (aTHX_ (AV *)coro->slf_frame.data, 0);
2409}
2410
2411static int
2412slf_check_semaphore_down_or_wait (pTHX_ struct CoroSLF *frame, int acquire)
2413{
2414 AV *av = (AV *)frame->data;
2415 SV *count_sv = AvARRAY (av)[0];
2416
2417 /* if we are about to throw, don't actually acquire the lock, just throw */
2418 if (CORO_THROW)
2419 return 0;
2420 else if (SvIVX (count_sv) > 0)
2421 {
2422 SvSTATE_current->on_destroy = 0;
2423
2424 if (acquire)
2425 SvIVX (count_sv) = SvIVX (count_sv) - 1;
2426 else
2427 coro_semaphore_adjust (aTHX_ av, 0);
2428
2429 return 0;
2430 }
2431 else
2432 {
2433 int i;
2434 /* if we were woken up but can't down, we look through the whole */
2435 /* waiters list and only add us if we aren't in there already */
2436 /* this avoids some degenerate memory usage cases */
2437
2438 for (i = 1; i <= AvFILLp (av); ++i)
2439 if (AvARRAY (av)[i] == SvRV (coro_current))
2440 return 1;
2441
2442 av_push (av, SvREFCNT_inc (SvRV (coro_current)));
2443 return 1;
2444 }
2445}
2446
2447static int
2448slf_check_semaphore_down (pTHX_ struct CoroSLF *frame)
2449{
2450 return slf_check_semaphore_down_or_wait (aTHX_ frame, 1);
2451}
2452
2453static int
2454slf_check_semaphore_wait (pTHX_ struct CoroSLF *frame)
2455{
2456 return slf_check_semaphore_down_or_wait (aTHX_ frame, 0);
2457}
2458
2459static void
2460slf_init_semaphore_down_or_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2461{
2462 AV *av = (AV *)SvRV (arg [0]);
2463
2464 if (SvIVX (AvARRAY (av)[0]) > 0)
2465 {
2466 frame->data = (void *)av;
2467 frame->prepare = prepare_nop;
2468 }
2469 else
2470 {
2471 av_push (av, SvREFCNT_inc (SvRV (coro_current)));
2472
2473 frame->data = (void *)sv_2mortal (SvREFCNT_inc ((SV *)av));
2474 frame->prepare = prepare_schedule;
2475
2476 /* to avoid race conditions when a woken-up coro gets terminated */
2477 /* we arrange for a temporary on_destroy that calls adjust (0) */
2478 SvSTATE_current->on_destroy = coro_semaphore_on_destroy;
2479 }
2480}
2481
2482static void
2483slf_init_semaphore_down (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2484{
2485 slf_init_semaphore_down_or_wait (aTHX_ frame, cv, arg, items);
2486 frame->check = slf_check_semaphore_down;
2487}
2488
2489static void
2490slf_init_semaphore_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2491{
2492 if (items >= 2)
2493 {
2494 /* callback form */
2495 AV *av = (AV *)SvRV (arg [0]);
2496 CV *cb_cv = coro_sv_2cv (aTHX_ arg [1]);
2497
2498 av_push (av, (SV *)SvREFCNT_inc_NN (cb_cv));
2499
2500 if (SvIVX (AvARRAY (av)[0]) > 0)
2501 coro_semaphore_adjust (aTHX_ av, 0);
2502
2503 frame->prepare = prepare_nop;
2504 frame->check = slf_check_nop;
2505 }
2506 else
2507 {
2508 slf_init_semaphore_down_or_wait (aTHX_ frame, cv, arg, items);
2509 frame->check = slf_check_semaphore_wait;
2510 }
2511}
2512
2513/* signal */
2514
2515static void
2516coro_signal_wake (pTHX_ AV *av, int count)
2517{
2518 SvIVX (AvARRAY (av)[0]) = 0;
2519
2520 /* now signal count waiters */
2521 while (count > 0 && AvFILLp (av) > 0)
2522 {
2523 SV *cb;
2524
2525 /* swap first two elements so we can shift a waiter */
2526 cb = AvARRAY (av)[0];
2527 AvARRAY (av)[0] = AvARRAY (av)[1];
2528 AvARRAY (av)[1] = cb;
2529
2530 cb = av_shift (av);
2531
2532 api_ready (aTHX_ cb);
2533 sv_setiv (cb, 0); /* signal waiter */
2534 SvREFCNT_dec (cb);
2535
2536 --count;
2537 }
2538}
2539
2540static int
2541slf_check_signal_wait (pTHX_ struct CoroSLF *frame)
2542{
2543 /* if we are about to throw, also stop waiting */
2544 return SvROK ((SV *)frame->data) && !CORO_THROW;
2545}
2546
2547static void
2548slf_init_signal_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2549{
2550 AV *av = (AV *)SvRV (arg [0]);
2551
2552 if (SvIVX (AvARRAY (av)[0]))
2553 {
2554 SvIVX (AvARRAY (av)[0]) = 0;
2555 frame->prepare = prepare_nop;
2556 frame->check = slf_check_nop;
2557 }
2558 else
2559 {
2560 SV *waiter = newRV_inc (SvRV (coro_current)); /* owned by signal av */
2561
2562 av_push (av, waiter);
2563
2564 frame->data = (void *)sv_2mortal (SvREFCNT_inc_NN (waiter)); /* owned by process */
2565 frame->prepare = prepare_schedule;
2566 frame->check = slf_check_signal_wait;
2567 }
2568}
2569
2570/*****************************************************************************/
2571/* Coro::AIO */
2572
2573#define CORO_MAGIC_type_aio PERL_MAGIC_ext
2574
2575/* helper storage struct */
2576struct io_state
2577{
2578 int errorno;
2579 I32 laststype; /* U16 in 5.10.0 */
2580 int laststatval;
2581 Stat_t statcache;
2582};
2583
2584static void
2585coro_aio_callback (pTHX_ CV *cv)
2586{
2587 dXSARGS;
2588 AV *state = (AV *)GENSUB_ARG;
2589 SV *coro = av_pop (state);
2590 SV *data_sv = newSV (sizeof (struct io_state));
2591
2592 av_extend (state, items - 1);
2593
2594 sv_upgrade (data_sv, SVt_PV);
2595 SvCUR_set (data_sv, sizeof (struct io_state));
2596 SvPOK_only (data_sv);
2597
2598 {
2599 struct io_state *data = (struct io_state *)SvPVX (data_sv);
2600
2601 data->errorno = errno;
2602 data->laststype = PL_laststype;
2603 data->laststatval = PL_laststatval;
2604 data->statcache = PL_statcache;
2605 }
2606
2607 /* now build the result vector out of all the parameters and the data_sv */
2608 {
2609 int i;
2610
2611 for (i = 0; i < items; ++i)
2612 av_push (state, SvREFCNT_inc_NN (ST (i)));
2613 }
2614
2615 av_push (state, data_sv);
2616
2617 api_ready (aTHX_ coro);
2618 SvREFCNT_dec (coro);
2619 SvREFCNT_dec ((AV *)state);
2620}
2621
2622static int
2623slf_check_aio_req (pTHX_ struct CoroSLF *frame)
2624{
2625 AV *state = (AV *)frame->data;
2626
2627 /* if we are about to throw, return early */
2628 /* this does not cancel the aio request, but at least */
2629 /* it quickly returns */
2630 if (CORO_THROW)
2631 return 0;
2632
2633 /* one element that is an RV? repeat! */
2634 if (AvFILLp (state) == 0 && SvROK (AvARRAY (state)[0]))
2635 return 1;
2636
2637 /* restore status */
2638 {
2639 SV *data_sv = av_pop (state);
2640 struct io_state *data = (struct io_state *)SvPVX (data_sv);
2641
2642 errno = data->errorno;
2643 PL_laststype = data->laststype;
2644 PL_laststatval = data->laststatval;
2645 PL_statcache = data->statcache;
2646
2647 SvREFCNT_dec (data_sv);
2648 }
2649
2650 /* push result values */
2651 {
2652 dSP;
2653 int i;
2654
2655 EXTEND (SP, AvFILLp (state) + 1);
2656 for (i = 0; i <= AvFILLp (state); ++i)
2657 PUSHs (sv_2mortal (SvREFCNT_inc_NN (AvARRAY (state)[i])));
2658
2659 PUTBACK;
2660 }
2661
2662 return 0;
2663}
2664
2665static void
2666slf_init_aio_req (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2667{
2668 AV *state = (AV *)sv_2mortal ((SV *)newAV ());
2669 SV *coro_hv = SvRV (coro_current);
2670 struct coro *coro = SvSTATE_hv (coro_hv);
2671
2672 /* put our coroutine id on the state arg */
2673 av_push (state, SvREFCNT_inc_NN (coro_hv));
2674
2675 /* first see whether we have a non-zero priority and set it as AIO prio */
2676 if (coro->prio)
2677 {
2678 dSP;
2679
2680 static SV *prio_cv;
2681 static SV *prio_sv;
2682
2683 if (expect_false (!prio_cv))
2684 {
2685 prio_cv = (SV *)get_cv ("IO::AIO::aioreq_pri", 0);
2686 prio_sv = newSViv (0);
2687 }
2688
2689 PUSHMARK (SP);
2690 sv_setiv (prio_sv, coro->prio);
2691 XPUSHs (prio_sv);
2692
2693 PUTBACK;
2694 call_sv (prio_cv, G_VOID | G_DISCARD);
2695 }
2696
2697 /* now call the original request */
2698 {
2699 dSP;
2700 CV *req = (CV *)CORO_MAGIC_NN ((SV *)cv, CORO_MAGIC_type_aio)->mg_obj;
2701 int i;
2702
2703 PUSHMARK (SP);
2704
2705 /* first push all args to the stack */
2706 EXTEND (SP, items + 1);
2707
2708 for (i = 0; i < items; ++i)
2709 PUSHs (arg [i]);
2710
2711 /* now push the callback closure */
2712 PUSHs (sv_2mortal (gensub (aTHX_ coro_aio_callback, (void *)SvREFCNT_inc_NN ((SV *)state))));
2713
2714 /* now call the AIO function - we assume our request is uncancelable */
2715 PUTBACK;
2716 call_sv ((SV *)req, G_VOID | G_DISCARD);
2717 }
2718
2719 /* now that the requets is going, we loop toll we have a result */
2720 frame->data = (void *)state;
2721 frame->prepare = prepare_schedule;
2722 frame->check = slf_check_aio_req;
2723}
2724
2725static void
2726coro_aio_req_xs (pTHX_ CV *cv)
2727{
2728 dXSARGS;
2729
2730 CORO_EXECUTE_SLF_XS (slf_init_aio_req);
2731
2732 XSRETURN_EMPTY;
2733}
2734
2735/*****************************************************************************/
2736
2737#if CORO_CLONE
2738# include "clone.c"
2739#endif
2740
2741MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_
2742
2743PROTOTYPES: DISABLE
2744
2745BOOT:
2746{
2747#ifdef USE_ITHREADS
2748# if CORO_PTHREAD
2749 coro_thx = PERL_GET_CONTEXT;
2750# endif
2751#endif
2752 BOOT_PAGESIZE;
2753
2754 cctx_current = cctx_new_empty ();
2755
2756 irsgv = gv_fetchpv ("/" , GV_ADD|GV_NOTQUAL, SVt_PV);
2757 stdoutgv = gv_fetchpv ("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO);
2758
2759 orig_sigelem_get = PL_vtbl_sigelem.svt_get; PL_vtbl_sigelem.svt_get = coro_sigelem_get;
2760 orig_sigelem_set = PL_vtbl_sigelem.svt_set; PL_vtbl_sigelem.svt_set = coro_sigelem_set;
2761 orig_sigelem_clr = PL_vtbl_sigelem.svt_clear; PL_vtbl_sigelem.svt_clear = coro_sigelem_clr;
2762
2763 hv_sig = coro_get_hv (aTHX_ "SIG", TRUE);
2764 rv_diehook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::diehook" , 0, SVt_PVCV));
2765 rv_warnhook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::warnhook", 0, SVt_PVCV));
2766
2767 coro_state_stash = gv_stashpv ("Coro::State", TRUE);
2768
2769 newCONSTSUB (coro_state_stash, "CC_TRACE" , newSViv (CC_TRACE));
2770 newCONSTSUB (coro_state_stash, "CC_TRACE_SUB" , newSViv (CC_TRACE_SUB));
2771 newCONSTSUB (coro_state_stash, "CC_TRACE_LINE", newSViv (CC_TRACE_LINE));
2772 newCONSTSUB (coro_state_stash, "CC_TRACE_ALL" , newSViv (CC_TRACE_ALL));
2773
2774 main_mainstack = PL_mainstack;
2775 main_top_env = PL_top_env;
2776
2777 while (main_top_env->je_prev)
2778 main_top_env = main_top_env->je_prev;
2779
2780 {
2781 SV *slf = sv_2mortal (newSViv (PTR2IV (pp_slf)));
2782
2783 if (!PL_custom_op_names) PL_custom_op_names = newHV ();
2784 hv_store_ent (PL_custom_op_names, slf, newSVpv ("coro_slf", 0), 0);
2785
2786 if (!PL_custom_op_descs) PL_custom_op_descs = newHV ();
2787 hv_store_ent (PL_custom_op_descs, slf, newSVpv ("coro schedule like function", 0), 0);
2788 }
2789
2790 coroapi.ver = CORO_API_VERSION;
2791 coroapi.rev = CORO_API_REVISION;
2792
2793 coroapi.transfer = api_transfer;
2794
2795 coroapi.sv_state = SvSTATE_;
2796 coroapi.execute_slf = api_execute_slf;
2797 coroapi.prepare_nop = prepare_nop;
2798 coroapi.prepare_schedule = prepare_schedule;
2799 coroapi.prepare_cede = prepare_cede;
2800 coroapi.prepare_cede_notself = prepare_cede_notself;
2801
2802 {
2803 SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
2804
2805 if (!svp) croak ("Time::HiRes is required");
2806 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer");
2807
2808 nvtime = INT2PTR (double (*)(), SvIV (*svp));
2809 }
2810
2811 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL));
2812}
2813
2814SV *
2815new (char *klass, ...)
2816 ALIAS:
2817 Coro::new = 1
2818 CODE:
2819{
2820 struct coro *coro;
2821 MAGIC *mg;
2822 HV *hv;
2823 CV *cb;
2824 int i;
2825
2826 if (items > 1)
2827 {
2828 cb = coro_sv_2cv (aTHX_ ST (1));
2829
2830 if (!ix)
235 { 2831 {
236 /* I never used formats, so how should I know how these are implemented? */ 2832 if (CvISXSUB (cb))
237 /* my bold guess is as a simple, plain sub... */ 2833 croak ("Coro::State doesn't support XS functions as coroutine start, caught");
238 croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats"); 2834
2835 if (!CvROOT (cb))
2836 croak ("Coro::State doesn't support autoloaded or undefined functions as coroutine start, caught");
239 } 2837 }
240 } 2838 }
241 2839
242 if (top_si->si_type == PERLSI_MAIN)
243 break;
244
245 top_si = top_si->si_prev;
246 ccstk = top_si->si_cxstack;
247 cxix = top_si->si_cxix;
248 }
249
250 PUTBACK;
251 }
252
253 c->dowarn = PL_dowarn;
254 c->defav = GvAV (PL_defgv);
255 c->curstackinfo = PL_curstackinfo;
256 c->curstack = PL_curstack;
257 c->mainstack = PL_mainstack;
258 c->stack_sp = PL_stack_sp;
259 c->op = PL_op;
260 c->curpad = PL_curpad;
261 c->stack_base = PL_stack_base;
262 c->stack_max = PL_stack_max;
263 c->tmps_stack = PL_tmps_stack;
264 c->tmps_floor = PL_tmps_floor;
265 c->tmps_ix = PL_tmps_ix;
266 c->tmps_max = PL_tmps_max;
267 c->markstack = PL_markstack;
268 c->markstack_ptr = PL_markstack_ptr;
269 c->markstack_max = PL_markstack_max;
270 c->scopestack = PL_scopestack;
271 c->scopestack_ix = PL_scopestack_ix;
272 c->scopestack_max = PL_scopestack_max;
273 c->savestack = PL_savestack;
274 c->savestack_ix = PL_savestack_ix;
275 c->savestack_max = PL_savestack_max;
276 c->retstack = PL_retstack;
277 c->retstack_ix = PL_retstack_ix;
278 c->retstack_max = PL_retstack_max;
279 c->curcop = PL_curcop;
280}
281
282#define LOAD(state) do { load_state(aTHX_ state); SPAGAIN; } while (0)
283#define SAVE(state) do { PUTBACK; save_state(aTHX_ state); } while (0)
284
285static void
286load_state(pTHX_ Coro__State c)
287{
288 PL_dowarn = c->dowarn;
289 GvAV (PL_defgv) = c->defav;
290 PL_curstackinfo = c->curstackinfo;
291 PL_curstack = c->curstack;
292 PL_mainstack = c->mainstack;
293 PL_stack_sp = c->stack_sp;
294 PL_op = c->op;
295 PL_curpad = c->curpad;
296 PL_stack_base = c->stack_base;
297 PL_stack_max = c->stack_max;
298 PL_tmps_stack = c->tmps_stack;
299 PL_tmps_floor = c->tmps_floor;
300 PL_tmps_ix = c->tmps_ix;
301 PL_tmps_max = c->tmps_max;
302 PL_markstack = c->markstack;
303 PL_markstack_ptr = c->markstack_ptr;
304 PL_markstack_max = c->markstack_max;
305 PL_scopestack = c->scopestack;
306 PL_scopestack_ix = c->scopestack_ix;
307 PL_scopestack_max = c->scopestack_max;
308 PL_savestack = c->savestack;
309 PL_savestack_ix = c->savestack_ix;
310 PL_savestack_max = c->savestack_max;
311 PL_retstack = c->retstack;
312 PL_retstack_ix = c->retstack_ix;
313 PL_retstack_max = c->retstack_max;
314 PL_curcop = c->curcop;
315
316 {
317 dSP;
318 CV *cv;
319
320 /* now do the ugly restore mess */
321 while ((cv = (CV *)POPs))
322 {
323 AV *padlist = (AV *)POPs;
324
325 put_padlist (cv);
326 CvPADLIST(cv) = padlist;
327 CvDEPTH(cv) = (I32)POPs;
328
329#ifdef USE_THREADS
330 CvOWNER(cv) = (struct perl_thread *)POPs;
331 error does not work either
332#endif
333 }
334
335 PUTBACK;
336 }
337}
338
339/* this is an EXACT copy of S_nuke_stacks in perl.c, which is unfortunately static */
340STATIC void
341destroy_stacks(pTHX)
342{
343 /* die does this while calling POPSTACK, but I just don't see why. */
344 /* OTOH, die does not have a memleak, but we do... */
345 dounwind(-1);
346
347 /* is this ugly, I ask? */
348 while (PL_scopestack_ix)
349 LEAVE;
350
351 while (PL_curstackinfo->si_next)
352 PL_curstackinfo = PL_curstackinfo->si_next;
353
354 while (PL_curstackinfo)
355 {
356 PERL_SI *p = PL_curstackinfo->si_prev;
357
358 SvREFCNT_dec(PL_curstackinfo->si_stack);
359 Safefree(PL_curstackinfo->si_cxstack);
360 Safefree(PL_curstackinfo);
361 PL_curstackinfo = p;
362 }
363
364 if (PL_scopestack_ix != 0)
365 Perl_warner(aTHX_ WARN_INTERNAL,
366 "Unbalanced scopes: %ld more ENTERs than LEAVEs\n",
367 (long)PL_scopestack_ix);
368 if (PL_savestack_ix != 0)
369 Perl_warner(aTHX_ WARN_INTERNAL,
370 "Unbalanced saves: %ld more saves than restores\n",
371 (long)PL_savestack_ix);
372 if (PL_tmps_floor != -1)
373 Perl_warner(aTHX_ WARN_INTERNAL,"Unbalanced tmps: %ld more allocs than frees\n",
374 (long)PL_tmps_floor + 1);
375 /*
376 */
377 Safefree(PL_tmps_stack);
378 Safefree(PL_markstack);
379 Safefree(PL_scopestack);
380 Safefree(PL_savestack);
381 Safefree(PL_retstack);
382}
383
384#define SUB_INIT "Coro::State::_newcoro"
385
386MODULE = Coro::State PACKAGE = Coro::State
387
388PROTOTYPES: ENABLE
389
390BOOT:
391 if (!padlist_cache)
392 padlist_cache = newHV ();
393
394Coro::State
395_newprocess(args)
396 SV * args
397 PROTOTYPE: $
398 CODE:
399 Coro__State coro;
400
401 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV)
402 croak ("Coro::State::newprocess expects an arrayref");
403
404 New (0, coro, 1, struct coro); 2840 Newz (0, coro, 1, struct coro);
2841 coro->args = newAV ();
2842 coro->flags = CF_NEW;
405 2843
406 coro->mainstack = 0; /* actual work is done inside transfer */ 2844 if (coro_first) coro_first->prev = coro;
407 coro->args = (AV *)SvREFCNT_inc (SvRV (args)); 2845 coro->next = coro_first;
2846 coro_first = coro;
408 2847
409 RETVAL = coro; 2848 coro->hv = hv = newHV ();
2849 mg = sv_magicext ((SV *)hv, 0, CORO_MAGIC_type_state, &coro_state_vtbl, (char *)coro, 0);
2850 mg->mg_flags |= MGf_DUP;
2851 RETVAL = sv_bless (newRV_noinc ((SV *)hv), gv_stashpv (klass, 1));
2852
2853 if (items > 1)
2854 {
2855 av_extend (coro->args, items - 1 + ix - 1);
2856
2857 if (ix)
2858 {
2859 av_push (coro->args, SvREFCNT_inc_NN ((SV *)cb));
2860 cb = cv_coro_run;
2861 }
2862
2863 coro->startcv = (CV *)SvREFCNT_inc_NN ((SV *)cb);
2864
2865 for (i = 2; i < items; i++)
2866 av_push (coro->args, newSVsv (ST (i)));
2867 }
2868}
410 OUTPUT: 2869 OUTPUT:
411 RETVAL 2870 RETVAL
412 2871
413void 2872void
414transfer(prev,next) 2873transfer (...)
415 Coro::State_or_hashref prev 2874 PROTOTYPE: $$
416 Coro::State_or_hashref next 2875 CODE:
417 CODE: 2876 CORO_EXECUTE_SLF_XS (slf_init_transfer);
418 2877
419 if (prev != next) 2878bool
2879_destroy (SV *coro_sv)
2880 CODE:
2881 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv));
2882 OUTPUT:
2883 RETVAL
2884
2885void
2886_exit (int code)
2887 PROTOTYPE: $
2888 CODE:
2889 _exit (code);
2890
2891SV *
2892clone (Coro::State coro)
2893 CODE:
2894{
2895#if CORO_CLONE
2896 struct coro *ncoro = coro_clone (coro);
2897 MAGIC *mg;
2898 /* TODO: too much duplication */
2899 ncoro->hv = newHV ();
2900 mg = sv_magicext ((SV *)ncoro->hv, 0, CORO_MAGIC_type_state, &coro_state_vtbl, (char *)ncoro, 0);
2901 mg->mg_flags |= MGf_DUP;
2902 RETVAL = sv_bless (newRV_noinc ((SV *)ncoro->hv), SvSTASH (coro->hv));
2903#else
2904 croak ("Coro::State->clone has not been configured into this installation of Coro, realised");
2905#endif
2906}
2907 OUTPUT:
2908 RETVAL
2909
2910int
2911cctx_stacksize (int new_stacksize = 0)
2912 PROTOTYPE: ;$
2913 CODE:
2914 RETVAL = cctx_stacksize;
2915 if (new_stacksize)
420 { 2916 {
2917 cctx_stacksize = new_stacksize;
2918 ++cctx_gen;
421 /* 2919 }
422 * this could be done in newprocess which would lead to 2920 OUTPUT:
423 * extremely elegant and fast (just SAVE/LOAD) 2921 RETVAL
424 * code here, but lazy allocation of stacks has also 2922
425 * some virtues and the overhead of the if() is nil. 2923int
2924cctx_max_idle (int max_idle = 0)
2925 PROTOTYPE: ;$
2926 CODE:
2927 RETVAL = cctx_max_idle;
2928 if (max_idle > 1)
2929 cctx_max_idle = max_idle;
2930 OUTPUT:
2931 RETVAL
2932
2933int
2934cctx_count ()
2935 PROTOTYPE:
2936 CODE:
2937 RETVAL = cctx_count;
2938 OUTPUT:
2939 RETVAL
2940
2941int
2942cctx_idle ()
2943 PROTOTYPE:
2944 CODE:
2945 RETVAL = cctx_idle;
2946 OUTPUT:
2947 RETVAL
2948
2949void
2950list ()
2951 PROTOTYPE:
2952 PPCODE:
2953{
2954 struct coro *coro;
2955 for (coro = coro_first; coro; coro = coro->next)
2956 if (coro->hv)
2957 XPUSHs (sv_2mortal (newRV_inc ((SV *)coro->hv)));
2958}
2959
2960void
2961call (Coro::State coro, SV *coderef)
2962 ALIAS:
2963 eval = 1
2964 CODE:
2965{
2966 if (coro->mainstack && ((coro->flags & CF_RUNNING) || coro->slot))
426 */ 2967 {
427 if (next->mainstack) 2968 struct coro temp;
2969
2970 if (!(coro->flags & CF_RUNNING))
428 { 2971 {
429 SAVE (prev); 2972 PUTBACK;
430 LOAD (next); 2973 save_perl (aTHX_ &temp);
431 /* mark this state as in-use */ 2974 load_perl (aTHX_ coro);
432 next->mainstack = 0;
433 next->tmps_ix = -2;
434 } 2975 }
435 else if (next->tmps_ix == -2) 2976
2977 {
2978 dSP;
2979 ENTER;
2980 SAVETMPS;
2981 PUTBACK;
2982 PUSHSTACK;
2983 PUSHMARK (SP);
2984
2985 if (ix)
2986 eval_sv (coderef, 0);
2987 else
2988 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
2989
2990 POPSTACK;
2991 SPAGAIN;
2992 FREETMPS;
2993 LEAVE;
2994 PUTBACK;
2995 }
2996
2997 if (!(coro->flags & CF_RUNNING))
436 { 2998 {
437 croak ("tried to transfer to running coroutine"); 2999 save_perl (aTHX_ coro);
438 } 3000 load_perl (aTHX_ &temp);
439 else
440 {
441 SAVE (prev);
442
443 /*
444 * emulate part of the perl startup here.
445 */
446 UNOP myop;
447
448 init_stacks (); /* from perl.c */
449 PL_op = (OP *)&myop;
450 /*PL_curcop = 0;*/
451 GvAV (PL_defgv) = (AV *)SvREFCNT_inc ((SV *)next->args);
452
453 SPAGAIN; 3001 SPAGAIN;
454 Zero(&myop, 1, UNOP);
455 myop.op_next = Nullop;
456 myop.op_flags = OPf_WANT_VOID;
457
458 PUSHMARK(SP);
459 XPUSHs ((SV*)get_cv(SUB_INIT, TRUE));
460 PUTBACK;
461 /*
462 * the next line is slightly wrong, as PL_op->op_next
463 * is actually being executed so we skip the first op.
464 * that doesn't matter, though, since it is only
465 * pp_nextstate and we never return...
466 */
467 PL_op = Perl_pp_entersub(aTHX);
468 SPAGAIN;
469
470 ENTER;
471 } 3002 }
472 } 3003 }
3004}
3005
3006SV *
3007is_ready (Coro::State coro)
3008 PROTOTYPE: $
3009 ALIAS:
3010 is_ready = CF_READY
3011 is_running = CF_RUNNING
3012 is_new = CF_NEW
3013 is_destroyed = CF_DESTROYED
3014 CODE:
3015 RETVAL = boolSV (coro->flags & ix);
3016 OUTPUT:
3017 RETVAL
473 3018
474void 3019void
475DESTROY(coro) 3020throw (Coro::State self, SV *throw = &PL_sv_undef)
476 Coro::State coro 3021 PROTOTYPE: $;$
477 CODE: 3022 CODE:
3023{
3024 struct coro *current = SvSTATE_current;
3025 SV **throwp = self == current ? &CORO_THROW : &self->except;
3026 SvREFCNT_dec (*throwp);
3027 *throwp = SvOK (throw) ? newSVsv (throw) : 0;
3028}
478 3029
479 if (coro->mainstack) 3030void
3031api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
3032 PROTOTYPE: $;$
3033 C_ARGS: aTHX_ coro, flags
3034
3035SV *
3036has_cctx (Coro::State coro)
3037 PROTOTYPE: $
3038 CODE:
3039 /* maybe manage the running flag differently */
3040 RETVAL = boolSV (!!coro->cctx || (coro->flags & CF_RUNNING));
3041 OUTPUT:
3042 RETVAL
3043
3044int
3045is_traced (Coro::State coro)
3046 PROTOTYPE: $
3047 CODE:
3048 RETVAL = (coro->cctx ? coro->cctx->flags : 0) & CC_TRACE_ALL;
3049 OUTPUT:
3050 RETVAL
3051
3052UV
3053rss (Coro::State coro)
3054 PROTOTYPE: $
3055 ALIAS:
3056 usecount = 1
3057 CODE:
3058 switch (ix)
3059 {
3060 case 0: RETVAL = coro_rss (aTHX_ coro); break;
3061 case 1: RETVAL = coro->usecount; break;
3062 }
3063 OUTPUT:
3064 RETVAL
3065
3066void
3067force_cctx ()
3068 PROTOTYPE:
3069 CODE:
3070 cctx_current->idle_sp = 0;
3071
3072void
3073swap_defsv (Coro::State self)
3074 PROTOTYPE: $
3075 ALIAS:
3076 swap_defav = 1
3077 CODE:
3078 if (!self->slot)
3079 croak ("cannot swap state with coroutine that has no saved state,");
3080 else
480 { 3081 {
481 struct coro temp; 3082 SV **src = ix ? (SV **)&GvAV (PL_defgv) : &GvSV (PL_defgv);
3083 SV **dst = ix ? (SV **)&self->slot->defav : (SV **)&self->slot->defsv;
482 3084
483 SAVE(aTHX_ (&temp)); 3085 SV *tmp = *src; *src = *dst; *dst = tmp;
484 LOAD(aTHX_ coro);
485
486 destroy_stacks ();
487 SvREFCNT_dec ((SV *)GvAV (PL_defgv));
488
489 LOAD((&temp));
490 } 3086 }
491 3087
3088
3089MODULE = Coro::State PACKAGE = Coro
3090
3091BOOT:
3092{
3093 int i;
3094
3095 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE);
3096 sv_pool_size = coro_get_sv (aTHX_ "Coro::POOL_SIZE" , TRUE);
3097 cv_coro_run = get_cv ( "Coro::_terminate", GV_ADD);
3098 cv_coro_terminate = get_cv ( "Coro::terminate" , GV_ADD);
3099 coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current);
3100 av_async_pool = coro_get_av (aTHX_ "Coro::async_pool", TRUE);
3101 av_destroy = coro_get_av (aTHX_ "Coro::destroy" , TRUE);
3102 sv_manager = coro_get_sv (aTHX_ "Coro::manager" , TRUE);
3103
3104 sv_async_pool_idle = newSVpv ("[async pool idle]", 0); SvREADONLY_on (sv_async_pool_idle);
3105 sv_Coro = newSVpv ("Coro", 0); SvREADONLY_on (sv_Coro);
3106 cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler);
3107 cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new);
3108
3109 coro_stash = gv_stashpv ("Coro", TRUE);
3110
3111 newCONSTSUB (coro_stash, "PRIO_MAX", newSViv (PRIO_MAX));
3112 newCONSTSUB (coro_stash, "PRIO_HIGH", newSViv (PRIO_HIGH));
3113 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (PRIO_NORMAL));
3114 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (PRIO_LOW));
3115 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (PRIO_IDLE));
3116 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (PRIO_MIN));
3117
3118 for (i = PRIO_MAX - PRIO_MIN + 1; i--; )
3119 coro_ready[i] = newAV ();
3120
3121 {
3122 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE);
3123
3124 coroapi.schedule = api_schedule;
3125 coroapi.schedule_to = api_schedule_to;
3126 coroapi.cede = api_cede;
3127 coroapi.cede_notself = api_cede_notself;
3128 coroapi.ready = api_ready;
3129 coroapi.is_ready = api_is_ready;
3130 coroapi.nready = coro_nready;
3131 coroapi.current = coro_current;
3132
3133 /*GCoroAPI = &coroapi;*/
3134 sv_setiv (sv, (IV)&coroapi);
3135 SvREADONLY_on (sv);
3136 }
3137}
3138
3139void
3140terminate (...)
3141 CODE:
3142 CORO_EXECUTE_SLF_XS (slf_init_terminate);
3143
3144void
3145schedule (...)
3146 CODE:
3147 CORO_EXECUTE_SLF_XS (slf_init_schedule);
3148
3149void
3150schedule_to (...)
3151 CODE:
3152 CORO_EXECUTE_SLF_XS (slf_init_schedule_to);
3153
3154void
3155cede_to (...)
3156 CODE:
3157 CORO_EXECUTE_SLF_XS (slf_init_cede_to);
3158
3159void
3160cede (...)
3161 CODE:
3162 CORO_EXECUTE_SLF_XS (slf_init_cede);
3163
3164void
3165cede_notself (...)
3166 CODE:
3167 CORO_EXECUTE_SLF_XS (slf_init_cede_notself);
3168
3169void
3170_cancel (Coro::State self)
3171 CODE:
3172 coro_state_destroy (aTHX_ self);
3173 coro_call_on_destroy (aTHX_ self);
3174
3175void
3176_set_current (SV *current)
3177 PROTOTYPE: $
3178 CODE:
3179 SvREFCNT_dec (SvRV (coro_current));
3180 SvRV_set (coro_current, SvREFCNT_inc_NN (SvRV (current)));
3181
3182void
3183_set_readyhook (SV *hook)
3184 PROTOTYPE: $
3185 CODE:
492 SvREFCNT_dec (coro->args); 3186 SvREFCNT_dec (coro_readyhook);
493 Safefree (coro); 3187 coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0;
494 3188
3189int
3190prio (Coro::State coro, int newprio = 0)
3191 PROTOTYPE: $;$
3192 ALIAS:
3193 nice = 1
3194 CODE:
3195{
3196 RETVAL = coro->prio;
495 3197
3198 if (items > 1)
3199 {
3200 if (ix)
3201 newprio = coro->prio - newprio;
3202
3203 if (newprio < PRIO_MIN) newprio = PRIO_MIN;
3204 if (newprio > PRIO_MAX) newprio = PRIO_MAX;
3205
3206 coro->prio = newprio;
3207 }
3208}
3209 OUTPUT:
3210 RETVAL
3211
3212SV *
3213ready (SV *self)
3214 PROTOTYPE: $
3215 CODE:
3216 RETVAL = boolSV (api_ready (aTHX_ self));
3217 OUTPUT:
3218 RETVAL
3219
3220int
3221nready (...)
3222 PROTOTYPE:
3223 CODE:
3224 RETVAL = coro_nready;
3225 OUTPUT:
3226 RETVAL
3227
3228void
3229_pool_handler (...)
3230 CODE:
3231 CORO_EXECUTE_SLF_XS (slf_init_pool_handler);
3232
3233void
3234async_pool (SV *cv, ...)
3235 PROTOTYPE: &@
3236 PPCODE:
3237{
3238 HV *hv = (HV *)av_pop (av_async_pool);
3239 AV *av = newAV ();
3240 SV *cb = ST (0);
3241 int i;
3242
3243 av_extend (av, items - 2);
3244 for (i = 1; i < items; ++i)
3245 av_push (av, SvREFCNT_inc_NN (ST (i)));
3246
3247 if ((SV *)hv == &PL_sv_undef)
3248 {
3249 PUSHMARK (SP);
3250 EXTEND (SP, 2);
3251 PUSHs (sv_Coro);
3252 PUSHs ((SV *)cv_pool_handler);
3253 PUTBACK;
3254 call_sv ((SV *)cv_coro_state_new, G_SCALAR);
3255 SPAGAIN;
3256
3257 hv = (HV *)SvREFCNT_inc_NN (SvRV (POPs));
3258 }
3259
3260 {
3261 struct coro *coro = SvSTATE_hv (hv);
3262
3263 assert (!coro->invoke_cb);
3264 assert (!coro->invoke_av);
3265 coro->invoke_cb = SvREFCNT_inc (cb);
3266 coro->invoke_av = av;
3267 }
3268
3269 api_ready (aTHX_ (SV *)hv);
3270
3271 if (GIMME_V != G_VOID)
3272 XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
3273 else
3274 SvREFCNT_dec (hv);
3275}
3276
3277SV *
3278rouse_cb ()
3279 PROTOTYPE:
3280 CODE:
3281 RETVAL = coro_new_rouse_cb (aTHX);
3282 OUTPUT:
3283 RETVAL
3284
3285void
3286rouse_wait (...)
3287 PROTOTYPE: ;$
3288 PPCODE:
3289 CORO_EXECUTE_SLF_XS (slf_init_rouse_wait);
3290
3291
3292MODULE = Coro::State PACKAGE = PerlIO::cede
3293
3294BOOT:
3295 PerlIO_define_layer (aTHX_ &PerlIO_cede);
3296
3297
3298MODULE = Coro::State PACKAGE = Coro::Semaphore
3299
3300SV *
3301new (SV *klass, SV *count = 0)
3302 CODE:
3303 RETVAL = sv_bless (
3304 coro_waitarray_new (aTHX_ count && SvOK (count) ? SvIV (count) : 1),
3305 GvSTASH (CvGV (cv))
3306 );
3307 OUTPUT:
3308 RETVAL
3309
3310# helper for Coro::Channel
3311SV *
3312_alloc (int count)
3313 CODE:
3314 RETVAL = coro_waitarray_new (aTHX_ count);
3315 OUTPUT:
3316 RETVAL
3317
3318SV *
3319count (SV *self)
3320 CODE:
3321 RETVAL = newSVsv (AvARRAY ((AV *)SvRV (self))[0]);
3322 OUTPUT:
3323 RETVAL
3324
3325void
3326up (SV *self, int adjust = 1)
3327 ALIAS:
3328 adjust = 1
3329 CODE:
3330 coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1);
3331
3332void
3333down (...)
3334 CODE:
3335 CORO_EXECUTE_SLF_XS (slf_init_semaphore_down);
3336
3337void
3338wait (...)
3339 CODE:
3340 CORO_EXECUTE_SLF_XS (slf_init_semaphore_wait);
3341
3342void
3343try (SV *self)
3344 PPCODE:
3345{
3346 AV *av = (AV *)SvRV (self);
3347 SV *count_sv = AvARRAY (av)[0];
3348 IV count = SvIVX (count_sv);
3349
3350 if (count > 0)
3351 {
3352 --count;
3353 SvIVX (count_sv) = count;
3354 XSRETURN_YES;
3355 }
3356 else
3357 XSRETURN_NO;
3358}
3359
3360void
3361waiters (SV *self)
3362 PPCODE:
3363{
3364 AV *av = (AV *)SvRV (self);
3365 int wcount = AvFILLp (av) + 1 - 1;
3366
3367 if (GIMME_V == G_SCALAR)
3368 XPUSHs (sv_2mortal (newSViv (wcount)));
3369 else
3370 {
3371 int i;
3372 EXTEND (SP, wcount);
3373 for (i = 1; i <= wcount; ++i)
3374 PUSHs (sv_2mortal (newRV_inc (AvARRAY (av)[i])));
3375 }
3376}
3377
3378MODULE = Coro::State PACKAGE = Coro::Signal
3379
3380SV *
3381new (SV *klass)
3382 CODE:
3383 RETVAL = sv_bless (
3384 coro_waitarray_new (aTHX_ 0),
3385 GvSTASH (CvGV (cv))
3386 );
3387 OUTPUT:
3388 RETVAL
3389
3390void
3391wait (...)
3392 CODE:
3393 CORO_EXECUTE_SLF_XS (slf_init_signal_wait);
3394
3395void
3396broadcast (SV *self)
3397 CODE:
3398{
3399 AV *av = (AV *)SvRV (self);
3400 coro_signal_wake (aTHX_ av, AvFILLp (av));
3401}
3402
3403void
3404send (SV *self)
3405 CODE:
3406{
3407 AV *av = (AV *)SvRV (self);
3408
3409 if (AvFILLp (av))
3410 coro_signal_wake (aTHX_ av, 1);
3411 else
3412 SvIVX (AvARRAY (av)[0]) = 1; /* remember the signal */
3413}
3414
3415IV
3416awaited (SV *self)
3417 CODE:
3418 RETVAL = AvFILLp ((AV *)SvRV (self)) + 1 - 1;
3419 OUTPUT:
3420 RETVAL
3421
3422
3423MODULE = Coro::State PACKAGE = Coro::AnyEvent
3424
3425BOOT:
3426 sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE);
3427
3428void
3429_schedule (...)
3430 CODE:
3431{
3432 static int incede;
3433
3434 api_cede_notself (aTHX);
3435
3436 ++incede;
3437 while (coro_nready >= incede && api_cede (aTHX))
3438 ;
3439
3440 sv_setsv (sv_activity, &PL_sv_undef);
3441 if (coro_nready >= incede)
3442 {
3443 PUSHMARK (SP);
3444 PUTBACK;
3445 call_pv ("Coro::AnyEvent::_activity", G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
3446 }
3447
3448 --incede;
3449}
3450
3451
3452MODULE = Coro::State PACKAGE = Coro::AIO
3453
3454void
3455_register (char *target, char *proto, SV *req)
3456 CODE:
3457{
3458 CV *req_cv = coro_sv_2cv (aTHX_ req);
3459 /* newXSproto doesn't return the CV on 5.8 */
3460 CV *slf_cv = newXS (target, coro_aio_req_xs, __FILE__);
3461 sv_setpv ((SV *)slf_cv, proto);
3462 sv_magicext ((SV *)slf_cv, (SV *)req_cv, CORO_MAGIC_type_aio, 0, 0, 0);
3463}
3464

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines