Author: bart
Date: 2008-02-29 17:27:03 +0000 (Fri, 29 Feb 2008)
New Revision: 7508

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

Modified:
   trunk/exp-drd/TODO.txt
   trunk/exp-drd/drd_barrier.c
   trunk/exp-drd/drd_barrier.h
   trunk/exp-drd/drd_clientobj.c
   trunk/exp-drd/drd_clientobj.h
   trunk/exp-drd/drd_clientreq.c
   trunk/exp-drd/drd_clientreq.h
   trunk/exp-drd/drd_cond.c
   trunk/exp-drd/drd_cond.h
   trunk/exp-drd/drd_intercepts.c
   trunk/exp-drd/drd_main.c
   trunk/exp-drd/drd_mutex.c
   trunk/exp-drd/drd_semaphore.c
   trunk/exp-drd/drd_semaphore.h
   trunk/exp-drd/drd_track.h


Modified: trunk/exp-drd/TODO.txt
===================================================================
--- trunk/exp-drd/TODO.txt      2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/TODO.txt      2008-02-29 17:27:03 UTC (rev 7508)
@@ -8,8 +8,6 @@
 - Print an error message when memory is freed that contains a locked
   reader-writer synchronization object.
 - Print an error message when a semaphore is freed that is being waited upon.
-- Eliminate the upper bounds on the number of condition variables,
-  semaphores, barriers and threads by converting arrays into OSet's.
 - Implement segment merging, such that the number of segments per thread
   remains limited even when there is no synchronization between threads.
 - Add locking order checking.
@@ -33,6 +31,9 @@
   a crash on AMD64. Is this an exp-drd or a VEX bug ?
 - On x86 and amd64 platforms, add support for implicit locking arising from
   the use of the LOCK instruction prefix.
+- Add test programs for freeing memory that contains a condition variable /
+  destroying a condition variable being waited upon.
+- Convert the array in drd_thread.c with thread information into an OSet.
 
 
 Testing

Modified: trunk/exp-drd/drd_barrier.c
===================================================================
--- trunk/exp-drd/drd_barrier.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_barrier.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -24,6 +24,7 @@
 
 
 #include "drd_barrier.h"
+#include "drd_clientobj.h"
 #include "drd_error.h"
 #include "drd_suppression.h"
 #include "priv_drd_clientreq.h"
@@ -38,19 +39,6 @@
 
 // Type definitions.
 
-/* Information associated with a client-side pthread_barrier_t object. */
-struct barrier_info
-{
-  Addr  barrier;             // Client address of barrier.
-  SizeT size;                // Size in bytes of client-side object.
-  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_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.
-};
-
 /* Information associated with one thread participating in a barrier. */
 struct barrier_thread_info
 {
@@ -62,11 +50,14 @@
 };
 
 
+// Local functions.
+
+void barrier_cleanup(struct barrier_info* p);
+
+
 // Local variables.
 
 static Bool s_trace_barrier = False;
-/* To do: eliminate the upper limit on the number of barriers (4). */
-struct barrier_info s_barrier[4];
 
 
 // Function definitions.
@@ -106,9 +97,10 @@
   tl_assert(barrier != 0);
   tl_assert(size > 0);
   tl_assert(count > 0);
+  tl_assert(p->a1 == barrier);
+  tl_assert(p->a2 - p->a1 == size);
 
-  p->barrier           = barrier;
-  p->size              = size;
+  p->cleanup           = (void(*)(DrdClientobj*))barrier_cleanup;
   p->count             = count;
   p->pre_iteration     = 0;
   p->post_iteration    = 0;
@@ -120,14 +112,20 @@
   p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
 }
 
-/** Deallocate the memory allocated by barrier_initialize() and in p->oset. */
-void barrier_destroy(struct barrier_info* const p)
+/** Deallocate the memory allocated by barrier_initialize() and in p->oset. 
+ *  Called by drd_clientobj_destroy().
+ */
+void barrier_cleanup(struct barrier_info* p)
 {
   struct barrier_thread_info* q;
 
   tl_assert(p);
 
-  drd_finish_suppression(p->barrier, p->barrier + p->size);
+  if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
+  {
+    VG_(message)(Vg_UserMsg, "Destruction of barrier 0x%lx being waited upon",
+                 p->a1);
+  }
 
   VG_(OSetGen_ResetIter)(p->oset);
   for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
@@ -135,13 +133,6 @@
     barrier_thread_destroy(q);
   }
   VG_(OSetGen_Destroy)(p->oset);
-  p->barrier           = 0;
-  p->size              = 0;
-  p->count             = 0;
-  p->pre_iteration     = 0;
-  p->post_iteration    = 0;
-  p->pre_waiters_left  = 0;
-  p->post_waiters_left = 0;
 }
 
 /** Look up the client-side barrier address barrier in s_barrier[]. If not
@@ -150,31 +141,30 @@
 struct barrier_info*
 barrier_get_or_allocate(const Addr barrier, const SizeT size, const Word count)
 {
-  int i;
+  struct barrier_info *p;
 
-  for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
+  tl_assert(offsetof(DrdClientobj, barrier) == 0);
+  p = &drd_clientobj_get(barrier, ClientBarrier)->barrier;
+  if (p == 0)
   {
-    if (s_barrier[i].barrier == barrier)
-    {
-      tl_assert(s_barrier[i].size == size);
-      return &s_barrier[i];
-    }
+    p = &drd_clientobj_add(barrier, barrier + size, ClientBarrier)->barrier;
+    barrier_initialize(p, barrier, size, count);
   }
-  for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
-  {
-    if (s_barrier[i].barrier == 0)
-    {
-      barrier_initialize(&s_barrier[i], barrier, size, count);
-      drd_start_suppression(barrier, barrier + size, "barrier");
-      return &s_barrier[i];
-    }
-  }
-  tl_assert(0);
-  return 0;
+  return p;
 }
 
+/** Look up the address of the information associated with the client-side
+ *  barrier object. */
+struct barrier_info* 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. */
+ *  where count threads participate in each barrier.
+ *  Called before pthread_barrier_init().
+ */
 struct barrier_info*
 barrier_init(const Addr barrier, const SizeT size, const Word count)
 {
@@ -182,17 +172,14 @@
   return barrier_get_or_allocate(barrier, size, count);
 }
 
-/** Look up the address of the information associated with the client-side
- *  barrier object. */
-struct barrier_info* barrier_get(const Addr barrier)
+/** Called after pthread_barrier_destroy(). */
+void barrier_destroy(struct barrier_info* const p)
 {
-  int i;
-  for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
-    if (s_barrier[i].barrier == barrier)
-      return &s_barrier[i];
-  return 0;
+  tl_assert(p);
+  drd_clientobj_remove(p->a1, ClientBarrier);
 }
 
+/** Called before pthread_barrier_wait(). */
 void barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
 {
   struct barrier_info* p;
@@ -227,6 +214,7 @@
   }
 }
 
+/** Called after pthread_barrier_wait(). */
 void barrier_post_wait(const DrdThreadId tid, const Addr barrier,
                        const Bool waited)
 {
@@ -286,31 +274,15 @@
 /** Call this function when thread tid stops to exist. */
 void barrier_thread_delete(const DrdThreadId tid)
 {
-  int i;
+  struct barrier_info* p;
 
-  for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
+  drd_clientobj_resetiter();
+  for ( ; (p = &drd_clientobj_next(ClientBarrier)->barrier) != 0; )
   {
-    struct barrier_info* const p = &s_barrier[i];
-    if (p->barrier)
-    {
-      struct barrier_thread_info* q;
-      const UWord word_tid = tid;
-      q = VG_(OSetGen_Remove)(p->oset, &word_tid);
-      barrier_thread_destroy(q);
-      VG_(OSetGen_FreeNode)(p->oset, q);
-    }
+    struct barrier_thread_info* q;
+    const UWord word_tid = tid;
+    q = VG_(OSetGen_Remove)(p->oset, &word_tid);
+    barrier_thread_destroy(q);
+    VG_(OSetGen_FreeNode)(p->oset, q);
   }
 }
-
-void barrier_stop_using_mem(const Addr a1, const Addr a2)
-{
-  unsigned i;
-  for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
-  {
-    if (a1 <= s_barrier[i].barrier && s_barrier[i].barrier < a2)
-    {
-      tl_assert(s_barrier[i].barrier + s_barrier[i].size <= a2);
-      barrier_destroy(&s_barrier[i]);
-    }
-  }
-}

Modified: trunk/exp-drd/drd_barrier.h
===================================================================
--- trunk/exp-drd/drd_barrier.h 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_barrier.h 2008-02-29 17:27:03 UTC (rev 7508)
@@ -26,8 +26,8 @@
 // Barrier state information.
 
 
-#ifndef __BARRIER_H
-#define __BARRIER_H
+#ifndef __DRD_BARRIER_H
+#define __DRD_BARRIER_H
 
 
 #include "drd_thread.h"           // DrdThreadId
@@ -50,4 +50,4 @@
 void barrier_stop_using_mem(const Addr a1, const Addr a2);
 
 
-#endif /* __BARRIER_H */
+#endif /* __DRD_BARRIER_H */

Modified: trunk/exp-drd/drd_clientobj.c
===================================================================
--- trunk/exp-drd/drd_clientobj.c       2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientobj.c       2008-02-29 17:27:03 UTC (rev 7508)
@@ -120,10 +120,12 @@
   return p;
 }
 
-Bool drd_clientobj_remove(const Addr addr)
+Bool drd_clientobj_remove(const Addr addr, const ObjType t)
 {
   DrdClientobj* p;
 
+  p = VG_(OSetGen_Lookup)(s_clientobj, &addr);
+  tl_assert(p->any.type == t);
   p = VG_(OSetGen_Remove)(s_clientobj, &addr);
   if (p)
   {
@@ -163,7 +165,7 @@
                    a1, a2);
 #endif
       removed_at = p->any.a1;
-      drd_clientobj_remove(p->any.a1);
+      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)(s_clientobj);

Modified: trunk/exp-drd/drd_clientobj.h
===================================================================
--- trunk/exp-drd/drd_clientobj.h       2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientobj.h       2008-02-29 17:27:03 UTC (rev 7508)
@@ -30,6 +30,7 @@
 #include "drd_clientreq.h"   /* MutexT */
 #include "drd_thread.h"      /* DrdThreadId */
 #include "pub_tool_basics.h"
+#include "pub_tool_oset.h"
 
 
 // Forward declarations.
@@ -39,7 +40,12 @@
 
 // Type definitions.
 
-typedef enum { ClientMutex = 1, } ObjType;
+typedef enum {
+  ClientMutex     = 1,
+  ClientCondvar   = 2,
+  ClientSemaphore = 3,
+  ClientBarrier   = 4,
+} ObjType;
 
 struct any
 {
@@ -61,10 +67,50 @@
   VectorClock vc;              // vector clock associated with last unlock.
 };
 
+struct cond_info
+{
+  Addr    a1;
+  Addr    a2;
+  ObjType type;
+  void    (*cleanup)(union drd_clientobj*);
+  int     waiter_count;
+  Addr    mutex; // Client mutex specified in pthread_cond_wait() call, and 
null
+                 // if no client threads are currently waiting on this 
cond.var.
+};
+
+struct semaphore_info
+{
+  Addr        a1;
+  Addr        a2;
+  ObjType     type;
+  void        (*cleanup)(union drd_clientobj*);
+  UWord       value;             // Semaphore value.
+  UWord       waiters;           // Number of threads inside sem_wait().
+  DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post().
+  VectorClock vc;                // Vector clock of last sem_post() call.
+};
+
+struct barrier_info
+{
+  Addr    a1;
+  Addr    a2;
+  ObjType type;
+  void    (*cleanup)(union drd_clientobj*);
+  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_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.
+};
+
 typedef union drd_clientobj
 {
-  struct any        any;
-  struct mutex_info mutex;
+  struct any            any;
+  struct mutex_info     mutex;
+  struct cond_info      cond;
+  struct semaphore_info semaphore;
+  struct barrier_info   barrier;
 } DrdClientobj;
 
 
