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;
}