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

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines