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.356 by root, Sat Jun 27 14:06:59 2009 UTC vs.
Revision 1.361 by root, Wed Jul 1 07:26:40 2009 UTC

159# if CORO_PTHREAD 159# if CORO_PTHREAD
160static void *coro_thx; 160static void *coro_thx;
161# endif 161# endif
162#endif 162#endif
163 163
164#ifdef __linux
165# include <time.h> /* for timespec */
166# include <syscall.h> /* for SYS_* */
167# ifdef SYS_clock_gettime
168# define coro_clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
169# define CORO_CLOCK_MONOTONIC 1
170# define CORO_CLOCK_THREAD_CPUTIME_ID 3
171# endif
172#endif
173
164static double (*nvtime)(); /* so why doesn't it take void? */ 174static double (*nvtime)(); /* so why doesn't it take void? */
175static void (*u2time)(pTHX_ UV ret[2]);
165 176
166/* we hijack an hopefully unused CV flag for our purposes */ 177/* we hijack an hopefully unused CV flag for our purposes */
167#define CVf_SLF 0x4000 178#define CVf_SLF 0x4000
168static OP *pp_slf (pTHX); 179static OP *pp_slf (pTHX);
169 180
194static CV *cv_pool_handler; 205static CV *cv_pool_handler;
195static CV *cv_coro_state_new; 206static CV *cv_coro_state_new;
196 207
197/* Coro::AnyEvent */ 208/* Coro::AnyEvent */
198static SV *sv_activity; 209static SV *sv_activity;
210
211/* enable processtime/realtime profiling */
212static char enable_times;
213typedef U32 coro_ts[2];
214static coro_ts time_real, time_cpu;
215static char times_valid;
199 216
200static struct coro_cctx *cctx_first; 217static struct coro_cctx *cctx_first;
201static int cctx_count, cctx_idle; 218static int cctx_count, cctx_idle;
202 219
203enum { 220enum {
293 310
294 /* on_enter/on_leave */ 311 /* on_enter/on_leave */
295 AV *on_enter; 312 AV *on_enter;
296 AV *on_leave; 313 AV *on_leave;
297 314
315 /* times */
316 coro_ts t_cpu, t_real;
317
298 /* linked list */ 318 /* linked list */
299 struct coro *next, *prev; 319 struct coro *next, *prev;
300}; 320};
301 321
302typedef struct coro *Coro__State; 322typedef struct coro *Coro__State;
307/* the mainr easonw e don't support windows process emulation */ 327/* the mainr easonw e don't support windows process emulation */
308static struct CoroSLF slf_frame; /* the current slf frame */ 328static struct CoroSLF slf_frame; /* the current slf frame */
309 329
310/** Coro ********************************************************************/ 330/** Coro ********************************************************************/
311 331
312#define PRIO_MAX 3 332#define CORO_PRIO_MAX 3
313#define PRIO_HIGH 1 333#define CORO_PRIO_HIGH 1
314#define PRIO_NORMAL 0 334#define CORO_PRIO_NORMAL 0
315#define PRIO_LOW -1 335#define CORO_PRIO_LOW -1
316#define PRIO_IDLE -3 336#define CORO_PRIO_IDLE -3
317#define PRIO_MIN -4 337#define CORO_PRIO_MIN -4
318 338
319/* for Coro.pm */ 339/* for Coro.pm */
320static SV *coro_current; 340static SV *coro_current;
321static SV *coro_readyhook; 341static SV *coro_readyhook;
322static struct coro *coro_ready [PRIO_MAX - PRIO_MIN + 1][2]; /* head|tail */ 342static struct coro *coro_ready [CORO_PRIO_MAX - CORO_PRIO_MIN + 1][2]; /* head|tail */
323static CV *cv_coro_run, *cv_coro_terminate; 343static CV *cv_coro_run, *cv_coro_terminate;
324static struct coro *coro_first; 344static struct coro *coro_first;
325#define coro_nready coroapi.nready 345#define coro_nready coroapi.nready
326 346
327/** lowlevel stuff **********************************************************/ 347/** lowlevel stuff **********************************************************/
366 386
367 if (!cv) 387 if (!cv)
368 croak ("code reference expected"); 388 croak ("code reference expected");
369 389
370 return cv; 390 return cv;
391}
392
393INLINE void
394coro_times_update ()
395{
396#ifdef coro_clock_gettime
397 struct timespec ts;
398
399 ts.tv_sec = ts.tv_nsec = 0;
400 coro_clock_gettime (CORO_CLOCK_THREAD_CPUTIME_ID, &ts);
401 time_cpu [0] = ts.tv_sec; time_cpu [1] = ts.tv_nsec;
402
403 ts.tv_sec = ts.tv_nsec = 0;
404 coro_clock_gettime (CORO_CLOCK_MONOTONIC, &ts);
405 time_real [0] = ts.tv_sec; time_real [1] = ts.tv_nsec;
406#else
407 dTHX;
408 UV tv[2];
409
410 u2time (aTHX_ &tv);
411 time_real [0] = tv [0];
412 time_real [1] = tv [1] * 1000;
413#endif
414}
415
416INLINE void
417coro_times_add (struct coro *c)
418{
419 c->t_real [1] += time_real [1];
420 if (c->t_real [1] > 1000000000) { c->t_real [1] -= 1000000000; ++c->t_real [0]; }
421 c->t_real [0] += time_real [0];
422
423 c->t_cpu [1] += time_cpu [1];
424 if (c->t_cpu [1] > 1000000000) { c->t_cpu [1] -= 1000000000; ++c->t_cpu [0]; }
425 c->t_cpu [0] += time_cpu [0];
426}
427
428INLINE void
429coro_times_sub (struct coro *c)
430{
431 if (c->t_real [1] < time_real [1]) { c->t_real [1] += 1000000000; --c->t_real [0]; }
432 c->t_real [1] -= time_real [1];
433 c->t_real [0] -= time_real [0];
434
435 if (c->t_cpu [1] < time_cpu [1]) { c->t_cpu [1] += 1000000000; --c->t_cpu [0]; }
436 c->t_cpu [1] -= time_cpu [1];
437 c->t_cpu [0] -= time_cpu [0];
371} 438}
372 439
373/*****************************************************************************/ 440/*****************************************************************************/
374/* magic glue */ 441/* magic glue */
375 442
475static int 542static int
476coro_cv_free (pTHX_ SV *sv, MAGIC *mg) 543coro_cv_free (pTHX_ SV *sv, MAGIC *mg)
477{ 544{
478 AV *padlist; 545 AV *padlist;
479 AV *av = (AV *)mg->mg_obj; 546 AV *av = (AV *)mg->mg_obj;
547
548 /* perl manages to free our internal AV and _then_ call us */
549 if (IN_DESTRUCT)
550 return;
480 551
481 /* casting is fun. */ 552 /* casting is fun. */
482 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av))) 553 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
483 free_padlist (aTHX_ padlist); 554 free_padlist (aTHX_ padlist);
484 555
573 } 644 }
574 645
575 slf_frame = c->slf_frame; 646 slf_frame = c->slf_frame;
576 CORO_THROW = c->except; 647 CORO_THROW = c->except;
577 648
649 if (expect_false (enable_times))
650 {
651 if (expect_false (!times_valid))
652 coro_times_update ();
653
654 coro_times_sub (c);
655 }
656
578 if (expect_false (c->on_enter)) 657 if (expect_false (c->on_enter))
579 { 658 {
580 int i; 659 int i;
581 660
582 for (i = 0; i <= AvFILLp (c->on_enter); ++i) 661 for (i = 0; i <= AvFILLp (c->on_enter); ++i)
591 { 670 {
592 int i; 671 int i;
593 672
594 for (i = AvFILLp (c->on_leave); i >= 0; --i) 673 for (i = AvFILLp (c->on_leave); i >= 0; --i)
595 on_enterleave_call (aTHX_ AvARRAY (c->on_leave)[i]); 674 on_enterleave_call (aTHX_ AvARRAY (c->on_leave)[i]);
675 }
676
677 times_valid = 0;
678
679 if (expect_false (enable_times))
680 {
681 coro_times_update (); times_valid = 1;
682 coro_times_add (c);
596 } 683 }
597 684
598 c->except = CORO_THROW; 685 c->except = CORO_THROW;
599 c->slf_frame = slf_frame; 686 c->slf_frame = slf_frame;
600 687
964 1051
965 PL_op = (OP *)&coro_setup_op; 1052 PL_op = (OP *)&coro_setup_op;
966 1053
967 /* copy throw, in case it was set before coro_setup */ 1054 /* copy throw, in case it was set before coro_setup */
968 CORO_THROW = coro->except; 1055 CORO_THROW = coro->except;
1056
1057 if (expect_false (enable_times))
1058 {
1059 coro_times_update ();
1060 coro_times_sub (coro);
1061 }
969} 1062}
970 1063
971static void 1064static void
972coro_unwind_stacks (pTHX) 1065coro_unwind_stacks (pTHX)
973{ 1066{
1622/** Coro ********************************************************************/ 1715/** Coro ********************************************************************/
1623 1716
1624INLINE void 1717INLINE void
1625coro_enq (pTHX_ struct coro *coro) 1718coro_enq (pTHX_ struct coro *coro)
1626{ 1719{
1627 struct coro **ready = coro_ready [coro->prio - PRIO_MIN]; 1720 struct coro **ready = coro_ready [coro->prio - CORO_PRIO_MIN];
1628 1721
1629 SvREFCNT_inc_NN (coro->hv); 1722 SvREFCNT_inc_NN (coro->hv);
1630 1723
1631 coro->next_ready = 0; 1724 coro->next_ready = 0;
1632 *(ready [0] ? &ready [1]->next_ready : &ready [0]) = coro; 1725 *(ready [0] ? &ready [1]->next_ready : &ready [0]) = coro;
1636INLINE struct coro * 1729INLINE struct coro *
1637coro_deq (pTHX) 1730coro_deq (pTHX)
1638{ 1731{
1639 int prio; 1732 int prio;
1640 1733
1641 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= 0; ) 1734 for (prio = CORO_PRIO_MAX - CORO_PRIO_MIN + 1; --prio >= 0; )
1642 { 1735 {
1643 struct coro **ready = coro_ready [prio]; 1736 struct coro **ready = coro_ready [prio];
1644 1737
1645 if (ready [0]) 1738 if (ready [0])
1646 { 1739 {
2965 3058
2966 if (!svp) croak ("Time::HiRes is required"); 3059 if (!svp) croak ("Time::HiRes is required");
2967 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer"); 3060 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer");
2968 3061
2969 nvtime = INT2PTR (double (*)(), SvIV (*svp)); 3062 nvtime = INT2PTR (double (*)(), SvIV (*svp));
3063
3064 svp = hv_fetch (PL_modglobal, "Time::U2time", 12, 0);
3065 u2time = INT2PTR (double (*)(), SvIV (*svp));
2970 } 3066 }
2971 3067
2972 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL)); 3068 assert (("PRIO_NORMAL must be 0", !CORO_PRIO_NORMAL));
2973} 3069}
2974 3070
2975SV * 3071SV *
2976new (char *klass, ...) 3072new (char *klass, ...)
2977 ALIAS: 3073 ALIAS:
3179 CODE: 3275 CODE:
3180{ 3276{
3181 struct coro *current = SvSTATE_current; 3277 struct coro *current = SvSTATE_current;
3182 SV **throwp = self == current ? &CORO_THROW : &self->except; 3278 SV **throwp = self == current ? &CORO_THROW : &self->except;
3183 SvREFCNT_dec (*throwp); 3279 SvREFCNT_dec (*throwp);
3280 SvGETMAGIC (throw);
3184 *throwp = SvOK (throw) ? newSVsv (throw) : 0; 3281 *throwp = SvOK (throw) ? newSVsv (throw) : 0;
3185} 3282}
3186 3283
3187void 3284void
3188api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) 3285api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
3247 CODE: 3344 CODE:
3248 coro_state_destroy (aTHX_ self); 3345 coro_state_destroy (aTHX_ self);
3249 coro_call_on_destroy (aTHX_ self); /* actually only for Coro objects */ 3346 coro_call_on_destroy (aTHX_ self); /* actually only for Coro objects */
3250 3347
3251 3348
3349SV *
3350enable_times (int enabled = enable_times)
3351 CODE:
3352{
3353 RETVAL = boolSV (enable_times);
3354
3355 if (enabled != enable_times)
3356 {
3357 enable_times = enabled;
3358
3359 coro_times_update ();
3360 (enabled ? coro_times_sub : coro_times_add)(SvSTATE (coro_current));
3361 }
3362}
3363 OUTPUT:
3364 RETVAL
3365
3366void
3367times (Coro::State self)
3368 PPCODE:
3369{
3370 struct coro *current = SvSTATE (coro_current);
3371
3372 if (expect_false (current == self))
3373 {
3374 coro_times_update ();
3375 coro_times_add (SvSTATE (coro_current));
3376 }
3377
3378 EXTEND (SP, 2);
3379 PUSHs (sv_2mortal (newSVnv (self->t_real [0] + self->t_real [1] * 1e-9)));
3380 PUSHs (sv_2mortal (newSVnv (self->t_cpu [0] + self->t_cpu [1] * 1e-9)));
3381
3382 if (expect_false (current == self))
3383 coro_times_sub (SvSTATE (coro_current));
3384}
3385
3252MODULE = Coro::State PACKAGE = Coro 3386MODULE = Coro::State PACKAGE = Coro
3253 3387
3254BOOT: 3388BOOT:
3255{ 3389{
3256 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE); 3390 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE);
3268 cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler); 3402 cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler);
3269 cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new); 3403 cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new);
3270 3404
3271 coro_stash = gv_stashpv ("Coro", TRUE); 3405 coro_stash = gv_stashpv ("Coro", TRUE);
3272 3406
3273 newCONSTSUB (coro_stash, "PRIO_MAX", newSViv (PRIO_MAX)); 3407 newCONSTSUB (coro_stash, "PRIO_MAX", newSViv (CORO_PRIO_MAX));
3274 newCONSTSUB (coro_stash, "PRIO_HIGH", newSViv (PRIO_HIGH)); 3408 newCONSTSUB (coro_stash, "PRIO_HIGH", newSViv (CORO_PRIO_HIGH));
3275 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (PRIO_NORMAL)); 3409 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (CORO_PRIO_NORMAL));
3276 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (PRIO_LOW)); 3410 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (CORO_PRIO_LOW));
3277 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (PRIO_IDLE)); 3411 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (CORO_PRIO_IDLE));
3278 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (PRIO_MIN)); 3412 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (CORO_PRIO_MIN));
3279 3413
3280 { 3414 {
3281 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE); 3415 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE);
3282 3416
3283 coroapi.schedule = api_schedule; 3417 coroapi.schedule = api_schedule;
3335void 3469void
3336_set_readyhook (SV *hook) 3470_set_readyhook (SV *hook)
3337 PROTOTYPE: $ 3471 PROTOTYPE: $
3338 CODE: 3472 CODE:
3339 SvREFCNT_dec (coro_readyhook); 3473 SvREFCNT_dec (coro_readyhook);
3474 SvGETMAGIC (hook);
3340 coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0; 3475 coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0;
3341 3476
3342int 3477int
3343prio (Coro::State coro, int newprio = 0) 3478prio (Coro::State coro, int newprio = 0)
3344 PROTOTYPE: $;$ 3479 PROTOTYPE: $;$
3351 if (items > 1) 3486 if (items > 1)
3352 { 3487 {
3353 if (ix) 3488 if (ix)
3354 newprio = coro->prio - newprio; 3489 newprio = coro->prio - newprio;
3355 3490
3356 if (newprio < PRIO_MIN) newprio = PRIO_MIN; 3491 if (newprio < CORO_PRIO_MIN) newprio = CORO_PRIO_MIN;
3357 if (newprio > PRIO_MAX) newprio = PRIO_MAX; 3492 if (newprio > CORO_PRIO_MAX) newprio = CORO_PRIO_MAX;
3358 3493
3359 coro->prio = newprio; 3494 coro->prio = newprio;
3360 } 3495 }
3361} 3496}
3362 OUTPUT: 3497 OUTPUT:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines