]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Changes:
authorBart Van Assche <bvanassche@acm.org>
Sat, 21 Feb 2009 15:27:04 +0000 (15:27 +0000)
committerBart Van Assche <bvanassche@acm.org>
Sat, 21 Feb 2009 15:27:04 +0000 (15:27 +0000)
- pthread_barrier_wait() intercept now passes the information to the DRD
  tool whether or not this function returned
  PTHREAD_BARRIER_SERIAL_THREAD. This information is now displayed when
  the command-line option --trace-barrier=yes has been specified.
- Changed the cleanup functions for client objects that are called just
  before a thread stops into callback functions.
- Added DRD_(clientobj_delete_thread)().
- Removed DRD_(clientobj_resetiter)(void) and DRD_(clientobj_next)().
- Added test for race conditions between pthread_barrier_wait() and
  pthread_barrier_destroy() calls. An error message is now printed if
  this condition has been detected.
- Bug fix: pthread_barrier_delete() calls on barriers being waited upon
  are now reported.
- Removed DRD_() wrapper from around the name of some static variables and
  functions.

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

18 files changed:
drd/drd_barrier.c
drd/drd_barrier.h
drd/drd_clientobj.c
drd/drd_clientobj.h
drd/drd_clientreq.c
drd/drd_clientreq.h
drd/drd_cond.c
drd/drd_cond.h
drd/drd_error.c
drd/drd_error.h
drd/drd_mutex.c
drd/drd_mutex.h
drd/drd_pthread_intercepts.c
drd/drd_rwlock.c
drd/drd_rwlock.h
drd/drd_semaphore.c
drd/drd_semaphore.h
drd/drd_thread.c

index 1807f5d14b9bb0061f2817ccea1721da4a34389a..e20447f22194af5128318787228ebe71e52baf63 100644 (file)
 /** Information associated with one thread participating in a barrier. */
 struct barrier_thread_info
 {
-  UWord       tid;           // A DrdThreadId
+  UWord       tid;           // A DrdThreadId declared as UWord because
+                             // this member variable is the key of an OSet.
   Word        iteration;     // iteration of last pthread_barrier_wait()
                              // call thread tid participated in.
   Segment*    sg[2];         // Segments of the last two
                              // pthread_barrier() calls by thread tid.
+  ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call.
+  Segment*    post_wait_sg;  // Segment created after *_barrier_wait() finished
 };
 
 
 /* Local functions. */
 
-static void DRD_(barrier_cleanup)(struct barrier_info* p);
-static const char* DRD_(barrier_get_typename)(struct barrier_info* const p);
-static const char* DRD_(barrier_type_name)(const BarrierT bt);
+static void barrier_cleanup(struct barrier_info* p);
+static void barrier_delete_thread(struct barrier_info* const p,
+                                  const DrdThreadId tid);
+static const char* barrier_get_typename(struct barrier_info* const p);
+static const char* barrier_type_name(const BarrierT bt);
+static
+void barrier_report_wait_delete_race(const struct barrier_info* const p,
+                                    const struct barrier_thread_info* const q);
 
 
 /* Local variables. */
 
-static Bool DRD_(s_trace_barrier) = False;
-static ULong DRD_(s_barrier_segment_creation_count);
+static Bool  s_trace_barrier = False;
+static ULong s_barrier_segment_creation_count;
 
 
 /* Function definitions. */
 
 void DRD_(barrier_set_trace)(const Bool trace_barrier)
 {
-  DRD_(s_trace_barrier) = trace_barrier;
+  s_trace_barrier = trace_barrier;
 }
 
-/** Initialize the structure *p with the specified thread ID and iteration
- *  information. */
+/**
+ * Initialize the structure *p with the specified thread ID and iteration
+ * information.
+ */
 static
 void DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p,
                                      const DrdThreadId tid,
                                      const Word iteration)
 {
-  p->tid = tid;
-  p->iteration = iteration;
-  p->sg[0] = 0;
-  p->sg[1] = 0;
+  p->tid            = tid;
+  p->iteration      = iteration;
+  p->sg[0]          = 0;
+  p->sg[1]          = 0;
+  p->wait_call_ctxt = 0;
+  p->post_wait_sg   = 0;
 }
 
-/** Deallocate the memory that was allocated in barrier_thread_initialize(). */
+/**
+ * Deallocate the memory that is owned by members of
+ * struct barrier_thread_info.
+ */
 static void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p)
 {
   tl_assert(p);
   DRD_(sg_put)(p->sg[0]);
   DRD_(sg_put)(p->sg[1]);
+  DRD_(sg_put)(p->post_wait_sg);
 }
 
-/** Initialize the structure *p with the specified client-side barrier address,
- *  barrier object size and number of participants in each barrier. */
+/**
+ * Initialize the structure *p with the specified client-side barrier address,
+ * barrier object size and number of participants in each barrier.
+ */
 static
 void DRD_(barrier_initialize)(struct barrier_info* const p,
                               const Addr barrier,
@@ -101,13 +119,16 @@ void DRD_(barrier_initialize)(struct barrier_info* const p,
   tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
   tl_assert(p->a1 == barrier);
 
-  p->cleanup           = (void(*)(DrdClientobj*))DRD_(barrier_cleanup);
+  p->cleanup           = (void(*)(DrdClientobj*))barrier_cleanup;
+  p->delete_thread
+    = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread;
   p->barrier_type      = barrier_type;
   p->count             = count;
   p->pre_iteration     = 0;
   p->post_iteration    = 0;
   p->pre_waiters_left  = count;
   p->post_waiters_left = count;
+
   tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word));
   tl_assert(sizeof(((struct barrier_thread_info*)0)->tid)
             >= sizeof(DrdThreadId));
@@ -116,18 +137,21 @@ void DRD_(barrier_initialize)(struct barrier_info* const p,
 }
 
 /**
- * Deallocate the memory allocated by barrier_initialize() and in p->oset. 
+ * Deallocate the memory owned by the struct barrier_info object and also
+ * all the nodes in the OSet p->oset.
+ *
  * Called by clientobj_destroy().
  */
-void DRD_(barrier_cleanup)(struct barrier_info* p)
+static void barrier_cleanup(struct barrier_info* p)
 {
   struct barrier_thread_info* q;
+    Segment* latest_sg = 0;
 
   tl_assert(p);
 
   if (p->pre_waiters_left != p->count)
   {
-    BarrierErrInfo bei = { p->a1 };
+    BarrierErrInfo bei = { p->a1, 0, 0 };
     VG_(maybe_record_error)(VG_(get_running_tid)(),
                             BarrierErr,
                             VG_(get_IP)(VG_(get_running_tid)()),
@@ -136,16 +160,29 @@ void DRD_(barrier_cleanup)(struct barrier_info* p)
                             &bei);
   }
 
+  DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)());
+  tl_assert(latest_sg);
+
   VG_(OSetGen_ResetIter)(p->oset);
   for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
   {
+    if (q->post_wait_sg
+        && ! DRD_(vc_lte)(&q->post_wait_sg->vc, &latest_sg->vc))
+    {
+      barrier_report_wait_delete_race(p, q);
+    }
+
     DRD_(barrier_thread_destroy)(q);
   }
   VG_(OSetGen_Destroy)(p->oset);
+
+  DRD_(sg_put)(latest_sg);
 }
 
-/** Look up the client-side barrier address barrier in s_barrier[]. If not
- *  found, add it. */
+/**
+ * Look up the client-side barrier address barrier in s_barrier[]. If not
+ * found, add it.
+ */
 static
 struct barrier_info*
 DRD_(barrier_get_or_allocate)(const Addr barrier,
@@ -165,17 +202,21 @@ DRD_(barrier_get_or_allocate)(const Addr barrier,
   return p;
 }
 
-/** Look up the address of the information associated with the client-side
- *  barrier object. */
+/**
+ * Look up the address of the information associated with the client-side
+ * barrier object.
+ */
 static struct barrier_info* DRD_(barrier_get)(const Addr barrier)
 {
   tl_assert(offsetof(DrdClientobj, barrier) == 0);
   return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier);
 }
 
-/** Initialize a barrier with client address barrier, client size size, and
- *  where count threads participate in each barrier.
- *  Called before pthread_barrier_init().
+/**
+ * Initialize a barrier with client address barrier, client size size, and
+ * where count threads participate in each barrier.
+ *
+ * Called before pthread_barrier_init().
  */
 void DRD_(barrier_init)(const Addr barrier,
                         const BarrierT barrier_type, const Word count,
@@ -187,7 +228,7 @@ void DRD_(barrier_init)(const Addr barrier,
 
   if (count == 0)
   {
-    BarrierErrInfo bei = { barrier };
+    BarrierErrInfo bei = { barrier, 0, 0 };
     VG_(maybe_record_error)(VG_(get_running_tid)(),
                             BarrierErr,
                             VG_(get_IP)(VG_(get_running_tid)()),
@@ -200,7 +241,7 @@ void DRD_(barrier_init)(const Addr barrier,
     p = DRD_(barrier_get)(barrier);
     if (p)
     {
-      BarrierErrInfo bei = { barrier };
+      BarrierErrInfo bei = { barrier, 0, 0 };
       VG_(maybe_record_error)(VG_(get_running_tid)(),
                               BarrierErr,
                               VG_(get_IP)(VG_(get_running_tid)()),
@@ -210,7 +251,7 @@ void DRD_(barrier_init)(const Addr barrier,
   }
   p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count);
 
-  if (DRD_(s_trace_barrier))
+  if (s_trace_barrier)
   {
     if (reinitialization)
     {
@@ -218,7 +259,7 @@ void DRD_(barrier_init)(const Addr barrier,
                    "[%d/%d] barrier_reinit    %s 0x%lx count %ld -> %ld",
                    VG_(get_running_tid)(),
                    DRD_(thread_get_running_tid)(),
-                   DRD_(barrier_get_typename)(p),
+                   barrier_get_typename(p),
                    barrier,
                    p->count,
                    count);
@@ -229,7 +270,7 @@ void DRD_(barrier_init)(const Addr barrier,
                    "[%d/%d] barrier_init      %s 0x%lx",
                    VG_(get_running_tid)(),
                    DRD_(thread_get_running_tid)(),
-                   DRD_(barrier_get_typename)(p),
+                   barrier_get_typename(p),
                    barrier);
     }
   }
@@ -238,7 +279,7 @@ void DRD_(barrier_init)(const Addr barrier,
   {
     if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
     {
-      BarrierErrInfo bei = { p->a1 };
+      BarrierErrInfo bei = { p->a1, 0, 0 };
       VG_(maybe_record_error)(VG_(get_running_tid)(),
                               BarrierErr,
                               VG_(get_IP)(VG_(get_running_tid)()),
@@ -250,20 +291,20 @@ void DRD_(barrier_init)(const Addr barrier,
   }
 }
 
-/** Called after pthread_barrier_destroy(). */
+/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */
 void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
 {
   struct barrier_info* p;
 
   p = DRD_(barrier_get)(barrier);
 
-  if (DRD_(s_trace_barrier))
+  if (s_trace_barrier)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] barrier_destroy   %s 0x%lx",
                  VG_(get_running_tid)(),
                  DRD_(thread_get_running_tid)(),
-                 DRD_(barrier_get_typename)(p),
+                 barrier_get_typename(p),
                  barrier);
   }
 
@@ -280,7 +321,7 @@ void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
 
   if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
   {
-    BarrierErrInfo bei = { p->a1 };
+    BarrierErrInfo bei = { p->a1, 0, 0 };
     VG_(maybe_record_error)(VG_(get_running_tid)(),
                             BarrierErr,
                             VG_(get_IP)(VG_(get_running_tid)()),
@@ -291,7 +332,7 @@ void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
   DRD_(clientobj_remove)(p->a1, ClientBarrier);
 }
 
-/** Called before pthread_barrier_wait(). */
+/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */
 void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
                             const BarrierT barrier_type)
 {
@@ -302,6 +343,11 @@ void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
   p = DRD_(barrier_get)(barrier);
   if (p == 0 && barrier_type == gomp_barrier)
   {
+    /*
+     * gomp_barrier_wait() call has been intercepted but gomp_barrier_init()
+     * not. The only cause I know of that can trigger this is that libgomp.so
+     * has been compiled with --enable-linux-futex.
+     */
     VG_(message)(Vg_UserMsg, "");
     VG_(message)(Vg_UserMsg,
                  "Please verify whether gcc has been configured"
@@ -312,17 +358,18 @@ void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
   }
   tl_assert(p);
 
-  if (DRD_(s_trace_barrier))
+  if (s_trace_barrier)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] barrier_pre_wait  %s 0x%lx iteration %ld",
                  VG_(get_running_tid)(),
                  DRD_(thread_get_running_tid)(),
-                 DRD_(barrier_get_typename)(p),
+                 barrier_get_typename(p),
                  barrier,
                  p->pre_iteration);
   }
 
+  /* Allocate the per-thread data structure if necessary. */
   q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
   if (q == 0)
   {
@@ -331,8 +378,21 @@ void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
     VG_(OSetGen_Insert)(p->oset, q);
     tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
   }
+
+  /* Record *_barrier_wait() call context. */
+  q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
+
+  /*
+   * Store a pointer to the latest segment of the current thread in the
+   * per-thread data structure.
+   */
   DRD_(thread_get_latest_segment)(&q->sg[p->pre_iteration], tid);
 
+  /*
+   * If the same number of threads as the barrier count indicates have
+   * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and
+   * reset the p->pre_waiters_left counter.
+   */
   if (--p->pre_waiters_left <= 0)
   {
     p->pre_iteration    = 1 - p->pre_iteration;
@@ -340,106 +400,143 @@ void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
   }
 }
 
-/** Called after pthread_barrier_wait(). */
+/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */
 void DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
-                             const BarrierT barrier_type, const Bool waited)
+                             const BarrierT barrier_type, const Bool waited,
+                             const Bool serializing)
 {
   struct barrier_info* p;
+  const UWord word_tid = tid;
+  struct barrier_thread_info* q;
+  struct barrier_thread_info* r;
 
   p = DRD_(barrier_get)(barrier);
 
-  if (DRD_(s_trace_barrier))
+  if (s_trace_barrier)
   {
     VG_(message)(Vg_UserMsg,
-                 "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld",
+                 "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld%s",
                  VG_(get_running_tid)(),
                  tid,
-                 p ? DRD_(barrier_get_typename)(p) : "(?)",
+                 p ? barrier_get_typename(p) : "(?)",
                  barrier,
-                 p ? p->post_iteration : -1);
+                 p ? p->post_iteration : -1,
+                 serializing ? " (serializing)" : "");
   }
 
-  /* If p == 0, this means that the barrier has been destroyed after     */
-  /* *_barrier_wait() returned and before this function was called. Just */
-  /* return in that case.                                                */
+  /*
+   * If p == 0, this means that the barrier has been destroyed after
+   * *_barrier_wait() returned and before this function was called. Just
+   * return in that case -- race conditions between *_barrier_wait()
+   * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper.
+   */
   if (p == 0)
     return;
 
-  if (waited)
-  {
-    const UWord word_tid = tid;
-    struct barrier_thread_info* q;
-    struct barrier_thread_info* r;
+  /* If the *_barrier_wait() call returned an error code, exit. */
+  if (! waited)
+    return;
 
-    q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
-    if (q == 0)
-    {
-      BarrierErrInfo bei = { p->a1 };
-      VG_(maybe_record_error)(VG_(get_running_tid)(),
-                              BarrierErr,
-                              VG_(get_IP)(VG_(get_running_tid)()),
-                              "Error in barrier implementation"
-                              " -- barrier_wait() started before"
-                              " barrier_destroy() and finished after"
-                              " barrier_destroy()",
-                              &bei);
+  q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
+  if (q == 0)
+  {
+    BarrierErrInfo bei = { p->a1, 0, 0 };
+    VG_(maybe_record_error)(VG_(get_running_tid)(),
+                            BarrierErr,
+                            VG_(get_IP)(VG_(get_running_tid)()),
+                            "Error in barrier implementation"
+                            " -- barrier_wait() started before"
+                            " barrier_destroy() and finished after"
+                            " barrier_destroy()",
+                            &bei);
 
-      q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
-      DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
-      VG_(OSetGen_Insert)(p->oset, q);
-      tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
-    }
-    VG_(OSetGen_ResetIter)(p->oset);
-    for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
+    q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
+    DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
+    VG_(OSetGen_Insert)(p->oset, q);
+    tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+  }
+  /*
+   * Combine all vector clocks that were stored in the pre_barrier_wait
+   * wrapper with the vector clock of the current thread.
+   */
+  VG_(OSetGen_ResetIter)(p->oset);
+  for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
+  {
+    if (r != q)
     {
-      if (r != q)
-      {
-        tl_assert(r->sg[p->post_iteration]);
-        DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc);
-      }
+      tl_assert(r->sg[p->post_iteration]);
+      DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc);
     }
+  }
 
-    DRD_(thread_new_segment)(tid);
-    DRD_(s_barrier_segment_creation_count)++;
+  /* Create a new segment and store a pointer to that segment. */
+  DRD_(thread_new_segment)(tid);
+  DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid);
+  s_barrier_segment_creation_count++;
+
+  /*
+   * If the same number of threads as the barrier count indicates have
+   * called the post *_barrier_wait() wrapper, toggle p->post_iteration and
+   * reset the p->post_waiters_left counter.
+   */
+  if (--p->post_waiters_left <= 0)
+  {
+    p->post_iteration    = 1 - p->post_iteration;
+    p->post_waiters_left = p->count;
+  }
+}
 
