]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Added detection of more types of runtime errors. Cleaned up tracing output. Added...
authorBart Van Assche <bvanassche@acm.org>
Fri, 29 Feb 2008 19:28:15 +0000 (19:28 +0000)
committerBart Van Assche <bvanassche@acm.org>
Fri, 29 Feb 2008 19:28:15 +0000 (19:28 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7511

18 files changed:
exp-drd/drd_barrier.c
exp-drd/drd_clientreq.c
exp-drd/drd_clientreq.h
exp-drd/drd_cond.c
exp-drd/drd_error.c
exp-drd/drd_error.h
exp-drd/drd_intercepts.c
exp-drd/drd_main.c
exp-drd/drd_mutex.c
exp-drd/drd_mutex.h
exp-drd/drd_semaphore.c
exp-drd/drd_track.h
exp-drd/tests/Makefile.am
exp-drd/tests/tc18_semabuse.stderr.exp
exp-drd/tests/tc20_verifywrap.stderr.exp2
exp-drd/tests/tc20_verifywrap2.stderr.exp [new file with mode: 0644]
exp-drd/tests/tc20_verifywrap2.stderr.exp2 [new file with mode: 0644]
exp-drd/tests/tc20_verifywrap2.vgtest [new file with mode: 0644]

index b4fca3da4bd8a6432385cd3db5b42342dbde3114..30c801e20549a7ff7fce923edd68c7a79e80ddeb 100644 (file)
@@ -123,8 +123,13 @@ void barrier_cleanup(struct barrier_info* p)
 
   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);
+    BarrierErrInfo bei = { p->a1 };
+    VG_(maybe_record_error)(VG_(get_running_tid)(),
+                            BarrierErr,
+                            VG_(get_IP)(VG_(get_running_tid)()),
+                            "Destruction of barrier that is being waited"
+                            " upon",
+                            &bei);
   }
 
   VG_(OSetGen_ResetIter)(p->oset);
@@ -168,6 +173,14 @@ struct barrier_info* barrier_get(const Addr barrier)
 struct barrier_info*
 barrier_init(const Addr barrier, const SizeT size, const Word count)
 {
+  if (s_trace_barrier)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] barrier_init 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 barrier);
+  }
   tl_assert(barrier_get(barrier) == 0);
   return barrier_get_or_allocate(barrier, size, count);
 }
@@ -175,6 +188,14 @@ barrier_init(const Addr barrier, const SizeT size, const Word count)
 /** Called after pthread_barrier_destroy(). */
 void barrier_destroy(struct barrier_info* const p)
 {
+  if (s_trace_barrier)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] barrier_destroy 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 p->a1);
+  }
   tl_assert(p);
   drd_clientobj_remove(p->a1, ClientBarrier);
 }
@@ -191,9 +212,12 @@ void barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
 
   if (s_trace_barrier)
   {
-    VG_(message)(Vg_DebugMsg,
-                 "[%d] barrier_pre_wait(%p) iteration %d",
-                 tid, barrier, p->pre_iteration);
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] barrier_pre_wait 0x%lx iteration %d",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 barrier,
+                 p->pre_iteration);
   }
 
   q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
@@ -218,14 +242,19 @@ void barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
 void barrier_post_wait(const DrdThreadId tid, const Addr barrier,
                        const Bool waited)
 {
-  struct barrier_info* const p = barrier_get(barrier);
+  struct barrier_info* p;
 
+  p = barrier_get(barrier);
   tl_assert(p);
 
   if (s_trace_barrier)
   {
-    VG_(message)(Vg_DebugMsg, "[%d] barrier_post_wait(%p) iteration %d",
-                 tid, barrier, p->post_iteration);
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] barrier_post_wait 0x%lx iteration %d",
+                 VG_(get_running_tid)(),
+                 tid,
+                 barrier,
+                 p->post_iteration);
   }
 
   if (waited)
@@ -241,23 +270,7 @@ void barrier_post_wait(const DrdThreadId tid, const Addr barrier,
     {
       if (r != q)
       {
-        if (s_trace_barrier)
-        {
-          VG_(message)(Vg_DebugMsg,
-                       "[%d] barrier_post_wait: combining vc of thread %d, "
-                       "iteration %d",
-                       tid, r->tid, p->post_iteration);
-          vc_print(&thread_get_segment(tid)->vc);
-          VG_(printf)(", ");
-          vc_print(&r->vc[p->post_iteration]);
-          VG_(printf)(" -> ");
-        }
         thread_combine_vc2(tid, &r->vc[p->post_iteration]);
-        if (s_trace_barrier)
-        {
-          vc_print(&thread_get_segment(tid)->vc);
-          VG_(printf)("\n");
-        }
       }
     }
 
index 8d4191c69e764d8f020eb1ebc15e86f78dcbd0a8..1de68515809b496594a253279ad78e5872003c99 100644 (file)
@@ -61,10 +61,11 @@ static void drd_pre_cond_wait(const Addr cond, const SizeT cond_size,
 }
 
 static void drd_post_cond_wait(const Addr cond, const Addr mutex,
-                               const SizeT size, const MutexT mutex_type)
+                               const SizeT size, const MutexT mutex_type,
+                               const Bool took_lock)
 {
    cond_post_wait(cond);
-   mutex_post_lock(mutex, size, mutex_type);
+   mutex_post_lock(mutex, size, mutex_type, took_lock);
 }
 
 static void drd_pre_cond_signal(const Addr cond)
@@ -144,7 +145,8 @@ static Bool drd_handle_client_request(ThreadId tid, UWord* arg, UWord* ret)
       break;
 
    case VG_USERREQ__POST_PTHREAD_MUTEX_LOCK:
-      drd_post_mutex_lock(thread_get_running_tid(), arg[1], arg[2], arg[3]);
+      drd_post_mutex_lock(thread_get_running_tid(),
+                          arg[1], arg[2], arg[3], arg[4]);
       break;
 
    case VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK:
@@ -170,7 +172,8 @@ static Bool drd_handle_client_request(ThreadId tid, UWord* arg, UWord* ret)
 
    case VG_USERREQ__POST_PTHREAD_COND_WAIT:
       drd_post_cond_wait(arg[1]/*cond*/, arg[2]/*mutex*/,
-                         arg[3]/*mutex_size*/, arg[4]/*mutex_type*/);
+                         arg[3]/*mutex_size*/, arg[4]/*mutex_type*/,
+                         arg[5]/*took_lock*/);
       break;
 
    case VG_USERREQ__PRE_PTHREAD_COND_SIGNAL:
index a41e8d6399bc860085abe68412ba5c907ba5edb5..68cf741de502e48f525de142a0818114f5ae4466 100644 (file)
@@ -63,7 +63,7 @@ enum {
   /* args: Addr, SizeT, MutexT */
   /* to notify the drd tool of pthread_mutex_lock calls */
   VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
-  /* args: Addr, SizeT, MutexT */
+  /* args: Addr, SizeT, MutexT, Bool */
   /* to notify the drd tool of pthread_mutex_unlock calls */
   VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
   /* args: Addr */
@@ -76,11 +76,11 @@ enum {
   /* args: Addr */
   /* to notify the drd tool of a pthread_cond_destroy call. */
   VG_USERREQ__PRE_PTHREAD_COND_DESTROY,
-  /* args: Addr cond, SizeT cond_size, Addr mutex, SizeT mutex_size, MutexT mt */
+  /* args: Addr cond, SizeT cond_size, Addr mutex, SizeT mutex_size,MutexT mt*/
   VG_USERREQ__PRE_PTHREAD_COND_WAIT,
   /* args: Addr cond, SizeT cond_size, Addr mutex, MutexT mt */
   VG_USERREQ__POST_PTHREAD_COND_WAIT,
-  /* args: Addr cond, Addr mutex, SizeT mutex_size, MutexT mt */
+  /* args: Addr cond, Addr mutex, SizeT mutex_size, MutexT mt, Bool took_lock*/
   VG_USERREQ__PRE_PTHREAD_COND_SIGNAL,
   /* args: Addr cond */
   VG_USERREQ__PRE_PTHREAD_COND_BROADCAST,
index 3de2f3b77a3f0c7ff39854aac5fe3387e4480436..4e2dbd02948ec40dece7607e3df206f6d138ecd0 100644 (file)
@@ -77,10 +77,16 @@ static void cond_cleanup(struct cond_info* p)
   {
     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);
+    tl_assert(q);
+    {
+      CondDestrErrInfo cde = { p->a1, q->a1, q->owner };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              CondDestrErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Destroying condition variable that is being"
+                              " waited upon",
+                              &cde);
+    }
   }
 }
 
@@ -110,8 +116,11 @@ 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_(message)(Vg_UserMsg,
+                 "[%d/%d] cond_init 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 cond);
   }
   tl_assert(cond_get(cond) == 0);
   tl_assert(size > 0);
@@ -123,8 +132,11 @@ void cond_destroy(struct cond_info* const p)
 {
   if (s_trace_cond)
   {
-    VG_(message)(Vg_UserMsg, "Destroying condition variable 0x%lx", p->a1);
-    VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] cond_destroy 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 p->a1);
   }
 
   // TO DO: print a proper error message if waiter_count != 0.
@@ -138,7 +150,18 @@ int cond_pre_wait(const Addr cond, const SizeT cond_size, const Addr mutex)
 {
   struct cond_info* p;
 
+  if (s_trace_cond)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] cond_pre_wait 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 cond);
+  }
+
   p = cond_get_or_allocate(cond, cond_size);
+  tl_assert(p);
+
   if (p->waiter_count == 0)
   {
     p->mutex = mutex;
@@ -158,6 +181,15 @@ int cond_post_wait(const Addr cond)
 {
   struct cond_info* p;
 
+  if (s_trace_cond)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] cond_post_wait 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 cond);
+  }
+
   p = cond_get(cond);
   tl_assert(p);
   tl_assert(p->waiter_count > 0);
@@ -169,12 +201,12 @@ int cond_post_wait(const Addr cond)
   return p->waiter_count;
 }
 
-/** Called before pthread_cond_signal(). */
-void cond_pre_signal(Addr const cond)
+static void cond_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 (cond_p && cond_p->waiter_count > 0)
   {
     if (! mutex_is_locked_by(cond_p->mutex, drd_tid))
@@ -196,10 +228,34 @@ void cond_pre_signal(Addr const cond)
   }
 }
 
+/** Called before pthread_cond_signal(). */
+void cond_pre_signal(Addr const cond)
+{
+  if (s_trace_cond)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] cond_signal 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 cond);
+  }
+
+  cond_signal(cond);
+}
+
 /** Called before pthread_cond_broadcast(). */
 void cond_pre_broadcast(Addr const cond)
 {
-  cond_pre_signal(cond);
+  if (s_trace_cond)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] cond_broadcast 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 cond);
+  }
+
+  cond_signal(cond);
 }
 
 /** Called after pthread_cond_destroy(). */
index 5e63e7c355ec0c22705b450310ff1eef414bd252..60f31d7beb55f3f71a12ec6c20e582fad6ea79b5 100644 (file)
@@ -269,22 +269,50 @@ static void drd_tool_error_pp(Error* const e)
       VG_(pp_ExeContext)(VG_(get_error_where)(e));
       break;
    }
+   case CondErr: {
+      CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "cond 0x%lx: %s",
+                   cdei->cond,
+                   VG_(get_error_string)(e));
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      break;
+   }
    case CondRaceErr: {
       CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e));
       VG_(message)(Vg_UserMsg,
-                   "Race condition: condition variable 0x%lx has been signalled"
-                   " but the associated mutex 0x%lx is not locked by the"
-                   " signalling thread",
+                   "Race condition: condition variable 0x%lx has been"
+                   " signalled but the associated mutex 0x%lx is not locked"
+                   " by the signalling thread",
                    cei->cond, cei->mutex);
       VG_(pp_ExeContext)(VG_(get_error_where)(e));
       break;
    }
-   case CondErr: {
-      CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
+   case CondDestrErr: {
+      CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e));
       VG_(message)(Vg_UserMsg,
-                   "cond 0x%lx: %s",
-                   cdei->cond,
-                   VG_(get_error_string)(e));
+                   "%s: cond 0x%lx, mutex 0x%lx locked by thread %d",
+                   cdi->cond, cdi->mutex, cdi->tid);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      break;
+   }
+   case SemaphoreErr: {
+      SemaphoreErrInfo* sei =(SemaphoreErrInfo*)(VG_(get_error_extra)(e));
+      tl_assert(sei);
+      VG_(message)(Vg_UserMsg,
+                   "%s 0x%lx",
+                   VG_(get_error_string)(e),
+                   sei->semaphore);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      break;
+   }
+   case BarrierErr: {
+      BarrierErrInfo* sei =(BarrierErrInfo*)(VG_(get_error_extra)(e));
+      tl_assert(sei);
+      VG_(message)(Vg_UserMsg,
+                   "%s: barrier 0x%lx",
+                   VG_(get_error_string)(e),
+                   sei->barrier);
       VG_(pp_ExeContext)(VG_(get_error_where)(e));
       break;
    }
@@ -311,10 +339,16 @@ static UInt drd_tool_error_update_extra(Error* e)
       return sizeof(DataRaceErrInfo);
    case MutexErr:
       return sizeof(MutexErrInfo);
-   case CondRaceErr:
-      return sizeof(CondRaceErrInfo);
    case CondErr:
       return sizeof(CondErrInfo);
+   case CondRaceErr:
+      return sizeof(CondRaceErrInfo);
+   case CondDestrErr:
+      return sizeof(CondDestrErrInfo);
+   case SemaphoreErr:
+      return sizeof(SemaphoreErrInfo);
+   case BarrierErr:
+      return sizeof(BarrierErrInfo);
    case GenericErr:
       return sizeof(GenericErrInfo);
    default:
index e9a54c48b3c269bf3d8362fa68960c1961bb10a1..9dfdd61f161c032880c16762855c3dae1cf159fb 100644 (file)
 typedef enum {
    DataRaceErr    = 1,
    MutexErr       = 2,
-   CondRaceErr    = 3,
-   CondErr        = 4,
-   GenericErr     = 5,
+   CondErr        = 3,
+   CondRaceErr    = 4,
+   CondDestrErr   = 5,
+   SemaphoreErr   = 6,
+   BarrierErr     = 7,
+   GenericErr     = 8,
 } DrdErrorKind;
 
 /* The classification of a faulting address. */
@@ -86,14 +89,28 @@ typedef struct {
    DrdThreadId owner;
 } MutexErrInfo;
 
+typedef struct {
+   Addr cond;
+} CondErrInfo;
+
 typedef struct {
    Addr cond;
    Addr mutex;
 } CondRaceErrInfo;
 
 typedef struct {
-   Addr cond;
-} CondErrInfo;
+   Addr        cond;
+   Addr        mutex;
+   DrdThreadId tid;
+} CondDestrErrInfo;
+
+typedef struct {
+   Addr semaphore;
+} SemaphoreErrInfo;
+
+typedef struct {
+   Addr barrier;
+} BarrierErrInfo;
 
 typedef struct {
 } GenericErrInfo;
index 2a569785855fdcb65aebdec53d97add510e63c83..6e14d639234e4e0bd27d991ad0697b36934fc141 100644 (file)
@@ -343,9 +343,9 @@ PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
    write(1, "", 0);
 #endif
    CALL_FN_W_W(ret, fn, mutex);
-   if (ret == 0)
-      VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
-                                mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
+                              mutex, sizeof(*mutex), mutex_type(mutex),
+                              ret == 0, 0);
    return ret;
 }
 
@@ -358,11 +358,9 @@ PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
    CALL_FN_W_W(ret, fn, mutex);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
-                                mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
+                              mutex, sizeof(*mutex), mutex_type(mutex),
+                              ret == 0, 0);
    return ret;
 }
 
@@ -376,11 +374,9 @@ PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
    CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
-                                mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
+                              mutex, sizeof(*mutex), mutex_type(mutex),
+                              ret == 0, 0);
    return ret;
 }
 
@@ -438,10 +434,12 @@ PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
    VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
-                              cond, sizeof(*cond), mutex, mutex_type(mutex), 0);
+                              cond, sizeof(*cond), mutex, mutex_type(mutex),
+                              0);
    CALL_FN_W_WW(ret, fn, cond, mutex);
    VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
-                              cond, mutex, sizeof(*mutex), mutex_type(mutex), 0);
+                              cond, mutex, sizeof(*mutex), mutex_type(mutex),
+                              ret == 0);
    return ret;
 }
 
@@ -456,10 +454,12 @@ PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
    VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
-                              cond, sizeof(*cond), mutex, mutex_type(mutex), 0);
+                              cond, sizeof(*cond), mutex, mutex_type(mutex),
+                              0);
    CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
    VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
-                              cond, mutex, sizeof(*mutex), mutex_type(mutex), 0);
+                              cond, mutex, sizeof(*mutex), mutex_type(mutex),
+                              ret == 0);
    return ret;
 }
 
@@ -531,12 +531,9 @@ PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
    CALL_FN_W_W(ret, fn, spinlock);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
-                                 spinlock, sizeof(*spinlock),
-                                 mutex_type_spinlock, 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
+                              spinlock, sizeof(*spinlock),
+                              mutex_type_spinlock, ret == 0, 0);
    return ret;
 }
 
@@ -549,12 +546,9 @@ PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
    OrigFn fn;
    VALGRIND_GET_ORIG_FN(fn);
    CALL_FN_W_W(ret, fn, spinlock);
-   if (ret == 0)
-   {
-      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
-                                 spinlock, sizeof(*spinlock),
-                                 mutex_type_spinlock, 0, 0);
-   }
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
+                              spinlock, sizeof(*spinlock),
+                              mutex_type_spinlock, ret == 0, 0);
    return ret;
 }
 
index 5b8b43678091e8dbee7cafca3a10e1b4872cf81d..af447f31f06d31cd48d0379569f8d9bb3567d99e 100644 (file)
@@ -428,9 +428,10 @@ void drd_pre_mutex_lock(const DrdThreadId drd_tid,
 void drd_post_mutex_lock(const DrdThreadId drd_tid,
                          const Addr mutex,
                          const SizeT size,
-                         const MutexT mutex_type)
+                         const MutexT mutex_type,
+                         const Bool took_lock)
 {
-   mutex_post_lock(mutex, size, mutex_type);
+   mutex_post_lock(mutex, size, mutex_type, took_lock);
 }
 
 void drd_pre_mutex_unlock(const DrdThreadId drd_tid,
index ac8ddfed3e72301e6f37b26eed8787e63b6d3588..568bf4d3039bdc49b49e935aa0e11f2cb2ffe505 100644 (file)
@@ -78,11 +78,10 @@ static void mutex_cleanup(struct mutex_info* p)
 {
   if (s_trace_mutex)
   {
-    const ThreadId vg_tid = VG_(get_running_tid)();
-    const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
-    VG_(message)(Vg_DebugMsg,
-                 "drd_pre_mutex_destroy tid = %d/%d, %s 0x%lx",
-                 vg_tid, drd_tid,
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] mutex_destroy   %s 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
                  mutex_get_typename(p),
                  p->a1);
   }
@@ -133,6 +132,12 @@ mutex_get_or_allocate(const Addr mutex,
   return p;
 }
 
+struct mutex_info* mutex_get(const Addr mutex)
+{
+  tl_assert(offsetof(DrdClientobj, mutex) == 0);
+  return &drd_clientobj_get(mutex, ClientMutex)->mutex;
+}
+
 struct mutex_info*
 mutex_init(const Addr mutex, const SizeT size, const MutexT mutex_type)
 {
@@ -140,11 +145,10 @@ mutex_init(const Addr mutex, const SizeT size, const MutexT mutex_type)
 
   if (s_trace_mutex)
   {
-    const ThreadId vg_tid = VG_(get_running_tid)();
-    const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
-    VG_(message)(Vg_DebugMsg,
-                 "drd_post_mutex_init  tid = %d/%d, %s 0x%lx",
-                 vg_tid, drd_tid,
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] mutex_init      %s 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
                  mutex_type_name(mutex_type),
                  mutex);
   }
@@ -185,12 +189,6 @@ void mutex_post_destroy(const Addr mutex)
    }
 }
 
-struct mutex_info* mutex_get(const Addr mutex)
-{
-  tl_assert(offsetof(DrdClientobj, mutex) == 0);
-  return &drd_clientobj_get(mutex, ClientMutex)->mutex;
-}
-
 /** Called before pthread_mutex_lock() is invoked. If a data structure for
  *  the client-side object was not yet created, do this now. Also check whether
  *  an attempt is made to lock recursively a synchronization object that must
@@ -227,17 +225,17 @@ void mutex_pre_lock(const Addr mutex, const SizeT size, MutexT mutex_type)
  * Note: this function must be called after pthread_mutex_lock() has been
  * called, or a race condition is triggered !
  */
-int mutex_post_lock(const Addr mutex, const SizeT size, MutexT mutex_type)
+int mutex_post_lock(const Addr mutex, const SizeT size, MutexT mutex_type,
+                    const Bool took_lock)
 {
-  const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(VG_(get_running_tid)());
+  const DrdThreadId drd_tid = thread_get_running_tid();
   struct mutex_info* const p = mutex_get_or_allocate(mutex, size, mutex_type);
 
   if (s_trace_mutex)
   {
-    const ThreadId tid = DrdThreadIdToVgThreadId(drd_tid);
-    VG_(message)(Vg_DebugMsg,
-                 "drd_post_mutex_lock  tid = %d/%d, %s 0x%lx rc %d owner %d",
-                 tid,
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] post_mutex_lock %s 0x%lx rc %d owner %d",
+                 VG_(get_running_tid)(),
                  drd_tid,
                  mutex_get_typename(p),
                  mutex,
@@ -266,10 +264,8 @@ int mutex_post_lock(const Addr mutex, const SizeT size, MutexT mutex_type)
      return 0;
   }
 
-#if 0
-  tl_assert(mutex_type == mutex_type_mutex
-            || mutex_type == mutex_type_spinlock);
-#endif
+  if (! took_lock)
+     return p->recursion_count;
 
   tl_assert(p->mutex_type == mutex_type);
   tl_assert(p->a2 - p->a1 == size);
@@ -281,7 +277,7 @@ int mutex_post_lock(const Addr mutex, const SizeT size, MutexT mutex_type)
   }
   else if (p->owner != drd_tid)
   {
-    VG_(message)(Vg_DebugMsg,
+    VG_(message)(Vg_UserMsg,
                  "The impossible happened: mutex 0x%lx is locked"
                  " simultaneously by two threads (recursion count %d,"
                  " owners %d and %d) !",
@@ -320,9 +316,10 @@ int mutex_unlock(const Addr mutex, const MutexT mutex_type)
 
   if (s_trace_mutex && p != 0)
   {
-    VG_(message)(Vg_DebugMsg,
-                 "drd_pre_mutex_unlock tid = %d/%d, %s 0x%lx rc %d",
-                 vg_tid, drd_tid,
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] mutex_unlock    %s 0x%lx rc %d",
+                 vg_tid,
+                 drd_tid,
                  mutex_get_typename(p),
                  mutex,
                  p->recursion_count,
@@ -364,7 +361,7 @@ int mutex_unlock(const Addr mutex, const MutexT mutex_type)
   tl_assert(p);
   if (p->mutex_type != mutex_type)
   {
-    VG_(message)(Vg_DebugMsg, "??? mutex %p: type changed from %d into %d",
+    VG_(message)(Vg_UserMsg, "??? mutex %p: type changed from %d into %d",
                 p->a1, p->mutex_type, mutex_type);
   }
   tl_assert(p->mutex_type == mutex_type);
index 5c5c7a050773c5e034ca3ff43b600a7eacfddd52..5c12c2b020e144e75b50d61b5f53558de8963423 100644 (file)
@@ -44,8 +44,10 @@ struct mutex_info* mutex_init(const Addr mutex, const SizeT size,
                               const MutexT mutex_type);
 void mutex_post_destroy(const Addr mutex);
 struct mutex_info* mutex_get(const Addr mutex);
-void mutex_pre_lock(const Addr mutex, const SizeT size, const MutexT mutex_type);
-int mutex_post_lock(const Addr mutex, const SizeT size, const MutexT mutex_type);
+void mutex_pre_lock(const Addr mutex, const SizeT size,
+                    const MutexT mutex_type);
+int mutex_post_lock(const Addr mutex, const SizeT size,
+                    const MutexT mutex_type, const Bool took_lock);
 int mutex_unlock(const Addr mutex, const MutexT mutex_type);
 const char* mutex_get_typename(struct mutex_info* const p);
 const char* mutex_type_name(const MutexT mt);
index 51a15ae2142564f58476097c7cb2e182ec875d36..513dcd1b1cb01eb514c23dbacc3b46b00e14ca1b 100644 (file)
@@ -78,8 +78,13 @@ 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);
+    SemaphoreErrInfo sei = { p->a1 };
+    VG_(maybe_record_error)(VG_(get_running_tid)(),
+                            SemaphoreErr,
+                            VG_(get_IP)(VG_(get_running_tid)()),
+                            "Destruction of semaphore that is being waited"
+                            " upon",
+                            &sei);
   }
   vc_cleanup(&p->vc);
 }
@@ -114,6 +119,14 @@ struct semaphore_info* semaphore_init(const Addr semaphore, const SizeT size,
 {
   struct semaphore_info* p;
 
+  if (s_trace_semaphore)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] semaphore_init 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 semaphore);
+  }
   tl_assert(semaphore_get(semaphore) == 0);
   p = semaphore_get_or_allocate(semaphore, size);
   p->value = value;
@@ -123,6 +136,17 @@ struct semaphore_info* semaphore_init(const Addr semaphore, const SizeT size,
 /** Called after sem_destroy(). */
 void semaphore_destroy(struct semaphore_info* const p)
 {
+  tl_assert(p);
+
+  if (s_trace_semaphore)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] semaphore_destroy 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 p->a1);
+  }
+
   drd_clientobj_remove(p->a1, ClientSemaphore);
 }
 
@@ -134,7 +158,11 @@ void semaphore_pre_wait(const Addr semaphore, const SizeT size)
   p = semaphore_get_or_allocate(semaphore, size);
   if (s_trace_semaphore)
   {
-    VG_(message)(Vg_UserMsg, "semaphore_pre_wait(0x%lx, %d)", semaphore, size);
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] semaphore_pre_wait 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 semaphore);
   }
   tl_assert(p);
   tl_assert(p->waiters >= 0);
@@ -154,7 +182,11 @@ void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
   p = semaphore_get(semaphore);
   if (s_trace_semaphore)
   {
-    VG_(message)(Vg_UserMsg, "semaphore_post_wait(0x%lx, %d)", semaphore);
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] semaphore_post_wait 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 semaphore);
   }
   tl_assert(p->waiters > 0);
   p->waiters--;
@@ -162,7 +194,12 @@ void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
   tl_assert(p->value >= 0);
   if (p->value == 0)
   {
-    VG_(message)(Vg_UserMsg, "Invalid semaphore 0x%lx", semaphore);
+    SemaphoreErrInfo sei = { semaphore };
+    VG_(maybe_record_error)(VG_(get_running_tid)(),
+                            SemaphoreErr,
+                            VG_(get_IP)(VG_(get_running_tid)()),
+                            "Invalid semaphore",
+                            &sei);
     return;
   }
   p->value--;
@@ -178,6 +215,14 @@ void semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
 {
   struct semaphore_info* p;
 
+  if (s_trace_semaphore)
+  {
+    VG_(message)(Vg_UserMsg,
+                 "[%d/%d] semaphore_post 0x%lx",
+                 VG_(get_running_tid)(),
+                 thread_get_running_tid(),
+                 semaphore);
+  }
   p = semaphore_get_or_allocate(semaphore, size);
   p->value++;
   if (p->value == 1)
index e5e2368acaf098c4bebedba9e3bd52dde1541505..1c71c8475666a6592ea82b60adf200721138a276 100644 (file)
@@ -30,7 +30,7 @@ void drd_post_mutex_destroy(Addr mutex, const MutexT mutex_type);
 void drd_pre_mutex_lock(DrdThreadId tid, Addr mutex, const SizeT size,
                         const MutexT mutex_type);
 void drd_post_mutex_lock(DrdThreadId tid, Addr mutex, const SizeT size,
-                         const MutexT mutex_type);
+                         const MutexT mutex_type, const Bool took_lock);
 void drd_pre_mutex_unlock(const DrdThreadId tid, const Addr mutex,
                           const MutexT mutex_type);
 
index 6e036bf2c88aea354f68da9ebf3826c4138823b3..30657edd2c15a4a28dc434c4e3d396e279693d26 100644 (file)
@@ -91,8 +91,9 @@ EXTRA_DIST = $(noinst_SCRIPTS)                                  \
        tc19_shadowmem.vgtest                                   \
        tc19_shadowmem.stderr.exp                               \
        tc20_verifywrap.vgtest                                  \
-       tc20_verifywrap.stderr.exp                              \
-       tc20_verifywrap.stderr.exp2                             \
+       tc20_verifywrap.stderr.exp tc20_verifywrap.stderr.exp2  \
+       tc20_verifywrap2.vgtest                                 \
+       tc20_verifywrap2.stderr.exp tc20_verifywrap2.stderr.exp2\
        tc21_pthonce.vgtest                                     \
        tc21_pthonce.stderr.exp tc21_pthonce.stdout.exp         \
        tc22_exit_w_lock.vgtest                                 \
index d18786f80668a209115b4a13cf5e8afa8d9cd471..dd534669dfc288df127a9349fdafe98884bb8b73 100644 (file)
@@ -1,3 +1,6 @@
 
+Invalid semaphore 0x........
+   at 0x........: sem_wait* (drd_intercepts.c:?)
+   by 0x........: main (tc18_semabuse.c:34)
 
-ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
index b5115ca839caf92432185b87ca2003f4ff57f8d7..e4bfdeb071c87da82e5cf4d55bd4e42d6e91ac57 100644 (file)
@@ -20,6 +20,18 @@ Destroying locked mutex: address 0x........, recursion count 1, owner 1.
    at 0x........: pthread_mutex_destroy (drd_intercepts.c:?)
    by 0x........: main (tc20_verifywrap.c:102)
 
+Invalid mutex
+   at 0x........: pthread_mutex_lock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:108)
+
+Invalid mutex
+   at 0x........: pthread_mutex_trylock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:116)
+
+Invalid mutex
+   at 0x........: pthread_mutex_timedlock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:121)
+
 Invalid mutex
    at 0x........: pthread_mutex_unlock (drd_intercepts.c:?)
    by 0x........: main (tc20_verifywrap.c:125)
@@ -41,6 +53,10 @@ FIXME: can't figure out how to verify wrap of pthread_cond_signal
 FIXME: can't figure out how to verify wrap of pthread_broadcast_signal
 
 
+Mutex not locked: address 0x........, recursion count 0, owner 0.
+   at 0x........: pthread_cond_timedwait* (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:165)
+
 ---------------- pthread_rwlock_* ----------------
 
 (1) no error on next line
@@ -58,6 +74,10 @@ FIXME: can't figure out how to verify wrap of pthread_broadcast_signal
 FIXME: can't figure out how to verify wrap of sem_destroy
 
 
+Invalid semaphore 0x........
+   at 0x........: sem_wait* (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:242)
+
 FIXME: can't figure out how to verify wrap of sem_post
 
 
@@ -67,4 +87,4 @@ FIXME: can't figure out how to verify wrap of sem_post
 Destroying locked mutex: address 0x........, recursion count 1, owner 1.
    at 0x........: main (tc20_verifywrap.c:262)
 
-ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
+ERROR SUMMARY: 10 errors from 10 contexts (suppressed: 0 from 0)
diff --git a/exp-drd/tests/tc20_verifywrap2.stderr.exp b/exp-drd/tests/tc20_verifywrap2.stderr.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/exp-drd/tests/tc20_verifywrap2.stderr.exp2 b/exp-drd/tests/tc20_verifywrap2.stderr.exp2
new file mode 100644 (file)
index 0000000..a05efce
--- /dev/null
@@ -0,0 +1,151 @@
+
+
+
+------ This is output for >= glibc 2.4 ------
+
+---------------- pthread_create/join ----------------
+
+[1/1] mutex_init      recursive mutex 0x........
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 0
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+Conflicting store by thread 1 at 0x........ size 2
+   at 0x........: main (tc20_verifywrap.c:78)
+Allocation context: unknown
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+---------------- pthread_mutex_lock et al ----------------
+
+[1/1] mutex_init      invalid mutex 0x........
+[1/1] mutex_init      mutex 0x........
+[1/1] post_mutex_lock mutex 0x........ rc 0 owner 0
+[1/1] mutex_destroy   mutex 0x........
+
+Destroying locked mutex: address 0x........, recursion count 1, owner 1.
+   at 0x........: pthread_mutex_destroy (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:102)
+[1/1] mutex_init      invalid mutex 0x........
+[1/1] post_mutex_lock invalid mutex 0x........ rc 0 owner 0
+
+Invalid mutex
+   at 0x........: pthread_mutex_lock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:108)
+[1/1] post_mutex_lock invalid mutex 0x........ rc 0 owner 0
+
+Invalid mutex
+   at 0x........: pthread_mutex_trylock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:116)
+[1/1] post_mutex_lock invalid mutex 0x........ rc 0 owner 0
+
+Invalid mutex
+   at 0x........: pthread_mutex_timedlock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:121)
+[1/1] mutex_unlock    invalid mutex 0x........ rc 0
+
+Invalid mutex
+   at 0x........: pthread_mutex_unlock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:125)
+
+Mutex not locked: address 0x........, recursion count 0, owner 0.
+   at 0x........: pthread_mutex_unlock (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:125)
+
+---------------- pthread_cond_wait et al ----------------
+
+[1/1] mutex_init      error checking mutex 0x........
+[1/1] cond_init 0x........
+[1/1] mutex_unlock    error checking mutex 0x........ rc 0
+
+Mutex not locked: address 0x........, recursion count 0, owner 0.
+   at 0x........: pthread_cond_wait* (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:147)
+[1/1] cond_pre_wait 0x........
+[1/1] cond_post_wait 0x........
+[1/1] post_mutex_lock error checking mutex 0x........ rc 0 owner 0
+[1/1] cond_signal 0x........
+
+FIXME: can't figure out how to verify wrap of pthread_cond_signal
+
+[1/1] cond_broadcast 0x........
+
+FIXME: can't figure out how to verify wrap of pthread_broadcast_signal
+
+[1/1] mutex_unlock    error checking mutex 0x........ rc 0
+
+Mutex not locked: address 0x........, recursion count 0, owner 0.
+   at 0x........: pthread_cond_timedwait* (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:165)
+[1/1] cond_pre_wait 0x........
+[1/1] cond_post_wait 0x........
+[1/1] post_mutex_lock error checking mutex 0x........ rc 0 owner 0
+
+---------------- pthread_rwlock_* ----------------
+
+(1) no error on next line
+(2) no error on next line
+(3)    ERROR on next line
+(4) no error on next line
+(5) no error on next line
+(6) no error on next line
+(7) no error on next line
+(8)    ERROR on next line
+
+---------------- sem_* ----------------
+
+[1/1] semaphore_init 0x........
+
+FIXME: can't figure out how to verify wrap of sem_destroy
+
+[1/1] semaphore_pre_wait 0x........
+[1/1] semaphore_post_wait 0x........
+
+Invalid semaphore 0x........
+   at 0x........: sem_wait* (drd_intercepts.c:?)
+   by 0x........: main (tc20_verifywrap.c:242)
+[1/1] semaphore_post 0x........
+
+FIXME: can't figure out how to verify wrap of sem_post
+
+[1/1] semaphore_destroy 0x........
+
+------------ dealloc of mem holding locks ------------
+
+[1/1] mutex_destroy   error checking mutex 0x........
+[1/1] mutex_destroy   invalid mutex 0x........
+[1/1] mutex_destroy   invalid mutex 0x........
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 1
+[1/1] mutex_unlock    recursive mutex 0x........ rc 1
+
+ERROR SUMMARY: 10 errors from 10 contexts (suppressed: 0 from 0)
diff --git a/exp-drd/tests/tc20_verifywrap2.vgtest b/exp-drd/tests/tc20_verifywrap2.vgtest
new file mode 100644 (file)
index 0000000..d7223f2
--- /dev/null
@@ -0,0 +1,2 @@
+prog: tc20_verifywrap
+vgopts: --trace-mutex=yes --trace-cond=yes --trace-semaphore=yes