From 06666933d9717e76a62bb2f41ea8cb665eb063eb Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Fri, 9 Nov 2007 23:21:44 +0000 Subject: [PATCH] Merge (from branches/THRCHECK) the following two changes to the core-tool interface: r6805: Modify two thread-notification events in the core-tool interface. This removes track_post_thread_create and track_post_thread_join. The core can only see low level thread creation and exiting, and has no idea about pthread-level concepts like "pthread_create" and "pthread_join", so these are a bit ambiguous. Replace them with track_pre_thread_ll_create, which is notified before a new thread makes any memory references, and track_pre_thread_ll_exit, which is notified just before the new thread exits, that is, after it has made its last memory reference. r6823: Core-tool interface: give 'needs_tool_errors' an extra Boolean indicating whether or not the core should print thread id's on error messages. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7123 --- coregrind/m_errormgr.c | 5 ++-- coregrind/m_syswrap/syswrap-amd64-linux.c | 8 ++++++ coregrind/m_syswrap/syswrap-linux.c | 5 ++-- coregrind/m_syswrap/syswrap-ppc32-linux.c | 8 ++++++ coregrind/m_syswrap/syswrap-ppc64-linux.c | 8 ++++++ coregrind/m_syswrap/syswrap-x86-linux.c | 11 ++++++++ coregrind/m_tooliface.c | 6 +++-- coregrind/pub_core_tooliface.h | 5 ++-- include/pub_tool_tooliface.h | 33 ++++++++++++++--------- 9 files changed, 69 insertions(+), 20 deletions(-) diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c index 40e91fc460..b719dcba91 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -293,7 +293,8 @@ static void pp_Error ( Error* err ) } if (!VG_(clo_xml)) { - if (err->tid > 0 && err->tid != last_tid_printed) { + if (VG_(tdict).tool_show_ThreadIDs_for_errors + && err->tid > 0 && err->tid != last_tid_printed) { VG_(message)(Vg_UserMsg, "Thread %d:", err->tid ); last_tid_printed = err->tid; } @@ -380,7 +381,7 @@ void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a, err->count = 1; err->tid = tid; if (NULL == where) - err->where = VG_(record_ExeContext)( tid ); + err->where = VG_(record_ExeContext)( tid, 0 ); else err->where = where; diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c index 335a112675..1c1d24bddb 100644 --- a/coregrind/m_syswrap/syswrap-amd64-linux.c +++ b/coregrind/m_syswrap/syswrap-amd64-linux.c @@ -267,6 +267,12 @@ static SysRes do_clone ( ThreadId ptid, ctst->client_stack_szB = 0; } + /* Assume the clone will succeed, and tell any tool that wants to + know that this thread has come into existence. If the clone + fails, we'll send out a ll_exit notification for it at the out: + label below, to clean up. */ + VG_TRACK ( pre_thread_ll_create, ptid, ctid ); + if (flags & VKI_CLONE_SETTLS) { if (debug) VG_(printf)("clone child has SETTLS: tls at %p\n", tlsaddr); @@ -292,6 +298,8 @@ static SysRes do_clone ( ThreadId ptid, /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); } return res; diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 71cc34c978..88b160cdd8 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -78,8 +78,6 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) VG_(printf)("thread tid %d started: stack = %p\n", tid, &tid); - VG_TRACK ( post_thread_create, tst->os_state.parent, tid ); - tst->os_state.lwpid = VG_(gettid)(); tst->os_state.threadgroup = VG_(getpid)(); @@ -128,6 +126,9 @@ static void run_a_thread_NORETURN ( Word tidW ) c = VG_(count_living_threads)(); vg_assert(c >= 1); /* stay sane */ + // Tell the tool this thread is exiting + VG_TRACK( pre_thread_ll_exit, tid ); + if (c == 1) { VG_(debugLog)(1, "syswrap-linux", diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c index faec292e45..9426d0b97a 100644 --- a/coregrind/m_syswrap/syswrap-ppc32-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c @@ -313,6 +313,12 @@ static SysRes do_clone ( ThreadId ptid, ctst->client_stack_szB = 0; } + /* Assume the clone will succeed, and tell any tool that wants to + know that this thread has come into existence. If the clone + fails, we'll send out a ll_exit notification for it at the out: + label below, to clean up. */ + VG_TRACK ( pre_thread_ll_create, ptid, ctid ); + if (flags & VKI_CLONE_SETTLS) { if (debug) VG_(printf)("clone child has SETTLS: tls at %p\n", child_tls); @@ -344,6 +350,8 @@ static SysRes do_clone ( ThreadId ptid, /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); } return res; diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c index 6907401d1c..9ebe705267 100644 --- a/coregrind/m_syswrap/syswrap-ppc64-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c @@ -341,6 +341,12 @@ static SysRes do_clone ( ThreadId ptid, ctst->client_stack_szB = 0; } + /* Assume the clone will succeed, and tell any tool that wants to + know that this thread has come into existence. If the clone + fails, we'll send out a ll_exit notification for it at the out: + label below, to clean up. */ + VG_TRACK ( pre_thread_ll_create, ptid, ctid ); + if (flags & VKI_CLONE_SETTLS) { if (debug) VG_(printf)("clone child has SETTLS: tls at %p\n", child_tls); @@ -374,6 +380,8 @@ static SysRes do_clone ( ThreadId ptid, /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); } return res; diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 6a9486548d..001d2a81bc 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -279,6 +279,15 @@ static SysRes do_clone ( ThreadId ptid, ctst->client_stack_szB = 0; } + /* Assume the clone will succeed, and tell any tool that wants to + know that this thread has come into existence. We cannot defer + it beyond this point because sys_set_thread_area, just below, + causes tCheck to assert by making references to the new ThreadId + if we don't state the new thread exists prior to that point. + If the clone fails, we'll send out a ll_exit notification for it + at the out: label below, to clean up. */ + VG_TRACK ( pre_thread_ll_create, ptid, ctid ); + if (flags & VKI_CLONE_SETTLS) { if (debug) VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d " @@ -311,6 +320,8 @@ static SysRes do_clone ( ThreadId ptid, /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); } return res; diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c index a5b8fbbc6d..b7440caa91 100644 --- a/coregrind/m_tooliface.c +++ b/coregrind/m_tooliface.c @@ -176,6 +176,7 @@ void VG_(needs_superblock_discards)( void VG_(needs_tool_errors)( Bool (*eq) (VgRes, Error*, Error*), void (*pp) (Error*), + Bool show_TIDs, UInt (*update) (Error*), Bool (*recog) (Char*, Supp*), Bool (*read_extra) (Int, Char*, Int, Supp*), @@ -187,6 +188,7 @@ void VG_(needs_tool_errors)( VG_(needs).tool_errors = True; VG_(tdict).tool_eq_Error = eq; VG_(tdict).tool_pp_Error = pp; + VG_(tdict).tool_show_ThreadIDs_for_errors = show_TIDs; VG_(tdict).tool_update_extra = update; VG_(tdict).tool_recognised_suppression = recog; VG_(tdict).tool_read_extra_suppression_info = read_extra; @@ -332,8 +334,8 @@ DEF(track_post_reg_write_clientcall_return, ThreadId, OffT, SizeT, Addr) DEF(track_start_client_code, ThreadId, ULong) DEF(track_stop_client_code, ThreadId, ULong) -DEF(track_post_thread_create, ThreadId, ThreadId) -DEF(track_post_thread_join, ThreadId, ThreadId) +DEF(track_pre_thread_ll_create, ThreadId, ThreadId) +DEF(track_pre_thread_ll_exit, ThreadId) DEF(track_pre_deliver_signal, ThreadId, Int sigNo, Bool) DEF(track_post_deliver_signal, ThreadId, Int sigNo) diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h index 3fa45c4196..f6690fe4d2 100644 --- a/coregrind/pub_core_tooliface.h +++ b/coregrind/pub_core_tooliface.h @@ -118,6 +118,7 @@ typedef struct { // VG_(needs).tool_errors Bool (*tool_eq_Error) (VgRes, Error*, Error*); void (*tool_pp_Error) (Error*); + Bool tool_show_ThreadIDs_for_errors; UInt (*tool_update_extra) (Error*); Bool (*tool_recognised_suppression) (Char*, Supp*); Bool (*tool_read_extra_suppression_info) (Int, Char*, Int, Supp*); @@ -207,8 +208,8 @@ typedef struct { void (*track_start_client_code)(ThreadId, ULong); void (*track_stop_client_code) (ThreadId, ULong); - void (*track_post_thread_create)(ThreadId, ThreadId); - void (*track_post_thread_join) (ThreadId, ThreadId); + void (*track_pre_thread_ll_create)(ThreadId, ThreadId); + void (*track_pre_thread_ll_exit) (ThreadId); void (*track_pre_deliver_signal) (ThreadId, Int sigNo, Bool); void (*track_post_deliver_signal)(ThreadId, Int sigNo); diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h index f2012dcbfb..b836833b62 100644 --- a/include/pub_tool_tooliface.h +++ b/include/pub_tool_tooliface.h @@ -303,6 +303,9 @@ extern void VG_(needs_tool_errors) ( // Print error context. void (*pp_Error)(Error* err), + // Should the core indicate which ThreadId each error comes from? + Bool show_ThreadIDs_for_errors, + // Should fill in any details that could be postponed until after the // decision whether to ignore the error (ie. details not affecting the // result of VG_(tdict).tool_eq_Error()). This saves time when errors @@ -544,13 +547,14 @@ void VG_(track_post_reg_write_clientcall_return)( /* Scheduler events (not exhaustive) */ /* Called when 'tid' starts or stops running client code blocks. - Gives the total dispatched block count at that event. Note, this is - not the same as 'tid' holding the BigLock (the lock that ensures that - only one thread runs at a time): a thread can hold the lock for other - purposes (making translations, etc) yet not be running client blocks. - Obviously though, a thread must hold the lock in order to run client - code blocks, so the times bracketed by 'thread_run'..'thread_runstate' - are a subset of the times when thread 'tid' holds the cpu lock. + Gives the total dispatched block count at that event. Note, this + is not the same as 'tid' holding the BigLock (the lock that ensures + that only one thread runs at a time): a thread can hold the lock + for other purposes (making translations, etc) yet not be running + client blocks. Obviously though, a thread must hold the lock in + order to run client code blocks, so the times bracketed by + 'start_client_code'..'stop_client_code' are a subset of the times + when thread 'tid' holds the cpu lock. */ void VG_(track_start_client_code)( void(*f)(ThreadId tid, ULong blocks_dispatched) @@ -562,11 +566,16 @@ void VG_(track_stop_client_code)( /* Thread events (not exhaustive) - Called during thread create, before the new thread has run any - instructions (or touched any memory). - */ -void VG_(track_post_thread_create)(void(*f)(ThreadId tid, ThreadId child)); -void VG_(track_post_thread_join) (void(*f)(ThreadId joiner, ThreadId joinee)); + ll_create: low level thread creation. Called before the new thread + has run any instructions (or touched any memory). In fact, called + immediately before the new thread has come into existence; the new + thread can be assumed to exist when notified by this call. + + ll_exit: low level thread exit. Called after the exiting thread + has run its last instruction. +*/ +void VG_(track_pre_thread_ll_create)(void(*f)(ThreadId tid, ThreadId child)); +void VG_(track_pre_thread_ll_exit) (void(*f)(ThreadId tid)); /* Signal events (not exhaustive) -- 2.47.2