Enabled support for nesting mutexes and condition variables in higher-level synchronization primitives. Changed mutex tracing output slightly.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8377 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c
index 9a267e5..6078dea 100644
--- a/drd/drd_clientreq.c
+++ b/drd/drd_clientreq.c
@@ -257,13 +257,21 @@
     break;
 
   case VG_USERREQ__PRE_COND_INIT:
-    tl_assert(thread_get_synchr_nesting_count(drd_tid) == 0);
-    drd_pre_cond_init(arg[1]);
+    if (thread_enter_synchr(drd_tid) == 0)
+      drd_pre_cond_init(arg[1]);
+    break;
+
+  case VG_USERREQ__POST_COND_INIT:
+    thread_leave_synchr(drd_tid);
+    break;
+
+  case VG_USERREQ__PRE_COND_DESTROY:
+    thread_enter_synchr(drd_tid);
     break;
 
   case VG_USERREQ__POST_COND_DESTROY:
-    tl_assert(thread_get_synchr_nesting_count(drd_tid) == 0);
-    drd_post_cond_destroy(arg[1]);
+    if (thread_leave_synchr(drd_tid) == 0)
+      drd_post_cond_destroy(arg[1]);
     break;
 
   case VG_USERREQ__PRE_COND_WAIT:
@@ -277,13 +285,21 @@
     break;
 
   case VG_USERREQ__PRE_COND_SIGNAL:
-    tl_assert(thread_get_synchr_nesting_count(drd_tid) == 0);
-    drd_pre_cond_signal(arg[1]);
+    if (thread_enter_synchr(drd_tid) == 0)
+      drd_pre_cond_signal(arg[1]);
+    break;
+
+  case VG_USERREQ__POST_COND_SIGNAL:
+    thread_leave_synchr(drd_tid);
     break;
 
   case VG_USERREQ__PRE_COND_BROADCAST:
-    tl_assert(thread_get_synchr_nesting_count(drd_tid) == 0);
-    drd_pre_cond_broadcast(arg[1]);
+    if (thread_enter_synchr(drd_tid) == 0)
+      drd_pre_cond_broadcast(arg[1]);
+    break;
+
+  case VG_USERREQ__POST_COND_BROADCAST:
+    thread_leave_synchr(drd_tid);
     break;
 
   case VG_USERREQ__PRE_SEM_INIT:
diff --git a/drd/drd_clientreq.h b/drd/drd_clientreq.h
index 2403382..b80b8a8 100644
--- a/drd/drd_clientreq.h
+++ b/drd/drd_clientreq.h
@@ -94,17 +94,27 @@
   /* to notify the drd tool of a pthread_cond_init call. */
   VG_USERREQ__PRE_COND_INIT,
   /* args: Addr */
+  /* to notify the drd tool of a pthread_cond_init call. */
+  VG_USERREQ__POST_COND_INIT,
+  /* args: Addr */
+  /* to notify the drd tool of a pthread_cond_destroy call. */
+  VG_USERREQ__PRE_COND_DESTROY,
+  /* args: Addr */
   /* to notify the drd tool of a pthread_cond_destroy call. */
   VG_USERREQ__POST_COND_DESTROY,
-  /* args: Addr cond */
+  /* args: Addr */
   VG_USERREQ__PRE_COND_WAIT,
   /* args: Addr cond, Addr mutex, MutexT mt */
   VG_USERREQ__POST_COND_WAIT,
   /* args: Addr cond, Addr mutex, Bool took_lock*/
   VG_USERREQ__PRE_COND_SIGNAL,
   /* args: Addr cond */
+  VG_USERREQ__POST_COND_SIGNAL,
+  /* args: Addr cond */
   VG_USERREQ__PRE_COND_BROADCAST,
   /* args: Addr cond */
+  VG_USERREQ__POST_COND_BROADCAST,
+  /* args: Addr cond */
 
   /* To notify the drd tool of a sem_init call. */
   VG_USERREQ__PRE_SEM_INIT,
@@ -179,11 +189,12 @@
 
 typedef enum
 {
-   mutex_type_invalid_mutex    = 0,
-   mutex_type_recursive_mutex  = 1,
-   mutex_type_errorcheck_mutex = 2,
-   mutex_type_default_mutex    = 3,
-   mutex_type_spinlock         = 4
+  mutex_type_unknown          = -1,
+  mutex_type_invalid_mutex    = 0,
+  mutex_type_recursive_mutex  = 1,
+  mutex_type_errorcheck_mutex = 2,
+  mutex_type_default_mutex    = 3,
+  mutex_type_spinlock         = 4
 } MutexT;
 
 typedef enum
diff --git a/drd/drd_mutex.c b/drd/drd_mutex.c
index db1ef84..fe0888c 100644
--- a/drd/drd_mutex.c
+++ b/drd/drd_mutex.c
@@ -67,9 +67,10 @@
 void mutex_initialize(struct mutex_info* const p,
                       const Addr mutex, const MutexT mutex_type)
 {
-  tl_assert(mutex != 0);
-
+  tl_assert(mutex);
+  tl_assert(mutex_type != mutex_type_unknown);
   tl_assert(p->a1 == mutex);
+
   p->cleanup             = (void(*)(DrdClientobj*))&mutex_cleanup;
   p->mutex_type          = mutex_type;
   p->recursion_count     = 0;
@@ -87,11 +88,13 @@
   if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
-                 "[%d/%d] mutex_destroy   %s 0x%lx",
+                 "[%d/%d] mutex_destroy   %s 0x%lx rc %d owner %d",
                  VG_(get_running_tid)(),
                  thread_get_running_tid(),
                  mutex_get_typename(p),
-                 p->a1);
+                 p->a1,
+                 p ? p->recursion_count : -1,
+                 p ? p->owner : DRD_INVALID_THREADID);
   }
 
   if (mutex_is_locked(p))
@@ -138,6 +141,8 @@
     return 0;
   }
 
+  tl_assert(mutex_type != mutex_type_unknown);
+
   p = &clientobj_add(mutex, ClientMutex)->mutex;
   mutex_initialize(p, mutex, mutex_type);
   return p;
@@ -155,6 +160,8 @@
 {
   struct mutex_info* p;
 
+  tl_assert(mutex_type != mutex_type_unknown);
+
   if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
@@ -209,18 +216,22 @@
  *  an attempt is made to lock recursively a synchronization object that must
  *  not be locked recursively.
  */
-void mutex_pre_lock(const Addr mutex, const MutexT mutex_type,
+void mutex_pre_lock(const Addr mutex, MutexT mutex_type,
                     const Bool trylock)
 {
   struct mutex_info* p;
 
   p = mutex_get_or_allocate(mutex, mutex_type);
+  if (mutex_type == mutex_type_unknown)
+    mutex_type = p->mutex_type;
+
   if (s_trace_mutex)
   {
     VG_(message)(Vg_UserMsg,
-                 "[%d/%d] pre_mutex_lock  %s 0x%lx rc %d owner %d",
+                 "[%d/%d] %s %s 0x%lx rc %d owner %d",
                  VG_(get_running_tid)(),
                  thread_get_running_tid(),
+                 trylock ? "pre_mutex_lock " : "mutex_trylock  ",
                  p ? mutex_get_typename(p) : "(?)",
                  mutex,
                  p ? p->recursion_count : -1,
@@ -325,11 +336,15 @@
  *  @note This function must be called before pthread_mutex_unlock() is called,
  *        or a race condition is triggered !
  */
-void mutex_unlock(const Addr mutex, const MutexT mutex_type)
+void mutex_unlock(const Addr mutex, MutexT mutex_type)
 {
   const DrdThreadId drd_tid = thread_get_running_tid();
   const ThreadId vg_tid = VG_(get_running_tid)();
-  struct mutex_info* const p = mutex_get(mutex);
+  struct mutex_info* p;
+
+  p = mutex_get(mutex);
+  if (mutex_type == mutex_type_unknown)
+    mutex_type = p->mutex_type;
 
   if (s_trace_mutex)
   {
diff --git a/drd/drd_pthread_intercepts.c b/drd/drd_pthread_intercepts.c
index 62dd1d9..064804e 100644
--- a/drd/drd_pthread_intercepts.c
+++ b/drd/drd_pthread_intercepts.c
@@ -1,6 +1,6 @@
 
 /*--------------------------------------------------------------------*/
-/*--- Client-space code for drd.                  drd_intercepts.c ---*/
+/*--- Client-space code for drd.          drd_pthread_intercepts.c ---*/
 /*--------------------------------------------------------------------*/
 
 /*
@@ -460,6 +460,8 @@
   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_INIT,
                              cond, 0, 0, 0, 0);
   CALL_FN_W_WW(ret, fn, cond, attr);
+  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_INIT,
+                             cond, 0, 0, 0, 0);
   return ret;
 }
 
@@ -471,6 +473,8 @@
   int res;
   OrigFn fn;
   VALGRIND_GET_ORIG_FN(fn);
+  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_DESTROY,
+                             cond, 0, 0, 0, 0);
   CALL_FN_W_W(ret, fn, cond);
   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY,
                              cond, 0, 0, 0, 0);
@@ -523,6 +527,8 @@
   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL,
                              cond, 0, 0, 0, 0);
   CALL_FN_W_W(ret, fn, cond);
+  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL,
+                             cond, 0, 0, 0, 0);
   return ret;
 }
 
@@ -537,6 +543,8 @@
   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_BROADCAST,
                              cond, 0, 0, 0, 0);
   CALL_FN_W_W(ret, fn, cond);
+  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_BROADCAST,
+                             cond, 0, 0, 0, 0);
   return ret;
 }