@@ -75,7 +121,7 @@
 DrdClientobj* drd_clientobj_get(const Addr addr, const ObjType t);
 Bool drd_clientobj_present(const Addr a1, const Addr a2);
 DrdClientobj* drd_clientobj_add(const Addr a1, const Addr a2, const ObjType t);
-Bool drd_clientobj_remove(const Addr addr);
+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);

Modified: trunk/exp-drd/drd_clientreq.c
===================================================================
--- trunk/exp-drd/drd_clientreq.c       2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientreq.c       2008-02-29 17:27:03 UTC (rev 7508)
@@ -189,6 +189,10 @@
       drd_semaphore_destroy(arg[1]);
       break;
 
+   case VG_USERREQ__PRE_SEM_WAIT:
+      drd_semaphore_pre_wait(thread_get_running_tid(), arg[1], arg[2]);
+      break;
+
    case VG_USERREQ__POST_SEM_WAIT:
       drd_semaphore_post_wait(thread_get_running_tid(), arg[1], arg[2]);
       break;

Modified: trunk/exp-drd/drd_clientreq.h
===================================================================
--- trunk/exp-drd/drd_clientreq.h       2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientreq.h       2008-02-29 17:27:03 UTC (rev 7508)
@@ -93,8 +93,11 @@
   VG_USERREQ__SEM_DESTROY,
   /* args: Addr sem */
   /* To notify the drd tool of a sem_wait call. */
+  VG_USERREQ__PRE_SEM_WAIT,
+  /* args: Addr sem, SizeT sem_size */
+  /* To notify the drd tool of a sem_wait call. */
   VG_USERREQ__POST_SEM_WAIT,
-  /* args: Addr sem, SizeT sem_size */
+  /* args: Addr sem, Bool waited */
   /* To notify the drd tool before a sem_post call. */
   VG_USERREQ__PRE_SEM_POST,
   /* args: Addr sem, SizeT sem_size */

Modified: trunk/exp-drd/drd_cond.c
===================================================================
--- trunk/exp-drd/drd_cond.c    2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_cond.c    2008-02-29 17:27:03 UTC (rev 7508)
@@ -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]);
-    }
-  }
-}

Modified: trunk/exp-drd/drd_cond.h
===================================================================
--- trunk/exp-drd/drd_cond.h    2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_cond.h    2008-02-29 17:27:03 UTC (rev 7508)
@@ -27,24 +27,17 @@
 // call.
 
 
-#ifndef __COND_H
-#define __COND_H
+#ifndef __DRD_COND_H
+#define __DRD_COND_H
 
 
-#include "pub_tool_basics.h"      // Addr, SizeT
-#include "drd_vc.h"
-#include "drd_thread.h"           // DrdThreadId
+#include "drd_thread.h"      // DrdThreadid
+#include "pub_tool_basics.h" // Addr, SizeT
 
 
-struct cond_info
-{
-  Addr  cond;  // Pointer to client condition variable.
-  SizeT size;  // sizeof(pthread_cond_t)
-  int   waiter_count;
-  Addr  mutex; // Client mutex specified in pthread_cond_wait() call, and null
-              // if no client threads are currently waiting on this cond.var.
-};
+struct cond_info;
 
+
 void cond_set_trace(const Bool trace_cond);
 void cond_init(const Addr cond, const SizeT size);
 void cond_destroy(struct cond_info* const p);
@@ -54,7 +47,6 @@
 void cond_pre_signal(const Addr cond);
 void cond_pre_broadcast(const Addr cond);
 void cond_thread_delete(const DrdThreadId tid);
-void cond_stop_using_mem(const Addr a1, const Addr a2);
 
 
-#endif /* __COND_H */
+#endif /* __DRD_COND_H */

