drd_barrier.c revision d61580edabd4bd165c2484b92cb8d4cb2b65d32f
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 {
167d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      oset = p->oset[1 - p->pre_iteration];
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
261bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_barrier)
262bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
263bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (reinitialization)
264bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
265bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(message)(Vg_UserMsg,
26663c92ea799549976957f5b4d54ede744f762c56fbart                      "[%d] barrier_reinit    %s 0x%lx count %ld -> %ld\n",
267bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      DRD_(thread_get_running_tid)(),
268bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      barrier_get_typename(p),
269bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      barrier,
270bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      p->count,
271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      count);
272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      else
274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
275bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(message)(Vg_UserMsg,
27663c92ea799549976957f5b4d54ede744f762c56fbart                      "[%d] barrier_init      %s 0x%lx\n",
277bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      DRD_(thread_get_running_tid)(),
278bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      barrier_get_typename(p),
279bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      barrier);
280bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
281bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
282bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
283bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (reinitialization && p->count != count)
284bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
285bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
286bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
287d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
288bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(maybe_record_error)(VG_(get_running_tid)(),
289bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 BarrierErr,
290bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 VG_(get_IP)(VG_(get_running_tid)()),
291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 "Reinitialization of barrier with active"
292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 " waiters",
293bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                 &bei);
294bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->count = count;
296bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
297bedfd237fbdc80d0c917cfcb85a94b5561c92633bart}
298bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
299bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */
300bedfd237fbdc80d0c917cfcb85a94b5561c92633bartvoid DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart{
302bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info* p;
303bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
304bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = DRD_(barrier_get)(barrier);
305bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
306bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_barrier)
307bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
308306527d7413780873a05cf801c47f725fb60c310bart      VG_(message)(Vg_UserMsg,
30963c92ea799549976957f5b4d54ede744f762c56fbart                   "[%d] barrier_destroy   %s 0x%lx\n",
31062a784c9382fdf7184065ad76ae8d3b905605f21bart                   DRD_(thread_get_running_tid)(),
311d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                   barrier_get_typename(p),
312306527d7413780873a05cf801c47f725fb60c310bart                   barrier);
313bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
314bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
315bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p == 0)
316bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
31762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart      GenericErrInfo GEI = {
31862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart	 .tid = DRD_(thread_get_running_tid)(),
31962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart	 .addr = barrier,
32062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart      };
321bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
322bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              GenericErr,
323bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              VG_(get_IP)(VG_(get_running_tid)()),
324bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Not a barrier",
325bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              &GEI);
326bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return;
327bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
328306527d7413780873a05cf801c47f725fb60c310bart
329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
330bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
331d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
332195a3983ff6030cbe21fd4561006acdd3c31dbafbart      VG_(maybe_record_error)(VG_(get_running_tid)(),
333195a3983ff6030cbe21fd4561006acdd3c31dbafbart                              BarrierErr,
334195a3983ff6030cbe21fd4561006acdd3c31dbafbart                              VG_(get_IP)(VG_(get_running_tid)()),
335bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Destruction of a barrier with active waiters",
336195a3983ff6030cbe21fd4561006acdd3c31dbafbart                              &bei);
337bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
3388564292ac4b9adf51c45517cca2878732feb5bb4sewardj
339bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(clientobj_remove)(p->a1, ClientBarrier);
3408564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
3418564292ac4b9adf51c45517cca2878732feb5bb4sewardj
342d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */
343a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
344a8cf765964dc9b9436384469a0a30889b24d1997bart                            const BarrierT barrier_type)
3458564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
346bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info* p;
347bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* q;
348bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const UWord word_tid = tid;
349d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   OSet* oset;
350bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
351bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = DRD_(barrier_get)(barrier);
352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p == 0 && barrier_type == gomp_barrier)
353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      /*
355bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * gomp_barrier_wait() call has been intercepted but gomp_barrier_init()
356bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * not. The only cause I know of that can trigger this is that libgomp.so
357bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * has been compiled with --enable-linux-futex.
358bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       */
3591e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_UserMsg, "\n");
360bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(message)(Vg_UserMsg,
361bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   "Please verify whether gcc has been configured"
3621e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj                   " with option --disable-linux-futex.\n");
363bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(message)(Vg_UserMsg,
3641e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj                   "See also the section about OpenMP in the DRD manual.\n");
3651e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_UserMsg, "\n");
366bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
367bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
368bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
369bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_barrier)
370bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
371bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(message)(Vg_UserMsg,
37263c92ea799549976957f5b4d54ede744f762c56fbart                   "[%d] barrier_pre_wait  %s 0x%lx iteration %ld\n",
373bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   DRD_(thread_get_running_tid)(),
374bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   barrier_get_typename(p),
375bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   barrier,
376bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   p->pre_iteration);
377bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
378bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
379d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   /* Clean up nodes associated with finished threads. */
380d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   oset = p->oset[p->pre_iteration];
381d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   tl_assert(oset);
382d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   VG_(OSetGen_ResetIter)(oset);
383d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) {
384d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      if (q->thread_finished) {
385d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         void* r = VG_(OSetGen_Remove)(oset, &q->tid);
386d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         tl_assert(r == q);
387d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         DRD_(barrier_thread_destroy)(q);
388d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         VG_(OSetGen_FreeNode)(oset, q);
389d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         VG_(OSetGen_ResetIterAt)(oset, &word_tid);
390d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      }
391d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   }
392bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /* Allocate the per-thread data structure if necessary. */
393d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   q = VG_(OSetGen_Lookup)(oset, &word_tid);
394d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   if (q == NULL) {
395d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      q = VG_(OSetGen_AllocNode)(oset, sizeof(*q));
396cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart      DRD_(barrier_thread_initialize)(q, tid);
397d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_Insert)(oset, q);
398d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q);
399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
400bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
401bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /* Record *_barrier_wait() call context. */
402bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
403bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
404bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
405bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * Store a pointer to the latest segment of the current thread in the
406bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * per-thread data structure.
407bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
408d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   DRD_(thread_get_latest_segment)(&q->sg, tid);
409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
411bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * If the same number of threads as the barrier count indicates have
412bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and
413bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * reset the p->pre_waiters_left counter.
414bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (--p->pre_waiters_left <= 0)
416bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
417bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->pre_iteration    = 1 - p->pre_iteration;
418bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->pre_waiters_left = p->count;
419bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
4208564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
4218564292ac4b9adf51c45517cca2878732feb5bb4sewardj
422d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */
423a8cf765964dc9b9436384469a0a30889b24d1997bartvoid DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
424d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                             const BarrierT barrier_type, const Bool waited,
425d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                             const Bool serializing)
4268564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
427bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_info* p;
428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const UWord word_tid = tid;
429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* q;
430bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* r;
431d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   OSet* oset;
432bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
433bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   p = DRD_(barrier_get)(barrier);
434bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
435bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_barrier)
436bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
437bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(message)(Vg_UserMsg,
43863c92ea799549976957f5b4d54ede744f762c56fbart                   "[%d] barrier_post_wait %s 0x%lx iteration %ld%s\n",
439bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   tid,
440bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   p ? barrier_get_typename(p) : "(?)",
441bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   barrier,
442bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   p ? p->post_iteration : -1,
443bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                   serializing ? " (serializing)" : "");
444bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
445bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
446bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
447bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * If p == 0, this means that the barrier has been destroyed after
448bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * *_barrier_wait() returned and before this function was called. Just
449bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * return in that case -- race conditions between *_barrier_wait()
450bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper.
451bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
452bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (p == 0)
453bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return;
454bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
455bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /* If the *_barrier_wait() call returned an error code, exit. */
456bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (! waited)
457bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return;
458bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
459d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   oset = p->oset[p->post_iteration];
460d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   q = VG_(OSetGen_Lookup)(oset, &word_tid);
461bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (q == 0)
462bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
463d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
464bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
465bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              BarrierErr,
466bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              VG_(get_IP)(VG_(get_running_tid)()),
467bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Error in barrier implementation"
468bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " -- barrier_wait() started before"
469bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " barrier_destroy() and finished after"
470bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " barrier_destroy()",
471bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              &bei);
472bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
473d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      q = VG_(OSetGen_AllocNode)(oset, sizeof(*q));
474cdc3fdb0d8e7c691f9dc52bcce83b63b1f2bce27bart      DRD_(barrier_thread_initialize)(q, tid);
475d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_Insert)(oset, q);
476d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q);
477bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
4787627be3e26162e4f59ccfd35eaf31495ddefdf9bbart
4797627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   /* Create a new segment and store a pointer to that segment. */
4807627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   DRD_(thread_new_segment)(tid);
4817627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid);
4827627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   s_barrier_segment_creation_count++;
4837627be3e26162e4f59ccfd35eaf31495ddefdf9bbart
484bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
485bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * Combine all vector clocks that were stored in the pre_barrier_wait
486bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * wrapper with the vector clock of the current thread.
487bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
488bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
4898f822af9b234e7c553c408eba65a641c4773457fbart      VectorClock old_vc;
4908f822af9b234e7c553c408eba65a641c4773457fbart
4918f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
492d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      VG_(OSetGen_ResetIter)(oset);
493d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      for ( ; (r = VG_(OSetGen_Next)(oset)) != 0; )
494bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
4958f822af9b234e7c553c408eba65a641c4773457fbart         if (r != q)
4968f822af9b234e7c553c408eba65a641c4773457fbart         {
497d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart            tl_assert(r->sg);
4988f822af9b234e7c553c408eba65a641c4773457fbart            DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc,
499d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart                             &r->sg->vc);
5008f822af9b234e7c553c408eba65a641c4773457fbart         }
501bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
5028f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(thread_update_conflict_set)(tid, &old_vc);
5038f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(vc_cleanup)(&old_vc);
504bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
505bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
506bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   /*
507bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * If the same number of threads as the barrier count indicates have
508bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * called the post *_barrier_wait() wrapper, toggle p->post_iteration and
509bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    * reset the p->post_waiters_left counter.
510bedfd237fbdc80d0c917cfcb85a94b5561c92633bart    */
511bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (--p->post_waiters_left <= 0)
512bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
513bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->post_iteration    = 1 - p->post_iteration;
514bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      p->post_waiters_left = p->count;
515bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
516d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart}
517bebc5d668dc5a6df337011181debbf8d91c338e0bart
518d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/** Called when thread tid stops to exist. */
519d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void barrier_delete_thread(struct barrier_info* const p,
520d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                                  const DrdThreadId tid)
521d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart{
522bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   struct barrier_thread_info* q;
523bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const UWord word_tid = tid;
524d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   int i;
525bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
526d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart   for (i = 0; i < 2; i++) {
527d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      q = VG_(OSetGen_Lookup)(p->oset[i], &word_tid);
528d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart      if (q)
529d61580edabd4bd165c2484b92cb8d4cb2b65d32fbart         q->thread_finished = True;
530bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
5318564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
5328564292ac4b9adf51c45517cca2878732feb5bb4sewardj
533d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart/**
534d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * Report that *_barrier_destroy() has been called but that this call was
535d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart * not synchronized with the last *_barrier_wait() call on the same barrier.
536776a91e8fe04875abc38c1e7d0bc30175d285975bart *
537776a91e8fe04875abc38c1e7d0bc30175d285975bart * This topic has been discussed extensively on comp.programming.threads
538776a91e8fe04875abc38c1e7d0bc30175d285975bart * (February 3, 2009). See also
539776a91e8fe04875abc38c1e7d0bc30175d285975bart * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>.
540d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart */
541d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic
542d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartvoid barrier_report_wait_delete_race(const struct barrier_info* const p,
543d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart                                     const struct barrier_thread_info* const q)
5448564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
545bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
546bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(q);
547bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
548bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
549bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      BarrierErrInfo bei
550d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt };
551bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(maybe_record_error)(VG_(get_running_tid)(),
552bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              BarrierErr,
553bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              VG_(get_IP)(VG_(get_running_tid)()),
554bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              "Destruction of barrier not synchronized with"
555bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              " barrier wait call",
556bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                              &bei);
557bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
5588564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
559306527d7413780873a05cf801c47f725fb60c310bart
560d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_get_typename(struct barrier_info* const p)
561306527d7413780873a05cf801c47f725fb60c310bart{
562bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
563306527d7413780873a05cf801c47f725fb60c310bart
564bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return barrier_type_name(p->barrier_type);
565306527d7413780873a05cf801c47f725fb60c310bart}
566306527d7413780873a05cf801c47f725fb60c310bart
567d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic const char* barrier_type_name(const BarrierT bt)
568306527d7413780873a05cf801c47f725fb60c310bart{
569bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   switch (bt)
570bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
571bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   case pthread_barrier:
572bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return "pthread barrier";
573bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   case gomp_barrier:
574bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return "gomp barrier";
575bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
576bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return "?";
577306527d7413780873a05cf801c47f725fb60c310bart}
5786bbefaf8418f3e225c4eefcc726b6874bef15d8cbart
579a8cf765964dc9b9436384469a0a30889b24d1997bartULong DRD_(get_barrier_segment_creation_count)(void)
5806bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{
581bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_barrier_segment_creation_count;
5826bbefaf8418f3e225c4eefcc726b6874bef15d8cbart}
583