ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/State.xs
(Generate patch)

Comparing Coro/Coro/State.xs (file contents):
Revision 1.6 by root, Tue Jul 17 15:42:28 2001 UTC vs.
Revision 1.382 by root, Thu Feb 10 08:06:27 2011 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines