drd_barrier.c revision 74b2d97cbe4fb11f3fc7e489e1812ec1f3228339
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 { 167d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart oset = p->oset[1 - (p->pre_iteration & 1)]; 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 261b92ff0fd192dd05700f7d20db00795965e20b5c5bart if (s_trace_barrier) { 262bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization) 263b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(trace_msg)("[%d] barrier_reinit %s 0x%lx count %ld -> %ld\n", 264b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 265b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), barrier, p->count, count); 266bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 267b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(trace_msg)("[%d] barrier_init %s 0x%lx\n", 268b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 269b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), 270b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier); 271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization && p->count != count) 274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 275bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 276bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 277d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 278bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 279bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 280bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 281bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Reinitialization of barrier with active" 282bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " waiters", 283bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 284bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 285bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count = count; 286bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 287bedfd237fbdc80d0c917cfcb85a94b5561c92633bart} 288bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 289bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */ 290bedfd237fbdc80d0c917cfcb85a94b5561c92633bartvoid DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type) 291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart{ 292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 293bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 294bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 296bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 297b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(trace_msg)("[%d] barrier_destroy %s 0x%lx\n", 298b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 299b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), barrier); 300bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 302bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 30362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart GenericErrInfo GEI = { 30462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .tid = DRD_(thread_get_running_tid)(), 30562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .addr = barrier, 30662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 307bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 308bedfd237fbdc80d0c917cfcb85a94b5561c92633bart GenericErr, 309bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 310bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Not a barrier", 311bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &GEI); 312bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 313bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 314306527d7413780873a05cf801c47f725fb60c310bart 315bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 316bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 317d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 318195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(maybe_record_error)(VG_(get_running_tid)(), 319195a3983ff6030cbe21fd4561006acdd3c31dbafbart BarrierErr, 320195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(get_IP)(VG_(get_running_tid)()), 321bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of a barrier with active waiters", 322195a3983ff6030cbe21fd4561006acdd3c31dbafbart &bei); 323bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 3248564292ac4b9adf51c45517cca2878732feb5bb4sewardj 325bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(clientobj_remove)(p->a1, ClientBarrier); 3268564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 3278564292ac4b9adf51c45517cca2878732feb5bb4sewardj 328d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */ 329a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier, 330a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type) 3318564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 332bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 333bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 334bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 335d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 336bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 337bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 33874b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart if (p == 0 && barrier_type == gomp_barrier) { 339bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 340bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * gomp_barrier_wait() call has been intercepted but gomp_barrier_init() 341bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * not. The only cause I know of that can trigger this is that libgomp.so 342bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * has been compiled with --enable-linux-futex. 343bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 34474b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), 0, 0, 0 }; 34574b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart VG_(maybe_record_error)(VG_(get_running_tid)(), 34674b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart BarrierErr, 34774b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart VG_(get_IP)(VG_(get_running_tid)()), 34874b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart "Please verify whether gcc has been configured" 34974b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart " with option --disable-linux-futex. See also" 35074b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart " the section about OpenMP in the DRD manual.", 35174b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart &bei); 352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 355bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 356b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(trace_msg)("[%d] barrier_pre_wait %s 0x%lx iteration %ld\n", 357b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 358b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier_get_typename(p), barrier, p->pre_iteration); 359bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 360d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart /* Clean up nodes associated with finished threads. */ 361d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart oset = p->oset[p->pre_iteration & 1]; 362d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(oset); 363d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 364d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) { 365d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q->thread_finished) { 366d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart void* r = VG_(OSetGen_Remove)(oset, &q->tid); 367d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(r == q); 368d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(barrier_thread_destroy)(q); 369d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_FreeNode)(oset, q); 370d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIterAt)(oset, &word_tid); 371d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 372d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart } 373bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Allocate the per-thread data structure if necessary. */ 374d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(oset, &word_tid); 375d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q == NULL) { 376d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); 377cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart DRD_(barrier_thread_initialize)(q, tid); 378d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Insert)(oset, q); 379d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q); 380bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 381bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 382bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Record *_barrier_wait() call context. */ 383bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); 384bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 385bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 386bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Store a pointer to the latest segment of the current thread in the 387bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * per-thread data structure. 388bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 389d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart DRD_(thread_get_latest_segment)(&q->sg, tid); 390bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 391bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 392bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 393bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and 394bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->pre_waiters_left counter. 395bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 396bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->pre_waiters_left <= 0) 397bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 398d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart p->pre_iteration++; 399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_waiters_left = p->count; 400bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4018564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 4028564292ac4b9adf51c45517cca2878732feb5bb4sewardj 403d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */ 404a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier, 405d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const BarrierT barrier_type, const Bool waited, 406d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const Bool serializing) 4078564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 408bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 411bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* r; 412d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart OSet* oset; 413bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 414bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 416bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 417b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(trace_msg)("[%d] barrier_post_wait %s 0x%lx iteration %ld%s\n", 418b92ff0fd192dd05700f7d20db00795965e20b5c5bart tid, p ? barrier_get_typename(p) : "(?)", 419b92ff0fd192dd05700f7d20db00795965e20b5c5bart barrier, p ? p->post_iteration : -1, 420b92ff0fd192dd05700f7d20db00795965e20b5c5bart serializing ? " (serializing)" : ""); 421bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 422bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 423bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If p == 0, this means that the barrier has been destroyed after 424bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * *_barrier_wait() returned and before this function was called. Just 425bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * return in that case -- race conditions between *_barrier_wait() 426bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper. 427bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 430bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 431bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* If the *_barrier_wait() call returned an error code, exit. */ 432bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (! waited) 433bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 434bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 435d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart oset = p->oset[p->post_iteration & 1]; 436d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(oset, &word_tid); 437d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart if (p->pre_iteration - p->post_iteration > 1) { 438d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 439d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart VG_(maybe_record_error)(VG_(get_running_tid)(), 440d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart BarrierErr, 441d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart VG_(get_IP)(VG_(get_running_tid)()), 442d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart "Number of concurrent pthread_barrier_wait()" 443d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart " calls exceeds the barrier count", 444d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart &bei); 445d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart } else if (q == NULL) { 446d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 447bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 448bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 449bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 450bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Error in barrier implementation" 451bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " -- barrier_wait() started before" 452bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy() and finished after" 453bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy()", 454bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 455d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart } 456d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart if (q == NULL) { 457d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); 458cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart DRD_(barrier_thread_initialize)(q, tid); 459d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_Insert)(oset, q); 460d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q); 461d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart DRD_(thread_get_latest_segment)(&q->sg, tid); 462bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4637627be3e26162e4f59ccfd35eaf31495ddefdf9bbart 4647627be3e26162e4f59ccfd35eaf31495ddefdf9bbart /* Create a new segment and store a pointer to that segment. */ 4657627be3e26162e4f59ccfd35eaf31495ddefdf9bbart DRD_(thread_new_segment)(tid); 4667627be3e26162e4f59ccfd35eaf31495ddefdf9bbart DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid); 4677627be3e26162e4f59ccfd35eaf31495ddefdf9bbart s_barrier_segment_creation_count++; 4687627be3e26162e4f59ccfd35eaf31495ddefdf9bbart 469bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 470bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Combine all vector clocks that were stored in the pre_barrier_wait 471bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * wrapper with the vector clock of the current thread. 472bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 473bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 4748f822af9b234e7c553c408eba65a641c4773457fbart VectorClock old_vc; 4758f822af9b234e7c553c408eba65a641c4773457fbart 4768f822af9b234e7c553c408eba65a641c4773457fbart DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc); 477d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart VG_(OSetGen_ResetIter)(oset); 478d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for ( ; (r = VG_(OSetGen_Next)(oset)) != 0; ) 479bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 4808f822af9b234e7c553c408eba65a641c4773457fbart if (r != q) 4818f822af9b234e7c553c408eba65a641c4773457fbart { 482d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart tl_assert(r->sg); 4838f822af9b234e7c553c408eba65a641c4773457fbart DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, 484d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart &r->sg->vc); 4858f822af9b234e7c553c408eba65a641c4773457fbart } 486bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4878f822af9b234e7c553c408eba65a641c4773457fbart DRD_(thread_update_conflict_set)(tid, &old_vc); 4888f822af9b234e7c553c408eba65a641c4773457fbart DRD_(vc_cleanup)(&old_vc); 489bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 490bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 491bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 492bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 493bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the post *_barrier_wait() wrapper, toggle p->post_iteration and 494bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->post_waiters_left counter. 495bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 496bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->post_waiters_left <= 0) 497bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 498d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart p->post_iteration++; 499bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_waiters_left = p->count; 500bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 501d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart} 502bebc5d668dc5a6df337011181debbf8d91c338e0bart 503d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called when thread tid stops to exist. */ 504d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p, 505d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const DrdThreadId tid) 506d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart{ 507bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 508bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 509d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart int i; 510bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 511d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart for (i = 0; i < 2; i++) { 512d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q = VG_(OSetGen_Lookup)(p->oset[i], &word_tid); 513d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart if (q) 514d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart q->thread_finished = True; 515bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5168564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 5178564292ac4b9adf51c45517cca2878732feb5bb4sewardj 518d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 519d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Report that *_barrier_destroy() has been called but that this call was 520d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * not synchronized with the last *_barrier_wait() call on the same barrier. 521776a91e8fe04875abc38c1e7d0bc30175d285975bart * 522776a91e8fe04875abc38c1e7d0bc30175d285975bart * This topic has been discussed extensively on comp.programming.threads 523776a91e8fe04875abc38c1e7d0bc30175d285975bart * (February 3, 2009). See also 524776a91e8fe04875abc38c1e7d0bc30175d285975bart * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>. 525d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 526d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic 527d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p, 528d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const struct barrier_thread_info* const q) 5298564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 530bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 531bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(q); 532bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 533bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 534bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErrInfo bei 535d45d99553c15a361bb797d21ec6afb9bad22d2d4bart = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt }; 536bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 537bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 538bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 539bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of barrier not synchronized with" 540bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier wait call", 541bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 542bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5438564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 544306527d7413780873a05cf801c47f725fb60c310bart 545d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p) 546306527d7413780873a05cf801c47f725fb60c310bart{ 547bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 548306527d7413780873a05cf801c47f725fb60c310bart 549bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return barrier_type_name(p->barrier_type); 550306527d7413780873a05cf801c47f725fb60c310bart} 551306527d7413780873a05cf801c47f725fb60c310bart 552d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt) 553306527d7413780873a05cf801c47f725fb60c310bart{ 554bedfd237fbdc80d0c917cfcb85a94b5561c92633bart switch (bt) 555bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 556bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case pthread_barrier: 557bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "pthread barrier"; 558bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case gomp_barrier: 559bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "gomp barrier"; 560bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 561bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "?"; 562306527d7413780873a05cf801c47f725fb60c310bart} 5636bbefaf8418f3e225c4eefcc726b6874bef15d8cbart 564a8cf765964dc9b9436384469a0a30889b24d1997bartULong DRD_(get_barrier_segment_creation_count)(void) 5656bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{ 566bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return s_barrier_segment_creation_count; 5676bbefaf8418f3e225c4eefcc726b6874bef15d8cbart} 568