1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
/* $Header$ */
/*
* Copyright © 1988-2004 Keith Packard and Bart Massey.
* All Rights Reserved. See the file COPYING in this directory
* for licensing information.
*/
#include "nickle.h"
#include <sys/time.h>
#include <assert.h>
#define TICK_MS 10
volatile static unsigned long currentTick;
volatile Bool signalProfile;
static unsigned long previousTick;
Bool profiling;
static RETSIGTYPE
sigprofile (int sig)
{
resetSignal (SIGVTALRM, sigprofile);
currentTick += TICK_MS;
SetSignalProfile ();
}
void
ProfileInterrupt (Value thread)
{
unsigned long now;
unsigned long ticks;
InstPtr pc;
ExprPtr stat;
FramePtr frame;
now = currentTick;
ticks = now - previousTick;
previousTick = now;
if (!thread)
return;
pc = thread->thread.continuation.pc;
if (pc)
{
ObjPtr obj = thread->thread.continuation.obj;
stat = ObjStatement (obj, pc);
if (stat)
{
stat->base.ticks += ticks;
stat->base.line = -stat->base.line - 1;
}
obj->ticks += ticks;
obj->error += 100;
}
for (frame = thread->thread.continuation.frame; frame; frame = frame->previous)
{
ObjPtr obj = frame->saveObj;
stat = ObjStatement (obj, frame->savePc);
if (stat && stat->base.line >= 0) {
stat->base.sub_ticks += ticks;
stat->base.line = -stat->base.line - 1;
}
if (obj->error < 100) {
obj->sub_ticks += ticks;
obj->error += 100;
}
}
for (frame = thread->thread.continuation.frame; frame; frame = frame->previous)
{
ObjPtr obj = frame->saveObj;
stat = ObjStatement (obj, frame->savePc);
if (stat)
stat->base.line = -stat->base.line + 1;
if (obj->error >= 100)
obj->error -= 100;
}
pc = thread->thread.continuation.pc;
if (pc)
{
ObjPtr obj = thread->thread.continuation.obj;
stat = ObjStatement (obj, pc);
if (stat)
stat->base.line = -stat->base.line + 1;
if (obj->error >= 100)
obj->error -= 100;
}
}
Value
do_profile (Value on)
{
struct itimerval v;
Bool previous = profiling;
if (True (on))
{
previousTick = currentTick;
catchSignal (SIGVTALRM, sigprofile);
v.it_interval.tv_sec = 0;
v.it_interval.tv_usec = TICK_MS * 1000;
v.it_value = v.it_interval;
setitimer (ITIMER_VIRTUAL, &v, 0);
profiling = True;
}
else
{
v.it_interval.tv_sec = 0;
v.it_interval.tv_usec = 0;
v.it_value = v.it_interval;
setitimer (ITIMER_VIRTUAL, &v, 0);
profiling = False;
/*
* expr nodes clear their accumulated time
* on GC when profiling is false
*/
MemCollect ();
}
return previous ? TrueVal : FalseVal;
}
|