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.358 by root, Mon Jun 29 04:30:25 2009 UTC vs.
Revision 1.360 by root, Mon Jun 29 06:14:23 2009 UTC

170# define CORO_CLOCK_THREAD_CPUTIME_ID 3 170# define CORO_CLOCK_THREAD_CPUTIME_ID 3
171# endif 171# endif
172#endif 172#endif
173 173
174static 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]);
175 176
176/* we hijack an hopefully unused CV flag for our purposes */ 177/* we hijack an hopefully unused CV flag for our purposes */
177#define CVf_SLF 0x4000 178#define CVf_SLF 0x4000
178static OP *pp_slf (pTHX); 179static OP *pp_slf (pTHX);
179 180
204static CV *cv_pool_handler; 205static CV *cv_pool_handler;
205static CV *cv_coro_state_new; 206static CV *cv_coro_state_new;
206 207
207/* Coro::AnyEvent */ 208/* Coro::AnyEvent */
208static 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;
209 216
210static struct coro_cctx *cctx_first; 217static struct coro_cctx *cctx_first;
211static int cctx_count, cctx_idle; 218static int cctx_count, cctx_idle;
212 219
213enum { 220enum {
303 310
304 /* on_enter/on_leave */ 311 /* on_enter/on_leave */
305 AV *on_enter; 312 AV *on_enter;
306 AV *on_leave; 313 AV *on_leave;
307 314
315 /* times */
316 coro_ts t_cpu, t_real;
317
308 /* linked list */ 318 /* linked list */
309 struct coro *next, *prev; 319 struct coro *next, *prev;
310}; 320};
311 321
312typedef struct coro *Coro__State; 322typedef struct coro *Coro__State;
376 386
377 if (!cv) 387 if (!cv)
378 croak ("code reference expected"); 388 croak ("code reference expected");
379 389
380 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 UV tv[2];
408
409 u2time (aTHX_ &tv);
410 time_real [0] = tv [0];
411 time_real [1] = tv [1] * 1000;
412#endif
413}
414
415INLINE void
416coro_times_add (struct coro *c)
417{
418 c->t_real [1] += time_real [1];
419 if (c->t_real [1] > 1000000000) { c->t_real [1] -= 1000000000; ++c->t_real [0]; }
420 c->t_real [0] += time_real [0];
421
422 c->t_cpu [1] += time_cpu [1];
423 if (c->t_cpu [1] > 1000000000) { c->t_cpu [1] -= 1000000000; ++c->t_cpu [0]; }
424 c->t_cpu [0] += time_cpu [0];
425}
426
427INLINE void
428coro_times_sub (struct coro *c)
429{
430 if (c->t_real [1] < time_real [1]) { c->t_real [1] += 1000000000; --c->t_real [0]; }
431 c->t_real [1] -= time_real [1];
432 c->t_real [0] -= time_real [0];
433
434 if (c->t_cpu [1] < time_cpu [1]) { c->t_cpu [1] += 1000000000; --c->t_cpu [0]; }
435 c->t_cpu [1] -= time_cpu [1];
436 c->t_cpu [0] -= time_cpu [0];
381} 437}
382 438
383/*****************************************************************************/ 439/*****************************************************************************/
384/* magic glue */ 440/* magic glue */
385 441
587 } 643 }
588 644
589 slf_frame = c->slf_frame; 645 slf_frame = c->slf_frame;
590 CORO_THROW = c->except; 646 CORO_THROW = c->except;
591 647
648 if (expect_false (enable_times))
649 {
650 if (expect_false (!times_valid))
651 coro_times_update ();
652
653 coro_times_sub (c);
654 }
655
592 if (expect_false (c->on_enter)) 656 if (expect_false (c->on_enter))
593 { 657 {
594 int i; 658 int i;
595 659
596 for (i = 0; i <= AvFILLp (c->on_enter); ++i) 660 for (i = 0; i <= AvFILLp (c->on_enter); ++i)
605 { 669 {
606 int i; 670 int i;
607 671
608 for (i = AvFILLp (c->on_leave); i >= 0; --i) 672 for (i = AvFILLp (c->on_leave); i >= 0; --i)
609 on_enterleave_call (aTHX_ AvARRAY (c->on_leave)[i]); 673 on_enterleave_call (aTHX_ AvARRAY (c->on_leave)[i]);
674 }
675
676 times_valid = 0;
677
678 if (expect_false (enable_times))
679 {
680 coro_times_update (); times_valid = 1;
681 coro_times_add (c);
610 } 682 }
611 683
612 c->except = CORO_THROW; 684 c->except = CORO_THROW;
613 c->slf_frame = slf_frame; 685 c->slf_frame = slf_frame;
614 686
978 1050
979 PL_op = (OP *)&coro_setup_op; 1051 PL_op = (OP *)&coro_setup_op;
980 1052
981 /* copy throw, in case it was set before coro_setup */ 1053 /* copy throw, in case it was set before coro_setup */
982 CORO_THROW = coro->except; 1054 CORO_THROW = coro->except;
1055
1056 if (expect_false (enable_times))
1057 {
1058 coro_times_update ();
1059 coro_times_sub (coro);
1060 }
983} 1061}
984 1062
985static void 1063static void
986coro_unwind_stacks (pTHX) 1064coro_unwind_stacks (pTHX)
987{ 1065{
2979 3057
2980 if (!svp) croak ("Time::HiRes is required"); 3058 if (!svp) croak ("Time::HiRes is required");
2981 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer"); 3059 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer");
2982 3060
2983 nvtime = INT2PTR (double (*)(), SvIV (*svp)); 3061 nvtime = INT2PTR (double (*)(), SvIV (*svp));
3062
3063 svp = hv_fetch (PL_modglobal, "Time::U2time", 12, 0);
3064 u2time = INT2PTR (double (*)(), SvIV (*svp));
2984 } 3065 }
2985 3066
2986 assert (("PRIO_NORMAL must be 0", !CORO_PRIO_NORMAL)); 3067 assert (("PRIO_NORMAL must be 0", !CORO_PRIO_NORMAL));
2987} 3068}
2988 3069
3262 CODE: 3343 CODE:
3263 coro_state_destroy (aTHX_ self); 3344 coro_state_destroy (aTHX_ self);
3264 coro_call_on_destroy (aTHX_ self); /* actually only for Coro objects */ 3345 coro_call_on_destroy (aTHX_ self); /* actually only for Coro objects */
3265 3346
3266 3347
3348SV *
3349enable_times (int enabled = enable_times)
3350 CODE:
3351{
3352 RETVAL = boolSV (enable_times);
3353
3354 if (enabled != enable_times)
3355 {
3356 enable_times = enabled;
3357
3358 coro_times_update ();
3359 (enabled ? coro_times_sub : coro_times_add)(SvSTATE (coro_current));
3360 }
3361}
3362 OUTPUT:
3363 RETVAL
3364
3365void
3366times (Coro::State self)
3367 PPCODE:
3368{
3369 struct coro *current = SvSTATE (coro_current);
3370
3371 if (expect_false (current == self))
3372 {
3373 coro_times_update ();
3374 coro_times_add (SvSTATE (coro_current));
3375 }
3376
3377 EXTEND (SP, 2);
3378 PUSHs (sv_2mortal (newSVnv (self->t_real [0] + self->t_real [1] * 1e-9)));
3379 PUSHs (sv_2mortal (newSVnv (self->t_cpu [0] + self->t_cpu [1] * 1e-9)));
3380
3381 if (expect_false (current == self))
3382 coro_times_sub (SvSTATE (coro_current));
3383}
3384
3267MODULE = Coro::State PACKAGE = Coro 3385MODULE = Coro::State PACKAGE = Coro
3268 3386
3269BOOT: 3387BOOT:
3270{ 3388{
3271 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE); 3389 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE);
3367 if (items > 1) 3485 if (items > 1)
3368 { 3486 {
3369 if (ix) 3487 if (ix)
3370 newprio = coro->prio - newprio; 3488 newprio = coro->prio - newprio;
3371 3489
3372 if (newprio < PRIO_MIN) newprio = PRIO_MIN; 3490 if (newprio < CORO_PRIO_MIN) newprio = CORO_PRIO_MIN;
3373 if (newprio > PRIO_MAX) newprio = PRIO_MAX; 3491 if (newprio > CORO_PRIO_MAX) newprio = CORO_PRIO_MAX;
3374 3492
3375 coro->prio = newprio; 3493 coro->prio = newprio;
3376 } 3494 }
3377} 3495}
3378 OUTPUT: 3496 OUTPUT:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines