drd_barrier.c revision d61580edabd4bd165c2484b92cb8d4cb2b65d32f
1922304f9e9d5df1a20a1bb1d4736263c99272aa4bart/* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */ 28564292ac4b9adf51c45517cca2878732feb5bb4sewardj/* 386562bd89ac23ce795d19c71fabcb9d1c8f956d3bart This file is part of drd, a thread error detector. 48564292ac4b9adf51c45517cca2878732feb5bb4sewardj 5922304f9e9d5df1a20a1bb1d4736263c99272aa4bart Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>. 68564292ac4b9adf51c45517cca2878732feb5bb4sewardj 78564292ac4b9adf51c45517cca2878732feb5bb4sewardj This program is free software; you can redistribute it and/or 88564292ac4b9adf51c45517cca2878732feb5bb4sewardj modify it under the terms of the GNU General Public License as 98564292ac4b9adf51c45517cca2878732feb5bb4sewardj published by the Free Software Foundation; either version 2 of the 108564292ac4b9adf51c45517cca2878732feb5bb4sewardj License, or (at your option) any later version. 118564292ac4b9adf51c45517cca2878732feb5bb4sewardj 128564292ac4b9adf51c45517cca2878732feb5bb4sewardj This program is distributed in the hope that it will be useful, but 138564292ac4b9adf51c45517cca2878732feb5bb4sewardj WITHOUT ANY WARRANTY; without even the implied warranty of 148564292ac4b9adf51c45517cca2878732feb5bb4sewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 158564292ac4b9adf51c45517cca2878732feb5bb4sewardj General Public License for more details. 168564292ac4b9adf51c45517cca2878732feb5bb4sewardj 178564292ac4b9adf51c45517cca2878732feb5bb4sewardj You should have received a copy of the GNU General Public License 188564292ac4b9adf51c45517cca2878732feb5bb4sewardj along with this program; if not, write to the Free Software 198564292ac4b9adf51c45517cca2878732feb5bb4sewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 208564292ac4b9adf51c45517cca2878732feb5bb4sewardj 02111-1307, USA. 218564292ac4b9adf51c45517cca2878732feb5bb4sewardj 228564292ac4b9adf51c45517cca2878732feb5bb4sewardj The GNU General Public License is contained in the file COPYING. 238564292ac4b9adf51c45517cca2878732feb5bb4sewardj*/ 248564292ac4b9adf51c45517cca2878732feb5bb4sewardj 258564292ac4b9adf51c45517cca2878732feb5bb4sewardj 268564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_barrier.h" 2728230a3734e045791173aca660efc7d7aeef78cebart#include "drd_clientobj.h" 288564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_error.h" 298564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_suppression.h" 308564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_errormgr.h" // VG_(maybe_record_error)() 318564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcassert.h" // tl_assert() 328564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcprint.h" // VG_(printf)() 338564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_machine.h" // VG_(get_IP)() 348564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)() 358564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_oset.h" 368564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_threadstate.h" // VG_(get_running_tid)() 378564292ac4b9adf51c45517cca2878732feb5bb4sewardj 388564292ac4b9adf51c45517cca2878732feb5bb4sewardj 39a8cf765964dc9b9436384469a0a30889b24d1997bart/* Type definitions. */ 408564292ac4b9adf51c45517cca2878732feb5bb4sewardj 418ddef8828240404bfcbd38651a53aa38be044ab6bart/** Information associated with one thread participating in a barrier. */ 42bebc5d668dc5a6df337011181debbf8d91c338e0bartstruct barrier_thread_info 43bebc5d668dc5a6df337011181debbf8d91c338e0bart{ 44bedfd237fbdc80d0c917cfcb85a94b5561c92633bart UWord tid; // A DrdThreadId declared as UWord because 4562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart // this member variable is the key of an OSet. 46d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart Segment* sg; // Segment of the last pthread_barrier() call 47d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart // by thread tid. 48bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* post_wait_sg; // Segment created after *_barrier_wait() finished 49d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call. 50d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart Bool thread_finished;// Whether thread 'tid' has finished. 518564292ac4b9adf51c45517cca2878732feb5bb4sewardj}; 528564292ac4b9adf51c45517cca2878732feb5bb4sewardj 538564292ac4b9adf51c45517cca2878732feb5bb4sewardj 54a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local functions. */ 5528230a3734e045791173aca660efc7d7aeef78cebart 56d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_cleanup(struct barrier_info* p); 57d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p, 58d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const DrdThreadId tid); 59d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p); 60d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt); 61d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic 62d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p, 63bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const struct barrier_thread_info* const q); 6428230a3734e045791173aca660efc7d7aeef78cebart 6528230a3734e045791173aca660efc7d7aeef78cebart 66a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local variables. */ 678564292ac4b9adf51c45517cca2878732feb5bb4sewardj 68d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic Bool s_trace_barrier = False; 69d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic ULong s_barrier_segment_creation_count; 708564292ac4b9adf51c45517cca2878732feb5bb4sewardj 718564292ac4b9adf51c45517cca2878732feb5bb4sewardj 72a8cf765964dc9b9436384469a0a30889b24d1997bart/* Function definitions. */ 738564292ac4b9adf51c45517cca2878732feb5bb4sewardj 74a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_set_trace)(const Bool trace_barrier) 758564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 76bedfd237fbdc80d0c917cfcb85a94b5561c92633bart s_trace_barrier = trace_barrier; 778564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 788564292ac4b9adf51c45517cca2878732feb5bb4sewardj 79d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 80d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified thread ID and iteration 81d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * information. 82d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 83a8cf765964dc9b9436384469a0a30889b24d1997bartstatic 84a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p, 85cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart const DrdThreadId tid) 868564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 87d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->tid = tid; 88d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->sg = NULL; 89d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->post_wait_sg = 0; 90d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->wait_call_ctxt = 0; 91d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->thread_finished = False; 928564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 938564292ac4b9adf51c45517cca2878732feb5bb4sewardj 94d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 95d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Deallocate the memory that is owned by members of 96d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * struct barrier_thread_info. 97d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 98a8cf765964dc9b9436384469a0a30889b24d1997bartstatic void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p) 998564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 100bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 101d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(sg_put)(p->sg); 102bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(p->post_wait_sg); 1038564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1048564292ac4b9adf51c45517cca2878732feb5bb4sewardj 105d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 106d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified client-side barrier address, 107d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * barrier object size and number of participants in each barrier. 108d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 1098564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 110a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_initialize)(struct barrier_info* const p, 111a8cf765964dc9b9436384469a0a30889b24d1997bart const Addr barrier, 112a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, 113a8cf765964dc9b9436384469a0a30889b24d1997bart const Word count) 1148564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 115d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart int i; 116d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart 117bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier != 0); 118bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 119bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p->a1 == barrier); 120bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 121bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup; 122bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->delete_thread 123bedfd237fbdc80d0c917cfcb85a94b5561c92633bart = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread; 124bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->barrier_type = barrier_type; 125bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count = count; 126bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_iteration = 0; 127bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_iteration = 0; 128bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_waiters_left = count; 129bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_waiters_left = count; 130bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 131bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word)); 132bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) 133bedfd237fbdc80d0c917cfcb85a94b5561c92633bart >= sizeof(DrdThreadId)); 134d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for (i = 0; i < 2; i++) { 135d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->oset[i] = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1", 136d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(free)); 137d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 1388564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1398564292ac4b9adf51c45517cca2878732feb5bb4sewardj 140195e41fe2b9e02e142a0461113bfa55c89d24c5ebart/** 141d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Deallocate the memory owned by the struct barrier_info object and also 142d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * all the nodes in the OSet p->oset. 143d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * 144195e41fe2b9e02e142a0461113bfa55c89d24c5ebart * Called by clientobj_destroy(). 14528230a3734e045791173aca660efc7d7aeef78cebart */ 146d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_cleanup(struct barrier_info* p) 1478564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 148bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 149bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* latest_sg = 0; 150d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 151d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart int i; 152bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 153bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 154bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 155d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)()); 156d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(latest_sg); 157d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart 158d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (p->pre_waiters_left != p->count) { 159d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 160bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 161bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 162bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 163bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of barrier that is being waited" 164bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " upon", 165bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 166d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } else { 167d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart oset = p->oset[1 - p->pre_iteration]; 168d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 169d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) { 170d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q->post_wait_sg && !DRD_(vc_lte)(&q->post_wait_sg->vc, 171d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart &latest_sg->vc)) 172d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart { 173d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart barrier_report_wait_delete_race(p, q); 174d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 175d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(barrier_thread_destroy)(q); 176bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 177d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 178bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 179d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for (i = 0; i < 2; i++) { 180d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Destroy)(p->oset[i]); 181d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart p->oset[i] = NULL; 182bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 183bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 184bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(latest_sg); 1858564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1868564292ac4b9adf51c45517cca2878732feb5bb4sewardj 187d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 188d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Look up the client-side barrier address barrier in s_barrier[]. If not 189d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * found, add it. 190d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 1918564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 1928564292ac4b9adf51c45517cca2878732feb5bb4sewardjstruct barrier_info* 193a8cf765964dc9b9436384469a0a30889b24d1997bartDRD_(barrier_get_or_allocate)(const Addr barrier, 194a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, const Word count) 1958564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info *p; 197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 198bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 199bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 200bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, barrier) == 0); 201bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); 202bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 203bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 204bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_add)(barrier, ClientBarrier)->barrier); 205bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(barrier_initialize)(p, barrier, barrier_type, count); 206bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 207bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return p; 20828230a3734e045791173aca660efc7d7aeef78cebart} 20928230a3734e045791173aca660efc7d7aeef78cebart 210d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 211d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * Look up the address of the struct barrier_info associated with the 212d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * client-side barrier object. 213d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 214a8cf765964dc9b9436384469a0a30889b24d1997bartstatic struct barrier_info* DRD_(barrier_get)(const Addr barrier) 21528230a3734e045791173aca660efc7d7aeef78cebart{ 216bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, barrier) == 0); 217bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); 2188564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 2198564292ac4b9adf51c45517cca2878732feb5bb4sewardj 220d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 221d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * Initialize a barrier with given client address, barrier type and number of 222d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * participants. The 'reinitialization' argument indicates whether a barrier 223d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * object is being initialized or reinitialized. 224d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * 225d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Called before pthread_barrier_init(). 22628230a3734e045791173aca660efc7d7aeef78cebart */ 227a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_init)(const Addr barrier, 228a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, const Word count, 229a8cf765964dc9b9436384469a0a30889b24d1997bart const Bool reinitialization) 2308564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 231bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 232bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 233bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 234bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 235bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (count == 0) 236bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 237d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; 238d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart VG_(maybe_record_error)(VG_(get_running_tid)(), 239d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart BarrierErr, 240d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart VG_(get_IP)(VG_(get_running_tid)()), 241bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "pthread_barrier_init: 'count' argument is zero", 242d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart &bei); 243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 244bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 245bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (! reinitialization && barrier_type == pthread_barrier) 246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 247bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 248bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p) 249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 250d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; 251bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 252bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 253bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 254bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Barrier reinitialization", 255bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 256bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 257bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 258d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart 259bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count); 260bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 261bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 262bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 263bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization) 264bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 265bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 26663c92ea799549976957f5b4d54ede744f762c56fbart "[%d] barrier_reinit %s 0x%lx count %ld -> %ld\n", 267bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 268bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier_get_typename(p), 269bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier, 270bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count, 271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart count); 272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 275bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 27663c92ea799549976957f5b4d54ede744f762c56fbart "[%d] barrier_init %s 0x%lx\n", 277bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 278bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier_get_typename(p), 279bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier); 280bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 281bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 282bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 283bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization && p->count != count) 284bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 285bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 286bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 287d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 288bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 289bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 290bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Reinitialization of barrier with active" 292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " waiters", 293bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 294bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count = count; 296bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 297bedfd237fbdc80d0c917cfcb85a94b5561c92633bart} 298bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 299bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */ 300bedfd237fbdc80d0c917cfcb85a94b5561c92633bartvoid DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type) 301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart{ 302bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 303bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 304bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 305bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 306bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 307bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 308306527d7413780873a05cf801c47f725fb60c310bart VG_(message)(Vg_UserMsg, 30963c92ea799549976957f5b4d54ede744f762c56fbart "[%d] barrier_destroy %s 0x%lx\n", 31062a784c9382fdf7184065ad76ae8d3b905605f21bart DRD_(thread_get_running_tid)(), 311d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart barrier_get_typename(p), 312306527d7413780873a05cf801c47f725fb60c310bart barrier); 313bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 314bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 315bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 316bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 31762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart GenericErrInfo GEI = { 31862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .tid = DRD_(thread_get_running_tid)(), 31962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .addr = barrier, 32062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 321bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 322bedfd237fbdc80d0c917cfcb85a94b5561c92633bart GenericErr, 323bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 324bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Not a barrier", 325bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &GEI); 326bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 327bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 328306527d7413780873a05cf801c47f725fb60c310bart 329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 330bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 331d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 332195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(maybe_record_error)(VG_(get_running_tid)(), 333195a3983ff6030cbe21fd4561006acdd3c31dbafbart BarrierErr, 334195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(get_IP)(VG_(get_running_tid)()), 335bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of a barrier with active waiters", 336195a3983ff6030cbe21fd4561006acdd3c31dbafbart &bei); 337bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 3388564292ac4b9adf51c45517cca2878732feb5bb4sewardj 339bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(clientobj_remove)(p->a1, ClientBarrier); 3408564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 3418564292ac4b9adf51c45517cca2878732feb5bb4sewardj 342d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */ 343a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier, 344a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type) 3458564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 346bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 347bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 348bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 349d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 350bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 351bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0 && barrier_type == gomp_barrier) 353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 355bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * gomp_barrier_wait() call has been intercepted but gomp_barrier_init() 356bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * not. The only cause I know of that can trigger this is that libgomp.so 357bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * has been compiled with --enable-linux-futex. 358bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 3591e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj VG_(message)(Vg_UserMsg, "\n"); 360bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 361bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Please verify whether gcc has been configured" 3621e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj " with option --disable-linux-futex.\n"); 363bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 3641e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj "See also the section about OpenMP in the DRD manual.\n"); 3651e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj VG_(message)(Vg_UserMsg, "\n"); 366bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 367bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 368bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 369bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 370bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 371bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 37263c92ea799549976957f5b4d54ede744f762c56fbart "[%d] barrier_pre_wait %s 0x%lx iteration %ld\n", 373bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 374bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier_get_typename(p), 375bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier, 376bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_iteration); 377bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 378bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 379d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart /* Clean up nodes associated with finished threads. */ 380d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart oset = p->oset[p->pre_iteration]; 381d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(oset); 382d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 383d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) { 384d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q->thread_finished) { 385d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart void* r = VG_(OSetGen_Remove)(oset, &q->tid); 386d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(r == q); 387d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(barrier_thread_destroy)(q); 388d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_FreeNode)(oset, q); 389d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIterAt)(oset, &word_tid); 390d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 391d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 392bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Allocate the per-thread data structure if necessary. */ 393d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(oset, &word_tid); 394d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q == NULL) { 395d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); 396cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart DRD_(barrier_thread_initialize)(q, tid); 397d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Insert)(oset, q); 398d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q); 399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 400bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 401bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Record *_barrier_wait() call context. */ 402bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); 403bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 404bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 405bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Store a pointer to the latest segment of the current thread in the 406bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * per-thread data structure. 407bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 408d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(thread_get_latest_segment)(&q->sg, tid); 409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 411bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 412bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and 413bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->pre_waiters_left counter. 414bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->pre_waiters_left <= 0) 416bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 417bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_iteration = 1 - p->pre_iteration; 418bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_waiters_left = p->count; 419bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4208564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 4218564292ac4b9adf51c45517cca2878732feb5bb4sewardj 422d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */ 423a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier, 424d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const BarrierT barrier_type, const Bool waited, 425d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const Bool serializing) 4268564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 427bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 430bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* r; 431d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 432bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 433bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 434bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 435bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 436bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 437bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 43863c92ea799549976957f5b4d54ede744f762c56fbart "[%d] barrier_post_wait %s 0x%lx iteration %ld%s\n", 439bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tid, 440bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p ? barrier_get_typename(p) : "(?)", 441bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier, 442bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p ? p->post_iteration : -1, 443bedfd237fbdc80d0c917cfcb85a94b5561c92633bart serializing ? " (serializing)" : ""); 444bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 445bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 446bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 447bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If p == 0, this means that the barrier has been destroyed after 448bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * *_barrier_wait() returned and before this function was called. Just 449bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * return in that case -- race conditions between *_barrier_wait() 450bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper. 451bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 452bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 453bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 454bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 455bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* If the *_barrier_wait() call returned an error code, exit. */ 456bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (! waited) 457bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 458bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 459d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart oset = p->oset[p->post_iteration]; 460d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(oset, &word_tid); 461bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (q == 0) 462bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 463d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 464bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 465bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 466bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 467bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Error in barrier implementation" 468bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " -- barrier_wait() started before" 469bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy() and finished after" 470bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy()", 471bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 472bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 473d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); 474cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart DRD_(barrier_thread_initialize)(q, tid); 475d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Insert)(oset, q); 476d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q); 477bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4787627be3e26162e4f59ccfd35eaf31495ddefdf9bbart 4797627be3e26162e4f59ccfd35eaf31495ddefdf9bbart /* Create a new segment and store a pointer to that segment. */ 4807627be3e26162e4f59ccfd35eaf31495ddefdf9bbart DRD_(thread_new_segment)(tid); 4817627be3e26162e4f59ccfd35eaf31495ddefdf9bbart DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid); 4827627be3e26162e4f59ccfd35eaf31495ddefdf9bbart s_barrier_segment_creation_count++; 4837627be3e26162e4f59ccfd35eaf31495ddefdf9bbart 484bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 485bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Combine all vector clocks that were stored in the pre_barrier_wait 486bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * wrapper with the vector clock of the current thread. 487bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 488bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 4898f822af9b234e7c553c408eba65a641c4773457fbart VectorClock old_vc; 4908f822af9b234e7c553c408eba65a641c4773457fbart 4918f822af9b234e7c553c408eba65a641c4773457fbart DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc); 492d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 493d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (r = VG_(OSetGen_Next)(oset)) != 0; ) 494bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 4958f822af9b234e7c553c408eba65a641c4773457fbart if (r != q) 4968f822af9b234e7c553c408eba65a641c4773457fbart { 497d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(r->sg); 4988f822af9b234e7c553c408eba65a641c4773457fbart DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, 499d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart &r->sg->vc); 5008f822af9b234e7c553c408eba65a641c4773457fbart } 501bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5028f822af9b234e7c553c408eba65a641c4773457fbart DRD_(thread_update_conflict_set)(tid, &old_vc); 5038f822af9b234e7c553c408eba65a641c4773457fbart DRD_(vc_cleanup)(&old_vc); 504bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 505bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 506bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 507bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 508bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the post *_barrier_wait() wrapper, toggle p->post_iteration and 509bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->post_waiters_left counter. 510bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 511bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->post_waiters_left <= 0) 512bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 513bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_iteration = 1 - p->post_iteration; 514bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_waiters_left = p->count; 515bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 516d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart} 517bebc5d668dc5a6df337011181debbf8d91c338e0bart 518d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called when thread tid stops to exist. */ 519d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p, 520d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const DrdThreadId tid) 521d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart{ 522bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 523bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 524d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart int i; 525bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 526d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for (i = 0; i < 2; i++) { 527d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(p->oset[i], &word_tid); 528d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q) 529d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q->thread_finished = True; 530bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5318564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 5328564292ac4b9adf51c45517cca2878732feb5bb4sewardj 533d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 534d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Report that *_barrier_destroy() has been called but that this call was 535d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * not synchronized with the last *_barrier_wait() call on the same barrier. 536776a91e8fe04875abc38c1e7d0bc30175d285975bart * 537776a91e8fe04875abc38c1e7d0bc30175d285975bart * This topic has been discussed extensively on comp.programming.threads 538776a91e8fe04875abc38c1e7d0bc30175d285975bart * (February 3, 2009). See also 539776a91e8fe04875abc38c1e7d0bc30175d285975bart * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>. 540d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 541d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic 542d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p, 543d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const struct barrier_thread_info* const q) 5448564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 545bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 546bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(q); 547bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 548bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 549bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErrInfo bei 550d45d99553c15a361bb797d21ec6afb9bad22d2d4bart = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt }; 551bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 552bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 553bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 554bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of barrier not synchronized with" 555bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier wait call", 556bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 557bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5588564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 559306527d7413780873a05cf801c47f725fb60c310bart 560d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p) 561306527d7413780873a05cf801c47f725fb60c310bart{ 562bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 563306527d7413780873a05cf801c47f725fb60c310bart 564bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return barrier_type_name(p->barrier_type); 565306527d7413780873a05cf801c47f725fb60c310bart} 566306527d7413780873a05cf801c47f725fb60c310bart 567d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt) 568306527d7413780873a05cf801c47f725fb60c310bart{ 569bedfd237fbdc80d0c917cfcb85a94b5561c92633bart switch (bt) 570bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 571bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case pthread_barrier: 572bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "pthread barrier"; 573bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case gomp_barrier: 574bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "gomp barrier"; 575bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 576bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "?"; 577306527d7413780873a05cf801c47f725fb60c310bart} 5786bbefaf8418f3e225c4eefcc726b6874bef15d8cbart 579a8cf765964dc9b9436384469a0a30889b24d1997bartULong DRD_(get_barrier_segment_creation_count)(void) 5806bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{ 581bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return s_barrier_segment_creation_count; 5826bbefaf8418f3e225c4eefcc726b6874bef15d8cbart} 583