drd_barrier.c revision d45d99553c15a361bb797d21ec6afb9bad22d2d4
1bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/* -*- mode: C; c-basic-offset: 3; -*- */ 28564292ac4b9adf51c45517cca2878732feb5bb4sewardj/* 386562bd89ac23ce795d19c71fabcb9d1c8f956d3bart This file is part of drd, a thread error detector. 48564292ac4b9adf51c45517cca2878732feb5bb4sewardj 586562bd89ac23ce795d19c71fabcb9d1c8f956d3bart Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>. 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 45bedfd237fbdc80d0c917cfcb85a94b5561c92633bart // this member variable is the key of an OSet. 46bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Word iteration; // iteration of last pthread_barrier_wait() 47bedfd237fbdc80d0c917cfcb85a94b5561c92633bart // call thread tid participated in. 48bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* sg[2]; // Segments of the last two 49bedfd237fbdc80d0c917cfcb85a94b5561c92633bart // pthread_barrier() calls by thread tid. 50bedfd237fbdc80d0c917cfcb85a94b5561c92633bart ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call. 51bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* post_wait_sg; // Segment created after *_barrier_wait() finished 528564292ac4b9adf51c45517cca2878732feb5bb4sewardj}; 538564292ac4b9adf51c45517cca2878732feb5bb4sewardj 548564292ac4b9adf51c45517cca2878732feb5bb4sewardj 55a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local functions. */ 5628230a3734e045791173aca660efc7d7aeef78cebart 57d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_cleanup(struct barrier_info* p); 58d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p, 59d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const DrdThreadId tid); 60d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p); 61d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt); 62d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic 63d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p, 64bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const struct barrier_thread_info* const q); 6528230a3734e045791173aca660efc7d7aeef78cebart 6628230a3734e045791173aca660efc7d7aeef78cebart 67a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local variables. */ 688564292ac4b9adf51c45517cca2878732feb5bb4sewardj 69d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic Bool s_trace_barrier = False; 70d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic ULong s_barrier_segment_creation_count; 718564292ac4b9adf51c45517cca2878732feb5bb4sewardj 728564292ac4b9adf51c45517cca2878732feb5bb4sewardj 73a8cf765964dc9b9436384469a0a30889b24d1997bart/* Function definitions. */ 748564292ac4b9adf51c45517cca2878732feb5bb4sewardj 75a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_set_trace)(const Bool trace_barrier) 768564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 77bedfd237fbdc80d0c917cfcb85a94b5561c92633bart s_trace_barrier = trace_barrier; 788564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 798564292ac4b9adf51c45517cca2878732feb5bb4sewardj 80d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 81d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified thread ID and iteration 82d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * information. 83d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 84a8cf765964dc9b9436384469a0a30889b24d1997bartstatic 85a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p, 86a8cf765964dc9b9436384469a0a30889b24d1997bart const DrdThreadId tid, 87a8cf765964dc9b9436384469a0a30889b24d1997bart const Word iteration) 888564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 89bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->tid = tid; 90bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->iteration = iteration; 91bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->sg[0] = 0; 92bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->sg[1] = 0; 93bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->wait_call_ctxt = 0; 94bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_wait_sg = 0; 958564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 968564292ac4b9adf51c45517cca2878732feb5bb4sewardj 97d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 98d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Deallocate the memory that is owned by members of 99d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * struct barrier_thread_info. 100d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 101a8cf765964dc9b9436384469a0a30889b24d1997bartstatic void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p) 1028564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 103bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 104bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(p->sg[0]); 105bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(p->sg[1]); 106bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(p->post_wait_sg); 1078564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1088564292ac4b9adf51c45517cca2878732feb5bb4sewardj 109d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 110d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified client-side barrier address, 111d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * barrier object size and number of participants in each barrier. 112d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 1138564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 114a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_initialize)(struct barrier_info* const p, 115a8cf765964dc9b9436384469a0a30889b24d1997bart const Addr barrier, 116a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, 117a8cf765964dc9b9436384469a0a30889b24d1997bart const Word count) 1188564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 119bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier != 0); 120bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 121bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p->a1 == barrier); 122bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 123bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup; 124bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->delete_thread 125bedfd237fbdc80d0c917cfcb85a94b5561c92633bart = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread; 126bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->barrier_type = barrier_type; 127bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count = count; 128bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_iteration = 0; 129bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_iteration = 0; 130bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_waiters_left = count; 131bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_waiters_left = count; 132bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 133bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word)); 134bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) 135bedfd237fbdc80d0c917cfcb85a94b5561c92633bart >= sizeof(DrdThreadId)); 136bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1", 137bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(free)); 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; 150bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 151bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 152bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 153bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count) 154bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 155d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 156bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 157bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 158bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 159bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of barrier that is being waited" 160bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " upon", 161bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 162bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 163bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 164bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)()); 165bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(latest_sg); 166bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 167bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(OSetGen_ResetIter)(p->oset); 168bedfd237fbdc80d0c917cfcb85a94b5561c92633bart for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; ) 169bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 170bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (q->post_wait_sg 171bedfd237fbdc80d0c917cfcb85a94b5561c92633bart && ! DRD_(vc_lte)(&q->post_wait_sg->vc, &latest_sg->vc)) 172bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 173bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier_report_wait_delete_race(p, q); 174bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 175bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 176bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(barrier_thread_destroy)(q); 177bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 178bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(OSetGen_Destroy)(p->oset); 179bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 180bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(latest_sg); 1818564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1828564292ac4b9adf51c45517cca2878732feb5bb4sewardj 183d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 184d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Look up the client-side barrier address barrier in s_barrier[]. If not 185d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * found, add it. 186d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 1878564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 1888564292ac4b9adf51c45517cca2878732feb5bb4sewardjstruct barrier_info* 189a8cf765964dc9b9436384469a0a30889b24d1997bartDRD_(barrier_get_or_allocate)(const Addr barrier, 190a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, const Word count) 1918564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 192bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info *p; 193bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 194bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 195bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, barrier) == 0); 197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); 198bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 199bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 200bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_add)(barrier, ClientBarrier)->barrier); 201bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(barrier_initialize)(p, barrier, barrier_type, count); 202bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 203bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return p; 20428230a3734e045791173aca660efc7d7aeef78cebart} 20528230a3734e045791173aca660efc7d7aeef78cebart 206d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 207d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Look up the address of the information associated with the client-side 208d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * barrier object. 209d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 210a8cf765964dc9b9436384469a0a30889b24d1997bartstatic struct barrier_info* DRD_(barrier_get)(const Addr barrier) 21128230a3734e045791173aca660efc7d7aeef78cebart{ 212bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, barrier) == 0); 213bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier); 2148564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 2158564292ac4b9adf51c45517cca2878732feb5bb4sewardj 216d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 217d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize a barrier with client address barrier, client size size, and 218d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * where count threads participate in each barrier. 219d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * 220d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Called before pthread_barrier_init(). 22128230a3734e045791173aca660efc7d7aeef78cebart */ 222a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_init)(const Addr barrier, 223a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type, const Word count, 224a8cf765964dc9b9436384469a0a30889b24d1997bart const Bool reinitialization) 2258564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 226bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 227bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 228bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); 229bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 230bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (count == 0) 231bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 232d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; 233d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart VG_(maybe_record_error)(VG_(get_running_tid)(), 234d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart BarrierErr, 235d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart VG_(get_IP)(VG_(get_running_tid)()), 236bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "pthread_barrier_init: 'count' argument is zero", 237d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart &bei); 238bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 239bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 240bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (! reinitialization && barrier_type == pthread_barrier) 241bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 242bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p) 244bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 245d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; 246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 247bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 248bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Barrier reinitialization", 250bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 251bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 252bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 253bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count); 254bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 255bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 256bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 257bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization) 258bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 259bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 260bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "[%d/%d] barrier_reinit %s 0x%lx count %ld -> %ld", 261bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_running_tid)(), 262bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 263bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier_get_typename(p), 264bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier, 265bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count, 266bedfd237fbdc80d0c917cfcb85a94b5561c92633bart count); 267bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 268bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 269bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 270bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "[%d/%d] barrier_init %s 0x%lx", 272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_running_tid)(), 273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier_get_typename(p), 275bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier); 276bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 277bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 278bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 279bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (reinitialization && p->count != count) 280bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 281bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 282bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 283d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 284bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 285bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 286bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 287bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Reinitialization of barrier with active" 288bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " waiters", 289bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 290bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->count = count; 292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 293bedfd237fbdc80d0c917cfcb85a94b5561c92633bart} 294bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */ 296bedfd237fbdc80d0c917cfcb85a94b5561c92633bartvoid DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type) 297bedfd237fbdc80d0c917cfcb85a94b5561c92633bart{ 298bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 299bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 300bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 302bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 303bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 304306527d7413780873a05cf801c47f725fb60c310bart VG_(message)(Vg_UserMsg, 305bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "[%d/%d] barrier_destroy %s 0x%lx", 306306527d7413780873a05cf801c47f725fb60c310bart VG_(get_running_tid)(), 30762a784c9382fdf7184065ad76ae8d3b905605f21bart DRD_(thread_get_running_tid)(), 308d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart barrier_get_typename(p), 309306527d7413780873a05cf801c47f725fb60c310bart barrier); 310bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 311bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 312bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 313bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 314d45d99553c15a361bb797d21ec6afb9bad22d2d4bart GenericErrInfo GEI = { DRD_(thread_get_running_tid)() }; 315bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 316bedfd237fbdc80d0c917cfcb85a94b5561c92633bart GenericErr, 317bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 318bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Not a barrier", 319bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &GEI); 320bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 321bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 322306527d7413780873a05cf801c47f725fb60c310bart 323bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) 324bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 325d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 326195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(maybe_record_error)(VG_(get_running_tid)(), 327195a3983ff6030cbe21fd4561006acdd3c31dbafbart BarrierErr, 328195a3983ff6030cbe21fd4561006acdd3c31dbafbart VG_(get_IP)(VG_(get_running_tid)()), 329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of a barrier with active waiters", 330195a3983ff6030cbe21fd4561006acdd3c31dbafbart &bei); 331bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 3328564292ac4b9adf51c45517cca2878732feb5bb4sewardj 333bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(clientobj_remove)(p->a1, ClientBarrier); 3348564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 3358564292ac4b9adf51c45517cca2878732feb5bb4sewardj 336d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */ 337a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier, 338a8cf765964dc9b9436384469a0a30889b24d1997bart const BarrierT barrier_type) 3398564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 340bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 341bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 342bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 343bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 344bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 345bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0 && barrier_type == gomp_barrier) 346bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 347bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 348bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * gomp_barrier_wait() call has been intercepted but gomp_barrier_init() 349bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * not. The only cause I know of that can trigger this is that libgomp.so 350bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * has been compiled with --enable-linux-futex. 351bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, ""); 353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Please verify whether gcc has been configured" 355bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " with option --disable-linux-futex."); 356bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 357bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "See also the section about OpenMP in the DRD manual."); 358bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, ""); 359bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 360bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 361bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 362bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 363bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 364bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 365bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "[%d/%d] barrier_pre_wait %s 0x%lx iteration %ld", 366bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_running_tid)(), 367bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 368bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier_get_typename(p), 369bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier, 370bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_iteration); 371bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 372bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 373bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Allocate the per-thread data structure if necessary. */ 374bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = VG_(OSetGen_Lookup)(p->oset, &word_tid); 375bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (q == 0) 376bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 377bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q)); 378bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration); 379bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(OSetGen_Insert)(p->oset, q); 380bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); 381bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 382bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 383bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Record *_barrier_wait() call context. */ 384bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); 385bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 386bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 387bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Store a pointer to the latest segment of the current thread in the 388bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * per-thread data structure. 389bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 390bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_latest_segment)(&q->sg[p->pre_iteration], tid); 391bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 392bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 393bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 394bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and 395bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->pre_waiters_left counter. 396bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 397bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->pre_waiters_left <= 0) 398bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_iteration = 1 - p->pre_iteration; 400bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->pre_waiters_left = p->count; 401bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4028564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 4038564292ac4b9adf51c45517cca2878732feb5bb4sewardj 404d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */ 405a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier, 406d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const BarrierT barrier_type, const Bool waited, 407d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const Bool serializing) 4088564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_info* p; 410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 411bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 412bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* r; 413bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 414bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(barrier_get)(barrier); 415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 416bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_barrier) 417bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 418bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 419bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld%s", 420bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_running_tid)(), 421bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tid, 422bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p ? barrier_get_typename(p) : "(?)", 423bedfd237fbdc80d0c917cfcb85a94b5561c92633bart barrier, 424bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p ? p->post_iteration : -1, 425bedfd237fbdc80d0c917cfcb85a94b5561c92633bart serializing ? " (serializing)" : ""); 426bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 427bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If p == 0, this means that the barrier has been destroyed after 430bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * *_barrier_wait() returned and before this function was called. Just 431bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * return in that case -- race conditions between *_barrier_wait() 432bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper. 433bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 434bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 435bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 436bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 437bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* If the *_barrier_wait() call returned an error code, exit. */ 438bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (! waited) 439bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 440bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 441bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = VG_(OSetGen_Lookup)(p->oset, &word_tid); 442bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (q == 0) 443bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 444d45d99553c15a361bb797d21ec6afb9bad22d2d4bart BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; 445bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 446bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 447bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 448bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Error in barrier implementation" 449bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " -- barrier_wait() started before" 450bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy() and finished after" 451bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier_destroy()", 452bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 453bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 454bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q)); 455bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration); 456bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(OSetGen_Insert)(p->oset, q); 457bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); 458bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 459bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 460bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * Combine all vector clocks that were stored in the pre_barrier_wait 461bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * wrapper with the vector clock of the current thread. 462bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 463bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(OSetGen_ResetIter)(p->oset); 464bedfd237fbdc80d0c917cfcb85a94b5561c92633bart for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; ) 465bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 466bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (r != q) 467bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 468bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(r->sg[p->post_iteration]); 469bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc); 470bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 471bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 472bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 473bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Create a new segment and store a pointer to that segment. */ 474bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_new_segment)(tid); 475bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid); 476bedfd237fbdc80d0c917cfcb85a94b5561c92633bart s_barrier_segment_creation_count++; 477bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 478bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 479bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * If the same number of threads as the barrier count indicates have 480bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * called the post *_barrier_wait() wrapper, toggle p->post_iteration and 481bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * reset the p->post_waiters_left counter. 482bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 483bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (--p->post_waiters_left <= 0) 484bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 485bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_iteration = 1 - p->post_iteration; 486bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->post_waiters_left = p->count; 487bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 488d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart} 489bebc5d668dc5a6df337011181debbf8d91c338e0bart 490d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called when thread tid stops to exist. */ 491d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p, 492d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const DrdThreadId tid) 493d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart{ 494bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct barrier_thread_info* q; 495bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const UWord word_tid = tid; 496bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 497bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = VG_(OSetGen_Remove)(p->oset, &word_tid); 498bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 499bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* 500bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * q is only non-zero if the barrier object has been used by thread tid 501bedfd237fbdc80d0c917cfcb85a94b5561c92633bart * after the barrier_init() call and before the thread finished. 502bedfd237fbdc80d0c917cfcb85a94b5561c92633bart */ 503bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (q) 504bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 505bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(barrier_thread_destroy)(q); 506bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(OSetGen_FreeNode)(p->oset, q); 507bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5088564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 5098564292ac4b9adf51c45517cca2878732feb5bb4sewardj 510d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** 511d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Report that *_barrier_destroy() has been called but that this call was 512d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * not synchronized with the last *_barrier_wait() call on the same barrier. 513776a91e8fe04875abc38c1e7d0bc30175d285975bart * 514776a91e8fe04875abc38c1e7d0bc30175d285975bart * This topic has been discussed extensively on comp.programming.threads 515776a91e8fe04875abc38c1e7d0bc30175d285975bart * (February 3, 2009). See also 516776a91e8fe04875abc38c1e7d0bc30175d285975bart * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>. 517d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */ 518d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic 519d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p, 520d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart const struct barrier_thread_info* const q) 5218564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 522bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 523bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(q); 524bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 525bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 526bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErrInfo bei 527d45d99553c15a361bb797d21ec6afb9bad22d2d4bart = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt }; 528bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 529bedfd237fbdc80d0c917cfcb85a94b5561c92633bart BarrierErr, 530bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 531bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of barrier not synchronized with" 532bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " barrier wait call", 533bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &bei); 534bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 5358564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 536306527d7413780873a05cf801c47f725fb60c310bart 537d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p) 538306527d7413780873a05cf801c47f725fb60c310bart{ 539bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 540306527d7413780873a05cf801c47f725fb60c310bart 541bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return barrier_type_name(p->barrier_type); 542306527d7413780873a05cf801c47f725fb60c310bart} 543306527d7413780873a05cf801c47f725fb60c310bart 544d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt) 545306527d7413780873a05cf801c47f725fb60c310bart{ 546bedfd237fbdc80d0c917cfcb85a94b5561c92633bart switch (bt) 547bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 548bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case pthread_barrier: 549bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "pthread barrier"; 550bedfd237fbdc80d0c917cfcb85a94b5561c92633bart case gomp_barrier: 551bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "gomp barrier"; 552bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 553bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return "?"; 554306527d7413780873a05cf801c47f725fb60c310bart} 5556bbefaf8418f3e225c4eefcc726b6874bef15d8cbart 556a8cf765964dc9b9436384469a0a30889b24d1997bartULong DRD_(get_barrier_segment_creation_count)(void) 5576bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{ 558bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return s_barrier_segment_creation_count; 5596bbefaf8418f3e225c4eefcc726b6874bef15d8cbart} 560