- 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/Makefile.am b/drd/Makefile.am
index 19e374d..18a8844 100644
--- a/drd/Makefile.am
+++ b/drd/Makefile.am
@@ -92,12 +92,13 @@
                                         $(LIBREPLACEMALLOC_LDFLAGS_PPC64_AIX5)
 
 
-DRD_SOURCES =    \
+DRD_SOURCES =           \
   drd_barrier.c         \
   drd_clientobj.c       \
   drd_clientreq.c       \
   drd_cond.c            \
   drd_error.c           \
+  drd_load_store.c      \
   drd_main.c            \
   drd_malloc_wrappers.c \
   drd_mutex.c           \
@@ -111,12 +112,14 @@
 
 noinst_HEADERS =        \
   drd_barrier.h         \
+  drd_basics.h          \
   drd_bitmap.c          \
   drd_bitmap.h          \
   drd_clientobj.h       \
   drd_clientreq.h       \
   drd_cond.h            \
   drd_error.h           \
+  drd_load_store.h      \
   drd_malloc_wrappers.h \
   drd_mutex.h           \
   drd_rwlock.h          \
@@ -127,7 +130,6 @@
   drd_thread.c          \
   drd_thread.h          \
   drd_thread_bitmap.h   \
-  drd_track.h           \
   drd_vc.c              \
   drd_vc.h              \
   pub_drd_bitmap.h
diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c
index 29ce30b..44c662e 100644
--- a/drd/drd_clientreq.c
+++ b/drd/drd_clientreq.c
@@ -1,8 +1,7 @@
 /*
   This file is part of drd, a data race detector.
 
-  Copyright (C) 2006-2008 Bart Van Assche
-  bart.vanassche@gmail.com
+  Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
 
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
@@ -23,14 +22,14 @@
 */
 
 
+#include "drd_barrier.h"
 #include "drd_clientreq.h"
 #include "drd_cond.h"
 #include "drd_mutex.h"
+#include "drd_rwlock.h"
 #include "drd_semaphore.h"
 #include "drd_suppression.h"      // drd_start_suppression()
 #include "drd_thread.h"
-#include "drd_track.h"
-#include "drd_rwlock.h"
 #include "pub_tool_basics.h"      // Bool
 #include "pub_tool_debuginfo.h"   // VG_(describe_IP)()
 #include "pub_tool_libcassert.h"
@@ -41,52 +40,22 @@
 #include "pub_tool_tooliface.h"   // VG_(needs_...)()
 
 
-static void drd_spin_init_or_unlock(const Addr spinlock)
-{
-  struct mutex_info* mutex_p = mutex_get(spinlock);
-  if (mutex_p)
-  {
-    mutex_unlock(spinlock, mutex_type_spinlock);
-  }
-  else
-  {
-    mutex_init(spinlock, mutex_type_spinlock);
-  }
-}
+/* Local function declarations. */
 
-static void drd_pre_cond_wait(const Addr cond,
-                              const Addr mutex, const MutexT mutex_type)
-{
-  mutex_unlock(mutex, mutex_type);
-  cond_pre_wait(cond, mutex);
-}
+static
+Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret);
+static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid);
 
-static void drd_post_cond_wait(const Addr cond,
-                               const Addr mutex,
-                               const Bool took_lock)
-{
-  cond_post_wait(cond);
-  mutex_post_lock(mutex, took_lock, True);
-}
 
-static void drd_pre_cond_signal(const Addr cond)
-{
-  cond_pre_signal(cond);
-}
-
-static void drd_pre_cond_broadcast(const Addr cond)
-{
-  cond_pre_broadcast(cond);
-}
-
-/** Walk the stack up to the highest stack frame, and return the stack pointer
- *  of the highest stack frame. It is assumed that there are no more than
- *  ten stack frames above the current frame. This should be no problem
- *  since this function is either called indirectly from the _init() function
- *  in vgpreload_exp-drd-*.so or from the thread wrapper for a newly created
- *  thread. See also drd_pthread_intercepts.c.
+/**
+ * Walk the stack up to the highest stack frame, and return the stack pointer
+ * of the highest stack frame. It is assumed that there are no more than
+ * ten stack frames above the current frame. This should be no problem
+ * since this function is either called indirectly from the _init() function
+ * in vgpreload_exp-drd-*.so or from the thread wrapper for a newly created
+ * thread. See also drd_pthread_intercepts.c.
  */
-static Addr highest_used_stack_address(const ThreadId vg_tid)
+static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid)
 {
     UInt nframes;
     const UInt n_ips = 10;
@@ -122,7 +91,12 @@
     return husa;
 }
 
