From 6529f121891bf39238523ab94888a56ca3d0706d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 24 Jul 2009 08:20:10 +0000 Subject: [PATCH] Replaced code for suppressing the stack memory in use at the time a thread is being created by code for suppressing the memory allocated from inside the pthread_create() call. The new implementation should be a more portable solution for suppressing data races triggered by the thread-local-storage implementation of a Pthreads library. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10584 --- drd/drd_clientreq.c | 14 ++++++++++++++ drd/drd_clientreq.h | 7 +++++++ drd/drd_main.c | 5 +++++ drd/drd_pthread_intercepts.c | 25 +++++++++++++++++++++++-- drd/drd_thread.c | 23 +++++++++++++++++++++++ drd/drd_thread.h | 25 +++++++++++++++++++++++-- 6 files changed, 95 insertions(+), 4 deletions(-) diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c index 3aca2d734d..82820a1a18 100644 --- a/drd/drd_clientreq.c +++ b/drd/drd_clientreq.c @@ -47,7 +47,9 @@ /* Local function declarations. */ static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret); +#if 0 static Addr highest_used_stack_address(const ThreadId vg_tid); +#endif /* Function definitions. */ @@ -175,6 +177,7 @@ static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret) case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK: { +#if 0 const Addr topmost_sp = highest_used_stack_address(vg_tid); #if 0 UInt nframes; @@ -201,6 +204,7 @@ static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret) DRD_(thread_set_stack_startup)(drd_tid, VG_(get_SP)(vg_tid)); DRD_(start_suppression)(topmost_sp, VG_(thread_get_stack_max)(vg_tid), "stack top"); +#endif break; } @@ -235,6 +239,14 @@ static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret) (Bool)arg[2]); break; + case VG_USERREQ__ENTERING_PTHREAD_CREATE: + DRD_(thread_entering_pthread_create)(drd_tid); + break; + + case VG_USERREQ__LEFT_PTHREAD_CREATE: + DRD_(thread_left_pthread_create)(drd_tid); + break; + case VG_USERREQ__POST_THREAD_JOIN: tl_assert(arg[1]); DRD_(thread_post_join)(drd_tid, DRD_(PtThreadIdToDrdThreadId)(arg[1])); @@ -492,6 +504,7 @@ static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret) return True; } +#if 0 /** * Walk the stack up to the highest stack frame, and return the stack pointer * of the highest stack frame. It is assumed that there are no more than @@ -535,3 +548,4 @@ static Addr highest_used_stack_address(const ThreadId vg_tid) return husa; } +#endif diff --git a/drd/drd_clientreq.h b/drd/drd_clientreq.h index 190ead5c49..c282a736c4 100644 --- a/drd/drd_clientreq.h +++ b/drd/drd_clientreq.h @@ -62,6 +62,13 @@ enum { VG_USERREQ__SET_JOINABLE, /* args: pthread_t, Bool */ + /* Tell DRD that the calling thread is about to enter pthread_create(). */ + VG_USERREQ__ENTERING_PTHREAD_CREATE, + /* args: (none) */ + /* Tell DRD that the calling thread has left pthread_create(). */ + VG_USERREQ__LEFT_PTHREAD_CREATE, + /* args: (none) */ + /* To notify drd that a thread finished because */ /* pthread_thread_join() was called on it. */ VG_USERREQ__POST_THREAD_JOIN, diff --git a/drd/drd_main.c b/drd/drd_main.c index b3b3708306..ed6f269280 100644 --- a/drd/drd_main.c +++ b/drd/drd_main.c @@ -291,6 +291,11 @@ void drd_start_using_mem(const Addr a1, const SizeT len) { DRD_(trace_mem_access)(a1, len, eStart); } + + if (UNLIKELY(DRD_(running_thread_inside_pthread_create)())) + { + DRD_(start_suppression)(a1, a1 + len, "pthread_create()"); + } } static void drd_start_using_mem_w_ecu(const Addr a1, diff --git a/drd/drd_pthread_intercepts.c b/drd/drd_pthread_intercepts.c index b2ef0184af..b9ef24f9b1 100644 --- a/drd/drd_pthread_intercepts.c +++ b/drd/drd_pthread_intercepts.c @@ -191,8 +191,25 @@ static void DRD_(set_joinable)(const pthread_t tid, const int joinable) tid, joinable, 0, 0, 0); } +/** Tell DRD that the calling thread is about to enter pthread_create(). */ +static __inline__ void DRD_(entering_pthread_create)(void) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__ENTERING_PTHREAD_CREATE, + 0, 0, 0, 0, 0); +} + +/** Tell DRD that the calling thread has left pthread_create(). */ +static __inline__ void DRD_(left_pthread_create)(void) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__LEFT_PTHREAD_CREATE, + 0, 0, 0, 0, 0); +} + /** - * The function called from the thread created by pthread_create(). + * Entry point for newly created threads. This function is called from the + * thread created by pthread_create(). */ static void* DRD_(thread_wrapper)(void* arg) { @@ -300,7 +317,8 @@ static void DRD_(set_main_thread_state)(void) /* - * Note: as of today there exist three different versions of pthread_create: + * Note: as of today there exist three different versions of pthread_create + * in Linux: * - pthread_create@GLIBC_2.0 * - pthread_create@@GLIBC_2.1 * - pthread_create@@GLIBC_2.2.5 @@ -360,7 +378,10 @@ PTH_FUNC(int, pthreadZucreateZa, // pthread_create* assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED); + + DRD_(entering_pthread_create)(); CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p); + DRD_(left_pthread_create)(); #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) if (ret == 0) diff --git a/drd/drd_thread.c b/drd/drd_thread.c index 04ec9125af..528b7b37eb 100644 --- a/drd/drd_thread.c +++ b/drd/drd_thread.c @@ -184,6 +184,7 @@ static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid) DRD_(thread_set_name)(i, ""); DRD_(g_threadinfo)[i].is_recording_loads = True; DRD_(g_threadinfo)[i].is_recording_stores = True; + DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0; DRD_(g_threadinfo)[i].synchr_nesting = 0; tl_assert(DRD_(g_threadinfo)[i].first == 0); tl_assert(DRD_(g_threadinfo)[i].last == 0); @@ -520,6 +521,28 @@ void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable) DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable; } +/** Tells DRD that the calling thread is about to enter pthread_create(). */ +void DRD_(thread_entering_pthread_create)(const DrdThreadId tid) +{ + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0); + + DRD_(g_threadinfo)[tid].pthread_create_nesting_level++; +} + +/** Tells DRD that the calling thread has left pthread_create(). */ +void DRD_(thread_left_pthread_create)(const DrdThreadId tid) +{ + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0); + + DRD_(g_threadinfo)[tid].pthread_create_nesting_level--; +} + /** Obtain the thread number and the user-assigned thread name. */ const char* DRD_(thread_get_name)(const DrdThreadId tid) { diff --git a/drd/drd_thread.h b/drd/drd_thread.h index 710f905c30..ea352b9df8 100644 --- a/drd/drd_thread.h +++ b/drd/drd_thread.h @@ -90,6 +90,8 @@ typedef struct Bool is_recording_loads; /** Wether recording of memory load accesses is currently enabled. */ Bool is_recording_stores; + /** pthread_create() nesting level. */ + Int pthread_create_nesting_level; /** Nesting level of synchronization functions called by the client. */ Int synchr_nesting; } ThreadInfo; @@ -143,6 +145,8 @@ SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid); void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid); Bool DRD_(thread_get_joinable)(const DrdThreadId tid); void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable); +void DRD_(thread_entering_pthread_create)(const DrdThreadId tid); +void DRD_(thread_left_pthread_create)(const DrdThreadId tid); const char* DRD_(thread_get_name)(const DrdThreadId tid); void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name); void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid); @@ -209,7 +213,9 @@ Bool DRD_(IsValidDrdThreadId)(const DrdThreadId tid) static __inline__ DrdThreadId DRD_(thread_get_running_tid)(void) { +#ifdef ENABLE_DRD_CONSISTENCY_CHECKS tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); +#endif return DRD_(g_drd_running_tid); } @@ -221,8 +227,19 @@ struct bitmap* DRD_(thread_get_conflict_set)(void) } /** - * Reports whether or not memory access recording is enabled for the - * currently running thread. + * Reports whether or not the currently running client thread is executing code + * inside the pthread_create() function. + */ +static __inline__ +Bool DRD_(running_thread_inside_pthread_create)(void) +{ + return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)] + .pthread_create_nesting_level > 0); +} + +/** + * Reports whether or not recording of memory loads is enabled for the + * currently running client thread. */ static __inline__ Bool DRD_(running_thread_is_recording_loads)(void) @@ -236,6 +253,10 @@ Bool DRD_(running_thread_is_recording_loads)(void) && DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].is_recording_loads); } +/** + * Reports whether or not recording memory stores is enabled for the + * currently running client thread. + */ static __inline__ Bool DRD_(running_thread_is_recording_stores)(void) { -- 2.47.3