Modified: trunk/exp-drd/drd_intercepts.c
===================================================================
--- trunk/exp-drd/drd_intercepts.c      2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_intercepts.c      2008-02-29 17:27:03 UTC (rev 7508)
@@ -706,15 +706,15 @@
    int   res;
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
    CALL_FN_W_W(ret, fn, sem);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
-                                 sem, sizeof(*sem), 0, 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
    return ret;
 }
 
+// sem_wait
 PTH_FUNC(int, sem_waitZa, // sem_wait*
               sem_t *sem)
 {
@@ -722,12 +722,11 @@
    int   res;
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
    CALL_FN_W_W(ret, fn, sem);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
-                                 sem, sizeof(*sem), 0, 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
    return ret;
 }
 
@@ -739,12 +738,11 @@
    int   res;
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
    CALL_FN_W_W(ret, fn, sem);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
-                                 sem, sizeof(*sem), 0, 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
    return ret;
 }
 
@@ -755,12 +753,11 @@
    int   res;
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
    CALL_FN_W_W(ret, fn, sem);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
-                                 sem, sizeof(*sem), 0, 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
    return ret;
 }
 
@@ -772,12 +769,11 @@
    int   res;
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
    CALL_FN_W_WW(ret, fn, sem, abs_timeout);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
-                                 sem, sizeof(*sem), 0, 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
    return ret;
 }
 

Modified: trunk/exp-drd/drd_main.c
===================================================================
--- trunk/exp-drd/drd_main.c    2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_main.c    2008-02-29 17:27:03 UTC (rev 7508)
@@ -82,6 +82,7 @@
    Bool trace_danger_set  = False;
    Bool trace_mutex       = False;
    Bool trace_segment     = False;
+   Bool trace_semaphore   = False;
    Bool trace_suppression = False;
    Char* trace_address    = 0;
 
@@ -94,6 +95,7 @@
    else VG_BOOL_CLO(arg, "--trace-mem",         drd_trace_mem)
    else VG_BOOL_CLO(arg, "--trace-mutex",       trace_mutex)
    else VG_BOOL_CLO(arg, "--trace-segment",     trace_segment)
+   else VG_BOOL_CLO(arg, "--trace-semaphore",   trace_semaphore)
    else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
    else VG_STR_CLO (arg, "--trace-address",     trace_address)
    else
@@ -115,6 +117,8 @@
       mutex_set_trace(trace_mutex);
    if (trace_segment)
       sg_set_trace(trace_segment);
+   if (trace_semaphore)
+      semaphore_set_trace(trace_semaphore);
    if (trace_suppression)
       suppression_set_trace(trace_suppression);
 
@@ -277,9 +281,6 @@
    }
    thread_stop_using_mem(a1, a2);
    drd_clientobj_stop_using_mem(a1, a2);
-   cond_stop_using_mem(a1, a2);
-   semaphore_stop_using_mem(a1, a2);
-   barrier_stop_using_mem(a1, a2);
    drd_suppression_stop_using_mem(a1, a2);
 }
 
@@ -491,10 +492,16 @@
    }
 }
 
+void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
+                            const SizeT size)
+{
+   semaphore_pre_wait(semaphore, size);
+}
+
 void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
-                             const SizeT size)
+                             const Bool waited)
 {
-   semaphore_post_wait(tid, semaphore, size);
+   semaphore_post_wait(tid, semaphore, waited);
 }
 
 void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,

Modified: trunk/exp-drd/drd_mutex.c
===================================================================
--- trunk/exp-drd/drd_mutex.c   2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_mutex.c   2008-02-29 17:27:03 UTC (rev 7508)
@@ -169,7 +169,7 @@
 
 static void mutex_destroy(struct mutex_info* const p)
 {
-  drd_clientobj_remove(p->a1);
+  drd_clientobj_remove(p->a1, ClientMutex);
 }
 
 /** Called after pthread_mutex_destroy(). */

Modified: trunk/exp-drd/drd_semaphore.c
===================================================================
--- trunk/exp-drd/drd_semaphore.c       2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_semaphore.c       2008-02-29 17:27:03 UTC (rev 7508)
@@ -23,6 +23,7 @@
 */
 
 
