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_error.h"
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_barrier.h"
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_clientobj.h"
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_cond.h"
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_mutex.h"
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_segment.h"
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_semaphore.h"
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_suppression.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_thread.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_vki.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h"      // Addr, SizeT
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"  // tl_assert()
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h"    // VG_(strlen)()
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"   // VG_(printf)()
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcproc.h"    // VG_(getenv)()
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h"     // VG_(clo_backtrace_size)
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local functions. */
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void thread_append_segment(const DrdThreadId tid, Segment* const sg);
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void thread_compute_conflict_set(struct bitmap** conflict_set,
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        const DrdThreadId tid);
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local variables. */
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_context_switch_count;
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_discard_ordered_segments_count;
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_compute_conflict_set_count;
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_update_conflict_set_count;
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_update_conflict_set_new_sg_count;
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_update_conflict_set_sync_count;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_update_conflict_set_join_count;
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_conflict_set_bitmap_creation_count;
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong    s_conflict_set_bitmap2_creation_count;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ThreadId s_vg_running_tid  = VG_INVALID_THREADID;
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDrdThreadId     DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThreadInfo      DRD_(g_threadinfo)[DRD_N_THREADS];
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct bitmap*  DRD_(g_conflict_set);
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool     s_trace_context_switches = False;
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool     s_trace_conflict_set = False;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool     s_trace_conflict_set_bm = False;
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool     s_trace_fork_join = False;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool     s_segment_merging = True;
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool     s_new_segments_since_last_merge;
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int      s_segment_merge_interval = 10;
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic unsigned s_join_list_vol = 10;
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic unsigned s_deletion_head;
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic unsigned s_deletion_tail;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function definitions. */
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Enables/disables context switch tracing. */
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_trace_context_switches)(const Bool t)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(t == False || t == True);
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_trace_context_switches = t;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Enables/disables conflict set tracing. */
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_trace_conflict_set)(const Bool t)
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(t == False || t == True);
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_trace_conflict_set = t;
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Enables/disables conflict set bitmap tracing. */
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_trace_conflict_set_bm)(const Bool t)
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(t == False || t == True);
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_trace_conflict_set_bm = t;
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Report whether fork/join tracing is enabled. */
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(thread_get_trace_fork_join)(void)
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_trace_fork_join;
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Enables/disables fork/join tracing. */
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_trace_fork_join)(const Bool t)
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(t == False || t == True);
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_trace_fork_join = t;
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Enables/disables segment merging. */
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_segment_merging)(const Bool m)
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(m == False || m == True);
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_segment_merging = m;
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Get the segment merging interval. */
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint DRD_(thread_get_segment_merge_interval)(void)
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_segment_merge_interval;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Set the segment merging interval. */
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_segment_merge_interval)(const int i)
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_segment_merge_interval = i;
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid DRD_(thread_set_join_list_vol)(const int jlv)
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   s_join_list_vol = jlv;
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid DRD_(thread_init)(void)
144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Convert Valgrind's ThreadId into a DrdThreadId.
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         Valgrind ThreadId does not yet exist.
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i;
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tid == VG_INVALID_THREADID)
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_INVALID_THREADID;
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 1; i < DRD_N_THREADS; i++)
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (DRD_(g_threadinfo)[i].vg_thread_exists == True
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && DRD_(g_threadinfo)[i].vg_threadid == tid)
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return i;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_INVALID_THREADID;
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i;
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 1; i < DRD_N_THREADS; i++)
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!DRD_(g_threadinfo)[i].valid)
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(! DRD_(IsValidDrdThreadId)(i));
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DRD_(g_threadinfo)[i].valid         = True;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].vg_thread_exists = True;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].vg_threadid   = tid;
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].pt_threadid   = INVALID_POSIX_THREADID;
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].stack_min     = 0;
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].stack_min_min = 0;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].stack_startup = 0;
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].stack_max     = 0;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(thread_set_name)(i, "");
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].on_alt_stack        = False;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].is_recording_loads  = True;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].is_recording_stores = True;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(g_threadinfo)[i].synchr_nesting = 0;
199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DRD_(g_threadinfo)[i].deletion_seq = s_deletion_tail - 1;
200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tl_assert(DRD_(g_threadinfo)[i].sg_first == NULL);
201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tl_assert(DRD_(g_threadinfo)[i].sg_last == NULL);
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(DRD_(IsValidDrdThreadId)(i));
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return i;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\nSorry, but the maximum number of threads supported by DRD has been exceeded."
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"Aborting.\n");
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(False);
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_INVALID_THREADID;
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Convert a POSIX thread ID into a DRD thread ID. */
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tid != INVALID_POSIX_THREADID)
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 1; i < DRD_N_THREADS; i++)
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DRD_(g_threadinfo)[i].posix_thread_exists
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && DRD_(g_threadinfo)[i].pt_threadid == tid)
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return i;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_INVALID_THREADID;
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Convert a DRD thread ID into a Valgrind thread ID. */
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (DRD_(g_threadinfo)[tid].vg_thread_exists
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ? DRD_(g_threadinfo)[tid].vg_threadid
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           : VG_INVALID_THREADID);
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Sanity check of the doubly linked list of segments referenced by a
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ThreadInfo struct.
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @return True if sane, False if not.
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* p;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2582ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov   for (p = ti->sg_first; p; p = p->thr_next) {
2592ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      if (p->thr_next && p->thr_next->thr_prev != p)
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
2612ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      if (p->thr_next == 0 && p != ti->sg_last)
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2642ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov   for (p = ti->sg_last; p; p = p->thr_prev) {
2652ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      if (p->thr_prev && p->thr_prev->thr_next != p)
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
2672ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      if (p->thr_prev == 0 && p != ti->sg_first)
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create the first segment for a newly started thread.
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function is called from the handler installed via
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * from the context of the creator thread, before the new thread has been
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * created.
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param[in] creator    DRD thread ID of the creator thread.
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param[in] vg_created Valgrind thread ID of the created thread.
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @return DRD thread ID of the created thread.
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    const ThreadId vg_created)
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DrdThreadId created;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)created && created < DRD_N_THREADS
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && created != DRD_INVALID_THREADID);
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[created].sg_first == NULL);
298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[created].sg_last == NULL);
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Create an initial segment for the newly created thread. */
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread_append_segment(created, DRD_(sg_new)(creator, created));
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return created;
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * after the thread has been created and before any client instructions are run
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * on the newly created thread, e.g. from the handler installed via
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * VG_(track_pre_thread_first_insn)().
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param[in] vg_created Valgrind thread ID of the newly created thread.
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @return DRD thread ID for the new thread.
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)created && created < DRD_N_THREADS
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && created != DRD_INVALID_THREADID);
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[created].stack_max
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = VG_(thread_get_stack_max)(vg_created);
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[created].stack_startup
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = DRD_(g_threadinfo)[created].stack_max;
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[created].stack_min
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = DRD_(g_threadinfo)[created].stack_max;
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[created].stack_min_min
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = DRD_(g_threadinfo)[created].stack_max;
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[created].stack_size
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = VG_(thread_get_stack_size)(vg_created);
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return created;
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void DRD_(thread_delayed_delete)(const DrdThreadId tid)
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int j;
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   DRD_(g_threadinfo)[tid].posix_thread_exists = False;
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   DRD_(g_threadinfo)[tid].deletion_seq = s_deletion_head++;
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(message)(Vg_DebugMsg, "Adding thread %d to the deletion list\n", tid);
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (s_deletion_head - s_deletion_tail >= s_join_list_vol) {
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (j = 0; j < DRD_N_THREADS; ++j) {
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (DRD_(IsValidDrdThreadId)(j)
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             && DRD_(g_threadinfo)[j].deletion_seq == s_deletion_tail)
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         {
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s_deletion_tail++;
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VG_(message)(Vg_DebugMsg, "Delayed delete of thread %d\n", j);
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DRD_(thread_delete)(j, False);
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * after thread drd_joiner joined thread drd_joinee.
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_new_segment)(drd_joiner);
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_new_segment)(drd_joinee);
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s_trace_fork_join)
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const unsigned msg_size = 256;
380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* msg;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      msg = VG_(malloc)("drd.main.dptj.1", msg_size);
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(msg);
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(snprintf)(msg, msg_size,
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "drd_post_thread_join joiner = %d, joinee = %d",
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    drd_joiner, drd_joinee);
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (joiner)
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* vc;
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ", new vc: %s", vc);
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(free)(vc);
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("%pS", msg);
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(msg);
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!  DRD_(get_check_stack_accesses)())
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               - DRD_(thread_get_stack_size)(drd_joinee),
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               DRD_(thread_get_stack_max)(drd_joinee));
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(clientobj_delete_thread)(drd_joinee);
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   DRD_(thread_delayed_delete)(drd_joinee);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * and accesses this data structure from multiple threads without locking.
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Any conflicting accesses in the range stack_startup..stack_max will be
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ignored.
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_stack_startup)(const DrdThreadId tid,
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    const Addr stack_startup)
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Return the stack pointer for the specified thread. */
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr DRD_(thread_get_stack_min)(const DrdThreadId tid)
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].stack_min;
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return the lowest value that was ever assigned to the stack pointer
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * for the specified thread.
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].stack_min_min;
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Return the top address for the stack of the specified thread. */
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr DRD_(thread_get_stack_max)(const DrdThreadId tid)
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].stack_max;
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Return the maximum stack size for the specified thread. */
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].stack_size;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid)
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].on_alt_stack;
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_on_alt_stack)(const DrdThreadId tid,
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   const Bool on_alt_stack)
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(on_alt_stack == !!on_alt_stack);
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].on_alt_stack = on_alt_stack;
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt DRD_(thread_get_threads_on_alt_stack)(void)
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i, n = 0;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 1; i < DRD_N_THREADS; i++)
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n += DRD_(g_threadinfo)[i].on_alt_stack;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return n;
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Clean up thread-specific data structures.
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
489f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootvoid DRD_(thread_delete)(const DrdThreadId tid, const Bool detached)
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* sg;
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* sg_prev;
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(IsValidDrdThreadId)(tid));
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (sg = DRD_(g_threadinfo)[tid].sg_last; sg; sg = sg_prev) {
498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sg_prev = sg->thr_prev;
499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sg->thr_next = NULL;
500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sg->thr_prev = NULL;
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(sg_put)(sg);
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   DRD_(g_threadinfo)[tid].valid = False;
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].posix_thread_exists = False;
506f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   if (detached)
507f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      DRD_(g_threadinfo)[tid].detached_posix_thread = False;
508f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   else
509f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      tl_assert(!DRD_(g_threadinfo)[tid].detached_posix_thread);
510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(g_threadinfo)[tid].sg_first = NULL;
511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(g_threadinfo)[tid].sg_last = NULL;
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(!DRD_(IsValidDrdThreadId)(tid));
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Called after a thread performed its last memory access and before
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * thread_delete() is called. Note: thread_delete() is only called for
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * joinable threads, not for detached threads.
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_finished)(const DrdThreadId tid)
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(g_threadinfo)[tid].detached_posix_thread)
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * Once a detached thread has finished, its stack is deallocated and
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * should no longer be taken into account when computing the conflict set.
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * For a detached thread, calling pthread_exit() invalidates the
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * POSIX thread ID associated with the detached thread. For joinable
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * POSIX threads however, the POSIX thread ID remains live after the
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * pthread_exit() call until pthread_join() is called.
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(g_threadinfo)[tid].posix_thread_exists = False;
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
546f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/** Called just after fork() in the child process. */
547f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootvoid DRD_(drd_thread_atfork_child)(const DrdThreadId tid)
548f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
549f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   unsigned i;
550f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
551f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 1; i < DRD_N_THREADS; i++)
552f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   {
553f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (i == tid)
554f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root	 continue;
555f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (DRD_(IsValidDrdThreadId(i)))
556f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root	 DRD_(thread_delete)(i, True);
557f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      tl_assert(!DRD_(IsValidDrdThreadId(i)));
558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
559f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
560f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Called just before pthread_cancel(). */
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_pre_cancel)(const DrdThreadId tid)
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (DRD_(thread_get_trace_fork_join)())
569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("[%d] drd_thread_pre_cancel %d",
570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      DRD_(g_drd_running_tid), tid);
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Store the POSIX thread ID for the specified thread.
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @note This function can be called two times for the same thread -- see also
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the comment block preceding the pthread_create() wrapper in
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * drd_pthread_intercepts.c.
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ptid != INVALID_POSIX_THREADID);
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].posix_thread_exists = True;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].pt_threadid         = ptid;
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Returns true for joinable threads and false for detached threads. */
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(thread_get_joinable)(const DrdThreadId tid)
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Store the thread mode: joinable or detached. */
600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* There is a cse related issue in gcc for MIPS. Optimization level
602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    has to be lowered, so cse related optimizations are not
603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    included.*/
604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng __attribute__((optimize("O1")))
605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(!! joinable == joinable);
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Tells DRD that the calling thread is about to enter pthread_create(). */
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Tells DRD that the calling thread has left pthread_create(). */
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_left_pthread_create)(const DrdThreadId tid)
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Obtain the thread number and the user-assigned thread name. */
639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst HChar* DRD_(thread_get_name)(const DrdThreadId tid)
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].name;
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Set the name of the specified thread. */
648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid DRD_(thread_set_name)(const DrdThreadId tid, const HChar* const name)
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (name == NULL || name[0] == 0)
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sizeof(DRD_(g_threadinfo)[tid].name),
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "Thread %d",
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tid);
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sizeof(DRD_(g_threadinfo)[tid].name),
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "Thread %d (%s)",
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tid, name);
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * conflict set.
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(vg_tid != VG_INVALID_THREADID);
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vg_tid != s_vg_running_tid)
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_set_running_tid)(vg_tid,
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   DRD_(VgThreadIdToDrdThreadId)(vg_tid));
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * conflict set.
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_running_tid)(const ThreadId vg_tid,
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  const DrdThreadId drd_tid)
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(vg_tid != VG_INVALID_THREADID);
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(drd_tid != DRD_INVALID_THREADID);
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vg_tid != s_vg_running_tid)
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (s_trace_context_switches
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg,
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Context switch from thread %d to thread %d;"
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      " segments: %llu\n",
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      DRD_(g_drd_running_tid), drd_tid,
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      DRD_(sg_get_segments_alive_count)());
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s_vg_running_tid = vg_tid;
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(g_drd_running_tid) = drd_tid;
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s_context_switch_count++;
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Increase the synchronization nesting counter. Must be called before the
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * client calls a synchronization function.
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint DRD_(thread_enter_synchr)(const DrdThreadId tid)
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(IsValidDrdThreadId)(tid));
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].synchr_nesting++;
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Decrease the synchronization nesting counter. Must be called after the
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * client left a synchronization function.
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint DRD_(thread_leave_synchr)(const DrdThreadId tid)
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(IsValidDrdThreadId)(tid));
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return --DRD_(g_threadinfo)[tid].synchr_nesting;
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Returns the synchronization nesting counter. */
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(IsValidDrdThreadId)(tid));
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(g_threadinfo)[tid].synchr_nesting;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Append a new segment at the end of the segment list. */
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid thread_append_segment(const DrdThreadId tid, Segment* const sg)
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // add at tail
755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sg->thr_prev = DRD_(g_threadinfo)[tid].sg_last;
756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sg->thr_next = NULL;
757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (DRD_(g_threadinfo)[tid].sg_last)
758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(g_threadinfo)[tid].sg_last->thr_next = sg;
759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(g_threadinfo)[tid].sg_last = sg;
760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (DRD_(g_threadinfo)[tid].sg_first == NULL)
761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(g_threadinfo)[tid].sg_first = sg;
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Remove a segment from the segment list of thread threadid, and free the
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * associated memory.
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid thread_discard_segment(const DrdThreadId tid, Segment* const sg)
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sg->thr_prev)
783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sg->thr_prev->thr_next = sg->thr_next;
784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sg->thr_next)
785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sg->thr_next->thr_prev = sg->thr_prev;
786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sg == DRD_(g_threadinfo)[tid].sg_first)
787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(g_threadinfo)[tid].sg_first = sg->thr_next;
788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sg == DRD_(g_threadinfo)[tid].sg_last)
789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(g_threadinfo)[tid].sg_last = sg->thr_prev;
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(sg_put)(sg);
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Returns a pointer to the vector clock of the most recent segment associated
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * with thread 'tid'.
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Segment* latest_sg;
804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   latest_sg = DRD_(g_threadinfo)[tid].sg_last;
808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(latest_sg);
809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return &latest_sg->vc;
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return the latest segment of thread 'tid' and increment its reference count.
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Segment* latest_sg;
818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sg);
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   latest_sg = DRD_(g_threadinfo)[tid].sg_last;
823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(latest_sg);
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(sg_put)(*sg);
826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *sg = DRD_(sg_get)(latest_sg);
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Compute the minimum of all latest vector clocks of all threads
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param vc pointer to a vectorclock, holds result upon return.
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool first;
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* latest_sg;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   first = True;
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < DRD_N_THREADS; i++)
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      latest_sg = DRD_(g_threadinfo)[i].sg_last;
845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (latest_sg) {
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (first)
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DRD_(vc_assign)(vc, &latest_sg->vc);
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DRD_(vc_min)(vc, &latest_sg->vc);
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         first = False;
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Compute the maximum of all latest vector clocks of all threads.
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param vc pointer to a vectorclock, holds result upon return.
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool first;
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* latest_sg;
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   first = True;
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < DRD_N_THREADS; i++)
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      latest_sg = DRD_(g_threadinfo)[i].sg_last;
870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (latest_sg) {
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (first)
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DRD_(vc_assign)(vc, &latest_sg->vc);
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DRD_(vc_combine)(vc, &latest_sg->vc);
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         first = False;
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Discard all segments that have a defined order against the latest vector
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * clock of all threads -- these segments can no longer be involved in a
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * data race.
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void thread_discard_ordered_segments(void)
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VectorClock thread_vc_min;
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_discard_ordered_segments_count++;
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(vc_init)(&thread_vc_min, 0, 0);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_compute_minimum_vc)(&thread_vc_min);
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(sg_get_trace)())
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
896436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar *vc_min, *vc_max;
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VectorClock thread_vc_max;
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(vc_init)(&thread_vc_max, 0, 0);
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_compute_maximum_vc)(&thread_vc_max);
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vc_min = DRD_(vc_aprint)(&thread_vc_min);
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vc_max = DRD_(vc_aprint)(&thread_vc_max);
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Discarding ordered segments -- min vc is %s, max vc is %s\n",
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vc_min, vc_max);
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(vc_min);
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(vc_max);
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(vc_cleanup)(&thread_vc_max);
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < DRD_N_THREADS; i++) {
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Segment* sg;
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Segment* sg_next;
914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (sg = DRD_(g_threadinfo)[i].sg_first;
916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           sg && (sg_next = sg->thr_next)
917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sg = sg_next)
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         thread_discard_segment(i, sg);
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(vc_cleanup)(&thread_vc_min);
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * all segments in the set CS are ordered consistently against both sg1 and
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * sg2. The set CS is defined as the set of segments that can immediately
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * precede future segments via inter-thread synchronization operations. In
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * DRD the set CS consists of the latest segment of each thread combined with
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * all segments for which the reference count is strictly greater than one.
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The code below is an optimized version of the following:
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * for (i = 0; i < DRD_N_THREADS; i++)
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * {
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *    Segment* sg;
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *    for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *    {
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *       if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *       {
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          if (   DRD_(vc_lte)(&sg1->vc, &sg->vc)
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *              != DRD_(vc_lte)(&sg2->vc, &sg->vc)
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *              || DRD_(vc_lte)(&sg->vc, &sg1->vc)
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *              != DRD_(vc_lte)(&sg->vc, &sg2->vc))
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          {
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *             return False;
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          }
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *       }
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *    }
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * }
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool thread_consistent_segment_ordering(const DrdThreadId tid,
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               Segment* const sg1,
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               Segment* const sg2)
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(sg1->thr_next);
962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(sg2->thr_next);
963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(sg1->thr_next == sg2);
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < DRD_N_THREADS; i++)
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Segment* sg;
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (sg = DRD_(g_threadinfo)[i].sg_first; sg; sg = sg->thr_next) {
971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!sg->thr_next || DRD_(sg_get_refcnt)(sg) > 1) {
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (sg = DRD_(g_threadinfo)[i].sg_last; sg; sg = sg->thr_prev) {
979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!sg->thr_next || DRD_(sg_get_refcnt)(sg) > 1) {
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Merge all segments that may be merged without triggering false positives
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * or discarding real data races. For the theoretical background of segment
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * and Koen De Bosschere. Bounding the number of segment histories during
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * data race detection. Parallel Computing archive, Volume 28, Issue 9,
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * pp 1221-1238, September 2002. This paper contains a proof that merging
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * consecutive segments for which the property equiv(s1,s2) holds can be
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * merged without reducing the accuracy of datarace detection. Furthermore
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * it is also proven that the total number of all segments will never grow
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * every time a new segment is created. The property equiv(s1, s2) is defined
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * clocks of segments s and s1 are ordered in the same way as those of segments
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * s and s2. The set CS is defined as the set of existing segments s that have
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the potential to conflict with not yet created segments, either because the
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * segment s is the latest segment of a thread or because it can become the
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * immediate predecessor of a new segment due to a synchronization operation.
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void thread_merge_segments(void)
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_new_segments_since_last_merge = 0;
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < DRD_N_THREADS; i++)
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Segment* sg;
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (sg = DRD_(g_threadinfo)[i].sg_first; sg; sg = sg->thr_next) {
1024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (DRD_(sg_get_refcnt)(sg) == 1 && sg->thr_next) {
1025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Segment* const sg_next = sg->thr_next;
1026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (DRD_(sg_get_refcnt)(sg_next) == 1
1027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                && sg_next->thr_next
1028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                && thread_consistent_segment_ordering(i, sg, sg_next))
1029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            {
1030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Merge sg and sg_next into sg. */
1031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DRD_(sg_merge)(sg, sg_next);
1032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               thread_discard_segment(i, sg_next);
1033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create a new segment for the specified thread, and discard any segments
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * that cannot cause races anymore.
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_new_segment)(const DrdThreadId tid)
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* last_sg;
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* new_sg;
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   last_sg = DRD_(g_threadinfo)[tid].sg_last;
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new_sg = DRD_(sg_new)(tid, tid);
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread_append_segment(tid, new_sg);
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tid == DRD_(g_drd_running_tid) && last_sg)
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s_update_conflict_set_new_sg_count++;
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s_segment_merging
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thread_discard_ordered_segments();
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thread_merge_segments();
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Call this function after thread 'joiner' joined thread 'joinee'. */
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(joiner != joinee);
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && joiner != DRD_INVALID_THREADID);
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && joinee != DRD_INVALID_THREADID);
1083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[joiner].sg_first);
1084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[joiner].sg_last);
1085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[joinee].sg_first);
1086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[joinee].sg_last);
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(sg_get_trace)())
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1090436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar *str1, *str2;
1091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      str1 = DRD_(vc_aprint)(DRD_(thread_get_vc)(joiner));
1092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      str2 = DRD_(vc_aprint)(DRD_(thread_get_vc)(joinee));
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   str1, str2);
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(str1);
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(str2);
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (joiner == DRD_(g_drd_running_tid)) {
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VectorClock old_vc;
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(joiner));
1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(vc_combine)(DRD_(thread_get_vc)(joiner),
1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       DRD_(thread_get_vc)(joinee));
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_update_conflict_set)(joiner, &old_vc);
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s_update_conflict_set_join_count++;
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(vc_cleanup)(&old_vc);
1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
1108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(vc_combine)(DRD_(thread_get_vc)(joiner),
1109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       DRD_(thread_get_vc)(joinee));
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread_discard_ordered_segments();
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (DRD_(sg_get_trace)()) {
1115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* str;
1116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      str = DRD_(vc_aprint)(DRD_(thread_get_vc)(joiner));
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(str);
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Update the vector clock of the last segment of thread tid with the
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the vector clock of segment sg.
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const VectorClock* const vc = &sg->vc;
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[tid].sg_first);
1134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(DRD_(g_threadinfo)[tid].sg_last);
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sg);
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(vc);
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (tid != sg->tid) {
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VectorClock old_vc;
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(tid));
1142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(vc_combine)(DRD_(thread_get_vc)(tid), vc);
1143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (DRD_(sg_get_trace)()) {
1144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar *str1, *str2;
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         str1 = DRD_(vc_aprint)(&old_vc);
1146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         str2 = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(free)(str1);
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(free)(str2);
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thread_discard_ordered_segments();
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_update_conflict_set)(tid, &old_vc);
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s_update_conflict_set_sync_count++;
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(vc_cleanup)(&old_vc);
1158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
1159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tl_assert(DRD_(vc_lte)(vc, DRD_(thread_get_vc)(tid)));
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create a new segment for thread tid and update the vector clock of the last
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * segment of this thread with the the vector clock of segment sg. Call this
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * function after thread tid had to wait because of thread synchronization
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * until the memory accesses in the segment sg finished.
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sg);
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread_append_segment(tid, DRD_(sg_new)(tid, tid));
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread_combine_vc_sync(tid, sg);
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s_segment_merging
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thread_discard_ordered_segments();
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thread_merge_segments();
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Call this function whenever a thread is no longer using the memory
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * increase.
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Segment* p;
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (p = DRD_(g_sg_list); p; p = p->g_next)
1198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   DRD_(bm_clear)(DRD_(g_conflict_set), a1, a2);
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Specify whether memory loads should be recorded. */
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(enabled == !! enabled);
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Specify whether memory stores should be recorded. */
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(enabled == !! enabled);
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Print the segment information for all threads.
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function is only used for debugging purposes.
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_print_all)(void)
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* p;
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < DRD_N_THREADS; i++)
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = DRD_(g_threadinfo)[i].sg_first;
1236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (p) {
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("**************\n"
1238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     "* thread %3d (%d/%d/%d/%d/0x%lx/%d) *\n"
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "**************\n",
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     i,
1241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     DRD_(g_threadinfo)[i].valid,
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DRD_(g_threadinfo)[i].vg_thread_exists,
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DRD_(g_threadinfo)[i].vg_threadid,
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DRD_(g_threadinfo)[i].posix_thread_exists,
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DRD_(g_threadinfo)[i].pt_threadid,
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DRD_(g_threadinfo)[i].detached_posix_thread);
1247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for ( ; p; p = p->thr_next)
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DRD_(sg_print)(p);
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Show a call stack involved in a data race. */
1254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void show_call_stack(const DrdThreadId tid, ExeContext* const callstack)
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (vg_tid != VG_INVALID_THREADID) {
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (callstack)
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(pp_ExeContext)(callstack);
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
1264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!VG_(clo_xml))
1265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(message)(Vg_UserMsg,
1266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      "   (thread finished, call stack no longer available)\n");
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Print information about the segments involved in a data race. */
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthread_report_conflicting_segments_segment(const DrdThreadId tid,
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           const Addr addr,
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           const SizeT size,
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           const BmAccessTypeT access_type,
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           const Segment* const p)
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(p);
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < DRD_N_THREADS; i++) {
1285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i != tid) {
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Segment* q;
1287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (q = DRD_(g_threadinfo)[i].sg_last; q; q = q->thr_prev) {
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * Since q iterates over the segments of thread i in order of
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * decreasing vector clocks, if q->vc <= p->vc, then
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * q->next->vc <= p->vc will also hold. Hence, break out of the
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * loop once this condition is met.
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             */
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DRD_(vc_lte)(&q->vc, &p->vc))
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (!DRD_(vc_lte)(&p->vc, &q->vc)) {
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
1299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              access_type)) {
1300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Segment* q_next;
1301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tl_assert(q->stacktrace);
1303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  if (VG_(clo_xml))
1304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     VG_(printf_xml)("  <other_segment_start>\n");
1305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  else
1306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     VG_(message)(Vg_UserMsg,
1307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  "Other segment start (thread %d)\n", i);
1308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  show_call_stack(i, q->stacktrace);
1309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  if (VG_(clo_xml))
1310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     VG_(printf_xml)("  </other_segment_start>\n"
1311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     "  <other_segment_end>\n");
1312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  else
1313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     VG_(message)(Vg_UserMsg,
1314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  "Other segment end (thread %d)\n", i);
1315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  q_next = q->thr_next;
1316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  show_call_stack(i, q_next ? q_next->stacktrace : 0);
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  if (VG_(clo_xml))
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     VG_(printf_xml)("  </other_segment_end>\n");
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Print information about all segments involved in a data race. */
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              const Addr addr,
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              const SizeT size,
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              const BmAccessTypeT access_type)
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* p;
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (p = DRD_(g_threadinfo)[tid].sg_first; p; p = p->thr_next) {
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         thread_report_conflicting_segments_segment(tid, addr, size,
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    access_type, p);
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Verify whether the conflict set for thread tid is up to date. Only perform
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static int do_verify_conflict_set = -1;
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool result;
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap* computed_conflict_set = 0;
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (do_verify_conflict_set < 0)
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (do_verify_conflict_set == 0)
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread_compute_conflict_set(&computed_conflict_set, tid);
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (! result)
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("actual conflict set:\n");
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_print)(DRD_(g_conflict_set));
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("computed conflict set:\n");
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_print)(computed_conflict_set);
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(bm_delete)(computed_conflict_set);
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return result;
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Compute the conflict set: a bitmap that represents the union of all memory
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * accesses of all segments that are unordered to the current segment of the
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * thread tid.
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void thread_compute_conflict_set(struct bitmap** conflict_set,
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        const DrdThreadId tid)
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* p;
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(tid == DRD_(g_drd_running_tid));
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_compute_conflict_set_count++;
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_conflict_set_bitmap_creation_count
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -= DRD_(bm_get_bitmap_creation_count)();
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_conflict_set_bitmap2_creation_count
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -= DRD_(bm_get_bitmap2_creation_count)();
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (*conflict_set) {
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_cleanup)(*conflict_set);
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_init)(*conflict_set);
1398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *conflict_set = DRD_(bm_new)();
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (s_trace_conflict_set) {
1403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* str;
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "computing conflict set for thread %d with vc %s\n",
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   tid, str);
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(str);
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p = DRD_(g_threadinfo)[tid].sg_last;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned j;
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (s_trace_conflict_set) {
1417436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* vc;
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vc = DRD_(vc_aprint)(&p->vc);
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      tid, vc);
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(free)(vc);
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (j = 0; j < DRD_N_THREADS; j++) {
1426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (j != tid && DRD_(IsValidDrdThreadId)(j)) {
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Segment* q;
1428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (q = DRD_(g_threadinfo)[j].sg_last; q; q = q->thr_prev) {
1430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (!DRD_(vc_lte)(&q->vc, &p->vc)
1431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   && !DRD_(vc_lte)(&p->vc, &q->vc)) {
1432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  if (s_trace_conflict_set) {
1433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     HChar* str;
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     str = DRD_(vc_aprint)(&q->vc);
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VG_(message)(Vg_DebugMsg,
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "conflict set: [%d] merging segment %s\n",
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  j, str);
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VG_(free)(str);
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
1442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
1443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  if (s_trace_conflict_set) {
1444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     HChar* str;
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     str = DRD_(vc_aprint)(&q->vc);
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VG_(message)(Vg_DebugMsg,
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "conflict set: [%d] ignoring segment %s\n",
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  j, str);
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VG_(free)(str);
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_conflict_set_bitmap_creation_count
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      += DRD_(bm_get_bitmap_creation_count)();
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_conflict_set_bitmap2_creation_count
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      += DRD_(bm_get_bitmap2_creation_count)();
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (s_trace_conflict_set_bm) {
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_print)(*conflict_set);
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Update the conflict set after the vector clock of thread tid has been
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * updated from old_vc to its current value, either because a new segment has
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * been created or because of a synchronization operation.
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      const VectorClock* const old_vc)
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const VectorClock* new_vc;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Segment* p;
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned j;
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid != DRD_INVALID_THREADID);
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(old_vc);
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(tid == DRD_(g_drd_running_tid));
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(g_conflict_set));
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (s_trace_conflict_set) {
1489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* str;
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "updating conflict set for thread %d with vc %s\n",
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   tid, str);
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(str);
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   new_vc = DRD_(thread_get_vc)(tid);
1499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(DRD_(vc_lte)(old_vc, new_vc));
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(bm_unmark)(DRD_(g_conflict_set));
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < DRD_N_THREADS; j++)
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Segment* q;
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (q = DRD_(g_threadinfo)[j].sg_last;
1511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           q && !DRD_(vc_lte)(&q->vc, new_vc);
1512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           q = q->thr_prev) {
1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         const Bool included_in_old_conflict_set
1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            = !DRD_(vc_lte)(old_vc, &q->vc);
1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         const Bool included_in_new_conflict_set
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            = !DRD_(vc_lte)(new_vc, &q->vc);
1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (UNLIKELY(s_trace_conflict_set)) {
1519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HChar* str;
1520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            str = DRD_(vc_aprint)(&q->vc);
1522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VG_(message)(Vg_DebugMsg,
1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         "conflict set: [%d] %s segment %s\n", j,
1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         included_in_old_conflict_set
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         != included_in_new_conflict_set
1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         ? "merging" : "ignoring", str);
1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VG_(free)(str);
1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (included_in_old_conflict_set != included_in_new_conflict_set)
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for ( ; q && !DRD_(vc_lte)(&q->vc, old_vc); q = q->thr_prev) {
1534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         const Bool included_in_old_conflict_set
1535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            = !DRD_(vc_lte)(old_vc, &q->vc);
1536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         const Bool included_in_new_conflict_set
1537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            = !DRD_(vc_lte)(&q->vc, new_vc)
1538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            && !DRD_(vc_lte)(new_vc, &q->vc);
1539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (UNLIKELY(s_trace_conflict_set)) {
1541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HChar* str;
1542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            str = DRD_(vc_aprint)(&q->vc);
1544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VG_(message)(Vg_DebugMsg,
1545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         "conflict set: [%d] %s segment %s\n", j,
1546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         included_in_old_conflict_set
1547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         != included_in_new_conflict_set
1548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         ? "merging" : "ignoring", str);
1549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VG_(free)(str);
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (included_in_old_conflict_set != included_in_new_conflict_set)
1552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p = DRD_(g_threadinfo)[tid].sg_last;
1559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (j = 0; j < DRD_N_THREADS; j++) {
1560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (j != tid && DRD_(IsValidDrdThreadId)(j)) {
1561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Segment* q;
1562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (q = DRD_(g_threadinfo)[j].sg_last;
1563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              q && !DRD_(vc_lte)(&q->vc, &p->vc);
1564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              q = q->thr_prev) {
1565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (!DRD_(vc_lte)(&p->vc, &q->vc))
1566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_update_conflict_set_count++;
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s_trace_conflict_set_bm)
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_print)(DRD_(g_conflict_set));
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Report the number of context switches performed. */
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_context_switch_count)(void)
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_context_switch_count;
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Report the number of ordered segments that have been discarded. */
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_discard_ordered_segments_count)(void)
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_discard_ordered_segments_count;
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Return how many times the conflict set has been updated entirely. */
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_compute_conflict_set_count)()
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_compute_conflict_set_count;
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Return how many times the conflict set has been updated partially. */
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_update_conflict_set_count)(void)
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_update_conflict_set_count;
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return how many times the conflict set has been updated partially
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * because a new segment has been created.
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_update_conflict_set_new_sg_count;
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return how many times the conflict set has been updated partially
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * because of combining vector clocks due to synchronization operations
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * other than reader/writer lock or barrier operations.
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_update_conflict_set_sync_count)(void)
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_update_conflict_set_sync_count;
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return how many times the conflict set has been updated partially
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * because of thread joins.
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_update_conflict_set_join_count)(void)
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_update_conflict_set_join_count;
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return the number of first-level bitmaps that have been created during
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * conflict set updates.
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_conflict_set_bitmap_creation_count;
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return the number of second-level bitmaps that have been created during
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * conflict set updates.
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_conflict_set_bitmap2_creation_count;
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1654