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.359 by root, Mon Jun 29 05:07:19 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
206 207
207/* Coro::AnyEvent */ 208/* Coro::AnyEvent */
208static SV *sv_activity; 209static SV *sv_activity;
209 210
210/* enable processtime/realtime profiling */ 211/* enable processtime/realtime profiling */
211static char profile_times; 212static char enable_times;
212typedef U32 coro_ts[2]; 213typedef U32 coro_ts[2];
214static coro_ts time_real, time_cpu;
215static char times_valid;
213 216
214static struct coro_cctx *cctx_first; 217static struct coro_cctx *cctx_first;
215static int cctx_count, cctx_idle; 218static int cctx_count, cctx_idle;
216 219
217enum { 220enum {
307 310
308 /* on_enter/on_leave */ 311 /* on_enter/on_leave */
309 AV *on_enter; 312 AV *on_enter;
310 AV *on_leave; 313 AV *on_leave;
311 314
315 /* times */
316 coro_ts t_cpu, t_real;
317
312 /* linked list */ 318 /* linked list */
313 struct coro *next, *prev; 319 struct coro *next, *prev;
314}; 320};
315 321
316typedef struct coro *Coro__State; 322typedef struct coro *Coro__State;
380 386
381 if (!cv) 387 if (!cv)
382 croak ("code reference expected"); 388 croak ("code reference expected");
383 389
384 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];
385} 437}
386 438
387/*****************************************************************************/ 439/*****************************************************************************/
388/* magic glue */ 440/* magic glue */
389 441
591 } 643 }
592 644
593 slf_frame = c->slf_frame; 645 slf_frame = c->slf_frame;
594 CORO_THROW = c->except; 646 CORO_THROW = c->except;
595 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
596 if (expect_false (c->on_enter)) 656 if (expect_false (c->on_enter))
597 { 657 {
598 int i; 658 int i;
599 659
600 for (i = 0; i <= AvFILLp (c->on_enter); ++i) 660 for (i = 0; i <= AvFILLp (c->on_enter); ++i)
609 { 669 {
610 int i; 670 int i;
611 671
612 for (i = AvFILLp (c->on_leave); i >= 0; --i) 672 for (i = AvFILLp (c->on_leave); i >= 0; --i)
613 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);
614 } 682 }
615 683
616 c->except = CORO_THROW; 684 c->except = CORO_THROW;
617 c->slf_frame = slf_frame; 685 c->slf_frame = slf_frame;
618 686
982 1050
983 PL_op = (OP *)&coro_setup_op; 1051 PL_op = (OP *)&coro_setup_op;
984 1052
985 /* copy throw, in case it was set before coro_setup */ 1053 /* copy throw, in case it was set before coro_setup */
986 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 }
987} 1061}
988 1062
989static void 1063static void
990coro_unwind_stacks (pTHX) 1064coro_unwind_stacks (pTHX)
991{ 1065{
2983 3057
2984 if (!svp) croak ("Time::HiRes is required"); 3058 if (!svp) croak ("Time::HiRes is required");
2985 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer"); 3059 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer");
2986 3060
2987 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));
2988 } 3065 }
2989 3066
2990 assert (("PRIO_NORMAL must be 0", !CORO_PRIO_NORMAL)); 3067 assert (("PRIO_NORMAL must be 0", !CORO_PRIO_NORMAL));
2991} 3068}
2992 3069
3266 CODE: 3343 CODE:
3267 coro_state_destroy (aTHX_ self); 3344 coro_state_destroy (aTHX_ self);
3268 coro_call_on_destroy (aTHX_ self); /* actually only for Coro objects */ 3345 coro_call_on_destroy (aTHX_ self); /* actually only for Coro objects */
3269 3346
3270 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
3271MODULE = Coro::State PACKAGE = Coro 3385MODULE = Coro::State PACKAGE = Coro
3272 3386
3273BOOT: 3387BOOT:
3274{ 3388{
3275 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE); 3389 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines