1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of drd, a thread error detector.
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>.
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_clientobj.h"
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_hb.h"
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_error.h"
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_errormgr.h"    /* VG_(maybe_record_error)() */
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"  /* tl_assert()               */
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"   /* VG_(printf)()             */
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"     /* VG_(get_IP)()             */
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"  /* VG_(malloc)(), VG_(free)()*/
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_threadstate.h" /* VG_(get_running_tid)()    */
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Type definitions. */
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Per-thread hb information. */
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct hb_thread_info
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord       tid; // A DrdThreadId declared as UWord because
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    // this member variable is the key of an OSet.
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment*    sg;  // Segment created before most recent
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    // ANNOTATE_HAPPENS_BEFORE().
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local functions. */
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(hb_cleanup)(struct hb_info* p);
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local variables. */
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool DRD_(s_trace_hb);
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function definitions. */
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(hb_set_trace)(const Bool trace_hb)
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(s_trace_hb) = trace_hb;
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Initialize the structure *p with the specified thread ID.
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(hb_thread_initialize)(struct hb_thread_info* const p,
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  const DrdThreadId tid)
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p->tid  = tid;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p->sg   = 0;
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Deallocate the memory that is owned by members of struct hb_thread_info.
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(hb_thread_destroy)(struct hb_thread_info* const p)
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(p);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(sg_put)(p->sg);
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(hb_initialize)(struct hb_info* const p, const Addr hb)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(hb != 0);
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(p->a1   == hb);
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(p->type == ClientHbvar);
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p->cleanup       = (void(*)(DrdClientobj*))(DRD_(hb_cleanup));
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p->delete_thread = 0;
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p->oset          = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.hb",
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          VG_(free));
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Free the memory that was allocated by hb_initialize(). Called by
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * DRD_(clientobj_remove)().
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(hb_cleanup)(struct hb_info* p)
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct hb_thread_info* r;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(p);
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(p->oset);
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(hb_thread_destroy)(r);
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_Destroy)(p->oset);
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Report that the synchronization object at address 'addr' is of the
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * wrong type.
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void wrong_type(const Addr addr)
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GenericErrInfo gei = {
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .tid  = DRD_(thread_get_running_tid)(),
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .addr = addr,
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   };
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(maybe_record_error)(VG_(get_running_tid)(),
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           GenericErr,
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           VG_(get_IP)(VG_(get_running_tid)()),
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           "wrong type of synchronization object",
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           &gei);
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct hb_info* DRD_(hb_get_or_allocate)(const Addr hb)
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct hb_info *p;
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(offsetof(DrdClientobj, hb) == 0);
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p = &(DRD_(clientobj_get)(hb, ClientHbvar)->hb);
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (p)
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return p;
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(clientobj_present)(hb, hb + 1))
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      wrong_type(hb);
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p = &(DRD_(clientobj_add)(hb, ClientHbvar)->hb);
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(hb_initialize)(p, hb);
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct hb_info* DRD_(hb_get)(const Addr hb)
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(offsetof(DrdClientobj, hb) == 0);
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return &(DRD_(clientobj_get)(hb, ClientHbvar)->hb);
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Called because of a happens-before annotation. */
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(hb_happens_before)(const DrdThreadId tid, Addr const hb)
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const ThreadId vg_tid = VG_(get_running_tid)();
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const DrdThreadId drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const UWord word_tid = tid;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct hb_info* p;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct hb_thread_info* q;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p = DRD_(hb_get_or_allocate)(hb);
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(s_trace_hb))
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("[%d] happens_before 0x%lx",
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      DRD_(thread_get_running_tid)(), hb);
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!p)
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Allocate the per-thread data structure if necessary. */
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!q)
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(hb_thread_initialize)(q, tid);
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(OSetGen_Insert)(p->oset, q);
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * Store a pointer to the latest segment of the current thread in the
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * per-thread data structure.
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_get_latest_segment)(&q->sg, tid);
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_new_segment)(drd_tid);
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Called because of a happens-after annotation. */
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(hb_happens_after)(const DrdThreadId tid, const Addr hb)
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct hb_info* p;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct hb_thread_info* q;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VectorClock old_vc;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p = DRD_(hb_get_or_allocate)(hb);
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(s_trace_hb))
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("[%d] happens_after  0x%lx",
202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      DRD_(thread_get_running_tid)(), hb);
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!p)
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_new_segment)(tid);
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * Combine all vector clocks that were stored because of happens-before
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * annotations with the vector clock of the current thread.
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(tid));
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(p->oset);
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (q->tid != tid)
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(q->sg);
220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DRD_(vc_combine)(DRD_(thread_get_vc)(tid), &q->sg->vc);
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_update_conflict_set)(tid, &old_vc);
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(vc_cleanup)(&old_vc);
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Called because of a happens-done annotation. */
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(hb_happens_done)(const DrdThreadId tid, const Addr hb)
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct hb_info* p;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(s_trace_hb))
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("[%d] happens_done  0x%lx",
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      DRD_(thread_get_running_tid)(), hb);
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p = DRD_(hb_get)(hb);
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!p)
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GenericErrInfo gei = {
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 .tid = DRD_(thread_get_running_tid)(),
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 .addr = hb,
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      };
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(maybe_record_error)(VG_(get_running_tid)(),
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              GenericErr,
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              VG_(get_IP)(VG_(get_running_tid)()),
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "missing happens-before annotation",
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              &gei);
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(clientobj_remove)(p->a1, ClientHbvar);
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
253