drd_barrier.c revision 6bbefaf8418f3e225c4eefcc726b6874bef15d8c
18564292ac4b9adf51c45517cca2878732feb5bb4sewardj/*
28564292ac4b9adf51c45517cca2878732feb5bb4sewardj  This file is part of drd, a data race detector.
38564292ac4b9adf51c45517cca2878732feb5bb4sewardj
48564292ac4b9adf51c45517cca2878732feb5bb4sewardj  Copyright (C) 2006-2008 Bart Van Assche
58564292ac4b9adf51c45517cca2878732feb5bb4sewardj  bart.vanassche@gmail.com
68564292ac4b9adf51c45517cca2878732feb5bb4sewardj
78564292ac4b9adf51c45517cca2878732feb5bb4sewardj  This program is free software; you can redistribute it and/or
88564292ac4b9adf51c45517cca2878732feb5bb4sewardj  modify it under the terms of the GNU General Public License as
98564292ac4b9adf51c45517cca2878732feb5bb4sewardj  published by the Free Software Foundation; either version 2 of the
108564292ac4b9adf51c45517cca2878732feb5bb4sewardj  License, or (at your option) any later version.
118564292ac4b9adf51c45517cca2878732feb5bb4sewardj
128564292ac4b9adf51c45517cca2878732feb5bb4sewardj  This program is distributed in the hope that it will be useful, but
138564292ac4b9adf51c45517cca2878732feb5bb4sewardj  WITHOUT ANY WARRANTY; without even the implied warranty of
148564292ac4b9adf51c45517cca2878732feb5bb4sewardj  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
158564292ac4b9adf51c45517cca2878732feb5bb4sewardj  General Public License for more details.
168564292ac4b9adf51c45517cca2878732feb5bb4sewardj
178564292ac4b9adf51c45517cca2878732feb5bb4sewardj  You should have received a copy of the GNU General Public License
188564292ac4b9adf51c45517cca2878732feb5bb4sewardj  along with this program; if not, write to the Free Software
198564292ac4b9adf51c45517cca2878732feb5bb4sewardj  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
208564292ac4b9adf51c45517cca2878732feb5bb4sewardj  02111-1307, USA.
218564292ac4b9adf51c45517cca2878732feb5bb4sewardj
228564292ac4b9adf51c45517cca2878732feb5bb4sewardj  The GNU General Public License is contained in the file COPYING.
238564292ac4b9adf51c45517cca2878732feb5bb4sewardj*/
248564292ac4b9adf51c45517cca2878732feb5bb4sewardj
258564292ac4b9adf51c45517cca2878732feb5bb4sewardj
268564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_barrier.h"
2728230a3734e045791173aca660efc7d7aeef78cebart#include "drd_clientobj.h"
288564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_error.h"
298564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_suppression.h"
308564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "priv_drd_clientreq.h"
318564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_errormgr.h"    // VG_(maybe_record_error)()
328564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcassert.h"  // tl_assert()
338564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcprint.h"   // VG_(printf)()
348564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_machine.h"     // VG_(get_IP)()
358564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
368564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_oset.h"
378564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
388564292ac4b9adf51c45517cca2878732feb5bb4sewardj
398564292ac4b9adf51c45517cca2878732feb5bb4sewardj
408564292ac4b9adf51c45517cca2878732feb5bb4sewardj// Type definitions.
418564292ac4b9adf51c45517cca2878732feb5bb4sewardj
428ddef8828240404bfcbd38651a53aa38be044ab6bart/** Information associated with one thread participating in a barrier. */
43bebc5d668dc5a6df337011181debbf8d91c338e0bartstruct barrier_thread_info
44bebc5d668dc5a6df337011181debbf8d91c338e0bart{
45bebc5d668dc5a6df337011181debbf8d91c338e0bart  UWord       tid;           // A DrdThreadId
46bebc5d668dc5a6df337011181debbf8d91c338e0bart  Word        iteration;     // iteration of last pthread_barrier_wait()
47bebc5d668dc5a6df337011181debbf8d91c338e0bart                             // call thread tid participated in.
48a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart  Segment*    sg[2];         // Segments of the last two
49bebc5d668dc5a6df337011181debbf8d91c338e0bart                             // pthread_barrier() calls by thread tid.
508564292ac4b9adf51c45517cca2878732feb5bb4sewardj};
518564292ac4b9adf51c45517cca2878732feb5bb4sewardj
528564292ac4b9adf51c45517cca2878732feb5bb4sewardj
5328230a3734e045791173aca660efc7d7aeef78cebart// Local functions.
5428230a3734e045791173aca660efc7d7aeef78cebart
55306527d7413780873a05cf801c47f725fb60c310bartstatic void barrier_cleanup(struct barrier_info* p);
56306527d7413780873a05cf801c47f725fb60c310bartstatic const char* barrier_get_typename(struct barrier_info* const p);
57306527d7413780873a05cf801c47f725fb60c310bartstatic const char* barrier_type_name(const BarrierT bt);
5828230a3734e045791173aca660efc7d7aeef78cebart
5928230a3734e045791173aca660efc7d7aeef78cebart
608564292ac4b9adf51c45517cca2878732feb5bb4sewardj// Local variables.
618564292ac4b9adf51c45517cca2878732feb5bb4sewardj
628564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic Bool s_trace_barrier = False;
636bbefaf8418f3e225c4eefcc726b6874bef15d8cbartstatic ULong s_barrier_segment_creation_count;
648564292ac4b9adf51c45517cca2878732feb5bb4sewardj
658564292ac4b9adf51c45517cca2878732feb5bb4sewardj
668564292ac4b9adf51c45517cca2878732feb5bb4sewardj// Function definitions.
678564292ac4b9adf51c45517cca2878732feb5bb4sewardj
688564292ac4b9adf51c45517cca2878732feb5bb4sewardjvoid barrier_set_trace(const Bool trace_barrier)
698564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
708564292ac4b9adf51c45517cca2878732feb5bb4sewardj  s_trace_barrier = trace_barrier;
718564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
728564292ac4b9adf51c45517cca2878732feb5bb4sewardj
73bebc5d668dc5a6df337011181debbf8d91c338e0bart/** Initialize the structure *p with the specified thread ID and iteration
74bebc5d668dc5a6df337011181debbf8d91c338e0bart *  information. */
758564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic void barrier_thread_initialize(struct barrier_thread_info* const p,
768564292ac4b9adf51c45517cca2878732feb5bb4sewardj                                      const DrdThreadId tid,
778564292ac4b9adf51c45517cca2878732feb5bb4sewardj                                      const Word iteration)
788564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
798564292ac4b9adf51c45517cca2878732feb5bb4sewardj  p->tid = tid;
808564292ac4b9adf51c45517cca2878732feb5bb4sewardj  p->iteration = iteration;
81a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart  p->sg[0] = 0;
82a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart  p->sg[1] = 0;
838564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
848564292ac4b9adf51c45517cca2878732feb5bb4sewardj
85bebc5d668dc5a6df337011181debbf8d91c338e0bart/** Deallocate the memory that was allocated in barrier_thread_initialize(). */
868564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic void barrier_thread_destroy(struct barrier_thread_info* const p)
878564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
88a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart  sg_put(p->sg[0]);
89a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart  sg_put(p->sg[1]);
908564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
918564292ac4b9adf51c45517cca2878732feb5bb4sewardj
92bebc5d668dc5a6df337011181debbf8d91c338e0bart/** Initialize the structure *p with the specified client-side barrier address,
93bebc5d668dc5a6df337011181debbf8d91c338e0bart *  barrier object size and number of participants in each barrier. */
948564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic
958564292ac4b9adf51c45517cca2878732feb5bb4sewardjvoid barrier_initialize(struct barrier_info* const p,
968564292ac4b9adf51c45517cca2878732feb5bb4sewardj                        const Addr barrier,
970268dfacec38138a01a58d05a038826e26b6c436bart                        const BarrierT barrier_type,
988564292ac4b9adf51c45517cca2878732feb5bb4sewardj                        const Word count)
998564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
1008564292ac4b9adf51c45517cca2878732feb5bb4sewardj  tl_assert(barrier != 0);
1010268dfacec38138a01a58d05a038826e26b6c436bart  tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
1028564292ac4b9adf51c45517cca2878732feb5bb4sewardj  tl_assert(count > 0);
10328230a3734e045791173aca660efc7d7aeef78cebart  tl_assert(p->a1 == barrier);
1048564292ac4b9adf51c45517cca2878732feb5bb4sewardj
10528230a3734e045791173aca660efc7d7aeef78cebart  p->cleanup           = (void(*)(DrdClientobj*))barrier_cleanup;
106306527d7413780873a05cf801c47f725fb60c310bart  p->barrier_type      = barrier_type;
107bebc5d668dc5a6df337011181debbf8d91c338e0bart  p->count             = count;
108bebc5d668dc5a6df337011181debbf8d91c338e0bart  p->pre_iteration     = 0;
109bebc5d668dc5a6df337011181debbf8d91c338e0bart  p->post_iteration    = 0;
110bebc5d668dc5a6df337011181debbf8d91c338e0bart  p->pre_waiters_left  = count;
111bebc5d668dc5a6df337011181debbf8d91c338e0bart  p->post_waiters_left = count;
1128564292ac4b9adf51c45517cca2878732feb5bb4sewardj  tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word));
1138564292ac4b9adf51c45517cca2878732feb5bb4sewardj  tl_assert(sizeof(((struct barrier_thread_info*)0)->tid)
1148564292ac4b9adf51c45517cca2878732feb5bb4sewardj            >= sizeof(DrdThreadId));
1158564292ac4b9adf51c45517cca2878732feb5bb4sewardj  p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
1168564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
1178564292ac4b9adf51c45517cca2878732feb5bb4sewardj
11828230a3734e045791173aca660efc7d7aeef78cebart/** Deallocate the memory allocated by barrier_initialize() and in p->oset.
11972b751c3ba354f7069108d26b445310f0cf4a73cbart *  Called by clientobj_destroy().
12028230a3734e045791173aca660efc7d7aeef78cebart */
12128230a3734e045791173aca660efc7d7aeef78cebartvoid barrier_cleanup(struct barrier_info* p)
1228564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
1238564292ac4b9adf51c45517cca2878732feb5bb4sewardj  struct barrier_thread_info* q;
1248564292ac4b9adf51c45517cca2878732feb5bb4sewardj
1258564292ac4b9adf51c45517cca2878732feb5bb4sewardj  tl_assert(p);
1268564292ac4b9adf51c45517cca2878732feb5bb4sewardj
127306527d7413780873a05cf801c47f725fb60c310bart  if (p->pre_waiters_left != p->count)
12828230a3734e045791173aca660efc7d7aeef78cebart  {
1293b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart    BarrierErrInfo bei = { p->a1 };
1303b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart    VG_(maybe_record_error)(VG_(get_running_tid)(),
1313b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                            BarrierErr,
1323b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                            VG_(get_IP)(VG_(get_running_tid)()),
1333b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                            "Destruction of barrier that is being waited"
1343b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                            " upon",
1353b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                            &bei);
13628230a3734e045791173aca660efc7d7aeef78cebart  }
1378564292ac4b9adf51c45517cca2878732feb5bb4sewardj
1388564292ac4b9adf51c45517cca2878732feb5bb4sewardj  VG_(OSetGen_ResetIter)(p->oset);
1398564292ac4b9adf51c45517cca2878732feb5bb4sewardj  for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
1408564292ac4b9adf51c45517cca2878732feb5bb4sewardj  {
1418564292ac4b9adf51c45517cca2878732feb5bb4sewardj    barrier_thread_destroy(q);
1428564292ac4b9adf51c45517cca2878732feb5bb4sewardj  }
1438564292ac4b9adf51c45517cca2878732feb5bb4sewardj  VG_(OSetGen_Destroy)(p->oset);
1448564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
1458564292ac4b9adf51c45517cca2878732feb5bb4sewardj
146bebc5d668dc5a6df337011181debbf8d91c338e0bart/** Look up the client-side barrier address barrier in s_barrier[]. If not
147bebc5d668dc5a6df337011181debbf8d91c338e0bart *  found, add it. */
1488564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic
1498564292ac4b9adf51c45517cca2878732feb5bb4sewardjstruct barrier_info*
1500268dfacec38138a01a58d05a038826e26b6c436bartbarrier_get_or_allocate(const Addr barrier,
1510268dfacec38138a01a58d05a038826e26b6c436bart                        const BarrierT barrier_type, const Word count)
1528564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
15328230a3734e045791173aca660efc7d7aeef78cebart  struct barrier_info *p;
1548564292ac4b9adf51c45517cca2878732feb5bb4sewardj
1550268dfacec38138a01a58d05a038826e26b6c436bart  tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
1560268dfacec38138a01a58d05a038826e26b6c436bart
15728230a3734e045791173aca660efc7d7aeef78cebart  tl_assert(offsetof(DrdClientobj, barrier) == 0);
15872b751c3ba354f7069108d26b445310f0cf4a73cbart  p = &clientobj_get(barrier, ClientBarrier)->barrier;
15928230a3734e045791173aca660efc7d7aeef78cebart  if (p == 0)
1608564292ac4b9adf51c45517cca2878732feb5bb4sewardj  {
1610268dfacec38138a01a58d05a038826e26b6c436bart    p = &clientobj_add(barrier, ClientBarrier)->barrier;
1620268dfacec38138a01a58d05a038826e26b6c436bart    barrier_initialize(p, barrier, barrier_type, count);
1638564292ac4b9adf51c45517cca2878732feb5bb4sewardj  }
16428230a3734e045791173aca660efc7d7aeef78cebart  return p;
16528230a3734e045791173aca660efc7d7aeef78cebart}
16628230a3734e045791173aca660efc7d7aeef78cebart
16728230a3734e045791173aca660efc7d7aeef78cebart/** Look up the address of the information associated with the client-side
16828230a3734e045791173aca660efc7d7aeef78cebart *  barrier object. */
16972b751c3ba354f7069108d26b445310f0cf4a73cbartstatic struct barrier_info* barrier_get(const Addr barrier)
17028230a3734e045791173aca660efc7d7aeef78cebart{
17128230a3734e045791173aca660efc7d7aeef78cebart  tl_assert(offsetof(DrdClientobj, barrier) == 0);
17272b751c3ba354f7069108d26b445310f0cf4a73cbart  return &clientobj_get(barrier, ClientBarrier)->barrier;
1738564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
1748564292ac4b9adf51c45517cca2878732feb5bb4sewardj
175bebc5d668dc5a6df337011181debbf8d91c338e0bart/** Initialize a barrier with client address barrier, client size size, and
17628230a3734e045791173aca660efc7d7aeef78cebart *  where count threads participate in each barrier.
17728230a3734e045791173aca660efc7d7aeef78cebart *  Called before pthread_barrier_init().
17828230a3734e045791173aca660efc7d7aeef78cebart */
1790268dfacec38138a01a58d05a038826e26b6c436bartvoid barrier_init(const Addr barrier,
1800268dfacec38138a01a58d05a038826e26b6c436bart                  const BarrierT barrier_type, const Word count,
1810268dfacec38138a01a58d05a038826e26b6c436bart                  const Bool reinitialization)
1828564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
183306527d7413780873a05cf801c47f725fb60c310bart  struct barrier_info* p;
184306527d7413780873a05cf801c47f725fb60c310bart
185306527d7413780873a05cf801c47f725fb60c310bart  tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
186306527d7413780873a05cf801c47f725fb60c310bart
187306527d7413780873a05cf801c47f725fb60c310bart  p = barrier_get_or_allocate(barrier, barrier_type, count);
188306527d7413780873a05cf801c47f725fb60c310bart
1893b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  if (s_trace_barrier)
1903b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  {
191306527d7413780873a05cf801c47f725fb60c310bart    if (reinitialization)
192306527d7413780873a05cf801c47f725fb60c310bart    {
193306527d7413780873a05cf801c47f725fb60c310bart      VG_(message)(Vg_UserMsg,
194a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart                   "[%d/%d] barrier_reinit    %s 0x%lx count %ld -> %ld",
195306527d7413780873a05cf801c47f725fb60c310bart                   VG_(get_running_tid)(),
196306527d7413780873a05cf801c47f725fb60c310bart                   thread_get_running_tid(),
197306527d7413780873a05cf801c47f725fb60c310bart                   barrier_get_typename(p),
198306527d7413780873a05cf801c47f725fb60c310bart                   barrier,
199306527d7413780873a05cf801c47f725fb60c310bart                   p->count,
200306527d7413780873a05cf801c47f725fb60c310bart                   count);
201306527d7413780873a05cf801c47f725fb60c310bart    }
202306527d7413780873a05cf801c47f725fb60c310bart    else
203306527d7413780873a05cf801c47f725fb60c310bart    {
204306527d7413780873a05cf801c47f725fb60c310bart      VG_(message)(Vg_UserMsg,
205306527d7413780873a05cf801c47f725fb60c310bart                   "[%d/%d] barrier_init      %s 0x%lx",
206306527d7413780873a05cf801c47f725fb60c310bart                   VG_(get_running_tid)(),
207306527d7413780873a05cf801c47f725fb60c310bart                   thread_get_running_tid(),
208306527d7413780873a05cf801c47f725fb60c310bart                   barrier_get_typename(p),
209306527d7413780873a05cf801c47f725fb60c310bart                   barrier);
210306527d7413780873a05cf801c47f725fb60c310bart    }
211306527d7413780873a05cf801c47f725fb60c310bart  }
212306527d7413780873a05cf801c47f725fb60c310bart
213306527d7413780873a05cf801c47f725fb60c310bart  if (reinitialization && p->count != count)
214306527d7413780873a05cf801c47f725fb60c310bart  {
215306527d7413780873a05cf801c47f725fb60c310bart    if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
216306527d7413780873a05cf801c47f725fb60c310bart    {
217306527d7413780873a05cf801c47f725fb60c310bart      VG_(message)(Vg_UserMsg, "Error: reinitialization with active waiters");
218306527d7413780873a05cf801c47f725fb60c310bart    }
219306527d7413780873a05cf801c47f725fb60c310bart    p->count = count;
2203b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  }
2218564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
2228564292ac4b9adf51c45517cca2878732feb5bb4sewardj
22328230a3734e045791173aca660efc7d7aeef78cebart/** Called after pthread_barrier_destroy(). */
2240268dfacec38138a01a58d05a038826e26b6c436bartvoid barrier_destroy(const Addr barrier, const BarrierT barrier_type)
2258564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
22672b751c3ba354f7069108d26b445310f0cf4a73cbart  struct barrier_info* p;
22772b751c3ba354f7069108d26b445310f0cf4a73cbart
228306527d7413780873a05cf801c47f725fb60c310bart  p = barrier_get(barrier);
229306527d7413780873a05cf801c47f725fb60c310bart
2303b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  if (s_trace_barrier)
2313b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  {
2323b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart    VG_(message)(Vg_UserMsg,
233306527d7413780873a05cf801c47f725fb60c310bart                 "[%d/%d] barrier_destroy   %s 0x%lx",
2343b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 VG_(get_running_tid)(),
2353b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 thread_get_running_tid(),
236306527d7413780873a05cf801c47f725fb60c310bart                 barrier_get_typename(p),
23772b751c3ba354f7069108d26b445310f0cf4a73cbart                 barrier);
2383b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  }
23972b751c3ba354f7069108d26b445310f0cf4a73cbart
24072b751c3ba354f7069108d26b445310f0cf4a73cbart  if (p == 0)
24172b751c3ba354f7069108d26b445310f0cf4a73cbart  {
24272b751c3ba354f7069108d26b445310f0cf4a73cbart    GenericErrInfo GEI;
24372b751c3ba354f7069108d26b445310f0cf4a73cbart    VG_(maybe_record_error)(VG_(get_running_tid)(),
24472b751c3ba354f7069108d26b445310f0cf4a73cbart                            GenericErr,
24572b751c3ba354f7069108d26b445310f0cf4a73cbart                            VG_(get_IP)(VG_(get_running_tid)()),
24672b751c3ba354f7069108d26b445310f0cf4a73cbart                            "Not a barrier",
24772b751c3ba354f7069108d26b445310f0cf4a73cbart                            &GEI);
24872b751c3ba354f7069108d26b445310f0cf4a73cbart    return;
24972b751c3ba354f7069108d26b445310f0cf4a73cbart  }
25072b751c3ba354f7069108d26b445310f0cf4a73cbart
25172b751c3ba354f7069108d26b445310f0cf4a73cbart  clientobj_remove(p->a1, ClientBarrier);
2528564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
2538564292ac4b9adf51c45517cca2878732feb5bb4sewardj
25428230a3734e045791173aca660efc7d7aeef78cebart/** Called before pthread_barrier_wait(). */
2550268dfacec38138a01a58d05a038826e26b6c436bartvoid barrier_pre_wait(const DrdThreadId tid, const Addr barrier,
2560268dfacec38138a01a58d05a038826e26b6c436bart                      const BarrierT barrier_type)
2578564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
2588564292ac4b9adf51c45517cca2878732feb5bb4sewardj  struct barrier_info* p;
2598564292ac4b9adf51c45517cca2878732feb5bb4sewardj  struct barrier_thread_info* q;
2608564292ac4b9adf51c45517cca2878732feb5bb4sewardj  const UWord word_tid = tid;
2618564292ac4b9adf51c45517cca2878732feb5bb4sewardj
2628564292ac4b9adf51c45517cca2878732feb5bb4sewardj  p = barrier_get(barrier);
263c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart  if (p == 0 && barrier_type == gomp_barrier)
264c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart  {
265a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart    VG_(message)(Vg_UserMsg, "%s", "");
266c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart    VG_(message)(Vg_UserMsg,
267c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart                 "Please verify whether gcc has been configured"
268c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart                 " with option --disable-linux-futex.");
269c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart    VG_(message)(Vg_UserMsg,
270c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart                 "See also the section about OpenMP in the DRD manual.");
271a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart    VG_(message)(Vg_UserMsg, "%s", "");
272c68bd60a06673f81e2bf25fc2a049f5cb91fa545bart  }
2738564292ac4b9adf51c45517cca2878732feb5bb4sewardj  tl_assert(p);
2748564292ac4b9adf51c45517cca2878732feb5bb4sewardj
2758564292ac4b9adf51c45517cca2878732feb5bb4sewardj  if (s_trace_barrier)
2768564292ac4b9adf51c45517cca2878732feb5bb4sewardj  {
2773b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart    VG_(message)(Vg_UserMsg,
278a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart                 "[%d/%d] barrier_pre_wait  %s 0x%lx iteration %ld",
2793b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 VG_(get_running_tid)(),
2803b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 thread_get_running_tid(),
281306527d7413780873a05cf801c47f725fb60c310bart                 barrier_get_typename(p),
2823b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 barrier,
2833b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 p->pre_iteration);
2848564292ac4b9adf51c45517cca2878732feb5bb4sewardj  }
2858564292ac4b9adf51c45517cca2878732feb5bb4sewardj
2868564292ac4b9adf51c45517cca2878732feb5bb4sewardj  q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
2878564292ac4b9adf51c45517cca2878732feb5bb4sewardj  if (q == 0)
2888564292ac4b9adf51c45517cca2878732feb5bb4sewardj  {
2898564292ac4b9adf51c45517cca2878732feb5bb4sewardj    q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
290bebc5d668dc5a6df337011181debbf8d91c338e0bart    barrier_thread_initialize(q, tid, p->pre_iteration);
2918564292ac4b9adf51c45517cca2878732feb5bb4sewardj    VG_(OSetGen_Insert)(p->oset, q);
2928564292ac4b9adf51c45517cca2878732feb5bb4sewardj    tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
2938564292ac4b9adf51c45517cca2878732feb5bb4sewardj  }
294a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart  thread_get_latest_segment(&q->sg[p->pre_iteration], tid);
295bebc5d668dc5a6df337011181debbf8d91c338e0bart
296bebc5d668dc5a6df337011181debbf8d91c338e0bart  if (--p->pre_waiters_left <= 0)
297bebc5d668dc5a6df337011181debbf8d91c338e0bart  {
298bebc5d668dc5a6df337011181debbf8d91c338e0bart    p->pre_iteration    = 1 - p->pre_iteration;
299bebc5d668dc5a6df337011181debbf8d91c338e0bart    p->pre_waiters_left = p->count;
300bebc5d668dc5a6df337011181debbf8d91c338e0bart  }
3018564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
3028564292ac4b9adf51c45517cca2878732feb5bb4sewardj
30328230a3734e045791173aca660efc7d7aeef78cebart/** Called after pthread_barrier_wait(). */
3048564292ac4b9adf51c45517cca2878732feb5bb4sewardjvoid barrier_post_wait(const DrdThreadId tid, const Addr barrier,
3050268dfacec38138a01a58d05a038826e26b6c436bart                       const BarrierT barrier_type, const Bool waited)
3068564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
3073b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  struct barrier_info* p;
3088564292ac4b9adf51c45517cca2878732feb5bb4sewardj
3093b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart  p = barrier_get(barrier);
310bebc5d668dc5a6df337011181debbf8d91c338e0bart
3118564292ac4b9adf51c45517cca2878732feb5bb4sewardj  if (s_trace_barrier)
3128564292ac4b9adf51c45517cca2878732feb5bb4sewardj  {
3133b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart    VG_(message)(Vg_UserMsg,
314a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart                 "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld",
3153b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 VG_(get_running_tid)(),
3163b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 tid,
317306527d7413780873a05cf801c47f725fb60c310bart                 p ? barrier_get_typename(p) : "(?)",
3183b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart                 barrier,
319306527d7413780873a05cf801c47f725fb60c310bart                 p ? p->post_iteration : -1);
3208564292ac4b9adf51c45517cca2878732feb5bb4sewardj  }
3218564292ac4b9adf51c45517cca2878732feb5bb4sewardj
322306527d7413780873a05cf801c47f725fb60c310bart  /* If p == 0, this means that the barrier has been destroyed after     */
323306527d7413780873a05cf801c47f725fb60c310bart  /* *_barrier_wait() returned and before this function was called. Just */
324306527d7413780873a05cf801c47f725fb60c310bart  /* return in that case.                                                */
325306527d7413780873a05cf801c47f725fb60c310bart  if (p == 0)
326306527d7413780873a05cf801c47f725fb60c310bart    return;
327306527d7413780873a05cf801c47f725fb60c310bart
3288564292ac4b9adf51c45517cca2878732feb5bb4sewardj  if (waited)
3298564292ac4b9adf51c45517cca2878732feb5bb4sewardj  {
3308564292ac4b9adf51c45517cca2878732feb5bb4sewardj    const UWord word_tid = tid;
3318564292ac4b9adf51c45517cca2878732feb5bb4sewardj    struct barrier_thread_info* q;
3328564292ac4b9adf51c45517cca2878732feb5bb4sewardj    struct barrier_thread_info* r;
3338564292ac4b9adf51c45517cca2878732feb5bb4sewardj
3348564292ac4b9adf51c45517cca2878732feb5bb4sewardj    q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
3358564292ac4b9adf51c45517cca2878732feb5bb4sewardj    tl_assert(q);
3368564292ac4b9adf51c45517cca2878732feb5bb4sewardj    VG_(OSetGen_ResetIter)(p->oset);
3378564292ac4b9adf51c45517cca2878732feb5bb4sewardj    for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
3388564292ac4b9adf51c45517cca2878732feb5bb4sewardj    {
3398564292ac4b9adf51c45517cca2878732feb5bb4sewardj      if (r != q)
3408564292ac4b9adf51c45517cca2878732feb5bb4sewardj      {
341a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart        tl_assert(r->sg[p->post_iteration]);
342a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart        thread_combine_vc2(tid, &r->sg[p->post_iteration]->vc);
3438564292ac4b9adf51c45517cca2878732feb5bb4sewardj      }
3448564292ac4b9adf51c45517cca2878732feb5bb4sewardj    }
345bebc5d668dc5a6df337011181debbf8d91c338e0bart
346bebc5d668dc5a6df337011181debbf8d91c338e0bart    thread_new_segment(tid);
3476bbefaf8418f3e225c4eefcc726b6874bef15d8cbart    s_barrier_segment_creation_count++;
348bebc5d668dc5a6df337011181debbf8d91c338e0bart
349bebc5d668dc5a6df337011181debbf8d91c338e0bart    if (--p->post_waiters_left <= 0)
350bebc5d668dc5a6df337011181debbf8d91c338e0bart    {
351bebc5d668dc5a6df337011181debbf8d91c338e0bart      p->post_iteration    = 1 - p->post_iteration;
352bebc5d668dc5a6df337011181debbf8d91c338e0bart      p->post_waiters_left = p->count;
353bebc5d668dc5a6df337011181debbf8d91c338e0bart    }
3548564292ac4b9adf51c45517cca2878732feb5bb4sewardj  }
3558564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
3568564292ac4b9adf51c45517cca2878732feb5bb4sewardj
357bebc5d668dc5a6df337011181debbf8d91c338e0bart/** Call this function when thread tid stops to exist. */
3588564292ac4b9adf51c45517cca2878732feb5bb4sewardjvoid barrier_thread_delete(const DrdThreadId tid)
3598564292ac4b9adf51c45517cca2878732feb5bb4sewardj{
36028230a3734e045791173aca660efc7d7aeef78cebart  struct barrier_info* p;
3618564292ac4b9adf51c45517cca2878732feb5bb4sewardj
36272b751c3ba354f7069108d26b445310f0cf4a73cbart  clientobj_resetiter();
36372b751c3ba354f7069108d26b445310f0cf4a73cbart  for ( ; (p = &clientobj_next(ClientBarrier)->barrier) != 0; )
3648564292ac4b9adf51c45517cca2878732feb5bb4sewardj  {
36528230a3734e045791173aca660efc7d7aeef78cebart    struct barrier_thread_info* q;
36628230a3734e045791173aca660efc7d7aeef78cebart    const UWord word_tid = tid;
36728230a3734e045791173aca660efc7d7aeef78cebart    q = VG_(OSetGen_Remove)(p->oset, &word_tid);
36828230a3734e045791173aca660efc7d7aeef78cebart    barrier_thread_destroy(q);
36928230a3734e045791173aca660efc7d7aeef78cebart    VG_(OSetGen_FreeNode)(p->oset, q);
3708564292ac4b9adf51c45517cca2878732feb5bb4sewardj  }
3718564292ac4b9adf51c45517cca2878732feb5bb4sewardj}
372306527d7413780873a05cf801c47f725fb60c310bart
373306527d7413780873a05cf801c47f725fb60c310bartstatic const char* barrier_get_typename(struct barrier_info* const p)
374306527d7413780873a05cf801c47f725fb60c310bart{
375306527d7413780873a05cf801c47f725fb60c310bart  tl_assert(p);
376306527d7413780873a05cf801c47f725fb60c310bart
377306527d7413780873a05cf801c47f725fb60c310bart  return barrier_type_name(p->barrier_type);
378306527d7413780873a05cf801c47f725fb60c310bart}
379306527d7413780873a05cf801c47f725fb60c310bart
380306527d7413780873a05cf801c47f725fb60c310bartstatic const char* barrier_type_name(const BarrierT bt)
381306527d7413780873a05cf801c47f725fb60c310bart{
382306527d7413780873a05cf801c47f725fb60c310bart  switch (bt)
383306527d7413780873a05cf801c47f725fb60c310bart  {
384306527d7413780873a05cf801c47f725fb60c310bart  case pthread_barrier:
385306527d7413780873a05cf801c47f725fb60c310bart    return "pthread barrier";
386306527d7413780873a05cf801c47f725fb60c310bart  case gomp_barrier:
387306527d7413780873a05cf801c47f725fb60c310bart    return "gomp barrier";
388306527d7413780873a05cf801c47f725fb60c310bart  }
389306527d7413780873a05cf801c47f725fb60c310bart  return "?";
390306527d7413780873a05cf801c47f725fb60c310bart}
3916bbefaf8418f3e225c4eefcc726b6874bef15d8cbart
3926bbefaf8418f3e225c4eefcc726b6874bef15d8cbartULong get_barrier_segment_creation_count(void)
3936bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{
3946bbefaf8418f3e225c4eefcc726b6874bef15d8cbart  return s_barrier_segment_creation_count;
3956bbefaf8418f3e225c4eefcc726b6874bef15d8cbart}
396