+#include "drd_clientobj.h"
 #include "drd_error.h"
 #include "drd_semaphore.h"
 #include "drd_suppression.h"
@@ -34,22 +35,14 @@
 #include "pub_tool_threadstate.h" // VG_(get_running_tid)()
 
 
-// Type definitions.
+// Local functions.
 
-struct semaphore_info
-{
-  Addr        semaphore;         // Pointer to client semaphore.
-  SizeT       size;              // Size in bytes of client-side object.
-  UWord       value;             // Semaphore value.
-  DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post().
-  VectorClock vc;                // Vector clock of last sem_post() call.
-};
+static void semaphore_cleanup(struct semaphore_info* p);
 
 
 // Local variables.
 
 static Bool s_trace_semaphore;
-struct semaphore_info s_semaphore[256];
 
 
 // Function definitions.
@@ -67,41 +60,55 @@
 {
   tl_assert(semaphore != 0);
   tl_assert(size > 0);
+  tl_assert(p->a1 == semaphore);
+  tl_assert(p->a2 - p->a1 == size);
+  tl_assert(p->type == ClientSemaphore);
 
-  p->semaphore = semaphore;
-  p->size      = size;
+  p->cleanup   = (void(*)(DrdClientobj*))semaphore_cleanup;
   p->value     = value;
+  p->waiters   = 0;
   p->last_sem_post_tid = DRD_INVALID_THREADID;
   vc_init(&p->vc, 0, 0);
 }
 
+/** Free the memory that was allocated by semaphore_initialize(). Called by
+ *  drd_clientobj_remove().
+ */
+static void semaphore_cleanup(struct semaphore_info* p)
+{
+  if (p->waiters > 0)
+  {
+    VG_(message)(Vg_UserMsg, "Error: destroying semaphore while %d threads are"
+                 "still waiting on the semaphore.\n", p->waiters);
+  }
+  vc_cleanup(&p->vc);
+}
+
 static
 struct semaphore_info*
 semaphore_get_or_allocate(const Addr semaphore, const SizeT size)
 {
-  int i;
+  struct semaphore_info *p;
 
-  for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
+  tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+  p = &drd_clientobj_get(semaphore, ClientSemaphore)->semaphore;
+  if (p == 0)
   {
-    if (s_semaphore[i].semaphore == semaphore)
-    {
-      tl_assert(s_semaphore[i].size == size);
-      return &s_semaphore[i];
-    }
+    tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+    p = &drd_clientobj_add(semaphore, semaphore + size,
+                           ClientSemaphore)->semaphore;
+    semaphore_initialize(p, semaphore, size, 0);
   }
-  for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
-  {
-    if (s_semaphore[i].semaphore == 0)
-    {
-      semaphore_initialize(&s_semaphore[i], semaphore, size, 0);
-      drd_start_suppression(semaphore, semaphore + size, "semaphore");
-      return &s_semaphore[i];
-    }
-  }
-  tl_assert(0);
-  return 0;
+  return p;
 }
 
+struct semaphore_info* semaphore_get(const Addr semaphore)
+{
+  tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+  return &drd_clientobj_get(semaphore, ClientSemaphore)->semaphore;
+}
+
+/** Called before sem_init(). */
 struct semaphore_info* semaphore_init(const Addr semaphore, const SizeT size,
                                       const Word pshared, const UWord value)
 {
@@ -113,31 +120,51 @@
   return p;
 }
 
+/** Called after sem_destroy(). */
 void semaphore_destroy(struct semaphore_info* const p)
 {
-  drd_finish_suppression(p->semaphore, p->semaphore + p->size);
-
-  vc_cleanup(&p->vc);
-  p->semaphore = 0;
+  drd_clientobj_remove(p->a1, ClientSemaphore);
 }
 
-struct semaphore_info* semaphore_get(const Addr semaphore)
+/** Called before sem_wait(). */
+void semaphore_pre_wait(const Addr semaphore, const SizeT size)
 {
-  int i;
-  for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
-    if (s_semaphore[i].semaphore == semaphore)
-      return &s_semaphore[i];
-  return 0;
+  struct semaphore_info* p;
+
+  p = semaphore_get_or_allocate(semaphore, size);
+  if (s_trace_semaphore)
+  {
+    VG_(message)(Vg_UserMsg, "semaphore_pre_wait(0x%lx, %d)", semaphore, size);
+  }
+  tl_assert(p);
+  tl_assert(p->waiters >= 0);
+  p->waiters++;
+  tl_assert(p->waiters > 0);
 }
 
-/** Called after sem_wait() finished successfully. */
+/** Called after sem_wait() finished.
+ *  @note Do not rely on the value of 'waited' -- some glibc versions do
+ *        not set it correctly.
+ */
 void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
-                         const SizeT size)
+                         const Bool waited)
 {
   struct semaphore_info* p;
 
-  p = semaphore_get_or_allocate(semaphore, size);
+  p = semaphore_get(semaphore);
+  if (s_trace_semaphore)
+  {
+    VG_(message)(Vg_UserMsg, "semaphore_post_wait(0x%lx, %d)", semaphore);
+  }
+  tl_assert(p->waiters > 0);
+  p->waiters--;
+  tl_assert(p->waiters >= 0);
   tl_assert(p->value >= 0);
+  if (p->value == 0)
+  {
+    VG_(message)(Vg_UserMsg, "Invalid semaphore 0x%lx", semaphore);
+    return;
+  }
   p->value--;
   tl_assert(p->value >= 0);
   if (p->last_sem_post_tid != tid)
@@ -178,16 +205,3 @@
 
 void semaphore_thread_delete(const DrdThreadId threadid)
 { }
-
-void semaphore_stop_using_mem(const Addr a1, const Addr a2)
-{
-  unsigned i;
-  for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
-  {
-    if (a1 <= s_semaphore[i].semaphore && s_semaphore[i].semaphore < a2)
-    {
-      tl_assert(s_semaphore[i].semaphore + s_semaphore[i].size <= a2);
-      semaphore_destroy(&s_semaphore[i]);
-    }
-  }
-}

Modified: trunk/exp-drd/drd_semaphore.h
===================================================================
--- trunk/exp-drd/drd_semaphore.h       2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_semaphore.h       2008-02-29 17:27:03 UTC (rev 7508)
@@ -26,8 +26,8 @@
 // Semaphore state information: owner thread and recursion count.
 
 
-#ifndef __SEMAPHORE_H
-#define __SEMAPHORE_H
+#ifndef __DRD_SEMAPHORE_H
+#define __DRD_SEMAPHORE_H
 
 
 #include "drd_thread.h"           // DrdThreadId
@@ -43,14 +43,14 @@
                                       const Word pshared, const UWord value);
 void semaphore_destroy(struct semaphore_info* const p);
 struct semaphore_info* semaphore_get(const Addr semaphore);
+void semaphore_pre_wait(const Addr semaphore, const SizeT size);
 void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
-                         const SizeT size);
+                         const Bool waited);
 void semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
                         const SizeT size);
 void semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
                          const SizeT size, const Bool waited);
 void semaphore_thread_delete(const DrdThreadId tid);
-void semaphore_stop_using_mem(const Addr a1, const Addr a2);
 
 
-#endif /* __SEMAPHORE_H */
+#endif /* __DRD_SEMAPHORE_H */

Modified: trunk/exp-drd/drd_track.h
===================================================================
--- trunk/exp-drd/drd_track.h   2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_track.h   2008-02-29 17:27:03 UTC (rev 7508)
@@ -40,8 +40,10 @@
 void drd_semaphore_init(const Addr semaphore, const SizeT size,
                         const Word pshared, const Word value);
 void drd_semaphore_destroy(const Addr semaphore);
+void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
+                            const SizeT size);
 void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
-                             const SizeT size);
+                             const Bool waited);
 void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
                             const SizeT size);
 void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Valgrind-developers mailing list
Valgrind-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-developers

Reply via email to