]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Change the core-tool interface 'thread_run' event to be more useful:
authorJulian Seward <jseward@acm.org>
Sat, 23 Dec 2006 01:21:12 +0000 (01:21 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 23 Dec 2006 01:21:12 +0000 (01:21 +0000)
- 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'
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.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6413

callgrind/main.c
coregrind/m_scheduler/scheduler.c
coregrind/m_tooliface.c
coregrind/pub_core_tooliface.h
include/pub_tool_tooliface.h

index 4bae4e022bd13067361d661a822d3394f13697d8..b54b72cc4f0341b6d5b7655c4f008f815cbf8e3b 100644 (file)
@@ -1022,6 +1022,19 @@ void CLG_(fini)(Int exitcode)
 /*--- Setup                                                        ---*/
 /*--------------------------------------------------------------------*/
 
+static void clg_thread_runstate_callback ( ThreadId tid,
+                                           Bool is_running, 
+                                           ULong blocks_done )
+{
+   if (0)
+      VG_(printf)("%d %c %llu\n", 
+                  (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 @@ void CLG_(pre_clo_init)(void)
     VG_(needs_syscall_wrapper)(CLG_(pre_syscalltime),
                               CLG_(post_syscalltime));
 
-    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) );
 
index e439e4994b10d875870dbdcf69a59f64c18e44f4..27bff8989d0bca899fdaabb9ecb56e16022d48c1 100644 (file)
@@ -233,10 +233,6 @@ void VG_(acquire_BigLock)(ThreadId tid, HChar* who)
       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 );
 }
 
 /* 
@@ -616,6 +612,9 @@ static UInt run_thread_for_a_while ( ThreadId tid )
       VG_(printf)("\n");
    }
 
+   // 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) == False);
    VG_(in_generated_code) = True;
 
@@ -641,6 +640,9 @@ static UInt run_thread_for_a_while ( ThreadId tid )
    vg_assert(done_this_time >= 0);
    bbs_done += (ULong)done_this_time;
 
+   // Tell the tool this thread has stopped running client code
+   VG_TRACK( thread_runstate, tid, False, bbs_done );
+
    return trc;
 }
 
@@ -652,6 +654,7 @@ static UInt run_noredir_translation ( Addr hcode, ThreadId tid )
    volatile Int          jumped;
    volatile ThreadState* tst; 
    volatile UWord        argblock[4];
+   volatile UInt         retval;
 
    /* Paranoia */
    vg_assert(VG_(is_valid_tid)(tid));
@@ -686,6 +689,9 @@ static UInt run_noredir_translation ( Addr hcode, ThreadId tid )
    argblock[2] = 0; /* next guest IP is written here */
    argblock[3] = 0; /* guest state ptr afterwards is written here */
 
+   // 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) == False);
    VG_(in_generated_code) = True;
 
@@ -703,16 +709,23 @@ static UInt run_noredir_translation ( Addr hcode, ThreadId tid )
       vg_assert(argblock[2] == 0); /* next guest IP was not written */
       vg_assert(argblock[3] == 0); /* trc was not written */
       block_signals(tid);
-      return VG_TRC_FAULT_SIGNAL;
+      retval = VG_TRC_FAULT_SIGNAL;
    } else {
       /* store away the guest program counter */
       VG_(set_IP)( tid, argblock[2] );
       if (argblock[3] == argblock[1])
          /* the guest state pointer afterwards was unchanged */
-         return VG_TRC_BORING;
+         retval = VG_TRC_BORING;
       else
-         return (UInt)argblock[3];
+         retval = (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;
 }
 
 
index 843ac5b1090afc822b89e94825e6851184c6f4fb..4dbf196ca8b3828be7268462a3c0661afbedc3ee 100644 (file)
@@ -321,7 +321,7 @@ DEF(track_post_reg_write,        CorePart, ThreadId,        OffT, SizeT)
 
 DEF(track_post_reg_write_clientcall_return, ThreadId, OffT, SizeT, Addr)
 
-DEF(track_thread_run,            ThreadId)
+DEF(track_thread_runstate,       ThreadId, Bool, ULong)
 
 DEF(track_post_thread_create,    ThreadId, ThreadId)
 DEF(track_post_thread_join,      ThreadId, ThreadId)
index bde51bdef86b80348293e4268af48dd0b813d4b8..603dee1d31fae842ef28cc753f80846d4520fd26 100644 (file)
@@ -200,7 +200,7 @@ typedef struct {
    void (*track_post_reg_write)(CorePart, ThreadId,        OffT, SizeT);
    void (*track_post_reg_write_clientcall_return)(ThreadId, OffT, SizeT, Addr);
 
-   void (*track_thread_run)(ThreadId);
+   void (*track_thread_runstate)(ThreadId, Bool, ULong);
 
    void (*track_post_thread_create)(ThreadId, ThreadId);
    void (*track_post_thread_join)  (ThreadId, ThreadId);
index be530a4b1eaf6690ec1b6e207c1116119de2a484..a3f1b6ce4b770af09104c0858215d2c217048302 100644 (file)
@@ -537,7 +537,19 @@ void VG_(track_post_reg_write_clientcall_return)(
 
 
 /* Scheduler events (not exhaustive) */
-void VG_(track_thread_run)(void(*f)(ThreadId tid));
+
+/* 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)
+     );
 
 
 /* Thread events (not exhaustive)