|
From: <sv...@va...> - 2006-12-23 01:21:18
|
Author: sewardj
Date: 2006-12-23 01:21:12 +0000 (Sat, 23 Dec 2006)
New Revision: 6413
Log:
Change the core-tool interface 'thread_run' event to be more useful:
- Rename the event to 'thread_runstate'.
- Add arguments: pass also a boolean indicating whether the thread
is running or stopping, and a 64-bit int showing how many blocks
overall have run, so tools can make a rough estimate of workload.
The boolean allows tools to see threads starting and stopping.
Prior to this, de-schedule events were invisible to tools.
- Call the callback (hand the event to tools) just before client
code is run, and again immediately after it stops running. This
should give correct sequencing w.r.t posting of thread creation/
destruction events.
In order to make callgrind work without complex changes, I added a
simple impedance-matching function 'clg_thread_runstate_callback'=20
which hands thread-run events onwards to CLG_(thread_run).
Use this new 'thread_runstate' with care: it will be called before
and after every translation, which means it will be called ~500k
times in a startup of firefox. So the callback needs to be fast.
Modified:
trunk/callgrind/main.c
trunk/coregrind/m_scheduler/scheduler.c
trunk/coregrind/m_tooliface.c
trunk/coregrind/pub_core_tooliface.h
trunk/include/pub_tool_tooliface.h
Modified: trunk/callgrind/main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/callgrind/main.c 2006-12-18 17:53:13 UTC (rev 6412)
+++ trunk/callgrind/main.c 2006-12-23 01:21:12 UTC (rev 6413)
@@ -1022,6 +1022,19 @@
/*--- Setup ---*/
/*--------------------------------------------------------------------*/
=20
+static void clg_thread_runstate_callback ( ThreadId tid,
+ Bool is_running,=20
+ ULong blocks_done )
+{
+ if (0)
+ VG_(printf)("%d %c %llu\n",=20
+ (Int)tid, is_running ? 'R' : 's', blocks_done);
+ /* Simply call onwards to CLG_(run_thread). Maybe this can be
+ simplified later? */
+ if (is_running)
+ CLG_(run_thread)( tid );
+}
+
static
void CLG_(post_clo_init)(void)
{
@@ -1088,7 +1101,7 @@
VG_(needs_syscall_wrapper)(CLG_(pre_syscalltime),
CLG_(post_syscalltime));
=20
- VG_(track_thread_run) ( & CLG_(run_thread) );
+ VG_(track_thread_runstate) ( & clg_thread_runstate_callback );
VG_(track_pre_deliver_signal) ( & CLG_(pre_signal) );
VG_(track_post_deliver_signal) ( & CLG_(post_signal) );
=20
Modified: trunk/coregrind/m_scheduler/scheduler.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_scheduler/scheduler.c 2006-12-18 17:53:13 UTC (rev =
6412)
+++ trunk/coregrind/m_scheduler/scheduler.c 2006-12-23 01:21:12 UTC (rev =
6413)
@@ -233,10 +233,6 @@
VG_(sprintf)(buf, " acquired lock (%s)", who);
print_sched_event(tid, buf);
}
-
- // While thre modeling is disable, issue thread_run events here
- // VG_(tm_thread_switchto)(tid);
- VG_TRACK( thread_run, tid );
}
=20
/*=20
@@ -616,6 +612,9 @@
VG_(printf)("\n");
}
=20
+ // Tell the tool this thread is about to run client code
+ VG_TRACK( thread_runstate, tid, True, bbs_done );
+
vg_assert(VG_(in_generated_code) =3D=3D False);
VG_(in_generated_code) =3D True;
=20
@@ -641,6 +640,9 @@
vg_assert(done_this_time >=3D 0);
bbs_done +=3D (ULong)done_this_time;
=20
+ // Tell the tool this thread has stopped running client code
+ VG_TRACK( thread_runstate, tid, False, bbs_done );
+
return trc;
}
=20
@@ -652,6 +654,7 @@
volatile Int jumped;
volatile ThreadState* tst;=20
volatile UWord argblock[4];
+ volatile UInt retval;
=20
/* Paranoia */
vg_assert(VG_(is_valid_tid)(tid));
@@ -686,6 +689,9 @@
argblock[2] =3D 0; /* next guest IP is written here */
argblock[3] =3D 0; /* guest state ptr afterwards is written here */
=20
+ // Tell the tool this thread is about to run client code
+ VG_TRACK( thread_runstate, tid, True, bbs_done );
+
vg_assert(VG_(in_generated_code) =3D=3D False);
VG_(in_generated_code) =3D True;
=20
@@ -703,16 +709,23 @@
vg_assert(argblock[2] =3D=3D 0); /* next guest IP was not written =
*/
vg_assert(argblock[3] =3D=3D 0); /* trc was not written */
block_signals(tid);
- return VG_TRC_FAULT_SIGNAL;
+ retval =3D VG_TRC_FAULT_SIGNAL;
} else {
/* store away the guest program counter */
VG_(set_IP)( tid, argblock[2] );
if (argblock[3] =3D=3D argblock[1])
/* the guest state pointer afterwards was unchanged */
- return VG_TRC_BORING;
+ retval =3D VG_TRC_BORING;
else
- return (UInt)argblock[3];
+ retval =3D (UInt)argblock[3];
}
+
+ bbs_done++;
+
+ // Tell the tool this thread has stopped running client code
+ VG_TRACK( thread_runstate, tid, False, bbs_done );
+
+ return retval;
}
=20
=20
Modified: trunk/coregrind/m_tooliface.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_tooliface.c 2006-12-18 17:53:13 UTC (rev 6412)
+++ trunk/coregrind/m_tooliface.c 2006-12-23 01:21:12 UTC (rev 6413)
@@ -321,7 +321,7 @@
=20
DEF(track_post_reg_write_clientcall_return, ThreadId, OffT, SizeT, Addr)
=20
-DEF(track_thread_run, ThreadId)
+DEF(track_thread_runstate, ThreadId, Bool, ULong)
=20
DEF(track_post_thread_create, ThreadId, ThreadId)
DEF(track_post_thread_join, ThreadId, ThreadId)
Modified: trunk/coregrind/pub_core_tooliface.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_tooliface.h 2006-12-18 17:53:13 UTC (rev 641=
2)
+++ trunk/coregrind/pub_core_tooliface.h 2006-12-23 01:21:12 UTC (rev 641=
3)
@@ -200,7 +200,7 @@
void (*track_post_reg_write)(CorePart, ThreadId, OffT, SizeT);
void (*track_post_reg_write_clientcall_return)(ThreadId, OffT, SizeT,=
Addr);
=20
- void (*track_thread_run)(ThreadId);
+ void (*track_thread_runstate)(ThreadId, Bool, ULong);
=20
void (*track_post_thread_create)(ThreadId, ThreadId);
void (*track_post_thread_join) (ThreadId, ThreadId);
Modified: trunk/include/pub_tool_tooliface.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_tooliface.h 2006-12-18 17:53:13 UTC (rev 6412)
+++ trunk/include/pub_tool_tooliface.h 2006-12-23 01:21:12 UTC (rev 6413)
@@ -537,9 +537,21 @@
=20
=20
/* Scheduler events (not exhaustive) */
-void VG_(track_thread_run)(void(*f)(ThreadId tid));
=20
+/* Called when 'tid' starts or stops running client code blocks.
+ Gives the total dispatched block count at that event. Note, this
+ is not the same as 'tid' holding the BigLock: a thread can hold the
+ lock for other purposes (making translations, etc) yet not be
+ running client blocks. Obviously though, a thread must hold the
+ lock in order to run client code blocks, so the times bracketed by
+ thread_runstate(tid, True, ..) .. thread_runstate(tid, False, ..)
+ are a subset of the times when 'tid' holds the cpu lock.
+*/
+void VG_(track_thread_runstate)(
+ void(*f)(ThreadId tid, Bool running, ULong blocks_dispatched)
+ );
=20
+
/* Thread events (not exhaustive)
=20
Called during thread create, before the new thread has run any
|
|
From: Nicholas N. <nj...@cs...> - 2006-12-23 06:00:33
|
On Sat, 23 Dec 2006 sv...@va... wrote:
> Log:
> Change the core-tool interface 'thread_run' event to be more useful:
>
> - Rename the event to 'thread_runstate'.
>
> - Add arguments: pass also a boolean indicating whether the thread
> is running or stopping, and a 64-bit int showing how many blocks
> overall have run, so tools can make a rough estimate of workload.
>
> The boolean allows tools to see threads starting and stopping.
> Prior to this, de-schedule events were invisible to tools.
Running and stopping are quite different. I imagine most tools are always
going to have event handlers like this:
if (is_running)
do_stuff_1
else
do_stuff_2
I think it would be better to split this into two separate events, "run" and
"stop".
This would better match how the events are currently structured -- for
example, Memcheck calls a common handler function for some closely-related
events, eg. some of the new_mem_*/die_mem_* functions.
Nick
|
|
From: Nicholas N. <nj...@cs...> - 2006-12-24 00:06:40
Attachments:
diff
|
On Sat, 23 Dec 2006, Nicholas Nethercote wrote: >> Log: >> Change the core-tool interface 'thread_run' event to be more useful: >> >> - Rename the event to 'thread_runstate'. >> >> - Add arguments: pass also a boolean indicating whether the thread >> is running or stopping, and a 64-bit int showing how many blocks >> overall have run, so tools can make a rough estimate of workload. >> >> The boolean allows tools to see threads starting and stopping. >> Prior to this, de-schedule events were invisible to tools. > > Running and stopping are quite different. I imagine most tools are always > going to have event handlers like this: > > if (is_running) > do_stuff_1 > else > do_stuff_2 > > I think it would be better to split this into two separate events, "run" and > "stop". Attached is a patch. I renamed the events "start_client_code" and "stop_client_code" since that seems a better description. I'll commit in the next day or two if nobody objects. Nick |
|
From: Josef W. <Jos...@gm...> - 2006-12-24 00:12:03
|
On Sunday 24 December 2006 01:06, Nicholas Nethercote wrote: > > I think it would be better to split this into two separate events, "run" and > > "stop". I agree. > Attached is a patch. I renamed the events "start_client_code" and > "stop_client_code" since that seems a better description. I'll commit in > the next day or two if nobody objects. Looks fine. Merry Xmas, Josef > > Nick |