-static Bool drd_handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
+/**
+ * DRD's handler for Valgrind client requests. The code below handles both
+ * DRD's public and tool-internal client requests.
+ */
+static
+Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret)
 {
   UWord result = 0;
   const DrdThreadId drd_tid = thread_get_running_tid();
@@ -150,7 +124,7 @@
 
   case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK:
   {
-    const Addr topmost_sp = highest_used_stack_address(vg_tid);
+    const Addr topmost_sp = DRD_(highest_used_stack_address)(vg_tid);
 #if 0
     UInt nframes;
     const UInt n_ips = 20;
@@ -206,23 +180,21 @@
 
   case VG_USERREQ__POST_THREAD_JOIN:
     tl_assert(arg[1]);
-    drd_post_thread_join(drd_tid,
-                         PtThreadIdToDrdThreadId(arg[1]));
+    DRD_(thread_post_join)(drd_tid, PtThreadIdToDrdThreadId(arg[1]));
     break;
 
   case VG_USERREQ__PRE_THREAD_CANCEL:
     tl_assert(arg[1]);
-    drd_pre_thread_cancel(drd_tid, PtThreadIdToDrdThreadId(arg[1]));
+    thread_pre_cancel(drd_tid);
     break;
 
   case VG_USERREQ__POST_THREAD_CANCEL:
     tl_assert(arg[1]);
-    drd_post_thread_cancel(drd_tid, PtThreadIdToDrdThreadId(arg[1]), arg[2]);
     break;
 
   case VG_USERREQ__PRE_MUTEX_INIT:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_pre_mutex_init(arg[1], arg[2]);
+      mutex_init(arg[1], arg[2]);
     break;
 
   case VG_USERREQ__POST_MUTEX_INIT:
@@ -235,22 +207,22 @@
 
   case VG_USERREQ__POST_MUTEX_DESTROY:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_post_mutex_destroy(arg[1], arg[2]);
+      mutex_post_destroy(arg[1]);
     break;
 
   case VG_USERREQ__PRE_MUTEX_LOCK:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_pre_mutex_lock(arg[1], arg[2], arg[3]);
+      mutex_pre_lock(arg[1], arg[2], arg[3]);
     break;
 
   case VG_USERREQ__POST_MUTEX_LOCK:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_post_mutex_lock(arg[1], arg[2]);
+      mutex_post_lock(arg[1], arg[2], False/*post_cond_wait*/);
     break;
 
   case VG_USERREQ__PRE_MUTEX_UNLOCK:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_pre_mutex_unlock(arg[1], arg[2]);
+      mutex_unlock(arg[1], arg[2]);
     break;
 
   case VG_USERREQ__POST_MUTEX_UNLOCK:
@@ -259,7 +231,7 @@
 
   case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_spin_init_or_unlock(arg[1]);
+      DRD_(spinlock_init_or_unlock)(arg[1]);
     break;
 
   case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK:
@@ -268,7 +240,7 @@
 
   case VG_USERREQ__PRE_COND_INIT:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_pre_cond_init(arg[1]);
+      cond_pre_init(arg[1]);
     break;
 
   case VG_USERREQ__POST_COND_INIT:
@@ -281,22 +253,34 @@
 
   case VG_USERREQ__POST_COND_DESTROY:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_post_cond_destroy(arg[1]);
+      cond_post_destroy(arg[1]);
     break;
 
   case VG_USERREQ__PRE_COND_WAIT:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_pre_cond_wait(arg[1], arg[2], arg[3]);
+    {
+      const Addr cond = arg[1];
+      const Addr mutex = arg[2];
+      const MutexT mutex_type = arg[3];
+      mutex_unlock(mutex, mutex_type);
+      cond_pre_wait(cond, mutex);
+    }
     break;
 
   case VG_USERREQ__POST_COND_WAIT:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_post_cond_wait(arg[1], arg[2], arg[3]);
+    {
+      const Addr cond = arg[1];
+      const Addr mutex = arg[2];
+      const Bool took_lock = arg[3];
+      cond_post_wait(cond);
+      mutex_post_lock(mutex, took_lock, True);
+    }
     break;
 
   case VG_USERREQ__PRE_COND_SIGNAL:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_pre_cond_signal(arg[1]);
+      cond_pre_signal(arg[1]);
     break;
 
   case VG_USERREQ__POST_COND_SIGNAL:
@@ -305,7 +289,7 @@
 
   case VG_USERREQ__PRE_COND_BROADCAST:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_pre_cond_broadcast(arg[1]);
+      cond_pre_broadcast(arg[1]);
     break;
 
   case VG_USERREQ__POST_COND_BROADCAST:
@@ -314,7 +298,7 @@
 
   case VG_USERREQ__PRE_SEM_INIT:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_semaphore_init(arg[1], arg[2], arg[3]);
+      semaphore_init(arg[1], arg[2], arg[3]);
     break;
 
   case VG_USERREQ__POST_SEM_INIT:
@@ -327,32 +311,32 @@
 
   case VG_USERREQ__POST_SEM_DESTROY:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_semaphore_destroy(arg[1]);
+      semaphore_destroy(arg[1]);
     break;
 
   case VG_USERREQ__PRE_SEM_WAIT:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_semaphore_pre_wait(drd_tid, arg[1]);
+      semaphore_pre_wait(arg[1]);
     break;
 
   case VG_USERREQ__POST_SEM_WAIT:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_semaphore_post_wait(drd_tid, arg[1], arg[2]);
+      semaphore_post_wait(drd_tid, arg[1], arg[2]);
     break;
 
   case VG_USERREQ__PRE_SEM_POST:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_semaphore_pre_post(drd_tid, arg[1]);
+      semaphore_pre_post(drd_tid, arg[1]);
     break;
 
   case VG_USERREQ__POST_SEM_POST:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_semaphore_post_post(drd_tid, arg[1], arg[2]);
+      semaphore_post_post(drd_tid, arg[1], arg[2]);
     break;
 
   case VG_USERREQ__PRE_BARRIER_INIT:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_barrier_init(arg[1], arg[2], arg[3], arg[4]);
+      barrier_init(arg[1], arg[2], arg[3], arg[4]);
     break;
 
   case VG_USERREQ__POST_BARRIER_INIT:
@@ -365,17 +349,17 @@
 
   case VG_USERREQ__POST_BARRIER_DESTROY:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_barrier_destroy(arg[1], arg[2]);
+      barrier_destroy(arg[1], arg[2]);
     break;
 
   case VG_USERREQ__PRE_BARRIER_WAIT:
     if (thread_enter_synchr(drd_tid) == 0)
-      drd_barrier_pre_wait(drd_tid, arg[1], arg[2]);
+      barrier_pre_wait(drd_tid, arg[1], arg[2]);
     break;
 
   case VG_USERREQ__POST_BARRIER_WAIT:
     if (thread_leave_synchr(drd_tid) == 0)
-      drd_barrier_post_wait(drd_tid, arg[1], arg[2], arg[3]);
+      barrier_post_wait(drd_tid, arg[1], arg[2], arg[3]);
     break;
 
   case VG_USERREQ__PRE_RWLOCK_INIT:
@@ -426,7 +410,11 @@
   return True;
 }
 
-void drd_clientreq_init(void)
+/**
+ * Tell the Valgrind core the address of the DRD function that processes
+ * client requests. Must be called before any client code is run.
+ */
+void DRD_(clientreq_init)(void)
 {
-  VG_(needs_client_requests)(drd_handle_client_request);
+  VG_(needs_client_requests)(DRD_(handle_client_request));
 }
diff --git a/drd/drd_clientreq.h b/drd/drd_clientreq.h
index 3d06e71..e43d845 100644
--- a/drd/drd_clientreq.h
+++ b/drd/drd_clientreq.h
@@ -22,14 +22,27 @@
   The GNU General Public License is contained in the file COPYING.
 */
 
+/*
+ * This header file contains the tool-internal interface for the code that
+ * processes client requests.
+ */
+
 
 #ifndef __DRD_CLIENTREQ_H
 #define __DRD_CLIENTREQ_H
 
 
 #include "drd.h"
+#include "drd_basics.h" /* DRD_() */
 
 
+/*
+ * While the client requests defined in the header file "drd.h" define a
+ * public interface between client programs and the DRD tool, the client
+ * requests defined below are a tool-internal interface. These last client
+ * requests must only be used by the source code in the various *_intercepts.c
+ * source files.
+ */
 enum {
   /* Ask drd to suppress data race reports on all currently allocated stack */
   /* data of the current thread.                                            */
@@ -194,6 +207,11 @@
 
 };
 
+/*
+ * Error checking on POSIX recursive mutexes, POSIX error checking mutexes,
+ * POSIX default mutexes and POSIX spinlocks happens by the same code. The
+ * values defined below specify which of these types a mutex really is.
+ */
 typedef enum
 {
   mutex_type_unknown          = -1,
@@ -204,13 +222,19 @@
   mutex_type_spinlock         = 4
 } MutexT;
 
+/*
+ * Error checking on POSIX barriers and GOMP barriers happens by the same
+ * code. The integer values defined below specify the type of a barrier with
+ * a given client address.
+ */
 typedef enum
   {
     pthread_barrier = 1,
     gomp_barrier = 2
   } BarrierT;
 
-void drd_clientreq_init(void);
+
+void DRD_(clientreq_init)(void);
 
 
 #endif //  __DRD_CLIENTREQ_H
diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c
new file mode 100644
index 0000000..160b356
--- /dev/null
+++ b/drd/drd_load_store.c
@@ -0,0 +1,547 @@
+/*
+  This file is part of drd, a data race detector.
+
+  Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_bitmap.h"
+#include "drd_thread_bitmap.h"
+
+/* Include several source files here in order to allow the compiler to */
+/* do more inlining.                                                   */
+#include "drd_bitmap.c"
+#include "drd_load_store.h"
+#include "drd_segment.c"
+#include "drd_thread.c"
+#include "drd_vc.c"
+#include "libvex_guest_offsets.h"
+
+
+/* STACK_POINTER_OFFSET: VEX register offset for the stack pointer register. */
+#if defined(VGA_x86)
+#define STACK_POINTER_OFFSET OFFSET_x86_ESP
+#elif defined(VGA_amd64)
+#define STACK_POINTER_OFFSET OFFSET_amd64_RSP
+#elif defined(VGA_ppc32)
+#define STACK_POINTER_OFFSET ((OFFSET_ppc32_GPR0 + OFFSET_ppc32_GPR2) / 2)
+#elif defined(VGA_ppc64)
+#define STACK_POINTER_OFFSET ((OFFSET_ppc64_GPR0 + OFFSET_ppc64_GPR2) / 2)
+#else
+#error Unknown architecture.
+#endif
+
+
+/* Local variables. */
+
+static Bool s_drd_check_stack_accesses = False;
+
+
+/* Function definitions. */
+
+Bool DRD_(get_check_stack_accesses)()
+{
+  return s_drd_check_stack_accesses;
+}
+
+void DRD_(set_check_stack_accesses)(const Bool c)
+{
+  tl_assert(c == False || c == True);
+  s_drd_check_stack_accesses = c;
+}
+
+void drd_trace_mem_access(const Addr addr, const SizeT size,
+                          const BmAccessTypeT access_type)
+{
+  if (drd_is_any_traced(addr, addr + size))
+  {
+    char vc[80];
+    vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid()));
+    VG_(message)(Vg_UserMsg,
+                 "%s 0x%lx size %ld (vg %d / drd %d / vc %s)",
+                 access_type == eLoad
+                 ? "load "
+                 : access_type == eStore
+                 ? "store"
+                 : access_type == eStart
+                 ? "start"
+                 : access_type == eEnd
+                 ? "end  "
+                 : "????",
+                 addr,
+                 size,
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 vc);
+    VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
+                               VG_(clo_backtrace_size));
+    tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
+              == VG_(get_running_tid)());
+  }
+}
+
+static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
+{
+  return drd_trace_mem_access(addr, size, eLoad);
+}
+
+static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
+{
+  return drd_trace_mem_access(addr, size, eStore);
+}
+
+static void drd_report_race(const Addr addr, const SizeT size,
+                            const BmAccessTypeT access_type)
+{
+  DataRaceErrInfo drei;
+
+  drei.tid  = thread_get_running_tid();
+  drei.addr = addr;
+  drei.size = size;
+  drei.access_type = access_type;
+  VG_(maybe_record_error)(VG_(get_running_tid)(),
+                          DataRaceErr,
+                          VG_(get_IP)(VG_(get_running_tid)()),
+                          "Conflicting accesses",
+                          &drei);
+}
+
+VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+  /* The assert below has been commented out because of performance reasons.*/
+  tl_assert(thread_get_running_tid()
+            == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
+#endif
+
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_load_triggers_conflict(addr, addr + size)
+      && ! drd_is_suppressed(addr, addr + size))
+  {
+    drd_report_race(addr, size, eLoad);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_load_1_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 1))
+  {
+    drd_report_race(addr, 1, eLoad);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_load_2_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 2))
+  {
+    drd_report_race(addr, 2, eLoad);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_load_4_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 4))
+  {
+    drd_report_race(addr, 4, eLoad);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_load_8_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 8))
+  {
+    drd_report_race(addr, 8, eLoad);
+  }
+}
+
+VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+  /* The assert below has been commented out because of performance reasons.*/
+  tl_assert(thread_get_running_tid()
+            == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
+#endif
+
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_store_triggers_conflict(addr, addr + size)
+      && ! drd_is_suppressed(addr, addr + size))
+  {
+    drd_report_race(addr, size, eStore);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_store_1_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 1))
+  {
+    drd_report_race(addr, 1, eStore);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_store_2_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 2))
+  {
+    drd_report_race(addr, 2, eStore);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_store_4_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 4))
+  {
+    drd_report_race(addr, 4, eStore);
+  }
+}
+
+static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
+{
+  if (running_thread_is_recording()
+      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
+      && bm_access_store_8_triggers_conflict(addr)
+      && ! drd_is_suppressed(addr, addr + 8))
+  {
+    drd_report_race(addr, 8, eStore);
+  }
+}
+
+/**
+ * Return true if and only if addr_expr matches the pattern (SP) or
+ * <offset>(SP).
+ */
+static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
+{
+  Bool result = False;
+
+  if (addr_expr->tag == Iex_RdTmp)
+  {
+    int i;
+    for (i = 0; i < bb->stmts_size; i++)
+    {
+      if (bb->stmts[i]
+          && bb->stmts[i]->tag == Ist_WrTmp
+          && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
+      {
+        IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
+        if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
+        {
+          result = True;
+        }
+
+        //ppIRExpr(e);
+        //VG_(printf)(" (%s)\n", result ? "True" : "False");
+        break;
+      }
+    }
+  }
+  return result;
+}
+
+static void instrument_load(IRSB* const bb,
+                            IRExpr* const addr_expr,
+                            const HWord size)
+{
+  IRExpr* size_expr;
+  IRExpr** argv;
+  IRDirty* di;
+
+  if (UNLIKELY(drd_any_address_is_traced()))
+  {
+    addStmtToIRSB(bb,
+		  IRStmt_Dirty(
+		    unsafeIRDirty_0_N(/*regparms*/2,
+				      "drd_trace_load",
+				      VG_(fnptr_to_fnentry)
+				      (drd_trace_mem_load),
+				      mkIRExprVec_2(addr_expr,
+						    mkIRExpr_HWord(size)))));
+  }
+
+  if (! s_drd_check_stack_accesses && is_stack_access(bb, addr_expr))
+    return;
+
+  switch (size)
+  {
+  case 1:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_load_1",
+                           VG_(fnptr_to_fnentry)(drd_trace_load_1),
+                           argv);
+    break;
+  case 2:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_load_2",
+                           VG_(fnptr_to_fnentry)(drd_trace_load_2),
+                           argv);
+    break;
+  case 4:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_load_4",
+                           VG_(fnptr_to_fnentry)(drd_trace_load_4),
+                           argv);
+    break;
+  case 8:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_load_8",
+                           VG_(fnptr_to_fnentry)(drd_trace_load_8),
+                           argv);
+    break;
+  default:
+    size_expr = mkIRExpr_HWord(size);
+    argv = mkIRExprVec_2(addr_expr, size_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/2,
+                           "drd_trace_load",
+                           VG_(fnptr_to_fnentry)(drd_trace_load),
+                           argv);
+    break;
+  }
+  addStmtToIRSB(bb, IRStmt_Dirty(di));
+}
+
+static void instrument_store(IRSB* const bb,
+                             IRExpr* const addr_expr,
+                             const HWord size)
+{
+  IRExpr* size_expr;
+  IRExpr** argv;
+  IRDirty* di;
+
+  if (UNLIKELY(drd_any_address_is_traced()))
+  {
+    addStmtToIRSB(bb,
+		  IRStmt_Dirty(
+		    unsafeIRDirty_0_N(/*regparms*/2,
+				      "drd_trace_store",
+				      VG_(fnptr_to_fnentry)
+				      (drd_trace_mem_store),
+				      mkIRExprVec_2(addr_expr,
+						    mkIRExpr_HWord(size)))));
+  }
+
+  if (! s_drd_check_stack_accesses && is_stack_access(bb, addr_expr))
+    return;
+
+  switch (size)
+  {
+  case 1:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_store_1",
+                           VG_(fnptr_to_fnentry)(drd_trace_store_1),
+                           argv);
+    break;
+  case 2:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_store_2",
+                           VG_(fnptr_to_fnentry)(drd_trace_store_2),
+                           argv);
+    break;
+  case 4:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_store_4",
+                           VG_(fnptr_to_fnentry)(drd_trace_store_4),
+                           argv);
+    break;
+  case 8:
+    argv = mkIRExprVec_1(addr_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/1,
+                           "drd_trace_store_8",
+                           VG_(fnptr_to_fnentry)(drd_trace_store_8),
+                           argv);
+    break;
+  default:
+    size_expr = mkIRExpr_HWord(size);
+    argv = mkIRExprVec_2(addr_expr, size_expr);
+    di = unsafeIRDirty_0_N(/*regparms*/2,
+                           "drd_trace_store",
+                           VG_(fnptr_to_fnentry)(drd_trace_store),
+                           argv);
+    break;
+  }
+  addStmtToIRSB(bb, IRStmt_Dirty(di));
+}
+
+IRSB* drd_instrument(VgCallbackClosure* const closure,
+                     IRSB* const bb_in,
+                     VexGuestLayout* const layout,
+                     VexGuestExtents* const vge, 
+                     IRType const gWordTy,
+                     IRType const hWordTy)
+{
+  IRDirty* di;
+  Int      i;
+  IRSB*    bb;
+  IRExpr** argv;
+  Bool     instrument = True;
+  Bool     bus_locked = False;
+
+  /* Set up BB */
+  bb           = emptyIRSB();
+  bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
+  bb->next     = deepCopyIRExpr(bb_in->next);
+  bb->jumpkind = bb_in->jumpkind;
+
+  for (i = 0; i < bb_in->stmts_used; i++)
+  {
+    IRStmt* const st = bb_in->stmts[i];
+    tl_assert(st);
+    if (st->tag == Ist_NoOp)
+      continue;
+
+    switch (st->tag)
+    {
+    /* Note: the code for not instrumenting the code in .plt          */
+    /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21    */
+    /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4).             */
+    /* This is because on this platform dynamic library symbols are   */
+    /* relocated in another way than by later binutils versions. The  */
+    /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
+    case Ist_IMark:
+      instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
+        != Vg_SectPLT;
+      addStmtToIRSB(bb, st);
+      break;
+
+    case Ist_MBE:
+      switch (st->Ist.MBE.event)
+      {
+      case Imbe_Fence:
+        break; /* not interesting */
+      case Imbe_BusLock:
+      case Imbe_SnoopedStoreBegin:
+        tl_assert(! bus_locked);
+        bus_locked = True;
+        break;
+      case Imbe_BusUnlock:
+      case Imbe_SnoopedStoreEnd:
+        tl_assert(bus_locked);
+        bus_locked = False;
+        break;
+      default:
+        tl_assert(0);
+      }
+      addStmtToIRSB(bb, st);
+      break;
+
+    case Ist_Store:
+      if (instrument && ! bus_locked)
+      {
+        instrument_store(bb,
+                         st->Ist.Store.addr,
+                         sizeofIRType(typeOfIRExpr(bb->tyenv,
+                                                   st->Ist.Store.data)));
+      }
+      addStmtToIRSB(bb, st);
+      break;
+
+    case Ist_WrTmp:
+      if (instrument)
+      {
+        const IRExpr* const data = st->Ist.WrTmp.data;
+        if (data->tag == Iex_Load)
+        {
+          instrument_load(bb,
+                          data->Iex.Load.addr,
+                          sizeofIRType(data->Iex.Load.ty));
+        }
+      }
+      addStmtToIRSB(bb, st);
+      break;
+
+    case Ist_Dirty:
+      if (instrument)
+      {
+        IRDirty* d = st->Ist.Dirty.details;
+        IREffect const mFx = d->mFx;
+        switch (mFx) {
+        case Ifx_None:
+          break;
+        case Ifx_Read:
+        case Ifx_Write:
+        case Ifx_Modify:
+          tl_assert(d->mAddr);
+          tl_assert(d->mSize > 0);
+          argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
+          if (mFx == Ifx_Read || mFx == Ifx_Modify) {
+            di = unsafeIRDirty_0_N(
+                                   /*regparms*/2,
+                                   "drd_trace_load",
+                                   VG_(fnptr_to_fnentry)(drd_trace_load),
+                                   argv);
+            addStmtToIRSB(bb, IRStmt_Dirty(di));
+          }
+          if ((mFx == Ifx_Write || mFx == Ifx_Modify)
+              && ! bus_locked)
+          {
+            di = unsafeIRDirty_0_N(
+                                   /*regparms*/2,
+                                   "drd_trace_store",
+                                   VG_(fnptr_to_fnentry)(drd_trace_store),
+                                   argv);
+            addStmtToIRSB(bb, IRStmt_Dirty(di));
+          }
+          break;
+        default:
+          tl_assert(0);
+        }
+      }
+      addStmtToIRSB(bb, st);
+      break;
+
+    default:
+      addStmtToIRSB(bb, st);
+      break;
+    }
+  }
+
+  tl_assert(! bus_locked);
+
+  return bb;
+}
+
diff --git a/drd/drd_load_store.h b/drd/drd_load_store.h
new file mode 100644
index 0000000..f820555
--- /dev/null
+++ b/drd/drd_load_store.h
@@ -0,0 +1,52 @@
+/*
+  This file is part of drd, a data race detector.
+
+  Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/*
+ * Functions related to instrumentation of loads and stores.
+ */
+
+
+#ifndef __DRD_LOAD_STORE_H
+#define __DRD_LOAD_STORE_H
+
+
+#include <libvex.h>             /* IRSB */
+#include <pub_tool_tooliface.h> /* VgCallbackClosure */
+
+
+Bool DRD_(get_check_stack_accesses)(void);
+void DRD_(set_check_stack_accesses)(const Bool c);
+IRSB* drd_instrument(VgCallbackClosure* const closure,
+                     IRSB* const bb_in,
+                     VexGuestLayout* const layout,
+                     VexGuestExtents* const vge, 
+                     IRType const gWordTy,
+                     IRType const hWordTy);
+void drd_trace_mem_access(const Addr addr, const SizeT size,
+                          const BmAccessTypeT access_type);
+VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size);
+VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size);
+
+
+#endif //  __DRD_LOAD_STORE_H
diff --git a/drd/drd_main.c b/drd/drd_main.c
index 4b8cdc2..a051711 100644
--- a/drd/drd_main.c
+++ b/drd/drd_main.c
@@ -1,8 +1,7 @@
 /*
   This file is part of drd, a data race detector.
 
-  Copyright (C) 2006-2008 Bart Van Assche
-  bart.vanassche@gmail.com
+  Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
 
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
@@ -24,10 +23,11 @@
 
 
 #include "drd_barrier.h"
-#include "drd_clientreq.h"
 #include "drd_clientobj.h"
+#include "drd_clientreq.h"
 #include "drd_cond.h"
 #include "drd_error.h"
+#include "drd_load_store.h"
 #include "drd_malloc_wrappers.h"
 #include "drd_mutex.h"
 #include "drd_rwlock.h"
@@ -35,8 +35,6 @@
 #include "drd_semaphore.h"
 #include "drd_suppression.h"
 #include "drd_thread.h"
-#include "drd_thread_bitmap.h"
-#include "drd_track.h"
 #include "drd_vc.h"
 #include "libvex_guest_offsets.h"
 #include "pub_drd_bitmap.h"
@@ -55,15 +53,6 @@
 #include "pub_tool_tooliface.h"
 
 
-/* Include several source files here in order to allow the compiler to */
-/* do more inlining.                                                   */
-#include "drd_bitmap.c"
-#include "drd_segment.c"
-#include "drd_thread.c"
-#include "drd_vc.c"
-
-
-
 // Function declarations.
 
 static void drd_start_client_code(const ThreadId tid, const ULong bbs_done);
@@ -71,9 +60,7 @@
 
 // Local variables.
 
-static Bool s_drd_check_stack_accesses = False;
 static Bool s_drd_print_stats          = False;
-static Bool s_drd_trace_fork_join      = False;
 static Bool s_drd_var_info             = False;
 static Bool s_show_stack_usage         = False;
 
@@ -84,6 +71,7 @@
 
 static Bool drd_process_cmd_line_option(Char* arg)
 {
+  int check_stack_accesses   = -1;
   int exclusive_threshold_ms = -1;
   int segment_merging        = -1;
   int shared_threshold_ms    = -1;
@@ -92,6 +80,7 @@
   int trace_clientobj        = -1;
   int trace_cond             = -1;
   int trace_csw              = -1;
+  int trace_fork_join        = -1;
   int trace_conflict_set     = -1;
   int trace_mutex            = -1;
   int trace_rwlock           = -1;
@@ -100,7 +89,7 @@
   int trace_suppression      = -1;
   Char* trace_address        = 0;
 
-  VG_BOOL_CLO     (arg, "--check-stack-var",     s_drd_check_stack_accesses)
+  VG_BOOL_CLO     (arg, "--check-stack-var",     check_stack_accesses)
   else VG_BOOL_CLO(arg, "--drd-stats",           s_drd_print_stats)
   else VG_BOOL_CLO(arg,"--report-signal-unlocked",s_drd_report_signal_unlocked)
   else VG_BOOL_CLO(arg, "--segment-merging",     segment_merging)
@@ -111,7 +100,7 @@
   else VG_BOOL_CLO(arg, "--trace-cond",          trace_cond)
   else VG_BOOL_CLO(arg, "--trace-conflict-set",  trace_conflict_set)
   else VG_BOOL_CLO(arg, "--trace-csw",           trace_csw)
-  else VG_BOOL_CLO(arg, "--trace-fork-join",     s_drd_trace_fork_join)
+  else VG_BOOL_CLO(arg, "--trace-fork-join",     trace_fork_join)
   else VG_BOOL_CLO(arg, "--trace-mutex",         trace_mutex)
   else VG_BOOL_CLO(arg, "--trace-rwlock",        trace_rwlock)
   else VG_BOOL_CLO(arg, "--trace-segment",       trace_segment)
@@ -124,6 +113,8 @@
   else
     return VG_(replacement_malloc_process_cmd_line_option)(arg);
 
+  if (check_stack_accesses != -1)
+    DRD_(set_check_stack_accesses)(check_stack_accesses);
   if (exclusive_threshold_ms != -1)
   {
     mutex_set_lock_threshold(exclusive_threshold_ms);
@@ -150,6 +141,8 @@
     cond_set_trace(trace_cond);
   if (trace_csw != -1)
     thread_trace_context_switches(trace_csw);
+  if (trace_fork_join != -1)
+    DRD_(thread_set_trace_fork_join)(trace_fork_join);
   if (trace_conflict_set != -1)
     thread_trace_conflict_set(trace_conflict_set);
   if (trace_mutex != -1)
@@ -223,185 +216,6 @@
 // Implements the thread-related core callbacks.
 //
 
-static void drd_trace_mem_access(const Addr addr, const SizeT size,
-                                 const BmAccessTypeT access_type)
-{
-  if (drd_is_any_traced(addr, addr + size))
-  {
-    char vc[80];
-    vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid()));
-    VG_(message)(Vg_UserMsg,
-                 "%s 0x%lx size %ld (vg %d / drd %d / vc %s)",
-                 access_type == eLoad
-                 ? "load "
-                 : access_type == eStore
-                 ? "store"
-                 : access_type == eStart
-                 ? "start"
-                 : access_type == eEnd
-                 ? "end  "
-                 : "????",
-                 addr,
-                 size,
-                 VG_(get_running_tid)(),
-                 thread_get_running_tid(),
-                 vc);
-    VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
-                               VG_(clo_backtrace_size));
-    tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
-              == VG_(get_running_tid)());
-  }
-}
-
-static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
-{
-  return drd_trace_mem_access(addr, size, eLoad);
-}
-
-static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
-{
-  return drd_trace_mem_access(addr, size, eStore);
-}
-
-static void drd_report_race(const Addr addr, const SizeT size,
-                            const BmAccessTypeT access_type)
-{
-  DataRaceErrInfo drei;
-
-  drei.tid  = thread_get_running_tid();
-  drei.addr = addr;
-  drei.size = size;
-  drei.access_type = access_type;
-  VG_(maybe_record_error)(VG_(get_running_tid)(),
-                          DataRaceErr,
-                          VG_(get_IP)(VG_(get_running_tid)()),
-                          "Conflicting accesses",
-                          &drei);
-}
-
-static VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
-{
-#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
-  /* The assert below has been commented out because of performance reasons.*/
-  tl_assert(thread_get_running_tid()
-            == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
-#endif
-
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_load_triggers_conflict(addr, addr + size)
-      && ! drd_is_suppressed(addr, addr + size))
-  {
-    drd_report_race(addr, size, eLoad);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_load_1_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 1))
-  {
-    drd_report_race(addr, 1, eLoad);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_load_2_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 2))
-  {
-    drd_report_race(addr, 2, eLoad);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_load_4_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 4))
-  {
-    drd_report_race(addr, 4, eLoad);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_load_8_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 8))
-  {
-    drd_report_race(addr, 8, eLoad);
-  }
-}
-
-static
-VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
-{
-#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
-  /* The assert below has been commented out because of performance reasons.*/
-  tl_assert(thread_get_running_tid()
-            == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
-#endif
-
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_store_triggers_conflict(addr, addr + size)
-      && ! drd_is_suppressed(addr, addr + size))
-  {
-    drd_report_race(addr, size, eStore);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_store_1_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 1))
-  {
-    drd_report_race(addr, 1, eStore);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_store_2_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 2))
-  {
-    drd_report_race(addr, 2, eStore);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_store_4_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 4))
-  {
-    drd_report_race(addr, 4, eStore);
-  }
-}
-
-static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
-{
-  if (running_thread_is_recording()
-      && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr))
-      && bm_access_store_8_triggers_conflict(addr)
-      && ! drd_is_suppressed(addr, addr + 8))
-  {
-    drd_report_race(addr, 8, eStore);
-  }
-}
-
 static void drd_pre_mem_read(const CorePart part,
                              const ThreadId tid,
                              Char* const s,
@@ -486,7 +300,7 @@
   {
     drd_trace_mem_access(a1, len, eEnd);
   }
-  if (! is_stack_mem || s_drd_check_stack_accesses)
+  if (! is_stack_mem || DRD_(get_check_stack_accesses)())
   {
     thread_stop_using_mem(a1, a2);
     clientobj_stop_using_mem(a1, a2);
@@ -606,7 +420,7 @@
   {
     thread_new_segment(drd_creator);
   }
-  if (s_drd_trace_fork_join)
+  if (DRD_(thread_get_trace_fork_join)())
   {
     VG_(message)(Vg_DebugMsg,
                  "drd_pre_thread_create creator = %d/%d, created = %d",
@@ -625,13 +439,13 @@
   tl_assert(vg_created != VG_INVALID_THREADID);
 
   drd_created = thread_post_create(vg_created);
-  if (s_drd_trace_fork_join)
+  if (DRD_(thread_get_trace_fork_join)())
   {
     VG_(message)(Vg_DebugMsg,
                  "drd_post_thread_create created = %d/%d",
                  vg_created, drd_created);
   }
-  if (! s_drd_check_stack_accesses)
+  if (! DRD_(get_check_stack_accesses)())
   {
     drd_start_suppression(thread_get_stack_max(drd_created)
                           - thread_get_stack_size(drd_created),
@@ -640,60 +454,6 @@
   }
 }
 
-/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
-/* after thread drd_joiner joined thread drd_joinee.                         */
-void drd_post_thread_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_drd_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 (! s_drd_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);
-}
-
-void drd_pre_thread_cancel(DrdThreadId canceling, DrdThreadId canceled)
-{
-  thread_pre_cancel(canceled);
-}
-
-void drd_post_thread_cancel(DrdThreadId canceling, DrdThreadId canceled, Bool succeeded)
-{ }
-
 /* Called after a thread has performed its last memory access. */
 static void drd_thread_finished(ThreadId vg_tid)
 {
@@ -702,7 +462,7 @@
   tl_assert(VG_(get_running_tid)() == vg_tid);
 
   drd_tid = VgThreadIdToDrdThreadId(vg_tid);
-  if (s_drd_trace_fork_join)
+  if (DRD_(thread_get_trace_fork_join)())
   {
     VG_(message)(Vg_DebugMsg,
                  "drd_thread_finished tid = %d/%d%s",
@@ -738,101 +498,6 @@
   thread_finished(drd_tid);
 }
 
-void drd_pre_mutex_init(const Addr mutex, const MutexT mutex_type)
-{
-  mutex_init(mutex, mutex_type);
-}
-
-void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
-{
-  mutex_post_destroy(mutex);
-}
-
-void drd_pre_mutex_lock(const Addr mutex, const MutexT mutex_type,
-                        const Bool trylock)
-{
-  mutex_pre_lock(mutex, mutex_type, trylock);
-}
-
-void drd_post_mutex_lock(const Addr mutex, const Bool took_lock)
-{
-  mutex_post_lock(mutex, took_lock, False);
-}
-
-void drd_pre_mutex_unlock(const Addr mutex, const MutexT mutex_type)
-{
-  mutex_unlock(mutex, mutex_type);
-}
-
-void drd_pre_cond_init(Addr cond)
-{
-  cond_pre_init(cond);
-}
-
-void drd_post_cond_destroy(Addr cond)
-{
-  cond_post_destroy(cond);
-}
-
-void drd_semaphore_init(const Addr semaphore,
-                        const Word pshared, const Word value)
-{
-  semaphore_init(semaphore, pshared, value);
-}
-
-void drd_semaphore_destroy(const Addr semaphore)
-{
-  semaphore_destroy(semaphore);
-}
-
-void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore)
-{
-  semaphore_pre_wait(semaphore);
-}
-
-void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
-                             const Bool waited)
-{
-  semaphore_post_wait(tid, semaphore, waited);
-}
-
-void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore)
-{
-  semaphore_pre_post(tid, semaphore);
-}
-
-void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
-                             const Bool waited)
-{
-  semaphore_post_post(tid, semaphore, waited);
-}
-
-
-void drd_barrier_init(const Addr barrier,
-                      const BarrierT barrier_type, const Word count,
-                      const Bool reinitialization)
-{
-  barrier_init(barrier, barrier_type, count, reinitialization);
-}
-
-void drd_barrier_destroy(const Addr barrier, const BarrierT barrier_type)
-{
-  barrier_destroy(barrier, barrier_type);
-}
-
-void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier,
-                          const BarrierT barrier_type)
-{
-  barrier_pre_wait(tid, barrier, barrier_type);
-}
-
-void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
-                           const BarrierT barrier_type, const Bool waited)
-{
-  barrier_post_wait(tid, barrier, barrier_type, waited);
-}
-
-
 //
 // Implementation of the tool interface.
 //