-    if (--p->post_waiters_left <= 0)
-    {
-      p->post_iteration    = 1 - p->post_iteration;
-      p->post_waiters_left = p->count;
-    }
+/** Called when thread tid stops to exist. */
+static void barrier_delete_thread(struct barrier_info* const p,
+                                  const DrdThreadId tid)
+{
+  struct barrier_thread_info* q;
+  const UWord word_tid = tid;
+
+  q = VG_(OSetGen_Remove)(p->oset, &word_tid);
+
+  /*
+   * q is only non-zero if the barrier object has been used by thread tid
+   * after the barrier_init() call and before the thread finished.
+   */
+  if (q)
+  {
+    DRD_(barrier_thread_destroy)(q);
+    VG_(OSetGen_FreeNode)(p->oset, q);
   }
 }
 
-/** Call this function when thread tid stops to exist. */
-void DRD_(barrier_thread_delete)(const DrdThreadId tid)
+/**
+ * Report that *_barrier_destroy() has been called but that this call was
+ * not synchronized with the last *_barrier_wait() call on the same barrier.
+ */
+static
+void barrier_report_wait_delete_race(const struct barrier_info* const p,
+                                     const struct barrier_thread_info* const q)
 {
-  struct barrier_info* p;
+  tl_assert(p);
+  tl_assert(q);
 
-  DRD_(clientobj_resetiter)();
-  for ( ; (p = &(DRD_(clientobj_next)(ClientBarrier)->barrier)) != 0; )
   {
-    struct barrier_thread_info* q;
-    const UWord word_tid = tid;
-    q = VG_(OSetGen_Remove)(p->oset, &word_tid);
-    /* q is only non-zero if the barrier object has been used by thread tid
-     * after the barrier_init() call and before the thread finished.
-     */
-    if (q)
-    {
-      DRD_(barrier_thread_destroy)(q);
-      VG_(OSetGen_FreeNode)(p->oset, q);
-    }
+    BarrierErrInfo bei
+      = { p->a1, q->tid, q->wait_call_ctxt };
+    VG_(maybe_record_error)(VG_(get_running_tid)(),
+                            BarrierErr,
+                            VG_(get_IP)(VG_(get_running_tid)()),
+                            "Destruction of barrier not synchronized with"
+                            " barrier wait call",
+                            &bei);
   }
 }
 
-static const char* DRD_(barrier_get_typename)(struct barrier_info* const p)
+static const char* barrier_get_typename(struct barrier_info* const p)
 {
   tl_assert(p);
 
-  return DRD_(barrier_type_name)(p->barrier_type);
+  return barrier_type_name(p->barrier_type);
 }
 
-static const char* DRD_(barrier_type_name)(const BarrierT bt)
+static const char* barrier_type_name(const BarrierT bt)
 {
   switch (bt)
   {
@@ -453,5 +550,5 @@ static const char* DRD_(barrier_type_name)(const BarrierT bt)
 
 ULong DRD_(get_barrier_segment_creation_count)(void)
 {
-  return DRD_(s_barrier_segment_creation_count);
+  return s_barrier_segment_creation_count;
 }
index 2ef1f89957848ec7f3159ad2728df42e8ca9e3fb..1acb4a6e30a5575a9b118c951eaeb86f45a4655b 100644 (file)
@@ -45,8 +45,8 @@ 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);
-void DRD_(barrier_thread_delete)(const DrdThreadId threadid);
+                             const BarrierT barrier_type, const Bool waited,
+                             const Bool serializing);
 void DRD_(barrier_stop_using_mem)(const Addr a1, const Addr a2);
 ULong DRD_(get_barrier_segment_creation_count)(void);
 
index 70c162a2a4c5a02b84e91817baa23bfbcfa2c54a..d1f5f9641c2c061de2e6cac775a5966b8e6baf34 100644 (file)
 
 /* Local variables. */
 
-static OSet* DRD_(s_clientobj_set);
-static Bool DRD_(s_trace_clientobj);
+static OSet* s_clientobj_set;
+static Bool s_trace_clientobj;
+
+
+/* Local functions. */
+
+static Bool clientobj_remove_obj(DrdClientobj* const p);
 
 
 /* Function definitions. */
 
 void DRD_(clientobj_set_trace)(const Bool trace)
 {
-  DRD_(s_trace_clientobj) = trace;
+  s_trace_clientobj = trace;
 }
 
 /** Initialize the client object set. */
 void DRD_(clientobj_init)(void)
 {
-  tl_assert(DRD_(s_clientobj_set) == 0);
-  DRD_(s_clientobj_set) = VG_(OSetGen_Create)(0, 0,
-                                              VG_(malloc),
-                                              "drd.clientobj.ci.1",
-                                              VG_(free));
-  tl_assert(DRD_(s_clientobj_set));
+  tl_assert(s_clientobj_set == 0);
+  s_clientobj_set = VG_(OSetGen_Create)(0, 0, VG_(malloc),
+                                        "drd.clientobj.ci.1", VG_(free));
+  tl_assert(s_clientobj_set);
 }
 
 /**
@@ -66,19 +69,20 @@ void DRD_(clientobj_init)(void)
  */
 void DRD_(clientobj_cleanup)(void)
 {
-  tl_assert(DRD_(s_clientobj_set));
-  tl_assert(VG_(OSetGen_Size)(DRD_(s_clientobj_set)) == 0);
-  VG_(OSetGen_Destroy)(DRD_(s_clientobj_set));
-  DRD_(s_clientobj_set) = 0;
+  tl_assert(s_clientobj_set);
+  tl_assert(VG_(OSetGen_Size)(s_clientobj_set) == 0);
+  VG_(OSetGen_Destroy)(s_clientobj_set);
+  s_clientobj_set = 0;
 }
 
