From: Bart Van Assche Date: Thu, 26 Mar 2009 19:07:15 +0000 (+0000) Subject: - Reindented code such that it uses three spaces for indentation instead X-Git-Tag: svn/VALGRIND_3_5_0~836 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=219e77b9bcc1681802bbc177e11baf1d88ab4137;p=thirdparty%2Fvalgrind.git - Reindented code such that it uses three spaces for indentation instead of two. The indentation of the DRD source code is now consistent with the other Valgrind source files. - Added emacs mode line with indentation settings. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9496 --- diff --git a/drd/drd.h b/drd/drd.h index 76c60b5862..011fe38d82 100644 --- a/drd/drd.h +++ b/drd/drd.h @@ -1,60 +1,61 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* - ---------------------------------------------------------------- + ---------------------------------------------------------------- - Notice that the following BSD-style license applies to this one - file (drd.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. + Notice that the following BSD-style license applies to this one + file (drd.h) only. The rest of Valgrind is licensed under the + terms of the GNU General Public License, version 2, unless + otherwise indicated. See the COPYING file in the source + distribution for details. - ---------------------------------------------------------------- + ---------------------------------------------------------------- - This file is part of drd, a Valgrind tool for verification of - multithreaded programs. + This file is part of drd, a Valgrind tool for verification of + multithreaded programs. - Copyright (C) 2006-2009 Bart Van Assche . - All rights reserved. + Copyright (C) 2006-2009 Bart Van Assche . + All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------- + ---------------------------------------------------------------- - Notice that the above BSD-style license applies to this one file - (drd.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. + Notice that the above BSD-style license applies to this one file + (drd.h) only. The entire rest of Valgrind is licensed under + the terms of the GNU General Public License, version 2. See the + COPYING file in the source distribution for details. - ---------------------------------------------------------------- + ---------------------------------------------------------------- */ #ifndef __VALGRIND_DRD_H @@ -68,38 +69,38 @@ This enum comprises an ABI exported by Valgrind to programs which use client requests. DO NOT CHANGE THE ORDER OF THESE ENTRIES, NOR DELETE ANY -- add new ones at the end. - */ +*/ enum -{ - /* Ask the core the thread ID assigned by Valgrind. */ - VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'), - /* args: none. */ - /* Ask the core the thread ID assigned by DRD. */ - VG_USERREQ__DRD_GET_DRD_THREAD_ID, - /* args: none. */ - - /* To tell the drd tool to suppress data race detection on the specified */ - /* address range. */ - VG_USERREQ__DRD_START_SUPPRESSION, - /* args: start address, size in bytes */ - /* To tell the drd tool no longer to suppress data race detection on the */ - /* specified address range. */ - VG_USERREQ__DRD_FINISH_SUPPRESSION, - /* args: start address, size in bytes */ - - /* To ask the drd tool to trace all accesses to the specified range. */ - VG_USERREQ__DRD_START_TRACE_ADDR, - /* args: Addr, SizeT. */ - /* To ask the drd tool to stop tracing accesses to the specified range. */ - VG_USERREQ__DRD_STOP_TRACE_ADDR, - /* args: Addr, SizeT. */ - - /* To ask the drd tool to discard all information about memory accesses */ - /* and client objects for the specified range. This client request is */ - /* binary compatible with the similarly named Helgrind client request. */ - VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'), - /* args: Addr, SizeT. */ -}; + { + /* Ask the core the thread ID assigned by Valgrind. */ + VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'), + /* args: none. */ + /* Ask the core the thread ID assigned by DRD. */ + VG_USERREQ__DRD_GET_DRD_THREAD_ID, + /* args: none. */ + + /* To tell the drd tool to suppress data race detection on the */ + /* specified address range. */ + VG_USERREQ__DRD_START_SUPPRESSION, + /* args: start address, size in bytes */ + /* To tell the drd tool no longer to suppress data race detection on */ + /* the specified address range. */ + VG_USERREQ__DRD_FINISH_SUPPRESSION, + /* args: start address, size in bytes */ + + /* To ask the drd tool to trace all accesses to the specified range. */ + VG_USERREQ__DRD_START_TRACE_ADDR, + /* args: Addr, SizeT. */ + /* To ask the drd tool to stop tracing accesses to the specified range. */ + VG_USERREQ__DRD_STOP_TRACE_ADDR, + /* args: Addr, SizeT. */ + + /* To ask the drd tool to discard all information about memory accesses */ + /* and client objects for the specified range. This client request is */ + /* binary compatible with the similarly named Helgrind client request. */ + VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'), + /* args: Addr, SizeT. */ + }; /** Tell DRD to suppress data race detection on the specified variable. */ @@ -114,35 +115,35 @@ enum static __inline__ int vg_get_valgrind_threadid(void) { - int res; - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID, - 0, 0, 0, 0, 0); - return res; + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID, + 0, 0, 0, 0, 0); + return res; } static __inline__ int vg_get_drd_threadid(void) { - int res; - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_DRD_THREAD_ID, - 0, 0, 0, 0, 0); - return res; + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_DRD_THREAD_ID, + 0, 0, 0, 0, 0); + return res; } static __inline__ void vg_drd_ignore_range(const void* const p, const int size) { - int res; - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION, - p, size, 0, 0, 0); + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION, + p, size, 0, 0, 0); } static __inline__ void vg_drd_trace_range(const void* const p, const int size) { - int res; - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_TRACE_ADDR, - p, size, 0, 0, 0); + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_TRACE_ADDR, + p, size, 0, 0, 0); } diff --git a/drd/drd_barrier.c b/drd/drd_barrier.c index d2f477f69d..55c64e4405 100644 --- a/drd/drd_barrier.c +++ b/drd/drd_barrier.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -40,14 +41,14 @@ /** Information associated with one thread participating in a barrier. */ struct barrier_thread_info { - UWord tid; // A DrdThreadId declared as UWord because - // this member variable is the key of an OSet. - Word iteration; // iteration of last pthread_barrier_wait() - // call thread tid participated in. - Segment* sg[2]; // Segments of the last two - // pthread_barrier() calls by thread tid. - ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call. - Segment* post_wait_sg; // Segment created after *_barrier_wait() finished + UWord tid; // A DrdThreadId declared as UWord because + // this member variable is the key of an OSet. + Word iteration; // iteration of last pthread_barrier_wait() + // call thread tid participated in. + Segment* sg[2]; // Segments of the last two + // pthread_barrier() calls by thread tid. + ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call. + Segment* post_wait_sg; // Segment created after *_barrier_wait() finished }; @@ -60,7 +61,7 @@ static const char* barrier_get_typename(struct barrier_info* const p); static const char* barrier_type_name(const BarrierT bt); static void barrier_report_wait_delete_race(const struct barrier_info* const p, - const struct barrier_thread_info* const q); + const struct barrier_thread_info* const q); /* Local variables. */ @@ -73,7 +74,7 @@ static ULong s_barrier_segment_creation_count; void DRD_(barrier_set_trace)(const Bool trace_barrier) { - s_trace_barrier = trace_barrier; + s_trace_barrier = trace_barrier; } /** @@ -85,12 +86,12 @@ void DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p, const DrdThreadId tid, const Word iteration) { - p->tid = tid; - p->iteration = iteration; - p->sg[0] = 0; - p->sg[1] = 0; - p->wait_call_ctxt = 0; - p->post_wait_sg = 0; + p->tid = tid; + p->iteration = iteration; + p->sg[0] = 0; + p->sg[1] = 0; + p->wait_call_ctxt = 0; + p->post_wait_sg = 0; } /** @@ -99,10 +100,10 @@ void DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p, */ static void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p) { - tl_assert(p); - DRD_(sg_put)(p->sg[0]); - DRD_(sg_put)(p->sg[1]); - DRD_(sg_put)(p->post_wait_sg); + tl_assert(p); + DRD_(sg_put)(p->sg[0]); + DRD_(sg_put)(p->sg[1]); + DRD_(sg_put)(p->post_wait_sg); } /** @@ -115,25 +116,25 @@ void DRD_(barrier_initialize)(struct barrier_info* const p, const BarrierT barrier_type, const Word count) { - tl_assert(barrier != 0); - tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); - tl_assert(p->a1 == barrier); - - p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup; - p->delete_thread - = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread; - p->barrier_type = barrier_type; - p->count = count; - p->pre_iteration = 0; - p->post_iteration = 0; - p->pre_waiters_left = count; - p->post_waiters_left = count; - - tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word)); - tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) - >= sizeof(DrdThreadId)); - p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1", - VG_(free)); + tl_assert(barrier != 0); + tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); + tl_assert(p->a1 == barrier); + + p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup; + p->delete_thread + = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread; + p->barrier_type = barrier_type; + p->count = count; + p->pre_iteration = 0; + p->post_iteration = 0; + p->pre_waiters_left = count; + p->post_waiters_left = count; + + tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word)); + tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) + >= sizeof(DrdThreadId)); + p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1", + VG_(free)); } /** @@ -144,39 +145,39 @@ void DRD_(barrier_initialize)(struct barrier_info* const p, */ static void barrier_cleanup(struct barrier_info* p) { - struct barrier_thread_info* q; - Segment* latest_sg = 0; - - tl_assert(p); - - if (p->pre_waiters_left != p->count) - { - BarrierErrInfo bei = { p->a1, 0, 0 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - BarrierErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Destruction of barrier that is being waited" - " upon", - &bei); - } - - DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)()); - tl_assert(latest_sg); - - VG_(OSetGen_ResetIter)(p->oset); - for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; ) - { - if (q->post_wait_sg - && ! DRD_(vc_lte)(&q->post_wait_sg->vc, &latest_sg->vc)) - { - barrier_report_wait_delete_race(p, q); - } - - DRD_(barrier_thread_destroy)(q); - } - VG_(OSetGen_Destroy)(p->oset); - - DRD_(sg_put)(latest_sg); + struct barrier_thread_info* q; + Segment* latest_sg = 0; + + tl_assert(p); + + if (p->pre_waiters_left != p->count) + { + BarrierErrInfo bei = { p->a1, 0, 0 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + BarrierErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Destruction of barrier that is being waited" + " upon", + &bei); + } + + DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)()); + tl_assert(latest_sg); + + VG_(OSetGen_ResetIter)(p->oset); + for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; ) + { + if (q->post_wait_sg + && ! DRD_(vc_lte)(&q->post_wait_sg->vc, &latest_sg->vc)) + { + barrier_report_wait_delete_race(p, q); + } + + DRD_(barrier_thread_destroy)(q); + } + VG_(OSetGen_Destroy)(p->oset); + + DRD_(sg_put)(latest_sg); } /** @@ -188,18 +189,18 @@ struct barrier_info* DRD_(barrier_get_or_allocate)(const Addr barrier, const BarrierT barrier_type, const Word count) { - struct barrier_info *p; - - tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); - - tl_assert(offsetof(DrdClientobj, barrier) == 0); - p = &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); - if (p == 0) - { - p = &(DRD_(clientobj_add)(barrier, ClientBarrier)->barrier); - DRD_(barrier_initialize)(p, barrier, barrier_type, count); - } - return p; + struct barrier_info *p; + + tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); + + tl_assert(offsetof(DrdClientobj, barrier) == 0); + p = &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); + if (p == 0) + { + p = &(DRD_(clientobj_add)(barrier, ClientBarrier)->barrier); + DRD_(barrier_initialize)(p, barrier, barrier_type, count); + } + return p; } /** @@ -208,8 +209,8 @@ DRD_(barrier_get_or_allocate)(const Addr barrier, */ static struct barrier_info* DRD_(barrier_get)(const Addr barrier) { - tl_assert(offsetof(DrdClientobj, barrier) == 0); - return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); + tl_assert(offsetof(DrdClientobj, barrier) == 0); + return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); } /** @@ -222,182 +223,182 @@ void DRD_(barrier_init)(const Addr barrier, const BarrierT barrier_type, const Word count, const Bool reinitialization) { - struct barrier_info* p; - - tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); - - if (count == 0) - { - BarrierErrInfo bei = { barrier, 0, 0 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - BarrierErr, - VG_(get_IP)(VG_(get_running_tid)()), - "pthread_barrier_init: 'count' argument is zero", - &bei); - } - - if (! reinitialization && barrier_type == pthread_barrier) - { - p = DRD_(barrier_get)(barrier); - if (p) - { + struct barrier_info* p; + + tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); + + if (count == 0) + { BarrierErrInfo bei = { barrier, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), - "Barrier reinitialization", + "pthread_barrier_init: 'count' argument is zero", &bei); - } - } - p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count); - - if (s_trace_barrier) - { - if (reinitialization) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_reinit %s 0x%lx count %ld -> %ld", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - barrier_get_typename(p), - barrier, - p->count, - count); - } - else - { + } + + if (! reinitialization && barrier_type == pthread_barrier) + { + p = DRD_(barrier_get)(barrier); + if (p) + { + BarrierErrInfo bei = { barrier, 0, 0 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + BarrierErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Barrier reinitialization", + &bei); + } + } + p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count); + + if (s_trace_barrier) + { + if (reinitialization) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] barrier_reinit %s 0x%lx count %ld -> %ld", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + barrier_get_typename(p), + barrier, + p->count, + count); + } + else + { + VG_(message)(Vg_UserMsg, + "[%d/%d] barrier_init %s 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + barrier_get_typename(p), + barrier); + } + } + + if (reinitialization && p->count != count) + { + if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) + { + BarrierErrInfo bei = { p->a1, 0, 0 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + BarrierErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Reinitialization of barrier with active" + " waiters", + &bei); + } + p->count = count; + } +} + +/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */ +void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type) +{ + struct barrier_info* p; + + p = DRD_(barrier_get)(barrier); + + if (s_trace_barrier) + { VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_init %s 0x%lx", + "[%d/%d] barrier_destroy %s 0x%lx", VG_(get_running_tid)(), DRD_(thread_get_running_tid)(), barrier_get_typename(p), barrier); - } - } + } + + if (p == 0) + { + GenericErrInfo GEI; + VG_(maybe_record_error)(VG_(get_running_tid)(), + GenericErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a barrier", + &GEI); + return; + } - if (reinitialization && p->count != count) - { - if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) - { + if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) + { BarrierErrInfo bei = { p->a1, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), - "Reinitialization of barrier with active" - " waiters", + "Destruction of a barrier with active waiters", &bei); - } - p->count = count; - } -} + } -/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */ -void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type) -{ - struct barrier_info* p; - - p = DRD_(barrier_get)(barrier); - - if (s_trace_barrier) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_destroy %s 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - barrier_get_typename(p), - barrier); - } - - if (p == 0) - { - GenericErrInfo GEI; - VG_(maybe_record_error)(VG_(get_running_tid)(), - GenericErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Not a barrier", - &GEI); - return; - } - - if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) - { - BarrierErrInfo bei = { p->a1, 0, 0 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - BarrierErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Destruction of a barrier with active waiters", - &bei); - } - - DRD_(clientobj_remove)(p->a1, ClientBarrier); + DRD_(clientobj_remove)(p->a1, ClientBarrier); } /** Called before pthread_barrier_wait() / gomp_barrier_wait(). */ void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier, const BarrierT barrier_type) { - struct barrier_info* p; - struct barrier_thread_info* q; - const UWord word_tid = tid; - - p = DRD_(barrier_get)(barrier); - if (p == 0 && barrier_type == gomp_barrier) - { - /* - * gomp_barrier_wait() call has been intercepted but gomp_barrier_init() - * not. The only cause I know of that can trigger this is that libgomp.so - * has been compiled with --enable-linux-futex. - */ - VG_(message)(Vg_UserMsg, ""); - VG_(message)(Vg_UserMsg, - "Please verify whether gcc has been configured" - " with option --disable-linux-futex."); - VG_(message)(Vg_UserMsg, - "See also the section about OpenMP in the DRD manual."); - VG_(message)(Vg_UserMsg, ""); - } - tl_assert(p); - - if (s_trace_barrier) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_pre_wait %s 0x%lx iteration %ld", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - barrier_get_typename(p), - barrier, - p->pre_iteration); - } - - /* Allocate the per-thread data structure if necessary. */ - q = VG_(OSetGen_Lookup)(p->oset, &word_tid); - if (q == 0) - { - q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q)); - DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration); - VG_(OSetGen_Insert)(p->oset, q); - tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); - } - - /* Record *_barrier_wait() call context. */ - q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); - - /* - * Store a pointer to the latest segment of the current thread in the - * per-thread data structure. - */ - DRD_(thread_get_latest_segment)(&q->sg[p->pre_iteration], tid); - - /* - * If the same number of threads as the barrier count indicates have - * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and - * reset the p->pre_waiters_left counter. - */ - if (--p->pre_waiters_left <= 0) - { - p->pre_iteration = 1 - p->pre_iteration; - p->pre_waiters_left = p->count; - } + struct barrier_info* p; + struct barrier_thread_info* q; + const UWord word_tid = tid; + + p = DRD_(barrier_get)(barrier); + if (p == 0 && barrier_type == gomp_barrier) + { + /* + * gomp_barrier_wait() call has been intercepted but gomp_barrier_init() + * not. The only cause I know of that can trigger this is that libgomp.so + * has been compiled with --enable-linux-futex. + */ + VG_(message)(Vg_UserMsg, ""); + VG_(message)(Vg_UserMsg, + "Please verify whether gcc has been configured" + " with option --disable-linux-futex."); + VG_(message)(Vg_UserMsg, + "See also the section about OpenMP in the DRD manual."); + VG_(message)(Vg_UserMsg, ""); + } + tl_assert(p); + + if (s_trace_barrier) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] barrier_pre_wait %s 0x%lx iteration %ld", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + barrier_get_typename(p), + barrier, + p->pre_iteration); + } + + /* Allocate the per-thread data structure if necessary. */ + q = VG_(OSetGen_Lookup)(p->oset, &word_tid); + if (q == 0) + { + q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q)); + DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration); + VG_(OSetGen_Insert)(p->oset, q); + tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); + } + + /* Record *_barrier_wait() call context. */ + q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); + + /* + * Store a pointer to the latest segment of the current thread in the + * per-thread data structure. + */ + DRD_(thread_get_latest_segment)(&q->sg[p->pre_iteration], tid); + + /* + * If the same number of threads as the barrier count indicates have + * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and + * reset the p->pre_waiters_left counter. + */ + if (--p->pre_waiters_left <= 0) + { + p->pre_iteration = 1 - p->pre_iteration; + p->pre_waiters_left = p->count; + } } /** Called after pthread_barrier_wait() / gomp_barrier_wait(). */ @@ -405,105 +406,105 @@ void DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier, const BarrierT barrier_type, const Bool waited, const Bool serializing) { - struct barrier_info* p; - const UWord word_tid = tid; - struct barrier_thread_info* q; - struct barrier_thread_info* r; - - p = DRD_(barrier_get)(barrier); - - if (s_trace_barrier) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld%s", - VG_(get_running_tid)(), - tid, - p ? barrier_get_typename(p) : "(?)", - barrier, - p ? p->post_iteration : -1, - serializing ? " (serializing)" : ""); - } - - /* - * If p == 0, this means that the barrier has been destroyed after - * *_barrier_wait() returned and before this function was called. Just - * return in that case -- race conditions between *_barrier_wait() - * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper. - */ - if (p == 0) - return; - - /* If the *_barrier_wait() call returned an error code, exit. */ - if (! waited) - return; - - q = VG_(OSetGen_Lookup)(p->oset, &word_tid); - if (q == 0) - { - BarrierErrInfo bei = { p->a1, 0, 0 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - BarrierErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Error in barrier implementation" - " -- barrier_wait() started before" - " barrier_destroy() and finished after" - " barrier_destroy()", - &bei); - - q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q)); - DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration); - VG_(OSetGen_Insert)(p->oset, q); - tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); - } - /* - * Combine all vector clocks that were stored in the pre_barrier_wait - * wrapper with the vector clock of the current thread. - */ - VG_(OSetGen_ResetIter)(p->oset); - for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; ) - { - if (r != q) - { - tl_assert(r->sg[p->post_iteration]); - DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc); - } - } - - /* Create a new segment and store a pointer to that segment. */ - DRD_(thread_new_segment)(tid); - DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid); - s_barrier_segment_creation_count++; - - /* - * If the same number of threads as the barrier count indicates have - * called the post *_barrier_wait() wrapper, toggle p->post_iteration and - * reset the p->post_waiters_left counter. - */ - if (--p->post_waiters_left <= 0) - { - p->post_iteration = 1 - p->post_iteration; - p->post_waiters_left = p->count; - } + struct barrier_info* p; + const UWord word_tid = tid; + struct barrier_thread_info* q; + struct barrier_thread_info* r; + + p = DRD_(barrier_get)(barrier); + + if (s_trace_barrier) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld%s", + VG_(get_running_tid)(), + tid, + p ? barrier_get_typename(p) : "(?)", + barrier, + p ? p->post_iteration : -1, + serializing ? " (serializing)" : ""); + } + + /* + * If p == 0, this means that the barrier has been destroyed after + * *_barrier_wait() returned and before this function was called. Just + * return in that case -- race conditions between *_barrier_wait() + * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper. + */ + if (p == 0) + return; + + /* If the *_barrier_wait() call returned an error code, exit. */ + if (! waited) + return; + + q = VG_(OSetGen_Lookup)(p->oset, &word_tid); + if (q == 0) + { + BarrierErrInfo bei = { p->a1, 0, 0 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + BarrierErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Error in barrier implementation" + " -- barrier_wait() started before" + " barrier_destroy() and finished after" + " barrier_destroy()", + &bei); + + q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q)); + DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration); + VG_(OSetGen_Insert)(p->oset, q); + tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); + } + /* + * Combine all vector clocks that were stored in the pre_barrier_wait + * wrapper with the vector clock of the current thread. + */ + VG_(OSetGen_ResetIter)(p->oset); + for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; ) + { + if (r != q) + { + tl_assert(r->sg[p->post_iteration]); + DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc); + } + } + + /* Create a new segment and store a pointer to that segment. */ + DRD_(thread_new_segment)(tid); + DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid); + s_barrier_segment_creation_count++; + + /* + * If the same number of threads as the barrier count indicates have + * called the post *_barrier_wait() wrapper, toggle p->post_iteration and + * reset the p->post_waiters_left counter. + */ + if (--p->post_waiters_left <= 0) + { + p->post_iteration = 1 - p->post_iteration; + p->post_waiters_left = p->count; + } } /** Called when thread tid stops to exist. */ static void barrier_delete_thread(struct barrier_info* const p, const DrdThreadId tid) { - struct barrier_thread_info* q; - const UWord word_tid = tid; - - q = VG_(OSetGen_Remove)(p->oset, &word_tid); - - /* - * q is only non-zero if the barrier object has been used by thread tid - * after the barrier_init() call and before the thread finished. - */ - if (q) - { - DRD_(barrier_thread_destroy)(q); - VG_(OSetGen_FreeNode)(p->oset, q); - } + struct barrier_thread_info* q; + const UWord word_tid = tid; + + q = VG_(OSetGen_Remove)(p->oset, &word_tid); + + /* + * q is only non-zero if the barrier object has been used by thread tid + * after the barrier_init() call and before the thread finished. + */ + if (q) + { + DRD_(barrier_thread_destroy)(q); + VG_(OSetGen_FreeNode)(p->oset, q); + } } /** @@ -518,41 +519,41 @@ static void barrier_report_wait_delete_race(const struct barrier_info* const p, const struct barrier_thread_info* const q) { - tl_assert(p); - tl_assert(q); - - { - BarrierErrInfo bei - = { p->a1, q->tid, q->wait_call_ctxt }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - BarrierErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Destruction of barrier not synchronized with" - " barrier wait call", - &bei); - } + tl_assert(p); + tl_assert(q); + + { + BarrierErrInfo bei + = { p->a1, q->tid, q->wait_call_ctxt }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + BarrierErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Destruction of barrier not synchronized with" + " barrier wait call", + &bei); + } } static const char* barrier_get_typename(struct barrier_info* const p) { - tl_assert(p); + tl_assert(p); - return barrier_type_name(p->barrier_type); + return barrier_type_name(p->barrier_type); } static const char* barrier_type_name(const BarrierT bt) { - switch (bt) - { - case pthread_barrier: - return "pthread barrier"; - case gomp_barrier: - return "gomp barrier"; - } - return "?"; + switch (bt) + { + case pthread_barrier: + return "pthread barrier"; + case gomp_barrier: + return "gomp barrier"; + } + return "?"; } ULong DRD_(get_barrier_segment_creation_count)(void) { - return s_barrier_segment_creation_count; + return s_barrier_segment_creation_count; } diff --git a/drd/drd_barrier.h b/drd/drd_barrier.h index 1acb4a6e30..5c019a3bd6 100644 --- a/drd/drd_barrier.h +++ b/drd/drd_barrier.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. diff --git a/drd/drd_basics.h b/drd/drd_basics.h index cc01899d3b..78b1794d78 100644 --- a/drd/drd_basics.h +++ b/drd/drd_basics.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of DRD, a thread error detector. diff --git a/drd/drd_bitmap.c b/drd/drd_bitmap.c index 73dcb04219..85cacd5078 100644 --- a/drd/drd_bitmap.c +++ b/drd/drd_bitmap.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -56,51 +57,51 @@ static ULong s_bitmap_creation_count; struct bitmap* DRD_(bm_new)() { - unsigned i; - struct bitmap* bm; + unsigned i; + struct bitmap* bm; - /* If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD */ - /* in drd_bitmap.h. */ - tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD); + /* If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD */ + /* in drd_bitmap.h. */ + tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD); - bm = VG_(malloc)("drd.bitmap.bn.1", sizeof(*bm)); - tl_assert(bm); - /* Cache initialization. a1 is initialized with a value that never can */ - /* match any valid address: the upper ADDR0_BITS bits of a1 are always */ - /* zero for a valid cache entry. */ - for (i = 0; i < N_CACHE_ELEM; i++) - { - bm->cache[i].a1 = ~(UWord)1; - bm->cache[i].bm2 = 0; - } - bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.bitmap.bn.2", - VG_(free)); + bm = VG_(malloc)("drd.bitmap.bn.1", sizeof(*bm)); + tl_assert(bm); + /* Cache initialization. a1 is initialized with a value that never can */ + /* match any valid address: the upper ADDR0_BITS bits of a1 are always */ + /* zero for a valid cache entry. */ + for (i = 0; i < N_CACHE_ELEM; i++) + { + bm->cache[i].a1 = ~(UWord)1; + bm->cache[i].bm2 = 0; + } + bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.bitmap.bn.2", + VG_(free)); - s_bitmap_creation_count++; + s_bitmap_creation_count++; - return bm; + return bm; } void DRD_(bm_delete)(struct bitmap* const bm) { - struct bitmap2* bm2; - struct bitmap2ref* bm2ref; + struct bitmap2* bm2; + struct bitmap2ref* bm2ref; - tl_assert(bm); + tl_assert(bm); - VG_(OSetGen_ResetIter)(bm->oset); - for ( ; (bm2ref = VG_(OSetGen_Next)(bm->oset)) != 0; ) - { - bm2 = bm2ref->bm2; - tl_assert(bm2->refcnt >= 1); - if (--bm2->refcnt == 0) - { - VG_(free)(bm2); - } - } + VG_(OSetGen_ResetIter)(bm->oset); + for ( ; (bm2ref = VG_(OSetGen_Next)(bm->oset)) != 0; ) + { + bm2 = bm2ref->bm2; + tl_assert(bm2->refcnt >= 1); + if (--bm2->refcnt == 0) + { + VG_(free)(bm2); + } + } - VG_(OSetGen_Destroy)(bm->oset); - VG_(free)(bm); + VG_(OSetGen_Destroy)(bm->oset); + VG_(free)(bm); } /** @@ -111,264 +112,264 @@ void DRD_(bm_access_range)(struct bitmap* const bm, const Addr a1, const Addr a2, const BmAccessTypeT access_type) { - Addr b, b_next; - - tl_assert(bm); - tl_assert(a1 < a2); - /* The current implementation of bm_access_range does not work for the */ - /* ADDR0_COUNT highest addresses in the address range. At least on Linux */ - /* this is not a problem since the upper part of the address space is */ - /* reserved for the kernel. */ - tl_assert(a2 + ADDR0_COUNT > a2); - - for (b = a1; b < a2; b = b_next) - { - Addr b_start; - Addr b_end; - struct bitmap2* bm2; - SPLIT_ADDRESS(b); - - b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; - if (b_next > a2) - { - b_next = a2; - } - - bm2 = bm2_lookup_or_insert_exclusive(bm, b1); - tl_assert(bm2); - - if ((bm2->addr << ADDR0_BITS) < a1) - b_start = a1; - else - if ((bm2->addr << ADDR0_BITS) < a2) - b_start = (bm2->addr << ADDR0_BITS); + Addr b, b_next; + + tl_assert(bm); + tl_assert(a1 < a2); + /* The current implementation of bm_access_range does not work for the */ + /* ADDR0_COUNT highest addresses in the address range. At least on Linux */ + /* this is not a problem since the upper part of the address space is */ + /* reserved for the kernel. */ + tl_assert(a2 + ADDR0_COUNT > a2); + + for (b = a1; b < a2; b = b_next) + { + Addr b_start; + Addr b_end; + struct bitmap2* bm2; + SPLIT_ADDRESS(b); + + b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; + if (b_next > a2) + { + b_next = a2; + } + + bm2 = bm2_lookup_or_insert_exclusive(bm, b1); + tl_assert(bm2); + + if ((bm2->addr << ADDR0_BITS) < a1) + b_start = a1; + else + if ((bm2->addr << ADDR0_BITS) < a2) + b_start = (bm2->addr << ADDR0_BITS); + else + break; + tl_assert(a1 <= b_start && b_start <= a2); + + if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) + b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; else - break; - tl_assert(a1 <= b_start && b_start <= a2); - - if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) - b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; - else - b_end = a2; - tl_assert(a1 <= b_end && b_end <= a2); - tl_assert(b_start < b_end); - tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); + b_end = a2; + tl_assert(a1 <= b_end && b_end <= a2); + tl_assert(b_start < b_end); + tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); - if (access_type == eLoad) - { - for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++) + if (access_type == eLoad) { - bm0_set(bm2->bm1.bm0_r, b0); + for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++) + { + bm0_set(bm2->bm1.bm0_r, b0); + } } - } - else - { - for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++) + else { - bm0_set(bm2->bm1.bm0_w, b0); + for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++) + { + bm0_set(bm2->bm1.bm0_w, b0); + } } - } - } + } } void DRD_(bm_access_range_load)(struct bitmap* const bm, const Addr a1, const Addr a2) { - DRD_(bm_access_range)(bm, a1, a2, eLoad); + DRD_(bm_access_range)(bm, a1, a2, eLoad); } void DRD_(bm_access_load_1)(struct bitmap* const bm, const Addr a1) { - bm_access_aligned_load(bm, a1, 1); + bm_access_aligned_load(bm, a1, 1); } void DRD_(bm_access_load_2)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 1) == 0) - bm_access_aligned_load(bm, a1, 2); - else - DRD_(bm_access_range)(bm, a1, a1 + 2, eLoad); + if ((a1 & 1) == 0) + bm_access_aligned_load(bm, a1, 2); + else + DRD_(bm_access_range)(bm, a1, a1 + 2, eLoad); } void DRD_(bm_access_load_4)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 3) == 0) - bm_access_aligned_load(bm, a1, 4); - else - DRD_(bm_access_range)(bm, a1, a1 + 4, eLoad); + if ((a1 & 3) == 0) + bm_access_aligned_load(bm, a1, 4); + else + DRD_(bm_access_range)(bm, a1, a1 + 4, eLoad); } void DRD_(bm_access_load_8)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 7) == 0) - bm_access_aligned_load(bm, a1, 8); - else if ((a1 & 3) == 0) - { - bm_access_aligned_load(bm, a1 + 0, 4); - bm_access_aligned_load(bm, a1 + 4, 4); - } - else - DRD_(bm_access_range)(bm, a1, a1 + 8, eLoad); + if ((a1 & 7) == 0) + bm_access_aligned_load(bm, a1, 8); + else if ((a1 & 3) == 0) + { + bm_access_aligned_load(bm, a1 + 0, 4); + bm_access_aligned_load(bm, a1 + 4, 4); + } + else + DRD_(bm_access_range)(bm, a1, a1 + 8, eLoad); } void DRD_(bm_access_range_store)(struct bitmap* const bm, const Addr a1, const Addr a2) { - DRD_(bm_access_range)(bm, a1, a2, eStore); + DRD_(bm_access_range)(bm, a1, a2, eStore); } void DRD_(bm_access_store_1)(struct bitmap* const bm, const Addr a1) { - bm_access_aligned_store(bm, a1, 1); + bm_access_aligned_store(bm, a1, 1); } void DRD_(bm_access_store_2)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 1) == 0) - bm_access_aligned_store(bm, a1, 2); - else - DRD_(bm_access_range)(bm, a1, a1 + 2, eStore); + if ((a1 & 1) == 0) + bm_access_aligned_store(bm, a1, 2); + else + DRD_(bm_access_range)(bm, a1, a1 + 2, eStore); } void DRD_(bm_access_store_4)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 3) == 0) - bm_access_aligned_store(bm, a1, 4); - else - DRD_(bm_access_range)(bm, a1, a1 + 4, eStore); + if ((a1 & 3) == 0) + bm_access_aligned_store(bm, a1, 4); + else + DRD_(bm_access_range)(bm, a1, a1 + 4, eStore); } void DRD_(bm_access_store_8)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 7) == 0) - bm_access_aligned_store(bm, a1, 8); - else if ((a1 & 3) == 0) - { - bm_access_aligned_store(bm, a1 + 0, 4); - bm_access_aligned_store(bm, a1 + 4, 4); - } - else - DRD_(bm_access_range)(bm, a1, a1 + 8, eStore); + if ((a1 & 7) == 0) + bm_access_aligned_store(bm, a1, 8); + else if ((a1 & 3) == 0) + { + bm_access_aligned_store(bm, a1 + 0, 4); + bm_access_aligned_store(bm, a1 + 4, 4); + } + else + DRD_(bm_access_range)(bm, a1, a1 + 8, eStore); } Bool DRD_(bm_has)(struct bitmap* const bm, const Addr a1, const Addr a2, const BmAccessTypeT access_type) { - Addr b; - for (b = a1; b < a2; b++) - { - if (! DRD_(bm_has_1)(bm, b, access_type)) - { - return False; - } - } - return True; + Addr b; + for (b = a1; b < a2; b++) + { + if (! DRD_(bm_has_1)(bm, b, access_type)) + { + return False; + } + } + return True; } Bool DRD_(bm_has_any_load)(struct bitmap* const bm, const Addr a1, const Addr a2) { - Addr b, b_next; + Addr b, b_next; - tl_assert(bm); + tl_assert(bm); - for (b = a1; b < a2; b = b_next) - { - const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); + for (b = a1; b < a2; b = b_next) + { + const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); - b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; - if (b_next > a2) - { - b_next = a2; - } - - if (bm2) - { - Addr b_start; - Addr b_end; - UWord b0; - const struct bitmap1* const p1 = &bm2->bm1; - - if ((bm2->addr << ADDR0_BITS) < a1) - b_start = a1; - else - if ((bm2->addr << ADDR0_BITS) < a2) - b_start = (bm2->addr << ADDR0_BITS); - else - break; - tl_assert(a1 <= b_start && b_start <= a2); + b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; + if (b_next > a2) + { + b_next = a2; + } - if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) - b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; - else - b_end = a2; - tl_assert(a1 <= b_end && b_end <= a2); - tl_assert(b_start < b_end); - tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); - - for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + if (bm2) { - if (bm0_is_set(p1->bm0_r, b0)) - { - return True; - } + Addr b_start; + Addr b_end; + UWord b0; + const struct bitmap1* const p1 = &bm2->bm1; + + if ((bm2->addr << ADDR0_BITS) < a1) + b_start = a1; + else + if ((bm2->addr << ADDR0_BITS) < a2) + b_start = (bm2->addr << ADDR0_BITS); + else + break; + tl_assert(a1 <= b_start && b_start <= a2); + + if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) + b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; + else + b_end = a2; + tl_assert(a1 <= b_end && b_end <= a2); + tl_assert(b_start < b_end); + tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); + + for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + { + if (bm0_is_set(p1->bm0_r, b0)) + { + return True; + } + } } - } - } - return 0; + } + return 0; } Bool DRD_(bm_has_any_store)(struct bitmap* const bm, const Addr a1, const Addr a2) { - Addr b, b_next; - - tl_assert(bm); + Addr b, b_next; - for (b = a1; b < a2; b = b_next) - { - const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); + tl_assert(bm); - b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; - if (b_next > a2) - { - b_next = a2; - } + for (b = a1; b < a2; b = b_next) + { + const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); - if (bm2) - { - Addr b_start; - Addr b_end; - UWord b0; - const struct bitmap1* const p1 = &bm2->bm1; - - if ((bm2->addr << ADDR0_BITS) < a1) - b_start = a1; - else - if ((bm2->addr << ADDR0_BITS) < a2) - b_start = (bm2->addr << ADDR0_BITS); - else - break; - tl_assert(a1 <= b_start && b_start <= a2); + b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; + if (b_next > a2) + { + b_next = a2; + } - if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) - b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; - else - b_end = a2; - tl_assert(a1 <= b_end && b_end <= a2); - tl_assert(b_start < b_end); - tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); - - for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + if (bm2) { - if (bm0_is_set(p1->bm0_w, b0)) - { - return True; - } + Addr b_start; + Addr b_end; + UWord b0; + const struct bitmap1* const p1 = &bm2->bm1; + + if ((bm2->addr << ADDR0_BITS) < a1) + b_start = a1; + else + if ((bm2->addr << ADDR0_BITS) < a2) + b_start = (bm2->addr << ADDR0_BITS); + else + break; + tl_assert(a1 <= b_start && b_start <= a2); + + if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) + b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; + else + b_end = a2; + tl_assert(a1 <= b_end && b_end <= a2); + tl_assert(b_start < b_end); + tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); + + for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + { + if (bm0_is_set(p1->bm0_w, b0)) + { + return True; + } + } } - } - } - return 0; + } + return 0; } /* Return True if there is a read access, write access or both */ @@ -376,54 +377,54 @@ Bool DRD_(bm_has_any_store)(struct bitmap* const bm, Bool DRD_(bm_has_any_access)(struct bitmap* const bm, const Addr a1, const Addr a2) { - Addr b, b_next; - - tl_assert(bm); + Addr b, b_next; - for (b = a1; b < a2; b = b_next) - { - const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); + tl_assert(bm); - b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; - if (b_next > a2) - { - b_next = a2; - } - - if (bm2) - { - Addr b_start; - Addr b_end; - UWord b0; - const struct bitmap1* const p1 = &bm2->bm1; + for (b = a1; b < a2; b = b_next) + { + const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); - if ((bm2->addr << ADDR0_BITS) < a1) - b_start = a1; - else - if ((bm2->addr << ADDR0_BITS) < a2) - b_start = (bm2->addr << ADDR0_BITS); - else - break; - tl_assert(a1 <= b_start && b_start <= a2); + b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; + if (b_next > a2) + { + b_next = a2; + } - if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) - b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; - else - b_end = a2; - tl_assert(a1 <= b_end && b_end <= a2); - tl_assert(b_start < b_end); - tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); - - for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + if (bm2) { - if (bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0)) - { - return True; - } + Addr b_start; + Addr b_end; + UWord b0; + const struct bitmap1* const p1 = &bm2->bm1; + + if ((bm2->addr << ADDR0_BITS) < a1) + b_start = a1; + else + if ((bm2->addr << ADDR0_BITS) < a2) + b_start = (bm2->addr << ADDR0_BITS); + else + break; + tl_assert(a1 <= b_start && b_start <= a2); + + if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) + b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; + else + b_end = a2; + tl_assert(a1 <= b_end && b_end <= a2); + tl_assert(b_start < b_end); + tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); + + for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + { + if (bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0)) + { + return True; + } + } } - } - } - return False; + } + return False; } /** @@ -433,78 +434,78 @@ Bool DRD_(bm_has_any_access)(struct bitmap* const bm, Bool DRD_(bm_has_1)(struct bitmap* const bm, const Addr a, const BmAccessTypeT access_type) { - const struct bitmap2* p2; - const struct bitmap1* p1; - const UWord* p0; - const UWord a0 = a & ADDR0_MASK; + const struct bitmap2* p2; + const struct bitmap1* p1; + const UWord* p0; + const UWord a0 = a & ADDR0_MASK; - tl_assert(bm); + tl_assert(bm); - p2 = bm2_lookup(bm, a >> ADDR0_BITS); - if (p2) - { - p1 = &p2->bm1; - p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w; - return bm0_is_set(p0, a0) ? True : False; - } - return False; + p2 = bm2_lookup(bm, a >> ADDR0_BITS); + if (p2) + { + p1 = &p2->bm1; + p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w; + return bm0_is_set(p0, a0) ? True : False; + } + return False; } void DRD_(bm_clear)(struct bitmap* const bm, const Addr a1, const Addr a2) { - Addr b, b_next; + Addr b, b_next; - tl_assert(bm); - tl_assert(a1); - tl_assert(a1 <= a2); + tl_assert(bm); + tl_assert(a1); + tl_assert(a1 <= a2); - for (b = a1; b < a2; b = b_next) - { - struct bitmap2* const p2 = bm2_lookup_exclusive(bm, b >> ADDR0_BITS); + for (b = a1; b < a2; b = b_next) + { + struct bitmap2* const p2 = bm2_lookup_exclusive(bm, b >> ADDR0_BITS); - b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; - if (b_next > a2) - { - b_next = a2; - } - - if (p2) - { - Addr c = b; - /* If the first address in the bitmap that must be cleared does not */ - /* start on an UWord boundary, start clearing the first addresses. */ - if (UWORD_LSB(c)) + b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; + if (b_next > a2) { - Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD; - if (c_next > b_next) - c_next = b_next; - bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, c_next - c); - bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, c_next - c); - c = c_next; + b_next = a2; } - /* If some UWords have to be cleared entirely, do this now. */ - if (UWORD_LSB(c) == 0) + + if (p2) { - const Addr c_next = UWORD_MSB(b_next); - tl_assert(UWORD_LSB(c) == 0); - tl_assert(UWORD_LSB(c_next) == 0); - tl_assert(c_next <= b_next); - tl_assert(c <= c_next); - if (c_next > c) - { - UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD; - VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8); - VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8); - c = c_next; - } + Addr c = b; + /* If the first address in the bitmap that must be cleared does not */ + /* start on an UWord boundary, start clearing the first addresses. */ + if (UWORD_LSB(c)) + { + Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD; + if (c_next > b_next) + c_next = b_next; + bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, c_next - c); + bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, c_next - c); + c = c_next; + } + /* If some UWords have to be cleared entirely, do this now. */ + if (UWORD_LSB(c) == 0) + { + const Addr c_next = UWORD_MSB(b_next); + tl_assert(UWORD_LSB(c) == 0); + tl_assert(UWORD_LSB(c_next) == 0); + tl_assert(c_next <= b_next); + tl_assert(c <= c_next); + if (c_next > c) + { + UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD; + VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8); + VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8); + c = c_next; + } + } + /* If the last address in the bitmap that must be cleared does not */ + /* fall on an UWord boundary, clear the last addresses. */ + /* tl_assert(c <= b_next); */ + bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, b_next - c); + bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, b_next - c); } - /* If the last address in the bitmap that must be cleared does not */ - /* fall on an UWord boundary, clear the last addresses. */ - /* tl_assert(c <= b_next); */ - bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, b_next - c); - bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, b_next - c); - } - } + } } /** @@ -513,16 +514,16 @@ void DRD_(bm_clear)(struct bitmap* const bm, const Addr a1, const Addr a2) */ void DRD_(bm_clear_load)(struct bitmap* const bm, const Addr a1, const Addr a2) { - Addr a; + Addr a; - for (a = a1; a < a2; a++) - { - struct bitmap2* const p2 = bm2_lookup_exclusive(bm, a >> ADDR0_BITS); - if (p2) - { - bm0_clear(p2->bm1.bm0_r, a & ADDR0_MASK); - } - } + for (a = a1; a < a2; a++) + { + struct bitmap2* const p2 = bm2_lookup_exclusive(bm, a >> ADDR0_BITS); + if (p2) + { + bm0_clear(p2->bm1.bm0_r, a & ADDR0_MASK); + } + } } /** @@ -532,16 +533,16 @@ void DRD_(bm_clear_load)(struct bitmap* const bm, const Addr a1, const Addr a2) void DRD_(bm_clear_store)(struct bitmap* const bm, const Addr a1, const Addr a2) { - Addr a; + Addr a; - for (a = a1; a < a2; a++) - { - struct bitmap2* const p2 = bm2_lookup_exclusive(bm, a >> ADDR0_BITS); - if (p2) - { - bm0_clear(p2->bm1.bm0_w, a & ADDR0_MASK); - } - } + for (a = a1; a < a2; a++) + { + struct bitmap2* const p2 = bm2_lookup_exclusive(bm, a >> ADDR0_BITS); + if (p2) + { + bm0_clear(p2->bm1.bm0_w, a & ADDR0_MASK); + } + } } /** @@ -552,147 +553,147 @@ void DRD_(bm_clear_store)(struct bitmap* const bm, Bool DRD_(bm_test_and_clear)(struct bitmap* const bm, const Addr a1, const Addr a2) { - Bool result; + Bool result; - result = DRD_(bm_has_any_access)(bm, a1, a2) != 0; - DRD_(bm_clear)(bm, a1, a2); - return result; + result = DRD_(bm_has_any_access)(bm, a1, a2) != 0; + DRD_(bm_clear)(bm, a1, a2); + return result; } Bool DRD_(bm_has_conflict_with)(struct bitmap* const bm, const Addr a1, const Addr a2, const BmAccessTypeT access_type) { - Addr b, b_next; - - tl_assert(bm); + Addr b, b_next; - for (b = a1; b < a2; b = b_next) - { - const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); + tl_assert(bm); - b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; - if (b_next > a2) - { - b_next = a2; - } + for (b = a1; b < a2; b = b_next) + { + const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS); - if (bm2) - { - Addr b_start; - Addr b_end; - UWord b0; - const struct bitmap1* const p1 = &bm2->bm1; - - if ((bm2->addr << ADDR0_BITS) < a1) - b_start = a1; - else - if ((bm2->addr << ADDR0_BITS) < a2) - b_start = (bm2->addr << ADDR0_BITS); - else - break; - tl_assert(a1 <= b_start && b_start <= a2); + b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; + if (b_next > a2) + { + b_next = a2; + } - if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) - b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; - else - b_end = a2; - tl_assert(a1 <= b_end && b_end <= a2); - tl_assert(b_start < b_end); - tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); - - for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + if (bm2) { - if (access_type == eLoad) - { - if (bm0_is_set(p1->bm0_w, b0)) - { - return True; - } - } - else - { - tl_assert(access_type == eStore); - if (bm0_is_set(p1->bm0_r, b0) - | bm0_is_set(p1->bm0_w, b0)) - { - return True; - } - } + Addr b_start; + Addr b_end; + UWord b0; + const struct bitmap1* const p1 = &bm2->bm1; + + if ((bm2->addr << ADDR0_BITS) < a1) + b_start = a1; + else + if ((bm2->addr << ADDR0_BITS) < a2) + b_start = (bm2->addr << ADDR0_BITS); + else + break; + tl_assert(a1 <= b_start && b_start <= a2); + + if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2) + b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT; + else + b_end = a2; + tl_assert(a1 <= b_end && b_end <= a2); + tl_assert(b_start < b_end); + tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK)); + + for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++) + { + if (access_type == eLoad) + { + if (bm0_is_set(p1->bm0_w, b0)) + { + return True; + } + } + else + { + tl_assert(access_type == eStore); + if (bm0_is_set(p1->bm0_r, b0) + | bm0_is_set(p1->bm0_w, b0)) + { + return True; + } + } + } } - } - } - return False; + } + return False; } Bool DRD_(bm_load_has_conflict_with)(struct bitmap* const bm, const Addr a1, const Addr a2) { - return DRD_(bm_has_conflict_with)(bm, a1, a2, eLoad); + return DRD_(bm_has_conflict_with)(bm, a1, a2, eLoad); } Bool DRD_(bm_load_1_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - return bm_aligned_load_has_conflict_with(bm, a1, 1); + return bm_aligned_load_has_conflict_with(bm, a1, 1); } Bool DRD_(bm_load_2_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 1) == 0) - return bm_aligned_load_has_conflict_with(bm, a1, 2); - else - return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eLoad); + if ((a1 & 1) == 0) + return bm_aligned_load_has_conflict_with(bm, a1, 2); + else + return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eLoad); } Bool DRD_(bm_load_4_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 3) == 0) - return bm_aligned_load_has_conflict_with(bm, a1, 4); - else - return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eLoad); + if ((a1 & 3) == 0) + return bm_aligned_load_has_conflict_with(bm, a1, 4); + else + return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eLoad); } Bool DRD_(bm_load_8_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 7) == 0) - return bm_aligned_load_has_conflict_with(bm, a1, 8); - else - return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eLoad); + if ((a1 & 7) == 0) + return bm_aligned_load_has_conflict_with(bm, a1, 8); + else + return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eLoad); } Bool DRD_(bm_store_1_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - return bm_aligned_store_has_conflict_with(bm, a1, 1); + return bm_aligned_store_has_conflict_with(bm, a1, 1); } Bool DRD_(bm_store_2_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 1) == 0) - return bm_aligned_store_has_conflict_with(bm, a1, 2); - else - return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eStore); + if ((a1 & 1) == 0) + return bm_aligned_store_has_conflict_with(bm, a1, 2); + else + return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eStore); } Bool DRD_(bm_store_4_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 3) == 0) - return bm_aligned_store_has_conflict_with(bm, a1, 4); - else - return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eStore); + if ((a1 & 3) == 0) + return bm_aligned_store_has_conflict_with(bm, a1, 4); + else + return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eStore); } Bool DRD_(bm_store_8_has_conflict_with)(struct bitmap* const bm, const Addr a1) { - if ((a1 & 7) == 0) - return bm_aligned_store_has_conflict_with(bm, a1, 8); - else - return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eStore); + if ((a1 & 7) == 0) + return bm_aligned_store_has_conflict_with(bm, a1, 8); + else + return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eStore); } Bool DRD_(bm_store_has_conflict_with)(struct bitmap* const bm, const Addr a1, const Addr a2) { - return DRD_(bm_has_conflict_with)(bm, a1, a2, eStore); + return DRD_(bm_has_conflict_with)(bm, a1, a2, eStore); } /** @@ -701,114 +702,114 @@ Bool DRD_(bm_store_has_conflict_with)(struct bitmap* const bm, */ Bool DRD_(bm_equal)(struct bitmap* const lhs, struct bitmap* const rhs) { - struct bitmap2* bm2l; - struct bitmap2ref* bm2l_ref; - struct bitmap2* bm2r; - const struct bitmap2ref* bm2r_ref; - - /* It's not possible to have two independent iterators over the same OSet, */ - /* so complain if lhs == rhs. */ - tl_assert(lhs != rhs); - - VG_(OSetGen_ResetIter)(lhs->oset); - VG_(OSetGen_ResetIter)(rhs->oset); - - for ( ; (bm2l_ref = VG_(OSetGen_Next)(lhs->oset)) != 0; ) - { - while (bm2l_ref - && (bm2l = bm2l_ref->bm2) - && bm2l - && ! DRD_(bm_has_any_access)(lhs, - bm2l->addr << ADDR0_BITS, - (bm2l->addr + 1) << ADDR0_BITS)) - { - bm2l_ref = VG_(OSetGen_Next)(lhs->oset); - } - if (bm2l_ref == 0) - break; - tl_assert(bm2l); + struct bitmap2* bm2l; + struct bitmap2ref* bm2l_ref; + struct bitmap2* bm2r; + const struct bitmap2ref* bm2r_ref; + + /* It's not possible to have two independent iterators over the same OSet, */ + /* so complain if lhs == rhs. */ + tl_assert(lhs != rhs); + + VG_(OSetGen_ResetIter)(lhs->oset); + VG_(OSetGen_ResetIter)(rhs->oset); + + for ( ; (bm2l_ref = VG_(OSetGen_Next)(lhs->oset)) != 0; ) + { + while (bm2l_ref + && (bm2l = bm2l_ref->bm2) + && bm2l + && ! DRD_(bm_has_any_access)(lhs, + bm2l->addr << ADDR0_BITS, + (bm2l->addr + 1) << ADDR0_BITS)) + { + bm2l_ref = VG_(OSetGen_Next)(lhs->oset); + } + if (bm2l_ref == 0) + break; + tl_assert(bm2l); #if 0 - VG_(message)(Vg_DebugMsg, "bm_equal: at 0x%lx", bm2l->addr << ADDR0_BITS); + VG_(message)(Vg_DebugMsg, "bm_equal: at 0x%lx", bm2l->addr << ADDR0_BITS); #endif - bm2r_ref = VG_(OSetGen_Next)(rhs->oset); - if (bm2r_ref == 0) - { + bm2r_ref = VG_(OSetGen_Next)(rhs->oset); + if (bm2r_ref == 0) + { #if 0 - VG_(message)(Vg_DebugMsg, "bm_equal: no match found"); + VG_(message)(Vg_DebugMsg, "bm_equal: no match found"); #endif - return False; - } - bm2r = bm2r_ref->bm2; - tl_assert(bm2r); - tl_assert(DRD_(bm_has_any_access)(rhs, - bm2r->addr << ADDR0_BITS, - (bm2r->addr + 1) << ADDR0_BITS)); - - if (bm2l != bm2r - && (bm2l->addr != bm2r->addr - || VG_(memcmp)(&bm2l->bm1, &bm2r->bm1, sizeof(bm2l->bm1)) != 0)) - { + return False; + } + bm2r = bm2r_ref->bm2; + tl_assert(bm2r); + tl_assert(DRD_(bm_has_any_access)(rhs, + bm2r->addr << ADDR0_BITS, + (bm2r->addr + 1) << ADDR0_BITS)); + + if (bm2l != bm2r + && (bm2l->addr != bm2r->addr + || VG_(memcmp)(&bm2l->bm1, &bm2r->bm1, sizeof(bm2l->bm1)) != 0)) + { #if 0 - VG_(message)(Vg_DebugMsg, "bm_equal: rhs 0x%lx -- returning false", - bm2r->addr << ADDR0_BITS); + VG_(message)(Vg_DebugMsg, "bm_equal: rhs 0x%lx -- returning false", + bm2r->addr << ADDR0_BITS); #endif - return False; - } - } - bm2r = VG_(OSetGen_Next)(rhs->oset); - if (bm2r) - { - tl_assert(DRD_(bm_has_any_access)(rhs, - bm2r->addr << ADDR0_BITS, - (bm2r->addr + 1) << ADDR0_BITS)); + return False; + } + } + bm2r = VG_(OSetGen_Next)(rhs->oset); + if (bm2r) + { + tl_assert(DRD_(bm_has_any_access)(rhs, + bm2r->addr << ADDR0_BITS, + (bm2r->addr + 1) << ADDR0_BITS)); #if 0 - VG_(message)(Vg_DebugMsg, - "bm_equal: remaining rhs 0x%lx -- returning false", - bm2r->addr << ADDR0_BITS); + VG_(message)(Vg_DebugMsg, + "bm_equal: remaining rhs 0x%lx -- returning false", + bm2r->addr << ADDR0_BITS); #endif - return False; - } - return True; + return False; + } + return True; } void DRD_(bm_swap)(struct bitmap* const bm1, struct bitmap* const bm2) { - OSet* const tmp = bm1->oset; - bm1->oset = bm2->oset; - bm2->oset = tmp; + OSet* const tmp = bm1->oset; + bm1->oset = bm2->oset; + bm2->oset = tmp; } /** Merge bitmaps *lhs and *rhs into *lhs. */ void DRD_(bm_merge2)(struct bitmap* const lhs, struct bitmap* const rhs) { - struct bitmap2* bm2l; - struct bitmap2ref* bm2l_ref; - struct bitmap2* bm2r; - const struct bitmap2ref* bm2r_ref; + struct bitmap2* bm2l; + struct bitmap2ref* bm2l_ref; + struct bitmap2* bm2r; + const struct bitmap2ref* bm2r_ref; - VG_(OSetGen_ResetIter)(rhs->oset); + VG_(OSetGen_ResetIter)(rhs->oset); - for ( ; (bm2r_ref = VG_(OSetGen_Next)(rhs->oset)) != 0; ) - { - bm2r = bm2r_ref->bm2; - bm2l_ref = VG_(OSetGen_Lookup)(lhs->oset, &bm2r->addr); - if (bm2l_ref) - { - bm2l = bm2l_ref->bm2; - if (bm2l != bm2r) + for ( ; (bm2r_ref = VG_(OSetGen_Next)(rhs->oset)) != 0; ) + { + bm2r = bm2r_ref->bm2; + bm2l_ref = VG_(OSetGen_Lookup)(lhs->oset, &bm2r->addr); + if (bm2l_ref) { - if (bm2l->refcnt > 1) - bm2l = bm2_make_exclusive(lhs, bm2l_ref); - bm2_merge(bm2l, bm2r); + bm2l = bm2l_ref->bm2; + if (bm2l != bm2r) + { + if (bm2l->refcnt > 1) + bm2l = bm2_make_exclusive(lhs, bm2l_ref); + bm2_merge(bm2l, bm2r); + } } - } - else - { - bm2_insert_addref(lhs, bm2r); - } - } + else + { + bm2_insert_addref(lhs, bm2r); + } + } } /** @@ -819,114 +820,114 @@ void DRD_(bm_merge2)(struct bitmap* const lhs, */ int DRD_(bm_has_races)(struct bitmap* const lhs, struct bitmap* const rhs) { - VG_(OSetGen_ResetIter)(lhs->oset); - VG_(OSetGen_ResetIter)(rhs->oset); - - for (;;) - { - const struct bitmap2ref* bm2l_ref; - const struct bitmap2ref* bm2r_ref; - const struct bitmap2* bm2l; - const struct bitmap2* bm2r; - const struct bitmap1* bm1l; - const struct bitmap1* bm1r; - unsigned k; - - bm2l_ref = VG_(OSetGen_Next)(lhs->oset); - bm2l = bm2l_ref->bm2; - bm2r_ref = VG_(OSetGen_Next)(rhs->oset); - bm2r = bm2r_ref->bm2; - while (bm2l && bm2r && bm2l->addr != bm2r->addr) - { - if (bm2l->addr < bm2r->addr) - bm2l = (bm2l_ref = VG_(OSetGen_Next)(lhs->oset))->bm2; - else - bm2r = (bm2r_ref = VG_(OSetGen_Next)(rhs->oset))->bm2; - } - if (bm2l == 0 || bm2r == 0) - break; + VG_(OSetGen_ResetIter)(lhs->oset); + VG_(OSetGen_ResetIter)(rhs->oset); - bm1l = &bm2l->bm1; - bm1r = &bm2r->bm1; + for (;;) + { + const struct bitmap2ref* bm2l_ref; + const struct bitmap2ref* bm2r_ref; + const struct bitmap2* bm2l; + const struct bitmap2* bm2r; + const struct bitmap1* bm1l; + const struct bitmap1* bm1r; + unsigned k; - for (k = 0; k < BITMAP1_UWORD_COUNT; k++) - { - unsigned b; - for (b = 0; b < BITS_PER_UWORD; b++) + bm2l_ref = VG_(OSetGen_Next)(lhs->oset); + bm2l = bm2l_ref->bm2; + bm2r_ref = VG_(OSetGen_Next)(rhs->oset); + bm2r = bm2r_ref->bm2; + while (bm2l && bm2r && bm2l->addr != bm2r->addr) { - UWord const access_mask - = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0) - | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0) - | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0) - | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0); - Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b); - if (HAS_RACE(access_mask) && ! DRD_(is_suppressed)(a, a + 1)) - { - return 1; - } + if (bm2l->addr < bm2r->addr) + bm2l = (bm2l_ref = VG_(OSetGen_Next)(lhs->oset))->bm2; + else + bm2r = (bm2r_ref = VG_(OSetGen_Next)(rhs->oset))->bm2; } - } - } - return 0; + if (bm2l == 0 || bm2r == 0) + break; + + bm1l = &bm2l->bm1; + bm1r = &bm2r->bm1; + + for (k = 0; k < BITMAP1_UWORD_COUNT; k++) + { + unsigned b; + for (b = 0; b < BITS_PER_UWORD; b++) + { + UWord const access_mask + = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0) + | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0) + | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0) + | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0); + Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b); + if (HAS_RACE(access_mask) && ! DRD_(is_suppressed)(a, a + 1)) + { + return 1; + } + } + } + } + return 0; } void DRD_(bm_print)(struct bitmap* const bm) { - struct bitmap2* bm2; - struct bitmap2ref* bm2ref; + struct bitmap2* bm2; + struct bitmap2ref* bm2ref; - VG_(OSetGen_ResetIter)(bm->oset); + VG_(OSetGen_ResetIter)(bm->oset); - for ( ; (bm2ref = VG_(OSetGen_Next)(bm->oset)) != 0; ) - { - const struct bitmap1* bm1; - unsigned b; + for ( ; (bm2ref = VG_(OSetGen_Next)(bm->oset)) != 0; ) + { + const struct bitmap1* bm1; + unsigned b; - bm2 = bm2ref->bm2; - bm1 = &bm2->bm1; - for (b = 0; b < ADDR0_COUNT; b++) - { - const Addr a = (bm2->addr << ADDR0_BITS) | b; - const Bool r = bm0_is_set(bm1->bm0_r, b) != 0; - const Bool w = bm0_is_set(bm1->bm0_w, b) != 0; - if (r || w) + bm2 = bm2ref->bm2; + bm1 = &bm2->bm1; + for (b = 0; b < ADDR0_COUNT; b++) { - VG_(printf)("0x%08lx %c %c\n", - a, - w ? 'W' : ' ', - r ? 'R' : ' '); + const Addr a = (bm2->addr << ADDR0_BITS) | b; + const Bool r = bm0_is_set(bm1->bm0_r, b) != 0; + const Bool w = bm0_is_set(bm1->bm0_w, b) != 0; + if (r || w) + { + VG_(printf)("0x%08lx %c %c\n", + a, + w ? 'W' : ' ', + r ? 'R' : ' '); + } } - } - } + } } ULong DRD_(bm_get_bitmap_creation_count)(void) { - return s_bitmap_creation_count; + return s_bitmap_creation_count; } ULong DRD_(bm_get_bitmap2_node_creation_count)(void) { - return s_bitmap2_node_creation_count; + return s_bitmap2_node_creation_count; } ULong DRD_(bm_get_bitmap2_creation_count)(void) { - return s_bitmap2_creation_count; + return s_bitmap2_creation_count; } /** Allocate and initialize a second level bitmap. */ static struct bitmap2* bm2_new(const UWord a1) { - struct bitmap2* bm2; + struct bitmap2* bm2; - bm2 = VG_(malloc)("drd.bitmap.bm2n.1", sizeof(*bm2)); - bm2->addr = a1; - bm2->refcnt = 1; + bm2 = VG_(malloc)("drd.bitmap.bm2n.1", sizeof(*bm2)); + bm2->addr = a1; + bm2->refcnt = 1; - s_bitmap2_creation_count++; + s_bitmap2_creation_count++; - return bm2; + return bm2; } /** Make a copy of a shared second level bitmap such that the copy can be @@ -938,46 +939,46 @@ static struct bitmap2* bm2_new(const UWord a1) static struct bitmap2* bm2_make_exclusive(struct bitmap* const bm, struct bitmap2ref* const bm2ref) { - UWord a1; - struct bitmap2* bm2; - struct bitmap2* bm2_copy; + UWord a1; + struct bitmap2* bm2; + struct bitmap2* bm2_copy; - tl_assert(bm); - tl_assert(bm2ref); - bm2 = bm2ref->bm2; - tl_assert(bm2); - tl_assert(bm2->refcnt > 1); - bm2->refcnt--; - tl_assert(bm2->refcnt >= 1); - a1 = bm2->addr; - bm2_copy = bm2_new(a1); - tl_assert(bm2_copy); - tl_assert(bm2_copy->addr == a1); - tl_assert(bm2_copy->refcnt == 1); - VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1)); - bm2ref->bm2 = bm2_copy; + tl_assert(bm); + tl_assert(bm2ref); + bm2 = bm2ref->bm2; + tl_assert(bm2); + tl_assert(bm2->refcnt > 1); + bm2->refcnt--; + tl_assert(bm2->refcnt >= 1); + a1 = bm2->addr; + bm2_copy = bm2_new(a1); + tl_assert(bm2_copy); + tl_assert(bm2_copy->addr == a1); + tl_assert(bm2_copy->refcnt == 1); + VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1)); + bm2ref->bm2 = bm2_copy; - bm_update_cache(bm, a1, bm2_copy); + bm_update_cache(bm, a1, bm2_copy); - return bm2_copy; + return bm2_copy; } static void bm2_merge(struct bitmap2* const bm2l, const struct bitmap2* const bm2r) { - unsigned k; - - tl_assert(bm2l); - tl_assert(bm2r); - tl_assert(bm2l->addr == bm2r->addr); - tl_assert(bm2l->refcnt == 1); - - for (k = 0; k < BITMAP1_UWORD_COUNT; k++) - { - bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k]; - } - for (k = 0; k < BITMAP1_UWORD_COUNT; k++) - { - bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k]; - } + unsigned k; + + tl_assert(bm2l); + tl_assert(bm2r); + tl_assert(bm2l->addr == bm2r->addr); + tl_assert(bm2l->refcnt == 1); + + for (k = 0; k < BITMAP1_UWORD_COUNT; k++) + { + bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k]; + } + for (k = 0; k < BITMAP1_UWORD_COUNT; k++) + { + bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k]; + } } diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h index 731bbcd024..84f1eb514b 100644 --- a/drd/drd_bitmap.h +++ b/drd/drd_bitmap.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -47,13 +48,13 @@ #define ADDR0_MASK (ADDR0_COUNT - 1) -#define SPLIT_ADDRESS(a) \ - UWord a##0 = ((a) & ADDR0_MASK); \ - UWord a##1 = ((a) >> ADDR0_BITS); +#define SPLIT_ADDRESS(a) \ + UWord a##0 = ((a) & ADDR0_MASK); \ + UWord a##1 = ((a) >> ADDR0_BITS); // Assumption: sizeof(Addr) == sizeof(UWord). -#define MAKE_ADDRESS(a1, a0) \ - (Addr)(((UWord)(a1) << (ADDR0_BITS)) | ((UWord)(a0))) +#define MAKE_ADDRESS(a1, a0) \ + (Addr)(((UWord)(a1) << (ADDR0_BITS)) | ((UWord)(a0))) #define BITS_PER_UWORD (8UL*sizeof(UWord)) #if defined(VGA_x86) || defined(VGA_ppc32) @@ -91,21 +92,21 @@ static ULong s_bitmap2_node_creation_count; /* Lowest level, corresponding to the lowest ADDR0_BITS of an address. */ struct bitmap1 { - UWord bm0_r[BITMAP1_UWORD_COUNT]; - UWord bm0_w[BITMAP1_UWORD_COUNT]; + UWord bm0_r[BITMAP1_UWORD_COUNT]; + UWord bm0_w[BITMAP1_UWORD_COUNT]; }; static __inline__ UWord bm0_mask(const Addr a) { - return ((UWord)1 << UWORD_LSB(a)); + return ((UWord)1 << UWORD_LSB(a)); } static __inline__ void bm0_set(UWord* bm0, const Addr a) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(a < ADDR0_COUNT); + tl_assert(a < ADDR0_COUNT); #endif - bm0[a >> BITS_PER_BITS_PER_UWORD] |= (UWord)1 << UWORD_LSB(a); + bm0[a >> BITS_PER_BITS_PER_UWORD] |= (UWord)1 << UWORD_LSB(a); } /** Set all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */ @@ -113,21 +114,21 @@ static __inline__ void bm0_set_range(UWord* bm0, const Addr a1, const SizeT size) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(a1 < ADDR0_COUNT); - tl_assert(size > 0); - tl_assert(a1 + size <= ADDR0_COUNT); - tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1)); + tl_assert(a1 < ADDR0_COUNT); + tl_assert(size > 0); + tl_assert(a1 + size <= ADDR0_COUNT); + tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1)); #endif - bm0[a1 >> BITS_PER_BITS_PER_UWORD] - |= (((UWord)1 << size) - 1) << UWORD_LSB(a1); + bm0[a1 >> BITS_PER_BITS_PER_UWORD] + |= (((UWord)1 << size) - 1) << UWORD_LSB(a1); } static __inline__ void bm0_clear(UWord* bm0, const Addr a) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(a < ADDR0_COUNT); + tl_assert(a < ADDR0_COUNT); #endif - bm0[a >> BITS_PER_BITS_PER_UWORD] &= ~((UWord)1 << UWORD_LSB(a)); + bm0[a >> BITS_PER_BITS_PER_UWORD] &= ~((UWord)1 << UWORD_LSB(a)); } /** Clear all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */ @@ -135,21 +136,21 @@ static __inline__ void bm0_clear_range(UWord* bm0, const Addr a1, const SizeT size) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(a1 < ADDR0_COUNT); - tl_assert(size > 0); - tl_assert(a1 + size <= ADDR0_COUNT); - tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1)); + tl_assert(a1 < ADDR0_COUNT); + tl_assert(size > 0); + tl_assert(a1 + size <= ADDR0_COUNT); + tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1)); #endif - bm0[a1 >> BITS_PER_BITS_PER_UWORD] - &= ~(((UWord)1 << size) - 1) << UWORD_LSB(a1); + bm0[a1 >> BITS_PER_BITS_PER_UWORD] + &= ~(((UWord)1 << size) - 1) << UWORD_LSB(a1); } static __inline__ UWord bm0_is_set(const UWord* bm0, const Addr a) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(a < ADDR0_COUNT); + tl_assert(a < ADDR0_COUNT); #endif - return (bm0[a >> BITS_PER_BITS_PER_UWORD] & ((UWord)1 << UWORD_LSB(a))); + return (bm0[a >> BITS_PER_BITS_PER_UWORD] & ((UWord)1 << UWORD_LSB(a))); } /** Return true if any of the bits [ a1 .. a1+size [ are set in bm0. */ @@ -157,13 +158,13 @@ static __inline__ UWord bm0_is_any_set(const UWord* bm0, const Addr a1, const SizeT size) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(a1 < ADDR0_COUNT); - tl_assert(size > 0); - tl_assert(a1 + size <= ADDR0_COUNT); - tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1)); + tl_assert(a1 < ADDR0_COUNT); + tl_assert(size > 0); + tl_assert(a1 + size <= ADDR0_COUNT); + tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1)); #endif - return (bm0[a1 >> BITS_PER_BITS_PER_UWORD] - & ((((UWord)1 << size) - 1) << UWORD_LSB(a1))); + return (bm0[a1 >> BITS_PER_BITS_PER_UWORD] + & ((((UWord)1 << size) - 1) << UWORD_LSB(a1))); } @@ -176,22 +177,22 @@ static __inline__ UWord bm0_is_any_set(const UWord* bm0, /* Second level bitmap. */ struct bitmap2 { - Addr addr; ///< address >> ADDR0_BITS - int refcnt; - struct bitmap1 bm1; + Addr addr; ///< address >> ADDR0_BITS + int refcnt; + struct bitmap1 bm1; }; /* One node of bitmap::oset. */ struct bitmap2ref { - Addr addr; ///< address >> ADDR0_BITS - struct bitmap2* bm2; + Addr addr; ///< address >> ADDR0_BITS + struct bitmap2* bm2; }; struct bm_cache_elem { - Addr a1; - struct bitmap2* bm2; + Addr a1; + struct bitmap2* bm2; }; #define N_CACHE_ELEM 4 @@ -199,8 +200,8 @@ struct bm_cache_elem /* Complete bitmap. */ struct bitmap { - struct bm_cache_elem cache[N_CACHE_ELEM]; - OSet* oset; + struct bm_cache_elem cache[N_CACHE_ELEM]; + OSet* oset; }; @@ -215,26 +216,26 @@ static __inline__ void bm_cache_rotate(struct bm_cache_elem cache[], const int n) { #if 0 - struct bm_cache_elem t; - - tl_assert(2 <= n && n <= 8); - - t = cache[0]; - if (n > 1) - cache[0] = cache[1]; - if (n > 2) - cache[1] = cache[2]; - if (n > 3) - cache[2] = cache[3]; - if (n > 4) - cache[3] = cache[4]; - if (n > 5) - cache[4] = cache[5]; - if (n > 6) - cache[5] = cache[6]; - if (n > 7) - cache[6] = cache[7]; - cache[n - 1] = t; + struct bm_cache_elem t; + + tl_assert(2 <= n && n <= 8); + + t = cache[0]; + if (n > 1) + cache[0] = cache[1]; + if (n > 2) + cache[1] = cache[2]; + if (n > 3) + cache[2] = cache[3]; + if (n > 4) + cache[3] = cache[4]; + if (n > 5) + cache[4] = cache[5]; + if (n > 6) + cache[5] = cache[6]; + if (n > 7) + cache[6] = cache[7]; + cache[n - 1] = t; #endif } @@ -243,77 +244,77 @@ Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1, struct bitmap2** bm2) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm); - tl_assert(bm2); + tl_assert(bm); + tl_assert(bm2); #endif #if N_CACHE_ELEM > 8 #error Please update the code below. #endif #if N_CACHE_ELEM >= 1 - if (a1 == bm->cache[0].a1) - { - *bm2 = bm->cache[0].bm2; - return True; - } + if (a1 == bm->cache[0].a1) + { + *bm2 = bm->cache[0].bm2; + return True; + } #endif #if N_CACHE_ELEM >= 2 - if (a1 == bm->cache[1].a1) - { - *bm2 = bm->cache[1].bm2; - return True; - } + if (a1 == bm->cache[1].a1) + { + *bm2 = bm->cache[1].bm2; + return True; + } #endif #if N_CACHE_ELEM >= 3 - if (a1 == bm->cache[2].a1) - { - *bm2 = bm->cache[2].bm2; - bm_cache_rotate(bm->cache, 3); - return True; - } + if (a1 == bm->cache[2].a1) + { + *bm2 = bm->cache[2].bm2; + bm_cache_rotate(bm->cache, 3); + return True; + } #endif #if N_CACHE_ELEM >= 4 - if (a1 == bm->cache[3].a1) - { - *bm2 = bm->cache[3].bm2; - bm_cache_rotate(bm->cache, 4); - return True; - } + if (a1 == bm->cache[3].a1) + { + *bm2 = bm->cache[3].bm2; + bm_cache_rotate(bm->cache, 4); + return True; + } #endif #if N_CACHE_ELEM >= 5 - if (a1 == bm->cache[4].a1) - { - *bm2 = bm->cache[4].bm2; - bm_cache_rotate(bm->cache, 5); - return True; - } + if (a1 == bm->cache[4].a1) + { + *bm2 = bm->cache[4].bm2; + bm_cache_rotate(bm->cache, 5); + return True; + } #endif #if N_CACHE_ELEM >= 6 - if (a1 == bm->cache[5].a1) - { - *bm2 = bm->cache[5].bm2; - bm_cache_rotate(bm->cache, 6); - return True; - } + if (a1 == bm->cache[5].a1) + { + *bm2 = bm->cache[5].bm2; + bm_cache_rotate(bm->cache, 6); + return True; + } #endif #if N_CACHE_ELEM >= 7 - if (a1 == bm->cache[6].a1) - { - *bm2 = bm->cache[6].bm2; - bm_cache_rotate(bm->cache, 7); - return True; - } + if (a1 == bm->cache[6].a1) + { + *bm2 = bm->cache[6].bm2; + bm_cache_rotate(bm->cache, 7); + return True; + } #endif #if N_CACHE_ELEM >= 8 - if (a1 == bm->cache[7].a1) - { - *bm2 = bm->cache[7].bm2; - bm_cache_rotate(bm->cache, 8); - return True; - } -#endif - *bm2 = 0; - return False; + if (a1 == bm->cache[7].a1) + { + *bm2 = bm->cache[7].bm2; + bm_cache_rotate(bm->cache, 8); + return True; + } +#endif + *bm2 = 0; + return False; } static __inline__ @@ -322,35 +323,35 @@ void bm_update_cache(struct bitmap* const bm, struct bitmap2* const bm2) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm); + tl_assert(bm); #endif #if N_CACHE_ELEM > 8 #error Please update the code below. #endif #if N_CACHE_ELEM >= 8 - bm->cache[7] = bm->cache[6]; + bm->cache[7] = bm->cache[6]; #endif #if N_CACHE_ELEM >= 7 - bm->cache[6] = bm->cache[5]; + bm->cache[6] = bm->cache[5]; #endif #if N_CACHE_ELEM >= 6 - bm->cache[5] = bm->cache[4]; + bm->cache[5] = bm->cache[4]; #endif #if N_CACHE_ELEM >= 5 - bm->cache[4] = bm->cache[3]; + bm->cache[4] = bm->cache[3]; #endif #if N_CACHE_ELEM >= 4 - bm->cache[3] = bm->cache[2]; + bm->cache[3] = bm->cache[2]; #endif #if N_CACHE_ELEM >= 3 - bm->cache[2] = bm->cache[1]; + bm->cache[2] = bm->cache[1]; #endif #if N_CACHE_ELEM >= 2 - bm->cache[1] = bm->cache[0]; + bm->cache[1] = bm->cache[0]; #endif - bm->cache[0].a1 = a1; - bm->cache[0].bm2 = bm2; + bm->cache[0].a1 = a1; + bm->cache[0].bm2 = bm2; } /** Look up the address a1 in bitmap bm and return a pointer to a potentially @@ -363,22 +364,22 @@ void bm_update_cache(struct bitmap* const bm, static __inline__ const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1) { - struct bitmap2* bm2; - struct bitmap2ref* bm2ref; + struct bitmap2* bm2; + struct bitmap2ref* bm2ref; #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm); + tl_assert(bm); #endif - if (! bm_cache_lookup(bm, a1, &bm2)) - { - bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); - if (bm2ref) - { - bm2 = bm2ref->bm2; - } - bm_update_cache(*(struct bitmap**)&bm, a1, bm2); - } - return bm2; + if (! bm_cache_lookup(bm, a1, &bm2)) + { + bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); + if (bm2ref) + { + bm2 = bm2ref->bm2; + } + bm_update_cache(*(struct bitmap**)&bm, a1, bm2); + } + return bm2; } /** Look up the address a1 in bitmap bm and return a pointer to a second @@ -391,40 +392,40 @@ static __inline__ struct bitmap2* bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1) { - struct bitmap2ref* bm2ref; - struct bitmap2* bm2; - - bm2ref = 0; - if (bm_cache_lookup(bm, a1, &bm2)) - { - if (bm2 == 0) - return 0; - if (bm2->refcnt > 1) - { + struct bitmap2ref* bm2ref; + struct bitmap2* bm2; + + bm2ref = 0; + if (bm_cache_lookup(bm, a1, &bm2)) + { + if (bm2 == 0) + return 0; + if (bm2->refcnt > 1) + { + bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); + } + } + else + { bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); - } - } - else - { - bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); - if (bm2ref == 0) - return 0; - bm2 = bm2ref->bm2; - } + if (bm2ref == 0) + return 0; + bm2 = bm2ref->bm2; + } #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm2); + tl_assert(bm2); #endif - if (bm2->refcnt > 1) - { + if (bm2->refcnt > 1) + { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm2ref); + tl_assert(bm2ref); #endif - bm2 = bm2_make_exclusive(*(struct bitmap**)&bm, bm2ref); - } + bm2 = bm2_make_exclusive(*(struct bitmap**)&bm, bm2ref); + } - return bm2; + return bm2; } /** Look up the address a1 in bitmap bm. The returned second level bitmap has @@ -436,20 +437,20 @@ bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1) static __inline__ struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1) { - struct bitmap2ref* bm2ref; - struct bitmap2* bm2; - - s_bitmap2_node_creation_count++; - bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref)); - bm2ref->addr = a1; - bm2 = bm2_new(a1); - bm2ref->bm2 = bm2; - VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1)); - VG_(OSetGen_Insert)(bm->oset, bm2ref); + struct bitmap2ref* bm2ref; + struct bitmap2* bm2; + + s_bitmap2_node_creation_count++; + bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref)); + bm2ref->addr = a1; + bm2 = bm2_new(a1); + bm2ref->bm2 = bm2; + VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1)); + VG_(OSetGen_Insert)(bm->oset, bm2ref); - bm_update_cache(*(struct bitmap**)&bm, a1, bm2); + bm_update_cache(*(struct bitmap**)&bm, a1, bm2); - return bm2; + return bm2; } /** Insert a new node in bitmap bm that points to the second level bitmap @@ -459,23 +460,23 @@ static __inline__ struct bitmap2* bm2_insert_addref(struct bitmap* const bm, struct bitmap2* const bm2) { - struct bitmap2ref* bm2ref; + struct bitmap2ref* bm2ref; #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm); - tl_assert(VG_(OSetGen_Lookup)(bm->oset, &bm2->addr) == 0); + tl_assert(bm); + tl_assert(VG_(OSetGen_Lookup)(bm->oset, &bm2->addr) == 0); #endif - s_bitmap2_node_creation_count++; - bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref)); - bm2ref->addr = bm2->addr; - bm2ref->bm2 = bm2; - bm2->refcnt++; - VG_(OSetGen_Insert)(bm->oset, bm2ref); + s_bitmap2_node_creation_count++; + bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref)); + bm2ref->addr = bm2->addr; + bm2ref->bm2 = bm2; + bm2->refcnt++; + VG_(OSetGen_Insert)(bm->oset, bm2ref); - bm_update_cache(*(struct bitmap**)&bm, bm2->addr, bm2); + bm_update_cache(*(struct bitmap**)&bm, bm2->addr, bm2); - return bm2; + return bm2; } /** Look up the address a1 in bitmap bm, and insert it if not found. @@ -487,33 +488,33 @@ struct bitmap2* bm2_insert_addref(struct bitmap* const bm, static __inline__ struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1) { - struct bitmap2ref* bm2ref; - struct bitmap2* bm2; + struct bitmap2ref* bm2ref; + struct bitmap2* bm2; #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm); -#endif - if (bm_cache_lookup(bm, a1, &bm2)) - { - if (bm2 == 0) - { - bm2 = bm2_insert(bm, a1); - } - } - else - { - bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); - if (bm2ref) - { - bm2 = bm2ref->bm2; - } - else - { - bm2 = bm2_insert(bm, a1); - } - bm_update_cache(*(struct bitmap**)&bm, a1, bm2); - } - return bm2; + tl_assert(bm); +#endif + if (bm_cache_lookup(bm, a1, &bm2)) + { + if (bm2 == 0) + { + bm2 = bm2_insert(bm, a1); + } + } + else + { + bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); + if (bm2ref) + { + bm2 = bm2ref->bm2; + } + else + { + bm2 = bm2_insert(bm, a1); + } + bm_update_cache(*(struct bitmap**)&bm, a1, bm2); + } + return bm2; } /** Look up the address a1 in bitmap bm, and insert it if not found. @@ -526,72 +527,72 @@ static __inline__ struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm, const UWord a1) { - struct bitmap2* bm2; + struct bitmap2* bm2; #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm); + tl_assert(bm); #endif - bm2 = (struct bitmap2*)bm2_lookup_or_insert(bm, a1); + bm2 = (struct bitmap2*)bm2_lookup_or_insert(bm, a1); #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - tl_assert(bm2); -#endif - if (bm2->refcnt > 1) - { - struct bitmap2ref* bm2ref; - bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); - bm2 = bm2_make_exclusive(bm, bm2ref); - } - return bm2; + tl_assert(bm2); +#endif + if (bm2->refcnt > 1) + { + struct bitmap2ref* bm2ref; + bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1); + bm2 = bm2_make_exclusive(bm, bm2ref); + } + return bm2; } static __inline__ void bm_access_aligned_load(struct bitmap* const bm, const Addr a1, const SizeT size) { - struct bitmap2* bm2; + struct bitmap2* bm2; - bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS); - bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size); + bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS); + bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size); } static __inline__ void bm_access_aligned_store(struct bitmap* const bm, const Addr a1, const SizeT size) { - struct bitmap2* bm2; + struct bitmap2* bm2; - bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS); - bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size); + bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS); + bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size); } static __inline__ Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm, const Addr a1, const SizeT size) { - const struct bitmap2* bm2; + const struct bitmap2* bm2; - bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS); + bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS); - return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size)); + return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size)); } static __inline__ Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm, const Addr a1, const SizeT size) { - const struct bitmap2* bm2; - - bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS); - - if (bm2) - { - if (bm0_is_any_set(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size) - | bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size)) - { - return True; - } - } - return False; + const struct bitmap2* bm2; + + bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS); + + if (bm2) + { + if (bm0_is_any_set(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size) + | bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size)) + { + return True; + } + } + return False; } #endif /* __DRD_BITMAP_H */ diff --git a/drd/drd_clientobj.c b/drd/drd_clientobj.c index bb54657033..87565e4f77 100644 --- a/drd/drd_clientobj.c +++ b/drd/drd_clientobj.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -50,16 +51,16 @@ static Bool clientobj_remove_obj(DrdClientobj* const p); void DRD_(clientobj_set_trace)(const Bool trace) { - s_trace_clientobj = trace; + s_trace_clientobj = trace; } /** Initialize the client object set. */ void DRD_(clientobj_init)(void) { - tl_assert(s_clientobj_set == 0); - s_clientobj_set = VG_(OSetGen_Create)(0, 0, VG_(malloc), - "drd.clientobj.ci.1", VG_(free)); - tl_assert(s_clientobj_set); + tl_assert(s_clientobj_set == 0); + s_clientobj_set = VG_(OSetGen_Create)(0, 0, VG_(malloc), + "drd.clientobj.ci.1", VG_(free)); + tl_assert(s_clientobj_set); } /** @@ -69,10 +70,10 @@ void DRD_(clientobj_init)(void) */ void DRD_(clientobj_cleanup)(void) { - tl_assert(s_clientobj_set); - tl_assert(VG_(OSetGen_Size)(s_clientobj_set) == 0); - VG_(OSetGen_Destroy)(s_clientobj_set); - s_clientobj_set = 0; + tl_assert(s_clientobj_set); + tl_assert(VG_(OSetGen_Size)(s_clientobj_set) == 0); + VG_(OSetGen_Destroy)(s_clientobj_set); + s_clientobj_set = 0; } /** @@ -82,7 +83,7 @@ void DRD_(clientobj_cleanup)(void) */ DrdClientobj* DRD_(clientobj_get_any)(const Addr addr) { - return VG_(OSetGen_Lookup)(s_clientobj_set, &addr); + return VG_(OSetGen_Lookup)(s_clientobj_set, &addr); } /** @@ -92,11 +93,11 @@ DrdClientobj* DRD_(clientobj_get_any)(const Addr addr) */ DrdClientobj* DRD_(clientobj_get)(const Addr addr, const ObjType t) { - DrdClientobj* p; - p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr); - if (p && p->any.type == t) - return p; - return 0; + DrdClientobj* p; + p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr); + if (p && p->any.type == t) + return p; + return 0; } /** Return true if and only if the address range of any client object overlaps @@ -104,45 +105,47 @@ DrdClientobj* DRD_(clientobj_get)(const Addr addr, const ObjType t) */ Bool DRD_(clientobj_present)(const Addr a1, const Addr a2) { - DrdClientobj *p; - - tl_assert(a1 < a2); - VG_(OSetGen_ResetIter)(s_clientobj_set); - for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; ) - { - if (a1 <= p->any.a1 && p->any.a1 < a2) - { - return True; - } - } - return False; + DrdClientobj *p; + + tl_assert(a1 < a2); + VG_(OSetGen_ResetIter)(s_clientobj_set); + for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; ) + { + if (a1 <= p->any.a1 && p->any.a1 < a2) + { + return True; + } + } + return False; } -/** Add state information for the client object at client address addr and - * of type t. Suppress data race reports on the address range [addr,addr+size[. - * @pre No other client object is present in the address range [addr,addr+size[. +/** + * Add state information for the client object at client address addr and + * of type t. Suppress data race reports on the address range [addr,addr+size[. + * + * @pre No other client object is present in the address range [addr,addr+size[. */ DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t) { - DrdClientobj* p; - - tl_assert(! DRD_(clientobj_present)(a1, a1 + 1)); - tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == 0); - - if (s_trace_clientobj) - { - VG_(message)(Vg_UserMsg, "Adding client object 0x%lx of type %d", a1, t); - } - - p = VG_(OSetGen_AllocNode)(s_clientobj_set, sizeof(*p)); - VG_(memset)(p, 0, sizeof(*p)); - p->any.a1 = a1; - p->any.type = t; - p->any.first_observed_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); - VG_(OSetGen_Insert)(s_clientobj_set, p); - tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == p); - DRD_(start_suppression)(a1, a1 + 1, "clientobj"); - return p; + DrdClientobj* p; + + tl_assert(! DRD_(clientobj_present)(a1, a1 + 1)); + tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == 0); + + if (s_trace_clientobj) + { + VG_(message)(Vg_UserMsg, "Adding client object 0x%lx of type %d", a1, t); + } + + p = VG_(OSetGen_AllocNode)(s_clientobj_set, sizeof(*p)); + VG_(memset)(p, 0, sizeof(*p)); + p->any.a1 = a1; + p->any.type = t; + p->any.first_observed_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); + VG_(OSetGen_Insert)(s_clientobj_set, p); + tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == p); + DRD_(start_suppression)(a1, a1 + 1, "clientobj"); + return p; } /** @@ -153,12 +156,12 @@ DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t) */ Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t) { - DrdClientobj* p; + DrdClientobj* p; - p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr); - tl_assert(p); - tl_assert(p->any.type == t); - return clientobj_remove_obj(p); + p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr); + tl_assert(p); + tl_assert(p->any.type == t); + return clientobj_remove_obj(p); } /** @@ -172,19 +175,19 @@ Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t) */ static Bool clientobj_remove_obj(DrdClientobj* const p) { - tl_assert(p); - - if (s_trace_clientobj) - { - VG_(message)(Vg_UserMsg, "Removing client object 0x%lx of type %d", - p->any.a1, p->any.type); - } - - tl_assert(p->any.cleanup); - (*p->any.cleanup)(p); - VG_(OSetGen_Remove)(s_clientobj_set, &p->any.a1); - VG_(OSetGen_FreeNode)(s_clientobj_set, p); - return True; + tl_assert(p); + + if (s_trace_clientobj) + { + VG_(message)(Vg_UserMsg, "Removing client object 0x%lx of type %d", + p->any.a1, p->any.type); + } + + tl_assert(p->any.cleanup); + (*p->any.cleanup)(p); + VG_(OSetGen_Remove)(s_clientobj_set, &p->any.a1); + VG_(OSetGen_FreeNode)(s_clientobj_set, p); + return True; } /** @@ -196,26 +199,26 @@ static Bool clientobj_remove_obj(DrdClientobj* const p) */ void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2) { - Addr removed_at; - DrdClientobj* p; - - tl_assert(s_clientobj_set); - - if (! DRD_(is_any_suppressed)(a1, a2)) - return; - - VG_(OSetGen_ResetIterAt)(s_clientobj_set, &a1); - for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0 && p->any.a1 < a2; ) - { - tl_assert(a1 <= p->any.a1); - removed_at = p->any.a1; - clientobj_remove_obj(p); - /* - * The above call removes an element from the oset and hence - * invalidates the iterator. Restore the iterator. - */ - VG_(OSetGen_ResetIterAt)(s_clientobj_set, &removed_at); - } + Addr removed_at; + DrdClientobj* p; + + tl_assert(s_clientobj_set); + + if (! DRD_(is_any_suppressed)(a1, a2)) + return; + + VG_(OSetGen_ResetIterAt)(s_clientobj_set, &a1); + for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0 && p->any.a1 < a2; ) + { + tl_assert(a1 <= p->any.a1); + removed_at = p->any.a1; + clientobj_remove_obj(p); + /* + * The above call removes an element from the oset and hence + * invalidates the iterator. Restore the iterator. + */ + VG_(OSetGen_ResetIterAt)(s_clientobj_set, &removed_at); + } } /** @@ -224,27 +227,27 @@ void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2) */ void DRD_(clientobj_delete_thread)(const DrdThreadId tid) { - DrdClientobj *p; - - VG_(OSetGen_ResetIter)(s_clientobj_set); - for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; ) - { - if (p->any.delete_thread) - { - (*p->any.delete_thread)(p, tid); - } - } + DrdClientobj *p; + + VG_(OSetGen_ResetIter)(s_clientobj_set); + for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; ) + { + if (p->any.delete_thread) + { + (*p->any.delete_thread)(p, tid); + } + } } const char* DRD_(clientobj_type_name)(const ObjType t) { - switch (t) - { - case ClientMutex: return "mutex"; - case ClientCondvar: return "cond"; - case ClientSemaphore: return "semaphore"; - case ClientBarrier: return "barrier"; - case ClientRwlock: return "rwlock"; - } - return "(unknown)"; + switch (t) + { + case ClientMutex: return "mutex"; + case ClientCondvar: return "cond"; + case ClientSemaphore: return "semaphore"; + case ClientBarrier: return "barrier"; + case ClientRwlock: return "rwlock"; + } + return "(unknown)"; } diff --git a/drd/drd_clientobj.h b/drd/drd_clientobj.h index c30a17cfbd..f24de5c83c 100644 --- a/drd/drd_clientobj.h +++ b/drd/drd_clientobj.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -42,100 +43,100 @@ union drd_clientobj; /* Type definitions. */ typedef enum { - ClientMutex = 1, - ClientCondvar = 2, - ClientSemaphore = 3, - ClientBarrier = 4, - ClientRwlock = 5, + ClientMutex = 1, + ClientCondvar = 2, + ClientSemaphore = 3, + ClientBarrier = 4, + ClientRwlock = 5, } ObjType; struct any { - Addr a1; - ObjType type; - void (*cleanup)(union drd_clientobj*); - void (*delete_thread)(union drd_clientobj*, DrdThreadId); - ExeContext* first_observed_at; + Addr a1; + ObjType type; + void (*cleanup)(union drd_clientobj*); + void (*delete_thread)(union drd_clientobj*, DrdThreadId); + ExeContext* first_observed_at; }; struct mutex_info { - Addr a1; - ObjType type; - void (*cleanup)(union drd_clientobj*); - void (*delete_thread)(union drd_clientobj*, DrdThreadId); - ExeContext* first_observed_at; - MutexT mutex_type; // pthread_mutex_t or pthread_spinlock_t. - int recursion_count; // 0 if free, >= 1 if locked. - DrdThreadId owner; // owner if locked, last owner if free. - struct segment* last_locked_segment; - ULong acquiry_time_ms; - ExeContext* acquired_at; + Addr a1; + ObjType type; + void (*cleanup)(union drd_clientobj*); + void (*delete_thread)(union drd_clientobj*, DrdThreadId); + ExeContext* first_observed_at; + MutexT mutex_type; // pthread_mutex_t or pthread_spinlock_t. + int recursion_count; // 0 if free, >= 1 if locked. + DrdThreadId owner; // owner if locked, last owner if free. + struct segment* last_locked_segment; + ULong acquiry_time_ms; + ExeContext* acquired_at; }; struct cond_info { - Addr a1; - ObjType type; - void (*cleanup)(union drd_clientobj*); - void (*delete_thread)(union drd_clientobj*, DrdThreadId); - ExeContext* first_observed_at; - int waiter_count; - Addr mutex; // Client mutex specified in pthread_cond_wait() call, and - // null if no client threads are currently waiting on this cond.var. + Addr a1; + ObjType type; + void (*cleanup)(union drd_clientobj*); + void (*delete_thread)(union drd_clientobj*, DrdThreadId); + ExeContext* first_observed_at; + int waiter_count; + Addr mutex; // Client mutex specified in pthread_cond_wait() call, and + // null if no client threads are currently waiting on this cond.var. }; struct semaphore_info { - Addr a1; - ObjType type; - void (*cleanup)(union drd_clientobj*); - void (*delete_thread)(union drd_clientobj*, DrdThreadId); - ExeContext* first_observed_at; - UInt waits_to_skip; // Number of sem_wait() calls to skip - // (due to the value assigned by sem_init()). - UInt value; // Semaphore value. - UWord waiters; // Number of threads inside sem_wait(). - DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post(). - XArray* last_sem_post_seg; // array of Segment*, used as a stack. + Addr a1; + ObjType type; + void (*cleanup)(union drd_clientobj*); + void (*delete_thread)(union drd_clientobj*, DrdThreadId); + ExeContext* first_observed_at; + UInt waits_to_skip; // Number of sem_wait() calls to skip + // (due to the value assigned by sem_init()). + UInt value; // Semaphore value. + UWord waiters; // Number of threads inside sem_wait(). + DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post(). + XArray* last_sem_post_seg; // array of Segment*, used as a stack. }; struct barrier_info { - Addr a1; - ObjType type; - void (*cleanup)(union drd_clientobj*); - void (*delete_thread)(union drd_clientobj*, DrdThreadId); - ExeContext* first_observed_at; - BarrierT barrier_type; // pthread_barrier or gomp_barrier. - Word count; // Participant count in a barrier wait. - Word pre_iteration; // pre barrier completion count modulo two. - Word post_iteration; // post barrier completion count modulo two. - Word pre_waiters_left; // number of waiters left for a complete barrier. - Word post_waiters_left; // number of waiters left for a complete barrier. - OSet* oset; // Per-thread barrier information. + Addr a1; + ObjType type; + void (*cleanup)(union drd_clientobj*); + void (*delete_thread)(union drd_clientobj*, DrdThreadId); + ExeContext* first_observed_at; + BarrierT barrier_type; // pthread_barrier or gomp_barrier. + Word count; // Participant count in a barrier wait. + Word pre_iteration; // pre barrier completion count modulo two. + Word post_iteration; // post barrier completion count modulo two. + Word pre_waiters_left; // number of waiters left for a complete barrier. + Word post_waiters_left; // number of waiters left for a complete barrier. + OSet* oset; // Per-thread barrier information. }; struct rwlock_info { - Addr a1; - ObjType type; - void (*cleanup)(union drd_clientobj*); - void (*delete_thread)(union drd_clientobj*, DrdThreadId); - ExeContext* first_observed_at; - OSet* thread_info; - ULong acquiry_time_ms; - ExeContext* acquired_at; + Addr a1; + ObjType type; + void (*cleanup)(union drd_clientobj*); + void (*delete_thread)(union drd_clientobj*, DrdThreadId); + ExeContext* first_observed_at; + OSet* thread_info; + ULong acquiry_time_ms; + ExeContext* acquired_at; }; typedef union drd_clientobj { - struct any any; - struct mutex_info mutex; - struct cond_info cond; - struct semaphore_info semaphore; - struct barrier_info barrier; - struct rwlock_info rwlock; + struct any any; + struct mutex_info mutex; + struct cond_info cond; + struct semaphore_info semaphore; + struct barrier_info barrier; + struct rwlock_info rwlock; } DrdClientobj; diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c index 57a51393f4..2aceffe289 100644 --- a/drd/drd_clientreq.c +++ b/drd/drd_clientreq.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -56,7 +57,7 @@ static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid); */ void DRD_(clientreq_init)(void) { - VG_(needs_client_requests)(DRD_(handle_client_request)); + VG_(needs_client_requests)(DRD_(handle_client_request)); } /** @@ -66,322 +67,322 @@ void DRD_(clientreq_init)(void) static Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret) { - UWord result = 0; - const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); + UWord result = 0; + const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); - tl_assert(vg_tid == VG_(get_running_tid())); - tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid); + tl_assert(vg_tid == VG_(get_running_tid())); + tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid); - switch (arg[0]) - { - case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID: - result = vg_tid; - break; + switch (arg[0]) + { + case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID: + result = vg_tid; + break; - case VG_USERREQ__DRD_GET_DRD_THREAD_ID: - result = drd_tid; - break; + case VG_USERREQ__DRD_GET_DRD_THREAD_ID: + result = drd_tid; + break; - case VG_USERREQ__DRD_START_SUPPRESSION: - DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client"); - break; + case VG_USERREQ__DRD_START_SUPPRESSION: + DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client"); + break; - case VG_USERREQ__DRD_FINISH_SUPPRESSION: - DRD_(finish_suppression)(arg[1], arg[1] + arg[2]); - break; + case VG_USERREQ__DRD_FINISH_SUPPRESSION: + DRD_(finish_suppression)(arg[1], arg[1] + arg[2]); + break; - case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK: - { - const Addr topmost_sp = DRD_(highest_used_stack_address)(vg_tid); + case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK: + { + const Addr topmost_sp = DRD_(highest_used_stack_address)(vg_tid); #if 0 - UInt nframes; - const UInt n_ips = 20; - Addr ips[n_ips], sps[n_ips], fps[n_ips]; - Char desc[128]; - unsigned i; - - nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, fps, 0); - - VG_(message)(Vg_DebugMsg, "thread %d/%d", vg_tid, drd_tid); - for (i = 0; i < nframes; i++) - { - VG_(describe_IP)(ips[i], desc, sizeof(desc)); - VG_(message)(Vg_DebugMsg, "[%2d] sp 0x%09lx fp 0x%09lx ip %s", - i, sps[i], fps[i], desc); - } + UInt nframes; + const UInt n_ips = 20; + Addr ips[n_ips], sps[n_ips], fps[n_ips]; + Char desc[128]; + unsigned i; + + nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, fps, 0); + + VG_(message)(Vg_DebugMsg, "thread %d/%d", vg_tid, drd_tid); + for (i = 0; i < nframes; i++) + { + VG_(describe_IP)(ips[i], desc, sizeof(desc)); + VG_(message)(Vg_DebugMsg, "[%2d] sp 0x%09lx fp 0x%09lx ip %s", + i, sps[i], fps[i], desc); + } #endif - 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"); - break; - } - - case VG_USERREQ__DRD_START_NEW_SEGMENT: - DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1])); - break; - - case VG_USERREQ__DRD_START_TRACE_ADDR: - DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2]); - break; - - case VG_USERREQ__DRD_STOP_TRACE_ADDR: - DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]); - break; - - case VG_USERREQ__DRD_STOP_RECORDING: - DRD_(thread_stop_recording)(drd_tid); - break; - - case VG_USERREQ__DRD_START_RECORDING: - DRD_(thread_start_recording)(drd_tid); - break; - - case VG_USERREQ__SET_PTHREADID: - // pthread_self() returns 0 for programs not linked with libpthread.so. - if (arg[1] != INVALID_POSIX_THREADID) - DRD_(thread_set_pthreadid)(drd_tid, arg[1]); - break; - - case VG_USERREQ__SET_JOINABLE: - DRD_(thread_set_joinable)(DRD_(PtThreadIdToDrdThreadId)(arg[1]), - (Bool)arg[2]); - break; - - case VG_USERREQ__POST_THREAD_JOIN: - tl_assert(arg[1]); - DRD_(thread_post_join)(drd_tid, DRD_(PtThreadIdToDrdThreadId)(arg[1])); - break; - - case VG_USERREQ__PRE_THREAD_CANCEL: - tl_assert(arg[1]); - DRD_(thread_pre_cancel)(drd_tid); - break; - - case VG_USERREQ__POST_THREAD_CANCEL: - tl_assert(arg[1]); - break; - - case VG_USERREQ__PRE_MUTEX_INIT: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(mutex_init)(arg[1], arg[2]); - break; - - case VG_USERREQ__POST_MUTEX_INIT: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_MUTEX_DESTROY: - DRD_(thread_enter_synchr)(drd_tid); - break; - - case VG_USERREQ__POST_MUTEX_DESTROY: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(mutex_post_destroy)(arg[1]); - break; - - case VG_USERREQ__PRE_MUTEX_LOCK: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]); - break; - - case VG_USERREQ__POST_MUTEX_LOCK: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/); - break; - - case VG_USERREQ__PRE_MUTEX_UNLOCK: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(mutex_unlock)(arg[1], arg[2]); - break; - - case VG_USERREQ__POST_MUTEX_UNLOCK: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(spinlock_init_or_unlock)(arg[1]); - break; - - case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_COND_INIT: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(cond_pre_init)(arg[1]); - break; - - case VG_USERREQ__POST_COND_INIT: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_COND_DESTROY: - DRD_(thread_enter_synchr)(drd_tid); - break; - - case VG_USERREQ__POST_COND_DESTROY: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(cond_post_destroy)(arg[1]); - break; - - case VG_USERREQ__PRE_COND_WAIT: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - { - const Addr cond = arg[1]; - const Addr mutex = arg[2]; - const MutexT mutex_type = arg[3]; - DRD_(mutex_unlock)(mutex, mutex_type); - DRD_(cond_pre_wait)(cond, mutex); - } - break; - - case VG_USERREQ__POST_COND_WAIT: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - { - const Addr cond = arg[1]; - const Addr mutex = arg[2]; - const Bool took_lock = arg[3]; - DRD_(cond_post_wait)(cond); - DRD_(mutex_post_lock)(mutex, took_lock, True); - } - break; - - case VG_USERREQ__PRE_COND_SIGNAL: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(cond_pre_signal)(arg[1]); - break; - - case VG_USERREQ__POST_COND_SIGNAL: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_COND_BROADCAST: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(cond_pre_broadcast)(arg[1]); - break; - - case VG_USERREQ__POST_COND_BROADCAST: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_SEM_INIT: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(semaphore_init)(arg[1], arg[2], arg[3]); - break; - - case VG_USERREQ__POST_SEM_INIT: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_SEM_DESTROY: - DRD_(thread_enter_synchr)(drd_tid); - break; - - case VG_USERREQ__POST_SEM_DESTROY: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(semaphore_destroy)(arg[1]); - break; - - case VG_USERREQ__PRE_SEM_WAIT: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(semaphore_pre_wait)(arg[1]); - break; - - case VG_USERREQ__POST_SEM_WAIT: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]); - break; - - case VG_USERREQ__PRE_SEM_POST: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(semaphore_pre_post)(drd_tid, arg[1]); - break; - - case VG_USERREQ__POST_SEM_POST: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]); - break; - - case VG_USERREQ__PRE_BARRIER_INIT: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]); - break; - - case VG_USERREQ__POST_BARRIER_INIT: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__PRE_BARRIER_DESTROY: - DRD_(thread_enter_synchr)(drd_tid); - break; - - case VG_USERREQ__POST_BARRIER_DESTROY: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(barrier_destroy)(arg[1], arg[2]); - break; - - case VG_USERREQ__PRE_BARRIER_WAIT: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]); - break; - - case VG_USERREQ__POST_BARRIER_WAIT: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]); - break; - - case VG_USERREQ__PRE_RWLOCK_INIT: - DRD_(rwlock_pre_init)(arg[1]); - break; - - case VG_USERREQ__POST_RWLOCK_DESTROY: - DRD_(rwlock_post_destroy)(arg[1]); - break; - - case VG_USERREQ__PRE_RWLOCK_RDLOCK: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(rwlock_pre_rdlock)(arg[1]); - break; - - case VG_USERREQ__POST_RWLOCK_RDLOCK: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(rwlock_post_rdlock)(arg[1], arg[2]); - break; - - case VG_USERREQ__PRE_RWLOCK_WRLOCK: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(rwlock_pre_wrlock)(arg[1]); - break; - - case VG_USERREQ__POST_RWLOCK_WRLOCK: - if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(rwlock_post_wrlock)(arg[1], arg[2]); - break; - - case VG_USERREQ__PRE_RWLOCK_UNLOCK: - if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(rwlock_pre_unlock)(arg[1]); - break; + 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"); + break; + } + + case VG_USERREQ__DRD_START_NEW_SEGMENT: + DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1])); + break; + + case VG_USERREQ__DRD_START_TRACE_ADDR: + DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2]); + break; + + case VG_USERREQ__DRD_STOP_TRACE_ADDR: + DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]); + break; + + case VG_USERREQ__DRD_STOP_RECORDING: + DRD_(thread_stop_recording)(drd_tid); + break; + + case VG_USERREQ__DRD_START_RECORDING: + DRD_(thread_start_recording)(drd_tid); + break; + + case VG_USERREQ__SET_PTHREADID: + // pthread_self() returns 0 for programs not linked with libpthread.so. + if (arg[1] != INVALID_POSIX_THREADID) + DRD_(thread_set_pthreadid)(drd_tid, arg[1]); + break; + + case VG_USERREQ__SET_JOINABLE: + DRD_(thread_set_joinable)(DRD_(PtThreadIdToDrdThreadId)(arg[1]), + (Bool)arg[2]); + break; + + case VG_USERREQ__POST_THREAD_JOIN: + tl_assert(arg[1]); + DRD_(thread_post_join)(drd_tid, DRD_(PtThreadIdToDrdThreadId)(arg[1])); + break; + + case VG_USERREQ__PRE_THREAD_CANCEL: + tl_assert(arg[1]); + DRD_(thread_pre_cancel)(drd_tid); + break; + + case VG_USERREQ__POST_THREAD_CANCEL: + tl_assert(arg[1]); + break; + + case VG_USERREQ__PRE_MUTEX_INIT: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(mutex_init)(arg[1], arg[2]); + break; + + case VG_USERREQ__POST_MUTEX_INIT: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_MUTEX_DESTROY: + DRD_(thread_enter_synchr)(drd_tid); + break; + + case VG_USERREQ__POST_MUTEX_DESTROY: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(mutex_post_destroy)(arg[1]); + break; + + case VG_USERREQ__PRE_MUTEX_LOCK: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]); + break; + + case VG_USERREQ__POST_MUTEX_LOCK: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/); + break; + + case VG_USERREQ__PRE_MUTEX_UNLOCK: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(mutex_unlock)(arg[1], arg[2]); + break; + + case VG_USERREQ__POST_MUTEX_UNLOCK: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(spinlock_init_or_unlock)(arg[1]); + break; + + case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_COND_INIT: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(cond_pre_init)(arg[1]); + break; + + case VG_USERREQ__POST_COND_INIT: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_COND_DESTROY: + DRD_(thread_enter_synchr)(drd_tid); + break; + + case VG_USERREQ__POST_COND_DESTROY: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(cond_post_destroy)(arg[1]); + break; + + case VG_USERREQ__PRE_COND_WAIT: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + { + const Addr cond = arg[1]; + const Addr mutex = arg[2]; + const MutexT mutex_type = arg[3]; + DRD_(mutex_unlock)(mutex, mutex_type); + DRD_(cond_pre_wait)(cond, mutex); + } + break; + + case VG_USERREQ__POST_COND_WAIT: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + { + const Addr cond = arg[1]; + const Addr mutex = arg[2]; + const Bool took_lock = arg[3]; + DRD_(cond_post_wait)(cond); + DRD_(mutex_post_lock)(mutex, took_lock, True); + } + break; + + case VG_USERREQ__PRE_COND_SIGNAL: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(cond_pre_signal)(arg[1]); + break; + + case VG_USERREQ__POST_COND_SIGNAL: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_COND_BROADCAST: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(cond_pre_broadcast)(arg[1]); + break; + + case VG_USERREQ__POST_COND_BROADCAST: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_SEM_INIT: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(semaphore_init)(arg[1], arg[2], arg[3]); + break; + + case VG_USERREQ__POST_SEM_INIT: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_SEM_DESTROY: + DRD_(thread_enter_synchr)(drd_tid); + break; + + case VG_USERREQ__POST_SEM_DESTROY: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(semaphore_destroy)(arg[1]); + break; + + case VG_USERREQ__PRE_SEM_WAIT: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(semaphore_pre_wait)(arg[1]); + break; + + case VG_USERREQ__POST_SEM_WAIT: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_SEM_POST: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(semaphore_pre_post)(drd_tid, arg[1]); + break; + + case VG_USERREQ__POST_SEM_POST: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_BARRIER_INIT: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]); + break; + + case VG_USERREQ__POST_BARRIER_INIT: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__PRE_BARRIER_DESTROY: + DRD_(thread_enter_synchr)(drd_tid); + break; + + case VG_USERREQ__POST_BARRIER_DESTROY: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(barrier_destroy)(arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_BARRIER_WAIT: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]); + break; + + case VG_USERREQ__POST_BARRIER_WAIT: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]); + break; + + case VG_USERREQ__PRE_RWLOCK_INIT: + DRD_(rwlock_pre_init)(arg[1]); + break; + + case VG_USERREQ__POST_RWLOCK_DESTROY: + DRD_(rwlock_post_destroy)(arg[1]); + break; + + case VG_USERREQ__PRE_RWLOCK_RDLOCK: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(rwlock_pre_rdlock)(arg[1]); + break; + + case VG_USERREQ__POST_RWLOCK_RDLOCK: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(rwlock_post_rdlock)(arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_RWLOCK_WRLOCK: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(rwlock_pre_wrlock)(arg[1]); + break; + + case VG_USERREQ__POST_RWLOCK_WRLOCK: + if (DRD_(thread_leave_synchr)(drd_tid) == 0) + DRD_(rwlock_post_wrlock)(arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_RWLOCK_UNLOCK: + if (DRD_(thread_enter_synchr)(drd_tid) == 0) + DRD_(rwlock_pre_unlock)(arg[1]); + break; - case VG_USERREQ__POST_RWLOCK_UNLOCK: - DRD_(thread_leave_synchr)(drd_tid); - break; - - case VG_USERREQ__DRD_CLEAN_MEMORY: - if (arg[2] > 0) - DRD_(clean_memory)(arg[1], arg[2]); - break; - - default: - VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx", - arg[0], arg[1]); - tl_assert(0); - return False; - } - - *ret = result; - return True; + case VG_USERREQ__POST_RWLOCK_UNLOCK: + DRD_(thread_leave_synchr)(drd_tid); + break; + + case VG_USERREQ__DRD_CLEAN_MEMORY: + if (arg[2] > 0) + DRD_(clean_memory)(arg[1], arg[2]); + break; + + default: + VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx", + arg[0], arg[1]); + tl_assert(0); + return False; + } + + *ret = result; + return True; } /** @@ -394,36 +395,36 @@ Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret) */ static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid) { - UInt nframes; - const UInt n_ips = 10; - UInt i; - Addr ips[n_ips], sps[n_ips]; - Addr husa; + UInt nframes; + const UInt n_ips = 10; + UInt i; + Addr ips[n_ips], sps[n_ips]; + Addr husa; - nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, 0, 0); - tl_assert(1 <= nframes && nframes <= n_ips); + nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, 0, 0); + tl_assert(1 <= nframes && nframes <= n_ips); - /* A hack to work around VG_(get_StackTrace)()'s behavior that sometimes */ - /* the topmost stackframes it returns are bogus (this occurs sometimes */ - /* at least on amd64, ppc32 and ppc64). */ + /* A hack to work around VG_(get_StackTrace)()'s behavior that sometimes */ + /* the topmost stackframes it returns are bogus (this occurs sometimes */ + /* at least on amd64, ppc32 and ppc64). */ - husa = sps[0]; + husa = sps[0]; - tl_assert(VG_(thread_get_stack_max)(vg_tid) - - VG_(thread_get_stack_size)(vg_tid) <= husa - && husa < VG_(thread_get_stack_max)(vg_tid)); + tl_assert(VG_(thread_get_stack_max)(vg_tid) + - VG_(thread_get_stack_size)(vg_tid) <= husa + && husa < VG_(thread_get_stack_max)(vg_tid)); - for (i = 1; i < nframes; i++) - { + for (i = 1; i < nframes; i++) + { if (sps[i] == 0) - break; + break; if (husa < sps[i] && sps[i] < VG_(thread_get_stack_max)(vg_tid)) - husa = sps[i]; - } + husa = sps[i]; + } - tl_assert(VG_(thread_get_stack_max)(vg_tid) - - VG_(thread_get_stack_size)(vg_tid) <= husa - && husa < VG_(thread_get_stack_max)(vg_tid)); + tl_assert(VG_(thread_get_stack_max)(vg_tid) + - VG_(thread_get_stack_size)(vg_tid) <= husa + && husa < VG_(thread_get_stack_max)(vg_tid)); - return husa; + return husa; } diff --git a/drd/drd_clientreq.h b/drd/drd_clientreq.h index a011cceab4..40cf225058 100644 --- a/drd/drd_clientreq.h +++ b/drd/drd_clientreq.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -44,166 +45,166 @@ * source files. */ enum { - /* Ask drd to suppress data race reports on all currently allocated stack */ - /* data of the current thread. */ - VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK = VG_USERREQ_TOOL_BASE('D', 'r'), - /* args: none */ - /* To ask the drd tool to start a new segment in the specified thread. */ - VG_USERREQ__DRD_START_NEW_SEGMENT, - /* args: POSIX thread ID. */ - /* Let the drd tool stop recording memory accesses in the calling thread. */ - VG_USERREQ__DRD_STOP_RECORDING, - /* args: none. */ - /* Let the drd tool start recording memory accesses in the calling thread. */ - VG_USERREQ__DRD_START_RECORDING, - /* args: none. */ - - /* Tell drd the pthread_t of the running thread. */ - VG_USERREQ__SET_PTHREADID, - /* args: pthread_t. */ - /* Ask drd that a the thread's state transition from */ - /* VgTs_Zombie to VgTs_Empty is delayed until */ - /* VG_USERREQ__POST_THREAD_JOIN is performed. */ - VG_USERREQ__SET_JOINABLE, - /* args: pthread_t, Bool */ - - /* To notify drd that a thread finished because */ - /* pthread_thread_join() was called on it. */ - VG_USERREQ__POST_THREAD_JOIN, - /* args: pthread_t (joinee) */ - - /* To notify drd before a pthread_cancel call. */ - VG_USERREQ__PRE_THREAD_CANCEL, - /* args: pthread_t */ - /* To notify drd after a pthread_cancel call. */ - VG_USERREQ__POST_THREAD_CANCEL, - /* args: pthread_t, Bool */ - - /* to notify the drd tool of a pthread_mutex_init call. */ - VG_USERREQ__PRE_MUTEX_INIT, - /* args: Addr, MutexT */ - /* to notify the drd tool of a pthread_mutex_init call. */ - VG_USERREQ__POST_MUTEX_INIT, - /* args: Addr */ - /* to notify the drd tool of a pthread_mutex_destroy call. */ - VG_USERREQ__PRE_MUTEX_DESTROY, - /* args: Addr */ - /* to notify the drd tool of a pthread_mutex_destroy call. */ - VG_USERREQ__POST_MUTEX_DESTROY, - /* args: Addr, MutexT */ - /* to notify the drd tool of pthread_mutex_lock calls */ - VG_USERREQ__PRE_MUTEX_LOCK, - /* args: Addr, MutexT, Bool */ - /* to notify the drd tool of pthread_mutex_lock calls */ - VG_USERREQ__POST_MUTEX_LOCK, - /* args: Addr, Bool */ - /* to notify the drd tool of pthread_mutex_unlock calls */ - VG_USERREQ__PRE_MUTEX_UNLOCK, - /* args: Addr */ - /* to notify the drd tool of pthread_mutex_unlock calls */ - VG_USERREQ__POST_MUTEX_UNLOCK, - /* args: Addr */ - /* to notify the drd tool of a pthread_spin_init/pthread_spin_unlock call */ - VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, - /* args: Addr */ - /* to notify the drd tool of a pthread_spin_init/pthread_spin_unlock call */ - VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, - /* args: Addr */ - - - /* 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 */ - 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, - /* args: Addr sem, Word pshared, Word value */ - /* To notify the drd tool of a sem_init call. */ - VG_USERREQ__POST_SEM_INIT, - /* args: Addr sem */ - /* To notify the drd tool of a sem_destroy call. */ - VG_USERREQ__PRE_SEM_DESTROY, - /* args: Addr sem */ - /* To notify the drd tool of a sem_destroy call. */ - VG_USERREQ__POST_SEM_DESTROY, - /* args: Addr sem */ - /* To notify the drd tool of a sem_wait call. */ - VG_USERREQ__PRE_SEM_WAIT, - /* args: Addr sem */ - /* To notify the drd tool of a sem_wait call. */ - VG_USERREQ__POST_SEM_WAIT, - /* args: Addr sem, Bool waited */ - /* To notify the drd tool before a sem_post call. */ - VG_USERREQ__PRE_SEM_POST, - /* args: Addr sem */ - /* To notify the drd tool after a sem_post call. */ - VG_USERREQ__POST_SEM_POST, - /* args: Addr sem, Bool waited */ - - /* To notify the drd tool of a pthread_barrier_init call. */ - VG_USERREQ__PRE_BARRIER_INIT, - /* args: Addr barrier, BarrierT type, Word count, Bool reinit */ - /* To notify the drd tool of a pthread_barrier_init call. */ - VG_USERREQ__POST_BARRIER_INIT, - /* args: Addr barrier, BarrierT type */ - /* To notify the drd tool of a pthread_barrier_destroy call. */ - VG_USERREQ__PRE_BARRIER_DESTROY, - /* args: Addr barrier, BarrierT type. */ - /* To notify the drd tool of a pthread_barrier_destroy call. */ - VG_USERREQ__POST_BARRIER_DESTROY, - /* args: Addr barrier, BarrierT type. */ - /* To notify the drd tool of a pthread_barrier_wait call. */ - VG_USERREQ__PRE_BARRIER_WAIT, - /* args: Addr barrier, BarrierT type. */ - /* To notify the drd tool of a pthread_barrier_wait call. */ - VG_USERREQ__POST_BARRIER_WAIT, - /* args: Addr barrier, BarrierT type, Word has_waited, Word serializing */ - - /* To notify the drd tool of a pthread_rwlock_init call. */ - VG_USERREQ__PRE_RWLOCK_INIT, - /* args: Addr rwlock */ - /* To notify the drd tool of a pthread_rwlock_destroy call. */ - VG_USERREQ__POST_RWLOCK_DESTROY, - /* args: Addr rwlock */ - /* To notify the drd tool of a pthread_rwlock_rdlock call. */ - VG_USERREQ__PRE_RWLOCK_RDLOCK, - /* args: Addr rwlock */ - /* To notify the drd tool of a pthread_rwlock_rdlock call. */ - VG_USERREQ__POST_RWLOCK_RDLOCK, - /* args: Addr rwlock, Bool took_lock */ - /* To notify the drd tool of a pthread_rwlock_wrlock call. */ - VG_USERREQ__PRE_RWLOCK_WRLOCK, - /* args: Addr rwlock */ - /* To notify the drd tool of a pthread_rwlock_wrlock call. */ - VG_USERREQ__POST_RWLOCK_WRLOCK, - /* args: Addr rwlock, Bool took_lock */ - /* To notify the drd tool of a pthread_rwlock_unlock call. */ - VG_USERREQ__PRE_RWLOCK_UNLOCK, - /* args: Addr rwlock */ - /* To notify the drd tool of a pthread_rwlock_unlock call. */ - VG_USERREQ__POST_RWLOCK_UNLOCK - /* args: Addr rwlock, Bool unlocked */ + /* Ask drd to suppress data race reports on all currently allocated stack */ + /* data of the current thread. */ + VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK = VG_USERREQ_TOOL_BASE('D', 'r'), + /* args: none */ + /* To ask the drd tool to start a new segment in the specified thread. */ + VG_USERREQ__DRD_START_NEW_SEGMENT, + /* args: POSIX thread ID. */ + /* Let the drd tool stop recording memory accesses in the calling thread. */ + VG_USERREQ__DRD_STOP_RECORDING, + /* args: none. */ + /* Let the drd tool start recording memory accesses in the calling thread. */ + VG_USERREQ__DRD_START_RECORDING, + /* args: none. */ + + /* Tell drd the pthread_t of the running thread. */ + VG_USERREQ__SET_PTHREADID, + /* args: pthread_t. */ + /* Ask drd that a the thread's state transition from */ + /* VgTs_Zombie to VgTs_Empty is delayed until */ + /* VG_USERREQ__POST_THREAD_JOIN is performed. */ + VG_USERREQ__SET_JOINABLE, + /* args: pthread_t, Bool */ + + /* To notify drd that a thread finished because */ + /* pthread_thread_join() was called on it. */ + VG_USERREQ__POST_THREAD_JOIN, + /* args: pthread_t (joinee) */ + + /* To notify drd before a pthread_cancel call. */ + VG_USERREQ__PRE_THREAD_CANCEL, + /* args: pthread_t */ + /* To notify drd after a pthread_cancel call. */ + VG_USERREQ__POST_THREAD_CANCEL, + /* args: pthread_t, Bool */ + + /* to notify the drd tool of a pthread_mutex_init call. */ + VG_USERREQ__PRE_MUTEX_INIT, + /* args: Addr, MutexT */ + /* to notify the drd tool of a pthread_mutex_init call. */ + VG_USERREQ__POST_MUTEX_INIT, + /* args: Addr */ + /* to notify the drd tool of a pthread_mutex_destroy call. */ + VG_USERREQ__PRE_MUTEX_DESTROY, + /* args: Addr */ + /* to notify the drd tool of a pthread_mutex_destroy call. */ + VG_USERREQ__POST_MUTEX_DESTROY, + /* args: Addr, MutexT */ + /* to notify the drd tool of pthread_mutex_lock calls */ + VG_USERREQ__PRE_MUTEX_LOCK, + /* args: Addr, MutexT, Bool */ + /* to notify the drd tool of pthread_mutex_lock calls */ + VG_USERREQ__POST_MUTEX_LOCK, + /* args: Addr, Bool */ + /* to notify the drd tool of pthread_mutex_unlock calls */ + VG_USERREQ__PRE_MUTEX_UNLOCK, + /* args: Addr */ + /* to notify the drd tool of pthread_mutex_unlock calls */ + VG_USERREQ__POST_MUTEX_UNLOCK, + /* args: Addr */ + /* to notify the drd tool of a pthread_spin_init/pthread_spin_unlock call */ + VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, + /* args: Addr */ + /* to notify the drd tool of a pthread_spin_init/pthread_spin_unlock call */ + VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, + /* args: Addr */ + + + /* 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 */ + 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, + /* args: Addr sem, Word pshared, Word value */ + /* To notify the drd tool of a sem_init call. */ + VG_USERREQ__POST_SEM_INIT, + /* args: Addr sem */ + /* To notify the drd tool of a sem_destroy call. */ + VG_USERREQ__PRE_SEM_DESTROY, + /* args: Addr sem */ + /* To notify the drd tool of a sem_destroy call. */ + VG_USERREQ__POST_SEM_DESTROY, + /* args: Addr sem */ + /* To notify the drd tool of a sem_wait call. */ + VG_USERREQ__PRE_SEM_WAIT, + /* args: Addr sem */ + /* To notify the drd tool of a sem_wait call. */ + VG_USERREQ__POST_SEM_WAIT, + /* args: Addr sem, Bool waited */ + /* To notify the drd tool before a sem_post call. */ + VG_USERREQ__PRE_SEM_POST, + /* args: Addr sem */ + /* To notify the drd tool after a sem_post call. */ + VG_USERREQ__POST_SEM_POST, + /* args: Addr sem, Bool waited */ + + /* To notify the drd tool of a pthread_barrier_init call. */ + VG_USERREQ__PRE_BARRIER_INIT, + /* args: Addr barrier, BarrierT type, Word count, Bool reinit */ + /* To notify the drd tool of a pthread_barrier_init call. */ + VG_USERREQ__POST_BARRIER_INIT, + /* args: Addr barrier, BarrierT type */ + /* To notify the drd tool of a pthread_barrier_destroy call. */ + VG_USERREQ__PRE_BARRIER_DESTROY, + /* args: Addr barrier, BarrierT type. */ + /* To notify the drd tool of a pthread_barrier_destroy call. */ + VG_USERREQ__POST_BARRIER_DESTROY, + /* args: Addr barrier, BarrierT type. */ + /* To notify the drd tool of a pthread_barrier_wait call. */ + VG_USERREQ__PRE_BARRIER_WAIT, + /* args: Addr barrier, BarrierT type. */ + /* To notify the drd tool of a pthread_barrier_wait call. */ + VG_USERREQ__POST_BARRIER_WAIT, + /* args: Addr barrier, BarrierT type, Word has_waited, Word serializing */ + + /* To notify the drd tool of a pthread_rwlock_init call. */ + VG_USERREQ__PRE_RWLOCK_INIT, + /* args: Addr rwlock */ + /* To notify the drd tool of a pthread_rwlock_destroy call. */ + VG_USERREQ__POST_RWLOCK_DESTROY, + /* args: Addr rwlock */ + /* To notify the drd tool of a pthread_rwlock_rdlock call. */ + VG_USERREQ__PRE_RWLOCK_RDLOCK, + /* args: Addr rwlock */ + /* To notify the drd tool of a pthread_rwlock_rdlock call. */ + VG_USERREQ__POST_RWLOCK_RDLOCK, + /* args: Addr rwlock, Bool took_lock */ + /* To notify the drd tool of a pthread_rwlock_wrlock call. */ + VG_USERREQ__PRE_RWLOCK_WRLOCK, + /* args: Addr rwlock */ + /* To notify the drd tool of a pthread_rwlock_wrlock call. */ + VG_USERREQ__POST_RWLOCK_WRLOCK, + /* args: Addr rwlock, Bool took_lock */ + /* To notify the drd tool of a pthread_rwlock_unlock call. */ + VG_USERREQ__PRE_RWLOCK_UNLOCK, + /* args: Addr rwlock */ + /* To notify the drd tool of a pthread_rwlock_unlock call. */ + VG_USERREQ__POST_RWLOCK_UNLOCK + /* args: Addr rwlock, Bool unlocked */ }; @@ -213,14 +214,14 @@ enum { * values defined below specify which of these types a mutex really is. */ typedef enum -{ - 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; + { + 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; /* * Error checking on POSIX barriers and GOMP barriers happens by the same @@ -228,10 +229,10 @@ typedef enum * a given client address. */ typedef enum - { - pthread_barrier = 1, - gomp_barrier = 2 - } BarrierT; + { + pthread_barrier = 1, + gomp_barrier = 2 + } BarrierT; void DRD_(clientreq_init)(void); diff --git a/drd/drd_cond.c b/drd/drd_cond.c index afee3115c4..a698e1cebc 100644 --- a/drd/drd_cond.c +++ b/drd/drd_cond.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -50,25 +51,25 @@ static Bool DRD_(s_trace_cond); void DRD_(cond_set_report_signal_unlocked)(const Bool r) { - DRD_(s_report_signal_unlocked) = r; + DRD_(s_report_signal_unlocked) = r; } void DRD_(cond_set_trace)(const Bool trace_cond) { - DRD_(s_trace_cond) = trace_cond; + DRD_(s_trace_cond) = trace_cond; } static void DRD_(cond_initialize)(struct cond_info* const p, const Addr cond) { - tl_assert(cond != 0); - tl_assert(p->a1 == cond); - tl_assert(p->type == ClientCondvar); - - p->cleanup = (void(*)(DrdClientobj*))(DRD_(cond_cleanup)); - p->delete_thread = 0; - p->waiter_count = 0; - p->mutex = 0; + tl_assert(cond != 0); + tl_assert(p->a1 == cond); + tl_assert(p->type == ClientCondvar); + + p->cleanup = (void(*)(DrdClientobj*))(DRD_(cond_cleanup)); + p->delete_thread = 0; + p->waiter_count = 0; + p->mutex = 0; } /** @@ -77,111 +78,111 @@ void DRD_(cond_initialize)(struct cond_info* const p, const Addr cond) */ static void DRD_(cond_cleanup)(struct cond_info* p) { - tl_assert(p); - if (p->mutex) - { - struct mutex_info* q; - q = &(DRD_(clientobj_get)(p->mutex, ClientMutex)->mutex); - tl_assert(q); - { - CondDestrErrInfo cde = { p->a1, q->a1, q->owner }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - CondDestrErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Destroying condition variable that is being" - " waited upon", - &cde); - } - } + tl_assert(p); + if (p->mutex) + { + struct mutex_info* q; + q = &(DRD_(clientobj_get)(p->mutex, ClientMutex)->mutex); + tl_assert(q); + { + CondDestrErrInfo cde = { p->a1, q->a1, q->owner }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + CondDestrErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Destroying condition variable that is being" + " waited upon", + &cde); + } + } } static struct cond_info* DRD_(cond_get_or_allocate)(const Addr cond) { - struct cond_info *p; - - tl_assert(offsetof(DrdClientobj, cond) == 0); - p = &(DRD_(clientobj_get)(cond, ClientCondvar)->cond); - if (p == 0) - { - p = &(DRD_(clientobj_add)(cond, ClientCondvar)->cond); - DRD_(cond_initialize)(p, cond); - } - return p; + struct cond_info *p; + + tl_assert(offsetof(DrdClientobj, cond) == 0); + p = &(DRD_(clientobj_get)(cond, ClientCondvar)->cond); + if (p == 0) + { + p = &(DRD_(clientobj_add)(cond, ClientCondvar)->cond); + DRD_(cond_initialize)(p, cond); + } + return p; } static struct cond_info* DRD_(cond_get)(const Addr cond) { - tl_assert(offsetof(DrdClientobj, cond) == 0); - return &(DRD_(clientobj_get)(cond, ClientCondvar)->cond); + tl_assert(offsetof(DrdClientobj, cond) == 0); + return &(DRD_(clientobj_get)(cond, ClientCondvar)->cond); } /** Called before pthread_cond_init(). */ void DRD_(cond_pre_init)(const Addr cond) { - struct cond_info* p; - - if (DRD_(s_trace_cond)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] cond_init cond 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - cond); - } - - p = DRD_(cond_get)(cond); - - if (p) - { - CondErrInfo cei = { .cond = cond }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - CondErr, - VG_(get_IP)(VG_(get_running_tid)()), - "initialized twice", - &cei); - } - - p = DRD_(cond_get_or_allocate)(cond); + struct cond_info* p; + + if (DRD_(s_trace_cond)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] cond_init cond 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + cond); + } + + p = DRD_(cond_get)(cond); + + if (p) + { + CondErrInfo cei = { .cond = cond }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + CondErr, + VG_(get_IP)(VG_(get_running_tid)()), + "initialized twice", + &cei); + } + + p = DRD_(cond_get_or_allocate)(cond); } /** Called after pthread_cond_destroy(). */ void DRD_(cond_post_destroy)(const Addr cond) { - struct cond_info* p; - - if (DRD_(s_trace_cond)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] cond_destroy cond 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - cond); - } - - p = DRD_(cond_get)(cond); - if (p == 0) - { - CondErrInfo cei = { .cond = cond }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - CondErr, - VG_(get_IP)(VG_(get_running_tid)()), - "not a condition variable", - &cei); - return; - } - - if (p->waiter_count != 0) - { - CondErrInfo cei = { .cond = cond }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - CondErr, - VG_(get_IP)(VG_(get_running_tid)()), - "destruction of condition variable being waited" - " upon", - &cei); - } - - DRD_(clientobj_remove)(p->a1, ClientCondvar); + struct cond_info* p; + + if (DRD_(s_trace_cond)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] cond_destroy cond 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + cond); + } + + p = DRD_(cond_get)(cond); + if (p == 0) + { + CondErrInfo cei = { .cond = cond }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + CondErr, + VG_(get_IP)(VG_(get_running_tid)()), + "not a condition variable", + &cei); + return; + } + + if (p->waiter_count != 0) + { + CondErrInfo cei = { .cond = cond }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + CondErr, + VG_(get_IP)(VG_(get_running_tid)()), + "destruction of condition variable being waited" + " upon", + &cei); + } + + DRD_(clientobj_remove)(p->a1, ClientCondvar); } /** Called before pthread_cond_wait(). Note: before this function is called, @@ -189,143 +190,143 @@ void DRD_(cond_post_destroy)(const Addr cond) */ int DRD_(cond_pre_wait)(const Addr cond, const Addr mutex) { - struct cond_info* p; - struct mutex_info* q; - - if (DRD_(s_trace_cond)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] cond_pre_wait cond 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - cond); - } - - p = DRD_(cond_get_or_allocate)(cond); - tl_assert(p); - - if (p->waiter_count == 0) - { - p->mutex = mutex; - } - else if (p->mutex != mutex) - { - CondWaitErrInfo cwei - = { .cond = cond, .mutex1 = p->mutex, .mutex2 = mutex }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - CondWaitErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Inconsistent association of condition variable" - " and mutex", - &cwei); - } - tl_assert(p->mutex); - q = DRD_(mutex_get)(p->mutex); - if (q - && q->owner == DRD_(thread_get_running_tid)() && q->recursion_count > 0) - { - const ThreadId vg_tid = VG_(get_running_tid)(); - MutexErrInfo MEI = { q->a1, q->recursion_count, q->owner }; - VG_(maybe_record_error)(vg_tid, - MutexErr, - VG_(get_IP)(vg_tid), - "Mutex locked recursively", - &MEI); - } - else if (q == 0) - { - DRD_(not_a_mutex)(p->mutex); - } - - return ++p->waiter_count; + struct cond_info* p; + struct mutex_info* q; + + if (DRD_(s_trace_cond)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] cond_pre_wait cond 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + cond); + } + + p = DRD_(cond_get_or_allocate)(cond); + tl_assert(p); + + if (p->waiter_count == 0) + { + p->mutex = mutex; + } + else if (p->mutex != mutex) + { + CondWaitErrInfo cwei + = { .cond = cond, .mutex1 = p->mutex, .mutex2 = mutex }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + CondWaitErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Inconsistent association of condition variable" + " and mutex", + &cwei); + } + tl_assert(p->mutex); + q = DRD_(mutex_get)(p->mutex); + if (q + && q->owner == DRD_(thread_get_running_tid)() && q->recursion_count > 0) + { + const ThreadId vg_tid = VG_(get_running_tid)(); + MutexErrInfo MEI = { q->a1, q->recursion_count, q->owner }; + VG_(maybe_record_error)(vg_tid, + MutexErr, + VG_(get_IP)(vg_tid), + "Mutex locked recursively", + &MEI); + } + else if (q == 0) + { + DRD_(not_a_mutex)(p->mutex); + } + + return ++p->waiter_count; } /** Called after pthread_cond_wait(). */ int DRD_(cond_post_wait)(const Addr cond) { - struct cond_info* p; - - if (DRD_(s_trace_cond)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] cond_post_wait cond 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - cond); - } - - p = DRD_(cond_get)(cond); - if (p) - { - if (p->waiter_count > 0) - { - --p->waiter_count; - if (p->waiter_count == 0) + struct cond_info* p; + + if (DRD_(s_trace_cond)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] cond_post_wait cond 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + cond); + } + + p = DRD_(cond_get)(cond); + if (p) + { + if (p->waiter_count > 0) { - p->mutex = 0; + --p->waiter_count; + if (p->waiter_count == 0) + { + p->mutex = 0; + } } - } - return p->waiter_count; - } - return 0; + return p->waiter_count; + } + return 0; } static void DRD_(cond_signal)(Addr const cond) { - const ThreadId vg_tid = VG_(get_running_tid)(); - const DrdThreadId drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); - struct cond_info* const cond_p = DRD_(cond_get)(cond); - - if (cond_p && cond_p->waiter_count > 0) - { - if (DRD_(s_report_signal_unlocked) - && ! DRD_(mutex_is_locked_by)(cond_p->mutex, drd_tid)) - { - /* A signal is sent while the associated mutex has not been locked. */ - /* This can indicate but is not necessarily a race condition. */ - CondRaceErrInfo cei; - cei.cond = cond; - cei.mutex = cond_p->mutex; - VG_(maybe_record_error)(vg_tid, - CondRaceErr, - VG_(get_IP)(vg_tid), - "CondErr", - &cei); - } - } - else - { - /* No other thread is waiting for the signal, hence the signal will be */ - /* lost. This is normal in a POSIX threads application. */ - } + const ThreadId vg_tid = VG_(get_running_tid)(); + const DrdThreadId drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); + struct cond_info* const cond_p = DRD_(cond_get)(cond); + + if (cond_p && cond_p->waiter_count > 0) + { + if (DRD_(s_report_signal_unlocked) + && ! DRD_(mutex_is_locked_by)(cond_p->mutex, drd_tid)) + { + /* A signal is sent while the associated mutex has not been locked. */ + /* This can indicate but is not necessarily a race condition. */ + CondRaceErrInfo cei; + cei.cond = cond; + cei.mutex = cond_p->mutex; + VG_(maybe_record_error)(vg_tid, + CondRaceErr, + VG_(get_IP)(vg_tid), + "CondErr", + &cei); + } + } + else + { + /* No other thread is waiting for the signal, hence the signal will be */ + /* lost. This is normal in a POSIX threads application. */ + } } /** Called before pthread_cond_signal(). */ void DRD_(cond_pre_signal)(Addr const cond) { - if (DRD_(s_trace_cond)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] cond_signal cond 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - cond); - } - - DRD_(cond_signal)(cond); + if (DRD_(s_trace_cond)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] cond_signal cond 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + cond); + } + + DRD_(cond_signal)(cond); } /** Called before pthread_cond_broadcast(). */ void DRD_(cond_pre_broadcast)(Addr const cond) { - if (DRD_(s_trace_cond)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] cond_broadcast cond 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - cond); - } - - DRD_(cond_signal)(cond); + if (DRD_(s_trace_cond)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] cond_broadcast cond 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + cond); + } + + DRD_(cond_signal)(cond); } diff --git a/drd/drd_cond.h b/drd/drd_cond.h index e75caef259..75a074323e 100644 --- a/drd/drd_cond.h +++ b/drd/drd_cond.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. diff --git a/drd/drd_error.c b/drd/drd_error.c index 42597513ee..fe37aabe27 100644 --- a/drd/drd_error.c +++ b/drd/drd_error.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -47,7 +48,7 @@ static Bool s_show_conflicting_segments = True; void DRD_(set_show_conflicting_segments)(const Bool scs) { - s_show_conflicting_segments = scs; + s_show_conflicting_segments = scs; } /** @@ -57,17 +58,17 @@ void DRD_(set_show_conflicting_segments)(const Bool scs) static void describe_malloced_addr(Addr const a, SizeT const len, AddrInfo* const ai) { - Addr data; - - if (DRD_(heap_addrinfo)(a, &data, &ai->size, &ai->lastchange)) - { - ai->akind = eMallocd; - ai->rwoffset = a - data; - } - else - { - ai->akind = eUnknown; - } + Addr data; + + if (DRD_(heap_addrinfo)(a, &data, &ai->size, &ai->lastchange)) + { + ai->akind = eMallocd; + ai->rwoffset = a - data; + } + else + { + ai->akind = eUnknown; + } } /** @@ -77,343 +78,344 @@ void describe_malloced_addr(Addr const a, SizeT const len, AddrInfo* const ai) */ static void first_observed(const Addr obj) { - DrdClientobj* cl; - - cl = DRD_(clientobj_get_any)(obj); - if (cl) - { - tl_assert(cl->any.first_observed_at); - VG_(message)(Vg_UserMsg, - "%s 0x%lx was first observed at:", - DRD_(clientobj_type_name)(cl->any.type), - obj); - VG_(pp_ExeContext)(cl->any.first_observed_at); - } + DrdClientobj* cl; + + cl = DRD_(clientobj_get_any)(obj); + if (cl) + { + tl_assert(cl->any.first_observed_at); + VG_(message)(Vg_UserMsg, + "%s 0x%lx was first observed at:", + DRD_(clientobj_type_name)(cl->any.type), + obj); + VG_(pp_ExeContext)(cl->any.first_observed_at); + } } static void drd_report_data_race(Error* const err, const DataRaceErrInfo* const dri) { - AddrInfo ai; - const unsigned descr_size = 256; - Char* descr1 = VG_(malloc)("drd.error.drdr2.1", descr_size); - Char* descr2 = VG_(malloc)("drd.error.drdr2.2", descr_size); - - tl_assert(dri); - tl_assert(dri->addr); - tl_assert(dri->size > 0); - tl_assert(descr1); - tl_assert(descr2); - - descr1[0] = 0; - descr2[0] = 0; - VG_(get_data_description)(descr1, descr2, descr_size, dri->addr); - if (descr1[0] == 0) - { - describe_malloced_addr(dri->addr, dri->size, &ai); - } - VG_(message)(Vg_UserMsg, - "Conflicting %s by thread %d/%d at 0x%08lx size %ld", - dri->access_type == eStore ? "store" : "load", - DRD_(DrdThreadIdToVgThreadId)(dri->tid), - dri->tid, - dri->addr, - dri->size); - VG_(pp_ExeContext)(VG_(get_error_where)(err)); - if (descr1[0]) - { - VG_(message)(Vg_UserMsg, "%s", descr1); - VG_(message)(Vg_UserMsg, "%s", descr2); - } - else if (ai.akind == eMallocd && ai.lastchange) - { - VG_(message)(Vg_UserMsg, - "Address 0x%lx is at offset %ld from 0x%lx." - " Allocation context:", - dri->addr, ai.rwoffset, dri->addr - ai.rwoffset); - VG_(pp_ExeContext)(ai.lastchange); - } - else - { - char sect_name[64]; - VgSectKind sect_kind; - - sect_kind = VG_(seginfo_sect_kind)(sect_name, sizeof(sect_name), dri->addr); - if (sect_kind != Vg_SectUnknown) - { + AddrInfo ai; + const unsigned descr_size = 256; + Char* descr1 = VG_(malloc)("drd.error.drdr2.1", descr_size); + Char* descr2 = VG_(malloc)("drd.error.drdr2.2", descr_size); + + tl_assert(dri); + tl_assert(dri->addr); + tl_assert(dri->size > 0); + tl_assert(descr1); + tl_assert(descr2); + + descr1[0] = 0; + descr2[0] = 0; + VG_(get_data_description)(descr1, descr2, descr_size, dri->addr); + if (descr1[0] == 0) + { + describe_malloced_addr(dri->addr, dri->size, &ai); + } + VG_(message)(Vg_UserMsg, + "Conflicting %s by thread %d/%d at 0x%08lx size %ld", + dri->access_type == eStore ? "store" : "load", + DRD_(DrdThreadIdToVgThreadId)(dri->tid), + dri->tid, + dri->addr, + dri->size); + VG_(pp_ExeContext)(VG_(get_error_where)(err)); + if (descr1[0]) + { + VG_(message)(Vg_UserMsg, "%s", descr1); + VG_(message)(Vg_UserMsg, "%s", descr2); + } + else if (ai.akind == eMallocd && ai.lastchange) + { VG_(message)(Vg_UserMsg, - "Allocation context: %s section of %s", - VG_(pp_SectKind)(sect_kind), - sect_name); - } - else - { - VG_(message)(Vg_UserMsg, "Allocation context: unknown."); - } - } - if (s_show_conflicting_segments) - { - DRD_(thread_report_conflicting_segments)(dri->tid, - dri->addr, dri->size, - dri->access_type); - } - - VG_(free)(descr2); - VG_(free)(descr1); + "Address 0x%lx is at offset %ld from 0x%lx." + " Allocation context:", + dri->addr, ai.rwoffset, dri->addr - ai.rwoffset); + VG_(pp_ExeContext)(ai.lastchange); + } + else + { + char sect_name[64]; + VgSectKind sect_kind; + + sect_kind = VG_(seginfo_sect_kind)(sect_name, sizeof(sect_name), + dri->addr); + if (sect_kind != Vg_SectUnknown) + { + VG_(message)(Vg_UserMsg, + "Allocation context: %s section of %s", + VG_(pp_SectKind)(sect_kind), + sect_name); + } + else + { + VG_(message)(Vg_UserMsg, "Allocation context: unknown."); + } + } + if (s_show_conflicting_segments) + { + DRD_(thread_report_conflicting_segments)(dri->tid, + dri->addr, dri->size, + dri->access_type); + } + + VG_(free)(descr2); + VG_(free)(descr1); } static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2) { - return False; + return False; } static void drd_tool_error_pp(Error* const e) { - switch (VG_(get_error_kind)(e)) - { - case DataRaceErr: { - drd_report_data_race(e, VG_(get_error_extra)(e)); - break; - } - case MutexErr: { - MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e)); - tl_assert(p); - if (p->recursion_count >= 0) - { + switch (VG_(get_error_kind)(e)) + { + case DataRaceErr: { + drd_report_data_race(e, VG_(get_error_extra)(e)); + break; + } + case MutexErr: { + MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e)); + tl_assert(p); + if (p->recursion_count >= 0) + { + VG_(message)(Vg_UserMsg, + "%s: mutex 0x%lx, recursion count %d, owner %d.", + VG_(get_error_string)(e), + p->mutex, + p->recursion_count, + p->owner); + } + else + { + VG_(message)(Vg_UserMsg, + "The object at address 0x%lx is not a mutex.", + p->mutex); + } + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(p->mutex); + break; + } + case CondErr: { + CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e)); + VG_(message)(Vg_UserMsg, + "%s: cond 0x%lx", + VG_(get_error_string)(e), + cdei->cond); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(cdei->cond); + break; + } + case CondDestrErr: { + CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e)); + VG_(message)(Vg_UserMsg, + "%s: cond 0x%lx, mutex 0x%lx locked by thread %d/%d", + VG_(get_error_string)(e), + cdi->cond, cdi->mutex, + DRD_(DrdThreadIdToVgThreadId)(cdi->tid), cdi->tid); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(cdi->mutex); + break; + } + case CondRaceErr: { + CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e)); + VG_(message)(Vg_UserMsg, + "Probably a race condition: condition variable 0x%lx has" + " been signaled but the associated mutex 0x%lx is not" + " locked by the signalling thread.", + cei->cond, cei->mutex); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(cei->cond); + first_observed(cei->mutex); + break; + } + case CondWaitErr: { + CondWaitErrInfo* cwei = (CondWaitErrInfo*)(VG_(get_error_extra)(e)); VG_(message)(Vg_UserMsg, - "%s: mutex 0x%lx, recursion count %d, owner %d.", + "%s: condition variable 0x%lx, mutexes 0x%lx and 0x%lx", VG_(get_error_string)(e), - p->mutex, - p->recursion_count, - p->owner); - } - else - { + cwei->cond, + cwei->mutex1, + cwei->mutex2); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(cwei->cond); + first_observed(cwei->mutex1); + first_observed(cwei->mutex2); + break; + } + case SemaphoreErr: { + SemaphoreErrInfo* sei = (SemaphoreErrInfo*)(VG_(get_error_extra)(e)); + tl_assert(sei); VG_(message)(Vg_UserMsg, - "The object at address 0x%lx is not a mutex.", - p->mutex); - } - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(p->mutex); - break; - } - case CondErr: { - CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e)); - VG_(message)(Vg_UserMsg, - "%s: cond 0x%lx", - VG_(get_error_string)(e), - cdei->cond); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(cdei->cond); - break; - } - case CondDestrErr: { - CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e)); - VG_(message)(Vg_UserMsg, - "%s: cond 0x%lx, mutex 0x%lx locked by thread %d/%d", - VG_(get_error_string)(e), - cdi->cond, cdi->mutex, - DRD_(DrdThreadIdToVgThreadId)(cdi->tid), cdi->tid); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(cdi->mutex); - break; - } - case CondRaceErr: { - CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e)); - VG_(message)(Vg_UserMsg, - "Probably a race condition: condition variable 0x%lx has been" - " signaled but the associated mutex 0x%lx is not locked" - " by the signalling thread.", - cei->cond, cei->mutex); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(cei->cond); - first_observed(cei->mutex); - break; - } - case CondWaitErr: { - CondWaitErrInfo* cwei = (CondWaitErrInfo*)(VG_(get_error_extra)(e)); - VG_(message)(Vg_UserMsg, - "%s: condition variable 0x%lx, mutexes 0x%lx and 0x%lx", - VG_(get_error_string)(e), - cwei->cond, - cwei->mutex1, - cwei->mutex2); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(cwei->cond); - first_observed(cwei->mutex1); - first_observed(cwei->mutex2); - break; - } - case SemaphoreErr: { - SemaphoreErrInfo* sei = (SemaphoreErrInfo*)(VG_(get_error_extra)(e)); - tl_assert(sei); - VG_(message)(Vg_UserMsg, - "%s: semaphore 0x%lx", - VG_(get_error_string)(e), - sei->semaphore); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(sei->semaphore); - break; - } - case BarrierErr: { - BarrierErrInfo* bei = (BarrierErrInfo*)(VG_(get_error_extra)(e)); - tl_assert(bei); - VG_(message)(Vg_UserMsg, - "%s: barrier 0x%lx", - VG_(get_error_string)(e), - bei->barrier); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - if (bei->other_context) - { + "%s: semaphore 0x%lx", + VG_(get_error_string)(e), + sei->semaphore); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(sei->semaphore); + break; + } + case BarrierErr: { + BarrierErrInfo* bei = (BarrierErrInfo*)(VG_(get_error_extra)(e)); + tl_assert(bei); + VG_(message)(Vg_UserMsg, + "%s: barrier 0x%lx", + VG_(get_error_string)(e), + bei->barrier); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + if (bei->other_context) + { + VG_(message)(Vg_UserMsg, + "Conflicting wait call by thread %d/%d:", + DRD_(DrdThreadIdToVgThreadId)(bei->other_tid), + bei->other_tid); + VG_(pp_ExeContext)(bei->other_context); + } + first_observed(bei->barrier); + break; + } + case RwlockErr: { + RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e)); + tl_assert(p); + VG_(message)(Vg_UserMsg, + "%s: rwlock 0x%lx.", + VG_(get_error_string)(e), + p->rwlock); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(p->rwlock); + break; + } + case HoldtimeErr: { + HoldtimeErrInfo* p =(HoldtimeErrInfo*)(VG_(get_error_extra)(e)); + tl_assert(p); + tl_assert(p->acquired_at); + VG_(message)(Vg_UserMsg, "Acquired at:"); + VG_(pp_ExeContext)(p->acquired_at); + VG_(message)(Vg_UserMsg, + "Lock on %s 0x%lx was held during %d ms (threshold: %d ms).", + VG_(get_error_string)(e), + p->synchronization_object, + p->hold_time_ms, + p->threshold_ms); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + first_observed(p->synchronization_object); + break; + } + case GenericErr: { + //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e)); + VG_(message)(Vg_UserMsg, "%s", VG_(get_error_string)(e)); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + break; + } + default: VG_(message)(Vg_UserMsg, - "Conflicting wait call by thread %d/%d:", - DRD_(DrdThreadIdToVgThreadId)(bei->other_tid), - bei->other_tid); - VG_(pp_ExeContext)(bei->other_context); - } - first_observed(bei->barrier); - break; - } - case RwlockErr: { - RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e)); - tl_assert(p); - VG_(message)(Vg_UserMsg, - "%s: rwlock 0x%lx.", - VG_(get_error_string)(e), - p->rwlock); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(p->rwlock); - break; - } - case HoldtimeErr: { - HoldtimeErrInfo* p =(HoldtimeErrInfo*)(VG_(get_error_extra)(e)); - tl_assert(p); - tl_assert(p->acquired_at); - VG_(message)(Vg_UserMsg, "Acquired at:"); - VG_(pp_ExeContext)(p->acquired_at); - VG_(message)(Vg_UserMsg, - "Lock on %s 0x%lx was held during %d ms (threshold: %d ms).", - VG_(get_error_string)(e), - p->synchronization_object, - p->hold_time_ms, - p->threshold_ms); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - first_observed(p->synchronization_object); - break; - } - case GenericErr: { - //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e)); - VG_(message)(Vg_UserMsg, "%s", VG_(get_error_string)(e)); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - break; - } - default: - VG_(message)(Vg_UserMsg, - "%s", - VG_(get_error_string)(e)); - VG_(pp_ExeContext)(VG_(get_error_where)(e)); - break; - } + "%s", + VG_(get_error_string)(e)); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + break; + } } static UInt drd_tool_error_update_extra(Error* e) { - switch (VG_(get_error_kind)(e)) - { - case DataRaceErr: - return sizeof(DataRaceErrInfo); - case MutexErr: - return sizeof(MutexErrInfo); - case CondErr: - return sizeof(CondErrInfo); - case CondDestrErr: - return sizeof(CondDestrErrInfo); - case CondRaceErr: - return sizeof(CondRaceErrInfo); - case CondWaitErr: - return sizeof(CondWaitErrInfo); - case SemaphoreErr: - return sizeof(SemaphoreErrInfo); - case BarrierErr: - return sizeof(BarrierErrInfo); - case RwlockErr: - return sizeof(RwlockErrInfo); - case HoldtimeErr: - return sizeof(HoldtimeErrInfo); - case GenericErr: - return sizeof(GenericErrInfo); - default: - tl_assert(False); - break; - } + switch (VG_(get_error_kind)(e)) + { + case DataRaceErr: + return sizeof(DataRaceErrInfo); + case MutexErr: + return sizeof(MutexErrInfo); + case CondErr: + return sizeof(CondErrInfo); + case CondDestrErr: + return sizeof(CondDestrErrInfo); + case CondRaceErr: + return sizeof(CondRaceErrInfo); + case CondWaitErr: + return sizeof(CondWaitErrInfo); + case SemaphoreErr: + return sizeof(SemaphoreErrInfo); + case BarrierErr: + return sizeof(BarrierErrInfo); + case RwlockErr: + return sizeof(RwlockErrInfo); + case HoldtimeErr: + return sizeof(HoldtimeErrInfo); + case GenericErr: + return sizeof(GenericErrInfo); + default: + tl_assert(False); + break; + } } static Bool drd_tool_error_recog(Char* const name, Supp* const supp) { - SuppKind skind = 0; - - if (VG_(strcmp)(name, STR_DataRaceErr) == 0) - ; - else if (VG_(strcmp)(name, STR_MutexErr) == 0) - ; - else if (VG_(strcmp)(name, STR_CondErr) == 0) - ; - else if (VG_(strcmp)(name, STR_CondDestrErr) == 0) - ; - else if (VG_(strcmp)(name, STR_CondRaceErr) == 0) - ; - else if (VG_(strcmp)(name, STR_CondWaitErr) == 0) - ; - else if (VG_(strcmp)(name, STR_SemaphoreErr) == 0) - ; - else if (VG_(strcmp)(name, STR_BarrierErr) == 0) - ; - else if (VG_(strcmp)(name, STR_RwlockErr) == 0) - ; - else if (VG_(strcmp)(name, STR_HoldtimeErr) == 0) - ; - else if (VG_(strcmp)(name, STR_GenericErr) == 0) - ; - else - return False; - - VG_(set_supp_kind)(supp, skind); - return True; + SuppKind skind = 0; + + if (VG_(strcmp)(name, STR_DataRaceErr) == 0) + ; + else if (VG_(strcmp)(name, STR_MutexErr) == 0) + ; + else if (VG_(strcmp)(name, STR_CondErr) == 0) + ; + else if (VG_(strcmp)(name, STR_CondDestrErr) == 0) + ; + else if (VG_(strcmp)(name, STR_CondRaceErr) == 0) + ; + else if (VG_(strcmp)(name, STR_CondWaitErr) == 0) + ; + else if (VG_(strcmp)(name, STR_SemaphoreErr) == 0) + ; + else if (VG_(strcmp)(name, STR_BarrierErr) == 0) + ; + else if (VG_(strcmp)(name, STR_RwlockErr) == 0) + ; + else if (VG_(strcmp)(name, STR_HoldtimeErr) == 0) + ; + else if (VG_(strcmp)(name, STR_GenericErr) == 0) + ; + else + return False; + + VG_(set_supp_kind)(supp, skind); + return True; } static Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp) { - return True; + return True; } static Bool drd_tool_error_matches(Error* const e, Supp* const supp) { - switch (VG_(get_supp_kind)(supp)) - { - } - return True; + switch (VG_(get_supp_kind)(supp)) + { + } + return True; } static Char* drd_tool_error_name(Error* e) { - switch (VG_(get_error_kind)(e)) - { - case DataRaceErr: return VGAPPEND(STR_, DataRaceErr); - case MutexErr: return VGAPPEND(STR_, MutexErr); - case CondErr: return VGAPPEND(STR_, CondErr); - case CondDestrErr: return VGAPPEND(STR_, CondDestrErr); - case CondRaceErr: return VGAPPEND(STR_, CondRaceErr); - case CondWaitErr: return VGAPPEND(STR_, CondWaitErr); - case SemaphoreErr: return VGAPPEND(STR_, SemaphoreErr); - case BarrierErr: return VGAPPEND(STR_, BarrierErr); - case RwlockErr: return VGAPPEND(STR_, RwlockErr); - case HoldtimeErr: return VGAPPEND(STR_, HoldtimeErr); - case GenericErr: return VGAPPEND(STR_, GenericErr); - default: - tl_assert(0); - } - return 0; + switch (VG_(get_error_kind)(e)) + { + case DataRaceErr: return VGAPPEND(STR_, DataRaceErr); + case MutexErr: return VGAPPEND(STR_, MutexErr); + case CondErr: return VGAPPEND(STR_, CondErr); + case CondDestrErr: return VGAPPEND(STR_, CondDestrErr); + case CondRaceErr: return VGAPPEND(STR_, CondRaceErr); + case CondWaitErr: return VGAPPEND(STR_, CondWaitErr); + case SemaphoreErr: return VGAPPEND(STR_, SemaphoreErr); + case BarrierErr: return VGAPPEND(STR_, BarrierErr); + case RwlockErr: return VGAPPEND(STR_, RwlockErr); + case HoldtimeErr: return VGAPPEND(STR_, HoldtimeErr); + case GenericErr: return VGAPPEND(STR_, GenericErr); + default: + tl_assert(0); + } + return 0; } static void drd_tool_error_print_extra(Error* e) @@ -421,14 +423,14 @@ static void drd_tool_error_print_extra(Error* e) void DRD_(register_error_handlers)(void) { - // Tool error reporting. - VG_(needs_tool_errors)(drd_tool_error_eq, - drd_tool_error_pp, - True, - drd_tool_error_update_extra, - drd_tool_error_recog, - drd_tool_error_read_extra, - drd_tool_error_matches, - drd_tool_error_name, - drd_tool_error_print_extra); + // Tool error reporting. + VG_(needs_tool_errors)(drd_tool_error_eq, + drd_tool_error_pp, + True, + drd_tool_error_update_extra, + drd_tool_error_recog, + drd_tool_error_read_extra, + drd_tool_error_matches, + drd_tool_error_name, + drd_tool_error_print_extra); } diff --git a/drd/drd_error.h b/drd/drd_error.h index 34fd62b114..2d5e6433af 100644 --- a/drd/drd_error.h +++ b/drd/drd_error.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -138,10 +139,10 @@ typedef struct { } RwlockErrInfo; typedef struct { - Addr synchronization_object; - ExeContext* acquired_at; - UInt hold_time_ms; - UInt threshold_ms; + Addr synchronization_object; + ExeContext* acquired_at; + UInt hold_time_ms; + UInt threshold_ms; } HoldtimeErrInfo; typedef struct { diff --git a/drd/drd_gomp_intercepts.c b/drd/drd_gomp_intercepts.c index d791c8336c..6cf2890b73 100644 --- a/drd/drd_gomp_intercepts.c +++ b/drd/drd_gomp_intercepts.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /*--------------------------------------------------------------------*/ /*--- Client-space code for drd. drd_gomp_intercepts.c ---*/ @@ -46,9 +47,9 @@ // Defines. -#define GOMP_FUNC(ret_ty, f, args...) \ - ret_ty VG_WRAP_FUNCTION_ZZ(libgompZdsoZd1Za,f)(args); \ - ret_ty VG_WRAP_FUNCTION_ZZ(libgompZdsoZd1Za,f)(args) +#define GOMP_FUNC(ret_ty, f, args...) \ + ret_ty VG_WRAP_FUNCTION_ZZ(libgompZdsoZd1Za,f)(args); \ + ret_ty VG_WRAP_FUNCTION_ZZ(libgompZdsoZd1Za,f)(args) // Type definitions @@ -61,56 +62,56 @@ typedef void* gomp_barrier_t; GOMP_FUNC(void, gompZubarrierZuinit, // gomp_barrier_init gomp_barrier_t* barrier, unsigned count) { - int ret; - int res; - OrigFn fn; - - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, - barrier, gomp_barrier, count, 0, 0); - VALGRIND_GET_ORIG_FN(fn); - CALL_FN_W_WW(ret, fn, barrier, count); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, - barrier, gomp_barrier, 0, 0, 0); + int ret; + int res; + OrigFn fn; + + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, + barrier, gomp_barrier, count, 0, 0); + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WW(ret, fn, barrier, count); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, + barrier, gomp_barrier, 0, 0, 0); } GOMP_FUNC(void, gompZubarrierZureinit, // gomp_barrier_reinit gomp_barrier_t* barrier, unsigned count) { - int ret; - int res; - OrigFn fn; - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, - barrier, gomp_barrier, count, 1, 0); - VALGRIND_GET_ORIG_FN(fn); - CALL_FN_W_WW(ret, fn, barrier, count); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, - barrier, gomp_barrier, 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, + barrier, gomp_barrier, count, 1, 0); + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WW(ret, fn, barrier, count); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, + barrier, gomp_barrier, 0, 0, 0); } GOMP_FUNC(void, gompZubarrierZudestroy, // gomp_barrier_destroy gomp_barrier_t* barrier) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY, - barrier, gomp_barrier, 0, 0, 0); - CALL_FN_W_W(ret, fn, barrier); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, - barrier, gomp_barrier, 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY, + barrier, gomp_barrier, 0, 0, 0); + CALL_FN_W_W(ret, fn, barrier); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, + barrier, gomp_barrier, 0, 0, 0); } GOMP_FUNC(void, gompZubarrierZuwait, // gomp_barrier_wait gomp_barrier_t* barrier) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, - barrier, gomp_barrier, 0, 0, 0); - CALL_FN_W_W(ret, fn, barrier); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, - barrier, gomp_barrier, 1, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, + barrier, gomp_barrier, 0, 0, 0); + CALL_FN_W_W(ret, fn, barrier); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, + barrier, gomp_barrier, 1, 0, 0); } diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c index 63706980b9..65210737b2 100644 --- a/drd/drd_load_store.c +++ b/drd/drd_load_store.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -59,202 +60,202 @@ static Bool DRD_(s_check_stack_accesses) = False; Bool DRD_(get_check_stack_accesses)() { - return DRD_(s_check_stack_accesses); + return DRD_(s_check_stack_accesses); } void DRD_(set_check_stack_accesses)(const Bool c) { - tl_assert(c == False || c == True); - DRD_(s_check_stack_accesses) = c; + tl_assert(c == False || c == True); + DRD_(s_check_stack_accesses) = c; } void DRD_(trace_mem_access)(const Addr addr, const SizeT size, - const BmAccessTypeT access_type) + const BmAccessTypeT access_type) { - if (DRD_(is_any_traced)(addr, addr + size)) - { - char vc[80]; - DRD_(vc_snprint)(vc, sizeof(vc), - DRD_(thread_get_vc)(DRD_(thread_get_running_tid)())); - VG_(message)(Vg_UserMsg, - "%s 0x%lx size %ld (vg %d / drd %d / vc %s)", - access_type == eLoad - ? "load " - : access_type == eStore - ? "store" - : access_type == eStart - ? "start" - : access_type == eEnd - ? "end " - : "????", - addr, - size, - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - vc); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), - VG_(clo_backtrace_size)); - tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)()) - == VG_(get_running_tid)()); - } + if (DRD_(is_any_traced)(addr, addr + size)) + { + char vc[80]; + DRD_(vc_snprint)(vc, sizeof(vc), + DRD_(thread_get_vc)(DRD_(thread_get_running_tid)())); + VG_(message)(Vg_UserMsg, + "%s 0x%lx size %ld (vg %d / drd %d / vc %s)", + access_type == eLoad + ? "load " + : access_type == eStore + ? "store" + : access_type == eStart + ? "start" + : access_type == eEnd + ? "end " + : "????", + addr, + size, + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + vc); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), + VG_(clo_backtrace_size)); + tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)()) + == VG_(get_running_tid)()); + } } static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size) { - return DRD_(trace_mem_access)(addr, size, eLoad); + return DRD_(trace_mem_access)(addr, size, eLoad); } static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size) { - return DRD_(trace_mem_access)(addr, size, eStore); + return DRD_(trace_mem_access)(addr, size, eStore); } static void drd_report_race(const Addr addr, const SizeT size, const BmAccessTypeT access_type) { - DataRaceErrInfo drei; - - drei.tid = DRD_(thread_get_running_tid)(); - drei.addr = addr; - drei.size = size; - drei.access_type = access_type; - VG_(maybe_record_error)(VG_(get_running_tid)(), - DataRaceErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Conflicting accesses", - &drei); + DataRaceErrInfo drei; + + drei.tid = DRD_(thread_get_running_tid)(); + drei.addr = addr; + drei.size = size; + drei.access_type = access_type; + VG_(maybe_record_error)(VG_(get_running_tid)(), + DataRaceErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Conflicting accesses", + &drei); } VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - /* The assert below has been commented out because of performance reasons.*/ - tl_assert(thread_get_running_tid() - == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); + /* The assert below has been commented out because of performance reasons.*/ + tl_assert(thread_get_running_tid() + == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); #endif - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_load_triggers_conflict(addr, addr + size) - && ! DRD_(is_suppressed)(addr, addr + size)) - { - drd_report_race(addr, size, eLoad); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_load_triggers_conflict(addr, addr + size) + && ! DRD_(is_suppressed)(addr, addr + size)) + { + drd_report_race(addr, size, eLoad); + } } static VG_REGPARM(1) void drd_trace_load_1(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_load_1_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 1)) - { - drd_report_race(addr, 1, eLoad); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_load_1_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 1)) + { + drd_report_race(addr, 1, eLoad); + } } static VG_REGPARM(1) void drd_trace_load_2(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_load_2_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 2)) - { - drd_report_race(addr, 2, eLoad); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_load_2_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 2)) + { + drd_report_race(addr, 2, eLoad); + } } static VG_REGPARM(1) void drd_trace_load_4(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_load_4_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 4)) - { - drd_report_race(addr, 4, eLoad); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_load_4_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 4)) + { + drd_report_race(addr, 4, eLoad); + } } static VG_REGPARM(1) void drd_trace_load_8(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_load_8_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 8)) - { - drd_report_race(addr, 8, eLoad); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_load_8_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 8)) + { + drd_report_race(addr, 8, eLoad); + } } VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size) { #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - /* The assert below has been commented out because of performance reasons.*/ - tl_assert(thread_get_running_tid() - == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); + /* The assert below has been commented out because of performance reasons.*/ + tl_assert(thread_get_running_tid() + == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); #endif - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_store_triggers_conflict(addr, addr + size) - && ! DRD_(is_suppressed)(addr, addr + size)) - { - drd_report_race(addr, size, eStore); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_store_triggers_conflict(addr, addr + size) + && ! DRD_(is_suppressed)(addr, addr + size)) + { + drd_report_race(addr, size, eStore); + } } static VG_REGPARM(1) void drd_trace_store_1(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_store_1_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 1)) - { - drd_report_race(addr, 1, eStore); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_store_1_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 1)) + { + drd_report_race(addr, 1, eStore); + } } static VG_REGPARM(1) void drd_trace_store_2(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_store_2_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 2)) - { - drd_report_race(addr, 2, eStore); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_store_2_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 2)) + { + drd_report_race(addr, 2, eStore); + } } static VG_REGPARM(1) void drd_trace_store_4(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_store_4_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 4)) - { - drd_report_race(addr, 4, eStore); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_store_4_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 4)) + { + drd_report_race(addr, 4, eStore); + } } static VG_REGPARM(1) void drd_trace_store_8(Addr addr) { - if (DRD_(running_thread_is_recording)() - && (DRD_(s_check_stack_accesses) - || ! DRD_(thread_address_on_stack)(addr)) - && bm_access_store_8_triggers_conflict(addr) - && ! DRD_(is_suppressed)(addr, addr + 8)) - { - drd_report_race(addr, 8, eStore); - } + if (DRD_(running_thread_is_recording)() + && (DRD_(s_check_stack_accesses) + || ! DRD_(thread_address_on_stack)(addr)) + && bm_access_store_8_triggers_conflict(addr) + && ! DRD_(is_suppressed)(addr, addr + 8)) + { + drd_report_race(addr, 8, eStore); + } } /** @@ -263,297 +264,297 @@ static VG_REGPARM(1) void drd_trace_store_8(Addr addr) */ static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr) { - Bool result = False; - - if (addr_expr->tag == Iex_RdTmp) - { - int i; - for (i = 0; i < bb->stmts_size; i++) - { - if (bb->stmts[i] - && bb->stmts[i]->tag == Ist_WrTmp - && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp) + Bool result = False; + + if (addr_expr->tag == Iex_RdTmp) + { + int i; + for (i = 0; i < bb->stmts_size; i++) { - IRExpr* e = bb->stmts[i]->Ist.WrTmp.data; - if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET) - { - result = True; - } - - //ppIRExpr(e); - //VG_(printf)(" (%s)\n", result ? "True" : "False"); - break; + if (bb->stmts[i] + && bb->stmts[i]->tag == Ist_WrTmp + && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp) + { + IRExpr* e = bb->stmts[i]->Ist.WrTmp.data; + if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET) + { + result = True; + } + + //ppIRExpr(e); + //VG_(printf)(" (%s)\n", result ? "True" : "False"); + break; + } } - } - } - return result; + } + return result; } static void instrument_load(IRSB* const bb, IRExpr* const addr_expr, const HWord size) { - IRExpr* size_expr; - IRExpr** argv; - IRDirty* di; - - if (UNLIKELY(DRD_(any_address_is_traced)())) - { - addStmtToIRSB(bb, - IRStmt_Dirty( - unsafeIRDirty_0_N(/*regparms*/2, - "drd_trace_load", - VG_(fnptr_to_fnentry) - (drd_trace_mem_load), - mkIRExprVec_2(addr_expr, - mkIRExpr_HWord(size))))); - } - - if (! DRD_(s_check_stack_accesses) && is_stack_access(bb, addr_expr)) - return; - - switch (size) - { - case 1: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_load_1", - VG_(fnptr_to_fnentry)(drd_trace_load_1), - argv); - break; - case 2: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_load_2", - VG_(fnptr_to_fnentry)(drd_trace_load_2), - argv); - break; - case 4: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_load_4", - VG_(fnptr_to_fnentry)(drd_trace_load_4), - argv); - break; - case 8: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_load_8", - VG_(fnptr_to_fnentry)(drd_trace_load_8), - argv); - break; - default: - size_expr = mkIRExpr_HWord(size); - argv = mkIRExprVec_2(addr_expr, size_expr); - di = unsafeIRDirty_0_N(/*regparms*/2, - "drd_trace_load", - VG_(fnptr_to_fnentry)(DRD_(trace_load)), - argv); - break; - } - addStmtToIRSB(bb, IRStmt_Dirty(di)); + IRExpr* size_expr; + IRExpr** argv; + IRDirty* di; + + if (UNLIKELY(DRD_(any_address_is_traced)())) + { + addStmtToIRSB(bb, + IRStmt_Dirty( + unsafeIRDirty_0_N(/*regparms*/2, + "drd_trace_load", + VG_(fnptr_to_fnentry) + (drd_trace_mem_load), + mkIRExprVec_2(addr_expr, + mkIRExpr_HWord(size))))); + } + + if (! DRD_(s_check_stack_accesses) && is_stack_access(bb, addr_expr)) + return; + + switch (size) + { + case 1: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_load_1", + VG_(fnptr_to_fnentry)(drd_trace_load_1), + argv); + break; + case 2: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_load_2", + VG_(fnptr_to_fnentry)(drd_trace_load_2), + argv); + break; + case 4: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_load_4", + VG_(fnptr_to_fnentry)(drd_trace_load_4), + argv); + break; + case 8: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_load_8", + VG_(fnptr_to_fnentry)(drd_trace_load_8), + argv); + break; + default: + size_expr = mkIRExpr_HWord(size); + argv = mkIRExprVec_2(addr_expr, size_expr); + di = unsafeIRDirty_0_N(/*regparms*/2, + "drd_trace_load", + VG_(fnptr_to_fnentry)(DRD_(trace_load)), + argv); + break; + } + addStmtToIRSB(bb, IRStmt_Dirty(di)); } static void instrument_store(IRSB* const bb, IRExpr* const addr_expr, const HWord size) { - IRExpr* size_expr; - IRExpr** argv; - IRDirty* di; - - if (UNLIKELY(DRD_(any_address_is_traced)())) - { - addStmtToIRSB(bb, - IRStmt_Dirty( - unsafeIRDirty_0_N(/*regparms*/2, - "drd_trace_store", - VG_(fnptr_to_fnentry) - (drd_trace_mem_store), - mkIRExprVec_2(addr_expr, - mkIRExpr_HWord(size))))); - } - - if (! DRD_(s_check_stack_accesses) && is_stack_access(bb, addr_expr)) - return; - - switch (size) - { - case 1: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_store_1", - VG_(fnptr_to_fnentry)(drd_trace_store_1), - argv); - break; - case 2: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_store_2", - VG_(fnptr_to_fnentry)(drd_trace_store_2), - argv); - break; - case 4: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_store_4", - VG_(fnptr_to_fnentry)(drd_trace_store_4), - argv); - break; - case 8: - argv = mkIRExprVec_1(addr_expr); - di = unsafeIRDirty_0_N(/*regparms*/1, - "drd_trace_store_8", - VG_(fnptr_to_fnentry)(drd_trace_store_8), - argv); - break; - default: - size_expr = mkIRExpr_HWord(size); - argv = mkIRExprVec_2(addr_expr, size_expr); - di = unsafeIRDirty_0_N(/*regparms*/2, - "drd_trace_store", - VG_(fnptr_to_fnentry)(DRD_(trace_store)), - argv); - break; - } - addStmtToIRSB(bb, IRStmt_Dirty(di)); -} - -IRSB* DRD_(instrument)(VgCallbackClosure* const closure, - IRSB* const bb_in, - VexGuestLayout* const layout, - VexGuestExtents* const vge, - IRType const gWordTy, - IRType const hWordTy) -{ - IRDirty* di; - Int i; - IRSB* bb; - IRExpr** argv; - Bool instrument = True; - Bool bus_locked = False; - - /* Set up BB */ - bb = emptyIRSB(); - bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv); - bb->next = deepCopyIRExpr(bb_in->next); - bb->jumpkind = bb_in->jumpkind; - - for (i = 0; i < bb_in->stmts_used; i++) - { - IRStmt* const st = bb_in->stmts[i]; - tl_assert(st); - if (st->tag == Ist_NoOp) - continue; - - switch (st->tag) - { - /* Note: the code for not instrumenting the code in .plt */ - /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */ - /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */ - /* This is because on this platform dynamic library symbols are */ - /* relocated in another way than by later binutils versions. The */ - /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */ - case Ist_IMark: - instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr) - != Vg_SectPLT; - addStmtToIRSB(bb, st); + IRExpr* size_expr; + IRExpr** argv; + IRDirty* di; + + if (UNLIKELY(DRD_(any_address_is_traced)())) + { + addStmtToIRSB(bb, + IRStmt_Dirty( + unsafeIRDirty_0_N(/*regparms*/2, + "drd_trace_store", + VG_(fnptr_to_fnentry) + (drd_trace_mem_store), + mkIRExprVec_2(addr_expr, + mkIRExpr_HWord(size))))); + } + + if (! DRD_(s_check_stack_accesses) && is_stack_access(bb, addr_expr)) + return; + + switch (size) + { + case 1: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_store_1", + VG_(fnptr_to_fnentry)(drd_trace_store_1), + argv); break; - - case Ist_MBE: - switch (st->Ist.MBE.event) - { - case Imbe_Fence: - break; /* not interesting */ - case Imbe_BusLock: - case Imbe_SnoopedStoreBegin: - tl_assert(! bus_locked); - bus_locked = True; - break; - case Imbe_BusUnlock: - case Imbe_SnoopedStoreEnd: - tl_assert(bus_locked); - bus_locked = False; - break; - default: - tl_assert(0); - } - addStmtToIRSB(bb, st); + case 2: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_store_2", + VG_(fnptr_to_fnentry)(drd_trace_store_2), + argv); break; - - case Ist_Store: - if (instrument && ! bus_locked) - { - instrument_store(bb, - st->Ist.Store.addr, - sizeofIRType(typeOfIRExpr(bb->tyenv, - st->Ist.Store.data))); - } - addStmtToIRSB(bb, st); + case 4: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_store_4", + VG_(fnptr_to_fnentry)(drd_trace_store_4), + argv); break; - - case Ist_WrTmp: - if (instrument) - { - const IRExpr* const data = st->Ist.WrTmp.data; - if (data->tag == Iex_Load) - { - instrument_load(bb, - data->Iex.Load.addr, - sizeofIRType(data->Iex.Load.ty)); - } - } - addStmtToIRSB(bb, st); + case 8: + argv = mkIRExprVec_1(addr_expr); + di = unsafeIRDirty_0_N(/*regparms*/1, + "drd_trace_store_8", + VG_(fnptr_to_fnentry)(drd_trace_store_8), + argv); break; + default: + size_expr = mkIRExpr_HWord(size); + argv = mkIRExprVec_2(addr_expr, size_expr); + di = unsafeIRDirty_0_N(/*regparms*/2, + "drd_trace_store", + VG_(fnptr_to_fnentry)(DRD_(trace_store)), + argv); + break; + } + addStmtToIRSB(bb, IRStmt_Dirty(di)); +} - case Ist_Dirty: - if (instrument) +IRSB* DRD_(instrument)(VgCallbackClosure* const closure, + IRSB* const bb_in, + VexGuestLayout* const layout, + VexGuestExtents* const vge, + IRType const gWordTy, + IRType const hWordTy) +{ + IRDirty* di; + Int i; + IRSB* bb; + IRExpr** argv; + Bool instrument = True; + Bool bus_locked = False; + + /* Set up BB */ + bb = emptyIRSB(); + bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv); + bb->next = deepCopyIRExpr(bb_in->next); + bb->jumpkind = bb_in->jumpkind; + + for (i = 0; i < bb_in->stmts_used; i++) + { + IRStmt* const st = bb_in->stmts[i]; + tl_assert(st); + if (st->tag == Ist_NoOp) + continue; + + switch (st->tag) { - IRDirty* d = st->Ist.Dirty.details; - IREffect const mFx = d->mFx; - switch (mFx) { - case Ifx_None: - break; - case Ifx_Read: - case Ifx_Write: - case Ifx_Modify: - tl_assert(d->mAddr); - tl_assert(d->mSize > 0); - argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize)); - if (mFx == Ifx_Read || mFx == Ifx_Modify) { - di = unsafeIRDirty_0_N( - /*regparms*/2, - "drd_trace_load", - VG_(fnptr_to_fnentry)(DRD_(trace_load)), - argv); - addStmtToIRSB(bb, IRStmt_Dirty(di)); - } - if ((mFx == Ifx_Write || mFx == Ifx_Modify) - && ! bus_locked) - { - di = unsafeIRDirty_0_N( - /*regparms*/2, - "drd_trace_store", - VG_(fnptr_to_fnentry)(DRD_(trace_store)), - argv); - addStmtToIRSB(bb, IRStmt_Dirty(di)); - } - break; - default: - tl_assert(0); - } - } - addStmtToIRSB(bb, st); - break; + /* Note: the code for not instrumenting the code in .plt */ + /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */ + /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */ + /* This is because on this platform dynamic library symbols are */ + /* relocated in another way than by later binutils versions. The */ + /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */ + case Ist_IMark: + instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr) + != Vg_SectPLT; + addStmtToIRSB(bb, st); + break; + + case Ist_MBE: + switch (st->Ist.MBE.event) + { + case Imbe_Fence: + break; /* not interesting */ + case Imbe_BusLock: + case Imbe_SnoopedStoreBegin: + tl_assert(! bus_locked); + bus_locked = True; + break; + case Imbe_BusUnlock: + case Imbe_SnoopedStoreEnd: + tl_assert(bus_locked); + bus_locked = False; + break; + default: + tl_assert(0); + } + addStmtToIRSB(bb, st); + break; + + case Ist_Store: + if (instrument && ! bus_locked) + { + instrument_store(bb, + st->Ist.Store.addr, + sizeofIRType(typeOfIRExpr(bb->tyenv, + st->Ist.Store.data))); + } + addStmtToIRSB(bb, st); + break; + + case Ist_WrTmp: + if (instrument) + { + const IRExpr* const data = st->Ist.WrTmp.data; + if (data->tag == Iex_Load) + { + instrument_load(bb, + data->Iex.Load.addr, + sizeofIRType(data->Iex.Load.ty)); + } + } + addStmtToIRSB(bb, st); + break; + + case Ist_Dirty: + if (instrument) + { + IRDirty* d = st->Ist.Dirty.details; + IREffect const mFx = d->mFx; + switch (mFx) { + case Ifx_None: + break; + case Ifx_Read: + case Ifx_Write: + case Ifx_Modify: + tl_assert(d->mAddr); + tl_assert(d->mSize > 0); + argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize)); + if (mFx == Ifx_Read || mFx == Ifx_Modify) { + di = unsafeIRDirty_0_N( + /*regparms*/2, + "drd_trace_load", + VG_(fnptr_to_fnentry)(DRD_(trace_load)), + argv); + addStmtToIRSB(bb, IRStmt_Dirty(di)); + } + if ((mFx == Ifx_Write || mFx == Ifx_Modify) + && ! bus_locked) + { + di = unsafeIRDirty_0_N( + /*regparms*/2, + "drd_trace_store", + VG_(fnptr_to_fnentry)(DRD_(trace_store)), + argv); + addStmtToIRSB(bb, IRStmt_Dirty(di)); + } + break; + default: + tl_assert(0); + } + } + addStmtToIRSB(bb, st); + break; - default: - addStmtToIRSB(bb, st); - break; - } - } + default: + addStmtToIRSB(bb, st); + break; + } + } - tl_assert(! bus_locked); + tl_assert(! bus_locked); - return bb; + return bb; } diff --git a/drd/drd_load_store.h b/drd/drd_load_store.h index 19ab44f754..fcd7cc8435 100644 --- a/drd/drd_load_store.h +++ b/drd/drd_load_store.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. diff --git a/drd/drd_main.c b/drd/drd_main.c index f580a82151..b37dfcea5b 100644 --- a/drd/drd_main.c +++ b/drd/drd_main.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -64,102 +65,103 @@ static Bool DRD_(s_show_stack_usage) = False; */ static Bool DRD_(process_cmd_line_option)(Char* arg) { - int check_stack_accesses = -1; - int exclusive_threshold_ms = -1; - int report_signal_unlocked = -1; - int segment_merging = -1; - int shared_threshold_ms = -1; - int show_confl_seg = -1; - int trace_barrier = -1; - int trace_clientobj = -1; - int trace_cond = -1; - int trace_csw = -1; - int trace_fork_join = -1; - int trace_conflict_set = -1; - int trace_mutex = -1; - int trace_rwlock = -1; - int trace_segment = -1; - int trace_semaphore = -1; - int trace_suppression = -1; - Char* trace_address = 0; - - if VG_BOOL_CLO(arg, "--check-stack-var", check_stack_accesses) {} - else if VG_BOOL_CLO(arg, "--drd-stats", DRD_(s_print_stats)) {} - else if VG_BOOL_CLO(arg,"--report-signal-unlocked",report_signal_unlocked) {} - else if VG_BOOL_CLO(arg, "--segment-merging", segment_merging) {} - else if VG_BOOL_CLO(arg, "--show-confl-seg", show_confl_seg) {} - else if VG_BOOL_CLO(arg, "--show-stack-usage", DRD_(s_show_stack_usage)) {} - else if VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier) {} - else if VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj) {} - else if VG_BOOL_CLO(arg, "--trace-cond", trace_cond) {} - else if VG_BOOL_CLO(arg, "--trace-conflict-set", trace_conflict_set) {} - else if VG_BOOL_CLO(arg, "--trace-csw", trace_csw) {} - else if VG_BOOL_CLO(arg, "--trace-fork-join", trace_fork_join) {} - else if VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex) {} - else if VG_BOOL_CLO(arg, "--trace-rwlock", trace_rwlock) {} - else if VG_BOOL_CLO(arg, "--trace-segment", trace_segment) {} - else if VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore) {} - else if VG_BOOL_CLO(arg, "--trace-suppr", trace_suppression) {} - else if VG_BOOL_CLO(arg, "--var-info", DRD_(s_var_info)) {} - else if VG_INT_CLO (arg, "--exclusive-threshold", exclusive_threshold_ms) {} - else if VG_INT_CLO (arg, "--shared-threshold", shared_threshold_ms) {} - else if VG_STR_CLO (arg, "--trace-addr", trace_address) {} - else - return VG_(replacement_malloc_process_cmd_line_option)(arg); - - if (check_stack_accesses != -1) - DRD_(set_check_stack_accesses)(check_stack_accesses); - if (exclusive_threshold_ms != -1) - { - DRD_(mutex_set_lock_threshold)(exclusive_threshold_ms); - DRD_(rwlock_set_exclusive_threshold)(exclusive_threshold_ms); - } - if (report_signal_unlocked != -1) - { - DRD_(cond_set_report_signal_unlocked)(report_signal_unlocked); - } - if (shared_threshold_ms != -1) - { - DRD_(rwlock_set_shared_threshold)(shared_threshold_ms); - } - if (segment_merging != -1) - DRD_(thread_set_segment_merging)(segment_merging); - if (show_confl_seg != -1) - DRD_(set_show_conflicting_segments)(show_confl_seg); - if (trace_address) - { - const Addr addr = VG_(strtoll16)(trace_address, 0); - DRD_(start_tracing_address_range)(addr, addr + 1); - } - if (trace_barrier != -1) - DRD_(barrier_set_trace)(trace_barrier); - if (trace_clientobj != -1) - DRD_(clientobj_set_trace)(trace_clientobj); - if (trace_cond != -1) - DRD_(cond_set_trace)(trace_cond); - if (trace_csw != -1) - DRD_(thread_trace_context_switches)(trace_csw); - if (trace_fork_join != -1) - DRD_(thread_set_trace_fork_join)(trace_fork_join); - if (trace_conflict_set != -1) - DRD_(thread_trace_conflict_set)(trace_conflict_set); - if (trace_mutex != -1) - DRD_(mutex_set_trace)(trace_mutex); - if (trace_rwlock != -1) - DRD_(rwlock_set_trace)(trace_rwlock); - if (trace_segment != -1) - DRD_(sg_set_trace)(trace_segment); - if (trace_semaphore != -1) - DRD_(semaphore_set_trace)(trace_semaphore); - if (trace_suppression != -1) - DRD_(suppression_set_trace)(trace_suppression); - - return True; + int check_stack_accesses = -1; + int exclusive_threshold_ms = -1; + int report_signal_unlocked = -1; + int segment_merging = -1; + int shared_threshold_ms = -1; + int show_confl_seg = -1; + int trace_barrier = -1; + int trace_clientobj = -1; + int trace_cond = -1; + int trace_csw = -1; + int trace_fork_join = -1; + int trace_conflict_set = -1; + int trace_mutex = -1; + int trace_rwlock = -1; + int trace_segment = -1; + int trace_semaphore = -1; + int trace_suppression = -1; + Char* trace_address = 0; + + if VG_BOOL_CLO(arg, "--check-stack-var", check_stack_accesses) {} + else if VG_BOOL_CLO(arg, "--drd-stats", DRD_(s_print_stats)) {} + else if VG_BOOL_CLO(arg,"--report-signal-unlocked",report_signal_unlocked) {} + else if VG_BOOL_CLO(arg, "--segment-merging", segment_merging) {} + else if VG_BOOL_CLO(arg, "--show-confl-seg", show_confl_seg) {} + else if VG_BOOL_CLO(arg, "--show-stack-usage", + DRD_(s_show_stack_usage)) {} + else if VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier) {} + else if VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj) {} + else if VG_BOOL_CLO(arg, "--trace-cond", trace_cond) {} + else if VG_BOOL_CLO(arg, "--trace-conflict-set", trace_conflict_set) {} + else if VG_BOOL_CLO(arg, "--trace-csw", trace_csw) {} + else if VG_BOOL_CLO(arg, "--trace-fork-join", trace_fork_join) {} + else if VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex) {} + else if VG_BOOL_CLO(arg, "--trace-rwlock", trace_rwlock) {} + else if VG_BOOL_CLO(arg, "--trace-segment", trace_segment) {} + else if VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore) {} + else if VG_BOOL_CLO(arg, "--trace-suppr", trace_suppression) {} + else if VG_BOOL_CLO(arg, "--var-info", DRD_(s_var_info)) {} + else if VG_INT_CLO (arg, "--exclusive-threshold", exclusive_threshold_ms) {} + else if VG_INT_CLO (arg, "--shared-threshold", shared_threshold_ms) {} + else if VG_STR_CLO (arg, "--trace-addr", trace_address) {} + else + return VG_(replacement_malloc_process_cmd_line_option)(arg); + + if (check_stack_accesses != -1) + DRD_(set_check_stack_accesses)(check_stack_accesses); + if (exclusive_threshold_ms != -1) + { + DRD_(mutex_set_lock_threshold)(exclusive_threshold_ms); + DRD_(rwlock_set_exclusive_threshold)(exclusive_threshold_ms); + } + if (report_signal_unlocked != -1) + { + DRD_(cond_set_report_signal_unlocked)(report_signal_unlocked); + } + if (shared_threshold_ms != -1) + { + DRD_(rwlock_set_shared_threshold)(shared_threshold_ms); + } + if (segment_merging != -1) + DRD_(thread_set_segment_merging)(segment_merging); + if (show_confl_seg != -1) + DRD_(set_show_conflicting_segments)(show_confl_seg); + if (trace_address) + { + const Addr addr = VG_(strtoll16)(trace_address, 0); + DRD_(start_tracing_address_range)(addr, addr + 1); + } + if (trace_barrier != -1) + DRD_(barrier_set_trace)(trace_barrier); + if (trace_clientobj != -1) + DRD_(clientobj_set_trace)(trace_clientobj); + if (trace_cond != -1) + DRD_(cond_set_trace)(trace_cond); + if (trace_csw != -1) + DRD_(thread_trace_context_switches)(trace_csw); + if (trace_fork_join != -1) + DRD_(thread_set_trace_fork_join)(trace_fork_join); + if (trace_conflict_set != -1) + DRD_(thread_trace_conflict_set)(trace_conflict_set); + if (trace_mutex != -1) + DRD_(mutex_set_trace)(trace_mutex); + if (trace_rwlock != -1) + DRD_(rwlock_set_trace)(trace_rwlock); + if (trace_segment != -1) + DRD_(sg_set_trace)(trace_segment); + if (trace_semaphore != -1) + DRD_(semaphore_set_trace)(trace_semaphore); + if (trace_suppression != -1) + DRD_(suppression_set_trace)(trace_suppression); + + return True; } static void DRD_(print_usage)(void) { - VG_(printf)( + VG_(printf)( " --check-stack-var=yes|no Whether or not to report data races on\n" " stack variables [no].\n" " --exclusive-threshold= Print an error message if any mutex or\n" @@ -192,20 +194,20 @@ static void DRD_(print_usage)(void) " --trace-mutex=yes|no Trace all mutex activity [no].\n" " --trace-rwlock=yes|no Trace all reader-writer lock activity[no].\n" " --trace-semaphore=yes|no Trace all semaphore activity [no].\n" - ); +); VG_(replacement_malloc_print_usage)(); } static void DRD_(print_debug_usage)(void) { - VG_(printf)( + VG_(printf)( " --drd-stats=yes|no Print statistics about DRD activity [no].\n" " --trace-clientobj=yes|no Trace all client object activity [no].\n" " --trace-csw=yes|no Trace all scheduler context switches [no].\n" " --trace-conflict-set=yes|no Trace all conflict set updates [no].\n" " --trace-segment=yes|no Trace segment actions [no].\n" " --trace-suppr=yes|no Trace all address suppression actions [no].\n" - ); +); VG_(replacement_malloc_print_debug_usage)(); } @@ -220,10 +222,10 @@ static void drd_pre_mem_read(const CorePart part, const Addr a, const SizeT size) { - if (size > 0) - { - DRD_(trace_load)(a, size); - } + if (size > 0) + { + DRD_(trace_load)(a, size); + } } static void drd_pre_mem_read_asciiz(const CorePart part, @@ -231,22 +233,22 @@ static void drd_pre_mem_read_asciiz(const CorePart part, Char* const s, const Addr a) { - const char* p = (void*)a; - SizeT size = 0; - - /* Note: the expression '*p' reads client memory and may crash if the */ - /* client provided an invalid pointer ! */ - while (*p) - { - p++; - size++; - } - // To do: find out what a reasonable upper limit on 'size' is. - tl_assert(size < 4096); - if (size > 0) - { - DRD_(trace_load)(a, size); - } + const char* p = (void*)a; + SizeT size = 0; + + /* Note: the expression '*p' reads client memory and may crash if the */ + /* client provided an invalid pointer ! */ + while (*p) + { + p++; + size++; + } + // To do: find out what a reasonable upper limit on 'size' is. + tl_assert(size < 4096); + if (size > 0) + { + DRD_(trace_load)(a, size); + } } static void drd_post_mem_write(const CorePart part, @@ -254,62 +256,62 @@ static void drd_post_mem_write(const CorePart part, const Addr a, const SizeT size) { - DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); - if (size > 0) - { - DRD_(trace_store)(a, size); - } + DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); + if (size > 0) + { + DRD_(trace_store)(a, size); + } } static __inline__ void drd_start_using_mem(const Addr a1, const SizeT len) { - tl_assert(a1 < a1 + len); + tl_assert(a1 < a1 + len); - if (UNLIKELY(DRD_(any_address_is_traced)())) - { - DRD_(trace_mem_access)(a1, len, eStart); - } + if (UNLIKELY(DRD_(any_address_is_traced)())) + { + DRD_(trace_mem_access)(a1, len, eStart); + } } static void drd_start_using_mem_w_ecu(const Addr a1, const SizeT len, UInt ec_uniq) { - drd_start_using_mem(a1, len); + drd_start_using_mem(a1, len); } static void drd_start_using_mem_w_tid(const Addr a1, const SizeT len, ThreadId tid) { - drd_start_using_mem(a1, len); + drd_start_using_mem(a1, len); } static __inline__ void drd_stop_using_mem(const Addr a1, const SizeT len, const Bool is_stack_mem) { - const Addr a2 = a1 + len; - - tl_assert(a1 < a2); - - if (UNLIKELY(DRD_(any_address_is_traced)())) - { - DRD_(trace_mem_access)(a1, len, eEnd); - } - if (! is_stack_mem || DRD_(get_check_stack_accesses)()) - { - DRD_(thread_stop_using_mem)(a1, a2); - DRD_(clientobj_stop_using_mem)(a1, a2); - DRD_(suppression_stop_using_mem)(a1, a2); - } + const Addr a2 = a1 + len; + + tl_assert(a1 < a2); + + if (UNLIKELY(DRD_(any_address_is_traced)())) + { + DRD_(trace_mem_access)(a1, len, eEnd); + } + if (! is_stack_mem || DRD_(get_check_stack_accesses)()) + { + DRD_(thread_stop_using_mem)(a1, a2); + DRD_(clientobj_stop_using_mem)(a1, a2); + DRD_(suppression_stop_using_mem)(a1, a2); + } } static __inline__ void drd_stop_using_nonstack_mem(const Addr a1, const SizeT len) { - drd_stop_using_mem(a1, len, False); + drd_stop_using_mem(a1, len, False); } /** @@ -318,9 +320,9 @@ void drd_stop_using_nonstack_mem(const Addr a1, const SizeT len) */ void DRD_(clean_memory)(const Addr a1, const SizeT len) { - const Bool is_stack_memory = DRD_(thread_address_on_any_stack)(a1); - drd_stop_using_mem(a1, len, is_stack_memory); - drd_start_using_mem(a1, len); + const Bool is_stack_memory = DRD_(thread_address_on_any_stack)(a1); + drd_stop_using_mem(a1, len, is_stack_memory); + drd_start_using_mem(a1, len); } /** @@ -335,41 +337,41 @@ void DRD_(clean_memory)(const Addr a1, const SizeT len) */ static void DRD_(suppress_relocation_conflicts)(const Addr a, const SizeT len) { - const DebugInfo* di; + const DebugInfo* di; #if 0 - VG_(printf)("Evaluating range @ 0x%lx size %ld\n", a, len); + VG_(printf)("Evaluating range @ 0x%lx size %ld\n", a, len); #endif - for (di = VG_(next_seginfo)(0); di; di = VG_(next_seginfo)(di)) - { - Addr avma; - SizeT size; + for (di = VG_(next_seginfo)(0); di; di = VG_(next_seginfo)(di)) + { + Addr avma; + SizeT size; - avma = VG_(seginfo_get_plt_avma)(di); - size = VG_(seginfo_get_plt_size)(di); - tl_assert((avma && size) || (avma == 0 && size == 0)); - if (size > 0) - { + avma = VG_(seginfo_get_plt_avma)(di); + size = VG_(seginfo_get_plt_size)(di); + tl_assert((avma && size) || (avma == 0 && size == 0)); + if (size > 0) + { #if 0 - VG_(printf)("Suppressing .plt @ 0x%lx size %ld\n", avma, size); + VG_(printf)("Suppressing .plt @ 0x%lx size %ld\n", avma, size); #endif - tl_assert(VG_(seginfo_sect_kind)(NULL, 0, avma) == Vg_SectPLT); - DRD_(start_suppression)(avma, avma + size, ".plt"); - } - - avma = VG_(seginfo_get_gotplt_avma)(di); - size = VG_(seginfo_get_gotplt_size)(di); - tl_assert((avma && size) || (avma == 0 && size == 0)); - if (size > 0) - { + tl_assert(VG_(seginfo_sect_kind)(NULL, 0, avma) == Vg_SectPLT); + DRD_(start_suppression)(avma, avma + size, ".plt"); + } + + avma = VG_(seginfo_get_gotplt_avma)(di); + size = VG_(seginfo_get_gotplt_size)(di); + tl_assert((avma && size) || (avma == 0 && size == 0)); + if (size > 0) + { #if 0 - VG_(printf)("Suppressing .got.plt @ 0x%lx size %ld\n", avma, size); + VG_(printf)("Suppressing .got.plt @ 0x%lx size %ld\n", avma, size); #endif - tl_assert(VG_(seginfo_sect_kind)(NULL, 0, avma) == Vg_SectGOTPLT); - DRD_(start_suppression)(avma, avma + size, ".gotplt"); - } - } + tl_assert(VG_(seginfo_sect_kind)(NULL, 0, avma) == Vg_SectGOTPLT); + DRD_(start_suppression)(avma, avma + size, ".gotplt"); + } + } } static @@ -377,11 +379,11 @@ void drd_start_using_mem_w_perms(const Addr a, const SizeT len, const Bool rr, const Bool ww, const Bool xx, ULong di_handle) { - DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); + DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); - drd_start_using_mem(a, len); + drd_start_using_mem(a, len); - DRD_(suppress_relocation_conflicts)(a, len); + DRD_(suppress_relocation_conflicts)(a, len); } /* Called by the core when the stack of a thread grows, to indicate that */ @@ -390,10 +392,10 @@ void drd_start_using_mem_w_perms(const Addr a, const SizeT len, static __inline__ void drd_start_using_mem_stack(const Addr a, const SizeT len) { - DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(), - a - VG_STACK_REDZONE_SZB); - drd_start_using_mem(a - VG_STACK_REDZONE_SZB, - len + VG_STACK_REDZONE_SZB); + DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(), + a - VG_STACK_REDZONE_SZB); + drd_start_using_mem(a - VG_STACK_REDZONE_SZB, + len + VG_STACK_REDZONE_SZB); } /* Called by the core when the stack of a thread shrinks, to indicate that */ @@ -402,41 +404,49 @@ void drd_start_using_mem_stack(const Addr a, const SizeT len) static __inline__ void drd_stop_using_mem_stack(const Addr a, const SizeT len) { - DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(), - a + len - VG_STACK_REDZONE_SZB); - drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB, - True); + DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(), + a + len - VG_STACK_REDZONE_SZB); + drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB, + True); } -static void drd_start_using_mem_stack_signal( - const Addr a, const SizeT len, - ThreadId tid_for_whom_the_signal_frame_is_being_constructed) +/** + * Callback function called by the Valgrind core before a stack area is + * being used by a signal handler. + * + * @param[in] a Start of address range. + * @param[in] len Address range length. + * @param[in] tid Valgrind thread ID for whom the signal frame is being + * constructed. + */ +static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len, + ThreadId tid) { - DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); - drd_start_using_mem(a, len); + DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); + drd_start_using_mem(a, len); } static void drd_stop_using_mem_stack_signal(Addr a, SizeT len) { - drd_stop_using_mem(a, len, True); + drd_stop_using_mem(a, len, True); } static void drd_pre_thread_create(const ThreadId creator, const ThreadId created) { - const DrdThreadId drd_creator = DRD_(VgThreadIdToDrdThreadId)(creator); - tl_assert(created != VG_INVALID_THREADID); - DRD_(thread_pre_create)(drd_creator, created); - if (DRD_(IsValidDrdThreadId)(drd_creator)) - { - DRD_(thread_new_segment)(drd_creator); - } - if (DRD_(thread_get_trace_fork_join)()) - { - VG_(message)(Vg_DebugMsg, - "drd_pre_thread_create creator = %d/%d, created = %d", - creator, drd_creator, created); - } + const DrdThreadId drd_creator = DRD_(VgThreadIdToDrdThreadId)(creator); + tl_assert(created != VG_INVALID_THREADID); + DRD_(thread_pre_create)(drd_creator, created); + if (DRD_(IsValidDrdThreadId)(drd_creator)) + { + DRD_(thread_new_segment)(drd_creator); + } + if (DRD_(thread_get_trace_fork_join)()) + { + VG_(message)(Vg_DebugMsg, + "drd_pre_thread_create creator = %d/%d, created = %d", + creator, drd_creator, created); + } } /* Called by Valgrind's core before any loads or stores are performed on */ @@ -445,69 +455,69 @@ void drd_pre_thread_create(const ThreadId creator, const ThreadId created) static void drd_post_thread_create(const ThreadId vg_created) { - DrdThreadId drd_created; - - tl_assert(vg_created != VG_INVALID_THREADID); - - drd_created = DRD_(thread_post_create)(vg_created); - if (DRD_(thread_get_trace_fork_join)()) - { - VG_(message)(Vg_DebugMsg, - "drd_post_thread_create created = %d/%d", - vg_created, drd_created); - } - if (! DRD_(get_check_stack_accesses)()) - { - DRD_(start_suppression)(DRD_(thread_get_stack_max)(drd_created) - - DRD_(thread_get_stack_size)(drd_created), - DRD_(thread_get_stack_max)(drd_created), - "stack"); - } + DrdThreadId drd_created; + + tl_assert(vg_created != VG_INVALID_THREADID); + + drd_created = DRD_(thread_post_create)(vg_created); + if (DRD_(thread_get_trace_fork_join)()) + { + VG_(message)(Vg_DebugMsg, + "drd_post_thread_create created = %d/%d", + vg_created, drd_created); + } + if (! DRD_(get_check_stack_accesses)()) + { + DRD_(start_suppression)(DRD_(thread_get_stack_max)(drd_created) + - DRD_(thread_get_stack_size)(drd_created), + DRD_(thread_get_stack_max)(drd_created), + "stack"); + } } /* Called after a thread has performed its last memory access. */ static void drd_thread_finished(ThreadId vg_tid) { - DrdThreadId drd_tid; - - tl_assert(VG_(get_running_tid)() == vg_tid); - - drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); - if (DRD_(thread_get_trace_fork_join)()) - { - VG_(message)(Vg_DebugMsg, - "drd_thread_finished tid = %d/%d%s", - vg_tid, - drd_tid, - DRD_(thread_get_joinable)(drd_tid) - ? "" - : " (which is a detached thread)"); - } - if (DRD_(s_show_stack_usage)) - { - const SizeT stack_size = DRD_(thread_get_stack_size)(drd_tid); - const SizeT used_stack - = (DRD_(thread_get_stack_max)(drd_tid) - - DRD_(thread_get_stack_min_min)(drd_tid)); - VG_(message)(Vg_UserMsg, - "thread %d/%d%s finished and used %ld bytes out of %ld" - " on its stack. Margin: %ld bytes.", - vg_tid, - drd_tid, - DRD_(thread_get_joinable)(drd_tid) - ? "" - : " (which is a detached thread)", - used_stack, - stack_size, - stack_size - used_stack); - - } - drd_stop_using_mem(DRD_(thread_get_stack_min)(drd_tid), - DRD_(thread_get_stack_max)(drd_tid) - - DRD_(thread_get_stack_min)(drd_tid), - True); - DRD_(thread_stop_recording)(drd_tid); - DRD_(thread_finished)(drd_tid); + DrdThreadId drd_tid; + + tl_assert(VG_(get_running_tid)() == vg_tid); + + drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); + if (DRD_(thread_get_trace_fork_join)()) + { + VG_(message)(Vg_DebugMsg, + "drd_thread_finished tid = %d/%d%s", + vg_tid, + drd_tid, + DRD_(thread_get_joinable)(drd_tid) + ? "" + : " (which is a detached thread)"); + } + if (DRD_(s_show_stack_usage)) + { + const SizeT stack_size = DRD_(thread_get_stack_size)(drd_tid); + const SizeT used_stack + = (DRD_(thread_get_stack_max)(drd_tid) + - DRD_(thread_get_stack_min_min)(drd_tid)); + VG_(message)(Vg_UserMsg, + "thread %d/%d%s finished and used %ld bytes out of %ld" + " on its stack. Margin: %ld bytes.", + vg_tid, + drd_tid, + DRD_(thread_get_joinable)(drd_tid) + ? "" + : " (which is a detached thread)", + used_stack, + stack_size, + stack_size - used_stack); + + } + drd_stop_using_mem(DRD_(thread_get_stack_min)(drd_tid), + DRD_(thread_get_stack_max)(drd_tid) + - DRD_(thread_get_stack_min)(drd_tid), + True); + DRD_(thread_stop_recording)(drd_tid); + DRD_(thread_finished)(drd_tid); } // @@ -516,124 +526,124 @@ static void drd_thread_finished(ThreadId vg_tid) static void DRD_(post_clo_init)(void) { -# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ - || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) - /* fine */ +# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ + || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) + /* fine */ # else - VG_(printf)("\nWARNING: DRD has only been tested on Linux.\n\n"); + VG_(printf)("\nWARNING: DRD has only been tested on Linux.\n\n"); # endif - if (DRD_(s_var_info)) - { - VG_(needs_var_info)(); - } + if (DRD_(s_var_info)) + { + VG_(needs_var_info)(); + } } static void drd_start_client_code(const ThreadId tid, const ULong bbs_done) { - tl_assert(tid == VG_(get_running_tid)()); - DRD_(thread_set_vg_running_tid)(tid); + tl_assert(tid == VG_(get_running_tid)()); + DRD_(thread_set_vg_running_tid)(tid); } static void DRD_(fini)(Int exitcode) { - // thread_print_all(); - if (VG_(clo_verbosity) > 1 || DRD_(s_print_stats)) - { - ULong update_conflict_set_count; - ULong dsnsc; - ULong dscvc; - - update_conflict_set_count - = DRD_(thread_get_update_conflict_set_count)(&dsnsc, &dscvc); - - VG_(message)(Vg_UserMsg, - " thread: %lld context switches" - " / %lld updates of the conflict set", - DRD_(thread_get_context_switch_count)(), - update_conflict_set_count); - VG_(message)(Vg_UserMsg, - " (%lld new sg + %lld combine vc + %lld csw).", - dsnsc, - dscvc, - update_conflict_set_count - dsnsc - dscvc); - VG_(message)(Vg_UserMsg, - " segments: created %lld segments, max %lld alive," - " %lld discard points.", - DRD_(sg_get_segments_created_count)(), - DRD_(sg_get_max_segments_alive_count)(), - DRD_(thread_get_discard_ordered_segments_count)()); - VG_(message)(Vg_UserMsg, - " (%lld m, %lld rw, %lld s, %lld b)", - DRD_(get_mutex_segment_creation_count)(), - DRD_(get_rwlock_segment_creation_count)(), - DRD_(get_semaphore_segment_creation_count)(), - DRD_(get_barrier_segment_creation_count)()); - VG_(message)(Vg_UserMsg, - " bitmaps: %lld level 1 / %lld level 2 bitmap refs", - DRD_(bm_get_bitmap_creation_count)(), - DRD_(bm_get_bitmap2_node_creation_count)()); - VG_(message)(Vg_UserMsg, - " and %lld level 2 bitmaps were allocated.", - DRD_(bm_get_bitmap2_creation_count)()); - VG_(message)(Vg_UserMsg, - " mutex: %lld non-recursive lock/unlock events.", - DRD_(get_mutex_lock_count)()); - DRD_(print_malloc_stats)(); - } + // thread_print_all(); + if (VG_(clo_verbosity) > 1 || DRD_(s_print_stats)) + { + ULong update_conflict_set_count; + ULong dsnsc; + ULong dscvc; + + update_conflict_set_count + = DRD_(thread_get_update_conflict_set_count)(&dsnsc, &dscvc); + + VG_(message)(Vg_UserMsg, + " thread: %lld context switches" + " / %lld updates of the conflict set", + DRD_(thread_get_context_switch_count)(), + update_conflict_set_count); + VG_(message)(Vg_UserMsg, + " (%lld new sg + %lld combine vc + %lld csw).", + dsnsc, + dscvc, + update_conflict_set_count - dsnsc - dscvc); + VG_(message)(Vg_UserMsg, + " segments: created %lld segments, max %lld alive," + " %lld discard points.", + DRD_(sg_get_segments_created_count)(), + DRD_(sg_get_max_segments_alive_count)(), + DRD_(thread_get_discard_ordered_segments_count)()); + VG_(message)(Vg_UserMsg, + " (%lld m, %lld rw, %lld s, %lld b)", + DRD_(get_mutex_segment_creation_count)(), + DRD_(get_rwlock_segment_creation_count)(), + DRD_(get_semaphore_segment_creation_count)(), + DRD_(get_barrier_segment_creation_count)()); + VG_(message)(Vg_UserMsg, + " bitmaps: %lld level 1 / %lld level 2 bitmap refs", + DRD_(bm_get_bitmap_creation_count)(), + DRD_(bm_get_bitmap2_node_creation_count)()); + VG_(message)(Vg_UserMsg, + " and %lld level 2 bitmaps were allocated.", + DRD_(bm_get_bitmap2_creation_count)()); + VG_(message)(Vg_UserMsg, + " mutex: %lld non-recursive lock/unlock events.", + DRD_(get_mutex_lock_count)()); + DRD_(print_malloc_stats)(); + } } static void drd_pre_clo_init(void) { - // Basic tool stuff. - - VG_(details_name) ("drd"); - VG_(details_version) (NULL); - VG_(details_description) ("a thread error detector"); - VG_(details_copyright_author)("Copyright (C) 2006-2009, and GNU GPL'd," - " by Bart Van Assche."); - VG_(details_bug_reports_to) (VG_BUGS_TO); - - VG_(basic_tool_funcs) (DRD_(post_clo_init), - DRD_(instrument), - DRD_(fini)); - - // Command line stuff. - VG_(needs_command_line_options)(DRD_(process_cmd_line_option), - DRD_(print_usage), - DRD_(print_debug_usage)); - - // Error handling. - DRD_(register_error_handlers)(); - - // Core event tracking. - VG_(track_pre_mem_read) (drd_pre_mem_read); - VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz); - VG_(track_post_mem_write) (drd_post_mem_write); - VG_(track_new_mem_brk) (drd_start_using_mem_w_tid); - VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms); - VG_(track_new_mem_stack) (drd_start_using_mem_stack); - VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal); - VG_(track_new_mem_startup) (drd_start_using_mem_w_perms); - VG_(track_die_mem_brk) (drd_stop_using_nonstack_mem); - VG_(track_die_mem_munmap) (drd_stop_using_nonstack_mem); - VG_(track_die_mem_stack) (drd_stop_using_mem_stack); - VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal); - VG_(track_start_client_code) (drd_start_client_code); - VG_(track_pre_thread_ll_create) (drd_pre_thread_create); - VG_(track_pre_thread_first_insn)(drd_post_thread_create); - VG_(track_pre_thread_ll_exit) (drd_thread_finished); - - // Other stuff. - DRD_(register_malloc_wrappers)(drd_start_using_mem_w_ecu, - drd_stop_using_nonstack_mem); - - DRD_(clientreq_init)(); - - DRD_(suppression_init)(); - - DRD_(clientobj_init)(); + // Basic tool stuff. + + VG_(details_name) ("drd"); + VG_(details_version) (NULL); + VG_(details_description) ("a thread error detector"); + VG_(details_copyright_author)("Copyright (C) 2006-2009, and GNU GPL'd," + " by Bart Van Assche."); + VG_(details_bug_reports_to) (VG_BUGS_TO); + + VG_(basic_tool_funcs) (DRD_(post_clo_init), + DRD_(instrument), + DRD_(fini)); + + // Command line stuff. + VG_(needs_command_line_options)(DRD_(process_cmd_line_option), + DRD_(print_usage), + DRD_(print_debug_usage)); + + // Error handling. + DRD_(register_error_handlers)(); + + // Core event tracking. + VG_(track_pre_mem_read) (drd_pre_mem_read); + VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz); + VG_(track_post_mem_write) (drd_post_mem_write); + VG_(track_new_mem_brk) (drd_start_using_mem_w_tid); + VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms); + VG_(track_new_mem_stack) (drd_start_using_mem_stack); + VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal); + VG_(track_new_mem_startup) (drd_start_using_mem_w_perms); + VG_(track_die_mem_brk) (drd_stop_using_nonstack_mem); + VG_(track_die_mem_munmap) (drd_stop_using_nonstack_mem); + VG_(track_die_mem_stack) (drd_stop_using_mem_stack); + VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal); + VG_(track_start_client_code) (drd_start_client_code); + VG_(track_pre_thread_ll_create) (drd_pre_thread_create); + VG_(track_pre_thread_first_insn)(drd_post_thread_create); + VG_(track_pre_thread_ll_exit) (drd_thread_finished); + + // Other stuff. + DRD_(register_malloc_wrappers)(drd_start_using_mem_w_ecu, + drd_stop_using_nonstack_mem); + + DRD_(clientreq_init)(); + + DRD_(suppression_init)(); + + DRD_(clientobj_init)(); } diff --git a/drd/drd_malloc_wrappers.c b/drd/drd_malloc_wrappers.c index 086f82f70e..62da58ec03 100644 --- a/drd/drd_malloc_wrappers.c +++ b/drd/drd_malloc_wrappers.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -40,10 +41,10 @@ /* Local type definitions. */ typedef struct _DRD_Chunk { - struct _DRD_Chunk* next; - Addr data; // ptr to actual block - SizeT size : (sizeof(UWord)*8)-2; //size requested; 30 or 62 bits - ExeContext* where; // where it was allocated + struct _DRD_Chunk* next; + Addr data; // ptr to actual block + SizeT size : (sizeof(UWord)*8)-2; //size requested; 30 or 62 bits + ExeContext* where; // where it was allocated } DRD_Chunk; @@ -66,13 +67,13 @@ static VgHashTable DRD_(s_malloc_list) = NULL; /** Allocate its shadow chunk, put it on the appropriate list. */ static DRD_Chunk* DRD_(create_chunk)(ThreadId tid, Addr p, SizeT size) { - DRD_Chunk* mc = VG_(malloc)("drd.malloc_wrappers.cDC.1", - sizeof(DRD_Chunk)); - mc->data = p; - mc->size = size; - mc->where = VG_(record_ExeContext)(tid, 0); + DRD_Chunk* mc = VG_(malloc)("drd.malloc_wrappers.cDC.1", + sizeof(DRD_Chunk)); + mc->data = p; + mc->size = size; + mc->where = VG_(record_ExeContext)(tid, 0); - return mc; + return mc; } /*------------------------------------------------------------*/ @@ -86,161 +87,163 @@ void* DRD_(new_block)(ThreadId tid, SizeT size, SizeT align, Bool is_zeroed) { - Addr p; + Addr p; - DRD_(s_cmalloc_n_mallocs) ++; + DRD_(s_cmalloc_n_mallocs) ++; - // Allocate and zero - p = (Addr)VG_(cli_malloc)(align, size); - if (!p) { - return NULL; - } - if (is_zeroed) VG_(memset)((void*)p, 0, size); - DRD_(s_start_using_mem_callback)(p, p + size, 0/*ec_uniq*/); + // Allocate and zero + p = (Addr)VG_(cli_malloc)(align, size); + if (!p) { + return NULL; + } + if (is_zeroed) VG_(memset)((void*)p, 0, size); + DRD_(s_start_using_mem_callback)(p, p + size, 0/*ec_uniq*/); - // Only update this stat if allocation succeeded. - DRD_(s_cmalloc_bs_mallocd) += size; + // Only update this stat if allocation succeeded. + DRD_(s_cmalloc_bs_mallocd) += size; - VG_(HT_add_node)(DRD_(s_malloc_list), DRD_(create_chunk)(tid, p, size)); + VG_(HT_add_node)(DRD_(s_malloc_list), DRD_(create_chunk)(tid, p, size)); - return (void*)p; + return (void*)p; } static void* DRD_(malloc)(ThreadId tid, SizeT n) { - return DRD_(new_block)(tid, n, VG_(clo_alignment), /*is_zeroed*/False); + return DRD_(new_block)(tid, n, VG_(clo_alignment), /*is_zeroed*/False); } static void* DRD_(memalign)(ThreadId tid, SizeT align, SizeT n) { - return DRD_(new_block)(tid, n, align, /*is_zeroed*/False); + return DRD_(new_block)(tid, n, align, /*is_zeroed*/False); } static void* DRD_(calloc)(ThreadId tid, SizeT nmemb, SizeT size1) { - return DRD_(new_block)(tid, nmemb*size1, VG_(clo_alignment), - /*is_zeroed*/True); + return DRD_(new_block)(tid, nmemb*size1, VG_(clo_alignment), + /*is_zeroed*/True); } static __inline__ void DRD_(handle_free)(ThreadId tid, Addr p) { - DRD_Chunk* mc; - - DRD_(s_cmalloc_n_frees)++; - - mc = VG_(HT_remove)(DRD_(s_malloc_list), (UWord)p); - if (mc == NULL) - { - tl_assert(0); - } - else - { - tl_assert(p == mc->data); - if (mc->size > 0) - DRD_(s_stop_using_mem_callback)(mc->data, mc->size); - VG_(cli_free)((void*)p); - VG_(free)(mc); - } + DRD_Chunk* mc; + + DRD_(s_cmalloc_n_frees)++; + + mc = VG_(HT_remove)(DRD_(s_malloc_list), (UWord)p); + if (mc == NULL) + { + tl_assert(0); + } + else + { + tl_assert(p == mc->data); + if (mc->size > 0) + DRD_(s_stop_using_mem_callback)(mc->data, mc->size); + VG_(cli_free)((void*)p); + VG_(free)(mc); + } } static void DRD_(free)(ThreadId tid, void* p) { - DRD_(handle_free)(tid, (Addr)p); + DRD_(handle_free)(tid, (Addr)p); } static void* DRD_(realloc)(ThreadId tid, void* p_old, SizeT new_size) { - DRD_Chunk* mc; - void* p_new; - SizeT old_size; - - DRD_(s_cmalloc_n_frees) ++; - DRD_(s_cmalloc_n_mallocs) ++; - DRD_(s_cmalloc_bs_mallocd) += new_size; - - /* Remove the old block */ - mc = VG_(HT_remove)(DRD_(s_malloc_list), (UWord)p_old); - if (mc == NULL) { - tl_assert(0); - return NULL; - } - - old_size = mc->size; - - if (old_size == new_size) - { - /* size unchanged */ - mc->where = VG_(record_ExeContext)(tid, 0); - p_new = p_old; + DRD_Chunk* mc; + void* p_new; + SizeT old_size; + + DRD_(s_cmalloc_n_frees) ++; + DRD_(s_cmalloc_n_mallocs) ++; + DRD_(s_cmalloc_bs_mallocd) += new_size; + + /* Remove the old block */ + mc = VG_(HT_remove)(DRD_(s_malloc_list), (UWord)p_old); + if (mc == NULL) { + tl_assert(0); + return NULL; + } + + old_size = mc->size; + + if (old_size == new_size) + { + /* size unchanged */ + mc->where = VG_(record_ExeContext)(tid, 0); + p_new = p_old; - } - else if (old_size > new_size) - { - /* new size is smaller */ - DRD_(s_stop_using_mem_callback)(mc->data + new_size, old_size); - mc->size = new_size; - mc->where = VG_(record_ExeContext)(tid, 0); - p_new = p_old; - - } - else - { - /* new size is bigger */ - /* Get new memory */ - const Addr a_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size); - - if (a_new) - { - /* Copy from old to new */ - VG_(memcpy)((void*)a_new, p_old, mc->size); - - /* Free old memory */ - DRD_(s_stop_using_mem_callback)(mc->data, mc->size); - VG_(free)(mc); - - // Allocate a new chunk. - mc = DRD_(create_chunk)(tid, a_new, new_size); - DRD_(s_start_using_mem_callback)(a_new, a_new + new_size, 0/*ec_uniq*/); - } - else - { - /* Allocation failed -- leave original block untouched. */ - } - - p_new = (void*)a_new; - } - - // Now insert the new mc (with a possibly new 'data' field) into - // malloc_list. If this realloc() did not increase the memory size, we - // will have removed and then re-added mc unnecessarily. But that's ok - // because shrinking a block with realloc() is (presumably) much rarer - // than growing it, and this way simplifies the growing case. - VG_(HT_add_node)(DRD_(s_malloc_list), mc); - - return p_new; + } + else if (old_size > new_size) + { + /* new size is smaller */ + DRD_(s_stop_using_mem_callback)(mc->data + new_size, old_size); + mc->size = new_size; + mc->where = VG_(record_ExeContext)(tid, 0); + p_new = p_old; + + } + else + { + /* new size is bigger */ + /* Get new memory */ + const Addr a_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size); + + if (a_new) + { + /* Copy from old to new */ + VG_(memcpy)((void*)a_new, p_old, mc->size); + + /* Free old memory */ + DRD_(s_stop_using_mem_callback)(mc->data, mc->size); + VG_(free)(mc); + + // Allocate a new chunk. + mc = DRD_(create_chunk)(tid, a_new, new_size); + DRD_(s_start_using_mem_callback)(a_new, a_new + new_size, + 0/*ec_uniq*/); + } + else + { + /* Allocation failed -- leave original block untouched. */ + } + + p_new = (void*)a_new; + } + + // Now insert the new mc (with a possibly new 'data' field) into + // malloc_list. If this realloc() did not increase the memory size, we + // will have removed and then re-added mc unnecessarily. But that's ok + // because shrinking a block with realloc() is (presumably) much rarer + // than growing it, and this way simplifies the growing case. + VG_(HT_add_node)(DRD_(s_malloc_list), mc); + + return p_new; } static void* DRD_(__builtin_new)(ThreadId tid, SizeT n) { - void* const result = DRD_(new_block)(tid, n, VG_(clo_alignment), /*is_zeroed*/False); - //VG_(message)(Vg_DebugMsg, "__builtin_new(%d, %d) = %p", tid, n, result); - return result; + void* const result = DRD_(new_block)(tid, n, VG_(clo_alignment), + /*is_zeroed*/False); + //VG_(message)(Vg_DebugMsg, "__builtin_new(%d, %d) = %p", tid, n, result); + return result; } static void DRD_(__builtin_delete)(ThreadId tid, void* p) { - //VG_(message)(Vg_DebugMsg, "__builtin_delete(%d, %p)", tid, p); - DRD_(handle_free)(tid, (Addr)p); + //VG_(message)(Vg_DebugMsg, "__builtin_delete(%d, %p)", tid, p); + DRD_(handle_free)(tid, (Addr)p); } static void* DRD_(__builtin_vec_new)(ThreadId tid, SizeT n) { - return DRD_(new_block)(tid, n, VG_(clo_alignment), /*is_zeroed*/False); + return DRD_(new_block)(tid, n, VG_(clo_alignment), /*is_zeroed*/False); } static void DRD_(__builtin_vec_delete)(ThreadId tid, void* p) { - DRD_(handle_free)(tid, (Addr)p); + DRD_(handle_free)(tid, (Addr)p); } static SizeT DRD_(malloc_usable_size) ( ThreadId tid, void* p ) @@ -255,26 +258,26 @@ static SizeT DRD_(malloc_usable_size) ( ThreadId tid, void* p ) void DRD_(register_malloc_wrappers)(const StartUsingMem start_callback, const StopUsingMem stop_callback) { - tl_assert(DRD_(s_malloc_list) == 0); - DRD_(s_malloc_list) = VG_(HT_construct)("drd_malloc_list"); // a big prime - tl_assert(DRD_(s_malloc_list) != 0); - tl_assert(start_callback); - tl_assert(stop_callback); - - DRD_(s_start_using_mem_callback) = start_callback; - DRD_(s_stop_using_mem_callback) = stop_callback; - - VG_(needs_malloc_replacement)(DRD_(malloc), - DRD_(__builtin_new), - DRD_(__builtin_vec_new), - DRD_(memalign), - DRD_(calloc), - DRD_(free), - DRD_(__builtin_delete), - DRD_(__builtin_vec_delete), - DRD_(realloc), - DRD_(malloc_usable_size), - 0); + tl_assert(DRD_(s_malloc_list) == 0); + DRD_(s_malloc_list) = VG_(HT_construct)("drd_malloc_list"); // a big prime + tl_assert(DRD_(s_malloc_list) != 0); + tl_assert(start_callback); + tl_assert(stop_callback); + + DRD_(s_start_using_mem_callback) = start_callback; + DRD_(s_stop_using_mem_callback) = stop_callback; + + VG_(needs_malloc_replacement)(DRD_(malloc), + DRD_(__builtin_new), + DRD_(__builtin_vec_new), + DRD_(memalign), + DRD_(calloc), + DRD_(free), + DRD_(__builtin_delete), + DRD_(__builtin_vec_delete), + DRD_(realloc), + DRD_(malloc_usable_size), + 0); } Bool DRD_(heap_addrinfo)(Addr const a, @@ -282,24 +285,24 @@ Bool DRD_(heap_addrinfo)(Addr const a, SizeT* const size, ExeContext** const where) { - DRD_Chunk* mc; - - tl_assert(data); - tl_assert(size); - tl_assert(where); - - VG_(HT_ResetIter)(DRD_(s_malloc_list)); - while ((mc = VG_(HT_Next)(DRD_(s_malloc_list)))) - { - if (mc->data <= a && a < mc->data + mc->size) - { - *data = mc->data; - *size = mc->size; - *where = mc->where; - return True; - } - } - return False; + DRD_Chunk* mc; + + tl_assert(data); + tl_assert(size); + tl_assert(where); + + VG_(HT_ResetIter)(DRD_(s_malloc_list)); + while ((mc = VG_(HT_Next)(DRD_(s_malloc_list)))) + { + if (mc->data <= a && a < mc->data + mc->size) + { + *data = mc->data; + *size = mc->size; + *where = mc->where; + return True; + } + } + return False; } /*------------------------------------------------------------*/ @@ -308,32 +311,32 @@ Bool DRD_(heap_addrinfo)(Addr const a, void DRD_(print_malloc_stats)(void) { - DRD_Chunk* mc; - SizeT nblocks = 0; - SizeT nbytes = 0; + DRD_Chunk* mc; + SizeT nblocks = 0; + SizeT nbytes = 0; - if (VG_(clo_verbosity) == 0) - return; - if (VG_(clo_xml)) - return; - - /* Count memory still in use. */ - VG_(HT_ResetIter)(DRD_(s_malloc_list)); - while ((mc = VG_(HT_Next)(DRD_(s_malloc_list)))) - { - nblocks++; - nbytes += mc->size; - } - - VG_(message)(Vg_DebugMsg, - "malloc/free: in use at exit: %lu bytes in %lu blocks.", - nbytes, nblocks); - VG_(message)(Vg_DebugMsg, - "malloc/free: %lu allocs, %lu frees, %lu bytes allocated.", - DRD_(s_cmalloc_n_mallocs), - DRD_(s_cmalloc_n_frees), DRD_(s_cmalloc_bs_mallocd)); - if (VG_(clo_verbosity) > 1) - VG_(message)(Vg_DebugMsg, " "); + if (VG_(clo_verbosity) == 0) + return; + if (VG_(clo_xml)) + return; + + /* Count memory still in use. */ + VG_(HT_ResetIter)(DRD_(s_malloc_list)); + while ((mc = VG_(HT_Next)(DRD_(s_malloc_list)))) + { + nblocks++; + nbytes += mc->size; + } + + VG_(message)(Vg_DebugMsg, + "malloc/free: in use at exit: %lu bytes in %lu blocks.", + nbytes, nblocks); + VG_(message)(Vg_DebugMsg, + "malloc/free: %lu allocs, %lu frees, %lu bytes allocated.", + DRD_(s_cmalloc_n_mallocs), + DRD_(s_cmalloc_n_frees), DRD_(s_cmalloc_bs_mallocd)); + if (VG_(clo_verbosity) > 1) + VG_(message)(Vg_DebugMsg, " "); } /*--------------------------------------------------------------------*/ diff --git a/drd/drd_malloc_wrappers.h b/drd/drd_malloc_wrappers.h index 0c35ed9d51..da2d20361d 100644 --- a/drd/drd_malloc_wrappers.h +++ b/drd/drd_malloc_wrappers.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. diff --git a/drd/drd_mutex.c b/drd/drd_mutex.c index fecb35585f..98de75e76f 100644 --- a/drd/drd_mutex.c +++ b/drd/drd_mutex.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -55,163 +56,163 @@ static UInt s_mutex_lock_threshold_ms = 1000 * 1000; void DRD_(mutex_set_trace)(const Bool trace_mutex) { - tl_assert(!! trace_mutex == trace_mutex); - s_trace_mutex = trace_mutex; + tl_assert(!! trace_mutex == trace_mutex); + s_trace_mutex = trace_mutex; } void DRD_(mutex_set_lock_threshold)(const UInt lock_threshold_ms) { - s_mutex_lock_threshold_ms = lock_threshold_ms; + s_mutex_lock_threshold_ms = lock_threshold_ms; } static void DRD_(mutex_initialize)(struct mutex_info* const p, const Addr mutex, const MutexT mutex_type) { - tl_assert(mutex); - tl_assert(mutex_type != mutex_type_unknown); - tl_assert(p->a1 == mutex); - - p->cleanup = (void(*)(DrdClientobj*))mutex_cleanup; - p->delete_thread - = (void(*)(DrdClientobj*, DrdThreadId))mutex_delete_thread; - p->mutex_type = mutex_type; - p->recursion_count = 0; - p->owner = DRD_INVALID_THREADID; - p->last_locked_segment = 0; - p->acquiry_time_ms = 0; - p->acquired_at = 0; + tl_assert(mutex); + tl_assert(mutex_type != mutex_type_unknown); + tl_assert(p->a1 == mutex); + + p->cleanup = (void(*)(DrdClientobj*))mutex_cleanup; + p->delete_thread + = (void(*)(DrdClientobj*, DrdThreadId))mutex_delete_thread; + p->mutex_type = mutex_type; + p->recursion_count = 0; + p->owner = DRD_INVALID_THREADID; + p->last_locked_segment = 0; + p->acquiry_time_ms = 0; + p->acquired_at = 0; } /** Deallocate the memory that was allocated by mutex_initialize(). */ static void mutex_cleanup(struct mutex_info* p) { - tl_assert(p); - - if (s_trace_mutex) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] mutex_destroy %s 0x%lx rc %d owner %d", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - DRD_(mutex_get_typename)(p), - p->a1, - p ? p->recursion_count : -1, - p ? p->owner : DRD_INVALID_THREADID); - } - - if (mutex_is_locked(p)) - { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - MutexErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Destroying locked mutex", - &MEI); - } - - DRD_(sg_put)(p->last_locked_segment); - p->last_locked_segment = 0; + tl_assert(p); + + if (s_trace_mutex) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] mutex_destroy %s 0x%lx rc %d owner %d", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + DRD_(mutex_get_typename)(p), + p->a1, + p ? p->recursion_count : -1, + p ? p->owner : DRD_INVALID_THREADID); + } + + if (mutex_is_locked(p)) + { + MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + MutexErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Destroying locked mutex", + &MEI); + } + + DRD_(sg_put)(p->last_locked_segment); + p->last_locked_segment = 0; } /** Let Valgrind report that there is no mutex object at address 'mutex'. */ void DRD_(not_a_mutex)(const Addr mutex) { - MutexErrInfo MEI = { mutex, -1, DRD_INVALID_THREADID }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - MutexErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Not a mutex", - &MEI); + MutexErrInfo MEI = { mutex, -1, DRD_INVALID_THREADID }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + MutexErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a mutex", + &MEI); } static struct mutex_info* DRD_(mutex_get_or_allocate)(const Addr mutex, const MutexT mutex_type) { - struct mutex_info* p; - - tl_assert(offsetof(DrdClientobj, mutex) == 0); - p = &(DRD_(clientobj_get)(mutex, ClientMutex)->mutex); - if (p) - { - return p; - } - - if (DRD_(clientobj_present)(mutex, mutex + 1)) - { - DRD_(not_a_mutex)(mutex); - return 0; - } - - tl_assert(mutex_type != mutex_type_unknown); - - p = &(DRD_(clientobj_add)(mutex, ClientMutex)->mutex); - DRD_(mutex_initialize)(p, mutex, mutex_type); - return p; + struct mutex_info* p; + + tl_assert(offsetof(DrdClientobj, mutex) == 0); + p = &(DRD_(clientobj_get)(mutex, ClientMutex)->mutex); + if (p) + { + return p; + } + + if (DRD_(clientobj_present)(mutex, mutex + 1)) + { + DRD_(not_a_mutex)(mutex); + return 0; + } + + tl_assert(mutex_type != mutex_type_unknown); + + p = &(DRD_(clientobj_add)(mutex, ClientMutex)->mutex); + DRD_(mutex_initialize)(p, mutex, mutex_type); + return p; } struct mutex_info* DRD_(mutex_get)(const Addr mutex) { - tl_assert(offsetof(DrdClientobj, mutex) == 0); - return &(DRD_(clientobj_get)(mutex, ClientMutex)->mutex); + tl_assert(offsetof(DrdClientobj, mutex) == 0); + return &(DRD_(clientobj_get)(mutex, ClientMutex)->mutex); } /** Called before pthread_mutex_init(). */ struct mutex_info* DRD_(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, - "[%d/%d] mutex_init %s 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - DRD_(mutex_type_name)(mutex_type), - mutex); - } - - if (mutex_type == mutex_type_invalid_mutex) - { - DRD_(not_a_mutex)(mutex); - return 0; - } - - p = DRD_(mutex_get)(mutex); - if (p) - { - const ThreadId vg_tid = VG_(get_running_tid)(); - MutexErrInfo MEI - = { p->a1, p->recursion_count, p->owner }; - VG_(maybe_record_error)(vg_tid, - MutexErr, - VG_(get_IP)(vg_tid), - "Mutex reinitialization", - &MEI); - return p; - } - p = DRD_(mutex_get_or_allocate)(mutex, mutex_type); - - return p; + struct mutex_info* p; + + tl_assert(mutex_type != mutex_type_unknown); + + if (s_trace_mutex) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] mutex_init %s 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + DRD_(mutex_type_name)(mutex_type), + mutex); + } + + if (mutex_type == mutex_type_invalid_mutex) + { + DRD_(not_a_mutex)(mutex); + return 0; + } + + p = DRD_(mutex_get)(mutex); + if (p) + { + const ThreadId vg_tid = VG_(get_running_tid)(); + MutexErrInfo MEI + = { p->a1, p->recursion_count, p->owner }; + VG_(maybe_record_error)(vg_tid, + MutexErr, + VG_(get_IP)(vg_tid), + "Mutex reinitialization", + &MEI); + return p; + } + p = DRD_(mutex_get_or_allocate)(mutex, mutex_type); + + return p; } /** Called after pthread_mutex_destroy(). */ void DRD_(mutex_post_destroy)(const Addr mutex) { - struct mutex_info* p; + struct mutex_info* p; - p = DRD_(mutex_get)(mutex); - if (p == 0) - { - DRD_(not_a_mutex)(mutex); - return; - } + p = DRD_(mutex_get)(mutex); + if (p == 0) + { + DRD_(not_a_mutex)(mutex); + return; + } - DRD_(clientobj_remove)(mutex, ClientMutex); + DRD_(clientobj_remove)(mutex, ClientMutex); } /** Called before pthread_mutex_lock() is invoked. If a data structure for @@ -222,51 +223,51 @@ void DRD_(mutex_post_destroy)(const Addr mutex) void DRD_(mutex_pre_lock)(const Addr mutex, MutexT mutex_type, const Bool trylock) { - struct mutex_info* p; - - p = DRD_(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] %s %s 0x%lx rc %d owner %d", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - trylock ? "pre_mutex_lock " : "mutex_trylock ", - p ? DRD_(mutex_get_typename)(p) : "(?)", - mutex, - p ? p->recursion_count : -1, - p ? p->owner : DRD_INVALID_THREADID); - } - - if (p == 0) - { - DRD_(not_a_mutex)(mutex); - return; - } - - tl_assert(p); - - if (mutex_type == mutex_type_invalid_mutex) - { - DRD_(not_a_mutex)(mutex); - return; - } - - if (! trylock - && p->owner == DRD_(thread_get_running_tid)() - && p->recursion_count >= 1 - && mutex_type != mutex_type_recursive_mutex) - { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - MutexErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Recursive locking not allowed", - &MEI); - } + struct mutex_info* p; + + p = DRD_(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] %s %s 0x%lx rc %d owner %d", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + trylock ? "pre_mutex_lock " : "mutex_trylock ", + p ? DRD_(mutex_get_typename)(p) : "(?)", + mutex, + p ? p->recursion_count : -1, + p ? p->owner : DRD_INVALID_THREADID); + } + + if (p == 0) + { + DRD_(not_a_mutex)(mutex); + return; + } + + tl_assert(p); + + if (mutex_type == mutex_type_invalid_mutex) + { + DRD_(not_a_mutex)(mutex); + return; + } + + if (! trylock + && p->owner == DRD_(thread_get_running_tid)() + && p->recursion_count >= 1 + && mutex_type != mutex_type_recursive_mutex) + { + MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + MutexErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Recursive locking not allowed", + &MEI); + } } /** @@ -277,55 +278,55 @@ void DRD_(mutex_pre_lock)(const Addr mutex, MutexT mutex_type, void DRD_(mutex_post_lock)(const Addr mutex, const Bool took_lock, const Bool post_cond_wait) { - const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); - struct mutex_info* p; - - p = DRD_(mutex_get)(mutex); - - if (s_trace_mutex) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] %s %s 0x%lx rc %d owner %d%s", - VG_(get_running_tid)(), - drd_tid, - post_cond_wait ? "cond_post_wait " : "post_mutex_lock", - p ? DRD_(mutex_get_typename)(p) : "(?)", - mutex, - p ? p->recursion_count : 0, - p ? p->owner : VG_INVALID_THREADID, - took_lock ? "" : " (locking failed)"); - } - - if (! p || ! took_lock) - return; - - if (p->recursion_count == 0) - { - const DrdThreadId last_owner = p->owner; - - if (last_owner != drd_tid && last_owner != DRD_INVALID_THREADID) - { - tl_assert(p->last_locked_segment); - DRD_(thread_combine_vc2)(drd_tid, &p->last_locked_segment->vc); - } - DRD_(thread_new_segment)(drd_tid); - s_mutex_segment_creation_count++; - - p->owner = drd_tid; - p->acquiry_time_ms = VG_(read_millisecond_timer)(); - p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); - s_mutex_lock_count++; - } - else if (p->owner != drd_tid) - { - VG_(message)(Vg_UserMsg, - "The impossible happened: mutex 0x%lx is locked" - " simultaneously by two threads (recursion count %d," - " owners %d and %d) !", - p->a1, p->recursion_count, p->owner, drd_tid); - p->owner = drd_tid; - } - p->recursion_count++; + const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); + struct mutex_info* p; + + p = DRD_(mutex_get)(mutex); + + if (s_trace_mutex) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] %s %s 0x%lx rc %d owner %d%s", + VG_(get_running_tid)(), + drd_tid, + post_cond_wait ? "cond_post_wait " : "post_mutex_lock", + p ? DRD_(mutex_get_typename)(p) : "(?)", + mutex, + p ? p->recursion_count : 0, + p ? p->owner : VG_INVALID_THREADID, + took_lock ? "" : " (locking failed)"); + } + + if (! p || ! took_lock) + return; + + if (p->recursion_count == 0) + { + const DrdThreadId last_owner = p->owner; + + if (last_owner != drd_tid && last_owner != DRD_INVALID_THREADID) + { + tl_assert(p->last_locked_segment); + DRD_(thread_combine_vc2)(drd_tid, &p->last_locked_segment->vc); + } + DRD_(thread_new_segment)(drd_tid); + s_mutex_segment_creation_count++; + + p->owner = drd_tid; + p->acquiry_time_ms = VG_(read_millisecond_timer)(); + p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); + s_mutex_lock_count++; + } + else if (p->owner != drd_tid) + { + VG_(message)(Vg_UserMsg, + "The impossible happened: mutex 0x%lx is locked" + " simultaneously by two threads (recursion count %d," + " owners %d and %d) !", + p->a1, p->recursion_count, p->owner, drd_tid); + p->owner = drd_tid; + } + p->recursion_count++; } /** @@ -341,155 +342,155 @@ void DRD_(mutex_post_lock)(const Addr mutex, const Bool took_lock, */ void DRD_(mutex_unlock)(const Addr mutex, MutexT mutex_type) { - const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); - const ThreadId vg_tid = VG_(get_running_tid)(); - struct mutex_info* p; - - p = DRD_(mutex_get)(mutex); - if (mutex_type == mutex_type_unknown) - mutex_type = p->mutex_type; - - if (s_trace_mutex) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] mutex_unlock %s 0x%lx rc %d", - vg_tid, - drd_tid, - p ? DRD_(mutex_get_typename)(p) : "(?)", - mutex, - p ? p->recursion_count : 0); - } - - if (p == 0 || mutex_type == mutex_type_invalid_mutex) - { - DRD_(not_a_mutex)(mutex); - return; - } - - if (p->owner == DRD_INVALID_THREADID) - { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; - VG_(maybe_record_error)(vg_tid, - MutexErr, - VG_(get_IP)(vg_tid), - "Mutex not locked", - &MEI); - return; - } - - tl_assert(p); - if (p->mutex_type != mutex_type) - { - VG_(message)(Vg_UserMsg, "??? mutex 0x%lx: type changed from %d into %d", - p->a1, p->mutex_type, mutex_type); - } - tl_assert(p->mutex_type == mutex_type); - tl_assert(p->owner != DRD_INVALID_THREADID); - - if (p->owner != drd_tid || p->recursion_count <= 0) - { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; - VG_(maybe_record_error)(vg_tid, - MutexErr, - VG_(get_IP)(vg_tid), - "Mutex not locked by calling thread", - &MEI); - return; - } - tl_assert(p->recursion_count > 0); - p->recursion_count--; - tl_assert(p->recursion_count >= 0); - - if (p->recursion_count == 0) - { - if (s_mutex_lock_threshold_ms > 0) - { - ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms; - if (held > s_mutex_lock_threshold_ms) + const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); + const ThreadId vg_tid = VG_(get_running_tid)(); + struct mutex_info* p; + + p = DRD_(mutex_get)(mutex); + if (mutex_type == mutex_type_unknown) + mutex_type = p->mutex_type; + + if (s_trace_mutex) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] mutex_unlock %s 0x%lx rc %d", + vg_tid, + drd_tid, + p ? DRD_(mutex_get_typename)(p) : "(?)", + mutex, + p ? p->recursion_count : 0); + } + + if (p == 0 || mutex_type == mutex_type_invalid_mutex) + { + DRD_(not_a_mutex)(mutex); + return; + } + + if (p->owner == DRD_INVALID_THREADID) + { + MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + VG_(maybe_record_error)(vg_tid, + MutexErr, + VG_(get_IP)(vg_tid), + "Mutex not locked", + &MEI); + return; + } + + tl_assert(p); + if (p->mutex_type != mutex_type) + { + VG_(message)(Vg_UserMsg, "??? mutex 0x%lx: type changed from %d into %d", + p->a1, p->mutex_type, mutex_type); + } + tl_assert(p->mutex_type == mutex_type); + tl_assert(p->owner != DRD_INVALID_THREADID); + + if (p->owner != drd_tid || p->recursion_count <= 0) + { + MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + VG_(maybe_record_error)(vg_tid, + MutexErr, + VG_(get_IP)(vg_tid), + "Mutex not locked by calling thread", + &MEI); + return; + } + tl_assert(p->recursion_count > 0); + p->recursion_count--; + tl_assert(p->recursion_count >= 0); + + if (p->recursion_count == 0) + { + if (s_mutex_lock_threshold_ms > 0) { - HoldtimeErrInfo HEI - = { mutex, p->acquired_at, held, s_mutex_lock_threshold_ms }; - VG_(maybe_record_error)(vg_tid, - HoldtimeErr, - VG_(get_IP)(vg_tid), - "mutex", - &HEI); + ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms; + if (held > s_mutex_lock_threshold_ms) + { + HoldtimeErrInfo HEI + = { mutex, p->acquired_at, held, s_mutex_lock_threshold_ms }; + VG_(maybe_record_error)(vg_tid, + HoldtimeErr, + VG_(get_IP)(vg_tid), + "mutex", + &HEI); + } } - } - /* This pthread_mutex_unlock() call really unlocks the mutex. Save the */ - /* current vector clock of the thread such that it is available when */ - /* this mutex is locked again. */ + /* This pthread_mutex_unlock() call really unlocks the mutex. Save the */ + /* current vector clock of the thread such that it is available when */ + /* this mutex is locked again. */ - DRD_(thread_get_latest_segment)(&p->last_locked_segment, drd_tid); - DRD_(thread_new_segment)(drd_tid); - p->acquired_at = 0; - s_mutex_segment_creation_count++; - } + DRD_(thread_get_latest_segment)(&p->last_locked_segment, drd_tid); + DRD_(thread_new_segment)(drd_tid); + p->acquired_at = 0; + s_mutex_segment_creation_count++; + } } void DRD_(spinlock_init_or_unlock)(const Addr spinlock) { - struct mutex_info* mutex_p = DRD_(mutex_get)(spinlock); - if (mutex_p) - { - DRD_(mutex_unlock)(spinlock, mutex_type_spinlock); - } - else - { - DRD_(mutex_init)(spinlock, mutex_type_spinlock); - } + struct mutex_info* mutex_p = DRD_(mutex_get)(spinlock); + if (mutex_p) + { + DRD_(mutex_unlock)(spinlock, mutex_type_spinlock); + } + else + { + DRD_(mutex_init)(spinlock, mutex_type_spinlock); + } } const char* DRD_(mutex_get_typename)(struct mutex_info* const p) { - tl_assert(p); + tl_assert(p); - return DRD_(mutex_type_name)(p->mutex_type); + return DRD_(mutex_type_name)(p->mutex_type); } const char* DRD_(mutex_type_name)(const MutexT mt) { - switch (mt) - { - case mutex_type_invalid_mutex: - return "invalid mutex"; - case mutex_type_recursive_mutex: - return "recursive mutex"; - case mutex_type_errorcheck_mutex: - return "error checking mutex"; - case mutex_type_default_mutex: - return "mutex"; - case mutex_type_spinlock: - return "spinlock"; - default: - tl_assert(0); - } - return "?"; + switch (mt) + { + case mutex_type_invalid_mutex: + return "invalid mutex"; + case mutex_type_recursive_mutex: + return "recursive mutex"; + case mutex_type_errorcheck_mutex: + return "error checking mutex"; + case mutex_type_default_mutex: + return "mutex"; + case mutex_type_spinlock: + return "spinlock"; + default: + tl_assert(0); + } + return "?"; } /** Return true if the specified mutex is locked by any thread. */ static Bool mutex_is_locked(struct mutex_info* const p) { - tl_assert(p); - return (p->recursion_count > 0); + tl_assert(p); + return (p->recursion_count > 0); } Bool DRD_(mutex_is_locked_by)(const Addr mutex, const DrdThreadId tid) { - struct mutex_info* const p = DRD_(mutex_get)(mutex); - if (p) - { - return (p->recursion_count > 0 && p->owner == tid); - } - return False; + struct mutex_info* const p = DRD_(mutex_get)(mutex); + if (p) + { + return (p->recursion_count > 0 && p->owner == tid); + } + return False; } int DRD_(mutex_get_recursion_count)(const Addr mutex) { - struct mutex_info* const p = DRD_(mutex_get)(mutex); - tl_assert(p); - return p->recursion_count; + struct mutex_info* const p = DRD_(mutex_get)(mutex); + tl_assert(p); + return p->recursion_count; } /** @@ -498,27 +499,27 @@ int DRD_(mutex_get_recursion_count)(const Addr mutex) */ static void mutex_delete_thread(struct mutex_info* p, const DrdThreadId tid) { - tl_assert(p); - - if (p->owner == tid && p->recursion_count > 0) - { - MutexErrInfo MEI - = { p->a1, p->recursion_count, p->owner }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - MutexErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Mutex still locked at thread exit", - &MEI); - p->owner = VG_INVALID_THREADID; - } + tl_assert(p); + + if (p->owner == tid && p->recursion_count > 0) + { + MutexErrInfo MEI + = { p->a1, p->recursion_count, p->owner }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + MutexErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Mutex still locked at thread exit", + &MEI); + p->owner = VG_INVALID_THREADID; + } } ULong DRD_(get_mutex_lock_count)(void) { - return s_mutex_lock_count; + return s_mutex_lock_count; } ULong DRD_(get_mutex_segment_creation_count)(void) { - return s_mutex_segment_creation_count; + return s_mutex_segment_creation_count; } diff --git a/drd/drd_mutex.h b/drd/drd_mutex.h index a36f6014f8..5096a8e383 100644 --- a/drd/drd_mutex.h +++ b/drd/drd_mutex.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. diff --git a/drd/drd_pthread_intercepts.c b/drd/drd_pthread_intercepts.c index 3c9ef5da84..bf19360f29 100644 --- a/drd/drd_pthread_intercepts.c +++ b/drd/drd_pthread_intercepts.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /*--------------------------------------------------------------------*/ /*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/ @@ -78,19 +79,19 @@ #define ALLOCATE_THREAD_ARGS_ON_THE_STACK #define PTH_FUNC(ret_ty, f, args...) \ - ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args); \ - ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args) + ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args); \ + ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args) /* Local data structures. */ typedef struct { - void* (*start)(void*); - void* arg; - int detachstate; + void* (*start)(void*); + void* arg; + int detachstate; #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) - int wrapper_started; + int wrapper_started; #endif } DrdPosixThreadArgs; @@ -116,8 +117,8 @@ static void DRD_(set_main_thread_state)(void); */ static void DRD_(init)(void) { - DRD_(check_threading_library)(); - DRD_(set_main_thread_state)(); + DRD_(check_threading_library)(); + DRD_(set_main_thread_state)(); } /** @@ -129,22 +130,22 @@ static void DRD_(init)(void) */ static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind) { - if (kind == PTHREAD_MUTEX_RECURSIVE) - return mutex_type_recursive_mutex; - else if (kind == PTHREAD_MUTEX_ERRORCHECK) - return mutex_type_errorcheck_mutex; - else if (kind == PTHREAD_MUTEX_NORMAL) - return mutex_type_default_mutex; - else if (kind == PTHREAD_MUTEX_DEFAULT) - return mutex_type_default_mutex; + if (kind == PTHREAD_MUTEX_RECURSIVE) + return mutex_type_recursive_mutex; + else if (kind == PTHREAD_MUTEX_ERRORCHECK) + return mutex_type_errorcheck_mutex; + else if (kind == PTHREAD_MUTEX_NORMAL) + return mutex_type_default_mutex; + else if (kind == PTHREAD_MUTEX_DEFAULT) + return mutex_type_default_mutex; #if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP) - else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP) - return mutex_type_default_mutex; + else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP) + return mutex_type_default_mutex; #endif - else - { - return mutex_type_invalid_mutex; - } + else + { + return mutex_type_invalid_mutex; + } } /** @@ -163,19 +164,19 @@ static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind) static __inline__ MutexT DRD_(mutex_type)(pthread_mutex_t* mutex) { #if defined(HAVE_PTHREAD_MUTEX_T__M_KIND) - /* glibc + LinuxThreads. */ - const int kind = mutex->__m_kind & 3; + /* glibc + LinuxThreads. */ + const int kind = mutex->__m_kind & 3; #elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND) - /* glibc + NPTL. */ - const int kind = mutex->__data.__kind & 3; + /* glibc + NPTL. */ + const int kind = mutex->__data.__kind & 3; #else - /* Another POSIX threads implementation. Regression tests will fail. */ - const int kind = PTHREAD_MUTEX_DEFAULT; - fprintf(stderr, - "Did not recognize your POSIX threads implementation. Giving up.\n"); - assert(0); + /* Another POSIX threads implementation. Regression tests will fail. */ + const int kind = PTHREAD_MUTEX_DEFAULT; + fprintf(stderr, + "Did not recognize your POSIX threads implementation. Giving up.\n"); + assert(0); #endif - return DRD_(pthread_to_drd_mutex_type)(kind); + return DRD_(pthread_to_drd_mutex_type)(kind); } /** @@ -183,10 +184,10 @@ static __inline__ MutexT DRD_(mutex_type)(pthread_mutex_t* mutex) */ static void DRD_(set_joinable)(const pthread_t tid, const int joinable) { - int res; - assert(joinable == 0 || joinable == 1); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE, - tid, joinable, 0, 0, 0); + int res; + assert(joinable == 0 || joinable == 1); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE, + tid, joinable, 0, 0, 0); } /** @@ -194,32 +195,33 @@ static void DRD_(set_joinable)(const pthread_t tid, const int joinable) */ static void* DRD_(thread_wrapper)(void* arg) { - int res; - DrdPosixThreadArgs* arg_ptr; - DrdPosixThreadArgs arg_copy; + int res; + DrdPosixThreadArgs* arg_ptr; + DrdPosixThreadArgs arg_copy; - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, - 0, 0, 0, 0, 0); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, + 0, 0, 0, 0, 0); - arg_ptr = (DrdPosixThreadArgs*)arg; - arg_copy = *arg_ptr; + arg_ptr = (DrdPosixThreadArgs*)arg; + arg_copy = *arg_ptr; #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) - arg_ptr->wrapper_started = 1; + arg_ptr->wrapper_started = 1; #else #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) -#error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not WAIT_UNTIL_CREATED_THREAD_STARTED is not supported. +#error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not \ + WAIT_UNTIL_CREATED_THREAD_STARTED is not supported. #else - free(arg_ptr); + free(arg_ptr); #endif #endif - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, - pthread_self(), 0, 0, 0, 0); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, + pthread_self(), 0, 0, 0, 0); - DRD_(set_joinable)(pthread_self(), - arg_copy.detachstate == PTHREAD_CREATE_JOINABLE); + DRD_(set_joinable)(pthread_self(), + arg_copy.detachstate == PTHREAD_CREATE_JOINABLE); - return (arg_copy.start)(arg_copy.arg); + return (arg_copy.start)(arg_copy.arg); } /** @@ -233,19 +235,19 @@ static int DRD_(detected_linuxthreads)(void) { #if defined(linux) #if defined(_CS_GNU_LIBPTHREAD_VERSION) - /* Linux with a recent glibc. */ - char buffer[256]; - unsigned len; - len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); - assert(len <= sizeof(buffer)); - return len > 0 && buffer[0] == 'l'; + /* Linux with a recent glibc. */ + char buffer[256]; + unsigned len; + len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); + assert(len <= sizeof(buffer)); + return len > 0 && buffer[0] == 'l'; #else - /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */ - return 1; + /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */ + return 1; #endif #else - /* Another OS than Linux, hence no LinuxThreads. */ - return 0; + /* Another OS than Linux, hence no LinuxThreads. */ + return 0; #endif } @@ -255,27 +257,27 @@ static int DRD_(detected_linuxthreads)(void) */ static void DRD_(check_threading_library)(void) { - if (DRD_(detected_linuxthreads)()) - { - if (getenv("LD_ASSUME_KERNEL")) - { - fprintf(stderr, + if (DRD_(detected_linuxthreads)()) + { + if (getenv("LD_ASSUME_KERNEL")) + { + fprintf(stderr, "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" "after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n" - ); - } - else - { - fprintf(stderr, +); + } + else + { + fprintf(stderr, "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" "after having upgraded to a newer version of your Linux distribution.\n" "Giving up.\n" - ); - } - abort(); - } +); + } + abort(); + } } /** @@ -284,14 +286,14 @@ static void DRD_(check_threading_library)(void) */ static void DRD_(set_main_thread_state)(void) { - int res; + int res; - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, - 0, 0, 0, 0, 0); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, + 0, 0, 0, 0, 0); - // Make sure that DRD knows about the main thread's POSIX thread ID. - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, - pthread_self(), 0, 0, 0, 0); + // Make sure that DRD knows about the main thread's POSIX thread ID. + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, + pthread_self(), 0, 0, 0, 0); } @@ -300,128 +302,128 @@ PTH_FUNC(int, pthreadZucreateZa, // pthread_create* pthread_t *thread, const pthread_attr_t *attr, void *(*start) (void *), void *arg) { - int res; - int ret; - OrigFn fn; + int res; + int ret; + OrigFn fn; #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) - DrdPosixThreadArgs thread_args; + DrdPosixThreadArgs thread_args; #endif - DrdPosixThreadArgs* thread_args_p; + DrdPosixThreadArgs* thread_args_p; - VALGRIND_GET_ORIG_FN(fn); + VALGRIND_GET_ORIG_FN(fn); #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) - thread_args_p = &thread_args; + thread_args_p = &thread_args; #else - thread_args_p = malloc(sizeof(*thread_args_p)); + thread_args_p = malloc(sizeof(*thread_args_p)); #endif - assert(thread_args_p); + assert(thread_args_p); - thread_args_p->start = start; - thread_args_p->arg = arg; + thread_args_p->start = start; + thread_args_p->arg = arg; #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) - DRD_IGNORE_VAR(thread_args_p->wrapper_started); - thread_args_p->wrapper_started = 0; + DRD_IGNORE_VAR(thread_args_p->wrapper_started); + thread_args_p->wrapper_started = 0; #endif - /* - * Find out whether the thread will be started as a joinable thread - * or as a detached thread. If no thread attributes have been specified, - * this means that the new thread will be started as a joinable thread. - */ - thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE; - if (attr) - { - if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0) - { - assert(0); - } - } - assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE - || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED); - - /* Suppress NPTL-specific conflicts between creator and created thread. */ - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_STOP_RECORDING, - 0, 0, 0, 0, 0); - - CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p); - - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_RECORDING, - 0, 0, 0, 0, 0); + /* + * Find out whether the thread will be started as a joinable thread + * or as a detached thread. If no thread attributes have been specified, + * this means that the new thread will be started as a joinable thread. + */ + thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE; + if (attr) + { + if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0) + { + assert(0); + } + } + assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE + || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED); + + /* Suppress NPTL-specific conflicts between creator and created thread. */ + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_STOP_RECORDING, + 0, 0, 0, 0, 0); + + CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p); + + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_RECORDING, + 0, 0, 0, 0, 0); #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) - if (ret == 0) - { - /* - * Wait until the thread wrapper started. - * @todo Find out why some regression tests fail if thread arguments are - * passed via dynamically allocated memory and if the loop below is - * removed. - */ - while (! thread_args_p->wrapper_started) - { - sched_yield(); - } - } + if (ret == 0) + { + /* + * Wait until the thread wrapper started. + * @todo Find out why some regression tests fail if thread arguments are + * passed via dynamically allocated memory and if the loop below is + * removed. + */ + while (! thread_args_p->wrapper_started) + { + sched_yield(); + } + } #if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY) - free(thread_args_p); + free(thread_args_p); #endif #endif - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT, - pthread_self(), 0, 0, 0, 0); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT, + pthread_self(), 0, 0, 0, 0); - return ret; + return ret; } // pthread_join PTH_FUNC(int, pthreadZujoin, // pthread_join pthread_t pt_joinee, void **thread_return) { - int ret; - int res; - OrigFn fn; + int ret; + int res; + OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - CALL_FN_W_WW(ret, fn, pt_joinee, thread_return); - if (ret == 0) - { - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN, - pt_joinee, 0, 0, 0, 0); - } - return ret; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WW(ret, fn, pt_joinee, thread_return); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN, + pt_joinee, 0, 0, 0, 0); + } + return ret; } // pthread_detach PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread) { - int ret; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - { - CALL_FN_W_W(ret, fn, pt_thread); - if (ret == 0) - { - DRD_(set_joinable)(pt_thread, 0); - } - } - return ret; + int ret; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + { + CALL_FN_W_W(ret, fn, pt_thread); + if (ret == 0) + { + DRD_(set_joinable)(pt_thread, 0); + } + } + return ret; } // pthread_cancel PTH_FUNC(int, pthreadZucancel, pthread_t pt_thread) { - int res; - int ret; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL, - pt_thread, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, pt_thread); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL, - pt_thread, ret==0, 0, 0, 0); - return ret; + int res; + int ret; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL, + pt_thread, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, pt_thread); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL, + pt_thread, ret==0, 0, 0, 0); + return ret; } // pthread_mutex_init @@ -429,69 +431,69 @@ PTH_FUNC(int, pthreadZumutexZuinit, pthread_mutex_t *mutex, const pthread_mutexattr_t* attr) { - int ret; - int res; - OrigFn fn; - int mt; - VALGRIND_GET_ORIG_FN(fn); - mt = PTHREAD_MUTEX_DEFAULT; - if (attr) - pthread_mutexattr_gettype(attr, &mt); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, - mutex, DRD_(pthread_to_drd_mutex_type)(mt), - 0, 0, 0); - CALL_FN_W_WW(ret, fn, mutex, attr); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, - mutex, 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + int mt; + VALGRIND_GET_ORIG_FN(fn); + mt = PTHREAD_MUTEX_DEFAULT; + if (attr) + pthread_mutexattr_gettype(attr, &mt); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, + mutex, DRD_(pthread_to_drd_mutex_type)(mt), + 0, 0, 0); + CALL_FN_W_WW(ret, fn, mutex, attr); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, + mutex, 0, 0, 0, 0); + return ret; } // pthread_mutex_destroy PTH_FUNC(int, pthreadZumutexZudestroy, pthread_mutex_t *mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, - mutex, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, - mutex, DRD_(mutex_type)(mutex), 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, + mutex, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, + mutex, DRD_(mutex_type)(mutex), 0, 0, 0); + return ret; } // pthread_mutex_lock PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock pthread_mutex_t *mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - mutex, DRD_(mutex_type)(mutex), 0, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, - mutex, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + mutex, DRD_(mutex_type)(mutex), 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, + mutex, ret == 0, 0, 0, 0); + return ret; } // pthread_mutex_trylock PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock pthread_mutex_t *mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - mutex, DRD_(mutex_type)(mutex), 1, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, - mutex, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + mutex, DRD_(mutex_type)(mutex), 1, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, + mutex, ret == 0, 0, 0, 0); + return ret; } // pthread_mutex_timedlock @@ -499,34 +501,34 @@ PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock pthread_mutex_t *mutex, const struct timespec *abs_timeout) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - mutex, DRD_(mutex_type)(mutex), 0, 0, 0); - CALL_FN_W_WW(ret, fn, mutex, abs_timeout); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, - mutex, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + mutex, DRD_(mutex_type)(mutex), 0, 0, 0); + CALL_FN_W_WW(ret, fn, mutex, abs_timeout); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, + mutex, ret == 0, 0, 0, 0); + return ret; } // pthread_mutex_unlock PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock pthread_mutex_t *mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, - VG_USERREQ__PRE_MUTEX_UNLOCK, - mutex, DRD_(mutex_type)(mutex), 0, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, - VG_USERREQ__POST_MUTEX_UNLOCK, - mutex, 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, + VG_USERREQ__PRE_MUTEX_UNLOCK, + mutex, DRD_(mutex_type)(mutex), 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, + VG_USERREQ__POST_MUTEX_UNLOCK, + mutex, 0, 0, 0, 0); + return ret; } // pthread_cond_init @@ -534,32 +536,32 @@ PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init* pthread_cond_t* cond, const pthread_condattr_t* attr) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - 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; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + 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; } // pthread_cond_destroy PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy* pthread_cond_t* cond) { - int ret; - 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); - return ret; + int ret; + 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); + return ret; } // pthread_cond_wait @@ -567,16 +569,16 @@ PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait* pthread_cond_t *cond, pthread_mutex_t *mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, - cond, mutex, DRD_(mutex_type)(mutex), 0, 0); - CALL_FN_W_WW(ret, fn, cond, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, - cond, mutex, 1, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, + cond, mutex, DRD_(mutex_type)(mutex), 0, 0); + CALL_FN_W_WW(ret, fn, cond, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, + cond, mutex, 1, 0, 0); + return ret; } // pthread_cond_timedwait @@ -585,48 +587,48 @@ PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait* pthread_mutex_t *mutex, const struct timespec* abstime) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, - cond, mutex, DRD_(mutex_type)(mutex), 0, 0); - CALL_FN_W_WWW(ret, fn, cond, mutex, abstime); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, - cond, mutex, 1, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, + cond, mutex, DRD_(mutex_type)(mutex), 0, 0); + CALL_FN_W_WWW(ret, fn, cond, mutex, abstime); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, + cond, mutex, 1, 0, 0); + return ret; } // pthread_cond_signal PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal* pthread_cond_t* cond) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - 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; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + 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; } // pthread_cond_broadcast PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast* pthread_cond_t* cond) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - 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; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + 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; } @@ -635,80 +637,80 @@ PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init pthread_spinlock_t *spinlock, int pshared) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, - spinlock, 0, 0, 0, 0); - CALL_FN_W_WW(ret, fn, spinlock, pshared); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, - spinlock, 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, + spinlock, 0, 0, 0, 0); + CALL_FN_W_WW(ret, fn, spinlock, pshared); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, + spinlock, 0, 0, 0, 0); + return ret; } // pthread_spin_destroy PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy pthread_spinlock_t *spinlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, - spinlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, spinlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, - spinlock, mutex_type_spinlock, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, + spinlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, spinlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, + spinlock, mutex_type_spinlock, 0, 0, 0); + return ret; } // pthread_spin_lock PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock pthread_spinlock_t *spinlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - spinlock, mutex_type_spinlock, 0, 0, 0); - CALL_FN_W_W(ret, fn, spinlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, - spinlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + spinlock, mutex_type_spinlock, 0, 0, 0); + CALL_FN_W_W(ret, fn, spinlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, + spinlock, ret == 0, 0, 0, 0); + return ret; } // pthread_spin_trylock PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock pthread_spinlock_t *spinlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - spinlock, mutex_type_spinlock, 0, 0, 0); - CALL_FN_W_W(ret, fn, spinlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, - spinlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + spinlock, mutex_type_spinlock, 0, 0, 0); + CALL_FN_W_W(ret, fn, spinlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, + spinlock, ret == 0, 0, 0, 0); + return ret; } // pthread_spin_unlock PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock pthread_spinlock_t *spinlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, - spinlock, mutex_type_spinlock, 0, 0, 0); - CALL_FN_W_W(ret, fn, spinlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, - spinlock, 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, + spinlock, mutex_type_spinlock, 0, 0, 0); + CALL_FN_W_W(ret, fn, spinlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, + spinlock, 0, 0, 0, 0); + return ret; } // pthread_barrier_init @@ -717,50 +719,50 @@ PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init const pthread_barrierattr_t* attr, unsigned count) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, - barrier, pthread_barrier, count, 0, 0); - CALL_FN_W_WWW(ret, fn, barrier, attr, count); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, - barrier, pthread_barrier, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, + barrier, pthread_barrier, count, 0, 0); + CALL_FN_W_WWW(ret, fn, barrier, attr, count); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, + barrier, pthread_barrier, 0, 0, 0); + return ret; } // pthread_barrier_destroy PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy pthread_barrier_t* barrier) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY, - barrier, pthread_barrier, 0, 0, 0); - CALL_FN_W_W(ret, fn, barrier); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, - barrier, pthread_barrier, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY, + barrier, pthread_barrier, 0, 0, 0); + CALL_FN_W_W(ret, fn, barrier); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, + barrier, pthread_barrier, 0, 0, 0); + return ret; } // pthread_barrier_wait PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait pthread_barrier_t* barrier) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, - barrier, pthread_barrier, 0, 0, 0); - CALL_FN_W_W(ret, fn, barrier); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, - barrier, pthread_barrier, - ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, - ret == PTHREAD_BARRIER_SERIAL_THREAD, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, + barrier, pthread_barrier, 0, 0, 0); + CALL_FN_W_W(ret, fn, barrier); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, + barrier, pthread_barrier, + ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, + ret == PTHREAD_BARRIER_SERIAL_THREAD, 0); + return ret; } @@ -770,96 +772,96 @@ PTH_FUNC(int, semZuinitZa, // sem_init* int pshared, unsigned int value) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT, - sem, pshared, value, 0, 0); - CALL_FN_W_WWW(ret, fn, sem, pshared, value); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT, - sem, 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT, + sem, pshared, value, 0, 0); + CALL_FN_W_WWW(ret, fn, sem, pshared, value); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT, + sem, 0, 0, 0, 0); + return ret; } // sem_destroy PTH_FUNC(int, semZudestroyZa, // sem_destroy* sem_t *sem) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY, - sem, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, sem); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY, - sem, 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY, + sem, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, sem); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY, + sem, 0, 0, 0, 0); + return ret; } // sem_wait PTH_FUNC(int, semZuwaitZa, // sem_wait* sem_t *sem) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, - sem, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, sem); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, - sem, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, + sem, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, sem); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, ret == 0, 0, 0, 0); + return ret; } // sem_trywait PTH_FUNC(int, semZutrywaitZa, // sem_trywait* sem_t *sem) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, - sem, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, sem); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, - sem, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, + sem, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, sem); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, ret == 0, 0, 0, 0); + return ret; } // sem_timedwait PTH_FUNC(int, semZutimedwait, // sem_timedwait sem_t *sem, const struct timespec *abs_timeout) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, - sem, 0, 0, 0, 0); - CALL_FN_W_WW(ret, fn, sem, abs_timeout); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, - sem, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, + sem, 0, 0, 0, 0); + CALL_FN_W_WW(ret, fn, sem, abs_timeout); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, ret == 0, 0, 0, 0); + return ret; } // sem_post PTH_FUNC(int, semZupostZa, // sem_post* sem_t *sem) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, - sem, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, sem); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, - sem, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, + sem, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, sem); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, + sem, ret == 0, 0, 0, 0); + return ret; } // pthread_rwlock_init @@ -868,14 +870,14 @@ PTH_FUNC(int, pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT, - rwlock, 0, 0, 0, 0); - CALL_FN_W_WW(ret, fn, rwlock, attr); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT, + rwlock, 0, 0, 0, 0); + CALL_FN_W_WW(ret, fn, rwlock, attr); + return ret; } // pthread_rwlock_destroy @@ -883,14 +885,14 @@ PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY, - rwlock, 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY, + rwlock, 0, 0, 0, 0); + return ret; } // pthread_rwlock_rdlock @@ -898,16 +900,16 @@ PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, - rwlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, - rwlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, + rwlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, + rwlock, ret == 0, 0, 0, 0); + return ret; } // pthread_rwlock_wrlock @@ -915,16 +917,16 @@ PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, - rwlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, - rwlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, + rwlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, + rwlock, ret == 0, 0, 0, 0); + return ret; } // pthread_rwlock_timedrdlock @@ -932,16 +934,16 @@ PTH_FUNC(int, pthreadZurwlockZutimedrdlockZa, // pthread_rwlock_timedrdlock* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, - rwlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, - rwlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, + rwlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, + rwlock, ret == 0, 0, 0, 0); + return ret; } // pthread_rwlock_timedwrlock @@ -949,16 +951,16 @@ PTH_FUNC(int, pthreadZurwlockZutimedwrlockZa, // pthread_rwlock_timedwrlock* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, - rwlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, - rwlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, + rwlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, + rwlock, ret == 0, 0, 0, 0); + return ret; } // pthread_rwlock_tryrdlock @@ -966,16 +968,16 @@ PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, - rwlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, - rwlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, + rwlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, + rwlock, ret == 0, 0, 0, 0); + return ret; } // pthread_rwlock_trywrlock @@ -983,16 +985,16 @@ PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, - rwlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, - rwlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, + rwlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, + rwlock, ret == 0, 0, 0, 0); + return ret; } // pthread_rwlock_unlock @@ -1000,14 +1002,14 @@ PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock* pthread_rwlock_t* rwlock) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK, - rwlock, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK, - rwlock, ret == 0, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK, + rwlock, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, rwlock); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK, + rwlock, ret == 0, 0, 0, 0); + return ret; } diff --git a/drd/drd_qtcore_intercepts.c b/drd/drd_qtcore_intercepts.c index 0a5ebe7d59..cddfef9cdd 100644 --- a/drd/drd_qtcore_intercepts.c +++ b/drd/drd_qtcore_intercepts.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /*--------------------------------------------------------------------*/ /*--- Client-space code for drd. drd_qtcore_intercepts.c ---*/ @@ -46,9 +47,9 @@ // Defines. -#define QT4CORE_FUNC(ret_ty, f, args...) \ - ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args); \ - ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args) +#define QT4CORE_FUNC(ret_ty, f, args...) \ + ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args); \ + ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args) @@ -63,14 +64,14 @@ typedef enum { qt_nonrecursive = 0, qt_recursive = 1 } qt_mutex_mode; /** Convert a Qt4 mutex type to a DRD mutex type. */ static MutexT qt_to_drd_mutex_type(qt_mutex_mode mode) { - switch (mode) - { - case qt_nonrecursive: - return mutex_type_default_mutex; - case qt_recursive: - return mutex_type_recursive_mutex; - } - return mutex_type_invalid_mutex; + switch (mode) + { + case qt_nonrecursive: + return mutex_type_default_mutex; + case qt_recursive: + return mutex_type_recursive_mutex; + } + return mutex_type_invalid_mutex; } /** Find out the type of a Qt4 mutex (recursive or not). @@ -79,7 +80,7 @@ static MutexT qt_to_drd_mutex_type(qt_mutex_mode mode) */ static MutexT mutex_type(void* qt4_mutex) { - return mutex_type_unknown; + return mutex_type_unknown; } @@ -88,15 +89,15 @@ QT4CORE_FUNC(void, _ZN6QMutexC1ENS_13RecursionModeE, void* mutex, qt_mutex_mode mode) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, - mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); - CALL_FN_W_WW(ret, fn, mutex, mode); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, - mutex, 0, 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, + mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); + CALL_FN_W_WW(ret, fn, mutex, mode); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, + mutex, 0, 0, 0, 0); } // QMutex::QMutex(RecursionMode) -- _ZN6QMutexC2ENS_13RecursionModeE @@ -104,76 +105,76 @@ QT4CORE_FUNC(void, _ZN6QMutexC2ENS_13RecursionModeE, void* mutex, qt_mutex_mode mode) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, - mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); - CALL_FN_W_WW(ret, fn, mutex, mode); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, - mutex, 0, 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, + mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); + CALL_FN_W_WW(ret, fn, mutex, mode); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, + mutex, 0, 0, 0, 0); } // QMutex::~QMutex() -- _ZN6QMutexD1Ev QT4CORE_FUNC(void, _ZN6QMutexD1Ev, void* mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, - mutex, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, - mutex, mutex_type(mutex), 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, + mutex, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, + mutex, mutex_type(mutex), 0, 0, 0); } // QMutex::~QMutex() -- _ZN6QMutexD2Ev QT4CORE_FUNC(void, _ZN6QMutexD2Ev, void** mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, - mutex, 0, 0, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, - mutex, mutex_type(mutex), 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, + mutex, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, + mutex, mutex_type(mutex), 0, 0, 0); } // QMutex::lock() -- _ZN6QMutex4lockEv QT4CORE_FUNC(void, _ZN6QMutex4lockEv, void* mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - mutex, mutex_type(mutex), 0, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, - mutex, 1, 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + mutex, mutex_type(mutex), 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, + mutex, 1, 0, 0, 0); } // QMutex::tryLock() -- _ZN6QMutex7tryLockEv QT4CORE_FUNC(int, _ZN6QMutex7tryLockEv, void* mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - mutex, mutex_type(mutex), 1, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, - mutex, ret, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + mutex, mutex_type(mutex), 1, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, + mutex, ret, 0, 0, 0); + return ret; } // QMutex::tryLock(int) -- _ZN6QMutex7tryLockEi @@ -181,31 +182,31 @@ QT4CORE_FUNC(int, _ZN6QMutex7tryLockEi, void* mutex, int timeout_ms) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, - mutex, mutex_type(mutex), 1, 0, 0); - CALL_FN_W_WW(ret, fn, mutex, timeout_ms); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, - mutex, ret, 0, 0, 0); - return ret; + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, + mutex, mutex_type(mutex), 1, 0, 0); + CALL_FN_W_WW(ret, fn, mutex, timeout_ms); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, + mutex, ret, 0, 0, 0); + return ret; } // QMutex::unlock() -- _ZN6QMutex6unlockEv QT4CORE_FUNC(void, _ZN6QMutex6unlockEv, void* mutex) { - int ret; - int res; - OrigFn fn; - VALGRIND_GET_ORIG_FN(fn); - VALGRIND_DO_CLIENT_REQUEST(res, -1, - VG_USERREQ__PRE_MUTEX_UNLOCK, - mutex, mutex_type(mutex), 0, 0, 0); - CALL_FN_W_W(ret, fn, mutex); - VALGRIND_DO_CLIENT_REQUEST(res, -1, - VG_USERREQ__POST_MUTEX_UNLOCK, - mutex, 0, 0, 0, 0); + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, + VG_USERREQ__PRE_MUTEX_UNLOCK, + mutex, mutex_type(mutex), 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + VALGRIND_DO_CLIENT_REQUEST(res, -1, + VG_USERREQ__POST_MUTEX_UNLOCK, + mutex, 0, 0, 0, 0); } diff --git a/drd/drd_rwlock.c b/drd/drd_rwlock.c index 12d89200a9..a2cfdaf1a0 100644 --- a/drd/drd_rwlock.c +++ b/drd/drd_rwlock.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -39,11 +40,11 @@ struct rwlock_thread_info { - UWord tid; // DrdThreadId. - UInt reader_nesting_count; - UInt writer_nesting_count; - Segment* last_unlock_segment; // Segment of last unlock call by this thread. - Bool last_lock_was_writer_lock; + UWord tid; // DrdThreadId. + UInt reader_nesting_count; + UInt writer_nesting_count; + Segment* last_unlock_segment; // Segment of last unlock call by this thread. + Bool last_lock_was_writer_lock; }; @@ -66,74 +67,74 @@ static ULong DRD_(s_rwlock_segment_creation_count); void DRD_(rwlock_set_trace)(const Bool trace_rwlock) { - tl_assert(trace_rwlock == False || trace_rwlock == True); - DRD_(s_trace_rwlock) = trace_rwlock; + tl_assert(trace_rwlock == False || trace_rwlock == True); + DRD_(s_trace_rwlock) = trace_rwlock; } void DRD_(rwlock_set_exclusive_threshold)(const UInt exclusive_threshold_ms) { - DRD_(s_exclusive_threshold_ms) = exclusive_threshold_ms; + DRD_(s_exclusive_threshold_ms) = exclusive_threshold_ms; } void DRD_(rwlock_set_shared_threshold)(const UInt shared_threshold_ms) { - DRD_(s_shared_threshold_ms) = shared_threshold_ms; + DRD_(s_shared_threshold_ms) = shared_threshold_ms; } static Bool DRD_(rwlock_is_rdlocked)(struct rwlock_info* p) { - struct rwlock_thread_info* q; - - VG_(OSetGen_ResetIter)(p->thread_info); - for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) - { - return q->reader_nesting_count > 0; - } - return False; + struct rwlock_thread_info* q; + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) + { + return q->reader_nesting_count > 0; + } + return False; } static Bool DRD_(rwlock_is_wrlocked)(struct rwlock_info* p) { - struct rwlock_thread_info* q; - - VG_(OSetGen_ResetIter)(p->thread_info); - for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) - { - return q->writer_nesting_count > 0; - } - return False; + struct rwlock_thread_info* q; + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) + { + return q->writer_nesting_count > 0; + } + return False; } static Bool DRD_(rwlock_is_locked)(struct rwlock_info* p) { - return DRD_(rwlock_is_rdlocked)(p) || DRD_(rwlock_is_wrlocked)(p); + return DRD_(rwlock_is_rdlocked)(p) || DRD_(rwlock_is_wrlocked)(p); } static Bool DRD_(rwlock_is_rdlocked_by)(struct rwlock_info* p, const DrdThreadId tid) { - const UWord uword_tid = tid; - struct rwlock_thread_info* q; + const UWord uword_tid = tid; + struct rwlock_thread_info* q; - q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid); - return q && q->reader_nesting_count > 0; + q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid); + return q && q->reader_nesting_count > 0; } static Bool DRD_(rwlock_is_wrlocked_by)(struct rwlock_info* p, const DrdThreadId tid) { - const UWord uword_tid = tid; - struct rwlock_thread_info* q; + const UWord uword_tid = tid; + struct rwlock_thread_info* q; - q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid); - return q && q->writer_nesting_count > 0; + q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid); + return q && q->writer_nesting_count > 0; } static Bool DRD_(rwlock_is_locked_by)(struct rwlock_info* p, const DrdThreadId tid) { - return (DRD_(rwlock_is_rdlocked_by)(p, tid) - || DRD_(rwlock_is_wrlocked_by)(p, tid)); + return (DRD_(rwlock_is_rdlocked_by)(p, tid) + || DRD_(rwlock_is_wrlocked_by)(p, tid)); } /** Either look up or insert a node corresponding to DRD thread id 'tid'. */ @@ -141,21 +142,21 @@ static struct rwlock_thread_info* DRD_(lookup_or_insert_node)(OSet* oset, const UWord tid) { - struct rwlock_thread_info* q; - - q = VG_(OSetGen_Lookup)(oset, &tid); - if (q == 0) - { - q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); - q->tid = tid; - q->reader_nesting_count = 0; - q->writer_nesting_count = 0; - q->last_unlock_segment = 0; - q->last_lock_was_writer_lock = False; - VG_(OSetGen_Insert)(oset, q); - } - tl_assert(q); - return q; + struct rwlock_thread_info* q; + + q = VG_(OSetGen_Lookup)(oset, &tid); + if (q == 0) + { + q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); + q->tid = tid; + q->reader_nesting_count = 0; + q->writer_nesting_count = 0; + q->last_unlock_segment = 0; + q->last_lock_was_writer_lock = False; + VG_(OSetGen_Insert)(oset, q); + } + tl_assert(q); + return q; } /** @@ -166,155 +167,156 @@ static void DRD_(rwlock_combine_other_vc)(struct rwlock_info* const p, const DrdThreadId tid, const Bool readers_too) { - struct rwlock_thread_info* q; - - VG_(OSetGen_ResetIter)(p->thread_info); - for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) - { - if (q->tid != tid && (readers_too || q->last_lock_was_writer_lock)) - { - DRD_(thread_combine_vc2)(tid, &q->last_unlock_segment->vc); - } - } + struct rwlock_thread_info* q; + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) + { + if (q->tid != tid && (readers_too || q->last_lock_was_writer_lock)) + { + DRD_(thread_combine_vc2)(tid, &q->last_unlock_segment->vc); + } + } } /** Initialize the rwlock_info data structure *p. */ static void DRD_(rwlock_initialize)(struct rwlock_info* const p, const Addr rwlock) { - tl_assert(rwlock != 0); - tl_assert(p->a1 == rwlock); - tl_assert(p->type == ClientRwlock); - - p->cleanup = (void(*)(DrdClientobj*))rwlock_cleanup; - p->delete_thread = (void(*)(DrdClientobj*, DrdThreadId))rwlock_delete_thread; - p->thread_info = VG_(OSetGen_Create)( - 0, 0, VG_(malloc), "drd.rwlock.ri.1", VG_(free)); - p->acquiry_time_ms = 0; - p->acquired_at = 0; + tl_assert(rwlock != 0); + tl_assert(p->a1 == rwlock); + tl_assert(p->type == ClientRwlock); + + p->cleanup = (void(*)(DrdClientobj*))rwlock_cleanup; + p->delete_thread + = (void(*)(DrdClientobj*, DrdThreadId))rwlock_delete_thread; + p->thread_info = VG_(OSetGen_Create)( + 0, 0, VG_(malloc), "drd.rwlock.ri.1", VG_(free)); + p->acquiry_time_ms = 0; + p->acquired_at = 0; } /** Deallocate the memory that was allocated by rwlock_initialize(). */ static void rwlock_cleanup(struct rwlock_info* p) { - struct rwlock_thread_info* q; - - tl_assert(p); - - if (DRD_(s_trace_rwlock)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] rwlock_destroy 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - p->a1); - } - - if (DRD_(rwlock_is_locked)(p)) - { - RwlockErrInfo REI = { p->a1 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - RwlockErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Destroying locked rwlock", - &REI); - } - - VG_(OSetGen_ResetIter)(p->thread_info); - for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) - { - DRD_(sg_put)(q->last_unlock_segment); - } - VG_(OSetGen_Destroy)(p->thread_info); + struct rwlock_thread_info* q; + + tl_assert(p); + + if (DRD_(s_trace_rwlock)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] rwlock_destroy 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + p->a1); + } + + if (DRD_(rwlock_is_locked)(p)) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + RwlockErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Destroying locked rwlock", + &REI); + } + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) + { + DRD_(sg_put)(q->last_unlock_segment); + } + VG_(OSetGen_Destroy)(p->thread_info); } static struct rwlock_info* DRD_(rwlock_get_or_allocate)(const Addr rwlock) { - struct rwlock_info* p; - - tl_assert(offsetof(DrdClientobj, rwlock) == 0); - p = &(DRD_(clientobj_get)(rwlock, ClientRwlock)->rwlock); - if (p) - { - return p; - } - - if (DRD_(clientobj_present)(rwlock, rwlock + 1)) - { - GenericErrInfo GEI; - VG_(maybe_record_error)(VG_(get_running_tid)(), - GenericErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Not a reader-writer lock", - &GEI); - return 0; - } - - p = &(DRD_(clientobj_add)(rwlock, ClientRwlock)->rwlock); - DRD_(rwlock_initialize)(p, rwlock); - return p; + struct rwlock_info* p; + + tl_assert(offsetof(DrdClientobj, rwlock) == 0); + p = &(DRD_(clientobj_get)(rwlock, ClientRwlock)->rwlock); + if (p) + { + return p; + } + + if (DRD_(clientobj_present)(rwlock, rwlock + 1)) + { + GenericErrInfo GEI; + VG_(maybe_record_error)(VG_(get_running_tid)(), + GenericErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a reader-writer lock", + &GEI); + return 0; + } + + p = &(DRD_(clientobj_add)(rwlock, ClientRwlock)->rwlock); + DRD_(rwlock_initialize)(p, rwlock); + return p; } static struct rwlock_info* DRD_(rwlock_get)(const Addr rwlock) { - tl_assert(offsetof(DrdClientobj, rwlock) == 0); - return &(DRD_(clientobj_get)(rwlock, ClientRwlock)->rwlock); + tl_assert(offsetof(DrdClientobj, rwlock) == 0); + return &(DRD_(clientobj_get)(rwlock, ClientRwlock)->rwlock); } /** Called before pthread_rwlock_init(). */ struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock) { - struct rwlock_info* p; - - if (DRD_(s_trace_rwlock)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] rwlock_init 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - rwlock); - } - - p = DRD_(rwlock_get)(rwlock); - - if (p) - { - const ThreadId vg_tid = VG_(get_running_tid)(); - RwlockErrInfo REI - = { p->a1 }; - VG_(maybe_record_error)(vg_tid, - RwlockErr, - VG_(get_IP)(vg_tid), - "Reader-writer lock reinitialization", - &REI); - return p; - } - - p = DRD_(rwlock_get_or_allocate)(rwlock); - - return p; + struct rwlock_info* p; + + if (DRD_(s_trace_rwlock)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] rwlock_init 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + rwlock); + } + + p = DRD_(rwlock_get)(rwlock); + + if (p) + { + const ThreadId vg_tid = VG_(get_running_tid)(); + RwlockErrInfo REI + = { p->a1 }; + VG_(maybe_record_error)(vg_tid, + RwlockErr, + VG_(get_IP)(vg_tid), + "Reader-writer lock reinitialization", + &REI); + return p; + } + + p = DRD_(rwlock_get_or_allocate)(rwlock); + + return p; } /** Called after pthread_rwlock_destroy(). */ void DRD_(rwlock_post_destroy)(const Addr rwlock) { - struct rwlock_info* p; - - p = DRD_(rwlock_get)(rwlock); - if (p == 0) - { - GenericErrInfo GEI; - VG_(maybe_record_error)(VG_(get_running_tid)(), - GenericErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Not a reader-writer lock", - &GEI); - return; - } - - DRD_(clientobj_remove)(rwlock, ClientRwlock); + struct rwlock_info* p; + + p = DRD_(rwlock_get)(rwlock); + if (p == 0) + { + GenericErrInfo GEI; + VG_(maybe_record_error)(VG_(get_running_tid)(), + GenericErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a reader-writer lock", + &GEI); + return; + } + + DRD_(clientobj_remove)(rwlock, ClientRwlock); } /** @@ -325,27 +327,27 @@ void DRD_(rwlock_post_destroy)(const Addr rwlock) */ void DRD_(rwlock_pre_rdlock)(const Addr rwlock) { - struct rwlock_info* p; - - if (DRD_(s_trace_rwlock)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] pre_rwlock_rdlock 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - rwlock); - } - - p = DRD_(rwlock_get_or_allocate)(rwlock); - tl_assert(p); - - if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)())) - { - VG_(message)(Vg_UserMsg, - "reader-writer lock 0x%lx is already locked for" - " writing by calling thread", - p->a1); - } + struct rwlock_info* p; + + if (DRD_(s_trace_rwlock)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] pre_rwlock_rdlock 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + rwlock); + } + + p = DRD_(rwlock_get_or_allocate)(rwlock); + tl_assert(p); + + if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)())) + { + VG_(message)(Vg_UserMsg, + "reader-writer lock 0x%lx is already locked for" + " writing by calling thread", + p->a1); + } } /** @@ -355,37 +357,37 @@ void DRD_(rwlock_pre_rdlock)(const Addr rwlock) */ void DRD_(rwlock_post_rdlock)(const Addr rwlock, const Bool took_lock) { - const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); - struct rwlock_info* p; - struct rwlock_thread_info* q; - - if (DRD_(s_trace_rwlock)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] post_rwlock_rdlock 0x%lx", - VG_(get_running_tid)(), - drd_tid, - rwlock); - } - - p = DRD_(rwlock_get)(rwlock); - - if (! p || ! took_lock) - return; - - tl_assert(! DRD_(rwlock_is_wrlocked)(p)); - - q = DRD_(lookup_or_insert_node)(p->thread_info, drd_tid); - if (++q->reader_nesting_count == 1) - { - DRD_(rwlock_combine_other_vc)(p, drd_tid, False); - q->last_lock_was_writer_lock = False; - DRD_(thread_new_segment)(drd_tid); - DRD_(s_rwlock_segment_creation_count)++; - - p->acquiry_time_ms = VG_(read_millisecond_timer)(); - p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); - } + const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); + struct rwlock_info* p; + struct rwlock_thread_info* q; + + if (DRD_(s_trace_rwlock)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] post_rwlock_rdlock 0x%lx", + VG_(get_running_tid)(), + drd_tid, + rwlock); + } + + p = DRD_(rwlock_get)(rwlock); + + if (! p || ! took_lock) + return; + + tl_assert(! DRD_(rwlock_is_wrlocked)(p)); + + q = DRD_(lookup_or_insert_node)(p->thread_info, drd_tid); + if (++q->reader_nesting_count == 1) + { + DRD_(rwlock_combine_other_vc)(p, drd_tid, False); + q->last_lock_was_writer_lock = False; + DRD_(thread_new_segment)(drd_tid); + DRD_(s_rwlock_segment_creation_count)++; + + p->acquiry_time_ms = VG_(read_millisecond_timer)(); + p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); + } } /** @@ -396,35 +398,35 @@ void DRD_(rwlock_post_rdlock)(const Addr rwlock, const Bool took_lock) */ void DRD_(rwlock_pre_wrlock)(const Addr rwlock) { - struct rwlock_info* p; - - p = DRD_(rwlock_get)(rwlock); - - if (DRD_(s_trace_rwlock)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] pre_rwlock_wrlock 0x%lx", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - rwlock); - } - - if (p == 0) - { - p = DRD_(rwlock_get_or_allocate)(rwlock); - } - - tl_assert(p); - - if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)())) - { - RwlockErrInfo REI = { p->a1 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - RwlockErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Recursive writer locking not allowed", - &REI); - } + struct rwlock_info* p; + + p = DRD_(rwlock_get)(rwlock); + + if (DRD_(s_trace_rwlock)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] pre_rwlock_wrlock 0x%lx", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + rwlock); + } + + if (p == 0) + { + p = DRD_(rwlock_get_or_allocate)(rwlock); + } + + tl_assert(p); + + if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)())) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + RwlockErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Recursive writer locking not allowed", + &REI); + } } /** @@ -434,35 +436,35 @@ void DRD_(rwlock_pre_wrlock)(const Addr rwlock) */ void DRD_(rwlock_post_wrlock)(const Addr rwlock, const Bool took_lock) { - const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); - struct rwlock_info* p; - struct rwlock_thread_info* q; - - p = DRD_(rwlock_get)(rwlock); - - if (DRD_(s_trace_rwlock)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] post_rwlock_wrlock 0x%lx", - VG_(get_running_tid)(), - drd_tid, - rwlock); - } - - if (! p || ! took_lock) - return; - - q = DRD_(lookup_or_insert_node)(p->thread_info, - DRD_(thread_get_running_tid)()); - tl_assert(q->writer_nesting_count == 0); - q->writer_nesting_count++; - q->last_lock_was_writer_lock = True; - tl_assert(q->writer_nesting_count == 1); - DRD_(rwlock_combine_other_vc)(p, drd_tid, True); - DRD_(thread_new_segment)(drd_tid); - DRD_(s_rwlock_segment_creation_count)++; - p->acquiry_time_ms = VG_(read_millisecond_timer)(); - p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); + const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); + struct rwlock_info* p; + struct rwlock_thread_info* q; + + p = DRD_(rwlock_get)(rwlock); + + if (DRD_(s_trace_rwlock)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] post_rwlock_wrlock 0x%lx", + VG_(get_running_tid)(), + drd_tid, + rwlock); + } + + if (! p || ! took_lock) + return; + + q = DRD_(lookup_or_insert_node)(p->thread_info, + DRD_(thread_get_running_tid)()); + tl_assert(q->writer_nesting_count == 0); + q->writer_nesting_count++; + q->last_lock_was_writer_lock = True; + tl_assert(q->writer_nesting_count == 1); + DRD_(rwlock_combine_other_vc)(p, drd_tid, True); + DRD_(thread_new_segment)(drd_tid); + DRD_(s_rwlock_segment_creation_count)++; + p->acquiry_time_ms = VG_(read_millisecond_timer)(); + p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); } /** @@ -477,94 +479,95 @@ void DRD_(rwlock_post_wrlock)(const Addr rwlock, const Bool took_lock) */ void DRD_(rwlock_pre_unlock)(const Addr rwlock) { - const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); - const ThreadId vg_tid = VG_(get_running_tid)(); - struct rwlock_info* p; - struct rwlock_thread_info* q; - - if (DRD_(s_trace_rwlock)) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] rwlock_unlock 0x%lx", - vg_tid, - drd_tid, - rwlock); - } - - p = DRD_(rwlock_get)(rwlock); - if (p == 0) - { - GenericErrInfo GEI; - VG_(maybe_record_error)(VG_(get_running_tid)(), - GenericErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Not a reader-writer lock", - &GEI); - return; - } - if (! DRD_(rwlock_is_locked_by)(p, drd_tid)) - { - RwlockErrInfo REI = { p->a1 }; - VG_(maybe_record_error)(vg_tid, - RwlockErr, - VG_(get_IP)(vg_tid), - "Reader-writer lock not locked by calling thread", - &REI); - return; - } - q = DRD_(lookup_or_insert_node)(p->thread_info, drd_tid); - tl_assert(q); - if (q->reader_nesting_count > 0) - { - q->reader_nesting_count--; - if (q->reader_nesting_count == 0 && DRD_(s_shared_threshold_ms) > 0) - { - ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms; - if (held > DRD_(s_shared_threshold_ms)) + const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); + const ThreadId vg_tid = VG_(get_running_tid)(); + struct rwlock_info* p; + struct rwlock_thread_info* q; + + if (DRD_(s_trace_rwlock)) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] rwlock_unlock 0x%lx", + vg_tid, + drd_tid, + rwlock); + } + + p = DRD_(rwlock_get)(rwlock); + if (p == 0) + { + GenericErrInfo GEI; + VG_(maybe_record_error)(VG_(get_running_tid)(), + GenericErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a reader-writer lock", + &GEI); + return; + } + if (! DRD_(rwlock_is_locked_by)(p, drd_tid)) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(vg_tid, + RwlockErr, + VG_(get_IP)(vg_tid), + "Reader-writer lock not locked by calling thread", + &REI); + return; + } + q = DRD_(lookup_or_insert_node)(p->thread_info, drd_tid); + tl_assert(q); + if (q->reader_nesting_count > 0) + { + q->reader_nesting_count--; + if (q->reader_nesting_count == 0 && DRD_(s_shared_threshold_ms) > 0) { - HoldtimeErrInfo HEI - = { rwlock, p->acquired_at, held, DRD_(s_shared_threshold_ms) }; - VG_(maybe_record_error)(vg_tid, - HoldtimeErr, - VG_(get_IP)(vg_tid), - "rwlock", - &HEI); + ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms; + if (held > DRD_(s_shared_threshold_ms)) + { + HoldtimeErrInfo HEI + = { rwlock, p->acquired_at, held, DRD_(s_shared_threshold_ms) }; + VG_(maybe_record_error)(vg_tid, + HoldtimeErr, + VG_(get_IP)(vg_tid), + "rwlock", + &HEI); + } } - } - } - else if (q->writer_nesting_count > 0) - { - q->writer_nesting_count--; - if (q->writer_nesting_count == 0 && DRD_(s_exclusive_threshold_ms) > 0) - { - ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms; - if (held > DRD_(s_exclusive_threshold_ms)) + } + else if (q->writer_nesting_count > 0) + { + q->writer_nesting_count--; + if (q->writer_nesting_count == 0 && DRD_(s_exclusive_threshold_ms) > 0) { - HoldtimeErrInfo HEI - = { rwlock, p->acquired_at, held, DRD_(s_exclusive_threshold_ms) }; - VG_(maybe_record_error)(vg_tid, - HoldtimeErr, - VG_(get_IP)(vg_tid), - "rwlock", - &HEI); + ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms; + if (held > DRD_(s_exclusive_threshold_ms)) + { + HoldtimeErrInfo HEI + = { rwlock, p->acquired_at, held, + DRD_(s_exclusive_threshold_ms) }; + VG_(maybe_record_error)(vg_tid, + HoldtimeErr, + VG_(get_IP)(vg_tid), + "rwlock", + &HEI); + } } - } - } - else - { - tl_assert(False); - } - - if (q->reader_nesting_count == 0 && q->writer_nesting_count == 0) - { - /* This pthread_rwlock_unlock() call really unlocks the rwlock. Save the */ - /* current vector clock of the thread such that it is available when */ - /* this rwlock is locked again. */ - - DRD_(thread_get_latest_segment)(&q->last_unlock_segment, drd_tid); - DRD_(thread_new_segment)(drd_tid); - DRD_(s_rwlock_segment_creation_count)++; - } + } + else + { + tl_assert(False); + } + + if (q->reader_nesting_count == 0 && q->writer_nesting_count == 0) + { + /* This pthread_rwlock_unlock() call really unlocks the rwlock. Save */ + /* the current vector clock of the thread such that it is available */ + /* when this rwlock is locked again. */ + + DRD_(thread_get_latest_segment)(&q->last_unlock_segment, drd_tid); + DRD_(thread_new_segment)(drd_tid); + DRD_(s_rwlock_segment_creation_count)++; + } } /** @@ -574,22 +577,22 @@ void DRD_(rwlock_pre_unlock)(const Addr rwlock) static void rwlock_delete_thread(struct rwlock_info* const p, const DrdThreadId tid) { - struct rwlock_thread_info* q; - if (DRD_(rwlock_is_locked_by)(p, tid)) - { - RwlockErrInfo REI = { p->a1 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - RwlockErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Reader-writer lock still locked at thread exit", - &REI); - q = DRD_(lookup_or_insert_node)(p->thread_info, tid); - q->reader_nesting_count = 0; - q->writer_nesting_count = 0; - } + struct rwlock_thread_info* q; + if (DRD_(rwlock_is_locked_by)(p, tid)) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + RwlockErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Reader-writer lock still locked at thread exit", + &REI); + q = DRD_(lookup_or_insert_node)(p->thread_info, tid); + q->reader_nesting_count = 0; + q->writer_nesting_count = 0; + } } ULong DRD_(get_rwlock_segment_creation_count)(void) { - return DRD_(s_rwlock_segment_creation_count); + return DRD_(s_rwlock_segment_creation_count); } diff --git a/drd/drd_rwlock.h b/drd/drd_rwlock.h index abb59c7bbf..e39a502891 100644 --- a/drd/drd_rwlock.h +++ b/drd/drd_rwlock.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. diff --git a/drd/drd_segment.c b/drd/drd_segment.c index 06972e4fd3..d513efae35 100644 --- a/drd/drd_segment.c +++ b/drd/drd_segment.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -58,110 +59,110 @@ static void sg_init(Segment* const sg, const DrdThreadId creator, const DrdThreadId created) { - Segment* creator_sg; - ThreadId vg_created = DRD_(DrdThreadIdToVgThreadId)(created); - - tl_assert(sg); - tl_assert(creator == DRD_INVALID_THREADID - || DRD_(IsValidDrdThreadId)(creator)); - - creator_sg = (creator != DRD_INVALID_THREADID - ? DRD_(thread_get_segment)(creator) : 0); - - sg->next = 0; - sg->prev = 0; - sg->refcnt = 1; - - if (vg_created != VG_INVALID_THREADID && VG_(get_SP)(vg_created) != 0) - sg->stacktrace = VG_(record_ExeContext)(vg_created, 0); - else - sg->stacktrace = 0; - - if (creator_sg) - DRD_(vc_copy)(&sg->vc, &creator_sg->vc); - else - DRD_(vc_init)(&sg->vc, 0, 0); - DRD_(vc_increment)(&sg->vc, created); - sg->bm = DRD_(bm_new)(); - - if (s_trace_segment) - { - char msg[256]; - VG_(snprintf)(msg, sizeof(msg), - "New segment for thread %d/%d with vc ", - created != VG_INVALID_THREADID - ? DRD_(DrdThreadIdToVgThreadId)(created) - : DRD_INVALID_THREADID, - created); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &sg->vc); - VG_(message)(Vg_UserMsg, "%s", msg); - } + Segment* creator_sg; + ThreadId vg_created = DRD_(DrdThreadIdToVgThreadId)(created); + + tl_assert(sg); + tl_assert(creator == DRD_INVALID_THREADID + || DRD_(IsValidDrdThreadId)(creator)); + + creator_sg = (creator != DRD_INVALID_THREADID + ? DRD_(thread_get_segment)(creator) : 0); + + sg->next = 0; + sg->prev = 0; + sg->refcnt = 1; + + if (vg_created != VG_INVALID_THREADID && VG_(get_SP)(vg_created) != 0) + sg->stacktrace = VG_(record_ExeContext)(vg_created, 0); + else + sg->stacktrace = 0; + + if (creator_sg) + DRD_(vc_copy)(&sg->vc, &creator_sg->vc); + else + DRD_(vc_init)(&sg->vc, 0, 0); + DRD_(vc_increment)(&sg->vc, created); + sg->bm = DRD_(bm_new)(); + + if (s_trace_segment) + { + char msg[256]; + VG_(snprintf)(msg, sizeof(msg), + "New segment for thread %d/%d with vc ", + created != VG_INVALID_THREADID + ? DRD_(DrdThreadIdToVgThreadId)(created) + : DRD_INVALID_THREADID, + created); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + &sg->vc); + VG_(message)(Vg_UserMsg, "%s", msg); + } } /** Deallocate the memory that was allocated by sg_init(). */ static void DRD_(sg_cleanup)(Segment* const sg) { - tl_assert(sg); - tl_assert(sg->refcnt == 0); + tl_assert(sg); + tl_assert(sg->refcnt == 0); - DRD_(vc_cleanup)(&sg->vc); - DRD_(bm_delete)(sg->bm); - sg->bm = 0; + DRD_(vc_cleanup)(&sg->vc); + DRD_(bm_delete)(sg->bm); + sg->bm = 0; } /** Allocate and initialize a new segment. */ Segment* DRD_(sg_new)(const DrdThreadId creator, const DrdThreadId created) { - Segment* sg; + Segment* sg; - s_segments_created_count++; - s_segments_alive_count++; - if (s_max_segments_alive_count < s_segments_alive_count) - s_max_segments_alive_count = s_segments_alive_count; + s_segments_created_count++; + s_segments_alive_count++; + if (s_max_segments_alive_count < s_segments_alive_count) + s_max_segments_alive_count = s_segments_alive_count; - sg = VG_(malloc)("drd.segment.sn.1", sizeof(*sg)); - tl_assert(sg); - sg_init(sg, creator, created); - return sg; + sg = VG_(malloc)("drd.segment.sn.1", sizeof(*sg)); + tl_assert(sg); + sg_init(sg, creator, created); + return sg; } static void DRD_(sg_delete)(Segment* const sg) { #if 1 - if (DRD_(sg_get_trace)()) - { - char msg[256]; - VG_(snprintf)(msg, sizeof(msg), - "Discarding the segment with vector clock "); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &sg->vc); - VG_(message)(Vg_UserMsg, "%s", msg); - } + if (DRD_(sg_get_trace)()) + { + char msg[256]; + VG_(snprintf)(msg, sizeof(msg), + "Discarding the segment with vector clock "); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + &sg->vc); + VG_(message)(Vg_UserMsg, "%s", msg); + } #endif - s_segments_alive_count--; + s_segments_alive_count--; - tl_assert(sg); - DRD_(sg_cleanup)(sg); - VG_(free)(sg); + tl_assert(sg); + DRD_(sg_cleanup)(sg); + VG_(free)(sg); } /** Query the reference count of the specified segment. */ int DRD_(sg_get_refcnt)(const Segment* const sg) { - tl_assert(sg); + tl_assert(sg); - return sg->refcnt; + return sg->refcnt; } /** Increment the reference count of the specified segment. */ Segment* DRD_(sg_get)(Segment* const sg) { - tl_assert(sg); + tl_assert(sg); - sg->refcnt++; - return sg; + sg->refcnt++; + return sg; } /** @@ -170,90 +171,90 @@ Segment* DRD_(sg_get)(Segment* const sg) */ void DRD_(sg_put)(Segment* const sg) { - if (sg == 0) - return; - - if (s_trace_segment) - { - char msg[256]; - VG_(snprintf)(msg, sizeof(msg), - "Decrementing segment reference count %d -> %d with vc ", - sg->refcnt, sg->refcnt - 1); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &sg->vc); - VG_(message)(Vg_UserMsg, "%s", msg); - } - - tl_assert(sg->refcnt >= 1); - - if (--sg->refcnt == 0) - { - DRD_(sg_delete)(sg); - } + if (sg == 0) + return; + + if (s_trace_segment) + { + char msg[256]; + VG_(snprintf)(msg, sizeof(msg), + "Decrementing segment reference count %d -> %d with vc ", + sg->refcnt, sg->refcnt - 1); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + &sg->vc); + VG_(message)(Vg_UserMsg, "%s", msg); + } + + tl_assert(sg->refcnt >= 1); + + if (--sg->refcnt == 0) + { + DRD_(sg_delete)(sg); + } } /** Merge sg1 and sg2 into sg1. */ void DRD_(sg_merge)(const Segment* const sg1, Segment* const sg2) { - tl_assert(sg1); - tl_assert(sg1->refcnt == 1); - tl_assert(sg2); - tl_assert(sg2->refcnt == 1); + tl_assert(sg1); + tl_assert(sg1->refcnt == 1); + tl_assert(sg2); + tl_assert(sg2->refcnt == 1); - if (s_trace_segment) - { + if (s_trace_segment) + { char msg[256]; VG_(snprintf)(msg, sizeof(msg), "Merging segments with vector clocks "); DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &sg1->vc); + &sg1->vc); VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), " and "); DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &sg2->vc); + &sg2->vc); VG_(message)(Vg_UserMsg, "%s", msg); - } + } - // Keep sg1->stacktrace. - // Keep sg1->vc. - // Merge sg2->bm into sg1->bm. - DRD_(bm_merge2)(sg1->bm, sg2->bm); + // Keep sg1->stacktrace. + // Keep sg1->vc. + // Merge sg2->bm into sg1->bm. + DRD_(bm_merge2)(sg1->bm, sg2->bm); } /** Print the vector clock and the bitmap of the specified segment. */ void DRD_(sg_print)(const Segment* const sg) { - tl_assert(sg); - VG_(printf)("vc: "); - DRD_(vc_print)(&sg->vc); - VG_(printf)("\n"); - DRD_(bm_print)(sg->bm); + tl_assert(sg); + VG_(printf)("vc: "); + DRD_(vc_print)(&sg->vc); + VG_(printf)("\n"); + DRD_(bm_print)(sg->bm); } /** Query whether segment tracing has been enabled. */ Bool DRD_(sg_get_trace)(void) { - return s_trace_segment; + return s_trace_segment; } /** Enable or disable segment tracing. */ void DRD_(sg_set_trace)(Bool const trace_segment) { - tl_assert(trace_segment == False || trace_segment == True); - s_trace_segment = trace_segment; + tl_assert(trace_segment == False || trace_segment == True); + s_trace_segment = trace_segment; } ULong DRD_(sg_get_segments_created_count)(void) { - return s_segments_created_count; + return s_segments_created_count; } ULong DRD_(sg_get_segments_alive_count)(void) { - return s_segments_alive_count; + return s_segments_alive_count; } ULong DRD_(sg_get_max_segments_alive_count)(void) { - return s_max_segments_alive_count; + return s_max_segments_alive_count; } diff --git a/drd/drd_segment.h b/drd/drd_segment.h index 012cca60e9..8658fae02c 100644 --- a/drd/drd_segment.h +++ b/drd/drd_segment.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -41,20 +42,20 @@ typedef struct segment { - /** Pointers to next and previous segments executed by the same thread. */ - struct segment* next; - struct segment* prev; - /** Reference count: number of pointers that point to this segment. */ - int refcnt; - /** Stack trace of the first instruction of the segment. */ - ExeContext* stacktrace; - /** Vector clock associated with the segment. */ - VectorClock vc; - /** - * Bitmap representing the memory accesses by the instructions associated - * with the segment. - */ - struct bitmap* bm; + /** Pointers to next and previous segments executed by the same thread. */ + struct segment* next; + struct segment* prev; + /** Reference count: number of pointers that point to this segment. */ + int refcnt; + /** Stack trace of the first instruction of the segment. */ + ExeContext* stacktrace; + /** Vector clock associated with the segment. */ + VectorClock vc; + /** + * Bitmap representing the memory accesses by the instructions associated + * with the segment. + */ + struct bitmap* bm; } Segment; diff --git a/drd/drd_semaphore.c b/drd/drd_semaphore.c index 02d5c7d4f6..362a9bde87 100644 --- a/drd/drd_semaphore.c +++ b/drd/drd_semaphore.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -50,42 +51,42 @@ static ULong s_semaphore_segment_creation_count; /** Push a segment at the end of the queue 'p->last_sem_post_seg'. */ static void DRD_(segment_push)(struct semaphore_info* p, Segment* sg) { - Word n; + Word n; - tl_assert(sg); - n = VG_(addToXA)(p->last_sem_post_seg, &sg); + tl_assert(sg); + n = VG_(addToXA)(p->last_sem_post_seg, &sg); #if 0 - VG_(message)(Vg_UserMsg, "0x%lx push: added at position %ld/%ld", - p->a1, n, VG_(sizeXA)(p->last_sem_post_seg)); + VG_(message)(Vg_UserMsg, "0x%lx push: added at position %ld/%ld", + p->a1, n, VG_(sizeXA)(p->last_sem_post_seg)); #endif - tl_assert(*(Segment**)VG_(indexXA)(p->last_sem_post_seg, n) == sg); + tl_assert(*(Segment**)VG_(indexXA)(p->last_sem_post_seg, n) == sg); } /** Pop a segment from the beginning of the queue 'p->last_sem_post_seg'. */ static Segment* DRD_(segment_pop)(struct semaphore_info* p) { - Word sz; - Segment* sg; + Word sz; + Segment* sg; - sz = VG_(sizeXA)(p->last_sem_post_seg); + sz = VG_(sizeXA)(p->last_sem_post_seg); #if 0 - VG_(message)(Vg_UserMsg, "0x%lx pop: removed from position %ld/%ld", - p->a1, sz - 1, sz); + VG_(message)(Vg_UserMsg, "0x%lx pop: removed from position %ld/%ld", + p->a1, sz - 1, sz); #endif - sg = 0; - if (sz > 0) - { - sg = *(Segment**)VG_(indexXA)(p->last_sem_post_seg, sz - 1); - tl_assert(sg); - VG_(dropTailXA)(p->last_sem_post_seg, 1); - } - return sg; + sg = 0; + if (sz > 0) + { + sg = *(Segment**)VG_(indexXA)(p->last_sem_post_seg, sz - 1); + tl_assert(sg); + VG_(dropTailXA)(p->last_sem_post_seg, 1); + } + return sg; } /** Enable or disable tracing of semaphore actions. */ void DRD_(semaphore_set_trace)(const Bool trace_semaphore) { - s_trace_semaphore = trace_semaphore; + s_trace_semaphore = trace_semaphore; } /** @@ -96,18 +97,18 @@ static void DRD_(semaphore_initialize)(struct semaphore_info* const p, const Addr semaphore) { - tl_assert(semaphore != 0); - tl_assert(p->a1 == semaphore); - tl_assert(p->type == ClientSemaphore); - - p->cleanup = (void(*)(DrdClientobj*))semaphore_cleanup; - p->delete_thread = 0; - p->waits_to_skip = 0; - p->value = 0; - p->waiters = 0; - p->last_sem_post_tid = DRD_INVALID_THREADID; - p->last_sem_post_seg = VG_(newXA)(VG_(malloc), "drd.sg-stack", - VG_(free), sizeof(Segment*)); + tl_assert(semaphore != 0); + tl_assert(p->a1 == semaphore); + tl_assert(p->type == ClientSemaphore); + + p->cleanup = (void(*)(DrdClientobj*))semaphore_cleanup; + p->delete_thread = 0; + p->waits_to_skip = 0; + p->value = 0; + p->waiters = 0; + p->last_sem_post_tid = DRD_INVALID_THREADID; + p->last_sem_post_seg = VG_(newXA)(VG_(malloc), "drd.sg-stack", + VG_(free), sizeof(Segment*)); } /** @@ -116,21 +117,21 @@ void DRD_(semaphore_initialize)(struct semaphore_info* const p, */ static void semaphore_cleanup(struct semaphore_info* p) { - Segment* sg; - - if (p->waiters > 0) - { - SemaphoreErrInfo sei = { p->a1 }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - SemaphoreErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Destruction of semaphore that is being waited" - " upon", - &sei); - } - while ((sg = DRD_(segment_pop)(p))) - DRD_(sg_put)(sg); - VG_(deleteXA)(p->last_sem_post_seg); + Segment* sg; + + if (p->waiters > 0) + { + SemaphoreErrInfo sei = { p->a1 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + SemaphoreErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Destruction of semaphore that is being waited" + " upon", + &sei); + } + while ((sg = DRD_(segment_pop)(p))) + DRD_(sg_put)(sg); + VG_(deleteXA)(p->last_sem_post_seg); } /** @@ -142,17 +143,17 @@ static struct semaphore_info* DRD_(semaphore_get_or_allocate)(const Addr semaphore) { - struct semaphore_info *p; - - tl_assert(offsetof(DrdClientobj, semaphore) == 0); - p = &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore); - if (p == 0) - { - tl_assert(offsetof(DrdClientobj, semaphore) == 0); - p = &(DRD_(clientobj_add)(semaphore, ClientSemaphore)->semaphore); - DRD_(semaphore_initialize)(p, semaphore); - } - return p; + struct semaphore_info *p; + + tl_assert(offsetof(DrdClientobj, semaphore) == 0); + p = &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore); + if (p == 0) + { + tl_assert(offsetof(DrdClientobj, semaphore) == 0); + p = &(DRD_(clientobj_add)(semaphore, ClientSemaphore)->semaphore); + DRD_(semaphore_initialize)(p, semaphore); + } + return p; } /** @@ -161,8 +162,8 @@ DRD_(semaphore_get_or_allocate)(const Addr semaphore) */ static struct semaphore_info* DRD_(semaphore_get)(const Addr semaphore) { - tl_assert(offsetof(DrdClientobj, semaphore) == 0); - return &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore); + tl_assert(offsetof(DrdClientobj, semaphore) == 0); + return &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore); } /** Called before sem_init(). */ @@ -170,85 +171,85 @@ struct semaphore_info* DRD_(semaphore_init)(const Addr semaphore, const Word pshared, const UInt value) { - struct semaphore_info* p; - Segment* sg; - - if (s_trace_semaphore) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] semaphore_init 0x%lx value %u", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - semaphore, - value); - } - p = DRD_(semaphore_get)(semaphore); - if (p) - { - const ThreadId vg_tid = VG_(get_running_tid)(); - SemaphoreErrInfo SEI = { semaphore }; - VG_(maybe_record_error)(vg_tid, - SemaphoreErr, - VG_(get_IP)(vg_tid), - "Semaphore reinitialization", - &SEI); - // Remove all segments from the segment stack. - while ((sg = DRD_(segment_pop)(p))) - { - DRD_(sg_put)(sg); - } - } - else - { - p = DRD_(semaphore_get_or_allocate)(semaphore); - } - tl_assert(p); - p->waits_to_skip = value; - p->value = value; - return p; + struct semaphore_info* p; + Segment* sg; + + if (s_trace_semaphore) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] semaphore_init 0x%lx value %u", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + semaphore, + value); + } + p = DRD_(semaphore_get)(semaphore); + if (p) + { + const ThreadId vg_tid = VG_(get_running_tid)(); + SemaphoreErrInfo SEI = { semaphore }; + VG_(maybe_record_error)(vg_tid, + SemaphoreErr, + VG_(get_IP)(vg_tid), + "Semaphore reinitialization", + &SEI); + // Remove all segments from the segment stack. + while ((sg = DRD_(segment_pop)(p))) + { + DRD_(sg_put)(sg); + } + } + else + { + p = DRD_(semaphore_get_or_allocate)(semaphore); + } + tl_assert(p); + p->waits_to_skip = value; + p->value = value; + return p; } /** Called after sem_destroy(). */ void DRD_(semaphore_destroy)(const Addr semaphore) { - struct semaphore_info* p; - - p = DRD_(semaphore_get)(semaphore); - - if (s_trace_semaphore) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] semaphore_destroy 0x%lx value %u", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - semaphore, - p ? p->value : 0); - } - - if (p == 0) - { - GenericErrInfo GEI; - VG_(maybe_record_error)(VG_(get_running_tid)(), - GenericErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Not a semaphore", - &GEI); - return; - } - - DRD_(clientobj_remove)(semaphore, ClientSemaphore); + struct semaphore_info* p; + + p = DRD_(semaphore_get)(semaphore); + + if (s_trace_semaphore) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] semaphore_destroy 0x%lx value %u", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + semaphore, + p ? p->value : 0); + } + + if (p == 0) + { + GenericErrInfo GEI; + VG_(maybe_record_error)(VG_(get_running_tid)(), + GenericErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a semaphore", + &GEI); + return; + } + + DRD_(clientobj_remove)(semaphore, ClientSemaphore); } /** Called before sem_wait(). */ void DRD_(semaphore_pre_wait)(const Addr semaphore) { - struct semaphore_info* p; + struct semaphore_info* p; - p = DRD_(semaphore_get_or_allocate)(semaphore); - tl_assert(p); - tl_assert((int)p->waiters >= 0); - p->waiters++; - tl_assert(p->waiters > 0); + p = DRD_(semaphore_get_or_allocate)(semaphore); + tl_assert(p); + tl_assert((int)p->waiters >= 0); + p->waiters++; + tl_assert(p->waiters > 0); } /** @@ -259,101 +260,101 @@ void DRD_(semaphore_pre_wait)(const Addr semaphore) void DRD_(semaphore_post_wait)(const DrdThreadId tid, const Addr semaphore, const Bool waited) { - struct semaphore_info* p; - Segment* sg; - - p = DRD_(semaphore_get)(semaphore); - if (s_trace_semaphore) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] semaphore_wait 0x%lx value %u -> %u", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - semaphore, - p ? p->value : 0, - p ? p->value - 1 : 0); - } - tl_assert(p); - tl_assert(p->waiters > 0); - p->waiters--; - tl_assert((int)p->waiters >= 0); - tl_assert((int)p->value >= 0); - if (p->value == 0) - { - SemaphoreErrInfo sei = { semaphore }; - VG_(maybe_record_error)(VG_(get_running_tid)(), - SemaphoreErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Invalid semaphore", - &sei); - return; - } - p->value--; - tl_assert((int)p->value >= 0); - if (p->waits_to_skip > 0) - p->waits_to_skip--; - else - { - sg = DRD_(segment_pop)(p); - tl_assert(sg); - if (sg) - { - if (p->last_sem_post_tid != tid - && p->last_sem_post_tid != DRD_INVALID_THREADID) + struct semaphore_info* p; + Segment* sg; + + p = DRD_(semaphore_get)(semaphore); + if (s_trace_semaphore) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] semaphore_wait 0x%lx value %u -> %u", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + semaphore, + p ? p->value : 0, + p ? p->value - 1 : 0); + } + tl_assert(p); + tl_assert(p->waiters > 0); + p->waiters--; + tl_assert((int)p->waiters >= 0); + tl_assert((int)p->value >= 0); + if (p->value == 0) + { + SemaphoreErrInfo sei = { semaphore }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + SemaphoreErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Invalid semaphore", + &sei); + return; + } + p->value--; + tl_assert((int)p->value >= 0); + if (p->waits_to_skip > 0) + p->waits_to_skip--; + else + { + sg = DRD_(segment_pop)(p); + tl_assert(sg); + if (sg) { - DRD_(thread_combine_vc2)(tid, &sg->vc); + if (p->last_sem_post_tid != tid + && p->last_sem_post_tid != DRD_INVALID_THREADID) + { + DRD_(thread_combine_vc2)(tid, &sg->vc); + } + DRD_(sg_put)(sg); + DRD_(thread_new_segment)(tid); + s_semaphore_segment_creation_count++; } - DRD_(sg_put)(sg); - DRD_(thread_new_segment)(tid); - s_semaphore_segment_creation_count++; - } - } + } } /** Called before sem_post(). */ void DRD_(semaphore_pre_post)(const DrdThreadId tid, const Addr semaphore) { - struct semaphore_info* p; - Segment* sg; - - p = DRD_(semaphore_get_or_allocate)(semaphore); - p->value++; - - if (s_trace_semaphore) - { - VG_(message)(Vg_UserMsg, - "[%d/%d] semaphore_post 0x%lx value %u -> %u", - VG_(get_running_tid)(), - DRD_(thread_get_running_tid)(), - semaphore, - p->value - 1, p->value); - } - - p->last_sem_post_tid = tid; - DRD_(thread_new_segment)(tid); - sg = 0; - DRD_(thread_get_latest_segment)(&sg, tid); - tl_assert(sg); - DRD_(segment_push)(p, sg); - s_semaphore_segment_creation_count++; + struct semaphore_info* p; + Segment* sg; + + p = DRD_(semaphore_get_or_allocate)(semaphore); + p->value++; + + if (s_trace_semaphore) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] semaphore_post 0x%lx value %u -> %u", + VG_(get_running_tid)(), + DRD_(thread_get_running_tid)(), + semaphore, + p->value - 1, p->value); + } + + p->last_sem_post_tid = tid; + DRD_(thread_new_segment)(tid); + sg = 0; + DRD_(thread_get_latest_segment)(&sg, tid); + tl_assert(sg); + DRD_(segment_push)(p, sg); + s_semaphore_segment_creation_count++; } /** Called after sem_post() finished successfully. */ void DRD_(semaphore_post_post)(const DrdThreadId tid, const Addr semaphore, const Bool waited) { - /* Note: it is hard to implement the sem_post() wrapper correctly in */ - /* case sem_post() returns an error code. This is because handling this */ - /* case correctly requires restoring the vector clock associated with */ - /* the semaphore to its original value here. In order to do that without */ - /* introducing a race condition, extra locking has to be added around */ - /* each semaphore call. Such extra locking would have to be added in */ - /* drd_intercepts.c. However, it is hard to implement synchronization */ - /* in drd_intercepts.c in a portable way without calling already */ - /* redirected functions. */ + /* Note: it is hard to implement the sem_post() wrapper correctly in */ + /* case sem_post() returns an error code. This is because handling this */ + /* case correctly requires restoring the vector clock associated with */ + /* the semaphore to its original value here. In order to do that without */ + /* introducing a race condition, extra locking has to be added around */ + /* each semaphore call. Such extra locking would have to be added in */ + /* drd_intercepts.c. However, it is hard to implement synchronization */ + /* in drd_intercepts.c in a portable way without calling already */ + /* redirected functions. */ } ULong DRD_(get_semaphore_segment_creation_count)(void) { - return s_semaphore_segment_creation_count; + return s_semaphore_segment_creation_count; } diff --git a/drd/drd_semaphore.h b/drd/drd_semaphore.h index e6b248fab8..b9cc1e1c5c 100644 --- a/drd/drd_semaphore.h +++ b/drd/drd_semaphore.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. diff --git a/drd/drd_strmem_intercepts.c b/drd/drd_strmem_intercepts.c index ca498eb385..5d23df30be 100644 --- a/drd/drd_strmem_intercepts.c +++ b/drd/drd_strmem_intercepts.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /*--------------------------------------------------------------------*/ /*--- Replacements for strlen() and strnlen(), which run on the ---*/ @@ -5,30 +6,30 @@ /*--------------------------------------------------------------------*/ /* - This file is part of DRD, a heavyweight Valgrind tool for - detecting threading errors. The code below has been extracted - from memchec/mc_replace_strmem.c, which has the following copyright - notice: + This file is part of DRD, a heavyweight Valgrind tool for + detecting threading errors. The code below has been extracted + from memchec/mc_replace_strmem.c, which has the following copyright + notice: - Copyright (C) 2000-2009 Julian Seward - jseward@acm.org + Copyright (C) 2000-2009 Julian Seward + jseward@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 - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. - The GNU General Public License is contained in the file COPYING. + The GNU General Public License is contained in the file COPYING. */ #include "pub_tool_basics.h" @@ -38,13 +39,13 @@ #include "valgrind.h" -#define STRNLEN(soname, fnname) \ +#define STRNLEN(soname, fnname) \ SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \ SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \ - { \ - SizeT i = 0; \ - while (i < n && str[i] != 0) i++; \ - return i; \ + { \ + SizeT i = 0; \ + while (i < n && str[i] != 0) i++; \ + return i; \ } STRNLEN(VG_Z_LIBC_SONAME, strnlen) @@ -54,13 +55,13 @@ STRNLEN(VG_Z_LIBC_SONAME, strnlen) // calls to strlen() with its own built-in version. This can be very // confusing if you aren't expecting it. Other small functions in this file // may also be inline by gcc. -#define STRLEN(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \ - { \ - SizeT i = 0; \ - while (str[i] != 0) i++; \ - return i; \ +#define STRLEN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \ + SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \ + { \ + SizeT i = 0; \ + while (str[i] != 0) i++; \ + return i; \ } STRLEN(VG_Z_LIBC_SONAME, strlen) diff --git a/drd/drd_suppression.c b/drd/drd_suppression.c index 0ed2e55a8b..8b7a55e844 100644 --- a/drd/drd_suppression.c +++ b/drd/drd_suppression.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -50,42 +51,42 @@ void DRD_(suppression_set_trace)(const Bool trace_suppression) void DRD_(suppression_init)(void) { - tl_assert(DRD_(s_suppressed) == 0); - DRD_(s_suppressed) = DRD_(bm_new)(); - tl_assert(DRD_(s_suppressed)); + tl_assert(DRD_(s_suppressed) == 0); + DRD_(s_suppressed) = DRD_(bm_new)(); + tl_assert(DRD_(s_suppressed)); } void DRD_(start_suppression)(const Addr a1, const Addr a2, const char* const reason) { - if (DRD_(s_trace_suppression)) - { - VG_(message)(Vg_DebugMsg, "start suppression of 0x%lx sz %ld (%s)", - a1, a2 - a1, reason); - } - - tl_assert(a1 < a2); - // tl_assert(! drd_is_any_suppressed(a1, a2)); - DRD_(bm_access_range_store)(DRD_(s_suppressed), a1, a2); + if (DRD_(s_trace_suppression)) + { + VG_(message)(Vg_DebugMsg, "start suppression of 0x%lx sz %ld (%s)", + a1, a2 - a1, reason); + } + + tl_assert(a1 < a2); + // tl_assert(! drd_is_any_suppressed(a1, a2)); + DRD_(bm_access_range_store)(DRD_(s_suppressed), a1, a2); } void DRD_(finish_suppression)(const Addr a1, const Addr a2) { - if (DRD_(s_trace_suppression)) - { - VG_(message)(Vg_DebugMsg, "finish suppression of 0x%lx sz %ld", - a1, a2 - a1); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); - } - - tl_assert(a1 < a2); - if (! DRD_(is_suppressed)(a1, a2)) - { - VG_(message)(Vg_DebugMsg, "?? [0x%lx,0x%lx[ not suppressed ??", a1, a2); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); - tl_assert(False); - } - DRD_(bm_clear_store)(DRD_(s_suppressed), a1, a2); + if (DRD_(s_trace_suppression)) + { + VG_(message)(Vg_DebugMsg, "finish suppression of 0x%lx sz %ld", + a1, a2 - a1); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); + } + + tl_assert(a1 < a2); + if (! DRD_(is_suppressed)(a1, a2)) + { + VG_(message)(Vg_DebugMsg, "?? [0x%lx,0x%lx[ not suppressed ??", a1, a2); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); + tl_assert(False); + } + DRD_(bm_clear_store)(DRD_(s_suppressed), a1, a2); } /** @@ -95,7 +96,7 @@ void DRD_(finish_suppression)(const Addr a1, const Addr a2) */ Bool DRD_(is_suppressed)(const Addr a1, const Addr a2) { - return DRD_(bm_has)(DRD_(s_suppressed), a1, a2, eStore); + return DRD_(bm_has)(DRD_(s_suppressed), a1, a2, eStore); } /** @@ -105,53 +106,53 @@ Bool DRD_(is_suppressed)(const Addr a1, const Addr a2) */ Bool DRD_(is_any_suppressed)(const Addr a1, const Addr a2) { - return DRD_(bm_has_any_store)(DRD_(s_suppressed), a1, a2); + return DRD_(bm_has_any_store)(DRD_(s_suppressed), a1, a2); } void DRD_(start_tracing_address_range)(const Addr a1, const Addr a2) { - tl_assert(a1 < a2); + tl_assert(a1 < a2); - DRD_(bm_access_range_load)(DRD_(s_suppressed), a1, a2); - if (! DRD_(g_any_address_traced)) - { - DRD_(g_any_address_traced) = True; - } + DRD_(bm_access_range_load)(DRD_(s_suppressed), a1, a2); + if (! DRD_(g_any_address_traced)) + { + DRD_(g_any_address_traced) = True; + } } void DRD_(stop_tracing_address_range)(const Addr a1, const Addr a2) { - tl_assert(a1 < a2); - - DRD_(bm_clear_load)(DRD_(s_suppressed), a1, a2); - if (DRD_(g_any_address_traced)) - { - DRD_(g_any_address_traced) - = DRD_(bm_has_any_load)(DRD_(s_suppressed), 0, ~(Addr)0); - } + tl_assert(a1 < a2); + + DRD_(bm_clear_load)(DRD_(s_suppressed), a1, a2); + if (DRD_(g_any_address_traced)) + { + DRD_(g_any_address_traced) + = DRD_(bm_has_any_load)(DRD_(s_suppressed), 0, ~(Addr)0); + } } Bool DRD_(is_any_traced)(const Addr a1, const Addr a2) { - return DRD_(bm_has_any_load)(DRD_(s_suppressed), a1, a2); + return DRD_(bm_has_any_load)(DRD_(s_suppressed), a1, a2); } void DRD_(suppression_stop_using_mem)(const Addr a1, const Addr a2) { - if (DRD_(s_trace_suppression)) - { - Addr b; - for (b = a1; b < a2; b++) - { - if (DRD_(bm_has_1)(DRD_(s_suppressed), b, eStore)) + if (DRD_(s_trace_suppression)) + { + Addr b; + for (b = a1; b < a2; b++) { - VG_(message)(Vg_DebugMsg, - "stop_using_mem(0x%lx, %ld) finish suppression of 0x%lx", - a1, a2 - a1, b); + if (DRD_(bm_has_1)(DRD_(s_suppressed), b, eStore)) + { + VG_(message)(Vg_DebugMsg, + "stop_using_mem(0x%lx, %ld) finish suppression of" + " 0x%lx", a1, a2 - a1, b); + } } - } - } - tl_assert(a1); - tl_assert(a1 < a2); - DRD_(bm_clear)(DRD_(s_suppressed), a1, a2); + } + tl_assert(a1); + tl_assert(a1 < a2); + DRD_(bm_clear)(DRD_(s_suppressed), a1, a2); } diff --git a/drd/drd_suppression.h b/drd/drd_suppression.h index 94848221cc..9d93b945c2 100644 --- a/drd/drd_suppression.h +++ b/drd/drd_suppression.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ #ifndef __PUB_CORE_DRD_H #define __PUB_CORE_DRD_H @@ -12,7 +13,7 @@ extern Bool DRD_(g_any_address_traced); void DRD_(suppression_set_trace)(const Bool trace_suppression); void DRD_(suppression_init)(void); void DRD_(start_suppression)(const Addr a1, const Addr a2, - const char* const reason); + const char* const reason); void DRD_(finish_suppression)(const Addr a1, const Addr a2); Bool DRD_(is_suppressed)(const Addr a1, const Addr a2); Bool DRD_(is_any_suppressed)(const Addr a1, const Addr a2); @@ -24,7 +25,7 @@ void DRD_(suppression_stop_using_mem)(const Addr a1, const Addr a2); static __inline__ Bool DRD_(any_address_is_traced)(void) { - return DRD_(g_any_address_traced); + return DRD_(g_any_address_traced); } diff --git a/drd/drd_thread.c b/drd/drd_thread.c index 90bd110afc..2b692b143d 100644 --- a/drd/drd_thread.c +++ b/drd/drd_thread.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -77,35 +78,35 @@ static Bool s_segment_merging = True; /** Enables/disables context switch tracing. */ void DRD_(thread_trace_context_switches)(const Bool t) { - tl_assert(t == False || t == True); - s_trace_context_switches = t; + tl_assert(t == False || t == True); + s_trace_context_switches = t; } /** Enables/disables conflict set tracing. */ void DRD_(thread_trace_conflict_set)(const Bool t) { - tl_assert(t == False || t == True); - s_trace_conflict_set = t; + tl_assert(t == False || t == True); + s_trace_conflict_set = t; } /** Report whether fork/join tracing is enabled. */ Bool DRD_(thread_get_trace_fork_join)(void) { - return s_trace_fork_join; + return s_trace_fork_join; } /** Enables/disables fork/join tracing. */ void DRD_(thread_set_trace_fork_join)(const Bool t) { - tl_assert(t == False || t == True); - s_trace_fork_join = t; + tl_assert(t == False || t == True); + s_trace_fork_join = t; } /** Enables/disables segment merging. */ void DRD_(thread_set_segment_merging)(const Bool m) { - tl_assert(m == False || m == True); - s_segment_merging = m; + tl_assert(m == False || m == True); + s_segment_merging = m; } /** @@ -116,87 +117,87 @@ void DRD_(thread_set_segment_merging)(const Bool m) */ DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid) { - int i; + int i; - if (tid == VG_INVALID_THREADID) - return DRD_INVALID_THREADID; + if (tid == VG_INVALID_THREADID) + return DRD_INVALID_THREADID; - for (i = 1; i < DRD_N_THREADS; i++) - { - if (DRD_(g_threadinfo)[i].vg_thread_exists == True - && DRD_(g_threadinfo)[i].vg_threadid == tid) - { - return i; - } - } + for (i = 1; i < DRD_N_THREADS; i++) + { + if (DRD_(g_threadinfo)[i].vg_thread_exists == True + && DRD_(g_threadinfo)[i].vg_threadid == tid) + { + return i; + } + } - return DRD_INVALID_THREADID; + return DRD_INVALID_THREADID; } /** Allocate a new DRD thread ID for the specified Valgrind thread ID. */ static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid) { - int i; - - tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID); - - for (i = 1; i < DRD_N_THREADS; i++) - { - if (DRD_(g_threadinfo)[i].vg_thread_exists == False - && DRD_(g_threadinfo)[i].posix_thread_exists == False - && DRD_(g_threadinfo)[i].detached_posix_thread == False) - { - tl_assert(! DRD_(IsValidDrdThreadId)(i)); - - DRD_(g_threadinfo)[i].vg_thread_exists = True; - DRD_(g_threadinfo)[i].vg_threadid = tid; - DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID; - DRD_(g_threadinfo)[i].stack_min = 0; - DRD_(g_threadinfo)[i].stack_min_min = 0; - DRD_(g_threadinfo)[i].stack_startup = 0; - DRD_(g_threadinfo)[i].stack_max = 0; - DRD_(g_threadinfo)[i].is_recording = True; - DRD_(g_threadinfo)[i].synchr_nesting = 0; - tl_assert(DRD_(g_threadinfo)[i].first == 0); - tl_assert(DRD_(g_threadinfo)[i].last == 0); - - tl_assert(DRD_(IsValidDrdThreadId)(i)); - - return i; - } - } - - tl_assert(False); - - return DRD_INVALID_THREADID; + int i; + + tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID); + + for (i = 1; i < DRD_N_THREADS; i++) + { + if (DRD_(g_threadinfo)[i].vg_thread_exists == False + && DRD_(g_threadinfo)[i].posix_thread_exists == False + && DRD_(g_threadinfo)[i].detached_posix_thread == False) + { + tl_assert(! DRD_(IsValidDrdThreadId)(i)); + + DRD_(g_threadinfo)[i].vg_thread_exists = True; + DRD_(g_threadinfo)[i].vg_threadid = tid; + DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID; + DRD_(g_threadinfo)[i].stack_min = 0; + DRD_(g_threadinfo)[i].stack_min_min = 0; + DRD_(g_threadinfo)[i].stack_startup = 0; + DRD_(g_threadinfo)[i].stack_max = 0; + DRD_(g_threadinfo)[i].is_recording = True; + DRD_(g_threadinfo)[i].synchr_nesting = 0; + tl_assert(DRD_(g_threadinfo)[i].first == 0); + tl_assert(DRD_(g_threadinfo)[i].last == 0); + + tl_assert(DRD_(IsValidDrdThreadId)(i)); + + return i; + } + } + + tl_assert(False); + + return DRD_INVALID_THREADID; } /** Convert a POSIX thread ID into a DRD thread ID. */ DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid) { - int i; - - tl_assert(tid != INVALID_POSIX_THREADID); - - for (i = 1; i < DRD_N_THREADS; i++) - { - if (DRD_(g_threadinfo)[i].posix_thread_exists - && DRD_(g_threadinfo)[i].pt_threadid == tid) - { - return i; - } - } - return DRD_INVALID_THREADID; + int i; + + tl_assert(tid != INVALID_POSIX_THREADID); + + for (i = 1; i < DRD_N_THREADS; i++) + { + if (DRD_(g_threadinfo)[i].posix_thread_exists + && DRD_(g_threadinfo)[i].pt_threadid == tid) + { + return i; + } + } + return DRD_INVALID_THREADID; } /** Convert a DRD thread ID into a Valgrind thread ID. */ ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - return (DRD_(g_threadinfo)[tid].vg_thread_exists - ? DRD_(g_threadinfo)[tid].vg_threadid - : VG_INVALID_THREADID); + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + return (DRD_(g_threadinfo)[tid].vg_thread_exists + ? DRD_(g_threadinfo)[tid].vg_threadid + : VG_INVALID_THREADID); } #if 0 @@ -207,20 +208,20 @@ ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid) */ static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti) { - Segment* p; - for (p = ti->first; p; p = p->next) { - if (p->next && p->next->prev != p) - return False; - if (p->next == 0 && p != ti->last) - return False; - } - for (p = ti->last; p; p = p->prev) { - if (p->prev && p->prev->next != p) - return False; - if (p->prev == 0 && p != ti->first) - return False; - } - return True; + Segment* p; + for (p = ti->first; p; p = p->next) { + if (p->next && p->next->prev != p) + return False; + if (p->next == 0 && p != ti->last) + return False; + } + for (p = ti->last; p; p = p->prev) { + if (p->prev && p->prev->next != p) + return False; + if (p->prev == 0 && p != ti->first) + return False; + } + return True; } #endif @@ -240,18 +241,18 @@ static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti) DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator, const ThreadId vg_created) { - DrdThreadId created; + DrdThreadId created; - tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID); - created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created); - tl_assert(0 <= (int)created && created < DRD_N_THREADS - && created != DRD_INVALID_THREADID); + tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID); + created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created); + tl_assert(0 <= (int)created && created < DRD_N_THREADS + && created != DRD_INVALID_THREADID); - tl_assert(DRD_(g_threadinfo)[created].first == 0); - tl_assert(DRD_(g_threadinfo)[created].last == 0); - thread_append_segment(created, DRD_(sg_new)(creator, created)); + tl_assert(DRD_(g_threadinfo)[created].first == 0); + tl_assert(DRD_(g_threadinfo)[created].last == 0); + thread_append_segment(created, DRD_(sg_new)(creator, created)); - return created; + return created; } /** @@ -266,19 +267,24 @@ DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator, */ DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created) { - const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created); - - tl_assert(0 <= (int)created && created < DRD_N_THREADS - && created != DRD_INVALID_THREADID); - - DRD_(g_threadinfo)[created].stack_max = VG_(thread_get_stack_max)(vg_created); - DRD_(g_threadinfo)[created].stack_startup = DRD_(g_threadinfo)[created].stack_max; - DRD_(g_threadinfo)[created].stack_min = DRD_(g_threadinfo)[created].stack_max; - DRD_(g_threadinfo)[created].stack_min_min = DRD_(g_threadinfo)[created].stack_max; - DRD_(g_threadinfo)[created].stack_size = VG_(thread_get_stack_size)(vg_created); - tl_assert(DRD_(g_threadinfo)[created].stack_max != 0); - - return created; + const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created); + + tl_assert(0 <= (int)created && created < DRD_N_THREADS + && created != DRD_INVALID_THREADID); + + DRD_(g_threadinfo)[created].stack_max + = VG_(thread_get_stack_max)(vg_created); + DRD_(g_threadinfo)[created].stack_startup + = DRD_(g_threadinfo)[created].stack_max; + DRD_(g_threadinfo)[created].stack_min + = DRD_(g_threadinfo)[created].stack_max; + DRD_(g_threadinfo)[created].stack_min_min + = DRD_(g_threadinfo)[created].stack_max; + DRD_(g_threadinfo)[created].stack_size + = VG_(thread_get_stack_size)(vg_created); + tl_assert(DRD_(g_threadinfo)[created].stack_max != 0); + + return created; } /** @@ -287,43 +293,43 @@ DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created) */ void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee) { - tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner)); - tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee)); - DRD_(thread_new_segment)(drd_joinee); - DRD_(thread_combine_vc)(drd_joiner, drd_joinee); - DRD_(thread_new_segment)(drd_joiner); - - if (s_trace_fork_join) - { - const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner); - const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee); - const unsigned msg_size = 256; - char* msg; - - msg = VG_(malloc)("drd.main.dptj.1", msg_size); - tl_assert(msg); - VG_(snprintf)(msg, msg_size, - "drd_post_thread_join joiner = %d/%d, joinee = %d/%d", - joiner, drd_joiner, joinee, drd_joinee); - if (joiner) - { - VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg), - ", new vc: "); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg), - DRD_(thread_get_vc)(drd_joiner)); - } - VG_(message)(Vg_DebugMsg, "%s", msg); - VG_(free)(msg); - } - - if (! DRD_(get_check_stack_accesses)()) - { - DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee) - - DRD_(thread_get_stack_size)(drd_joinee), - DRD_(thread_get_stack_max)(drd_joinee)); - } - DRD_(clientobj_delete_thread)(drd_joinee); - DRD_(thread_delete)(drd_joinee); + tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner)); + tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee)); + DRD_(thread_new_segment)(drd_joinee); + DRD_(thread_combine_vc)(drd_joiner, drd_joinee); + DRD_(thread_new_segment)(drd_joiner); + + if (s_trace_fork_join) + { + const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner); + const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee); + const unsigned msg_size = 256; + char* msg; + + msg = VG_(malloc)("drd.main.dptj.1", msg_size); + tl_assert(msg); + VG_(snprintf)(msg, msg_size, + "drd_post_thread_join joiner = %d/%d, joinee = %d/%d", + joiner, drd_joiner, joinee, drd_joinee); + if (joiner) + { + VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg), + ", new vc: "); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg), + DRD_(thread_get_vc)(drd_joiner)); + } + VG_(message)(Vg_DebugMsg, "%s", msg); + VG_(free)(msg); + } + + if (! DRD_(get_check_stack_accesses)()) + { + DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee) + - DRD_(thread_get_stack_size)(drd_joinee), + DRD_(thread_get_stack_max)(drd_joinee)); + } + DRD_(clientobj_delete_thread)(drd_joinee); + DRD_(thread_delete)(drd_joinee); } /** @@ -335,19 +341,19 @@ void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee) void DRD_(thread_set_stack_startup)(const DrdThreadId tid, const Addr stack_startup) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup); - tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max); - DRD_(g_threadinfo)[tid].stack_startup = stack_startup; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup); + tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max); + DRD_(g_threadinfo)[tid].stack_startup = stack_startup; } /** Return the stack pointer for the specified thread. */ Addr DRD_(thread_get_stack_min)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - return DRD_(g_threadinfo)[tid].stack_min; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + return DRD_(g_threadinfo)[tid].stack_min; } /** @@ -356,25 +362,25 @@ Addr DRD_(thread_get_stack_min)(const DrdThreadId tid) */ Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - return DRD_(g_threadinfo)[tid].stack_min_min; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + return DRD_(g_threadinfo)[tid].stack_min_min; } /** Return the top address for the stack of the specified thread. */ Addr DRD_(thread_get_stack_max)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - return DRD_(g_threadinfo)[tid].stack_max; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + return DRD_(g_threadinfo)[tid].stack_max; } /** Return the maximum stack size for the specified thread. */ SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - return DRD_(g_threadinfo)[tid].stack_size; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + return DRD_(g_threadinfo)[tid].stack_size; } /** @@ -383,26 +389,26 @@ SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid) */ void DRD_(thread_delete)(const DrdThreadId tid) { - Segment* sg; - Segment* sg_prev; - - tl_assert(DRD_(IsValidDrdThreadId)(tid)); - - tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0); - for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev) - { - sg_prev = sg->prev; - sg->prev = 0; - sg->next = 0; - DRD_(sg_put)(sg); - } - DRD_(g_threadinfo)[tid].vg_thread_exists = False; - DRD_(g_threadinfo)[tid].posix_thread_exists = False; - tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False); - DRD_(g_threadinfo)[tid].first = 0; - DRD_(g_threadinfo)[tid].last = 0; - - tl_assert(! DRD_(IsValidDrdThreadId)(tid)); + Segment* sg; + Segment* sg_prev; + + tl_assert(DRD_(IsValidDrdThreadId)(tid)); + + tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0); + for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev) + { + sg_prev = sg->prev; + sg->prev = 0; + sg->next = 0; + DRD_(sg_put)(sg); + } + DRD_(g_threadinfo)[tid].vg_thread_exists = False; + DRD_(g_threadinfo)[tid].posix_thread_exists = False; + tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False); + DRD_(g_threadinfo)[tid].first = 0; + DRD_(g_threadinfo)[tid].last = 0; + + tl_assert(! DRD_(IsValidDrdThreadId)(tid)); } /** @@ -412,73 +418,73 @@ void DRD_(thread_delete)(const DrdThreadId tid) */ void DRD_(thread_finished)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - - DRD_(g_threadinfo)[tid].vg_thread_exists = False; - - if (DRD_(g_threadinfo)[tid].detached_posix_thread) - { - /* - * Once a detached thread has finished, its stack is deallocated and - * should no longer be taken into account when computing the conflict set. - */ - DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max; - - /* - * For a detached thread, calling pthread_exit() invalidates the - * POSIX thread ID associated with the detached thread. For joinable - * POSIX threads however, the POSIX thread ID remains live after the - * pthread_exit() call until pthread_join() is called. - */ - DRD_(g_threadinfo)[tid].posix_thread_exists = False; - } + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + + DRD_(g_threadinfo)[tid].vg_thread_exists = False; + + if (DRD_(g_threadinfo)[tid].detached_posix_thread) + { + /* + * Once a detached thread has finished, its stack is deallocated and + * should no longer be taken into account when computing the conflict set. + */ + DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max; + + /* + * For a detached thread, calling pthread_exit() invalidates the + * POSIX thread ID associated with the detached thread. For joinable + * POSIX threads however, the POSIX thread ID remains live after the + * pthread_exit() call until pthread_join() is called. + */ + DRD_(g_threadinfo)[tid].posix_thread_exists = False; + } } /** Called just before pthread_cancel(). */ void DRD_(thread_pre_cancel)(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(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID); - DRD_(g_threadinfo)[tid].synchr_nesting = 0; + DRD_(g_threadinfo)[tid].synchr_nesting = 0; } /** Store the POSIX thread ID for the specified thread. */ void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid) { - 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(ptid != INVALID_POSIX_THREADID); - DRD_(g_threadinfo)[tid].posix_thread_exists = True; - DRD_(g_threadinfo)[tid].pt_threadid = ptid; + 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(ptid != INVALID_POSIX_THREADID); + DRD_(g_threadinfo)[tid].posix_thread_exists = True; + DRD_(g_threadinfo)[tid].pt_threadid = ptid; } /** Returns true for joinable threads and false for detached threads. */ Bool DRD_(thread_get_joinable)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - return ! DRD_(g_threadinfo)[tid].detached_posix_thread; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + return ! DRD_(g_threadinfo)[tid].detached_posix_thread; } /** Store the thread mode: joinable or detached. */ void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(!! joinable == joinable); - tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID); + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(!! joinable == joinable); + tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID); #if 0 - VG_(message)(Vg_DebugMsg, - "thread_set_joinable(%d/%d, %s)", - tid, - DRD_(g_threadinfo)[tid].vg_threadid, - joinable ? "joinable" : "detached"); + VG_(message)(Vg_DebugMsg, + "thread_set_joinable(%d/%d, %s)", + tid, + DRD_(g_threadinfo)[tid].vg_threadid, + joinable ? "joinable" : "detached"); #endif - DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable; + DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable; } /** @@ -487,16 +493,16 @@ void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable) */ void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid) { - tl_assert(vg_tid != VG_INVALID_THREADID); + tl_assert(vg_tid != VG_INVALID_THREADID); - if (vg_tid != s_vg_running_tid) - { - DRD_(thread_set_running_tid)(vg_tid, - DRD_(VgThreadIdToDrdThreadId)(vg_tid)); - } + if (vg_tid != s_vg_running_tid) + { + DRD_(thread_set_running_tid)(vg_tid, + DRD_(VgThreadIdToDrdThreadId)(vg_tid)); + } - tl_assert(s_vg_running_tid != VG_INVALID_THREADID); - tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); + tl_assert(s_vg_running_tid != VG_INVALID_THREADID); + tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); } /** @@ -506,29 +512,29 @@ void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid) void DRD_(thread_set_running_tid)(const ThreadId vg_tid, const DrdThreadId drd_tid) { - tl_assert(vg_tid != VG_INVALID_THREADID); - tl_assert(drd_tid != DRD_INVALID_THREADID); + tl_assert(vg_tid != VG_INVALID_THREADID); + tl_assert(drd_tid != DRD_INVALID_THREADID); - if (vg_tid != s_vg_running_tid) - { - if (s_trace_context_switches - && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID) - { - VG_(message)(Vg_DebugMsg, - "Context switch from thread %d/%d to thread %d/%d;" - " segments: %llu", - s_vg_running_tid, DRD_(g_drd_running_tid), - DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid, - DRD_(sg_get_segments_alive_count)()); - } - s_vg_running_tid = vg_tid; - DRD_(g_drd_running_tid) = drd_tid; - thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid); - s_context_switch_count++; - } - - tl_assert(s_vg_running_tid != VG_INVALID_THREADID); - tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); + if (vg_tid != s_vg_running_tid) + { + if (s_trace_context_switches + && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID) + { + VG_(message)(Vg_DebugMsg, + "Context switch from thread %d/%d to thread %d/%d;" + " segments: %llu", + s_vg_running_tid, DRD_(g_drd_running_tid), + DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid, + DRD_(sg_get_segments_alive_count)()); + } + s_vg_running_tid = vg_tid; + DRD_(g_drd_running_tid) = drd_tid; + thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid); + s_context_switch_count++; + } + + tl_assert(s_vg_running_tid != VG_INVALID_THREADID); + tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); } /** @@ -537,8 +543,8 @@ void DRD_(thread_set_running_tid)(const ThreadId vg_tid, */ int DRD_(thread_enter_synchr)(const DrdThreadId tid) { - tl_assert(DRD_(IsValidDrdThreadId)(tid)); - return DRD_(g_threadinfo)[tid].synchr_nesting++; + tl_assert(DRD_(IsValidDrdThreadId)(tid)); + return DRD_(g_threadinfo)[tid].synchr_nesting++; } /** @@ -547,33 +553,33 @@ int DRD_(thread_enter_synchr)(const DrdThreadId tid) */ int DRD_(thread_leave_synchr)(const DrdThreadId tid) { - tl_assert(DRD_(IsValidDrdThreadId)(tid)); - tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1); - return --DRD_(g_threadinfo)[tid].synchr_nesting; + tl_assert(DRD_(IsValidDrdThreadId)(tid)); + tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1); + return --DRD_(g_threadinfo)[tid].synchr_nesting; } /** Returns the synchronization nesting counter. */ int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid) { - tl_assert(DRD_(IsValidDrdThreadId)(tid)); - return DRD_(g_threadinfo)[tid].synchr_nesting; + tl_assert(DRD_(IsValidDrdThreadId)(tid)); + return DRD_(g_threadinfo)[tid].synchr_nesting; } /** Append a new segment at the end of the segment list. */ static void thread_append_segment(const DrdThreadId tid, Segment* const sg) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); - sg->prev = DRD_(g_threadinfo)[tid].last; - sg->next = 0; - if (DRD_(g_threadinfo)[tid].last) - DRD_(g_threadinfo)[tid].last->next = sg; - DRD_(g_threadinfo)[tid].last = sg; - if (DRD_(g_threadinfo)[tid].first == 0) - DRD_(g_threadinfo)[tid].first = sg; - // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); + sg->prev = DRD_(g_threadinfo)[tid].last; + sg->next = 0; + if (DRD_(g_threadinfo)[tid].last) + DRD_(g_threadinfo)[tid].last->next = sg; + DRD_(g_threadinfo)[tid].last = sg; + if (DRD_(g_threadinfo)[tid].first == 0) + DRD_(g_threadinfo)[tid].first = sg; + // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); } /** @@ -583,21 +589,21 @@ void thread_append_segment(const DrdThreadId tid, Segment* const sg) static void thread_discard_segment(const DrdThreadId tid, Segment* const sg) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); - - if (sg->prev) - sg->prev->next = sg->next; - if (sg->next) - sg->next->prev = sg->prev; - if (sg == DRD_(g_threadinfo)[tid].first) - DRD_(g_threadinfo)[tid].first = sg->next; - if (sg == DRD_(g_threadinfo)[tid].last) - DRD_(g_threadinfo)[tid].last = sg->prev; - DRD_(sg_put)(sg); - - //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); + + if (sg->prev) + sg->prev->next = sg->next; + if (sg->next) + sg->next->prev = sg->prev; + if (sg == DRD_(g_threadinfo)[tid].first) + DRD_(g_threadinfo)[tid].first = sg->next; + if (sg == DRD_(g_threadinfo)[tid].last) + DRD_(g_threadinfo)[tid].last = sg->prev; + DRD_(sg_put)(sg); + + //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid])); } /** @@ -606,10 +612,10 @@ void thread_discard_segment(const DrdThreadId tid, Segment* const sg) */ VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(DRD_(g_threadinfo)[tid].last); - return &DRD_(g_threadinfo)[tid].last->vc; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].last); + return &DRD_(g_threadinfo)[tid].last->vc; } /** @@ -617,13 +623,13 @@ VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid) */ void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid) { - tl_assert(sg); - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(DRD_(g_threadinfo)[tid].last); + tl_assert(sg); + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].last); - DRD_(sg_put)(*sg); - *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last); + DRD_(sg_put)(*sg); + *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last); } /** @@ -634,24 +640,24 @@ void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid) */ static void DRD_(thread_compute_minimum_vc)(VectorClock* vc) { - unsigned i; - Bool first; - Segment* latest_sg; - - first = True; - for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - i++) - { - latest_sg = DRD_(g_threadinfo)[i].last; - if (latest_sg) - { - if (first) - DRD_(vc_assign)(vc, &latest_sg->vc); - else - DRD_(vc_min)(vc, &latest_sg->vc); - first = False; - } - } + unsigned i; + Bool first; + Segment* latest_sg; + + first = True; + for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + i++) + { + latest_sg = DRD_(g_threadinfo)[i].last; + if (latest_sg) + { + if (first) + DRD_(vc_assign)(vc, &latest_sg->vc); + else + DRD_(vc_min)(vc, &latest_sg->vc); + first = False; + } + } } /** @@ -661,24 +667,24 @@ static void DRD_(thread_compute_minimum_vc)(VectorClock* vc) */ static void DRD_(thread_compute_maximum_vc)(VectorClock* vc) { - unsigned i; - Bool first; - Segment* latest_sg; - - first = True; - for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - i++) - { - latest_sg = DRD_(g_threadinfo)[i].last; - if (latest_sg) - { - if (first) - DRD_(vc_assign)(vc, &latest_sg->vc); - else - DRD_(vc_combine)(vc, &latest_sg->vc); - first = False; - } - } + unsigned i; + Bool first; + Segment* latest_sg; + + first = True; + for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + i++) + { + latest_sg = DRD_(g_threadinfo)[i].last; + if (latest_sg) + { + if (first) + DRD_(vc_assign)(vc, &latest_sg->vc); + else + DRD_(vc_combine)(vc, &latest_sg->vc); + first = False; + } + } } /** @@ -688,45 +694,45 @@ static void DRD_(thread_compute_maximum_vc)(VectorClock* vc) */ static void DRD_(thread_discard_ordered_segments)(void) { - unsigned i; - VectorClock thread_vc_min; - - s_discard_ordered_segments_count++; - - DRD_(vc_init)(&thread_vc_min, 0, 0); - DRD_(thread_compute_minimum_vc)(&thread_vc_min); - if (DRD_(sg_get_trace)()) - { - char msg[256]; - VectorClock thread_vc_max; - - DRD_(vc_init)(&thread_vc_max, 0, 0); - DRD_(thread_compute_maximum_vc)(&thread_vc_max); - VG_(snprintf)(msg, sizeof(msg), - "Discarding ordered segments -- min vc is "); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &thread_vc_min); - VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - ", max vc is "); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &thread_vc_max); - VG_(message)(Vg_UserMsg, "%s", msg); - DRD_(vc_cleanup)(&thread_vc_max); - } - - for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - i++) - { - Segment* sg; - Segment* sg_next; - for (sg = DRD_(g_threadinfo)[i].first; - sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min); - sg = sg_next) - { - thread_discard_segment(i, sg); - } - } - DRD_(vc_cleanup)(&thread_vc_min); + unsigned i; + VectorClock thread_vc_min; + + s_discard_ordered_segments_count++; + + DRD_(vc_init)(&thread_vc_min, 0, 0); + DRD_(thread_compute_minimum_vc)(&thread_vc_min); + if (DRD_(sg_get_trace)()) + { + char msg[256]; + VectorClock thread_vc_max; + + DRD_(vc_init)(&thread_vc_max, 0, 0); + DRD_(thread_compute_maximum_vc)(&thread_vc_max); + VG_(snprintf)(msg, sizeof(msg), + "Discarding ordered segments -- min vc is "); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + &thread_vc_min); + VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + ", max vc is "); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + &thread_vc_max); + VG_(message)(Vg_UserMsg, "%s", msg); + DRD_(vc_cleanup)(&thread_vc_max); + } + + for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + i++) + { + Segment* sg; + Segment* sg_next; + for (sg = DRD_(g_threadinfo)[i].first; + sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min); + sg = sg_next) + { + thread_discard_segment(i, sg); + } + } + DRD_(vc_cleanup)(&thread_vc_min); } /** @@ -740,30 +746,30 @@ static void DRD_(thread_discard_ordered_segments)(void) */ static void thread_merge_segments(void) { - unsigned i; + unsigned i; - for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - i++) - { - Segment* sg; + for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + i++) + { + Segment* sg; - // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i])); + // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i])); - for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next) - { - if (DRD_(sg_get_refcnt)(sg) == 1 - && sg->next - && DRD_(sg_get_refcnt)(sg->next) == 1 - && sg->next->next) + for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next) { - /* Merge sg and sg->next into sg. */ - DRD_(sg_merge)(sg, sg->next); - thread_discard_segment(i, sg->next); + if (DRD_(sg_get_refcnt)(sg) == 1 + && sg->next + && DRD_(sg_get_refcnt)(sg->next) == 1 + && sg->next->next) + { + /* Merge sg and sg->next into sg. */ + DRD_(sg_merge)(sg, sg->next); + thread_discard_segment(i, sg->next); + } } - } - // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i])); - } + // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i])); + } } /** @@ -772,43 +778,43 @@ static void thread_merge_segments(void) */ void DRD_(thread_new_segment)(const DrdThreadId tid) { - Segment* new_sg; + Segment* new_sg; - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); - new_sg = DRD_(sg_new)(tid, tid); - thread_append_segment(tid, new_sg); + new_sg = DRD_(sg_new)(tid, tid); + thread_append_segment(tid, new_sg); - thread_compute_conflict_set(&DRD_(g_conflict_set), DRD_(g_drd_running_tid)); - s_conflict_set_new_segment_count++; + thread_compute_conflict_set(&DRD_(g_conflict_set), DRD_(g_drd_running_tid)); + s_conflict_set_new_segment_count++; - DRD_(thread_discard_ordered_segments)(); + DRD_(thread_discard_ordered_segments)(); - if (s_segment_merging) - { - thread_merge_segments(); - } + if (s_segment_merging) + { + thread_merge_segments(); + } } /** Call this function after thread 'joiner' joined thread 'joinee'. */ void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee) { - tl_assert(joiner != joinee); - tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS - && joiner != DRD_INVALID_THREADID); - tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS - && joinee != DRD_INVALID_THREADID); - tl_assert(DRD_(g_threadinfo)[joiner].last); - tl_assert(DRD_(g_threadinfo)[joinee].last); - DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc, - &DRD_(g_threadinfo)[joinee].last->vc); - DRD_(thread_discard_ordered_segments)(); - - if (joiner == DRD_(g_drd_running_tid)) - { - thread_compute_conflict_set(&DRD_(g_conflict_set), joiner); - } + tl_assert(joiner != joinee); + tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS + && joiner != DRD_INVALID_THREADID); + tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS + && joinee != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[joiner].last); + tl_assert(DRD_(g_threadinfo)[joinee].last); + DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc, + &DRD_(g_threadinfo)[joinee].last->vc); + DRD_(thread_discard_ordered_segments)(); + + if (joiner == DRD_(g_drd_running_tid)) + { + thread_compute_conflict_set(&DRD_(g_conflict_set), joiner); + } } /** @@ -818,14 +824,14 @@ void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee) */ void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(DRD_(g_threadinfo)[tid].last); - tl_assert(vc); - DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc); - thread_compute_conflict_set(&DRD_(g_conflict_set), tid); - DRD_(thread_discard_ordered_segments)(); - s_conflict_set_combine_vc_count++; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].last); + tl_assert(vc); + DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc); + thread_compute_conflict_set(&DRD_(g_conflict_set), tid); + DRD_(thread_discard_ordered_segments)(); + s_conflict_set_combine_vc_count++; } /** @@ -835,58 +841,58 @@ void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc) */ void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2) { - DrdThreadId other_user; - unsigned i; - - /* For all threads, mark the range [ a1, a2 [ as no longer in use. */ - other_user = DRD_INVALID_THREADID; - for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - i++) - { - Segment* p; - for (p = DRD_(g_threadinfo)[i].first; p; p = p->next) - { - if (other_user == DRD_INVALID_THREADID - && i != DRD_(g_drd_running_tid)) + DrdThreadId other_user; + unsigned i; + + /* For all threads, mark the range [ a1, a2 [ as no longer in use. */ + other_user = DRD_INVALID_THREADID; + for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + i++) + { + Segment* p; + for (p = DRD_(g_threadinfo)[i].first; p; p = p->next) { - if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2))) - { - other_user = i; - } - continue; + if (other_user == DRD_INVALID_THREADID + && i != DRD_(g_drd_running_tid)) + { + if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2))) + { + other_user = i; + } + continue; + } + DRD_(bm_clear)(p->bm, a1, a2); } - DRD_(bm_clear)(p->bm, a1, a2); - } - } - - /* - * If any other thread had accessed memory in [ a1, a2 [, update the - * conflict set. - */ - if (other_user != DRD_INVALID_THREADID - && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2)) - { - thread_compute_conflict_set(&DRD_(g_conflict_set), - DRD_(thread_get_running_tid)()); - } + } + + /* + * If any other thread had accessed memory in [ a1, a2 [, update the + * conflict set. + */ + if (other_user != DRD_INVALID_THREADID + && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2)) + { + thread_compute_conflict_set(&DRD_(g_conflict_set), + DRD_(thread_get_running_tid)()); + } } /** Start recording memory access information. */ void DRD_(thread_start_recording)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(! DRD_(g_threadinfo)[tid].is_recording); - DRD_(g_threadinfo)[tid].is_recording = True; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(! DRD_(g_threadinfo)[tid].is_recording); + DRD_(g_threadinfo)[tid].is_recording = True; } /** Stop recording memory access information. */ void DRD_(thread_stop_recording)(const DrdThreadId tid) { - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(DRD_(g_threadinfo)[tid].is_recording); - DRD_(g_threadinfo)[tid].is_recording = False; + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(DRD_(g_threadinfo)[tid].is_recording); + DRD_(g_threadinfo)[tid].is_recording = False; } /** @@ -896,29 +902,29 @@ void DRD_(thread_stop_recording)(const DrdThreadId tid) */ void DRD_(thread_print_all)(void) { - unsigned i; - Segment* p; - - for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - i++) - { - if (DRD_(g_threadinfo)[i].first) - { - VG_(printf)("**************\n" - "* thread %3d (%d/%d/%d/0x%lx/%d) *\n" - "**************\n", - i, - DRD_(g_threadinfo)[i].vg_thread_exists, - DRD_(g_threadinfo)[i].vg_threadid, - DRD_(g_threadinfo)[i].posix_thread_exists, - DRD_(g_threadinfo)[i].pt_threadid, - DRD_(g_threadinfo)[i].detached_posix_thread); - for (p = DRD_(g_threadinfo)[i].first; p; p = p->next) + unsigned i; + Segment* p; + + for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + i++) + { + if (DRD_(g_threadinfo)[i].first) { - DRD_(sg_print)(p); + VG_(printf)("**************\n" + "* thread %3d (%d/%d/%d/0x%lx/%d) *\n" + "**************\n", + i, + DRD_(g_threadinfo)[i].vg_thread_exists, + DRD_(g_threadinfo)[i].vg_threadid, + DRD_(g_threadinfo)[i].posix_thread_exists, + DRD_(g_threadinfo)[i].pt_threadid, + DRD_(g_threadinfo)[i].detached_posix_thread); + for (p = DRD_(g_threadinfo)[i].first; p; p = p->next) + { + DRD_(sg_print)(p); + } } - } - } + } } /** Show a call stack involved in a data race. */ @@ -926,26 +932,26 @@ static void show_call_stack(const DrdThreadId tid, const Char* const msg, ExeContext* const callstack) { - const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid); - - VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid); - - if (vg_tid != VG_INVALID_THREADID) - { - if (callstack) - { - VG_(pp_ExeContext)(callstack); - } - else - { - VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size)); - } - } - else - { - VG_(message)(Vg_UserMsg, - " (thread finished, call stack no longer available)"); - } + const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid); + + VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid); + + if (vg_tid != VG_INVALID_THREADID) + { + if (callstack) + { + VG_(pp_ExeContext)(callstack); + } + else + { + VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size)); + } + } + else + { + VG_(message)(Vg_UserMsg, + " (thread finished, call stack no longer available)"); + } } /** Print information about the segments involved in a data race. */ @@ -956,43 +962,43 @@ thread_report_conflicting_segments_segment(const DrdThreadId tid, const BmAccessTypeT access_type, const Segment* const p) { - unsigned i; - - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(p); - - for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - i++) - { - if (i != tid) - { - Segment* q; - for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev) + unsigned i; + + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(p); + + for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + i++) + { + if (i != tid) { - /* - * Since q iterates over the segments of thread i in order of - * decreasing vector clocks, if q->vc <= p->vc, then - * q->next->vc <= p->vc will also hold. Hence, break out of the - * loop once this condition is met. - */ - if (DRD_(vc_lte)(&q->vc, &p->vc)) - break; - if (! DRD_(vc_lte)(&p->vc, &q->vc)) - { - if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size, - access_type)) - { - tl_assert(q->stacktrace); - show_call_stack(i, "Other segment start", - q->stacktrace); - show_call_stack(i, "Other segment end", - q->next ? q->next->stacktrace : 0); - } - } + Segment* q; + for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev) + { + /* + * Since q iterates over the segments of thread i in order of + * decreasing vector clocks, if q->vc <= p->vc, then + * q->next->vc <= p->vc will also hold. Hence, break out of the + * loop once this condition is met. + */ + if (DRD_(vc_lte)(&q->vc, &p->vc)) + break; + if (! DRD_(vc_lte)(&p->vc, &q->vc)) + { + if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size, + access_type)) + { + tl_assert(q->stacktrace); + show_call_stack(i, "Other segment start", + q->stacktrace); + show_call_stack(i, "Other segment end", + q->next ? q->next->stacktrace : 0); + } + } + } } - } - } + } } /** Print information about all segments involved in a data race. */ @@ -1001,19 +1007,19 @@ void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid, const SizeT size, const BmAccessTypeT access_type) { - Segment* p; - - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - - for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next) - { - if (DRD_(bm_has)(p->bm, addr, addr + size, access_type)) - { - thread_report_conflicting_segments_segment(tid, addr, size, - access_type, p); - } - } + Segment* p; + + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + + for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next) + { + if (DRD_(bm_has)(p->bm, addr, addr + size, access_type)) + { + thread_report_conflicting_segments_segment(tid, addr, size, + access_type, p); + } + } } /** @@ -1023,123 +1029,129 @@ void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid, static void thread_compute_conflict_set(struct bitmap** conflict_set, const DrdThreadId tid) { - Segment* p; - - tl_assert(0 <= (int)tid && tid < DRD_N_THREADS - && tid != DRD_INVALID_THREADID); - tl_assert(tid == DRD_(g_drd_running_tid)); - - s_update_conflict_set_count++; - s_conflict_set_bitmap_creation_count -= DRD_(bm_get_bitmap_creation_count)(); - s_conflict_set_bitmap2_creation_count -= DRD_(bm_get_bitmap2_creation_count)(); - - if (*conflict_set) - { - DRD_(bm_delete)(*conflict_set); - } - *conflict_set = DRD_(bm_new)(); - - if (s_trace_conflict_set) - { - char msg[256]; - - VG_(snprintf)(msg, sizeof(msg), - "computing conflict set for thread %d/%d with vc ", - DRD_(DrdThreadIdToVgThreadId)(tid), tid); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), - sizeof(msg) - VG_(strlen)(msg), - &DRD_(g_threadinfo)[tid].last->vc); - VG_(message)(Vg_UserMsg, "%s", msg); - } - - p = DRD_(g_threadinfo)[tid].last; - { - unsigned j; - - if (s_trace_conflict_set) - { + Segment* p; + + tl_assert(0 <= (int)tid && tid < DRD_N_THREADS + && tid != DRD_INVALID_THREADID); + tl_assert(tid == DRD_(g_drd_running_tid)); + + s_update_conflict_set_count++; + s_conflict_set_bitmap_creation_count + -= DRD_(bm_get_bitmap_creation_count)(); + s_conflict_set_bitmap2_creation_count + -= DRD_(bm_get_bitmap2_creation_count)(); + + if (*conflict_set) + { + DRD_(bm_delete)(*conflict_set); + } + *conflict_set = DRD_(bm_new)(); + + if (s_trace_conflict_set) + { char msg[256]; VG_(snprintf)(msg, sizeof(msg), - "conflict set: thread [%d] at vc ", - tid); + "computing conflict set for thread %d/%d with vc ", + DRD_(DrdThreadIdToVgThreadId)(tid), tid); DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), - &p->vc); + &DRD_(g_threadinfo)[tid].last->vc); VG_(message)(Vg_UserMsg, "%s", msg); - } + } + + p = DRD_(g_threadinfo)[tid].last; + { + unsigned j; - for (j = 0; j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); - j++) - { - if (j != tid && DRD_(IsValidDrdThreadId)(j)) + if (s_trace_conflict_set) { - const Segment* q; - for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev) - { - if (! DRD_(vc_lte)(&q->vc, &p->vc) && ! DRD_(vc_lte)(&p->vc, &q->vc)) - { - if (s_trace_conflict_set) - { - char msg[256]; - VG_(snprintf)(msg, sizeof(msg), - "conflict set: [%d] merging segment ", j); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), - sizeof(msg) - VG_(strlen)(msg), - &q->vc); - VG_(message)(Vg_UserMsg, "%s", msg); - } - DRD_(bm_merge2)(*conflict_set, q->bm); - } - else - { - if (s_trace_conflict_set) + char msg[256]; + + VG_(snprintf)(msg, sizeof(msg), + "conflict set: thread [%d] at vc ", + tid); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), + sizeof(msg) - VG_(strlen)(msg), + &p->vc); + VG_(message)(Vg_UserMsg, "%s", msg); + } + + for (j = 0; + j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); + j++) + { + if (j != tid && DRD_(IsValidDrdThreadId)(j)) + { + const Segment* q; + for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev) { - char msg[256]; - VG_(snprintf)(msg, sizeof(msg), - "conflict set: [%d] ignoring segment ", j); - DRD_(vc_snprint)(msg + VG_(strlen)(msg), - sizeof(msg) - VG_(strlen)(msg), - &q->vc); - VG_(message)(Vg_UserMsg, "%s", msg); + if (! DRD_(vc_lte)(&q->vc, &p->vc) + && ! DRD_(vc_lte)(&p->vc, &q->vc)) + { + if (s_trace_conflict_set) + { + char msg[256]; + VG_(snprintf)(msg, sizeof(msg), + "conflict set: [%d] merging segment ", j); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), + sizeof(msg) - VG_(strlen)(msg), + &q->vc); + VG_(message)(Vg_UserMsg, "%s", msg); + } + DRD_(bm_merge2)(*conflict_set, q->bm); + } + else + { + if (s_trace_conflict_set) + { + char msg[256]; + VG_(snprintf)(msg, sizeof(msg), + "conflict set: [%d] ignoring segment ", j); + DRD_(vc_snprint)(msg + VG_(strlen)(msg), + sizeof(msg) - VG_(strlen)(msg), + &q->vc); + VG_(message)(Vg_UserMsg, "%s", msg); + } + } } - } - } + } } - } - } - - s_conflict_set_bitmap_creation_count += DRD_(bm_get_bitmap_creation_count)(); - s_conflict_set_bitmap2_creation_count += DRD_(bm_get_bitmap2_creation_count)(); - - if (0 && s_trace_conflict_set) - { - VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid); - DRD_(bm_print)(*conflict_set); - VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid); - } + } + + s_conflict_set_bitmap_creation_count + += DRD_(bm_get_bitmap_creation_count)(); + s_conflict_set_bitmap2_creation_count + += DRD_(bm_get_bitmap2_creation_count)(); + + if (0 && s_trace_conflict_set) + { + VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid); + DRD_(bm_print)(*conflict_set); + VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid); + } } /** Report the number of context switches performed. */ ULong DRD_(thread_get_context_switch_count)(void) { - return s_context_switch_count; + return s_context_switch_count; } /** Report the number of ordered segments that have been discarded. */ ULong DRD_(thread_get_discard_ordered_segments_count)(void) { - return s_discard_ordered_segments_count; + return s_discard_ordered_segments_count; } /** Return how many times the conflict set has been updated. */ ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc) { - tl_assert(dsnsc); - tl_assert(dscvc); - *dsnsc = s_conflict_set_new_segment_count; - *dscvc = s_conflict_set_combine_vc_count; - return s_update_conflict_set_count; + tl_assert(dsnsc); + tl_assert(dscvc); + *dsnsc = s_conflict_set_new_segment_count; + *dscvc = s_conflict_set_combine_vc_count; + return s_update_conflict_set_count; } /** @@ -1148,7 +1160,7 @@ ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc) */ ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void) { - return s_conflict_set_bitmap_creation_count; + return s_conflict_set_bitmap_creation_count; } /** @@ -1157,5 +1169,5 @@ ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void) */ ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void) { - return s_conflict_set_bitmap2_creation_count; + return s_conflict_set_bitmap2_creation_count; } diff --git a/drd/drd_thread.h b/drd/drd_thread.h index d861464157..bf24fbc108 100644 --- a/drd/drd_thread.h +++ b/drd/drd_thread.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -66,28 +67,28 @@ typedef UWord PThreadId; /** Per-thread information managed by DRD. */ typedef struct { - Segment* first; /**< Pointer to first segment. */ - Segment* last; /**< Pointer to last segment. */ - ThreadId vg_threadid; /**< Valgrind thread ID. */ - PThreadId pt_threadid; /**< POSIX thread ID. */ - Addr stack_min_min; /**< Lowest value stack pointer ever had. */ - Addr stack_min; /**< Current stack pointer. */ - Addr stack_startup; /**bm, a1); - return DRD_(bm_load_1_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1); + DRD_(bm_access_load_1)(DRD_(running_thread_get_segment)()->bm, a1); + return DRD_(bm_load_1_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1); } static __inline__ Bool bm_access_load_2_triggers_conflict(const Addr a1) { - if ((a1 & 1) == 0) - { - bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 2); - return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(), a1, 2); - } - else - { - DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, a1, a1 + 2, eLoad); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 2, eLoad); - } + if ((a1 & 1) == 0) + { + bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 2); + return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(), + a1, 2); + } + else + { + DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, + a1, a1 + 2, eLoad); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 2, eLoad); + } } static __inline__ Bool bm_access_load_4_triggers_conflict(const Addr a1) { - if ((a1 & 3) == 0) - { - bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 4); - return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(), a1, 4); - } - else - { - DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, a1, a1 + 4, eLoad); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 4, eLoad); - } + if ((a1 & 3) == 0) + { + bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 4); + return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(), + a1, 4); + } + else + { + DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, + a1, a1 + 4, eLoad); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 4, eLoad); + } } static __inline__ Bool bm_access_load_8_triggers_conflict(const Addr a1) { - if ((a1 & 7) == 0) - { - bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 8); - return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(), a1, 8); - } - else if ((a1 & 3) == 0) - { - bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1 + 0, 4); - bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1 + 4, 4); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 8, eLoad); - } - else - { - DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, a1, a1 + 8, eLoad); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 8, eLoad); - } + if ((a1 & 7) == 0) + { + bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 8); + return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(), + a1, 8); + } + else if ((a1 & 3) == 0) + { + bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1 + 0, 4); + bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1 + 4, 4); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 8, eLoad); + } + else + { + DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, + a1, a1 + 8, eLoad); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 8, eLoad); + } } static __inline__ Bool bm_access_load_triggers_conflict(const Addr a1, const Addr a2) { - DRD_(bm_access_range_load)(DRD_(running_thread_get_segment)()->bm, a1, a2); - return DRD_(bm_load_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a2); + DRD_(bm_access_range_load)(DRD_(running_thread_get_segment)()->bm, a1, a2); + return DRD_(bm_load_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a2); } static __inline__ Bool bm_access_store_1_triggers_conflict(const Addr a1) { - DRD_(bm_access_store_1)(DRD_(running_thread_get_segment)()->bm, a1); - return DRD_(bm_store_1_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1); + DRD_(bm_access_store_1)(DRD_(running_thread_get_segment)()->bm, a1); + return DRD_(bm_store_1_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1); } static __inline__ Bool bm_access_store_2_triggers_conflict(const Addr a1) { - if ((a1 & 1) == 0) - { - bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 2); - return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(), a1, 2); - } - else - { - DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, a1, a1 + 2, eStore); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 2, eStore); - } + if ((a1 & 1) == 0) + { + bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 2); + return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(), + a1, 2); + } + else + { + DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, + a1, a1 + 2, eStore); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 2, eStore); + } } static __inline__ Bool bm_access_store_4_triggers_conflict(const Addr a1) { - if ((a1 & 3) == 0) - { - bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 4); - return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(), a1, 4); - } - else - { - DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, a1, a1 + 4, eStore); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 4, eStore); - } + if ((a1 & 3) == 0) + { + bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 4); + return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(), + a1, 4); + } + else + { + DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, + a1, a1 + 4, eStore); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 4, eStore); + } } static __inline__ Bool bm_access_store_8_triggers_conflict(const Addr a1) { - if ((a1 & 7) == 0) - { - bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 8); - return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(), a1, 8); - } - else if ((a1 & 3) == 0) - { - bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1 + 0, 4); - bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1 + 4, 4); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 8, eStore); - } - else - { - DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, a1, a1 + 8, eStore); - return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a1 + 8, eStore); - } + if ((a1 & 7) == 0) + { + bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 8); + return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(), + a1, 8); + } + else if ((a1 & 3) == 0) + { + bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, + a1 + 0, 4); + bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, + a1 + 4, 4); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 8, eStore); + } + else + { + DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm, + a1, a1 + 8, eStore); + return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a1 + 8, eStore); + } } static __inline__ Bool bm_access_store_triggers_conflict(const Addr a1, const Addr a2) { - DRD_(bm_access_range_store)(DRD_(running_thread_get_segment)()->bm, a1, a2); - return DRD_(bm_store_has_conflict_with)(DRD_(thread_get_conflict_set)(), a1, a2); + DRD_(bm_access_range_store)(DRD_(running_thread_get_segment)()->bm, a1, a2); + return DRD_(bm_store_has_conflict_with)(DRD_(thread_get_conflict_set)(), + a1, a2); } #endif // __DRD_THREAD_BITMAP_H diff --git a/drd/drd_vc.c b/drd/drd_vc.c index 7f14f1a270..583c3e2b8d 100644 --- a/drd/drd_vc.c +++ b/drd/drd_vc.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -47,65 +48,65 @@ void DRD_(vc_init)(VectorClock* const vc, const VCElem* const vcelem, const unsigned size) { - tl_assert(vc); - vc->size = 0; - vc->capacity = 0; - vc->vc = 0; - DRD_(vc_reserve)(vc, size); - tl_assert(size == 0 || vc->vc != 0); - if (vcelem) - { - VG_(memcpy)(vc->vc, vcelem, size * sizeof(vcelem[0])); - vc->size = size; - } + tl_assert(vc); + vc->size = 0; + vc->capacity = 0; + vc->vc = 0; + DRD_(vc_reserve)(vc, size); + tl_assert(size == 0 || vc->vc != 0); + if (vcelem) + { + VG_(memcpy)(vc->vc, vcelem, size * sizeof(vcelem[0])); + vc->size = size; + } } /** Reset vc to the empty vector clock. */ void DRD_(vc_cleanup)(VectorClock* const vc) { - DRD_(vc_reserve)(vc, 0); + DRD_(vc_reserve)(vc, 0); } /** Copy constructor -- initializes *new. */ void DRD_(vc_copy)(VectorClock* const new, const VectorClock* const rhs) { - DRD_(vc_init)(new, rhs->vc, rhs->size); + DRD_(vc_init)(new, rhs->vc, rhs->size); } /** Assignment operator -- *lhs is already a valid vector clock. */ void DRD_(vc_assign)(VectorClock* const lhs, const VectorClock* const rhs) { - DRD_(vc_cleanup)(lhs); - DRD_(vc_copy)(lhs, rhs); + DRD_(vc_cleanup)(lhs); + DRD_(vc_copy)(lhs, rhs); } /** Increment the clock of thread 'tid' in vector clock 'vc'. */ void DRD_(vc_increment)(VectorClock* const vc, DrdThreadId const tid) { - unsigned i; - for (i = 0; i < vc->size; i++) - { - if (vc->vc[i].threadid == tid) - { - typeof(vc->vc[i].count) const oldcount = vc->vc[i].count; - vc->vc[i].count++; - // Check for integer overflow. - tl_assert(oldcount < vc->vc[i].count); - return; - } - } - - /* - * The specified thread ID does not yet exist in the vector clock - * -- insert it. - */ - { - const VCElem vcelem = { tid, 1 }; - VectorClock vc2; - DRD_(vc_init)(&vc2, &vcelem, 1); - DRD_(vc_combine)(vc, &vc2); - DRD_(vc_cleanup)(&vc2); - } + unsigned i; + for (i = 0; i < vc->size; i++) + { + if (vc->vc[i].threadid == tid) + { + typeof(vc->vc[i].count) const oldcount = vc->vc[i].count; + vc->vc[i].count++; + // Check for integer overflow. + tl_assert(oldcount < vc->vc[i].count); + return; + } + } + + /* + * The specified thread ID does not yet exist in the vector clock + * -- insert it. + */ + { + const VCElem vcelem = { tid, 1 }; + VectorClock vc2; + DRD_(vc_init)(&vc2, &vcelem, 1); + DRD_(vc_combine)(vc, &vc2); + DRD_(vc_cleanup)(&vc2); + } } /** @@ -115,46 +116,46 @@ void DRD_(vc_increment)(VectorClock* const vc, DrdThreadId const tid) Bool DRD_(vc_ordered)(const VectorClock* const vc1, const VectorClock* const vc2) { - return DRD_(vc_lte)(vc1, vc2) || DRD_(vc_lte)(vc2, vc1); + return DRD_(vc_lte)(vc1, vc2) || DRD_(vc_lte)(vc2, vc1); } /** Compute elementwise minimum. */ void DRD_(vc_min)(VectorClock* const result, const VectorClock* const rhs) { - unsigned i; - unsigned j; - - tl_assert(result); - tl_assert(rhs); - - DRD_(vc_check)(result); - - /* Next, combine both vector clocks into one. */ - i = 0; - for (j = 0; j < rhs->size; j++) - { - while (i < result->size && result->vc[i].threadid < rhs->vc[j].threadid) - { - /* Thread ID is missing in second vector clock. Clear the count. */ - result->vc[i].count = 0; - i++; - } - if (i >= result->size) - { - break; - } - if (result->vc[i].threadid <= rhs->vc[j].threadid) - { - /* The thread ID is present in both vector clocks. Compute the minimum */ - /* of vc[i].count and vc[j].count. */ - tl_assert(result->vc[i].threadid == rhs->vc[j].threadid); - if (rhs->vc[j].count < result->vc[i].count) + unsigned i; + unsigned j; + + tl_assert(result); + tl_assert(rhs); + + DRD_(vc_check)(result); + + /* Next, combine both vector clocks into one. */ + i = 0; + for (j = 0; j < rhs->size; j++) + { + while (i < result->size && result->vc[i].threadid < rhs->vc[j].threadid) { - result->vc[i].count = rhs->vc[j].count; + /* Thread ID is missing in second vector clock. Clear the count. */ + result->vc[i].count = 0; + i++; } - } - } - DRD_(vc_check)(result); + if (i >= result->size) + { + break; + } + if (result->vc[i].threadid <= rhs->vc[j].threadid) + { + /* The thread ID is present in both vector clocks. Compute the */ + /* minimum of vc[i].count and vc[j].count. */ + tl_assert(result->vc[i].threadid == rhs->vc[j].threadid); + if (rhs->vc[j].count < result->vc[i].count) + { + result->vc[i].count = rhs->vc[j].count; + } + } + } + DRD_(vc_check)(result); } /** @@ -162,7 +163,7 @@ void DRD_(vc_min)(VectorClock* const result, const VectorClock* const rhs) */ void DRD_(vc_combine)(VectorClock* const result, const VectorClock* const rhs) { - DRD_(vc_combine2)(result, rhs, -1); + DRD_(vc_combine2)(result, rhs, -1); } /** @@ -175,111 +176,111 @@ Bool DRD_(vc_combine2)(VectorClock* const result, const VectorClock* const rhs, const DrdThreadId tid) { - unsigned i; - unsigned j; - unsigned shared; - unsigned new_size; - Bool almost_equal = True; - - tl_assert(result); - tl_assert(rhs); - - // First count the number of shared thread id's. - j = 0; - shared = 0; - for (i = 0; i < result->size; i++) - { - while (j < rhs->size && rhs->vc[j].threadid < result->vc[i].threadid) - j++; - if (j >= rhs->size) - break; - if (result->vc[i].threadid == rhs->vc[j].threadid) - shared++; - } - - DRD_(vc_check)(result); - - new_size = result->size + rhs->size - shared; - if (new_size > result->capacity) - DRD_(vc_reserve)(result, new_size); - - DRD_(vc_check)(result); - - // Next, combine both vector clocks into one. - i = 0; - for (j = 0; j < rhs->size; j++) - { - /* First of all, skip those clocks in result->vc[] for which there */ - /* is no corresponding clock in rhs->vc[]. */ - while (i < result->size && result->vc[i].threadid < rhs->vc[j].threadid) - { - if (result->vc[i].threadid != tid) - { - almost_equal = False; - } - i++; - } - /* If the end of *result is met, append rhs->vc[j] to *result. */ - if (i >= result->size) - { - result->size++; - result->vc[i] = rhs->vc[j]; - if (result->vc[i].threadid != tid) + unsigned i; + unsigned j; + unsigned shared; + unsigned new_size; + Bool almost_equal = True; + + tl_assert(result); + tl_assert(rhs); + + // First count the number of shared thread id's. + j = 0; + shared = 0; + for (i = 0; i < result->size; i++) + { + while (j < rhs->size && rhs->vc[j].threadid < result->vc[i].threadid) + j++; + if (j >= rhs->size) + break; + if (result->vc[i].threadid == rhs->vc[j].threadid) + shared++; + } + + DRD_(vc_check)(result); + + new_size = result->size + rhs->size - shared; + if (new_size > result->capacity) + DRD_(vc_reserve)(result, new_size); + + DRD_(vc_check)(result); + + // Next, combine both vector clocks into one. + i = 0; + for (j = 0; j < rhs->size; j++) + { + /* First of all, skip those clocks in result->vc[] for which there */ + /* is no corresponding clock in rhs->vc[]. */ + while (i < result->size && result->vc[i].threadid < rhs->vc[j].threadid) { - almost_equal = False; + if (result->vc[i].threadid != tid) + { + almost_equal = False; + } + i++; } - } - /* If clock rhs->vc[j] is not in *result, insert it. */ - else if (result->vc[i].threadid > rhs->vc[j].threadid) - { - unsigned k; - for (k = result->size; k > i; k--) + /* If the end of *result is met, append rhs->vc[j] to *result. */ + if (i >= result->size) { - result->vc[k] = result->vc[k - 1]; + result->size++; + result->vc[i] = rhs->vc[j]; + if (result->vc[i].threadid != tid) + { + almost_equal = False; + } } - result->size++; - result->vc[i] = rhs->vc[j]; - if (result->vc[i].threadid != tid) + /* If clock rhs->vc[j] is not in *result, insert it. */ + else if (result->vc[i].threadid > rhs->vc[j].threadid) { - almost_equal = False; + unsigned k; + for (k = result->size; k > i; k--) + { + result->vc[k] = result->vc[k - 1]; + } + result->size++; + result->vc[i] = rhs->vc[j]; + if (result->vc[i].threadid != tid) + { + almost_equal = False; + } } - } - /* Otherwise, both *result and *rhs have a clock for thread */ - /* result->vc[i].threadid == rhs->vc[j].threadid. Compute the maximum. */ - else - { - tl_assert(result->vc[i].threadid == rhs->vc[j].threadid); - if (result->vc[i].threadid != tid - && rhs->vc[j].count != result->vc[i].count) + /* Otherwise, both *result and *rhs have a clock for thread */ + /* result->vc[i].threadid == rhs->vc[j].threadid. Compute the maximum. */ + else { - almost_equal = False; + tl_assert(result->vc[i].threadid == rhs->vc[j].threadid); + if (result->vc[i].threadid != tid + && rhs->vc[j].count != result->vc[i].count) + { + almost_equal = False; + } + if (rhs->vc[j].count > result->vc[i].count) + { + result->vc[i].count = rhs->vc[j].count; + } } - if (rhs->vc[j].count > result->vc[i].count) - { - result->vc[i].count = rhs->vc[j].count; - } - } - } - DRD_(vc_check)(result); - tl_assert(result->size == new_size); + } + DRD_(vc_check)(result); + tl_assert(result->size == new_size); - return almost_equal; + return almost_equal; } /** Print the contents of vector clock 'vc'. */ void DRD_(vc_print)(const VectorClock* const vc) { - unsigned i; - - tl_assert(vc); - VG_(printf)("["); - for (i = 0; i < vc->size; i++) - { - tl_assert(vc->vc); - VG_(printf)("%s %d: %d", i > 0 ? "," : "", - vc->vc[i].threadid, vc->vc[i].count); - } - VG_(printf)(" ]"); + unsigned i; + + tl_assert(vc); + VG_(printf)("["); + for (i = 0; i < vc->size; i++) + { + tl_assert(vc->vc); + VG_(printf)("%s %d: %d", i > 0 ? "," : "", + vc->vc[i].threadid, vc->vc[i].count); + } + VG_(printf)(" ]"); } /** @@ -289,23 +290,23 @@ void DRD_(vc_print)(const VectorClock* const vc) void DRD_(vc_snprint)(Char* const str, const Int size, const VectorClock* const vc) { - unsigned i; - unsigned j = 1; - - tl_assert(vc); - VG_(snprintf)(str, size, "["); - for (i = 0; i < vc->size; i++) - { - tl_assert(vc->vc); - for ( ; j <= vc->vc[i].threadid; j++) - { - VG_(snprintf)(str + VG_(strlen)(str), size - VG_(strlen)(str), - "%s %d", - i > 0 ? "," : "", - (j == vc->vc[i].threadid) ? vc->vc[i].count : 0); - } - } - VG_(snprintf)(str + VG_(strlen)(str), size - VG_(strlen)(str), " ]"); + unsigned i; + unsigned j = 1; + + tl_assert(vc); + VG_(snprintf)(str, size, "["); + for (i = 0; i < vc->size; i++) + { + tl_assert(vc->vc); + for ( ; j <= vc->vc[i].threadid; j++) + { + VG_(snprintf)(str + VG_(strlen)(str), size - VG_(strlen)(str), + "%s %d", + i > 0 ? "," : "", + (j == vc->vc[i].threadid) ? vc->vc[i].count : 0); + } + } + VG_(snprintf)(str + VG_(strlen)(str), size - VG_(strlen)(str), " ]"); } /** @@ -320,12 +321,12 @@ void DRD_(vc_snprint)(Char* const str, const Int size, */ void DRD_(vc_check)(const VectorClock* const vc) { - unsigned i; - tl_assert(vc->size <= vc->capacity); - for (i = 1; i < vc->size; i++) - { - tl_assert(vc->vc[i-1].threadid < vc->vc[i].threadid); - } + unsigned i; + tl_assert(vc->size <= vc->capacity); + for (i = 1; i < vc->size; i++) + { + tl_assert(vc->vc[i-1].threadid < vc->vc[i].threadid); + } } /** @@ -336,26 +337,26 @@ void DRD_(vc_check)(const VectorClock* const vc) static void DRD_(vc_reserve)(VectorClock* const vc, const unsigned new_capacity) { - tl_assert(vc); - if (new_capacity > vc->capacity) - { - if (vc->vc) - { - vc->vc = VG_(realloc)("drd.vc.vr.1", - vc->vc, new_capacity * sizeof(vc->vc[0])); - } - else if (new_capacity > 0) - { - vc->vc = VG_(malloc)("drd.vc.vr.2", - new_capacity * sizeof(vc->vc[0])); - } - else - { - tl_assert(vc->vc == 0 && new_capacity == 0); - } - vc->capacity = new_capacity; - } - tl_assert(new_capacity == 0 || vc->vc != 0); + tl_assert(vc); + if (new_capacity > vc->capacity) + { + if (vc->vc) + { + vc->vc = VG_(realloc)("drd.vc.vr.1", + vc->vc, new_capacity * sizeof(vc->vc[0])); + } + else if (new_capacity > 0) + { + vc->vc = VG_(malloc)("drd.vc.vr.2", + new_capacity * sizeof(vc->vc[0])); + } + else + { + tl_assert(vc->vc == 0 && new_capacity == 0); + } + vc->capacity = new_capacity; + } + tl_assert(new_capacity == 0 || vc->vc != 0); } #if 0 @@ -364,40 +365,42 @@ void DRD_(vc_reserve)(VectorClock* const vc, const unsigned new_capacity) */ void DRD_(vc_test)(void) { - VectorClock vc1; - VCElem vc1elem[] = { { 3, 7 }, { 5, 8 }, }; - VectorClock vc2; - VCElem vc2elem[] = { { 1, 4 }, { 3, 9 }, }; - VectorClock vc3; - VCElem vc4elem[] = { { 1, 3 }, { 2, 1 }, }; - VectorClock vc4; - VCElem vc5elem[] = { { 1, 4 }, }; - VectorClock vc5; - - vc_init(&vc1, vc1elem, sizeof(vc1elem)/sizeof(vc1elem[0])); - vc_init(&vc2, vc2elem, sizeof(vc2elem)/sizeof(vc2elem[0])); - vc_init(&vc3, 0, 0); - vc_init(&vc4, vc4elem, sizeof(vc4elem)/sizeof(vc4elem[0])); - vc_init(&vc5, vc5elem, sizeof(vc5elem)/sizeof(vc5elem[0])); - - vc_combine(&vc3, &vc1); - vc_combine(&vc3, &vc2); - - VG_(printf)("vc1: "); - vc_print(&vc1); - VG_(printf)("\nvc2: "); - vc_print(&vc2); - VG_(printf)("\nvc3: "); - vc_print(&vc3); - VG_(printf)("\n"); - VG_(printf)("vc_lte(vc1, vc2) = %d, vc_lte(vc1, vc3) = %d, vc_lte(vc2, vc3) = %d, vc_lte(", vc_lte(&vc1, &vc2), vc_lte(&vc1, &vc3), vc_lte(&vc2, &vc3)); - vc_print(&vc4); - VG_(printf)(", "); - vc_print(&vc5); - VG_(printf)(") = %d sw %d\n", vc_lte(&vc4, &vc5), vc_lte(&vc5, &vc4)); + VectorClock vc1; + VCElem vc1elem[] = { { 3, 7 }, { 5, 8 }, }; + VectorClock vc2; + VCElem vc2elem[] = { { 1, 4 }, { 3, 9 }, }; + VectorClock vc3; + VCElem vc4elem[] = { { 1, 3 }, { 2, 1 }, }; + VectorClock vc4; + VCElem vc5elem[] = { { 1, 4 }, }; + VectorClock vc5; + + vc_init(&vc1, vc1elem, sizeof(vc1elem)/sizeof(vc1elem[0])); + vc_init(&vc2, vc2elem, sizeof(vc2elem)/sizeof(vc2elem[0])); + vc_init(&vc3, 0, 0); + vc_init(&vc4, vc4elem, sizeof(vc4elem)/sizeof(vc4elem[0])); + vc_init(&vc5, vc5elem, sizeof(vc5elem)/sizeof(vc5elem[0])); + + vc_combine(&vc3, &vc1); + vc_combine(&vc3, &vc2); + + VG_(printf)("vc1: "); + vc_print(&vc1); + VG_(printf)("\nvc2: "); + vc_print(&vc2); + VG_(printf)("\nvc3: "); + vc_print(&vc3); + VG_(printf)("\n"); + VG_(printf)("vc_lte(vc1, vc2) = %d, vc_lte(vc1, vc3) = %d," + " vc_lte(vc2, vc3) = %d, vc_lte(", + vc_lte(&vc1, &vc2), vc_lte(&vc1, &vc3), vc_lte(&vc2, &vc3)); + vc_print(&vc4); + VG_(printf)(", "); + vc_print(&vc5); + VG_(printf)(") = %d sw %d\n", vc_lte(&vc4, &vc5), vc_lte(&vc5, &vc4)); - vc_cleanup(&vc1); - vc_cleanup(&vc2); - vc_cleanup(&vc3); + vc_cleanup(&vc1); + vc_cleanup(&vc2); + vc_cleanup(&vc3); } #endif diff --git a/drd/drd_vc.h b/drd/drd_vc.h index a97c5314ae..c7f1fb168c 100644 --- a/drd/drd_vc.h +++ b/drd/drd_vc.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -52,15 +53,15 @@ /** Vector clock element. */ typedef struct { - DrdThreadId threadid; - UInt count; + DrdThreadId threadid; + UInt count; } VCElem; typedef struct { - unsigned capacity; /**< number of elements allocated for array vc. */ - unsigned size; /**< number of elements used of array vc. */ - VCElem* vc; /**< vector clock elements. */ + unsigned capacity; /**< number of elements allocated for array vc. */ + unsigned size; /**< number of elements used of array vc. */ + VCElem* vc; /**< vector clock elements. */ } VectorClock; @@ -99,26 +100,26 @@ void DRD_(vc_test)(void); static __inline__ Bool DRD_(vc_lte)(const VectorClock* const vc1, const VectorClock* const vc2) { - unsigned i; - unsigned j = 0; - - for (i = 0; i < vc1->size; i++) - { - while (j < vc2->size && vc2->vc[j].threadid < vc1->vc[i].threadid) - { - j++; - } - if (j >= vc2->size || vc2->vc[j].threadid > vc1->vc[i].threadid) - return False; + unsigned i; + unsigned j = 0; + + for (i = 0; i < vc1->size; i++) + { + while (j < vc2->size && vc2->vc[j].threadid < vc1->vc[i].threadid) + { + j++; + } + if (j >= vc2->size || vc2->vc[j].threadid > vc1->vc[i].threadid) + return False; #ifdef ENABLE_DRD_CONSISTENCY_CHECKS - /* This assert statement has been commented out because of performance */ - /* reasons.*/ - tl_assert(j < vc2->size && vc2->vc[j].threadid == vc1->vc[i].threadid); + /* This assert statement has been commented out because of performance */ + /* reasons.*/ + tl_assert(j < vc2->size && vc2->vc[j].threadid == vc1->vc[i].threadid); #endif - if (vc1->vc[i].count > vc2->vc[j].count) - return False; - } - return True; + if (vc1->vc[i].count > vc2->vc[j].count) + return False; + } + return True; } diff --git a/drd/pub_drd_bitmap.h b/drd/pub_drd_bitmap.h index c0d932306c..e6f23049dc 100644 --- a/drd/pub_drd_bitmap.h +++ b/drd/pub_drd_bitmap.h @@ -1,3 +1,4 @@ +/* -*- mode: C; c-basic-offset: 3; -*- */ /* This file is part of drd, a thread error detector. @@ -42,8 +43,8 @@ #define LHS_W (1<<1) #define RHS_R (1<<2) #define RHS_W (1<<3) -#define HAS_RACE(a) ((((a) & RHS_W) && ((a) & (LHS_R | LHS_W))) \ - || (((a) & LHS_W) && ((a) & (RHS_R | RHS_W)))) +#define HAS_RACE(a) ((((a) & RHS_W) && ((a) & (LHS_R | LHS_W))) \ + || (((a) & LHS_W) && ((a) & (RHS_R | RHS_W)))) /* Forward declarations. */