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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines