diff options
Diffstat (limited to 'drd/drd_thread.c')
-rw-r--r-- | drd/drd_thread.c | 114 |
1 files changed, 91 insertions, 23 deletions
diff --git a/drd/drd_thread.c b/drd/drd_thread.c index 247dd91eb..9bb320091 100644 --- a/drd/drd_thread.c +++ b/drd/drd_thread.c @@ -1,7 +1,7 @@ /* This file is part of drd, a thread error detector. - Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>. + Copyright (C) 2006-2015 Bart Van Assche <bvanassche@acm.org>. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -78,6 +78,11 @@ static int s_segment_merge_interval = 10; static unsigned s_join_list_vol = 10; static unsigned s_deletion_head; static unsigned s_deletion_tail; +#if defined(VGO_solaris) +Bool DRD_(ignore_thread_creation) = True; +#else +Bool DRD_(ignore_thread_creation) = False; +#endif /* VGO_solaris */ /* Function definitions. */ @@ -203,6 +208,11 @@ static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid) DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0; DRD_(g_threadinfo)[i].synchr_nesting = 0; DRD_(g_threadinfo)[i].deletion_seq = s_deletion_tail - 1; + DRD_(g_threadinfo)[i].creator_thread = DRD_INVALID_THREADID; +#if defined (VGO_solaris) + DRD_(g_threadinfo)[i].bind_guard_flag = 0; +#endif /* VGO_solaris */ + tl_assert(DRD_(g_threadinfo)[i].sg_first == NULL); tl_assert(DRD_(g_threadinfo)[i].sg_last == NULL); @@ -302,6 +312,16 @@ DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator, tl_assert(DRD_(g_threadinfo)[created].sg_first == NULL); tl_assert(DRD_(g_threadinfo)[created].sg_last == NULL); + + if (creator != DRD_INVALID_THREADID) { + if (DRD_(ignore_thread_creation)) { + tl_assert(DRD_(thread_get_synchr_nesting_count)(created) == 0); + DRD_(thread_enter_synchr)(created); + /* Counterpart in DRD_(thread_set_pthreadid)(). */ + } + } + DRD_(g_threadinfo)[created].creator_thread = creator; + /* Create an initial segment for the newly created thread. */ thread_append_segment(created, DRD_(sg_new)(creator, created)); @@ -388,7 +408,7 @@ void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee) msg = VG_(malloc)("drd.main.dptj.1", msg_size); VG_(snprintf)(msg, msg_size, - "drd_post_thread_join joiner = %d, joinee = %d", + "drd_post_thread_join joiner = %u, joinee = %u", drd_joiner, drd_joinee); if (joiner) { @@ -575,7 +595,7 @@ void DRD_(thread_pre_cancel)(const DrdThreadId tid) tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID); if (DRD_(thread_get_trace_fork_join)()) - DRD_(trace_msg)("[%d] drd_thread_pre_cancel %d", + DRD_(trace_msg)("[%u] drd_thread_pre_cancel %u", DRD_(g_drd_running_tid), tid); } @@ -595,6 +615,13 @@ void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid) tl_assert(ptid != INVALID_POSIX_THREADID); DRD_(g_threadinfo)[tid].posix_thread_exists = True; DRD_(g_threadinfo)[tid].pt_threadid = ptid; + + if (DRD_(g_threadinfo)[tid].creator_thread != DRD_INVALID_THREADID) { + if (DRD_(ignore_thread_creation)) { + DRD_(thread_leave_synchr)(tid); + tl_assert(DRD_(thread_get_synchr_nesting_count)(tid) == 0); + } + } } /** Returns true for joinable threads and false for detached threads. */ @@ -631,6 +658,11 @@ void DRD_(thread_entering_pthread_create)(const DrdThreadId tid) tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0); DRD_(g_threadinfo)[tid].pthread_create_nesting_level++; + + if (DRD_(ignore_thread_creation)) { + tl_assert(DRD_(thread_get_synchr_nesting_count)(tid) == 0); + DRD_(thread_enter_synchr)(tid); + } } /** Tells DRD that the calling thread has left pthread_create(). */ @@ -642,8 +674,44 @@ void DRD_(thread_left_pthread_create)(const DrdThreadId tid) tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0); DRD_(g_threadinfo)[tid].pthread_create_nesting_level--; + + if (DRD_(ignore_thread_creation)) { + DRD_(thread_leave_synchr)(tid); + tl_assert(DRD_(thread_get_synchr_nesting_count)(tid) == 0); + } +} + +#if defined(VGO_solaris) +/** Handles the bind_guard() intercept. */ +void DRD_(thread_entering_rtld_bind_guard)(const DrdThreadId tid, int flags) +{ + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + + Int bindflag = (flags & VKI_THR_FLG_RTLD); + if ((bindflag & DRD_(g_threadinfo)[tid].bind_guard_flag) == 0) { + DRD_(g_threadinfo)[tid].bind_guard_flag |= bindflag; + DRD_(thread_enter_synchr)(tid); + } } +/** + * Handles the bind_clear() intercept. + * Call to bind_clear(0) is typically used to determine value of bind_flags. + */ +void DRD_(thread_leaving_rtld_bind_clear)(const DrdThreadId tid, int flags) +{ + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + + Int bindflag = (flags & VKI_THR_FLG_RTLD); + if ((DRD_(g_threadinfo)[tid].bind_guard_flag & bindflag) != 0) { + DRD_(g_threadinfo)[tid].bind_guard_flag &= ~bindflag; + DRD_(thread_leave_synchr)(tid); + } +} +#endif /* VGO_solaris */ + /** Obtain the thread number and the user-assigned thread name. */ const HChar* DRD_(thread_get_name)(const DrdThreadId tid) { @@ -662,12 +730,12 @@ void DRD_(thread_set_name)(const DrdThreadId tid, const HChar* const name) if (name == NULL || name[0] == 0) VG_(snprintf)(DRD_(g_threadinfo)[tid].name, sizeof(DRD_(g_threadinfo)[tid].name), - "Thread %d", + "Thread %u", tid); else VG_(snprintf)(DRD_(g_threadinfo)[tid].name, sizeof(DRD_(g_threadinfo)[tid].name), - "Thread %d (%s)", + "Thread %u (%s)", tid, name); DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0; } @@ -706,7 +774,7 @@ void DRD_(thread_set_running_tid)(const ThreadId vg_tid, && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID) { VG_(message)(Vg_DebugMsg, - "Context switch from thread %d to thread %d;" + "Context switch from thread %u to thread %u;" " segments: %llu\n", DRD_(g_drd_running_tid), drd_tid, DRD_(sg_get_segments_alive_count)()); @@ -1153,7 +1221,7 @@ static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg) HChar *str1, *str2; str1 = DRD_(vc_aprint)(&old_vc); str2 = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid)); - VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2); + VG_(message)(Vg_DebugMsg, "thread %u: vc %s -> %s\n", tid, str1, str2); VG_(free)(str1); VG_(free)(str2); } @@ -1171,7 +1239,7 @@ static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg) /** * Create a new segment for thread tid and update the vector clock of the last - * segment of this thread with the the vector clock of segment sg. Call this + * segment of this thread with the vector clock of segment sg. Call this * function after thread tid had to wait because of thread synchronization * until the memory accesses in the segment sg finished. */ @@ -1236,7 +1304,7 @@ void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled) */ void DRD_(thread_print_all)(void) { - unsigned i; + UInt i; Segment* p; for (i = 0; i < DRD_N_THREADS; i++) @@ -1244,7 +1312,7 @@ void DRD_(thread_print_all)(void) p = DRD_(g_threadinfo)[i].sg_first; if (p) { VG_(printf)("**************\n" - "* thread %3d (%d/%d/%d/%d/0x%lx/%d) *\n" + "* thread %3u (%d/%u/%u/%u/0x%lx/%d) *\n" "**************\n", i, DRD_(g_threadinfo)[i].valid, @@ -1313,14 +1381,14 @@ thread_report_conflicting_segments_segment(const DrdThreadId tid, VG_(printf_xml)(" <other_segment_start>\n"); else VG_(message)(Vg_UserMsg, - "Other segment start (thread %d)\n", i); + "Other segment start (thread %u)\n", i); show_call_stack(i, q->stacktrace); if (VG_(clo_xml)) VG_(printf_xml)(" </other_segment_start>\n" " <other_segment_end>\n"); else VG_(message)(Vg_UserMsg, - "Other segment end (thread %d)\n", i); + "Other segment end (thread %u)\n", i); q_next = q->thr_next; show_call_stack(i, q_next ? q_next->stacktrace : 0); if (VG_(clo_xml)) @@ -1409,7 +1477,7 @@ static void thread_compute_conflict_set(struct bitmap** conflict_set, str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid)); VG_(message)(Vg_DebugMsg, - "computing conflict set for thread %d with vc %s\n", + "computing conflict set for thread %u with vc %s\n", tid, str); VG_(free)(str); } @@ -1422,7 +1490,7 @@ static void thread_compute_conflict_set(struct bitmap** conflict_set, HChar* vc; vc = DRD_(vc_aprint)(&p->vc); - VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n", + VG_(message)(Vg_DebugMsg, "conflict set: thread [%u] at vc %s\n", tid, vc); VG_(free)(vc); } @@ -1439,7 +1507,7 @@ static void thread_compute_conflict_set(struct bitmap** conflict_set, str = DRD_(vc_aprint)(&q->vc); VG_(message)(Vg_DebugMsg, - "conflict set: [%d] merging segment %s\n", + "conflict set: [%u] merging segment %s\n", j, str); VG_(free)(str); } @@ -1450,7 +1518,7 @@ static void thread_compute_conflict_set(struct bitmap** conflict_set, str = DRD_(vc_aprint)(&q->vc); VG_(message)(Vg_DebugMsg, - "conflict set: [%d] ignoring segment %s\n", + "conflict set: [%u] ignoring segment %s\n", j, str); VG_(free)(str); } @@ -1466,9 +1534,9 @@ static void thread_compute_conflict_set(struct bitmap** conflict_set, += DRD_(bm_get_bitmap2_creation_count)(); if (s_trace_conflict_set_bm) { - VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid); + VG_(message)(Vg_DebugMsg, "[%u] new conflict set:\n", tid); DRD_(bm_print)(*conflict_set); - VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid); + VG_(message)(Vg_DebugMsg, "[%u] end of new conflict set.\n", tid); } } @@ -1495,7 +1563,7 @@ void DRD_(thread_update_conflict_set)(const DrdThreadId tid, str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid)); VG_(message)(Vg_DebugMsg, - "updating conflict set for thread %d with vc %s\n", + "updating conflict set for thread %u with vc %s\n", tid, str); VG_(free)(str); } @@ -1525,7 +1593,7 @@ void DRD_(thread_update_conflict_set)(const DrdThreadId tid, str = DRD_(vc_aprint)(&q->vc); VG_(message)(Vg_DebugMsg, - "conflict set: [%d] %s segment %s\n", j, + "conflict set: [%u] %s segment %s\n", j, included_in_old_conflict_set != included_in_new_conflict_set ? "merging" : "ignoring", str); @@ -1547,7 +1615,7 @@ void DRD_(thread_update_conflict_set)(const DrdThreadId tid, str = DRD_(vc_aprint)(&q->vc); VG_(message)(Vg_DebugMsg, - "conflict set: [%d] %s segment %s\n", j, + "conflict set: [%u] %s segment %s\n", j, included_in_old_conflict_set != included_in_new_conflict_set ? "merging" : "ignoring", str); @@ -1579,9 +1647,9 @@ void DRD_(thread_update_conflict_set)(const DrdThreadId tid, if (s_trace_conflict_set_bm) { - VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid); + VG_(message)(Vg_DebugMsg, "[%u] updated conflict set:\n", tid); DRD_(bm_print)(DRD_(g_conflict_set)); - VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid); + VG_(message)(Vg_DebugMsg, "[%u] end of updated conflict set.\n", tid); } tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid))); |