@@ -853,319 +518,6 @@
   }
 }
 
-#if defined(VGA_x86)
-#define STACK_POINTER_OFFSET OFFSET_x86_ESP
-#elif defined(VGA_amd64)
-#define STACK_POINTER_OFFSET OFFSET_amd64_RSP
-#elif defined(VGA_ppc32)
-#define STACK_POINTER_OFFSET ((OFFSET_ppc32_GPR0 + OFFSET_ppc32_GPR2) / 2)
-#elif defined(VGA_ppc64)
-#define STACK_POINTER_OFFSET ((OFFSET_ppc64_GPR0 + OFFSET_ppc64_GPR2) / 2)
-#else
-#error Unknown architecture.
-#endif
-
-
-/** Return true if and only if addr_expr matches the pattern (SP) or
- *  <offset>(SP).
- */
-static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
-{
-  Bool result = False;
-
-  if (addr_expr->tag == Iex_RdTmp)
-  {
-    int i;
-    for (i = 0; i < bb->stmts_size; i++)
-    {
-      if (bb->stmts[i]
-          && bb->stmts[i]->tag == Ist_WrTmp
-          && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
-      {
-        IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
-        if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
-        {
-          result = True;
-        }
-
-        //ppIRExpr(e);
-        //VG_(printf)(" (%s)\n", result ? "True" : "False");
-        break;
-      }
-    }
-  }
-  return result;
-}
-
-static void instrument_load(IRSB* const bb,
-                            IRExpr* const addr_expr,
-                            const HWord size)
-{
-  IRExpr* size_expr;
-  IRExpr** argv;
-  IRDirty* di;
-
-  if (UNLIKELY(drd_any_address_is_traced()))
-  {
-    addStmtToIRSB(bb,
-		  IRStmt_Dirty(
-		    unsafeIRDirty_0_N(/*regparms*/2,
-				      "drd_trace_load",
-				      VG_(fnptr_to_fnentry)
-				      (drd_trace_mem_load),
-				      mkIRExprVec_2(addr_expr,
-						    mkIRExpr_HWord(size)))));
-  }
-
-  if (! s_drd_check_stack_accesses && is_stack_access(bb, addr_expr))
-    return;
-
-  switch (size)
-  {
-  case 1:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_load_1",
-                           VG_(fnptr_to_fnentry)(drd_trace_load_1),
-                           argv);
-    break;
-  case 2:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_load_2",
-                           VG_(fnptr_to_fnentry)(drd_trace_load_2),
-                           argv);
-    break;
-  case 4:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_load_4",
-                           VG_(fnptr_to_fnentry)(drd_trace_load_4),
-                           argv);
-    break;
-  case 8:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_load_8",
-                           VG_(fnptr_to_fnentry)(drd_trace_load_8),
-                           argv);
-    break;
-  default:
-    size_expr = mkIRExpr_HWord(size);
-    argv = mkIRExprVec_2(addr_expr, size_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/2,
-                           "drd_trace_load",
-                           VG_(fnptr_to_fnentry)(drd_trace_load),
-                           argv);
-    break;
-  }
-  addStmtToIRSB(bb, IRStmt_Dirty(di));
-}
-
-static void instrument_store(IRSB* const bb,
-                             IRExpr* const addr_expr,
-                             const HWord size)
-{
-  IRExpr* size_expr;
-  IRExpr** argv;
-  IRDirty* di;
-
-  if (UNLIKELY(drd_any_address_is_traced()))
-  {
-    addStmtToIRSB(bb,
-		  IRStmt_Dirty(
-		    unsafeIRDirty_0_N(/*regparms*/2,
-				      "drd_trace_store",
-				      VG_(fnptr_to_fnentry)
-				      (drd_trace_mem_store),
-				      mkIRExprVec_2(addr_expr,
-						    mkIRExpr_HWord(size)))));
-  }
-
-  if (! s_drd_check_stack_accesses && is_stack_access(bb, addr_expr))
-    return;
-
-  switch (size)
-  {
-  case 1:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_store_1",
-                           VG_(fnptr_to_fnentry)(drd_trace_store_1),
-                           argv);
-    break;
-  case 2:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_store_2",
-                           VG_(fnptr_to_fnentry)(drd_trace_store_2),
-                           argv);
-    break;
-  case 4:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_store_4",
-                           VG_(fnptr_to_fnentry)(drd_trace_store_4),
-                           argv);
-    break;
-  case 8:
-    argv = mkIRExprVec_1(addr_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/1,
-                           "drd_trace_store_8",
-                           VG_(fnptr_to_fnentry)(drd_trace_store_8),
-                           argv);
-    break;
-  default:
-    size_expr = mkIRExpr_HWord(size);
-    argv = mkIRExprVec_2(addr_expr, size_expr);
-    di = unsafeIRDirty_0_N(/*regparms*/2,
-                           "drd_trace_store",
-                           VG_(fnptr_to_fnentry)(drd_trace_store),
-                           argv);
-    break;
-  }
-  addStmtToIRSB(bb, IRStmt_Dirty(di));
-}
-
-static
-IRSB* drd_instrument(VgCallbackClosure* const closure,
-                     IRSB* const bb_in,
-                     VexGuestLayout* const layout,
-                     VexGuestExtents* const vge, 
-                     IRType const gWordTy,
-                     IRType const hWordTy)
-{
-  IRDirty* di;
-  Int      i;
-  IRSB*    bb;
-  IRExpr** argv;
-  Bool     instrument = True;
-  Bool     bus_locked = False;
-
-  /* Set up BB */
-  bb           = emptyIRSB();
-  bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
-  bb->next     = deepCopyIRExpr(bb_in->next);
-  bb->jumpkind = bb_in->jumpkind;
-
-  for (i = 0; i < bb_in->stmts_used; i++)
-  {
-    IRStmt* const st = bb_in->stmts[i];
-    tl_assert(st);
-    if (st->tag == Ist_NoOp)
-      continue;
-
-    switch (st->tag)
-    {
-    /* Note: the code for not instrumenting the code in .plt          */
-    /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21    */
-    /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4).             */
-    /* This is because on this platform dynamic library symbols are   */
-    /* relocated in another way than by later binutils versions. The  */
-    /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
-    case Ist_IMark:
-      instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
-        != Vg_SectPLT;
-      addStmtToIRSB(bb, st);
-      break;
-
-    case Ist_MBE:
-      switch (st->Ist.MBE.event)
-      {
-      case Imbe_Fence:
-        break; /* not interesting */
-      case Imbe_BusLock:
-      case Imbe_SnoopedStoreBegin:
-        tl_assert(! bus_locked);
-        bus_locked = True;
-        break;
-      case Imbe_BusUnlock:
-      case Imbe_SnoopedStoreEnd:
-        tl_assert(bus_locked);
-        bus_locked = False;
-        break;
-      default:
-        tl_assert(0);
-      }
-      addStmtToIRSB(bb, st);
-      break;
-
-    case Ist_Store:
-      if (instrument && ! bus_locked)
-      {
-        instrument_store(bb,
-                         st->Ist.Store.addr,
-                         sizeofIRType(typeOfIRExpr(bb->tyenv,
-                                                   st->Ist.Store.data)));
-      }
-      addStmtToIRSB(bb, st);
-      break;
-
-    case Ist_WrTmp:
-      if (instrument)
-      {
-        const IRExpr* const data = st->Ist.WrTmp.data;
-        if (data->tag == Iex_Load)
-        {
-          instrument_load(bb,
-                          data->Iex.Load.addr,
-                          sizeofIRType(data->Iex.Load.ty));
-        }
-      }
-      addStmtToIRSB(bb, st);
-      break;
-
-    case Ist_Dirty:
-      if (instrument)
-      {
-        IRDirty* d = st->Ist.Dirty.details;
-        IREffect const mFx = d->mFx;
-        switch (mFx) {
-        case Ifx_None:
-          break;
-        case Ifx_Read:
-        case Ifx_Write:
-        case Ifx_Modify:
-          tl_assert(d->mAddr);
-          tl_assert(d->mSize > 0);
-          argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
-          if (mFx == Ifx_Read || mFx == Ifx_Modify) {
-            di = unsafeIRDirty_0_N(
-                                   /*regparms*/2,
-                                   "drd_trace_load",
-                                   VG_(fnptr_to_fnentry)(drd_trace_load),
-                                   argv);
-            addStmtToIRSB(bb, IRStmt_Dirty(di));
-          }
-          if ((mFx == Ifx_Write || mFx == Ifx_Modify)
-              && ! bus_locked)
-          {
-            di = unsafeIRDirty_0_N(
-                                   /*regparms*/2,
-                                   "drd_trace_store",
-                                   VG_(fnptr_to_fnentry)(drd_trace_store),
-                                   argv);
-            addStmtToIRSB(bb, IRStmt_Dirty(di));
-          }
-          break;
-        default:
-          tl_assert(0);
-        }
-      }
-      addStmtToIRSB(bb, st);
-      break;
-
-    default:
-      addStmtToIRSB(bb, st);
-      break;
-    }
-  }
-
-  tl_assert(! bus_locked);
-
-  return bb;
-}
-
 static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
 {
   tl_assert(tid == VG_(get_running_tid)());
@@ -1267,7 +619,7 @@
   drd_register_malloc_wrappers(drd_start_using_mem_w_ecu,
                                drd_stop_using_nonstack_mem);
 
-  drd_clientreq_init();
+  DRD_(clientreq_init)();
 
   drd_suppression_init();
 
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)
 {
diff --git a/drd/drd_thread.h b/drd/drd_thread.h
index 895502f..525c945 100644
--- a/drd/drd_thread.h
+++ b/drd/drd_thread.h
@@ -29,6 +29,7 @@
 
 // Includes.
 
+#include "drd_basics.h"
 #include "drd_segment.h"
 #include "pub_drd_bitmap.h"
 #include "pub_tool_libcassert.h"  // tl_assert()
@@ -92,6 +93,8 @@
 
 void thread_trace_context_switches(const Bool t);
 void thread_trace_conflict_set(const Bool t);
+Bool DRD_(thread_get_trace_fork_join)(void);
+void DRD_(thread_set_trace_fork_join)(const Bool t);
 void thread_set_segment_merging(const Bool m);
 
 DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid);