-/** Return the data associated with the client object at client address addr.
- *  Return 0 if there is no client object in the set with the specified start
- *  address.
+/**
+ * Return the data associated with the client object at client address addr.
+ * Return 0 if there is no client object in the set with the specified start
+ * address.
  */
 DrdClientobj* DRD_(clientobj_get_any)(const Addr addr)
 {
-  return VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr);
+  return VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
 }
 
 /** Return the data associated with the client object at client address addr
@@ -88,7 +92,7 @@ DrdClientobj* DRD_(clientobj_get_any)(const Addr addr)
 DrdClientobj* DRD_(clientobj_get)(const Addr addr, const ObjType t)
 {
   DrdClientobj* p;
-  p = VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr);
+  p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
   if (p && p->any.type == t)
     return p;
   return 0;
@@ -102,8 +106,8 @@ Bool DRD_(clientobj_present)(const Addr a1, const Addr a2)
   DrdClientobj *p;
 
   tl_assert(a1 < a2);
-  VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
-  for ( ; (p = VG_(OSetGen_Next)(DRD_(s_clientobj_set))) != 0; )
+  VG_(OSetGen_ResetIter)(s_clientobj_set);
+  for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
   {
     if (a1 <= p->any.a1 && p->any.a1 < a2)
     {
@@ -122,20 +126,20 @@ DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t)
   DrdClientobj* p;
 
   tl_assert(! DRD_(clientobj_present)(a1, a1 + 1));
-  tl_assert(VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &a1) == 0);
+  tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == 0);
 
-  if (DRD_(s_trace_clientobj))
+  if (s_trace_clientobj)
   {
     VG_(message)(Vg_UserMsg, "Adding client object 0x%lx of type %d", a1, t);
   }
 
-  p = VG_(OSetGen_AllocNode)(DRD_(s_clientobj_set), sizeof(*p));
+  p = VG_(OSetGen_AllocNode)(s_clientobj_set, sizeof(*p));
   VG_(memset)(p, 0, sizeof(*p));
   p->any.a1   = a1;
   p->any.type = t;
   p->any.first_observed_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
-  VG_(OSetGen_Insert)(DRD_(s_clientobj_set), p);
-  tl_assert(VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &a1) == p);
+  VG_(OSetGen_Insert)(s_clientobj_set, p);
+  tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == p);
   DRD_(start_suppression)(a1, a1 + 1, "clientobj");
   return p;
 }
@@ -144,28 +148,35 @@ Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t)
 {
   DrdClientobj* p;
 
-  if (DRD_(s_trace_clientobj))
+  p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
+  tl_assert(p);
+  tl_assert(p->any.type == t);
+  return clientobj_remove_obj(p);
+}
+
+static Bool clientobj_remove_obj(DrdClientobj* const p)
+{
+  DrdClientobj* q;
+
+  if (s_trace_clientobj)
   {
     VG_(message)(Vg_UserMsg, "Removing client object 0x%lx of type %d",
-                 addr, t);
+                 p->any.a1, p->any.type);
 #if 0
     VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
                                VG_(clo_backtrace_size));
 #endif
   }
 
-  p = VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr);
-  tl_assert(p->any.type == t);
-  p = VG_(OSetGen_Remove)(DRD_(s_clientobj_set), &addr);
-  if (p)
-  {
-    tl_assert(VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr) == 0);
-    tl_assert(p->any.cleanup);
-    (*p->any.cleanup)(p);
-    VG_(OSetGen_FreeNode)(DRD_(s_clientobj_set), p);
-    return True;
-  }
-  return False;
+  tl_assert(p);
+  q = VG_(OSetGen_Remove)(s_clientobj_set, &p->any.a1);
+  tl_assert(p == q);
+
+  tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &p->any.a1) == 0);
+  tl_assert(p->any.cleanup);
+  (*p->any.cleanup)(p);
+  VG_(OSetGen_FreeNode)(s_clientobj_set, p);
+  return True;
 }
 
 void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2)
@@ -173,13 +184,13 @@ void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2)
   Addr removed_at;
   DrdClientobj* p;
 
-  tl_assert(DRD_(s_clientobj_set));
+  tl_assert(s_clientobj_set);
 
   if (! DRD_(is_any_suppressed)(a1, a2))
     return;
 
-  VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
-  p = VG_(OSetGen_Next)(DRD_(s_clientobj_set));
+  VG_(OSetGen_ResetIter)(s_clientobj_set);
+  p = VG_(OSetGen_Next)(s_clientobj_set);
   for ( ; p != 0; )
   {
     if (a1 <= p->any.a1 && p->any.a1 < a2)
@@ -188,30 +199,34 @@ void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2)
       DRD_(clientobj_remove)(p->any.a1, p->any.type);
       /* The above call removes an element from the oset and hence */
       /* invalidates the iterator. Set the iterator back.          */
-      VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
-      while ((p = VG_(OSetGen_Next)(DRD_(s_clientobj_set))) != 0
+      VG_(OSetGen_ResetIter)(s_clientobj_set);
+      while ((p = VG_(OSetGen_Next)(s_clientobj_set)) != 0
              && p->any.a1 <= removed_at)
       { }
     }
     else
     {
-      p = VG_(OSetGen_Next)(DRD_(s_clientobj_set));
+      p = VG_(OSetGen_Next)(s_clientobj_set);
     }
   }
 }
 
-void DRD_(clientobj_resetiter)(void)
+/**
+ * Delete the per-thread information stored in client objects for the
+ * specified thread.
+ */
+void DRD_(clientobj_delete_thread)(const DrdThreadId tid)
 {
-  VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
-}
+  DrdClientobj *p;
 
-DrdClientobj* DRD_(clientobj_next)(const ObjType t)
-{
-  DrdClientobj* p;
-  while ((p = VG_(OSetGen_Next)(DRD_(s_clientobj_set))) != 0
-         && p->any.type != t)
-    ;
-  return p;
+  VG_(OSetGen_ResetIter)(s_clientobj_set);
+  for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
+  {
+    if (p->any.delete_thread)
+    {
+      (*p->any.delete_thread)(p, tid);
+    }
+  }
 }
 
 const char* DRD_(clientobj_type_name)(const ObjType t)
index efe4e6d5c481aa701bfda06aadbfce38d2e63ea9..c30a17cfbd308a5a1e369cc380683d1be4c55379 100644 (file)
@@ -53,7 +53,8 @@ struct any
 {
   Addr        a1;
   ObjType     type;
-  void      (*cleanup)(union drd_clientobj*);
+  void        (*cleanup)(union drd_clientobj*);
+  void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
   ExeContext* first_observed_at;
 };
 
@@ -62,6 +63,7 @@ struct mutex_info
   Addr            a1;
   ObjType         type;
   void            (*cleanup)(union drd_clientobj*);
+  void            (*delete_thread)(union drd_clientobj*, DrdThreadId);
   ExeContext*     first_observed_at;
   MutexT          mutex_type;      // pthread_mutex_t or pthread_spinlock_t.
   int             recursion_count; // 0 if free, >= 1 if locked.
@@ -75,7 +77,8 @@ struct cond_info
 {
   Addr        a1;
   ObjType     type;
-  void      (*cleanup)(union drd_clientobj*);
+  void        (*cleanup)(union drd_clientobj*);
+  void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
   ExeContext* first_observed_at;
   int         waiter_count;
   Addr        mutex; // Client mutex specified in pthread_cond_wait() call, and
@@ -87,6 +90,7 @@ struct semaphore_info
   Addr        a1;
   ObjType     type;
   void        (*cleanup)(union drd_clientobj*);
+  void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
   ExeContext* first_observed_at;
   UInt        waits_to_skip;     // Number of sem_wait() calls to skip
                                  // (due to the value assigned by sem_init()).
@@ -101,14 +105,15 @@ struct barrier_info
   Addr     a1;
   ObjType  type;
   void     (*cleanup)(union drd_clientobj*);
+  void     (*delete_thread)(union drd_clientobj*, DrdThreadId);
   ExeContext* first_observed_at;
   BarrierT barrier_type;      // pthread_barrier or gomp_barrier.
   Word     count;             // Participant count in a barrier wait.
-  Word     pre_iteration;     // pthread_barrier_wait() call count modulo two.
-  Word     post_iteration;    // pthread_barrier_wait() call count modulo two.
+  Word     pre_iteration;     // pre barrier completion count modulo two.
+  Word     post_iteration;    // post barrier completion count modulo two.
   Word     pre_waiters_left;  // number of waiters left for a complete barrier.
   Word     post_waiters_left; // number of waiters left for a complete barrier.
-  OSet*    oset;              // Thread-specific barrier information.
+  OSet*    oset;              // Per-thread barrier information.
 };
 
 struct rwlock_info
@@ -116,6 +121,7 @@ struct rwlock_info
   Addr        a1;
   ObjType     type;
   void        (*cleanup)(union drd_clientobj*);
+  void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
   ExeContext* first_observed_at;
   OSet*       thread_info;
   ULong       acquiry_time_ms;
@@ -144,8 +150,7 @@ Bool DRD_(clientobj_present)(const Addr a1, const Addr a2);
 DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t);
 Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t);
 void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2);
-void DRD_(clientobj_resetiter)(void);
-DrdClientobj* DRD_(clientobj_next)(const ObjType t);
+void DRD_(clientobj_delete_thread)(const DrdThreadId tid);
 const char* DRD_(clientobj_type_name)(const ObjType t);
 
 
index d407f844a488b0a050934eb0fcd1bf2d433cc26f..8a94741809bade21e7472771aecb45eb14f019d4 100644 (file)
@@ -327,7 +327,7 @@ Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret)
 
   case VG_USERREQ__POST_BARRIER_WAIT:
     if (DRD_(thread_leave_synchr)(drd_tid) == 0)
-      DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3]);
+      DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]);
     break;
 
   case VG_USERREQ__PRE_RWLOCK_INIT:
index 82f58425a6a079073390e82e1e547340085f6c10..907e1e9d1777f85b28840764ca8c1d0a21c70a49 100644 (file)
@@ -178,7 +178,7 @@ enum {
   /* args: Addr barrier, BarrierT type. */
   /* To notify the drd tool of a pthread_barrier_wait call. */
   VG_USERREQ__POST_BARRIER_WAIT,
-  /* args: Addr barrier, BarrierT type, Word has_waited */
+  /* args: Addr barrier, BarrierT type, Word has_waited, Word serializing */
 
   /* To notify the drd tool of a pthread_rwlock_init call. */
   VG_USERREQ__PRE_RWLOCK_INIT,
index 8d1bf7f6155ef0ab382dbec13dcc63dfae85f3ef..afee3115c47f53b572b090ef09ed071e07ce57e9 100644 (file)
@@ -65,9 +65,10 @@ void DRD_(cond_initialize)(struct cond_info* const p, const Addr cond)
   tl_assert(p->a1         == cond);
   tl_assert(p->type       == ClientCondvar);
 
-  p->cleanup      = (void(*)(DrdClientobj*))(DRD_(cond_cleanup));
-  p->waiter_count = 0;
-  p->mutex        = 0;
+  p->cleanup       = (void(*)(DrdClientobj*))(DRD_(cond_cleanup));
+  p->delete_thread = 0;
+  p->waiter_count  = 0;
+  p->mutex         = 0;
 }
 
 /**
@@ -328,7 +329,3 @@ void DRD_(cond_pre_broadcast)(Addr const cond)
 
   DRD_(cond_signal)(cond);
 }
-
-/** Called after pthread_cond_destroy(). */
-void DRD_(cond_thread_delete)(const DrdThreadId tid)
-{ }
index fed3f0f2393877be7c4a9b6690c9e6670704b36e..e75caef259d1c33bb142cceb8fa920a0dc3d248e 100644 (file)
@@ -45,7 +45,6 @@ int DRD_(cond_pre_wait)(const Addr cond, const Addr mutex);
 int DRD_(cond_post_wait)(const Addr cond);
 void DRD_(cond_pre_signal)(const Addr cond);
 void DRD_(cond_pre_broadcast)(const Addr cond);
-void DRD_(cond_thread_delete)(const DrdThreadId tid);
 
 
 #endif /* __DRD_COND_H */
index db42abb36e26e590586408436545d10f4eda3edd..42597513ee3dfbed34ab047aa6e0e42af01e1c90 100644 (file)
 
 /* Local variables. */
 
-static Bool DRD_(s_show_conflicting_segments) = True;
+static Bool s_show_conflicting_segments = True;
 
 
 void DRD_(set_show_conflicting_segments)(const Bool scs)
 {
-  DRD_(s_show_conflicting_segments) = scs;
+  s_show_conflicting_segments = scs;
 }
 
 /**
@@ -55,8 +55,7 @@ void DRD_(set_show_conflicting_segments)(const Bool scs)
  * messages, putting the result in ai.
  */
 static
-void DRD_(describe_malloced_addr)(Addr const a, SizeT const len,
-                                  AddrInfo* const ai)
+void describe_malloced_addr(Addr const a, SizeT const len, AddrInfo* const ai)
 {
   Addr data;
 
@@ -76,7 +75,7 @@ void DRD_(describe_malloced_addr)(Addr const a, SizeT const len,
  * call stack will either refer to a pthread_*_init() or a pthread_*lock()
  * call.
  */
-static void DRD_(first_observed)(const Addr obj)
+static void first_observed(const Addr obj)
 {
   DrdClientobj* cl;
 
@@ -93,8 +92,7 @@ static void DRD_(first_observed)(const Addr obj)
 }
 
 static
-void DRD_(drd_report_data_race)(Error* const err,
-                                const DataRaceErrInfo* const dri)
+void drd_report_data_race(Error* const err, const DataRaceErrInfo* const dri)
 {
   AddrInfo ai;
   const unsigned descr_size = 256;
@@ -112,7 +110,7 @@ void DRD_(drd_report_data_race)(Error* const err,
   VG_(get_data_description)(descr1, descr2, descr_size, dri->addr);
   if (descr1[0] == 0)
   {
-    DRD_(describe_malloced_addr)(dri->addr, dri->size, &ai);
+    describe_malloced_addr(dri->addr, dri->size, &ai);
   }
   VG_(message)(Vg_UserMsg,
                "Conflicting %s by thread %d/%d at 0x%08lx size %ld",
@@ -153,7 +151,7 @@ void DRD_(drd_report_data_race)(Error* const err,
       VG_(message)(Vg_UserMsg, "Allocation context: unknown.");
     }
   }
-  if (DRD_(s_show_conflicting_segments))
+  if (s_show_conflicting_segments)
   {
     DRD_(thread_report_conflicting_segments)(dri->tid,
                                              dri->addr, dri->size,
@@ -164,17 +162,17 @@ void DRD_(drd_report_data_race)(Error* const err,
   VG_(free)(descr1);
 }
 
-static Bool DRD_(drd_tool_error_eq)(VgRes res, Error* e1, Error* e2)
+static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
 {
   return False;
 }
 
-static void DRD_(drd_tool_error_pp)(Error* const e)
+static void drd_tool_error_pp(Error* const e)
 {
   switch (VG_(get_error_kind)(e))
   {
   case DataRaceErr: {
-    DRD_(drd_report_data_race)(e, VG_(get_error_extra)(e));
+    drd_report_data_race(e, VG_(get_error_extra)(e));
     break;
   }
   case MutexErr: {
@@ -196,7 +194,7 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                    p->mutex);
     }
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(p->mutex);
+    first_observed(p->mutex);
     break;
   }
   case CondErr: {
@@ -206,7 +204,7 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                  VG_(get_error_string)(e),
                  cdei->cond);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(cdei->cond);
+    first_observed(cdei->cond);
     break;
   }
   case CondDestrErr: {
@@ -217,7 +215,7 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                  cdi->cond, cdi->mutex,
                  DRD_(DrdThreadIdToVgThreadId)(cdi->tid), cdi->tid);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(cdi->mutex);
+    first_observed(cdi->mutex);
     break;
   }
   case CondRaceErr: {
@@ -228,8 +226,8 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                  " by the signalling thread.",
                  cei->cond, cei->mutex);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(cei->cond);
-    DRD_(first_observed)(cei->mutex);
+    first_observed(cei->cond);
+    first_observed(cei->mutex);
     break;
   }
   case CondWaitErr: {
@@ -241,9 +239,9 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                  cwei->mutex1,
                  cwei->mutex2);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(cwei->cond);
-    DRD_(first_observed)(cwei->mutex1);
-    DRD_(first_observed)(cwei->mutex2);
+    first_observed(cwei->cond);
+    first_observed(cwei->mutex1);
+    first_observed(cwei->mutex2);
     break;
   }
   case SemaphoreErr: {
@@ -254,18 +252,26 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                  VG_(get_error_string)(e),
                  sei->semaphore);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(sei->semaphore);
+    first_observed(sei->semaphore);
     break;
   }
   case BarrierErr: {
-    BarrierErrInfo* bei =(BarrierErrInfo*)(VG_(get_error_extra)(e));
+    BarrierErrInfo* bei = (BarrierErrInfo*)(VG_(get_error_extra)(e));
     tl_assert(bei);
     VG_(message)(Vg_UserMsg,
                  "%s: barrier 0x%lx",
                  VG_(get_error_string)(e),
                  bei->barrier);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(bei->barrier);
+    if (bei->other_context)
+    {
+      VG_(message)(Vg_UserMsg,
+                   "Conflicting wait call by thread %d/%d:",
+                   DRD_(DrdThreadIdToVgThreadId)(bei->other_tid),
+                   bei->other_tid);
+      VG_(pp_ExeContext)(bei->other_context);
+    }
+    first_observed(bei->barrier);
     break;
   }
   case RwlockErr: {
@@ -276,7 +282,7 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                  VG_(get_error_string)(e),
                  p->rwlock);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(p->rwlock);
+    first_observed(p->rwlock);
     break;
   }
   case HoldtimeErr: {
@@ -292,7 +298,7 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
                  p->hold_time_ms,
                  p->threshold_ms);
     VG_(pp_ExeContext)(VG_(get_error_where)(e));
-    DRD_(first_observed)(p->synchronization_object);
+    first_observed(p->synchronization_object);
     break;
   }
   case GenericErr: {
@@ -310,7 +316,7 @@ static void DRD_(drd_tool_error_pp)(Error* const e)
   }
 }
 
-static UInt DRD_(drd_tool_error_update_extra)(Error* e)
+static UInt drd_tool_error_update_extra(Error* e)
 {
   switch (VG_(get_error_kind)(e))
   {
@@ -342,7 +348,7 @@ static UInt DRD_(drd_tool_error_update_extra)(Error* e)
   }
 }
 
-static Bool DRD_(drd_tool_error_recog)(Char* const name, Supp* const supp)
+static Bool drd_tool_error_recog(Char* const name, Supp* const supp)
 {
   SuppKind skind = 0;
 
@@ -376,12 +382,12 @@ static Bool DRD_(drd_tool_error_recog)(Char* const name, Supp* const supp)
 }
 
 static
-Bool DRD_(drd_tool_error_read_extra)(Int fd, Char* buf, Int nBuf, Supp* supp)
+Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp)
 {
   return True;
 }
 
-static Bool DRD_(drd_tool_error_matches)(Error* const e, Supp* const supp)
+static Bool drd_tool_error_matches(Error* const e, Supp* const supp)
 {
   switch (VG_(get_supp_kind)(supp))
   {
@@ -389,7 +395,7 @@ static Bool DRD_(drd_tool_error_matches)(Error* const e, Supp* const supp)
   return True;
 }
 
-static Char* DRD_(drd_tool_error_name)(Error* e)
+static Char* drd_tool_error_name(Error* e)
 {
   switch (VG_(get_error_kind)(e))
   {
@@ -410,19 +416,19 @@ static Char* DRD_(drd_tool_error_name)(Error* e)
   return 0;
 }
 
-static void DRD_(drd_tool_error_print_extra)(Error* e)
+static void drd_tool_error_print_extra(Error* e)
 { }
 
 void DRD_(register_error_handlers)(void)
 {
   // Tool error reporting.
-  VG_(needs_tool_errors)(DRD_(drd_tool_error_eq),
-                         DRD_(drd_tool_error_pp),
+  VG_(needs_tool_errors)(drd_tool_error_eq,
+                         drd_tool_error_pp,
                          True,
-                         DRD_(drd_tool_error_update_extra),
-                         DRD_(drd_tool_error_recog),
-                         DRD_(drd_tool_error_read_extra),
-                         DRD_(drd_tool_error_matches),
-                         DRD_(drd_tool_error_name),
-                         DRD_(drd_tool_error_print_extra));
+                         drd_tool_error_update_extra,
+                         drd_tool_error_recog,
+                         drd_tool_error_read_extra,
+                         drd_tool_error_matches,
+                         drd_tool_error_name,
+                         drd_tool_error_print_extra);
 }
index 2efa26fb8ebd7a4478e6f6fbbe635d93fb4ee640..34fd62b1142b2b2116177dad8112e788edddd7c1 100644 (file)
@@ -128,7 +128,9 @@ typedef struct {
 } SemaphoreErrInfo;
 
 typedef struct {
-   Addr barrier;
+   Addr        barrier;
+   DrdThreadId other_tid;
+   ExeContext* other_context;
 } BarrierErrInfo;
 
 typedef struct {
index a55959b6726a50b7d86ddf4ccac1a48954862d3d..fecb35585f74a0119fff8b123494f378850b6763 100644 (file)
 
 /* Local functions. */
 
-static void DRD_(mutex_cleanup)(struct mutex_info* p);
-static Bool DRD_(mutex_is_locked)(struct mutex_info* const p);
+static void mutex_cleanup(struct mutex_info* p);
+static Bool mutex_is_locked(struct mutex_info* const p);
+static void mutex_delete_thread(struct mutex_info* p, const DrdThreadId tid);
 
 
 /* Local variables. */
 
-static Bool DRD_(s_trace_mutex);
-static ULong DRD_(s_mutex_lock_count);
-static ULong DRD_(s_mutex_segment_creation_count);
-static UInt DRD_(s_mutex_lock_threshold_ms) = 1000 * 1000;
+static Bool s_trace_mutex;
+static ULong s_mutex_lock_count;
+static ULong s_mutex_segment_creation_count;
+static UInt s_mutex_lock_threshold_ms = 1000 * 1000;
 
 
 /* Function definitions. */
@@ -55,12 +56,12 @@ static UInt DRD_(s_mutex_lock_threshold_ms) = 1000 * 1000;
 void DRD_(mutex_set_trace)(const Bool trace_mutex)
 {
   tl_assert(!! trace_mutex == trace_mutex);
-  DRD_(s_trace_mutex) = trace_mutex;
+  s_trace_mutex = trace_mutex;
 }
 
 void DRD_(mutex_set_lock_threshold)(const UInt lock_threshold_ms)
 {
-  DRD_(s_mutex_lock_threshold_ms) = lock_threshold_ms;
+  s_mutex_lock_threshold_ms = lock_threshold_ms;
 }
 
 static
@@ -71,7 +72,9 @@ void DRD_(mutex_initialize)(struct mutex_info* const p,
   tl_assert(mutex_type != mutex_type_unknown);
   tl_assert(p->a1 == mutex);
 
-  p->cleanup             = (void(*)(DrdClientobj*))&(DRD_(mutex_cleanup));
+  p->cleanup             = (void(*)(DrdClientobj*))mutex_cleanup;
+  p->delete_thread
+    = (void(*)(DrdClientobj*, DrdThreadId))mutex_delete_thread;
   p->mutex_type          = mutex_type;
   p->recursion_count     = 0;
   p->owner               = DRD_INVALID_THREADID;
@@ -81,11 +84,11 @@ void DRD_(mutex_initialize)(struct mutex_info* const p,
 }
 
 /** Deallocate the memory that was allocated by mutex_initialize(). */
-static void DRD_(mutex_cleanup)(struct mutex_info* p)
+static void mutex_cleanup(struct mutex_info* p)
 {
   tl_assert(p);
 
-  if (DRD_(s_trace_mutex))
+  if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] mutex_destroy   %s 0x%lx rc %d owner %d",
@@ -97,7 +100,7 @@ static void DRD_(mutex_cleanup)(struct mutex_info* p)
                  p ? p->owner : DRD_INVALID_THREADID);
   }
 
-  if (DRD_(mutex_is_locked)(p))
+  if (mutex_is_locked(p))
   {
     MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner };
     VG_(maybe_record_error)(VG_(get_running_tid)(),
@@ -162,7 +165,7 @@ DRD_(mutex_init)(const Addr mutex, const MutexT mutex_type)
 
   tl_assert(mutex_type != mutex_type_unknown);
 
-  if (DRD_(s_trace_mutex))
+  if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] mutex_init      %s 0x%lx",
@@ -225,7 +228,7 @@ void DRD_(mutex_pre_lock)(const Addr mutex, MutexT mutex_type,
   if (mutex_type == mutex_type_unknown)
     mutex_type = p->mutex_type;
 
-  if (DRD_(s_trace_mutex))
+  if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] %s %s 0x%lx rc %d owner %d",
@@ -279,7 +282,7 @@ void DRD_(mutex_post_lock)(const Addr mutex, const Bool took_lock,
 
   p = DRD_(mutex_get)(mutex);
 
-  if (DRD_(s_trace_mutex))
+  if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] %s %s 0x%lx rc %d owner %d%s",
@@ -306,12 +309,12 @@ void DRD_(mutex_post_lock)(const Addr mutex, const Bool took_lock,
       DRD_(thread_combine_vc2)(drd_tid, &p->last_locked_segment->vc);
     }
     DRD_(thread_new_segment)(drd_tid);
-    DRD_(s_mutex_segment_creation_count)++;
+    s_mutex_segment_creation_count++;
 
     p->owner           = drd_tid;
     p->acquiry_time_ms = VG_(read_millisecond_timer)();
     p->acquired_at     = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
-    DRD_(s_mutex_lock_count)++;
+    s_mutex_lock_count++;
   }
   else if (p->owner != drd_tid)
   {
@@ -346,7 +349,7 @@ void DRD_(mutex_unlock)(const Addr mutex, MutexT mutex_type)
   if (mutex_type == mutex_type_unknown)
     mutex_type = p->mutex_type;
 
-  if (DRD_(s_trace_mutex))
+  if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] mutex_unlock    %s 0x%lx rc %d",
@@ -399,13 +402,13 @@ void DRD_(mutex_unlock)(const Addr mutex, MutexT mutex_type)
 
   if (p->recursion_count == 0)
   {
-    if (DRD_(s_mutex_lock_threshold_ms) > 0)
+    if (s_mutex_lock_threshold_ms > 0)
     {
       ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms;
-      if (held > DRD_(s_mutex_lock_threshold_ms))
+      if (held > s_mutex_lock_threshold_ms)
       {
         HoldtimeErrInfo HEI
-          = { mutex, p->acquired_at, held, DRD_(s_mutex_lock_threshold_ms) };
+          = { mutex, p->acquired_at, held, s_mutex_lock_threshold_ms };
         VG_(maybe_record_error)(vg_tid,
                                 HoldtimeErr,
                                 VG_(get_IP)(vg_tid),
@@ -421,7 +424,7 @@ void DRD_(mutex_unlock)(const Addr mutex, MutexT mutex_type)
     DRD_(thread_get_latest_segment)(&p->last_locked_segment, drd_tid);
     DRD_(thread_new_segment)(drd_tid);
     p->acquired_at = 0;
-    DRD_(s_mutex_segment_creation_count)++;
+    s_mutex_segment_creation_count++;
   }
 }
 
@@ -466,7 +469,7 @@ const char* DRD_(mutex_type_name)(const MutexT mt)
 }
 
 /** Return true if the specified mutex is locked by any thread. */
-static Bool DRD_(mutex_is_locked)(struct mutex_info* const p)
+static Bool mutex_is_locked(struct mutex_info* const p)
 {
   tl_assert(p);
   return (p->recursion_count > 0);
@@ -493,33 +496,29 @@ int DRD_(mutex_get_recursion_count)(const Addr mutex)
  * Call this function when thread tid stops to exist, such that the
  * "last owner" field can be cleared if it still refers to that thread.
  */
-void DRD_(mutex_thread_delete)(const DrdThreadId tid)
+static void mutex_delete_thread(struct mutex_info* p, const DrdThreadId tid)
 {
-  struct mutex_info* p;
+  tl_assert(p);
 
-  DRD_(clientobj_resetiter)();
-  for ( ; (p = &(DRD_(clientobj_next)(ClientMutex)->mutex)) != 0; )
+  if (p->owner == tid && p->recursion_count > 0)
   {
-    if (p->owner == tid && p->recursion_count > 0)
-    {
-      MutexErrInfo MEI
-        = { p->a1, p->recursion_count, p->owner };
-      VG_(maybe_record_error)(VG_(get_running_tid)(),
-                              MutexErr,
-                              VG_(get_IP)(VG_(get_running_tid)()),
-                              "Mutex still locked at thread exit",
-                              &MEI);
-      p->owner = VG_INVALID_THREADID;
-    }
+    MutexErrInfo MEI
+      = { p->a1, p->recursion_count, p->owner };
+    VG_(maybe_record_error)(VG_(get_running_tid)(),
+                            MutexErr,
+                            VG_(get_IP)(VG_(get_running_tid)()),
+                            "Mutex still locked at thread exit",
+                            &MEI);
+    p->owner = VG_INVALID_THREADID;
   }
 }
 
 ULong DRD_(get_mutex_lock_count)(void)
 {
-  return DRD_(s_mutex_lock_count);
+  return s_mutex_lock_count;
 }
 
 ULong DRD_(get_mutex_segment_creation_count)(void)
 {
-  return DRD_(s_mutex_segment_creation_count);
+  return s_mutex_segment_creation_count;
 }
index 07f2fb35f0041fa2a899227fa8f713b3f3de7ff4..a36f6014f89f5abcaa693482f28aa5bba18fb791 100644 (file)
@@ -50,7 +50,6 @@ const char* DRD_(mutex_get_typename)(struct mutex_info* const p);
 const char* DRD_(mutex_type_name)(const MutexT mt);
 Bool DRD_(mutex_is_locked_by)(const Addr mutex, const DrdThreadId tid);
 int DRD_(mutex_get_recursion_count)(const Addr mutex);
-void DRD_(mutex_thread_delete)(const DrdThreadId tid);
 ULong DRD_(get_mutex_lock_count)(void);
 ULong DRD_(get_mutex_segment_creation_count)(void);
 
index 7530b6b0af541fd54124ee51c83dcc701ca03fe8..2c29c44d070447c5cd75b40f84e196bb43b82a2e 100644 (file)
@@ -194,8 +194,10 @@ static void* DRD_(thread_wrapper)(void* arg)
 }
 
 /**
- * Return 1 if the LinuxThread implementation has been detected, and 0
- * otherwise. For more information about the confstr() function, see also
+ * Return 1 if the LinuxThreads implementation of POSIX Threads has been
+ * detected, and 0 otherwise.
+ *
+ * @see For more information about the confstr() function, see also
  * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
  */
 static int DRD_(detected_linuxthreads)(void)
@@ -283,7 +285,7 @@ PTH_FUNC(int, pthreadZucreateZa, // pthread_create*
   /*
    * Find out whether the thread will be started as a joinable thread
    * or as a detached thread. If no thread attributes have been specified,
-   * the new thread will be started as a joinable thread.
+   * this means that the new thread will be started as a joinable thread.
    */
   thread_args.detachstate = PTHREAD_CREATE_JOINABLE;
   if (attr)
@@ -706,7 +708,7 @@ PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
                              barrier, pthread_barrier,
                              ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
-                             0, 0);
+                             ret == PTHREAD_BARRIER_SERIAL_THREAD, 0);
   return ret;
 }
 
index 9b545d10f444e64f657726f50baa6739225cd0a7..12d89200a97d402405b83c160483fec877fa2bd1 100644 (file)
@@ -49,7 +49,9 @@ struct rwlock_thread_info
 
 /* Local functions. */
 
-static void DRD_(rwlock_cleanup)(struct rwlock_info* p);
+static void rwlock_cleanup(struct rwlock_info* p);
+static void rwlock_delete_thread(struct rwlock_info* const p,
+                                 const DrdThreadId tid);
 
 
 /* Local variables. */
@@ -184,7 +186,8 @@ void DRD_(rwlock_initialize)(struct rwlock_info* const p, const Addr rwlock)
   tl_assert(p->a1 == rwlock);
   tl_assert(p->type == ClientRwlock);
 
-  p->cleanup         = (void(*)(DrdClientobj*))&(DRD_(rwlock_cleanup));
+  p->cleanup         = (void(*)(DrdClientobj*))rwlock_cleanup;
+  p->delete_thread = (void(*)(DrdClientobj*, DrdThreadId))rwlock_delete_thread;
   p->thread_info     = VG_(OSetGen_Create)(
                           0, 0, VG_(malloc), "drd.rwlock.ri.1", VG_(free));
   p->acquiry_time_ms = 0;
@@ -192,7 +195,7 @@ void DRD_(rwlock_initialize)(struct rwlock_info* const p, const Addr rwlock)
 }
 
 /** Deallocate the memory that was allocated by rwlock_initialize(). */
-static void DRD_(rwlock_cleanup)(struct rwlock_info* p)
+static void rwlock_cleanup(struct rwlock_info* p)
 {
   struct rwlock_thread_info* q;
 
@@ -568,26 +571,21 @@ void DRD_(rwlock_pre_unlock)(const Addr rwlock)
  * Call this function when thread tid stops to exist, such that the
  * "last owner" field can be cleared if it still refers to that thread.
  */
-void DRD_(rwlock_thread_delete)(const DrdThreadId tid)
+static void rwlock_delete_thread(struct rwlock_info* const p,
+                                 const DrdThreadId tid)
 {
-  struct rwlock_info* p;
-
-  DRD_(clientobj_resetiter)();
-  for ( ; (p = &(DRD_(clientobj_next)(ClientRwlock)->rwlock)) != 0; )
+  struct rwlock_thread_info* q;
+  if (DRD_(rwlock_is_locked_by)(p, tid))
   {
-    struct rwlock_thread_info* q;
-    if (DRD_(rwlock_is_locked_by)(p, tid))
-    {
-      RwlockErrInfo REI = { p->a1 };
-      VG_(maybe_record_error)(VG_(get_running_tid)(),
-                              RwlockErr,
-                              VG_(get_IP)(VG_(get_running_tid)()),
-                              "Reader-writer lock still locked at thread exit",
-                              &REI);
-      q = DRD_(lookup_or_insert_node)(p->thread_info, tid);
-      q->reader_nesting_count = 0;
-      q->writer_nesting_count = 0;
-    }
+    RwlockErrInfo REI = { p->a1 };
+    VG_(maybe_record_error)(VG_(get_running_tid)(),
+                            RwlockErr,
+                            VG_(get_IP)(VG_(get_running_tid)()),
+                            "Reader-writer lock still locked at thread exit",
+                            &REI);
+    q = DRD_(lookup_or_insert_node)(p->thread_info, tid);
+    q->reader_nesting_count = 0;
+    q->writer_nesting_count = 0;
   }
 }
 
index 5f344e9dcc96f8506e7c6b018d473f54cff9afdf..abb59c7bbf5b4fdc25b390ba65ba76671e7c2bb7 100644 (file)
@@ -47,7 +47,6 @@ void DRD_(rwlock_post_rdlock)(const Addr rwlock, const Bool took_lock);
 void DRD_(rwlock_pre_wrlock)(const Addr rwlock);
 void DRD_(rwlock_post_wrlock)(const Addr rwlock, const Bool took_lock);
 void DRD_(rwlock_pre_unlock)(const Addr rwlock);
-void DRD_(rwlock_thread_delete)(const DrdThreadId tid);
 ULong DRD_(get_rwlock_segment_creation_count)(void);
 
 
index da99d06294a8d21fb7800346527941952fd24996..02d5c7d4f6e95f99e1942ac0ab1a38db34a77190 100644 (file)
 
 /* Local functions. */
 
-static void DRD_(semaphore_cleanup)(struct semaphore_info* p);
+static void semaphore_cleanup(struct semaphore_info* p);
 
 
 /* Local variables. */
 
-static Bool DRD_(s_trace_semaphore);
-static ULong DRD_(s_semaphore_segment_creation_count);
+static Bool s_trace_semaphore;
+static ULong s_semaphore_segment_creation_count;
 
 
 /* Function definitions. */
@@ -85,7 +85,7 @@ static Segment* DRD_(segment_pop)(struct semaphore_info* p)
 /** Enable or disable tracing of semaphore actions. */
 void DRD_(semaphore_set_trace)(const Bool trace_semaphore)
 {
-  DRD_(s_trace_semaphore) = trace_semaphore;
+  s_trace_semaphore = trace_semaphore;
 }
 
 /**
@@ -100,7 +100,8 @@ void DRD_(semaphore_initialize)(struct semaphore_info* const p,
   tl_assert(p->a1 == semaphore);
   tl_assert(p->type == ClientSemaphore);
 
-  p->cleanup           = (void(*)(DrdClientobj*))(DRD_(semaphore_cleanup));
+  p->cleanup           = (void(*)(DrdClientobj*))semaphore_cleanup;
+  p->delete_thread     = 0;
   p->waits_to_skip     = 0;
   p->value             = 0;
   p->waiters           = 0;
@@ -113,7 +114,7 @@ void DRD_(semaphore_initialize)(struct semaphore_info* const p,
  * Free the memory that was allocated by semaphore_initialize(). Called by
  * DRD_(clientobj_remove)().
  */
-static void DRD_(semaphore_cleanup)(struct semaphore_info* p)
+static void semaphore_cleanup(struct semaphore_info* p)
 {
   Segment* sg;
 
@@ -172,7 +173,7 @@ struct semaphore_info* DRD_(semaphore_init)(const Addr semaphore,
   struct semaphore_info* p;
   Segment* sg;
 
-  if (DRD_(s_trace_semaphore))
+  if (s_trace_semaphore)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] semaphore_init      0x%lx value %u",
@@ -214,7 +215,7 @@ void DRD_(semaphore_destroy)(const Addr semaphore)
 
   p = DRD_(semaphore_get)(semaphore);
 
-  if (DRD_(s_trace_semaphore))
+  if (s_trace_semaphore)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] semaphore_destroy   0x%lx value %u",
@@ -262,7 +263,7 @@ void DRD_(semaphore_post_wait)(const DrdThreadId tid, const Addr semaphore,
   Segment* sg;
 
   p = DRD_(semaphore_get)(semaphore);
-  if (DRD_(s_trace_semaphore))
+  if (s_trace_semaphore)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] semaphore_wait      0x%lx value %u -> %u",
@@ -304,7 +305,7 @@ void DRD_(semaphore_post_wait)(const DrdThreadId tid, const Addr semaphore,
       }
       DRD_(sg_put)(sg);
       DRD_(thread_new_segment)(tid);
-      DRD_(s_semaphore_segment_creation_count)++;
+      s_semaphore_segment_creation_count++;
     }
   }
 }
@@ -318,7 +319,7 @@ void DRD_(semaphore_pre_post)(const DrdThreadId tid, const Addr semaphore)
   p = DRD_(semaphore_get_or_allocate)(semaphore);
   p->value++;
 
-  if (DRD_(s_trace_semaphore))
+  if (s_trace_semaphore)
   {
     VG_(message)(Vg_UserMsg,
                  "[%d/%d] semaphore_post      0x%lx value %u -> %u",
@@ -334,7 +335,7 @@ void DRD_(semaphore_pre_post)(const DrdThreadId tid, const Addr semaphore)
   DRD_(thread_get_latest_segment)(&sg, tid);
   tl_assert(sg);
   DRD_(segment_push)(p, sg);
-  DRD_(s_semaphore_segment_creation_count)++;
+  s_semaphore_segment_creation_count++;
 }
 
 /** Called after sem_post() finished successfully. */
@@ -352,10 +353,7 @@ void DRD_(semaphore_post_post)(const DrdThreadId tid, const Addr semaphore,
   /* redirected functions.                                                 */
 }
 
-void DRD_(semaphore_thread_delete)(const DrdThreadId threadid)
-{ }
-
 ULong DRD_(get_semaphore_segment_creation_count)(void)
 {
-  return DRD_(s_semaphore_segment_creation_count);
+  return s_semaphore_segment_creation_count;
 }
index d57a23b466bd972a7c0c6d7c8dbadd14f3a651d2..e6b248fab84c68ef18be5ad041057aca0a7821d1 100644 (file)
@@ -47,7 +47,6 @@ void DRD_(semaphore_post_wait)(const DrdThreadId tid, const Addr semaphore,
 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_(semaphore_thread_delete)(const DrdThreadId tid);
 ULong DRD_(get_semaphore_segment_creation_count)(void);
 
 
index aeacbfa620f406e0dae541ebc966f5e10719b35e..5a8b130d2c6c8b5c0f3b56605ecde6d877b4410c 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "drd_error.h"
 #include "drd_barrier.h"
+#include "drd_clientobj.h"
 #include "drd_cond.h"
 #include "drd_mutex.h"
 #include "drd_segment.h"
@@ -302,11 +303,8 @@ void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
                              - DRD_(thread_get_stack_size)(drd_joinee),
                              DRD_(thread_get_stack_max)(drd_joinee));
   }
+  DRD_(clientobj_delete_thread)(drd_joinee);
   DRD_(thread_delete)(drd_joinee);
-  DRD_(mutex_thread_delete)(drd_joinee);
-  DRD_(cond_thread_delete)(drd_joinee);
-  DRD_(semaphore_thread_delete)(drd_joinee);
-  DRD_(barrier_thread_delete)(drd_joinee);
 }
 
 /**