/* 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. */
case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK:
{
+#if 0
const Addr topmost_sp = highest_used_stack_address(vg_tid);
#if 0
UInt nframes;
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;
}
(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]));
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
return husa;
}
+#endif
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,
{
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,
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)
{
/*
- * 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
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)
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);
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)
{
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;
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);
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);
}
}
/**
- * 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)
&& 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)
{