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