@@ -101,6 +104,7 @@
 DrdThreadId thread_pre_create(const DrdThreadId creator,
                               const ThreadId vg_created);
 DrdThreadId thread_post_create(const ThreadId vg_created);
+void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee);
 void thread_delete(const DrdThreadId tid);
 void thread_finished(const DrdThreadId tid);
 void thread_pre_cancel(const DrdThreadId tid);
diff --git a/drd/drd_thread_bitmap.h b/drd/drd_thread_bitmap.h
index 4fb098f..aa43e83 100644
--- a/drd/drd_thread_bitmap.h
+++ b/drd/drd_thread_bitmap.h
@@ -26,7 +26,11 @@
 #ifndef __DRD_THREAD_BITMAP_H
 #define __DRD_THREAD_BITMAP_H
 
+
 #include "drd_bitmap.h"
+#include "drd_thread.h" /* running_thread_get_segment() */
+#include "pub_drd_bitmap.h"
+
 
 static __inline__
 Bool bm_access_load_1_triggers_conflict(const Addr a1)
diff --git a/drd/drd_track.h b/drd/drd_track.h
deleted file mode 100644
index 880e3f1..0000000
--- a/drd/drd_track.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-  This file is part of drd, a data race detector.
-
-  Copyright (C) 2006-2008 Bart Van Assche
-  bart.vanassche@gmail.com
-
-  This program is free software; you can redistribute it and/or
-  modify it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 2 of the
-  License, or (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-  02111-1307, USA.
-
-  The GNU General Public License is contained in the file COPYING.
-*/
-
-
-void drd_post_thread_join(DrdThreadId joiner, DrdThreadId joinee);
-
-void drd_pre_thread_cancel(DrdThreadId canceling, DrdThreadId canceled);
-void drd_post_thread_cancel(DrdThreadId canceling, DrdThreadId canceled, Bool succeeded);
-
-void drd_pre_mutex_init(Addr mutex, const MutexT mutex_type);
-void drd_post_mutex_destroy(Addr mutex, const MutexT mutex_type);
-void drd_pre_mutex_lock(const Addr mutex, const MutexT mutex_type,
-                        const Bool trylock);
-void drd_post_mutex_lock(Addr mutex, const Bool took_lock);
-void drd_pre_mutex_unlock(const Addr mutex, const MutexT mutex_type);
-
-void drd_pre_cond_init(Addr cond);
-void drd_post_cond_destroy(Addr cond);
-
-void drd_semaphore_init(const Addr semaphore,
-                        const Word pshared, const Word value);
-void drd_semaphore_destroy(const Addr semaphore);
-void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore);
-void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
-                             const Bool waited);
-void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore);
-void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
-                             const Bool waited);
-
-void drd_barrier_init(const Addr barrier,
-                      const BarrierT barrier_type, const Word count,
-                      const Bool reinitialization);
-void drd_barrier_destroy(const Addr barrier, const BarrierT barrier_type);
-void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier,
-                          const BarrierT barrier_type);
-void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
-                           const BarrierT barrier_type, const Bool waited);