From 10c73ac342ba8ed28f059800ae1ce98e895763cd Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 7 Jul 2008 16:53:07 +0000 Subject: [PATCH] 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 --- drd/drd_clientreq.c | 32 ++++++++++++++++++++++++-------- drd/drd_clientreq.h | 23 +++++++++++++++++------ drd/drd_mutex.c | 31 +++++++++++++++++++++++-------- drd/drd_pthread_intercepts.c | 10 +++++++++- 4 files changed, 73 insertions(+), 23 deletions(-) diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c index 9a267e541d..6078deaa85 100644 --- a/drd/drd_clientreq.c +++ b/drd/drd_clientreq.c @@ -257,13 +257,21 @@ static Bool drd_handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret) 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 @@ static Bool drd_handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret) 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 24033827ad..b80b8a89ad 100644 --- a/drd/drd_clientreq.h +++ b/drd/drd_clientreq.h @@ -94,17 +94,27 @@ enum { /* 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 @@ enum { 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 db1ef84634..fe0888ca06 100644 --- a/drd/drd_mutex.c +++ b/drd/drd_mutex.c @@ -67,9 +67,10 @@ static 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 @@ static void mutex_cleanup(struct mutex_info* p) 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 @@ mutex_get_or_allocate(const Addr mutex, const MutexT mutex_type) 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 @@ mutex_init(const Addr mutex, const MutexT mutex_type) { struct mutex_info* p; + tl_assert(mutex_type != mutex_type_unknown); + if (s_trace_mutex) { VG_(message)(Vg_UserMsg, @@ -209,18 +216,22 @@ void mutex_post_destroy(const Addr mutex) * 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 @@ void mutex_post_lock(const Addr mutex, const Bool took_lock, * @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 62dd1d9d56..064804e13e 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 @@ PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init* 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 @@ PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy* 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 @@ PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal* 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 @@ PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast* 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; } -- 2.47.2