Merge (from branches/THRCHECK) the following two changes to the core-tool
interface:

r6805: Modify two thread-notification events in the core-tool
interface.  This removes track_post_thread_create and
track_post_thread_join.  The core can only see low level thread
creation and exiting, and has no idea about pthread-level concepts
like "pthread_create" and "pthread_join", so these are a bit
ambiguous.

Replace them with track_pre_thread_ll_create, which is notified before
a new thread makes any memory references, and
track_pre_thread_ll_exit, which is notified just before the new thread
exits, that is, after it has made its last memory reference.

r6823: Core-tool interface: give 'needs_tool_errors' an extra Boolean
indicating whether or not the core should print thread id's on error
messages.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7123 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c
index 40e91fc..b719dcb 100644
--- a/coregrind/m_errormgr.c
+++ b/coregrind/m_errormgr.c
@@ -293,7 +293,8 @@
    }
 
    if (!VG_(clo_xml)) {
-      if (err->tid > 0 && err->tid != last_tid_printed) {
+     if (VG_(tdict).tool_show_ThreadIDs_for_errors
+         && err->tid > 0 && err->tid != last_tid_printed) {
          VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
          last_tid_printed = err->tid;
       }
@@ -380,7 +381,7 @@
    err->count    = 1;
    err->tid      = tid;
    if (NULL == where)
-      err->where = VG_(record_ExeContext)( tid );
+     err->where = VG_(record_ExeContext)( tid, 0 );
    else
       err->where = where;
 
diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
index 335a112..1c1d24b 100644
--- a/coregrind/m_syswrap/syswrap-amd64-linux.c
+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
@@ -267,6 +267,12 @@
       ctst->client_stack_szB  = 0;
    }
 
+   /* Assume the clone will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  If the clone
+      fails, we'll send out a ll_exit notification for it at the out:
+      label below, to clean up. */
+   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
    if (flags & VKI_CLONE_SETTLS) {
       if (debug)
 	 VG_(printf)("clone child has SETTLS: tls at %p\n", tlsaddr);
@@ -292,6 +298,8 @@
       /* clone failed */
       VG_(cleanup_thread)(&ctst->arch);
       ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
    }
 
    return res;
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 71cc34c..88b160c 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -78,8 +78,6 @@
       VG_(printf)("thread tid %d started: stack = %p\n",
 		  tid, &tid);
 
-   VG_TRACK ( post_thread_create, tst->os_state.parent, tid );
-
    tst->os_state.lwpid = VG_(gettid)();
    tst->os_state.threadgroup = VG_(getpid)();
 
@@ -128,6 +126,9 @@
    c = VG_(count_living_threads)();
    vg_assert(c >= 1); /* stay sane */
 
+   // Tell the tool this thread is exiting
+   VG_TRACK( pre_thread_ll_exit, tid );
+
    if (c == 1) {
 
       VG_(debugLog)(1, "syswrap-linux", 
diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c
index faec292..9426d0b 100644
--- a/coregrind/m_syswrap/syswrap-ppc32-linux.c
+++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c
@@ -313,6 +313,12 @@
       ctst->client_stack_szB  = 0;
    }
 
+   /* Assume the clone will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  If the clone
+      fails, we'll send out a ll_exit notification for it at the out:
+      label below, to clean up. */
+   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
    if (flags & VKI_CLONE_SETTLS) {
       if (debug)
          VG_(printf)("clone child has SETTLS: tls at %p\n", child_tls);
@@ -344,6 +350,8 @@
       /* clone failed */
       VG_(cleanup_thread)(&ctst->arch);
       ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
    }
 
    return res;
diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c
index 6907401..9ebe705 100644
--- a/coregrind/m_syswrap/syswrap-ppc64-linux.c
+++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c
@@ -341,6 +341,12 @@
       ctst->client_stack_szB  = 0;
    }
 
+   /* Assume the clone will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  If the clone
+      fails, we'll send out a ll_exit notification for it at the out:
+      label below, to clean up. */
+   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
    if (flags & VKI_CLONE_SETTLS) {
       if (debug)
          VG_(printf)("clone child has SETTLS: tls at %p\n", child_tls);
@@ -374,6 +380,8 @@
       /* clone failed */
       VG_(cleanup_thread)(&ctst->arch);
       ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
    }
 
    return res;
diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
index 6a94865..001d2a8 100644
--- a/coregrind/m_syswrap/syswrap-x86-linux.c
+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
@@ -279,6 +279,15 @@
       ctst->client_stack_szB  = 0;
    }
 
+   /* Assume the clone will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  We cannot defer
+      it beyond this point because sys_set_thread_area, just below,
+      causes tCheck to assert by making references to the new ThreadId
+      if we don't state the new thread exists prior to that point.
+      If the clone fails, we'll send out a ll_exit notification for it
+      at the out: label below, to clean up. */
+   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
    if (flags & VKI_CLONE_SETTLS) {
       if (debug)
 	 VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d "
@@ -311,6 +320,8 @@
       /* clone failed */
       VG_(cleanup_thread)(&ctst->arch);
       ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
    }
 
    return res;
diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c
index a5b8fbb..b7440ca 100644
--- a/coregrind/m_tooliface.c
+++ b/coregrind/m_tooliface.c
@@ -176,6 +176,7 @@
 void VG_(needs_tool_errors)(
    Bool (*eq)         (VgRes, Error*, Error*),
    void (*pp)         (Error*),
+   Bool show_TIDs,
    UInt (*update)     (Error*),
    Bool (*recog)      (Char*, Supp*),
    Bool (*read_extra) (Int, Char*, Int, Supp*),
@@ -187,6 +188,7 @@
    VG_(needs).tool_errors = True;
    VG_(tdict).tool_eq_Error                     = eq;
    VG_(tdict).tool_pp_Error                     = pp;
+   VG_(tdict).tool_show_ThreadIDs_for_errors    = show_TIDs;
    VG_(tdict).tool_update_extra                 = update;
    VG_(tdict).tool_recognised_suppression       = recog;
    VG_(tdict).tool_read_extra_suppression_info  = read_extra;
@@ -332,8 +334,8 @@
 DEF(track_start_client_code,     ThreadId, ULong)
 DEF(track_stop_client_code,      ThreadId, ULong)
 
-DEF(track_post_thread_create,    ThreadId, ThreadId)
-DEF(track_post_thread_join,      ThreadId, ThreadId)
+DEF(track_pre_thread_ll_create,  ThreadId, ThreadId)
+DEF(track_pre_thread_ll_exit,    ThreadId)
 
 DEF(track_pre_deliver_signal,    ThreadId, Int sigNo, Bool)
 DEF(track_post_deliver_signal,   ThreadId, Int sigNo)
diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h
index 3fa45c4..f6690fe 100644
--- a/coregrind/pub_core_tooliface.h
+++ b/coregrind/pub_core_tooliface.h
@@ -118,6 +118,7 @@
    // VG_(needs).tool_errors
    Bool  (*tool_eq_Error)                    (VgRes, Error*, Error*);
    void  (*tool_pp_Error)                    (Error*);
+   Bool  tool_show_ThreadIDs_for_errors;
    UInt  (*tool_update_extra)                (Error*);
    Bool  (*tool_recognised_suppression)      (Char*, Supp*);
    Bool  (*tool_read_extra_suppression_info) (Int, Char*, Int, Supp*);
@@ -207,8 +208,8 @@
    void (*track_start_client_code)(ThreadId, ULong);
    void (*track_stop_client_code) (ThreadId, ULong);
 
-   void (*track_post_thread_create)(ThreadId, ThreadId);
-   void (*track_post_thread_join)  (ThreadId, ThreadId);
+   void (*track_pre_thread_ll_create)(ThreadId, ThreadId);
+   void (*track_pre_thread_ll_exit)  (ThreadId);
 
    void (*track_pre_deliver_signal) (ThreadId, Int sigNo, Bool);
    void (*track_post_deliver_signal)(ThreadId, Int sigNo);
diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h
index f2012dc..b836833 100644
--- a/include/pub_tool_tooliface.h
+++ b/include/pub_tool_tooliface.h
@@ -303,6 +303,9 @@
    // Print error context.
    void (*pp_Error)(Error* err),
 
+   // Should the core indicate which ThreadId each error comes from?
+   Bool show_ThreadIDs_for_errors,
+
    // Should fill in any details that could be postponed until after the
    // decision whether to ignore the error (ie. details not affecting the
    // result of VG_(tdict).tool_eq_Error()).  This saves time when errors
@@ -544,13 +547,14 @@
 /* Scheduler events (not exhaustive) */
 
 /* 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 (the lock that ensures that
-   only one thread runs at a time): 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_run'..'thread_runstate'
-   are a subset of the times when thread 'tid' holds the cpu lock.
+   Gives the total dispatched block count at that event.  Note, this
+   is not the same as 'tid' holding the BigLock (the lock that ensures
+   that only one thread runs at a time): 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
+   'start_client_code'..'stop_client_code' are a subset of the times
+   when thread 'tid' holds the cpu lock.
 */
 void VG_(track_start_client_code)(
         void(*f)(ThreadId tid, ULong blocks_dispatched)
@@ -562,11 +566,16 @@
 
 /* Thread events (not exhaustive)
 
-   Called during thread create, before the new thread has run any
-   instructions (or touched any memory).
- */
-void VG_(track_post_thread_create)(void(*f)(ThreadId tid, ThreadId child));
-void VG_(track_post_thread_join)  (void(*f)(ThreadId joiner, ThreadId joinee));
+   ll_create: low level thread creation.  Called before the new thread
+   has run any instructions (or touched any memory).  In fact, called
+   immediately before the new thread has come into existence; the new
+   thread can be assumed to exist when notified by this call.
+
+   ll_exit: low level thread exit.  Called after the exiting thread
+   has run its last instruction.
+*/
+void VG_(track_pre_thread_ll_create)(void(*f)(ThreadId tid, ThreadId child));
+void VG_(track_pre_thread_ll_exit)  (void(*f)(ThreadId tid));
 
 
 /* Signal events (not exhaustive)