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.4 by root, Tue Jul 17 02:21:56 2001 UTC vs.
Revision 1.400 by root, Thu May 12 23:55:39 2011 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines