18564292ac4b9adf51c45517cca2878732feb5bb4sewardj/* 286562bd89ac23ce795d19c71fabcb9d1c8f956d3bart This file is part of drd, a thread error detector. 38564292ac4b9adf51c45517cca2878732feb5bb4sewardj 4b3a1e4bffbdbbf38304f216af405009868f43628sewardj Copyright (C) 2006-2015 Bart Van Assche <bvanassche@acm.org>. 58564292ac4b9adf51c45517cca2878732feb5bb4sewardj 68564292ac4b9adf51c45517cca2878732feb5bb4sewardj This program is free software; you can redistribute it and/or 78564292ac4b9adf51c45517cca2878732feb5bb4sewardj modify it under the terms of the GNU General Public License as 88564292ac4b9adf51c45517cca2878732feb5bb4sewardj published by the Free Software Foundation; either version 2 of the 98564292ac4b9adf51c45517cca2878732feb5bb4sewardj License, or (at your option) any later version. 108564292ac4b9adf51c45517cca2878732feb5bb4sewardj 118564292ac4b9adf51c45517cca2878732feb5bb4sewardj This program is distributed in the hope that it will be useful, but 128564292ac4b9adf51c45517cca2878732feb5bb4sewardj WITHOUT ANY WARRANTY; without even the implied warranty of 138564292ac4b9adf51c45517cca2878732feb5bb4sewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 148564292ac4b9adf51c45517cca2878732feb5bb4sewardj General Public License for more details. 158564292ac4b9adf51c45517cca2878732feb5bb4sewardj 168564292ac4b9adf51c45517cca2878732feb5bb4sewardj You should have received a copy of the GNU General Public License 178564292ac4b9adf51c45517cca2878732feb5bb4sewardj along with this program; if not, write to the Free Software 188564292ac4b9adf51c45517cca2878732feb5bb4sewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 198564292ac4b9adf51c45517cca2878732feb5bb4sewardj 02111-1307, USA. 208564292ac4b9adf51c45517cca2878732feb5bb4sewardj 218564292ac4b9adf51c45517cca2878732feb5bb4sewardj The GNU General Public License is contained in the file COPYING. 228564292ac4b9adf51c45517cca2878732feb5bb4sewardj*/ 238564292ac4b9adf51c45517cca2878732feb5bb4sewardj 248564292ac4b9adf51c45517cca2878732feb5bb4sewardj 258564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_barrier.h" 2628230a3734e045791173aca660efc7d7aeef78cebart#include "drd_clientobj.h" 278564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_error.h" 288564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_suppression.h" 298564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_errormgr.h" // VG_(maybe_record_error)() 308564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcassert.h" // tl_assert() 318564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcprint.h" // VG_(printf)() 328564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_machine.h" // VG_(get_IP)() 338564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)() 348564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_oset.h" 358564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_threadstate.h" // VG_(get_running_tid)() 368564292ac4b9adf51c45517cca2878732feb5bb4sewardj 378564292ac4b9adf51c45517cca2878732feb5bb4sewardj 38a8cf765964dc9b9436384469a0a30889b24d1997bart/* Type definitions. */ 398564292ac4b9adf51c45517cca2878732feb5bb4sewardj 408ddef8828240404bfcbd38651a53aa38be044ab6bart/** Information associated with one thread participating in a barrier. */ 41bebc5d668dc5a6df337011181debbf8d91c338e0bartstruct barrier_thread_info 42bebc5d668dc5a6df337011181debbf8d91c338e0bart{ 43bedfd237fbdc80d0c917cfcb85a94b5561c92633bart UWord tid; // A DrdThreadId declared as UWord because 4462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart // this member variable is the key of an OSet. 45d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart Segment* sg; // Segment of the last pthread_barrier() call 46d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart // by thread tid. 47bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* post_wait_sg; // Segment created after *_barrier_wait() finished 48d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call. 49d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart Bool thread_finished;// Whether thread 'tid' has finished. 508564292ac4b9adf51c45517cca2878732feb5bb4sewardj}; 518564292ac4b9adf51c45517cca2878732feb5bb4sewardj 528564292ac4b9adf51c45517cca2878732feb5bb4sewardj 53a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local functions. */ 5428230a3734e045791173aca660efc7d7aeef78cebart 55d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_cleanup(struct barrier_info* p); 56d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p, 57d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const DrdThreadId tid); 5819f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic const HChar* barrier_get_typename(struct barrier_info* const p); 5919f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic const HChar* barrier_type_name(const BarrierT bt); 60d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic 61d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p, 62bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const struct barrier_thread_info* const q); 6328230a3734e045791173aca660efc7d7aeef78cebart 6428230a3734e045791173aca660efc7d7aeef78cebart 65a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local variables. */ 668564292ac4b9adf51c45517cca2878732feb5bb4sewardj 67d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic Bool s_trace_barrier = False; 68d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic ULong s_barrier_segment_creation_count; 698564292ac4b9adf51c45517cca2878732feb5bb4sewardj 708564292ac4b9adf51c45517cca2878732feb5bb4sewardj 71a8cf765964dc9b9436384469a0a30889b24d1997bart/* Function definitions. */ 728564292ac4b9adf51c45517cca2878732feb5bb4sewardj 73a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_set_trace)(const Bool trace_barrier) 748564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 75bedfd237fbdc80d0c917cfcb85a94b5561c92633bart s_trace_barrier = trace_barrier; 768564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 778564292ac4b9adf51c45517cca2878732feb5bb4sewardj 78d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 79d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified thread ID and iteration 80d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * information. 81d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 82a8cf765964dc9b9436384469a0a30889b24d1997bartstatic 83a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p, 84cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart const DrdThreadId tid) 858564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 86d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->tid = tid; 87d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->sg = NULL; 88d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->post_wait_sg = 0; 89d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->wait_call_ctxt = 0; 90d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->thread_finished = False; 918564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 928564292ac4b9adf51c45517cca2878732feb5bb4sewardj 93d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 94d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Deallocate the memory that is owned by members of 95d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * struct barrier_thread_info. 96d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 97a8cf765964dc9b9436384469a0a30889b24d1997bartstatic void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p) 988564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 99bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 100d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(sg_put)(p->sg); 101bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(p->post_wait_sg); 1028564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1038564292ac4b9adf51c45517cca2878732feb5bb4sewardj 104d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 105d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified client-side barrier address, 106d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * barrier object size and number of participants in each barrier. 107d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 1088564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 109a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_initialize)(struct barrier_info* const p, 110a8cf765964dc9b9436384469a0a30889b24d1997bart const Addr barrier, 111a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, 112a8cf765964dc9b9436384469a0a30889b24d1997bart const Word count) 1138564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 114d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart int i; 115d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart 116bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier != 0); 117bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 118bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p->a1 == barrier); 119bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 120bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup; 121bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->delete_thread 122bedfd237fbdc80d0c917cfcb85a94b5561c92633bart = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread; 123bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->barrier_type = barrier_type; 124bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count = count; 125bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_iteration = 0; 126bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_iteration = 0; 127bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_waiters_left = count; 128bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_waiters_left = count; 129bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 130bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word)); 131bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) 132bedfd237fbdc80d0c917cfcb85a94b5561c92633bart >= sizeof(DrdThreadId)); 133d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for (i = 0; i < 2; i++) { 134d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->oset[i] = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1", 135d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(free)); 136d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 1378564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1388564292ac4b9adf51c45517cca2878732feb5bb4sewardj 139195e41fe2b9e02e142a0461113bfa55c89d24c5ebart/** 140d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Deallocate the memory owned by the struct barrier_info object and also 141d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * all the nodes in the OSet p->oset. 142d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * 143195e41fe2b9e02e142a0461113bfa55c89d24c5ebart * Called by clientobj_destroy(). 14428230a3734e045791173aca660efc7d7aeef78cebart */ 145d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_cleanup(struct barrier_info* p) 1468564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 147bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 148bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* latest_sg = 0; 149d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 150d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart int i; 151bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 152bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 153bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 154d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)()); 155d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(latest_sg); 156d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart 157d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (p->pre_waiters_left != p->count) { 158d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 159bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 160bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 161bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 162bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of barrier that is being waited" 163bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " upon", 164bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 165d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } else { 166d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart oset = p->oset[1 - (p->pre_iteration & 1)]; 167d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 168d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) { 169d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q->post_wait_sg && !DRD_(vc_lte)(&q->post_wait_sg->vc, 170d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart &latest_sg->vc)) 171d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart { 172d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart barrier_report_wait_delete_race(p, q); 173d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 174d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(barrier_thread_destroy)(q); 175bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 176d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 177bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 178d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for (i = 0; i < 2; i++) { 179d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Destroy)(p->oset[i]); 180d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->oset[i] = NULL; 181bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 182bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 183bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(latest_sg); 1848564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1858564292ac4b9adf51c45517cca2878732feb5bb4sewardj 186d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 187d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Look up the client-side barrier address barrier in s_barrier[]. If not 188d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * found, add it. 189d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 1908564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 1918564292ac4b9adf51c45517cca2878732feb5bb4sewardjstruct barrier_info* 192a8cf765964dc9b9436384469a0a30889b24d1997bartDRD_(barrier_get_or_allocate)(const Addr barrier, 193a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, const Word count) 1948564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 195bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info *p; 196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 198bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 199bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, barrier) == 0); 200bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); 201bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 202bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 203bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_add)(barrier, ClientBarrier)->barrier); 204bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(barrier_initialize)(p, barrier, barrier_type, count); 205bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 206bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return p; 20728230a3734e045791173aca660efc7d7aeef78cebart} 20828230a3734e045791173aca660efc7d7aeef78cebart 209d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 210d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * Look up the address of the struct barrier_info associated with the 211d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * client-side barrier object. 212d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 213a8cf765964dc9b9436384469a0a30889b24d1997bartstatic struct barrier_info* DRD_(barrier_get)(const Addr barrier) 21428230a3734e045791173aca660efc7d7aeef78cebart{ 215bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, barrier) == 0); 216bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); 2178564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 2188564292ac4b9adf51c45517cca2878732feb5bb4sewardj 219d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 220d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * Initialize a barrier with given client address, barrier type and number of 221d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * participants. The 'reinitialization' argument indicates whether a barrier 222d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * object is being initialized or reinitialized. 223d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * 224d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Called before pthread_barrier_init(). 22528230a3734e045791173aca660efc7d7aeef78cebart */ 226a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_init)(const Addr barrier, 227a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, const Word count, 228a8cf765964dc9b9436384469a0a30889b24d1997bart const Bool reinitialization) 2298564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 230bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 231bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 232bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 233bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 234bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (count == 0) 235bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 236d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; 237d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart VG_(maybe_record_error)(VG_(get_running_tid)(), 238d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart BarrierErr, 239d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart VG_(get_IP)(VG_(get_running_tid)()), 240bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "pthread_barrier_init: 'count' argument is zero", 241d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart &bei); 242bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 244bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (! reinitialization && barrier_type == pthread_barrier) 245bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 247bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p) 248bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 249d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; 250bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 251bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 252bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 253bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Barrier reinitialization", 254bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 255bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 256bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 257d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart 258bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count); 259bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 260b92ff0fd192dd05700f7d20db00795965e20b5c5bart if (s_trace_barrier) { 261bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization) 262ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] barrier_reinit %s 0x%lx count %ld -> %ld", 263b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 264b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), barrier, p->count, count); 265bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 266ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] barrier_init %s 0x%lx", 267b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 268b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), 269b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier); 270bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization && p->count != count) 273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 275bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 276d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 277bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 278bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 279bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 280bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Reinitialization of barrier with active" 281bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " waiters", 282bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 283bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 284bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count = count; 285bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 286bedfd237fbdc80d0c917cfcb85a94b5561c92633bart} 287bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 288bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */ 289bedfd237fbdc80d0c917cfcb85a94b5561c92633bartvoid DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type) 290bedfd237fbdc80d0c917cfcb85a94b5561c92633bart{ 291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 293bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 294bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 296ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] barrier_destroy %s 0x%lx", 297b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 298b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), barrier); 299bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 300bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 30262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart GenericErrInfo GEI = { 30362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .tid = DRD_(thread_get_running_tid)(), 30462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .addr = barrier, 30562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 306bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 307bedfd237fbdc80d0c917cfcb85a94b5561c92633bart GenericErr, 308bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 309bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Not a barrier", 310bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &GEI); 311bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 312bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 313306527d7413780873a05cf801c47f725fb60c310bart 314bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 315bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 316d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 317195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(maybe_record_error)(VG_(get_running_tid)(), 318195a3983ff6030cbe21fd4561006acdd3c31dbafbart BarrierErr, 319195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(get_IP)(VG_(get_running_tid)()), 320bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of a barrier with active waiters", 321195a3983ff6030cbe21fd4561006acdd3c31dbafbart &bei); 322bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 3238564292ac4b9adf51c45517cca2878732feb5bb4sewardj 324bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(clientobj_remove)(p->a1, ClientBarrier); 3258564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 3268564292ac4b9adf51c45517cca2878732feb5bb4sewardj 327d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */ 328a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier, 329a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type) 3308564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 331bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 332bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 333bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 334d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 335bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 336bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 33774b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart if (p == 0 && barrier_type == gomp_barrier) { 338bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 339bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * gomp_barrier_wait() call has been intercepted but gomp_barrier_init() 340bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * not. The only cause I know of that can trigger this is that libgomp.so 341bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * has been compiled with --enable-linux-futex. 342bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 34374b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), 0, 0, 0 }; 34474b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart VG_(maybe_record_error)(VG_(get_running_tid)(), 34574b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart BarrierErr, 34674b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart VG_(get_IP)(VG_(get_running_tid)()), 34774b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart "Please verify whether gcc has been configured" 34874b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart " with option --disable-linux-futex. See also" 34974b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart " the section about OpenMP in the DRD manual.", 35074b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart &bei); 351bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 355ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] barrier_pre_wait %s 0x%lx iteration %ld", 356b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 357b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), barrier, p->pre_iteration); 358bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 359d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart /* Clean up nodes associated with finished threads. */ 360d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart oset = p->oset[p->pre_iteration & 1]; 361d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(oset); 362d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 363d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) { 364d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q->thread_finished) { 365d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart void* r = VG_(OSetGen_Remove)(oset, &q->tid); 366d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(r == q); 367d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(barrier_thread_destroy)(q); 368d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_FreeNode)(oset, q); 369d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIterAt)(oset, &word_tid); 370d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 371d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 372bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Allocate the per-thread data structure if necessary. */ 373d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(oset, &word_tid); 374d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q == NULL) { 375d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); 376cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart DRD_(barrier_thread_initialize)(q, tid); 377d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Insert)(oset, q); 378d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q); 379bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 380bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 381bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Record *_barrier_wait() call context. */ 382bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); 383bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 384bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 385bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Store a pointer to the latest segment of the current thread in the 386bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * per-thread data structure. 387bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 388d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(thread_get_latest_segment)(&q->sg, tid); 389bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 390bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 391bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 392bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and 393bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->pre_waiters_left counter. 394bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 395bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->pre_waiters_left <= 0) 396bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 397d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart p->pre_iteration++; 398bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_waiters_left = p->count; 399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4008564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 4018564292ac4b9adf51c45517cca2878732feb5bb4sewardj 402d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */ 403a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier, 404d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const BarrierT barrier_type, const Bool waited, 405d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const Bool serializing) 4068564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 407bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 408bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* r; 411d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 412bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 413bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 414bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 416ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] barrier_post_wait %s 0x%lx iteration %ld%s", 417b92ff0fd192dd05700f7d20db00795965e20b5c5bart tid, p ? barrier_get_typename(p) : "(?)", 418b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier, p ? p->post_iteration : -1, 419b92ff0fd192dd05700f7d20db00795965e20b5c5bart serializing ? " (serializing)" : ""); 420bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 421bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 422bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If p == 0, this means that the barrier has been destroyed after 423bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * *_barrier_wait() returned and before this function was called. Just 424bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * return in that case -- race conditions between *_barrier_wait() 425bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper. 426bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 427bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 430bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* If the *_barrier_wait() call returned an error code, exit. */ 431bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (! waited) 432bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 433bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 434d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart oset = p->oset[p->post_iteration & 1]; 435d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(oset, &word_tid); 436d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart if (p->pre_iteration - p->post_iteration > 1) { 437d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 438d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart VG_(maybe_record_error)(VG_(get_running_tid)(), 439d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart BarrierErr, 440d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart VG_(get_IP)(VG_(get_running_tid)()), 441d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart "Number of concurrent pthread_barrier_wait()" 442d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart " calls exceeds the barrier count", 443d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart &bei); 444d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart } else if (q == NULL) { 445d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 446bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 447bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 448bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 449bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Error in barrier implementation" 450bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " -- barrier_wait() started before" 451bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy() and finished after" 452bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy()", 453bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 454d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart } 455d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart if (q == NULL) { 456d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); 457cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart DRD_(barrier_thread_initialize)(q, tid); 458d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Insert)(oset, q); 459d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q); 460d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart DRD_(thread_get_latest_segment)(&q->sg, tid); 461bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4627627be3e26162e4f59ccfd35eaf31495ddefdf9bbart 4637627be3e26162e4f59ccfd35eaf31495ddefdf9bbart /* Create a new segment and store a pointer to that segment. */ 4647627be3e26162e4f59ccfd35eaf31495ddefdf9bbart DRD_(thread_new_segment)(tid); 4657627be3e26162e4f59ccfd35eaf31495ddefdf9bbart DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid); 4667627be3e26162e4f59ccfd35eaf31495ddefdf9bbart s_barrier_segment_creation_count++; 4677627be3e26162e4f59ccfd35eaf31495ddefdf9bbart 468bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 469bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Combine all vector clocks that were stored in the pre_barrier_wait 470bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * wrapper with the vector clock of the current thread. 471bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 472bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 4738f822af9b234e7c553c408eba65a641c4773457fbart VectorClock old_vc; 4748f822af9b234e7c553c408eba65a641c4773457fbart 475ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(tid)); 476d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 477d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (r = VG_(OSetGen_Next)(oset)) != 0; ) 478bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 4798f822af9b234e7c553c408eba65a641c4773457fbart if (r != q) 4808f822af9b234e7c553c408eba65a641c4773457fbart { 481d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(r->sg); 482ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart DRD_(vc_combine)(DRD_(thread_get_vc)(tid), &r->sg->vc); 4838f822af9b234e7c553c408eba65a641c4773457fbart } 484bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4858f822af9b234e7c553c408eba65a641c4773457fbart DRD_(thread_update_conflict_set)(tid, &old_vc); 4868f822af9b234e7c553c408eba65a641c4773457fbart DRD_(vc_cleanup)(&old_vc); 487bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 488bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 489bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 490bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 491bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the post *_barrier_wait() wrapper, toggle p->post_iteration and 492bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->post_waiters_left counter. 493bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 494bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->post_waiters_left <= 0) 495bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 496d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart p->post_iteration++; 497bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_waiters_left = p->count; 498bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 499d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart} 500bebc5d668dc5a6df337011181debbf8d91c338e0bart 501d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called when thread tid stops to exist. */ 502d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p, 503d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const DrdThreadId tid) 504d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart{ 505bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 506bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 507d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart int i; 508bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 509d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for (i = 0; i < 2; i++) { 510d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(p->oset[i], &word_tid); 511d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q) 512d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q->thread_finished = True; 513bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5148564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 5158564292ac4b9adf51c45517cca2878732feb5bb4sewardj 516d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 517d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Report that *_barrier_destroy() has been called but that this call was 518d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * not synchronized with the last *_barrier_wait() call on the same barrier. 519776a91e8fe04875abc38c1e7d0bc30175d285975bart * 520776a91e8fe04875abc38c1e7d0bc30175d285975bart * This topic has been discussed extensively on comp.programming.threads 521776a91e8fe04875abc38c1e7d0bc30175d285975bart * (February 3, 2009). See also 522776a91e8fe04875abc38c1e7d0bc30175d285975bart * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>. 523d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 524d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic 525d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p, 526d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const struct barrier_thread_info* const q) 5278564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 528bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 529bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(q); 530bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 531bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 532bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErrInfo bei 533d45d99553c15a361bb797d21ec6afb9bad22d2d4bart = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt }; 534bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 535bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 536bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 537bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of barrier not synchronized with" 538bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier wait call", 539bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 540bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5418564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 542306527d7413780873a05cf801c47f725fb60c310bart 54319f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic const HChar* barrier_get_typename(struct barrier_info* const p) 544306527d7413780873a05cf801c47f725fb60c310bart{ 545bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 546306527d7413780873a05cf801c47f725fb60c310bart 547bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return barrier_type_name(p->barrier_type); 548306527d7413780873a05cf801c47f725fb60c310bart} 549306527d7413780873a05cf801c47f725fb60c310bart 55019f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic const HChar* barrier_type_name(const BarrierT bt) 551306527d7413780873a05cf801c47f725fb60c310bart{ 552bedfd237fbdc80d0c917cfcb85a94b5561c92633bart switch (bt) 553bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 554bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case pthread_barrier: 555bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "pthread barrier"; 556bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case gomp_barrier: 557bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "gomp barrier"; 558bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 559bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "?"; 560306527d7413780873a05cf801c47f725fb60c310bart} 5616bbefaf8418f3e225c4eefcc726b6874bef15d8cbart 562a8cf765964dc9b9436384469a0a30889b24d1997bartULong DRD_(get_barrier_segment_creation_count)(void) 5636bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{ 564bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return s_barrier_segment_creation_count; 5656bbefaf8418f3e225c4eefcc726b6874bef15d8cbart} 566