drd_barrier.c revision 74b2d97cbe4fb11f3fc7e489e1812ec1f3228339
1922304f9e9d5df1a20a1bb1d4736263c99272aa4bart/* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */
28564292ac4b9adf51c45517cca2878732feb5bb4sewardj/*
386562bd89ac23ce795d19c71fabcb9d1c8f956d3bart  This file is part of drd, a thread error detector.
48564292ac4b9adf51c45517cca2878732feb5bb4sewardj
5922304f9e9d5df1a20a1bb1d4736263c99272aa4bart  Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
68564292ac4b9adf51c45517cca2878732feb5bb4sewardj
78564292ac4b9adf51c45517cca2878732feb5bb4sewardj  This program is free software; you can redistribute it and/or
88564292ac4b9adf51c45517cca2878732feb5bb4sewardj  modify it under the terms of the GNU General Public License as
98564292ac4b9adf51c45517cca2878732feb5bb4sewardj  published by the Free Software Foundation; either version 2 of the
108564292ac4b9adf51c45517cca2878732feb5bb4sewardj  License, or (at your option) any later version.
118564292ac4b9adf51c45517cca2878732feb5bb4sewardj
128564292ac4b9adf51c45517cca2878732feb5bb4sewardj  This program is distributed in the hope that it will be useful, but
138564292ac4b9adf51c45517cca2878732feb5bb4sewardj  WITHOUT ANY WARRANTY; without even the implied warranty of
148564292ac4b9adf51c45517cca2878732feb5bb4sewardj  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
158564292ac4b9adf51c45517cca2878732feb5bb4sewardj  General Public License for more details.
168564292ac4b9adf51c45517cca2878732feb5bb4sewardj
178564292ac4b9adf51c45517cca2878732feb5bb4sewardj  You should have received a copy of the GNU General Public License
188564292ac4b9adf51c45517cca2878732feb5bb4sewardj  along with this program; if not, write to the Free Software
198564292ac4b9adf51c45517cca2878732feb5bb4sewardj  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
208564292ac4b9adf51c45517cca2878732feb5bb4sewardj  02111-1307, USA.
218564292ac4b9adf51c45517cca2878732feb5bb4sewardj
228564292ac4b9adf51c45517cca2878732feb5bb4sewardj  The GNU General Public License is contained in the file COPYING.
238564292ac4b9adf51c45517cca2878732feb5bb4sewardj*/
248564292ac4b9adf51c45517cca2878732feb5bb4sewardj
258564292ac4b9adf51c45517cca2878732feb5bb4sewardj
268564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_barrier.h"
2728230a3734e045791173aca660efc7d7aeef78cebart#include "drd_clientobj.h"
288564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_error.h"
298564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_suppression.h"
308564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_errormgr.h"    // VG_(maybe_record_error)()
318564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcassert.h"  // tl_assert()
328564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcprint.h"   // VG_(printf)()
338564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_machine.h"     // VG_(get_IP)()
348564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
358564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_oset.h"
368564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
378564292ac4b9adf51c45517cca2878732feb5bb4sewardj
388564292ac4b9adf51c45517cca2878732feb5bb4sewardj
39a8cf765964dc9b9436384469a0a30889b24d1997bart/* Type definitions. */
408564292ac4b9adf51c45517cca2878732feb5bb4sewardj
418ddef8828240404bfcbd38651a53aa38be044ab6bart/** Information associated with one thread participating in a barrier. */
42bebc5d668dc5a6df337011181debbf8d91c338e0bartstruct barrier_thread_info
43bebc5d668dc5a6df337011181debbf8d91c338e0bart{
44bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   UWord       tid;           // A DrdThreadId declared as UWord because
4562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart                              // this member variable is the key of an OSet.
46d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   Segment*    sg;            // Segment of the last pthread_barrier() call
47d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart                              // by thread tid.
48bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment*    post_wait_sg;  // Segment created after *_barrier_wait() finished
49d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call.
50d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   Bool       thread_finished;// Whether thread 'tid' has finished.
518564292ac4b9adf51c45517cca2878732feb5bb4sewardj};
528564292ac4b9adf51c45517cca2878732feb5bb4sewardj
538564292ac4b9adf51c45517cca2878732feb5bb4sewardj
54a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local functions. */
5528230a3734e045791173aca660efc7d7aeef78cebart
56d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_cleanup(struct barrier_info* p);
57d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p,
58d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                                  const DrdThreadId tid);
59d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p);
60d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt);
61d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic
62d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p,
63bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                     const struct barrier_thread_info* const q);
6428230a3734e045791173aca660efc7d7aeef78cebart
6528230a3734e045791173aca660efc7d7aeef78cebart
66a8cf765964dc9b9436384469a0a30889b24d1997bart/* Local variables. */
678564292ac4b9adf51c45517cca2878732feb5bb4sewardj
68d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic Bool  s_trace_barrier = False;
69d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic ULong s_barrier_segment_creation_count;
708564292ac4b9adf51c45517cca2878732feb5bb4sewardj
718564292ac4b9adf51c45517cca2878732feb5bb4sewardj
72a8cf765964dc9b9436384469a0a30889b24d1997bart/* Function definitions. */
738564292ac4b9adf51c45517cca2878732feb5bb4sewardj
74a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_set_trace)(const Bool trace_barrier)
758564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
76bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_trace_barrier = trace_barrier;
778564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
788564292ac4b9adf51c45517cca2878732feb5bb4sewardj
79d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
80d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified thread ID and iteration
81d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * information.
82d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */
83a8cf765964dc9b9436384469a0a30889b24d1997bartstatic
84a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p,
85cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart                                     const DrdThreadId tid)
868564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
87d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   p->tid             = tid;
88d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   p->sg              = NULL;
89d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   p->post_wait_sg    = 0;
90d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   p->wait_call_ctxt  = 0;
91d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   p->thread_finished = False;
928564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
938564292ac4b9adf51c45517cca2878732feb5bb4sewardj
94d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
95d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Deallocate the memory that is owned by members of
96d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * struct barrier_thread_info.
97d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */
98a8cf765964dc9b9436384469a0a30889b24d1997bartstatic void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p)
998564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
100bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
101d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   DRD_(sg_put)(p->sg);
102bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(sg_put)(p->post_wait_sg);
1038564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
1048564292ac4b9adf51c45517cca2878732feb5bb4sewardj
105d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
106d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Initialize the structure *p with the specified client-side barrier address,
107d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * barrier object size and number of participants in each barrier.
108d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */
1098564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic
110a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_initialize)(struct barrier_info* const p,
111a8cf765964dc9b9436384469a0a30889b24d1997bart                              const Addr barrier,
112a8cf765964dc9b9436384469a0a30889b24d1997bart                              const BarrierT barrier_type,
113a8cf765964dc9b9436384469a0a30889b24d1997bart                              const Word count)
1148564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
115d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   int i;
116d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart
117bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(barrier != 0);
118bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
119bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p->a1 == barrier);
120bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
121bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->cleanup           = (void(*)(DrdClientobj*))barrier_cleanup;
122bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->delete_thread
123bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread;
124bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->barrier_type      = barrier_type;
125bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->count             = count;
126bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->pre_iteration     = 0;
127bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->post_iteration    = 0;
128bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->pre_waiters_left  = count;
129bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p->post_waiters_left = count;
130bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
131bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word));
132bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(sizeof(((struct barrier_thread_info*)0)->tid)
133bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             >= sizeof(DrdThreadId));
134d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   for (i = 0; i < 2; i++) {
135d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      p->oset[i] = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1",
136d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart                                       VG_(free));
137d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   }
1388564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
1398564292ac4b9adf51c45517cca2878732feb5bb4sewardj
140195e41fe2b9e02e142a0461113bfa55c89d24c5ebart/**
141d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Deallocate the memory owned by the struct barrier_info object and also
142d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * all the nodes in the OSet p->oset.
143d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart *
144195e41fe2b9e02e142a0461113bfa55c89d24c5ebart * Called by clientobj_destroy().
14528230a3734e045791173aca660efc7d7aeef78cebart */
146d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_cleanup(struct barrier_info* p)
1478564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
148bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* q;
149bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* latest_sg = 0;
150d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   OSet* oset;
151d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   int i;
152bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
153bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
154bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
155d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)());
156d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   tl_assert(latest_sg);
157d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart
158d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   if (p->pre_waiters_left != p->count) {
159d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
160bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
161bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              BarrierErr,
162bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              VG_(get_IP)(VG_(get_running_tid)()),
163bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Destruction of barrier that is being waited"
164bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " upon",
165bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              &bei);
166d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   } else {
167d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart      oset = p->oset[1 - (p->pre_iteration & 1)];
168d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_ResetIter)(oset);
169d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) {
170d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         if (q->post_wait_sg && !DRD_(vc_lte)(&q->post_wait_sg->vc,
171d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart                                              &latest_sg->vc))
172d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         {
173d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart            barrier_report_wait_delete_race(p, q);
174d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         }
175d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         DRD_(barrier_thread_destroy)(q);
176bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
177d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   }
178bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
179d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   for (i = 0; i < 2; i++) {
180d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_Destroy)(p->oset[i]);
181d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      p->oset[i] = NULL;
182bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
183bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
184bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(sg_put)(latest_sg);
1858564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
1868564292ac4b9adf51c45517cca2878732feb5bb4sewardj
187d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
188d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Look up the client-side barrier address barrier in s_barrier[]. If not
189d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * found, add it.
190d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */
1918564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic
1928564292ac4b9adf51c45517cca2878732feb5bb4sewardjstruct barrier_info*
193a8cf765964dc9b9436384469a0a30889b24d1997bartDRD_(barrier_get_or_allocate)(const Addr barrier,
194a8cf765964dc9b9436384469a0a30889b24d1997bart                              const BarrierT barrier_type, const Word count)
1958564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info *p;
197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
198bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
199bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
200bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(offsetof(DrdClientobj, barrier) == 0);
201bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier);
202bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p == 0)
203bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
204bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p = &(DRD_(clientobj_add)(barrier, ClientBarrier)->barrier);
205bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(barrier_initialize)(p, barrier, barrier_type, count);
206bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
207bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return p;
20828230a3734e045791173aca660efc7d7aeef78cebart}
20928230a3734e045791173aca660efc7d7aeef78cebart
210d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
211d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * Look up the address of the struct barrier_info associated with the
212d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * client-side barrier object.
213d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */
214a8cf765964dc9b9436384469a0a30889b24d1997bartstatic struct barrier_info* DRD_(barrier_get)(const Addr barrier)
21528230a3734e045791173aca660efc7d7aeef78cebart{
216bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(offsetof(DrdClientobj, barrier) == 0);
217bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier);
2188564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
2198564292ac4b9adf51c45517cca2878732feb5bb4sewardj
220d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
221d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * Initialize a barrier with given client address, barrier type and number of
222d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * participants. The 'reinitialization' argument indicates whether a barrier
223d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart * object is being initialized or reinitialized.
224d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart *
225d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Called before pthread_barrier_init().
22628230a3734e045791173aca660efc7d7aeef78cebart */
227a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_init)(const Addr barrier,
228a8cf765964dc9b9436384469a0a30889b24d1997bart                        const BarrierT barrier_type, const Word count,
229a8cf765964dc9b9436384469a0a30889b24d1997bart                        const Bool reinitialization)
2308564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
231bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info* p;
232bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
233bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
234bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
235bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (count == 0)
236bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
237d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 };
238d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart      VG_(maybe_record_error)(VG_(get_running_tid)(),
239d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart                              BarrierErr,
240d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart                              VG_(get_IP)(VG_(get_running_tid)()),
241bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "pthread_barrier_init: 'count' argument is zero",
242d9e39ec61f09dc9b5b4e9948445b6bc97bac5dfcbart                              &bei);
243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
244bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
245bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (! reinitialization && barrier_type == pthread_barrier)
246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
247bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p = DRD_(barrier_get)(barrier);
248bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (p)
249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
250d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 };
251bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(maybe_record_error)(VG_(get_running_tid)(),
252bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 BarrierErr,
253bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 VG_(get_IP)(VG_(get_running_tid)()),
254bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 "Barrier reinitialization",
255bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 &bei);
256bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
257bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
258d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart
259bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count);
260bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
261b92ff0fd192dd05700f7d20db00795965e20b5c5bart   if (s_trace_barrier) {
262bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (reinitialization)
263b92ff0fd192dd05700f7d20db00795965e20b5c5bart         DRD_(trace_msg)("[%d] barrier_reinit    %s 0x%lx count %ld -> %ld\n",
264b92ff0fd192dd05700f7d20db00795965e20b5c5bart                         DRD_(thread_get_running_tid)(),
265b92ff0fd192dd05700f7d20db00795965e20b5c5bart                         barrier_get_typename(p), barrier, p->count, count);
266bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      else
267b92ff0fd192dd05700f7d20db00795965e20b5c5bart         DRD_(trace_msg)("[%d] barrier_init      %s 0x%lx\n",
268b92ff0fd192dd05700f7d20db00795965e20b5c5bart                         DRD_(thread_get_running_tid)(),
269b92ff0fd192dd05700f7d20db00795965e20b5c5bart                         barrier_get_typename(p),
270b92ff0fd192dd05700f7d20db00795965e20b5c5bart                         barrier);
271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (reinitialization && p->count != count)
274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
275bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
276bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
277d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
278bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(maybe_record_error)(VG_(get_running_tid)(),
279bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 BarrierErr,
280bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 VG_(get_IP)(VG_(get_running_tid)()),
281bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 "Reinitialization of barrier with active"
282bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 " waiters",
283bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 &bei);
284bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
285bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->count = count;
286bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
287bedfd237fbdc80d0c917cfcb85a94b5561c92633bart}
288bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
289bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */
290bedfd237fbdc80d0c917cfcb85a94b5561c92633bartvoid DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart{
292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info* p;
293bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
294bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = DRD_(barrier_get)(barrier);
295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
296bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_barrier)
297b92ff0fd192dd05700f7d20db00795965e20b5c5bart      DRD_(trace_msg)("[%d] barrier_destroy   %s 0x%lx\n",
298b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      DRD_(thread_get_running_tid)(),
299b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      barrier_get_typename(p), barrier);
300bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p == 0)
302bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
30362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart      GenericErrInfo GEI = {
30462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart	 .tid = DRD_(thread_get_running_tid)(),
30562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart	 .addr = barrier,
30662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart      };
307bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
308bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              GenericErr,
309bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              VG_(get_IP)(VG_(get_running_tid)()),
310bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Not a barrier",
311bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              &GEI);
312bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return;
313bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
314306527d7413780873a05cf801c47f725fb60c310bart
315bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
316bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
317d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
318195a3983ff6030cbe21fd4561006acdd3c31dbafbart      VG_(maybe_record_error)(VG_(get_running_tid)(),
319195a3983ff6030cbe21fd4561006acdd3c31dbafbart                              BarrierErr,
320195a3983ff6030cbe21fd4561006acdd3c31dbafbart                              VG_(get_IP)(VG_(get_running_tid)()),
321bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Destruction of a barrier with active waiters",
322195a3983ff6030cbe21fd4561006acdd3c31dbafbart                              &bei);
323bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
3248564292ac4b9adf51c45517cca2878732feb5bb4sewardj
325bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(clientobj_remove)(p->a1, ClientBarrier);
3268564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
3278564292ac4b9adf51c45517cca2878732feb5bb4sewardj
328d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */
329a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
330a8cf765964dc9b9436384469a0a30889b24d1997bart                            const BarrierT barrier_type)
3318564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
332bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info* p;
333bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* q;
334bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const UWord word_tid = tid;
335d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   OSet* oset;
336bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
337bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = DRD_(barrier_get)(barrier);
33874b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart   if (p == 0 && barrier_type == gomp_barrier) {
339bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      /*
340bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * gomp_barrier_wait() call has been intercepted but gomp_barrier_init()
341bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * not. The only cause I know of that can trigger this is that libgomp.so
342bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * has been compiled with --enable-linux-futex.
343bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       */
34474b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), 0, 0, 0 };
34574b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
34674b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart                              BarrierErr,
34774b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart                              VG_(get_IP)(VG_(get_running_tid)()),
34874b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart                              "Please verify whether gcc has been configured"
34974b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart                              " with option --disable-linux-futex. See also"
35074b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart                              " the section about OpenMP in the DRD manual.",
35174b2d97cbe4fb11f3fc7e489e1812ec1f3228339bart                              &bei);
352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
355bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_barrier)
356b92ff0fd192dd05700f7d20db00795965e20b5c5bart      DRD_(trace_msg)("[%d] barrier_pre_wait  %s 0x%lx iteration %ld\n",
357b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      DRD_(thread_get_running_tid)(),
358b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      barrier_get_typename(p), barrier, p->pre_iteration);
359bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
360d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   /* Clean up nodes associated with finished threads. */
361d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart   oset = p->oset[p->pre_iteration & 1];
362d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   tl_assert(oset);
363d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   VG_(OSetGen_ResetIter)(oset);
364d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) {
365d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      if (q->thread_finished) {
366d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         void* r = VG_(OSetGen_Remove)(oset, &q->tid);
367d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         tl_assert(r == q);
368d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         DRD_(barrier_thread_destroy)(q);
369d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         VG_(OSetGen_FreeNode)(oset, q);
370d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         VG_(OSetGen_ResetIterAt)(oset, &word_tid);
371d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      }
372d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   }
373bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /* Allocate the per-thread data structure if necessary. */
374d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   q = VG_(OSetGen_Lookup)(oset, &word_tid);
375d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   if (q == NULL) {
376d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      q = VG_(OSetGen_AllocNode)(oset, sizeof(*q));
377cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart      DRD_(barrier_thread_initialize)(q, tid);
378d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_Insert)(oset, q);
379d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q);
380bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
381bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
382bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /* Record *_barrier_wait() call context. */
383bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
384bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
385bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
386bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * Store a pointer to the latest segment of the current thread in the
387bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * per-thread data structure.
388bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
389d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   DRD_(thread_get_latest_segment)(&q->sg, tid);
390bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
391bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
392bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * If the same number of threads as the barrier count indicates have
393bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and
394bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * reset the p->pre_waiters_left counter.
395bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
396bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (--p->pre_waiters_left <= 0)
397bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
398d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart      p->pre_iteration++;
399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->pre_waiters_left = p->count;
400bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
4018564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
4028564292ac4b9adf51c45517cca2878732feb5bb4sewardj
403d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */
404a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
405d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                             const BarrierT barrier_type, const Bool waited,
406d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                             const Bool serializing)
4078564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
408bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info* p;
409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const UWord word_tid = tid;
410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* q;
411bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* r;
412d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   OSet* oset;
413bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
414bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = DRD_(barrier_get)(barrier);
415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
416bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_barrier)
417b92ff0fd192dd05700f7d20db00795965e20b5c5bart      DRD_(trace_msg)("[%d] barrier_post_wait %s 0x%lx iteration %ld%s\n",
418b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      tid, p ? barrier_get_typename(p) : "(?)",
419b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      barrier, p ? p->post_iteration : -1,
420b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      serializing ? " (serializing)" : "");
421bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
422bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
423bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * If p == 0, this means that the barrier has been destroyed after
424bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * *_barrier_wait() returned and before this function was called. Just
425bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * return in that case -- race conditions between *_barrier_wait()
426bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper.
427bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p == 0)
429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return;
430bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
431bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /* If the *_barrier_wait() call returned an error code, exit. */
432bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (! waited)
433bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return;
434bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
435d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart   oset = p->oset[p->post_iteration & 1];
436d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   q = VG_(OSetGen_Lookup)(oset, &word_tid);
437d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart   if (p->pre_iteration - p->post_iteration > 1) {
438d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
439d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
440d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart                              BarrierErr,
441d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart                              VG_(get_IP)(VG_(get_running_tid)()),
442d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart                              "Number of concurrent pthread_barrier_wait()"
443d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart                              " calls exceeds the barrier count",
444d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart                              &bei);
445d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart   } else if (q == NULL) {
446d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
447bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
448bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              BarrierErr,
449bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              VG_(get_IP)(VG_(get_running_tid)()),
450bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Error in barrier implementation"
451bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " -- barrier_wait() started before"
452bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " barrier_destroy() and finished after"
453bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " barrier_destroy()",
454bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              &bei);
455d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart   }
456d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart   if (q == NULL) {
457d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      q = VG_(OSetGen_AllocNode)(oset, sizeof(*q));
458cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart      DRD_(barrier_thread_initialize)(q, tid);
459d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_Insert)(oset, q);
460d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q);
461d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart      DRD_(thread_get_latest_segment)(&q->sg, tid);
462bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
4637627be3e26162e4f59ccfd35eaf31495ddefdf9bbart
4647627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   /* Create a new segment and store a pointer to that segment. */
4657627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   DRD_(thread_new_segment)(tid);
4667627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid);
4677627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   s_barrier_segment_creation_count++;
4687627be3e26162e4f59ccfd35eaf31495ddefdf9bbart
469bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
470bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * Combine all vector clocks that were stored in the pre_barrier_wait
471bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * wrapper with the vector clock of the current thread.
472bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
473bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
4748f822af9b234e7c553c408eba65a641c4773457fbart      VectorClock old_vc;
4758f822af9b234e7c553c408eba65a641c4773457fbart
4768f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
477d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_ResetIter)(oset);
478d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      for ( ; (r = VG_(OSetGen_Next)(oset)) != 0; )
479bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
4808f822af9b234e7c553c408eba65a641c4773457fbart         if (r != q)
4818f822af9b234e7c553c408eba65a641c4773457fbart         {
482d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart            tl_assert(r->sg);
4838f822af9b234e7c553c408eba65a641c4773457fbart            DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc,
484d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart                             &r->sg->vc);
4858f822af9b234e7c553c408eba65a641c4773457fbart         }
486bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
4878f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(thread_update_conflict_set)(tid, &old_vc);
4888f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(vc_cleanup)(&old_vc);
489bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
490bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
491bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
492bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * If the same number of threads as the barrier count indicates have
493bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * called the post *_barrier_wait() wrapper, toggle p->post_iteration and
494bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * reset the p->post_waiters_left counter.
495bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
496bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (--p->post_waiters_left <= 0)
497bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
498d378eaae99616b3d4d6c85d0e5839e5b9cd85dd3bart      p->post_iteration++;
499bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->post_waiters_left = p->count;
500bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
501d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart}
502bebc5d668dc5a6df337011181debbf8d91c338e0bart
503d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called when thread tid stops to exist. */
504d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p,
505d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                                  const DrdThreadId tid)
506d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart{
507bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* q;
508bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const UWord word_tid = tid;
509d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   int i;
510bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
511d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   for (i = 0; i < 2; i++) {
512d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      q = VG_(OSetGen_Lookup)(p->oset[i], &word_tid);
513d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      if (q)
514d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         q->thread_finished = True;
515bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
5168564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
5178564292ac4b9adf51c45517cca2878732feb5bb4sewardj
518d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
519d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Report that *_barrier_destroy() has been called but that this call was
520d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * not synchronized with the last *_barrier_wait() call on the same barrier.
521776a91e8fe04875abc38c1e7d0bc30175d285975bart *
522776a91e8fe04875abc38c1e7d0bc30175d285975bart * This topic has been discussed extensively on comp.programming.threads
523776a91e8fe04875abc38c1e7d0bc30175d285975bart * (February 3, 2009). See also
524776a91e8fe04875abc38c1e7d0bc30175d285975bart * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>.
525d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */
526d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic
527d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p,
528d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                                     const struct barrier_thread_info* const q)
5298564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
530bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
531bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(q);
532bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
533bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
534bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      BarrierErrInfo bei
535d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt };
536bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
537bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              BarrierErr,
538bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              VG_(get_IP)(VG_(get_running_tid)()),
539bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Destruction of barrier not synchronized with"
540bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " barrier wait call",
541bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              &bei);
542bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
5438564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
544306527d7413780873a05cf801c47f725fb60c310bart
545d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p)
546306527d7413780873a05cf801c47f725fb60c310bart{
547bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
548306527d7413780873a05cf801c47f725fb60c310bart
549bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return barrier_type_name(p->barrier_type);
550306527d7413780873a05cf801c47f725fb60c310bart}
551306527d7413780873a05cf801c47f725fb60c310bart
552d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt)
553306527d7413780873a05cf801c47f725fb60c310bart{
554bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   switch (bt)
555bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
556bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   case pthread_barrier:
557bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return "pthread barrier";
558bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   case gomp_barrier:
559bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return "gomp barrier";
560bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
561bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return "?";
562306527d7413780873a05cf801c47f725fb60c310bart}
5636bbefaf8418f3e225c4eefcc726b6874bef15d8cbart
564a8cf765964dc9b9436384469a0a30889b24d1997bartULong DRD_(get_barrier_segment_creation_count)(void)
5656bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{
566bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_barrier_segment_creation_count;
5676bbefaf8418f3e225c4eefcc726b6874bef15d8cbart}
568