- Moved several functions and variables from one source file to another.
- Created two new source files: drd_load_store.h and .c.
- Removed the header file drd_track.h.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9153 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_thread.c b/drd/drd_thread.c
index af137c5..8ca0547 100644
--- a/drd/drd_thread.c
+++ b/drd/drd_thread.c
@@ -24,7 +24,11 @@
 
 
 #include "drd_error.h"
+#include "drd_barrier.h"
+#include "drd_cond.h"
+#include "drd_mutex.h"
 #include "drd_segment.h"
+#include "drd_semaphore.h"
 #include "drd_suppression.h"
 #include "drd_thread.h"
 #include "pub_tool_vki.h"
@@ -66,6 +70,7 @@
 struct bitmap* s_conflict_set;
 static Bool s_trace_context_switches = False;
 static Bool s_trace_conflict_set = False;
+static Bool s_trace_fork_join = False;
 static Bool s_segment_merging = True;
 
 
@@ -73,16 +78,30 @@
 
 void thread_trace_context_switches(const Bool t)
 {
+  tl_assert(t == False || t == True);
   s_trace_context_switches = t;
 }
 
 void thread_trace_conflict_set(const Bool t)
 {
+  tl_assert(t == False || t == True);
   s_trace_conflict_set = t;
 }
 
+Bool DRD_(thread_get_trace_fork_join)(void)
+{
+  return s_trace_fork_join;
+}
+
+void DRD_(thread_set_trace_fork_join)(const Bool t)
+{
+  tl_assert(t == False || t == True);
+  s_trace_fork_join = t;
+}
+
 void thread_set_segment_merging(const Bool m)
 {
+  tl_assert(m == False || m == True);
   s_segment_merging = m;
 }
 
@@ -211,6 +230,53 @@
   return created;
 }
 
+
+/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
+/* after thread drd_joiner joined thread drd_joinee.                         */
+void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
+{
+  tl_assert(IsValidDrdThreadId(drd_joiner));
+  tl_assert(IsValidDrdThreadId(drd_joinee));
+  thread_new_segment(drd_joinee);
+  thread_combine_vc(drd_joiner, drd_joinee);
+  thread_new_segment(drd_joiner);
+
+  if (s_trace_fork_join)
+  {
+    const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
+    const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
+    const unsigned msg_size = 256;
+    char* msg;
+
+    msg = VG_(malloc)("drd.main.dptj.1", msg_size);
+    tl_assert(msg);
+    VG_(snprintf)(msg, msg_size,
+                  "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
+                  joiner, drd_joiner, joinee, drd_joinee);
+    if (joiner)
+    {
+      VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
+                    ", new vc: ");
+      vc_snprint(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
+                 thread_get_vc(drd_joiner));
+    }
+    VG_(message)(Vg_DebugMsg, "%s", msg);
+    VG_(free)(msg);
+  }
+
+  if (!  DRD_(get_check_stack_accesses)())
+  {
+    drd_finish_suppression(thread_get_stack_max(drd_joinee)
+                           - thread_get_stack_size(drd_joinee),
+                           thread_get_stack_max(drd_joinee));
+  }
+  thread_delete(drd_joinee);
+  mutex_thread_delete(drd_joinee);
+  cond_thread_delete(drd_joinee);
+  semaphore_thread_delete(drd_joinee);
+  barrier_thread_delete(drd_joinee);
+}
+
 /** Allocate the first segment for a thread. Call this just after
  *  pthread_create().
  */
@@ -272,8 +338,9 @@
   return s_threadinfo[tid].stack_size;
 }
 
-/** Clean up thread-specific data structures. Call this just after 
- *  pthread_join().
+/**
+ * Clean up thread-specific data structures. Call this just after 
+ * pthread_join().
  */
 void thread_delete(const DrdThreadId tid)
 {