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