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.110 by root, Tue Nov 28 23:08:07 2006 UTC vs.
Revision 1.149 by root, Sat Apr 14 15:06:05 2007 UTC

1#include "libcoro/coro.c" 1#include "libcoro/coro.c"
2
3#define PERL_NO_GET_CONTEXT
2 4
3#include "EXTERN.h" 5#include "EXTERN.h"
4#include "perl.h" 6#include "perl.h"
5#include "XSUB.h" 7#include "XSUB.h"
6 8
7#include "patchlevel.h" 9#include "patchlevel.h"
8 10
9#if USE_VALGRIND
10# include <valgrind/valgrind.h>
11#endif
12
13#define PERL_VERSION_ATLEAST(a,b,c) \
14 (PERL_REVISION > (a) \
15 || (PERL_REVISION == (a) \
16 && (PERL_VERSION > (b) \
17 || (PERL_VERSION == (b) && PERLSUBVERSION >= (c)))))
18
19#if !PERL_VERSION_ATLEAST (5,6,0)
20# ifndef PL_ppaddr
21# define PL_ppaddr ppaddr
22# endif
23# ifndef call_sv
24# define call_sv perl_call_sv
25# endif
26# ifndef get_sv
27# define get_sv perl_get_sv
28# endif
29# ifndef get_cv
30# define get_cv perl_get_cv
31# endif
32# ifndef IS_PADGV
33# define IS_PADGV(v) 0
34# endif
35# ifndef IS_PADCONST
36# define IS_PADCONST(v) 0
37# endif
38#endif
39
40#include <stdio.h> 11#include <stdio.h>
41#include <errno.h> 12#include <errno.h>
42 13#include <assert.h>
43#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64
44# undef STACKGUARD
45#endif
46
47#ifndef STACKGUARD
48# define STACKGUARD 0
49#endif
50 14
51#ifdef HAVE_MMAP 15#ifdef HAVE_MMAP
52# include <unistd.h> 16# include <unistd.h>
53# include <sys/mman.h> 17# include <sys/mman.h>
54# ifndef MAP_ANONYMOUS 18# ifndef MAP_ANONYMOUS
69#else 33#else
70# define PAGESIZE 0 34# define PAGESIZE 0
71# define BOOT_PAGESIZE (void)0 35# define BOOT_PAGESIZE (void)0
72#endif 36#endif
73 37
38#if CORO_USE_VALGRIND
39# include <valgrind/valgrind.h>
40# define REGISTER_STACK(cctx,start,end) (cctx)->valgrind_id = VALGRIND_STACK_REGISTER ((start), (end))
41#else
42# define REGISTER_STACK(cctx,start,end)
43#endif
44
45/* the maximum number of idle cctx that will be pooled */
46#define MAX_IDLE_CCTX 8
47
48#define PERL_VERSION_ATLEAST(a,b,c) \
49 (PERL_REVISION > (a) \
50 || (PERL_REVISION == (a) \
51 && (PERL_VERSION > (b) \
52 || (PERL_VERSION == (b) && PERLSUBVERSION >= (c)))))
53
54#if !PERL_VERSION_ATLEAST (5,6,0)
55# ifndef PL_ppaddr
56# define PL_ppaddr ppaddr
57# endif
58# ifndef call_sv
59# define call_sv perl_call_sv
60# endif
61# ifndef get_sv
62# define get_sv perl_get_sv
63# endif
64# ifndef get_cv
65# define get_cv perl_get_cv
66# endif
67# ifndef IS_PADGV
68# define IS_PADGV(v) 0
69# endif
70# ifndef IS_PADCONST
71# define IS_PADCONST(v) 0
72# endif
73#endif
74
75/* 5.8.7 */
76#ifndef SvRV_set
77# define SvRV_set(s,v) SvRV(s) = (v)
78#endif
79
80#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64
81# undef CORO_STACKGUARD
82#endif
83
84#ifndef CORO_STACKGUARD
85# define CORO_STACKGUARD 0
86#endif
87
88/* prefer perl internal functions over our own? */
89#ifndef CORO_PREFER_PERL_FUNCTIONS
90# define CORO_PREFER_PERL_FUNCTIONS 0
91#endif
92
74/* The next macro should declare a variable stacklevel that contains and approximation 93/* The next macro should declare a variable stacklevel that contains and approximation
75 * to the current C stack pointer. Its property is that it changes with each call 94 * to the current C stack pointer. Its property is that it changes with each call
76 * and should be unique. */ 95 * and should be unique. */
77#define dSTACKLEVEL int stacklevel 96#define dSTACKLEVEL int stacklevel
78#define STACKLEVEL ((void *)&stacklevel) 97#define STACKLEVEL ((void *)&stacklevel)
79 98
80#define IN_DESTRUCT (PL_main_cv == Nullcv) 99#define IN_DESTRUCT (PL_main_cv == Nullcv)
81 100
82#if __GNUC__ >= 3 101#if __GNUC__ >= 3
83# define attribute(x) __attribute__(x) 102# define attribute(x) __attribute__(x)
103# define BARRIER __asm__ __volatile__ ("" : : : "memory")
84#else 104#else
85# define attribute(x) 105# define attribute(x)
106# define BARRIER
86#endif 107#endif
87 108
88#define NOINLINE attribute ((noinline)) 109#define NOINLINE attribute ((noinline))
89 110
90#include "CoroAPI.h" 111#include "CoroAPI.h"
91
92#define TRANSFER_SET_STACKLEVEL 0x8bfbfbfb /* magic cookie */
93 112
94#ifdef USE_ITHREADS 113#ifdef USE_ITHREADS
95static perl_mutex coro_mutex; 114static perl_mutex coro_mutex;
96# define LOCK do { MUTEX_LOCK (&coro_mutex); } while (0) 115# define LOCK do { MUTEX_LOCK (&coro_mutex); } while (0)
97# define UNLOCK do { MUTEX_UNLOCK (&coro_mutex); } while (0) 116# define UNLOCK do { MUTEX_UNLOCK (&coro_mutex); } while (0)
98#else 117#else
99# define LOCK (void)0 118# define LOCK (void)0
100# define UNLOCK (void)0 119# define UNLOCK (void)0
101#endif 120#endif
102 121
122/* helper storage struct for Coro::AIO */
123struct io_state
124{
125 int errorno;
126 I32 laststype;
127 int laststatval;
128 Stat_t statcache;
129};
130
131static size_t coro_stacksize = CORO_STACKSIZE;
103static struct CoroAPI coroapi; 132static struct CoroAPI coroapi;
104static AV *main_mainstack; /* used to differentiate between $main and others */ 133static AV *main_mainstack; /* used to differentiate between $main and others */
134static JMPENV *main_top_env;
105static HV *coro_state_stash, *coro_stash; 135static HV *coro_state_stash, *coro_stash;
106static SV *coro_mortal; /* will be freed after next transfer */ 136static SV *coro_mortal; /* will be freed after next transfer */
107 137
108static struct coro_cctx *cctx_first; 138static struct coro_cctx *cctx_first;
109static int cctx_count, cctx_idle; 139static int cctx_count, cctx_idle;
112typedef struct coro_cctx { 142typedef struct coro_cctx {
113 struct coro_cctx *next; 143 struct coro_cctx *next;
114 144
115 /* the stack */ 145 /* the stack */
116 void *sptr; 146 void *sptr;
117 long ssize; /* positive == mmap, otherwise malloc */ 147 size_t ssize;
118 148
119 /* cpu state */ 149 /* cpu state */
120 void *idle_sp; /* sp of top-level transfer/schedule/cede call */ 150 void *idle_sp; /* sp of top-level transfer/schedule/cede call */
151 JMPENV *idle_te; /* same as idle_sp, but for top_env, TODO: remove once stable */
121 JMPENV *top_env; 152 JMPENV *top_env;
122 coro_context cctx; 153 coro_context cctx;
123 154
124#if USE_VALGRIND 155#if CORO_USE_VALGRIND
125 int valgrind_id; 156 int valgrind_id;
126#endif 157#endif
158 char inuse, mapped;
127} coro_cctx; 159} coro_cctx;
160
161enum {
162 CF_RUNNING = 0x0001, /* coroutine is running */
163 CF_READY = 0x0002, /* coroutine is ready */
164 CF_NEW = 0x0004, /* has never been switched to */
165 CF_DESTROYED = 0x0008, /* coroutine data has been freed */
166};
128 167
129/* this is a structure representing a perl-level coroutine */ 168/* this is a structure representing a perl-level coroutine */
130struct coro { 169struct coro {
131 /* the c coroutine allocated to this perl coroutine, if any */ 170 /* the c coroutine allocated to this perl coroutine, if any */
132 coro_cctx *cctx; 171 coro_cctx *cctx;
133 172
134 /* data associated with this coroutine (initial args) */ 173 /* data associated with this coroutine (initial args) */
135 AV *args; 174 AV *args;
136 int refcnt; 175 int refcnt;
176 int save; /* CORO_SAVE flags */
177 int flags; /* CF_ flags */
137 178
138 /* optionally saved, might be zero */ 179 /* optionally saved, might be zero */
139 AV *defav; 180 AV *defav; /* @_ */
140 SV *defsv; 181 SV *defsv; /* $_ */
141 SV *errsv; 182 SV *errsv; /* $@ */
183 GV *deffh; /* default filehandle */
184 SV *irssv; /* $/ */
185 SV *irssv_sv; /* real $/ cache */
142 186
143#define VAR(name,type) type name; 187#define VAR(name,type) type name;
144# include "state.h" 188# include "state.h"
145#undef VAR 189#undef VAR
146 190
149}; 193};
150 194
151typedef struct coro *Coro__State; 195typedef struct coro *Coro__State;
152typedef struct coro *Coro__State_or_hashref; 196typedef struct coro *Coro__State_or_hashref;
153 197
198/** Coro ********************************************************************/
199
200#define PRIO_MAX 3
201#define PRIO_HIGH 1
202#define PRIO_NORMAL 0
203#define PRIO_LOW -1
204#define PRIO_IDLE -3
205#define PRIO_MIN -4
206
207/* for Coro.pm */
208static SV *coro_current;
209static AV *coro_ready [PRIO_MAX-PRIO_MIN+1];
210static int coro_nready;
211
212/** lowlevel stuff **********************************************************/
213
154static AV * 214static AV *
155coro_clone_padlist (CV *cv) 215coro_clone_padlist (pTHX_ CV *cv)
156{ 216{
157 AV *padlist = CvPADLIST (cv); 217 AV *padlist = CvPADLIST (cv);
158 AV *newpadlist, *newpad; 218 AV *newpadlist, *newpad;
159 219
160 newpadlist = newAV (); 220 newpadlist = newAV ();
172 232
173 return newpadlist; 233 return newpadlist;
174} 234}
175 235
176static void 236static void
177free_padlist (AV *padlist) 237free_padlist (pTHX_ AV *padlist)
178{ 238{
179 /* may be during global destruction */ 239 /* may be during global destruction */
180 if (SvREFCNT (padlist)) 240 if (SvREFCNT (padlist))
181 { 241 {
182 I32 i = AvFILLp (padlist); 242 I32 i = AvFILLp (padlist);
203 AV *padlist; 263 AV *padlist;
204 AV *av = (AV *)mg->mg_obj; 264 AV *av = (AV *)mg->mg_obj;
205 265
206 /* casting is fun. */ 266 /* casting is fun. */
207 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av))) 267 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
208 free_padlist (padlist); 268 free_padlist (aTHX_ padlist);
209 269
210 SvREFCNT_dec (av); 270 SvREFCNT_dec (av);
211 271
212 return 0; 272 return 0;
213} 273}
223 : mg_find ((SV *)cv, PERL_MAGIC_coro) \ 283 : mg_find ((SV *)cv, PERL_MAGIC_coro) \
224 : 0 284 : 0
225 285
226/* the next two functions merely cache the padlists */ 286/* the next two functions merely cache the padlists */
227static void 287static void
228get_padlist (CV *cv) 288get_padlist (pTHX_ CV *cv)
229{ 289{
230 MAGIC *mg = CORO_MAGIC (cv); 290 MAGIC *mg = CORO_MAGIC (cv);
231 AV *av; 291 AV *av;
232 292
233 if (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0) 293 if (mg && AvFILLp ((av = (AV *)mg->mg_obj)) >= 0)
234 CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--]; 294 CvPADLIST (cv) = (AV *)AvARRAY (av)[AvFILLp (av)--];
235 else 295 else
236 { 296 {
237#if 0 297#if CORO_PREFER_PERL_FUNCTIONS
238 /* this is probably cleaner, but also slower? */ 298 /* this is probably cleaner, but also slower? */
239 CV *cp = Perl_cv_clone (cv); 299 CV *cp = Perl_cv_clone (cv);
240 CvPADLIST (cv) = CvPADLIST (cp); 300 CvPADLIST (cv) = CvPADLIST (cp);
241 CvPADLIST (cp) = 0; 301 CvPADLIST (cp) = 0;
242 SvREFCNT_dec (cp); 302 SvREFCNT_dec (cp);
243#else 303#else
244 CvPADLIST (cv) = coro_clone_padlist (cv); 304 CvPADLIST (cv) = coro_clone_padlist (aTHX_ cv);
245#endif 305#endif
246 } 306 }
247} 307}
248 308
249static void 309static void
250put_padlist (CV *cv) 310put_padlist (pTHX_ CV *cv)
251{ 311{
252 MAGIC *mg = CORO_MAGIC (cv); 312 MAGIC *mg = CORO_MAGIC (cv);
253 AV *av; 313 AV *av;
254 314
255 if (!mg) 315 if (!mg)
266 av_extend (av, AvMAX (av) + 1); 326 av_extend (av, AvMAX (av) + 1);
267 327
268 AvARRAY (av)[++AvFILLp (av)] = (SV *)CvPADLIST (cv); 328 AvARRAY (av)[++AvFILLp (av)] = (SV *)CvPADLIST (cv);
269} 329}
270 330
331/** load & save, init *******************************************************/
332
271#define SB do { 333#define SB do {
272#define SE } while (0) 334#define SE } while (0)
273 335
274#define LOAD(state) load_state((state));
275#define SAVE(state,flags) save_state((state),(flags));
276
277#define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); (val) = 0; SE 336#define REPLACE_SV(sv,val) SB SvREFCNT_dec (sv); (sv) = (val); (val) = 0; SE
278 337
279static void 338static void
280load_state(Coro__State c) 339load_perl (pTHX_ Coro__State c)
281{ 340{
282#define VAR(name,type) PL_ ## name = c->name; 341#define VAR(name,type) PL_ ## name = c->name;
283# include "state.h" 342# include "state.h"
284#undef VAR 343#undef VAR
285 344
286 if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav); 345 if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav);
287 if (c->defsv) REPLACE_SV (DEFSV , c->defsv); 346 if (c->defsv) REPLACE_SV (DEFSV , c->defsv);
288 if (c->errsv) REPLACE_SV (ERRSV , c->errsv); 347 if (c->errsv) REPLACE_SV (ERRSV , c->errsv);
348 if (c->deffh) REPLACE_SV (PL_defoutgv , c->deffh);
349
350 if (c->irssv)
351 {
352 if (c->irssv == PL_rs || sv_eq (PL_rs, c->irssv))
353 {
354 SvREFCNT_dec (c->irssv);
355 c->irssv = 0;
356 }
357 else
358 {
359 REPLACE_SV (PL_rs, c->irssv);
360 if (!c->irssv_sv) c->irssv_sv = get_sv ("/", 0);
361 sv_setsv (c->irssv_sv, PL_rs);
362 }
363 }
289 364
290 { 365 {
291 dSP; 366 dSP;
292 CV *cv; 367 CV *cv;
293 368
294 /* now do the ugly restore mess */ 369 /* now do the ugly restore mess */
295 while ((cv = (CV *)POPs)) 370 while ((cv = (CV *)POPs))
296 { 371 {
297 put_padlist (cv); /* mark this padlist as available */ 372 put_padlist (aTHX_ cv); /* mark this padlist as available */
298 CvDEPTH (cv) = PTR2IV (POPs); 373 CvDEPTH (cv) = PTR2IV (POPs);
299 CvPADLIST (cv) = (AV *)POPs; 374 CvPADLIST (cv) = (AV *)POPs;
300 } 375 }
301 376
302 PUTBACK; 377 PUTBACK;
303 } 378 }
379 assert (!PL_comppad || AvARRAY (PL_comppad));//D
304} 380}
305 381
306static void 382static void
307save_state(Coro__State c, int flags) 383save_perl (pTHX_ Coro__State c)
308{ 384{
385 assert (!PL_comppad || AvARRAY (PL_comppad));//D
309 { 386 {
310 dSP; 387 dSP;
311 I32 cxix = cxstack_ix; 388 I32 cxix = cxstack_ix;
312 PERL_CONTEXT *ccstk = cxstack; 389 PERL_CONTEXT *ccstk = cxstack;
313 PERL_SI *top_si = PL_curstackinfo; 390 PERL_SI *top_si = PL_curstackinfo;
315 /* 392 /*
316 * the worst thing you can imagine happens first - we have to save 393 * the worst thing you can imagine happens first - we have to save
317 * (and reinitialize) all cv's in the whole callchain :( 394 * (and reinitialize) all cv's in the whole callchain :(
318 */ 395 */
319 396
397 EXTEND (SP, 3 + 1);
320 PUSHs (Nullsv); 398 PUSHs (Nullsv);
321 /* this loop was inspired by pp_caller */ 399 /* this loop was inspired by pp_caller */
322 for (;;) 400 for (;;)
323 { 401 {
324 while (cxix >= 0) 402 while (cxix >= 0)
325 { 403 {
326 PERL_CONTEXT *cx = &ccstk[cxix--]; 404 PERL_CONTEXT *cx = &ccstk[cxix--];
327 405
328 if (CxTYPE(cx) == CXt_SUB) 406 if (CxTYPE (cx) == CXt_SUB)
329 { 407 {
330 CV *cv = cx->blk_sub.cv; 408 CV *cv = cx->blk_sub.cv;
331 409
332 if (CvDEPTH (cv)) 410 if (CvDEPTH (cv))
333 { 411 {
334 EXTEND (SP, 3); 412 EXTEND (SP, 3);
335
336 PUSHs ((SV *)CvPADLIST(cv)); 413 PUSHs ((SV *)CvPADLIST (cv));
337 PUSHs (INT2PTR (SV *, CvDEPTH (cv))); 414 PUSHs (INT2PTR (SV *, CvDEPTH (cv)));
338 PUSHs ((SV *)cv); 415 PUSHs ((SV *)cv);
339 416
340 CvDEPTH (cv) = 0; 417 CvDEPTH (cv) = 0;
341 get_padlist (cv); 418 get_padlist (aTHX_ cv);
342 } 419 }
343 } 420 }
344#ifdef CXt_FORMAT
345 else if (CxTYPE(cx) == CXt_FORMAT)
346 {
347 /* I never used formats, so how should I know how these are implemented? */
348 /* my bold guess is as a simple, plain sub... */
349 croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats");
350 }
351#endif
352 } 421 }
353 422
354 if (top_si->si_type == PERLSI_MAIN) 423 if (top_si->si_type == PERLSI_MAIN)
355 break; 424 break;
356 425
360 } 429 }
361 430
362 PUTBACK; 431 PUTBACK;
363 } 432 }
364 433
365 c->defav = flags & TRANSFER_SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0; 434 c->defav = c->save & CORO_SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0;
366 c->defsv = flags & TRANSFER_SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0; 435 c->defsv = c->save & CORO_SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0;
367 c->errsv = flags & TRANSFER_SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0; 436 c->errsv = c->save & CORO_SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0;
437 c->deffh = c->save & CORO_SAVE_DEFFH ? (GV *)SvREFCNT_inc (PL_defoutgv) : 0;
438 c->irssv = c->save & CORO_SAVE_IRSSV ? SvREFCNT_inc (PL_rs) : 0;
368 439
369#define VAR(name,type)c->name = PL_ ## name; 440#define VAR(name,type)c->name = PL_ ## name;
370# include "state.h" 441# include "state.h"
371#undef VAR 442#undef VAR
372} 443}
375 * allocate various perl stacks. This is an exact copy 446 * allocate various perl stacks. This is an exact copy
376 * of perl.c:init_stacks, except that it uses less memory 447 * of perl.c:init_stacks, except that it uses less memory
377 * on the (sometimes correct) assumption that coroutines do 448 * on the (sometimes correct) assumption that coroutines do
378 * not usually need a lot of stackspace. 449 * not usually need a lot of stackspace.
379 */ 450 */
451#if CORO_PREFER_PERL_FUNCTIONS
452# define coro_init_stacks init_stacks
453#else
380static void 454static void
381coro_init_stacks () 455coro_init_stacks (pTHX)
382{ 456{
383 PL_curstackinfo = new_stackinfo(96, 1024/sizeof(PERL_CONTEXT) - 1); 457 PL_curstackinfo = new_stackinfo(128, 1024/sizeof(PERL_CONTEXT));
384 PL_curstackinfo->si_type = PERLSI_MAIN; 458 PL_curstackinfo->si_type = PERLSI_MAIN;
385 PL_curstack = PL_curstackinfo->si_stack; 459 PL_curstack = PL_curstackinfo->si_stack;
386 PL_mainstack = PL_curstack; /* remember in case we switch stacks */ 460 PL_mainstack = PL_curstack; /* remember in case we switch stacks */
387 461
388 PL_stack_base = AvARRAY(PL_curstack); 462 PL_stack_base = AvARRAY(PL_curstack);
389 PL_stack_sp = PL_stack_base; 463 PL_stack_sp = PL_stack_base;
390 PL_stack_max = PL_stack_base + AvMAX(PL_curstack); 464 PL_stack_max = PL_stack_base + AvMAX(PL_curstack);
391 465
392 New(50,PL_tmps_stack,96,SV*); 466 New(50,PL_tmps_stack,128,SV*);
393 PL_tmps_floor = -1; 467 PL_tmps_floor = -1;
394 PL_tmps_ix = -1; 468 PL_tmps_ix = -1;
395 PL_tmps_max = 96; 469 PL_tmps_max = 128;
396 470
397 New(54,PL_markstack,16,I32); 471 New(54,PL_markstack,32,I32);
398 PL_markstack_ptr = PL_markstack; 472 PL_markstack_ptr = PL_markstack;
399 PL_markstack_max = PL_markstack + 16; 473 PL_markstack_max = PL_markstack + 32;
400 474
401#ifdef SET_MARK_OFFSET 475#ifdef SET_MARK_OFFSET
402 SET_MARK_OFFSET; 476 SET_MARK_OFFSET;
403#endif 477#endif
404 478
405 New(54,PL_scopestack,16,I32); 479 New(54,PL_scopestack,32,I32);
406 PL_scopestack_ix = 0; 480 PL_scopestack_ix = 0;
407 PL_scopestack_max = 16; 481 PL_scopestack_max = 32;
408 482
409 New(54,PL_savestack,96,ANY); 483 New(54,PL_savestack,64,ANY);
410 PL_savestack_ix = 0; 484 PL_savestack_ix = 0;
411 PL_savestack_max = 96; 485 PL_savestack_max = 64;
412 486
413#if !PERL_VERSION_ATLEAST (5,9,0) 487#if !PERL_VERSION_ATLEAST (5,9,0)
414 New(54,PL_retstack,8,OP*); 488 New(54,PL_retstack,16,OP*);
415 PL_retstack_ix = 0; 489 PL_retstack_ix = 0;
416 PL_retstack_max = 8; 490 PL_retstack_max = 16;
417#endif 491#endif
418} 492}
493#endif
419 494
420/* 495/*
421 * destroy the stacks, the callchain etc... 496 * destroy the stacks, the callchain etc...
422 */ 497 */
423static void 498static void
424coro_destroy_stacks () 499coro_destroy_stacks (pTHX)
425{ 500{
426 if (!IN_DESTRUCT) 501 if (!IN_DESTRUCT)
427 { 502 {
428 /* is this ugly, I ask? */ 503 /* restore all saved variables and stuff */
429 LEAVE_SCOPE (0); 504 LEAVE_SCOPE (0);
505 assert (PL_tmps_floor == -1);
430 506
431 /* sure it is, but more important: is it correct?? :/ */ 507 /* free all temporaries */
432 FREETMPS; 508 FREETMPS;
509 assert (PL_tmps_ix == -1);
433 510
511 /* unwind all extra stacks */
434 /*POPSTACK_TO (PL_mainstack);*//*D*//*use*/ 512 POPSTACK_TO (PL_mainstack);
513
514 /* unwind main stack */
515 dounwind (-1);
435 } 516 }
436 517
437 while (PL_curstackinfo->si_next) 518 while (PL_curstackinfo->si_next)
438 PL_curstackinfo = PL_curstackinfo->si_next; 519 PL_curstackinfo = PL_curstackinfo->si_next;
439 520
440 while (PL_curstackinfo) 521 while (PL_curstackinfo)
441 { 522 {
442 PERL_SI *p = PL_curstackinfo->si_prev; 523 PERL_SI *p = PL_curstackinfo->si_prev;
443 524
444 { /*D*//*remove*/
445 dSP;
446 SWITCHSTACK (PL_curstack, PL_curstackinfo->si_stack);
447 PUTBACK; /* possibly superfluous */
448 }
449
450 if (!IN_DESTRUCT) 525 if (!IN_DESTRUCT)
451 {
452 dounwind (-1);/*D*//*remove*/
453 SvREFCNT_dec (PL_curstackinfo->si_stack); 526 SvREFCNT_dec (PL_curstackinfo->si_stack);
454 }
455 527
456 Safefree (PL_curstackinfo->si_cxstack); 528 Safefree (PL_curstackinfo->si_cxstack);
457 Safefree (PL_curstackinfo); 529 Safefree (PL_curstackinfo);
458 PL_curstackinfo = p; 530 PL_curstackinfo = p;
459 } 531 }
465#if !PERL_VERSION_ATLEAST (5,9,0) 537#if !PERL_VERSION_ATLEAST (5,9,0)
466 Safefree (PL_retstack); 538 Safefree (PL_retstack);
467#endif 539#endif
468} 540}
469 541
542/** coroutine stack handling ************************************************/
543
470static void 544static void
471setup_coro (struct coro *coro) 545setup_coro (pTHX_ struct coro *coro)
472{ 546{
473 /* 547 /*
474 * emulate part of the perl startup here. 548 * emulate part of the perl startup here.
475 */ 549 */
476
477 coro_init_stacks (); 550 coro_init_stacks (aTHX);
478 551
552 PL_curcop = &PL_compiling;
553 PL_in_eval = EVAL_NULL;
479 PL_curcop = 0; 554 PL_comppad = 0;
480 PL_in_eval = 0;
481 PL_curpm = 0; 555 PL_curpm = 0;
556 PL_localizing = 0;
557 PL_dirty = 0;
558 PL_restartop = 0;
482 559
483 { 560 {
484 dSP; 561 dSP;
485 LOGOP myop; 562 LOGOP myop;
486 563
487 /* I have no idea why this is needed, but it is */
488 PUSHMARK (SP);
489
490 SvREFCNT_dec (GvAV (PL_defgv)); 564 SvREFCNT_dec (GvAV (PL_defgv));
491 GvAV (PL_defgv) = coro->args; coro->args = 0; 565 GvAV (PL_defgv) = coro->args; coro->args = 0;
492 566
493 Zero (&myop, 1, LOGOP); 567 Zero (&myop, 1, LOGOP);
494 myop.op_next = Nullop; 568 myop.op_next = Nullop;
495 myop.op_flags = OPf_WANT_VOID; 569 myop.op_flags = OPf_WANT_VOID;
496 570
571 PUSHMARK (SP);
572 XPUSHs (av_shift (GvAV (PL_defgv)));
573 PUTBACK;
497 PL_op = (OP *)&myop; 574 PL_op = (OP *)&myop;
498
499 PUSHMARK (SP);
500 XPUSHs ((SV *)get_cv ("Coro::State::_coro_init", FALSE));
501 PUTBACK;
502 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX); 575 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
503 SPAGAIN; 576 SPAGAIN;
504
505 ENTER; /* necessary e.g. for dounwind */
506 } 577 }
507}
508 578
579 ENTER; /* necessary e.g. for dounwind */
580}
581
509static void 582static void
510free_coro_mortal () 583free_coro_mortal (pTHX)
511{ 584{
512 if (coro_mortal) 585 if (coro_mortal)
513 { 586 {
514 SvREFCNT_dec (coro_mortal); 587 SvREFCNT_dec (coro_mortal);
515 coro_mortal = 0; 588 coro_mortal = 0;
516 } 589 }
517} 590}
518 591
592/* inject a fake call to Coro::State::_cctx_init into the execution */
593/* _cctx_init shoukld be careful, as it could be called at almost any time */
594/* during execution of a pelr program */
519static void NOINLINE 595static void NOINLINE
520prepare_cctx (coro_cctx *cctx) 596prepare_cctx (pTHX_ coro_cctx *cctx)
521{ 597{
522 dSP; 598 dSP;
523 LOGOP myop; 599 LOGOP myop;
524 600
525 Zero (&myop, 1, LOGOP); 601 Zero (&myop, 1, LOGOP);
526 myop.op_next = PL_op; 602 myop.op_next = PL_op;
527 myop.op_flags = OPf_WANT_VOID; 603 myop.op_flags = OPf_WANT_VOID | OPf_STACKED;
528
529 sv_setiv (get_sv ("Coro::State::_cctx", FALSE), PTR2IV (cctx));
530 604
531 PUSHMARK (SP); 605 PUSHMARK (SP);
606 EXTEND (SP, 2);
607 PUSHs (sv_2mortal (newSViv (PTR2IV (cctx))));
532 XPUSHs ((SV *)get_cv ("Coro::State::_cctx_init", FALSE)); 608 PUSHs ((SV *)get_cv ("Coro::State::_cctx_init", FALSE));
533 PUTBACK; 609 PUTBACK;
610 PL_op = (OP *)&myop;
534 PL_restartop = PL_ppaddr[OP_ENTERSUB](aTHX); 611 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
535 SPAGAIN; 612 SPAGAIN;
536} 613}
537 614
615/*
616 * this is a _very_ stripped down perl interpreter ;)
617 */
538static void 618static void
539coro_run (void *arg) 619coro_run (void *arg)
540{ 620{
621 dTHX;
622
541 /* coro_run is the alternative epilogue of transfer() */ 623 /* coro_run is the alternative tail of transfer(), so unlock here. */
542 UNLOCK; 624 UNLOCK;
543 625
626 PL_top_env = &PL_start_env;
627
628 /* inject a fake subroutine call to cctx_init */
629 prepare_cctx (aTHX_ (coro_cctx *)arg);
630
631 /* somebody or something will hit me for both perl_run and PL_restartop */
632 PL_restartop = PL_op;
633 perl_run (PL_curinterp);
634
544 /* 635 /*
545 * this is a _very_ stripped down perl interpreter ;) 636 * If perl-run returns we assume exit() was being called or the coro
637 * fell off the end, which seems to be the only valid (non-bug)
638 * reason for perl_run to return. We try to exit by jumping to the
639 * bootstrap-time "top" top_env, as we cannot restore the "main"
640 * coroutine as Coro has no such concept
546 */ 641 */
547 PL_top_env = &PL_start_env; 642 PL_top_env = main_top_env;
548 643 JMPENV_JUMP (2); /* I do not feel well about the hardcoded 2 at all */
549 /* inject call to cctx_init */
550 prepare_cctx ((coro_cctx *)arg);
551
552 /* somebody will hit me for both perl_run and PL_restartop */
553 perl_run (PL_curinterp);
554
555 fputs ("FATAL: C coroutine fell over the edge of the world, aborting. Did you call exit in a coroutine?\n", stderr);
556 abort ();
557} 644}
558 645
559static coro_cctx * 646static coro_cctx *
560cctx_new () 647cctx_new ()
561{ 648{
562 coro_cctx *cctx; 649 coro_cctx *cctx;
650 void *stack_start;
651 size_t stack_size;
563 652
564 ++cctx_count; 653 ++cctx_count;
565 654
566 New (0, cctx, 1, coro_cctx); 655 Newz (0, cctx, 1, coro_cctx);
567 656
568#if HAVE_MMAP 657#if HAVE_MMAP
569 658
570 cctx->ssize = ((STACKSIZE * sizeof (long) + PAGESIZE - 1) / PAGESIZE + STACKGUARD) * PAGESIZE; 659 cctx->ssize = ((coro_stacksize * sizeof (long) + PAGESIZE - 1) / PAGESIZE + CORO_STACKGUARD) * PAGESIZE;
571 /* mmap suppsedly does allocate-on-write for us */ 660 /* mmap supposedly does allocate-on-write for us */
572 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 661 cctx->sptr = mmap (0, cctx->ssize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
573 662
574 if (cctx->sptr == (void *)-1) 663 if (cctx->sptr != (void *)-1)
575 {
576 perror ("FATAL: unable to mmap stack for coroutine");
577 _exit (EXIT_FAILURE);
578 } 664 {
579
580# if STACKGUARD 665# if CORO_STACKGUARD
581 mprotect (cctx->sptr, STACKGUARD * PAGESIZE, PROT_NONE); 666 mprotect (cctx->sptr, CORO_STACKGUARD * PAGESIZE, PROT_NONE);
582# endif 667# endif
668 stack_start = CORO_STACKGUARD * PAGESIZE + (char *)cctx->sptr;
669 stack_size = cctx->ssize - CORO_STACKGUARD * PAGESIZE;
670 cctx->mapped = 1;
671 }
672 else
673#endif
674 {
675 cctx->ssize = coro_stacksize * (long)sizeof (long);
676 New (0, cctx->sptr, coro_stacksize, long);
583 677
584#else
585
586 cctx->ssize = STACKSIZE * (long)sizeof (long);
587 New (0, cctx->sptr, STACKSIZE, long);
588
589 if (!cctx->sptr) 678 if (!cctx->sptr)
590 { 679 {
591 perror ("FATAL: unable to malloc stack for coroutine"); 680 perror ("FATAL: unable to allocate stack for coroutine");
592 _exit (EXIT_FAILURE); 681 _exit (EXIT_FAILURE);
593 } 682 }
594 683
595#endif 684 stack_start = cctx->sptr;
685 stack_size = cctx->ssize;
686 }
596 687
597#if USE_VALGRIND 688 REGISTER_STACK (cctx, (char *)stack_start, (char *)stack_start + stack_size);
598 cctx->valgrind_id = VALGRIND_STACK_REGISTER (
599 STACKGUARD * PAGESIZE + (char *)cctx->sptr,
600 cctx->ssize + (char *)cctx->sptr
601 );
602#endif
603
604 coro_create (&cctx->cctx, coro_run, (void *)cctx, cctx->sptr, cctx->ssize); 689 coro_create (&cctx->cctx, coro_run, (void *)cctx, stack_start, stack_size);
605 690
606 return cctx; 691 return cctx;
607} 692}
608 693
609static void 694static void
610cctx_free (coro_cctx *cctx) 695cctx_destroy (coro_cctx *cctx)
611{ 696{
612 if (!cctx) 697 if (!cctx)
613 return; 698 return;
614 699
615 --cctx_count; 700 --cctx_count;
616 701
617#if USE_VALGRIND 702#if CORO_USE_VALGRIND
618 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id); 703 VALGRIND_STACK_DEREGISTER (cctx->valgrind_id);
619#endif 704#endif
620 705
621#if HAVE_MMAP 706#if HAVE_MMAP
707 if (cctx->mapped)
622 munmap (cctx->sptr, cctx->ssize); 708 munmap (cctx->sptr, cctx->ssize);
623#else 709 else
710#endif
624 Safefree (cctx->sptr); 711 Safefree (cctx->sptr);
625#endif
626 712
627 Safefree (cctx); 713 Safefree (cctx);
628} 714}
629 715
630static coro_cctx * 716static coro_cctx *
631cctx_get () 717cctx_get (pTHX)
632{ 718{
633 coro_cctx *cctx;
634
635 if (cctx_first) 719 while (cctx_first)
636 { 720 {
721 coro_cctx *cctx = cctx_first;
722 cctx_first = cctx->next;
637 --cctx_idle; 723 --cctx_idle;
638 cctx = cctx_first; 724
639 cctx_first = cctx->next; 725 if (cctx->ssize >= coro_stacksize)
726 return cctx;
727
728 cctx_destroy (cctx);
640 } 729 }
641 else 730
642 {
643 cctx = cctx_new ();
644 PL_op = PL_op->op_next; 731 PL_op = PL_op->op_next;
645 }
646
647 return cctx; 732 return cctx_new ();
648} 733}
649 734
650static void 735static void
651cctx_put (coro_cctx *cctx) 736cctx_put (coro_cctx *cctx)
652{ 737{
738 /* free another cctx if overlimit */
739 if (cctx_idle >= MAX_IDLE_CCTX)
740 {
741 coro_cctx *first = cctx_first;
742 cctx_first = first->next;
743 --cctx_idle;
744
745 assert (!first->inuse);
746 cctx_destroy (first);
747 }
748
653 ++cctx_idle; 749 ++cctx_idle;
654 cctx->next = cctx_first; 750 cctx->next = cctx_first;
655 cctx_first = cctx; 751 cctx_first = cctx;
656} 752}
657 753
754/** coroutine switching *****************************************************/
755
658/* never call directly, always through the coro_state_transfer global variable */ 756/* never call directly, always through the coro_state_transfer global variable */
659static void NOINLINE 757static void NOINLINE
660transfer (struct coro *prev, struct coro *next, int flags) 758transfer (pTHX_ struct coro *prev, struct coro *next)
661{ 759{
662 dSTACKLEVEL; 760 dSTACKLEVEL;
663 761
664 /* sometimes transfer is only called to set idle_sp */ 762 /* sometimes transfer is only called to set idle_sp */
665 if (flags == TRANSFER_SET_STACKLEVEL) 763 if (!next)
764 {
666 ((coro_cctx *)prev)->idle_sp = STACKLEVEL; 765 ((coro_cctx *)prev)->idle_sp = STACKLEVEL;
766 assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */
767 }
667 else if (prev != next) 768 else if (prev != next)
668 { 769 {
669 coro_cctx *prev__cctx; 770 coro_cctx *prev__cctx;
670 771
772 if (prev->flags & CF_NEW)
773 {
774 /* create a new empty context */
775 Newz (0, prev->cctx, 1, coro_cctx);
776 prev->cctx->inuse = 1;
777 prev->flags &= ~CF_NEW;
778 prev->flags |= CF_RUNNING;
779 }
780
781 /*TODO: must not croak here */
782 if (!prev->flags & CF_RUNNING)
783 croak ("Coro::State::transfer called with non-running prev Coro::State, but can only transfer from running states");
784
785 if (next->flags & CF_RUNNING)
786 croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states");
787
788 if (next->flags & CF_DESTROYED)
789 croak ("Coro::State::transfer called with destroyed next Coro::State, but can only transfer to inactive states");
790
791 prev->flags &= ~CF_RUNNING;
792 next->flags |= CF_RUNNING;
793
671 LOCK; 794 LOCK;
672 795
673 if (next->mainstack) 796 if (next->flags & CF_NEW)
674 { 797 {
675 /* coroutine already started */ 798 /* need to start coroutine */
676 SAVE (prev, flags); 799 next->flags &= ~CF_NEW;
677 LOAD (next); 800 /* first get rid of the old state */
801 save_perl (aTHX_ prev);
802 /* setup coroutine call */
803 setup_coro (aTHX_ next);
804 /* need a new stack */
805 assert (!next->cctx);
678 } 806 }
679 else 807 else
680 { 808 {
681 /* need to start coroutine */ 809 /* coroutine already started */
682 /* first get rid of the old state */ 810 save_perl (aTHX_ prev);
683 SAVE (prev, -1); 811 load_perl (aTHX_ next);
684 /* setup coroutine call */
685 setup_coro (next);
686 /* need a stack */
687 next->cctx = 0;
688 } 812 }
689
690 if (!prev->cctx)
691 /* create a new empty context */
692 Newz (0, prev->cctx, 1, coro_cctx);
693 813
694 prev__cctx = prev->cctx; 814 prev__cctx = prev->cctx;
695 815
696 /* possibly "free" the cctx */ 816 /* possibly "free" the cctx */
697 if (prev__cctx->idle_sp == STACKLEVEL) 817 if (prev__cctx->idle_sp == STACKLEVEL)
698 { 818 {
699 assert (PL_top_env == prev__cctx->top_env);//D 819 /* I assume that STACKLEVEL is a stronger indicator than PL_top_env changes */
820 assert (("ERROR: current top_env must equal previous top_env", PL_top_env == prev__cctx->idle_te));
821
822 prev->cctx = 0;
823
700 cctx_put (prev__cctx); 824 cctx_put (prev__cctx);
701 prev->cctx = 0; 825 prev__cctx->inuse = 0;
702 } 826 }
703 827
704 if (!next->cctx) 828 if (!next->cctx)
829 {
705 next->cctx = cctx_get (); 830 next->cctx = cctx_get (aTHX);
831 assert (!next->cctx->inuse);
832 next->cctx->inuse = 1;
833 }
706 834
707 if (prev__cctx != next->cctx) 835 if (prev__cctx != next->cctx)
708 { 836 {
709 prev__cctx->top_env = PL_top_env; 837 prev__cctx->top_env = PL_top_env;
710 PL_top_env = next->cctx->top_env; 838 PL_top_env = next->cctx->top_env;
711 coro_transfer (&prev__cctx->cctx, &next->cctx->cctx); 839 coro_transfer (&prev__cctx->cctx, &next->cctx->cctx);
712 } 840 }
713 841
714 free_coro_mortal (); 842 free_coro_mortal (aTHX);
715
716 UNLOCK; 843 UNLOCK;
717 } 844 }
718} 845}
719 846
720struct transfer_args 847struct transfer_args
721{ 848{
722 struct coro *prev, *next; 849 struct coro *prev, *next;
723 int flags;
724}; 850};
725 851
726#define TRANSFER(ta) transfer ((ta).prev, (ta).next, (ta).flags) 852#define TRANSFER(ta) transfer (aTHX_ (ta).prev, (ta).next)
727 853
854/** high level stuff ********************************************************/
855
728static void 856static int
729coro_state_destroy (struct coro *coro) 857coro_state_destroy (pTHX_ struct coro *coro)
730{ 858{
731 if (coro->refcnt--) 859 if (coro->flags & CF_DESTROYED)
732 return; 860 return 0;
861
862 coro->flags |= CF_DESTROYED;
863
864 if (coro->flags & CF_READY)
865 {
866 /* reduce nready, as destroying a ready coro effectively unreadies it */
867 /* alternative: look through all ready queues and remove the coro */
868 LOCK;
869 --coro_nready;
870 UNLOCK;
871 }
872 else
873 coro->flags |= CF_READY; /* make sure it is NOT put into the readyqueue */
733 874
734 if (coro->mainstack && coro->mainstack != main_mainstack) 875 if (coro->mainstack && coro->mainstack != main_mainstack)
735 { 876 {
736 struct coro temp; 877 struct coro temp;
737 878
738 SAVE ((&temp), TRANSFER_SAVE_ALL); 879 assert (!(coro->flags & CF_RUNNING));
739 LOAD (coro);
740 880
881 Zero (&temp, 1, struct coro);
882 temp.save = CORO_SAVE_DEF;
883
884 if (coro->flags & CF_RUNNING)
885 croak ("FATAL: tried to destroy currently running coroutine");
886
887 save_perl (aTHX_ &temp);
888 load_perl (aTHX_ coro);
889
741 coro_destroy_stacks (); 890 coro_destroy_stacks (aTHX);
742 891
743 LOAD ((&temp)); /* this will get rid of defsv etc.. */ 892 load_perl (aTHX_ &temp); /* this will get rid of defsv etc.. */
744 893
745 coro->mainstack = 0; 894 coro->mainstack = 0;
746 } 895 }
747 896
748 cctx_free (coro->cctx); 897 cctx_destroy (coro->cctx);
749 SvREFCNT_dec (coro->args); 898 SvREFCNT_dec (coro->args);
750 Safefree (coro); 899
900 return 1;
751} 901}
752 902
753static int 903static int
754coro_state_clear (pTHX_ SV *sv, MAGIC *mg) 904coro_state_free (pTHX_ SV *sv, MAGIC *mg)
755{ 905{
756 struct coro *coro = (struct coro *)mg->mg_ptr; 906 struct coro *coro = (struct coro *)mg->mg_ptr;
757 mg->mg_ptr = 0; 907 mg->mg_ptr = 0;
758 908
909 if (--coro->refcnt < 0)
910 {
759 coro_state_destroy (coro); 911 coro_state_destroy (aTHX_ coro);
912 Safefree (coro);
913 }
760 914
761 return 0; 915 return 0;
762} 916}
763 917
764static int 918static int
771 return 0; 925 return 0;
772} 926}
773 927
774static MGVTBL coro_state_vtbl = { 928static MGVTBL coro_state_vtbl = {
775 0, 0, 0, 0, 929 0, 0, 0, 0,
776 coro_state_clear, 930 coro_state_free,
777 0, 931 0,
778#ifdef MGf_DUP 932#ifdef MGf_DUP
779 coro_state_dup, 933 coro_state_dup,
780#else 934#else
781# define MGf_DUP 0 935# define MGf_DUP 0
782#endif 936#endif
783}; 937};
784 938
785static struct coro * 939static struct coro *
786SvSTATE (SV *coro) 940SvSTATE_ (pTHX_ SV *coro)
787{ 941{
788 HV *stash; 942 HV *stash;
789 MAGIC *mg; 943 MAGIC *mg;
790 944
791 if (SvROK (coro)) 945 if (SvROK (coro))
797 /* very slow, but rare, check */ 951 /* very slow, but rare, check */
798 if (!sv_derived_from (sv_2mortal (newRV_inc (coro)), "Coro::State")) 952 if (!sv_derived_from (sv_2mortal (newRV_inc (coro)), "Coro::State"))
799 croak ("Coro::State object required"); 953 croak ("Coro::State object required");
800 } 954 }
801 955
802 mg = SvMAGIC (coro); 956 mg = CORO_MAGIC (coro);
803 assert (mg->mg_type == PERL_MAGIC_ext);
804 return (struct coro *)mg->mg_ptr; 957 return (struct coro *)mg->mg_ptr;
805} 958}
806 959
960#define SvSTATE(sv) SvSTATE_ (aTHX_ (sv))
961
807static void 962static void
808prepare_transfer (struct transfer_args *ta, SV *prev, SV *next, int flags) 963prepare_transfer (pTHX_ struct transfer_args *ta, SV *prev_sv, SV *next_sv)
809{ 964{
810 ta->prev = SvSTATE (prev); 965 ta->prev = SvSTATE (prev_sv);
811 ta->next = SvSTATE (next); 966 ta->next = SvSTATE (next_sv);
812 ta->flags = flags;
813} 967}
814 968
815static void 969static void
816api_transfer (SV *prev, SV *next, int flags) 970api_transfer (SV *prev_sv, SV *next_sv)
817{ 971{
818 dTHX; 972 dTHX;
819 struct transfer_args ta; 973 struct transfer_args ta;
820 974
821 prepare_transfer (&ta, prev, next, flags); 975 prepare_transfer (aTHX_ &ta, prev_sv, next_sv);
822 TRANSFER (ta); 976 TRANSFER (ta);
823} 977}
824 978
979static int
980api_save (SV *coro_sv, int new_save)
981{
982 dTHX;
983 struct coro *coro = SvSTATE (coro_sv);
984 int old_save = coro->save;
985
986 if (new_save >= 0)
987 coro->save = new_save;
988
989 return old_save;
990}
991
825/** Coro ********************************************************************/ 992/** Coro ********************************************************************/
826 993
827#define PRIO_MAX 3
828#define PRIO_HIGH 1
829#define PRIO_NORMAL 0
830#define PRIO_LOW -1
831#define PRIO_IDLE -3
832#define PRIO_MIN -4
833
834/* for Coro.pm */
835static GV *coro_current, *coro_idle;
836static AV *coro_ready [PRIO_MAX-PRIO_MIN+1];
837static int coro_nready;
838
839static void 994static void
840coro_enq (SV *sv) 995coro_enq (pTHX_ SV *coro_sv)
841{ 996{
842 int prio;
843
844 if (SvTYPE (sv) != SVt_PVHV)
845 croak ("Coro::ready tried to enqueue something that is not a coroutine");
846
847 prio = SvSTATE (sv)->prio;
848
849 av_push (coro_ready [prio - PRIO_MIN], sv); 997 av_push (coro_ready [SvSTATE (coro_sv)->prio - PRIO_MIN], coro_sv);
850 coro_nready++;
851} 998}
852 999
853static SV * 1000static SV *
854coro_deq (int min_prio) 1001coro_deq (pTHX_ int min_prio)
855{ 1002{
856 int prio = PRIO_MAX - PRIO_MIN; 1003 int prio = PRIO_MAX - PRIO_MIN;
857 1004
858 min_prio -= PRIO_MIN; 1005 min_prio -= PRIO_MIN;
859 if (min_prio < 0) 1006 if (min_prio < 0)
860 min_prio = 0; 1007 min_prio = 0;
861 1008
862 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; ) 1009 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; )
863 if (AvFILLp (coro_ready [prio]) >= 0) 1010 if (AvFILLp (coro_ready [prio]) >= 0)
864 {
865 coro_nready--;
866 return av_shift (coro_ready [prio]); 1011 return av_shift (coro_ready [prio]);
867 }
868 1012
869 return 0; 1013 return 0;
870} 1014}
871 1015
872static void 1016static int
873api_ready (SV *coro) 1017api_ready (SV *coro_sv)
874{ 1018{
875 dTHX; 1019 dTHX;
1020 struct coro *coro;
876 1021
877 if (SvROK (coro)) 1022 if (SvROK (coro_sv))
878 coro = SvRV (coro); 1023 coro_sv = SvRV (coro_sv);
1024
1025 coro = SvSTATE (coro_sv);
1026
1027 if (coro->flags & CF_READY)
1028 return 0;
1029
1030 coro->flags |= CF_READY;
879 1031
880 LOCK; 1032 LOCK;
881 coro_enq (SvREFCNT_inc (coro)); 1033 coro_enq (aTHX_ SvREFCNT_inc (coro_sv));
1034 ++coro_nready;
882 UNLOCK; 1035 UNLOCK;
883}
884 1036
1037 return 1;
1038}
1039
885static void 1040static int
1041api_is_ready (SV *coro_sv)
1042{
1043 dTHX;
1044 return !!(SvSTATE (coro_sv)->flags & CF_READY);
1045}
1046
1047static void
886prepare_schedule (struct transfer_args *ta) 1048prepare_schedule (pTHX_ struct transfer_args *ta)
887{ 1049{
888 SV *current, *prev, *next; 1050 SV *prev_sv, *next_sv;
889
890 current = GvSV (coro_current);
891 1051
892 for (;;) 1052 for (;;)
893 { 1053 {
894 LOCK; 1054 LOCK;
895 next = coro_deq (PRIO_MIN); 1055 next_sv = coro_deq (aTHX_ PRIO_MIN);
1056
1057 /* nothing to schedule: call the idle handler */
1058 if (!next_sv)
1059 {
1060 dSP;
1061 UNLOCK;
1062
1063 ENTER;
1064 SAVETMPS;
1065
1066 PUSHMARK (SP);
1067 PUTBACK;
1068 call_sv (get_sv ("Coro::idle", FALSE), G_DISCARD);
1069
1070 FREETMPS;
1071 LEAVE;
1072 continue;
1073 }
1074
1075 ta->next = SvSTATE (next_sv);
1076
1077 /* cannot transfer to destroyed coros, skip and look for next */
1078 if (ta->next->flags & CF_DESTROYED)
1079 {
1080 UNLOCK;
1081 SvREFCNT_dec (next_sv);
1082 /* coro_nready is already taken care of by destroy */
1083 continue;
1084 }
1085
1086 --coro_nready;
896 UNLOCK; 1087 UNLOCK;
897
898 if (next)
899 break; 1088 break;
900
901 {
902 dSP;
903
904 ENTER;
905 SAVETMPS;
906
907 PUSHMARK (SP);
908 PUTBACK;
909 call_sv (GvSV (coro_idle), G_DISCARD);
910
911 FREETMPS;
912 LEAVE;
913 } 1089 }
914 }
915
916 prev = SvRV (current);
917 SvRV (current) = next;
918 1090
919 /* free this only after the transfer */ 1091 /* free this only after the transfer */
1092 prev_sv = SvRV (coro_current);
1093 SvRV_set (coro_current, next_sv);
1094 ta->prev = SvSTATE (prev_sv);
1095
1096 assert (ta->next->flags & CF_READY);
1097 ta->next->flags &= ~CF_READY;
1098
920 LOCK; 1099 LOCK;
921 free_coro_mortal (); 1100 free_coro_mortal (aTHX);
1101 coro_mortal = prev_sv;
922 UNLOCK; 1102 UNLOCK;
923 coro_mortal = prev;
924
925 ta->prev = SvSTATE (prev);
926 ta->next = SvSTATE (next);
927 ta->flags = TRANSFER_SAVE_ALL;
928} 1103}
929 1104
930static void 1105static void
931prepare_cede (struct transfer_args *ta) 1106prepare_cede (pTHX_ struct transfer_args *ta)
932{ 1107{
933 LOCK; 1108 api_ready (coro_current);
934 coro_enq (SvREFCNT_inc (SvRV (GvSV (coro_current))));
935 UNLOCK;
936
937 prepare_schedule (ta); 1109 prepare_schedule (aTHX_ ta);
1110}
1111
1112static int
1113prepare_cede_notself (pTHX_ struct transfer_args *ta)
1114{
1115 if (coro_nready)
1116 {
1117 SV *prev = SvRV (coro_current);
1118 prepare_schedule (aTHX_ ta);
1119 api_ready (prev);
1120 return 1;
1121 }
1122 else
1123 return 0;
938} 1124}
939 1125
940static void 1126static void
941api_schedule (void) 1127api_schedule (void)
942{ 1128{
943 dTHX; 1129 dTHX;
944 struct transfer_args ta; 1130 struct transfer_args ta;
945 1131
946 prepare_schedule (&ta); 1132 prepare_schedule (aTHX_ &ta);
947 TRANSFER (ta); 1133 TRANSFER (ta);
948} 1134}
949 1135
950static void 1136static int
951api_cede (void) 1137api_cede (void)
952{ 1138{
953 dTHX; 1139 dTHX;
954 struct transfer_args ta; 1140 struct transfer_args ta;
955 1141
956 prepare_cede (&ta); 1142 prepare_cede (aTHX_ &ta);
1143
1144 if (ta.prev != ta.next)
1145 {
957 TRANSFER (ta); 1146 TRANSFER (ta);
1147 return 1;
1148 }
1149 else
1150 return 0;
1151}
1152
1153static int
1154api_cede_notself (void)
1155{
1156 dTHX;
1157 struct transfer_args ta;
1158
1159 if (prepare_cede_notself (aTHX_ &ta))
1160 {
1161 TRANSFER (ta);
1162 return 1;
1163 }
1164 else
1165 return 0;
958} 1166}
959 1167
960MODULE = Coro::State PACKAGE = Coro::State 1168MODULE = Coro::State PACKAGE = Coro::State
961 1169
962PROTOTYPES: DISABLE 1170PROTOTYPES: DISABLE
968#endif 1176#endif
969 BOOT_PAGESIZE; 1177 BOOT_PAGESIZE;
970 1178
971 coro_state_stash = gv_stashpv ("Coro::State", TRUE); 1179 coro_state_stash = gv_stashpv ("Coro::State", TRUE);
972 1180
973 newCONSTSUB (coro_state_stash, "SAVE_DEFAV", newSViv (TRANSFER_SAVE_DEFAV)); 1181 newCONSTSUB (coro_state_stash, "SAVE_DEFAV", newSViv (CORO_SAVE_DEFAV));
974 newCONSTSUB (coro_state_stash, "SAVE_DEFSV", newSViv (TRANSFER_SAVE_DEFSV)); 1182 newCONSTSUB (coro_state_stash, "SAVE_DEFSV", newSViv (CORO_SAVE_DEFSV));
975 newCONSTSUB (coro_state_stash, "SAVE_ERRSV", newSViv (TRANSFER_SAVE_ERRSV)); 1183 newCONSTSUB (coro_state_stash, "SAVE_ERRSV", newSViv (CORO_SAVE_ERRSV));
1184 newCONSTSUB (coro_state_stash, "SAVE_IRSSV", newSViv (CORO_SAVE_IRSSV));
1185 newCONSTSUB (coro_state_stash, "SAVE_DEFFH", newSViv (CORO_SAVE_DEFFH));
1186 newCONSTSUB (coro_state_stash, "SAVE_DEF", newSViv (CORO_SAVE_DEF));
1187 newCONSTSUB (coro_state_stash, "SAVE_ALL", newSViv (CORO_SAVE_ALL));
976 1188
977 main_mainstack = PL_mainstack; 1189 main_mainstack = PL_mainstack;
1190 main_top_env = PL_top_env;
1191
1192 while (main_top_env->je_prev)
1193 main_top_env = main_top_env->je_prev;
978 1194
979 coroapi.ver = CORO_API_VERSION; 1195 coroapi.ver = CORO_API_VERSION;
980 coroapi.transfer = api_transfer; 1196 coroapi.transfer = api_transfer;
981 1197
982 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL)); 1198 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL));
990 HV *hv; 1206 HV *hv;
991 int i; 1207 int i;
992 1208
993 Newz (0, coro, 1, struct coro); 1209 Newz (0, coro, 1, struct coro);
994 coro->args = newAV (); 1210 coro->args = newAV ();
1211 coro->save = CORO_SAVE_DEF;
1212 coro->flags = CF_NEW;
995 1213
996 hv = newHV (); 1214 hv = newHV ();
997 sv_magicext ((SV *)hv, 0, PERL_MAGIC_ext, &coro_state_vtbl, (char *)coro, 0)->mg_flags |= MGf_DUP; 1215 sv_magicext ((SV *)hv, 0, PERL_MAGIC_ext, &coro_state_vtbl, (char *)coro, 0)->mg_flags |= MGf_DUP;
998 RETVAL = sv_bless (newRV_noinc ((SV *)hv), gv_stashpv (klass, 1)); 1216 RETVAL = sv_bless (newRV_noinc ((SV *)hv), gv_stashpv (klass, 1));
999 1217
1000 for (i = 1; i < items; i++) 1218 for (i = 1; i < items; i++)
1001 av_push (coro->args, newSVsv (ST (i))); 1219 av_push (coro->args, newSVsv (ST (i)));
1002} 1220}
1003 OUTPUT: 1221 OUTPUT:
1222 RETVAL
1223
1224int
1225save (SV *coro, int new_save = -1)
1226 CODE:
1227 RETVAL = api_save (coro, new_save);
1228 OUTPUT:
1229 RETVAL
1230
1231int
1232save_also (SV *coro_sv, int save_also)
1233 CODE:
1234{
1235 struct coro *coro = SvSTATE (coro_sv);
1236 RETVAL = coro->save;
1237 coro->save |= save_also;
1238}
1239 OUTPUT:
1004 RETVAL 1240 RETVAL
1005 1241
1006void 1242void
1007_set_stacklevel (...) 1243_set_stacklevel (...)
1008 ALIAS: 1244 ALIAS:
1009 Coro::State::transfer = 1 1245 Coro::State::transfer = 1
1010 Coro::schedule = 2 1246 Coro::schedule = 2
1011 Coro::cede = 3 1247 Coro::cede = 3
1012 Coro::Cont::yield = 4 1248 Coro::cede_notself = 4
1013 CODE: 1249 CODE:
1014{ 1250{
1015 struct transfer_args ta; 1251 struct transfer_args ta;
1016 1252
1017 switch (ix) 1253 switch (ix)
1018 { 1254 {
1019 case 0: 1255 case 0:
1020 ta.prev = (struct coro *)INT2PTR (coro_cctx *, SvIV (ST (0))); 1256 ta.prev = (struct coro *)INT2PTR (coro_cctx *, SvIV (ST (0)));
1021 ta.next = 0; 1257 ta.next = 0;
1022 ta.flags = TRANSFER_SET_STACKLEVEL;
1023 break; 1258 break;
1024 1259
1025 case 1: 1260 case 1:
1026 if (items != 3) 1261 if (items != 2)
1027 croak ("Coro::State::transfer(prev,next,flags) expects three arguments, not %d", items); 1262 croak ("Coro::State::transfer (prev,next) expects two arguments, not %d", items);
1028 1263
1029 prepare_transfer (&ta, ST (0), ST (1), SvIV (ST (2))); 1264 prepare_transfer (aTHX_ &ta, ST (0), ST (1));
1030 break; 1265 break;
1031 1266
1032 case 2: 1267 case 2:
1033 prepare_schedule (&ta); 1268 prepare_schedule (aTHX_ &ta);
1034 break; 1269 break;
1035 1270
1036 case 3: 1271 case 3:
1037 prepare_cede (&ta); 1272 prepare_cede (aTHX_ &ta);
1038 break; 1273 break;
1039 1274
1040 case 4: 1275 case 4:
1041 { 1276 if (!prepare_cede_notself (aTHX_ &ta))
1042 SV *yieldstack; 1277 XSRETURN_EMPTY;
1043 SV *sv;
1044 AV *defav = GvAV (PL_defgv);
1045 1278
1046 yieldstack = *hv_fetch (
1047 (HV *)SvRV (GvSV (coro_current)),
1048 "yieldstack", sizeof ("yieldstack") - 1,
1049 0
1050 );
1051
1052 /* set up @_ -- ugly */
1053 av_clear (defav);
1054 av_fill (defav, items - 1);
1055 while (items--)
1056 av_store (defav, items, SvREFCNT_inc (ST(items)));
1057
1058 sv = av_pop ((AV *)SvRV (yieldstack));
1059 ta.prev = SvSTATE (*av_fetch ((AV *)SvRV (sv), 0, 0));
1060 ta.next = SvSTATE (*av_fetch ((AV *)SvRV (sv), 1, 0));
1061 ta.flags = 0;
1062 SvREFCNT_dec (sv);
1063 }
1064 break; 1279 break;
1065
1066 } 1280 }
1067 1281
1282 BARRIER;
1068 TRANSFER (ta); 1283 TRANSFER (ta);
1069}
1070 1284
1071void 1285 if (GIMME_V != G_VOID && ta.next != ta.prev)
1072_clone_state_from (SV *dst, SV *src) 1286 XSRETURN_YES;
1287}
1288
1289bool
1290_destroy (SV *coro_sv)
1073 CODE: 1291 CODE:
1074{ 1292 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv));
1075 struct coro *coro_src = SvSTATE (src); 1293 OUTPUT:
1076 1294 RETVAL
1077 sv_unmagic (SvRV (dst), PERL_MAGIC_ext);
1078
1079 ++coro_src->refcnt;
1080 sv_magicext (SvRV (dst), 0, PERL_MAGIC_ext, &coro_state_vtbl, (char *)coro_src, 0)->mg_flags |= MGf_DUP;
1081}
1082 1295
1083void 1296void
1084_exit (code) 1297_exit (code)
1085 int code 1298 int code
1086 PROTOTYPE: $ 1299 PROTOTYPE: $
1087 CODE: 1300 CODE:
1088 _exit (code); 1301 _exit (code);
1089 1302
1090int 1303int
1304cctx_stacksize (int new_stacksize = 0)
1305 CODE:
1306 RETVAL = coro_stacksize;
1307 if (new_stacksize)
1308 coro_stacksize = new_stacksize;
1309 OUTPUT:
1310 RETVAL
1311
1312int
1091cctx_count () 1313cctx_count ()
1092 CODE: 1314 CODE:
1093 RETVAL = cctx_count; 1315 RETVAL = cctx_count;
1094 OUTPUT: 1316 OUTPUT:
1095 RETVAL 1317 RETVAL
1114 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (PRIO_NORMAL)); 1336 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (PRIO_NORMAL));
1115 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (PRIO_LOW)); 1337 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (PRIO_LOW));
1116 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (PRIO_IDLE)); 1338 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (PRIO_IDLE));
1117 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (PRIO_MIN)); 1339 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (PRIO_MIN));
1118 1340
1119 coro_current = gv_fetchpv ("Coro::current", TRUE, SVt_PV); 1341 coro_current = get_sv ("Coro::current", FALSE);
1120 coro_idle = gv_fetchpv ("Coro::idle" , TRUE, SVt_PV); 1342 SvREADONLY_on (coro_current);
1121 1343
1122 for (i = PRIO_MAX - PRIO_MIN + 1; i--; ) 1344 for (i = PRIO_MAX - PRIO_MIN + 1; i--; )
1123 coro_ready[i] = newAV (); 1345 coro_ready[i] = newAV ();
1124 1346
1125 { 1347 {
1126 SV *sv = perl_get_sv("Coro::API", 1); 1348 SV *sv = perl_get_sv("Coro::API", 1);
1127 1349
1128 coroapi.schedule = api_schedule; 1350 coroapi.schedule = api_schedule;
1351 coroapi.save = api_save;
1129 coroapi.cede = api_cede; 1352 coroapi.cede = api_cede;
1353 coroapi.cede_notself = api_cede_notself;
1130 coroapi.ready = api_ready; 1354 coroapi.ready = api_ready;
1355 coroapi.is_ready = api_is_ready;
1131 coroapi.nready = &coro_nready; 1356 coroapi.nready = &coro_nready;
1132 coroapi.current = coro_current; 1357 coroapi.current = coro_current;
1133 1358
1134 GCoroAPI = &coroapi; 1359 GCoroAPI = &coroapi;
1135 sv_setiv (sv, (IV)&coroapi); 1360 sv_setiv (sv, (IV)&coroapi);
1136 SvREADONLY_on (sv); 1361 SvREADONLY_on (sv);
1137 } 1362 }
1138} 1363}
1364
1365void
1366_set_current (SV *current)
1367 PROTOTYPE: $
1368 CODE:
1369 SvREFCNT_dec (SvRV (coro_current));
1370 SvRV_set (coro_current, SvREFCNT_inc (SvRV (current)));
1139 1371
1140int 1372int
1141prio (Coro::State coro, int newprio = 0) 1373prio (Coro::State coro, int newprio = 0)
1142 ALIAS: 1374 ALIAS:
1143 nice = 1 1375 nice = 1
1146 RETVAL = coro->prio; 1378 RETVAL = coro->prio;
1147 1379
1148 if (items > 1) 1380 if (items > 1)
1149 { 1381 {
1150 if (ix) 1382 if (ix)
1151 newprio += coro->prio; 1383 newprio = coro->prio - newprio;
1152 1384
1153 if (newprio < PRIO_MIN) newprio = PRIO_MIN; 1385 if (newprio < PRIO_MIN) newprio = PRIO_MIN;
1154 if (newprio > PRIO_MAX) newprio = PRIO_MAX; 1386 if (newprio > PRIO_MAX) newprio = PRIO_MAX;
1155 1387
1156 coro->prio = newprio; 1388 coro->prio = newprio;
1157 } 1389 }
1158} 1390}
1391 OUTPUT:
1392 RETVAL
1159 1393
1160void 1394SV *
1161ready (SV *self) 1395ready (SV *self)
1162 PROTOTYPE: $ 1396 PROTOTYPE: $
1163 CODE: 1397 CODE:
1164 api_ready (self); 1398 RETVAL = boolSV (api_ready (self));
1399 OUTPUT:
1400 RETVAL
1401
1402SV *
1403is_ready (SV *self)
1404 PROTOTYPE: $
1405 CODE:
1406 RETVAL = boolSV (api_is_ready (self));
1407 OUTPUT:
1408 RETVAL
1165 1409
1166int 1410int
1167nready (...) 1411nready (...)
1168 PROTOTYPE: 1412 PROTOTYPE:
1169 CODE: 1413 CODE:
1175 1419
1176SV * 1420SV *
1177_get_state () 1421_get_state ()
1178 CODE: 1422 CODE:
1179{ 1423{
1180 struct { 1424 struct io_state *data;
1181 int errorno;
1182 int laststype;
1183 int laststatval;
1184 Stat_t statcache;
1185 } data;
1186 1425
1426 RETVAL = newSV (sizeof (struct io_state));
1427 data = (struct io_state *)SvPVX (RETVAL);
1428 SvCUR_set (RETVAL, sizeof (struct io_state));
1429 SvPOK_only (RETVAL);
1430
1187 data.errorno = errno; 1431 data->errorno = errno;
1188 data.laststype = PL_laststype; 1432 data->laststype = PL_laststype;
1189 data.laststatval = PL_laststatval; 1433 data->laststatval = PL_laststatval;
1190 data.statcache = PL_statcache; 1434 data->statcache = PL_statcache;
1191
1192 RETVAL = newSVpvn ((char *)&data, sizeof data);
1193} 1435}
1194 OUTPUT: 1436 OUTPUT:
1195 RETVAL 1437 RETVAL
1196 1438
1197void 1439void
1198_set_state (char *data_) 1440_set_state (char *data_)
1199 PROTOTYPE: $ 1441 PROTOTYPE: $
1200 CODE: 1442 CODE:
1201{ 1443{
1202 struct { 1444 struct io_state *data = (void *)data_;
1203 int errorno;
1204 int laststype;
1205 int laststatval;
1206 Stat_t statcache;
1207 } *data = (void *)data_;
1208 1445
1209 errno = data->errorno; 1446 errno = data->errorno;
1210 PL_laststype = data->laststype; 1447 PL_laststype = data->laststype;
1211 PL_laststatval = data->laststatval; 1448 PL_laststatval = data->laststatval;
1212 PL_statcache = data->statcache; 1449 PL_statcache = data->statcache;
1213} 1450}
1451

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines