Eliminated upper bounds on the number of condition variables, semaphores and barriers. Added command-line option --trace-semaphore.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7508 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/exp-drd/drd_cond.c b/exp-drd/drd_cond.c
index 6fdd912..3de2f3b 100644
--- a/exp-drd/drd_cond.c
+++ b/exp-drd/drd_cond.c
@@ -23,6 +23,7 @@
 */
 
 
+#include "drd_clientobj.h"
 #include "drd_cond.h"
 #include "drd_error.h"
 #include "drd_mutex.h"
@@ -35,10 +36,18 @@
 #include "pub_tool_threadstate.h" // VG_(get_running_tid)()
 
 
-static struct cond_info s_cond[256];
+// Local functions.
+
+static void cond_cleanup(struct cond_info* p);
+
+
+// Local variables.
+
 static Bool s_trace_cond;
 
 
+// Function definitions.
+
 void cond_set_trace(const Bool trace_cond)
 {
   s_trace_cond = trace_cond;
@@ -49,81 +58,82 @@
                      const SizeT size)
 {
   tl_assert(cond != 0);
+  tl_assert(p->a1         == cond);
+  tl_assert(p->a2 - p->a1 == size);
+  tl_assert(p->type       == ClientCondvar);
 
-  p->cond         = cond;
-  p->size         = size;
+  p->cleanup      = (void(*)(DrdClientobj*))cond_cleanup;
   p->waiter_count = 0;
   p->mutex        = 0;
 }
 
+/** Free the memory that was allocated by cond_initialize(). Called by
+ *  drd_clientobj_remove().
+ */
+static void cond_cleanup(struct cond_info* p)
+{
+  tl_assert(p);
+  if (p->mutex)
+  {
+    struct mutex_info* q;
+    q = &drd_clientobj_get(p->mutex, ClientMutex)->mutex;
+    VG_(message)(Vg_UserMsg,
+                 "Error: destroying condition variable 0x%lx while thread %d"
+                 " is waiting on it.\n",
+                 p->a1, q ? q->owner : -1);
+  }
+}
+
 static struct cond_info*
 cond_get_or_allocate(const Addr cond, const SizeT size)
 {
-  int i;
-  for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
+  struct cond_info *p;
+
+  tl_assert(offsetof(DrdClientobj, cond) == 0);
+  p = &drd_clientobj_get(cond, ClientCondvar)->cond;
+  if (p == 0)
   {
-    if (s_cond[i].cond == cond)
-    {
-      tl_assert(s_cond[i].size == size);
-      return &s_cond[i];
-    }
+    p = &drd_clientobj_add(cond, cond + size, ClientCondvar)->cond;
+    cond_initialize(p, cond, size);
   }
-  for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
-  {
-    if (s_cond[i].cond == 0)
-    {
-      cond_initialize(&s_cond[i], cond, size);
-      /* TO DO: replace the constant below by a symbolic constant referring */
-      /* to sizeof(pthread_cond_t).                                        */
-      drd_start_suppression(cond, cond + size, "cond");
-      return &s_cond[i];
-    }
-  }
-  tl_assert(0);
-  return 0;
+  return p;
 }
 
+struct cond_info* cond_get(const Addr cond)
+{
+  tl_assert(offsetof(DrdClientobj, cond) == 0);
+  return &drd_clientobj_get(cond, ClientCondvar)->cond;
+}
+
+/** Called before pthread_cond_init(). */
 void cond_init(const Addr cond, const SizeT size)
 {
   if (s_trace_cond)
   {
     VG_(message)(Vg_UserMsg, "Initializing condition variable 0x%lx", cond);
-    VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
-                               VG_(clo_backtrace_size));
+    VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
   }
   tl_assert(cond_get(cond) == 0);
   tl_assert(size > 0);
   cond_get_or_allocate(cond, size);
 }
 
+/** Called after pthread_cond_destroy(). */
 void cond_destroy(struct cond_info* const p)
 {
   if (s_trace_cond)
   {
-    VG_(message)(Vg_UserMsg, "Destroying condition variable 0x%lx", p->cond);
-    VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
-                               VG_(clo_backtrace_size));
+    VG_(message)(Vg_UserMsg, "Destroying condition variable 0x%lx", p->a1);
+    VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
   }
 
   // TO DO: print a proper error message if waiter_count != 0.
   tl_assert(p->waiter_count == 0);
 
-  drd_finish_suppression(p->cond, p->cond + p->size);
-
-  p->cond         = 0;
-  p->waiter_count = 0;
-  p->mutex        = 0;
+  drd_clientobj_remove(p->a1, ClientCondvar);
 }
 
-struct cond_info* cond_get(const Addr cond)
-{
-  int i;
-  for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
-    if (s_cond[i].cond == cond)
-      return &s_cond[i];
-  return 0;
-}
-
+/** Called before pthread_cond_wait(). */
 int cond_pre_wait(const Addr cond, const SizeT cond_size, const Addr mutex)
 {
   struct cond_info* p;
@@ -143,6 +153,7 @@
   return ++p->waiter_count;
 }
 
+/** Called after pthread_cond_wait(). */
 int cond_post_wait(const Addr cond)
 {
   struct cond_info* p;
@@ -158,17 +169,12 @@
   return p->waiter_count;
 }
 
+/** Called before pthread_cond_signal(). */
 void cond_pre_signal(Addr const cond)
 {
   const ThreadId vg_tid = VG_(get_running_tid)();
   const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
   struct cond_info* const cond_p = cond_get(cond);
-#if 0
-  VG_(message)(Vg_DebugMsg, "cond_pre_signal cond %d, w.c. %d, mutex %d",
-               cond,
-               cond_p ? cond_p->waiter_count : 0,
-               cond_p ? cond_p->mutex : 0);
-#endif
   if (cond_p && cond_p->waiter_count > 0)
   {
     if (! mutex_is_locked_by(cond_p->mutex, drd_tid))
@@ -190,23 +196,12 @@
   }
 }
 
+/** Called before pthread_cond_broadcast(). */
 void cond_pre_broadcast(Addr const cond)
 {
   cond_pre_signal(cond);
 }
 
+/** Called after pthread_cond_destroy(). */
 void cond_thread_delete(const DrdThreadId tid)
 { }
-
-void cond_stop_using_mem(const Addr a1, const Addr a2)
-{
-  unsigned i;
-  for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
-  {
-    if (a1 <= s_cond[i].cond && s_cond[i].cond < a2)
-    {
-      tl_assert(s_cond[i].cond + s_cond[i].size <= a2);
-      cond_destroy(&s_cond[i]);
-    }
-  }
-}