blob: ef52f56378829f109db207de609ab8e3f93056ef [file] [log] [blame]
bartbedfd232009-03-26 19:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardjaf44c822007-11-25 14:01:38 +00002/*
bart86562bd2009-02-16 19:43:56 +00003 This file is part of drd, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00004
bart86562bd2009-02-16 19:43:56 +00005 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
sewardjaf44c822007-11-25 14:01:38 +00006
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
26#include "drd_error.h"
bart09dc13f2009-02-14 15:13:31 +000027#include "drd_barrier.h"
bartd2c5eae2009-02-21 15:27:04 +000028#include "drd_clientobj.h"
bart09dc13f2009-02-14 15:13:31 +000029#include "drd_cond.h"
30#include "drd_mutex.h"
sewardjaf44c822007-11-25 14:01:38 +000031#include "drd_segment.h"
bart09dc13f2009-02-14 15:13:31 +000032#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000033#include "drd_suppression.h"
34#include "drd_thread.h"
bart82195c12008-04-13 17:35:08 +000035#include "pub_tool_vki.h"
sewardjaf44c822007-11-25 14:01:38 +000036#include "pub_tool_basics.h" // Addr, SizeT
37#include "pub_tool_errormgr.h" // VG_(unique_error)()
38#include "pub_tool_libcassert.h" // tl_assert()
39#include "pub_tool_libcbase.h" // VG_(strlen)()
40#include "pub_tool_libcprint.h" // VG_(printf)()
bart82195c12008-04-13 17:35:08 +000041#include "pub_tool_libcproc.h" // VG_(getenv)()
sewardjaf44c822007-11-25 14:01:38 +000042#include "pub_tool_machine.h"
43#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
sewardj85642922008-01-14 11:54:56 +000044#include "pub_tool_options.h" // VG_(clo_backtrace_size)
sewardjaf44c822007-11-25 14:01:38 +000045#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
46
bart32ba2082008-06-05 08:53:42 +000047
sewardjaf44c822007-11-25 14:01:38 +000048
bart324a23b2009-02-15 12:14:52 +000049/* Local functions. */
sewardjaf44c822007-11-25 14:01:38 +000050
bart86a87df2009-03-04 19:26:47 +000051static void thread_append_segment(const DrdThreadId tid, Segment* const sg);
52static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
53static void thread_compute_conflict_set(struct bitmap** conflict_set,
54 const DrdThreadId tid);
bart8f822af2009-06-08 18:20:42 +000055static Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
sewardjaf44c822007-11-25 14:01:38 +000056
57
bart324a23b2009-02-15 12:14:52 +000058/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000059
bart86a87df2009-03-04 19:26:47 +000060static ULong s_context_switch_count;
61static ULong s_discard_ordered_segments_count;
bart54803fe2009-06-21 09:26:27 +000062static ULong s_compute_conflict_set_count;
bart86a87df2009-03-04 19:26:47 +000063static ULong s_update_conflict_set_count;
bart86a87df2009-03-04 19:26:47 +000064static ULong s_conflict_set_bitmap_creation_count;
65static ULong s_conflict_set_bitmap2_creation_count;
66static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bart324a23b2009-02-15 12:14:52 +000067DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
68ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
69struct bitmap* DRD_(g_conflict_set);
bart86a87df2009-03-04 19:26:47 +000070static Bool s_trace_context_switches = False;
71static Bool s_trace_conflict_set = False;
bart8f822af2009-06-08 18:20:42 +000072static Bool s_trace_conflict_set_bm = False;
bart86a87df2009-03-04 19:26:47 +000073static Bool s_trace_fork_join = False;
74static Bool s_segment_merging = True;
bart8f822af2009-06-08 18:20:42 +000075static Bool s_new_segments_since_last_merge;
76static int s_segment_merge_interval = 64;
sewardjaf44c822007-11-25 14:01:38 +000077
78
bart324a23b2009-02-15 12:14:52 +000079/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000080
bart86a87df2009-03-04 19:26:47 +000081/** Enables/disables context switch tracing. */
bart62a784c2009-02-15 13:11:14 +000082void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000083{
bartbedfd232009-03-26 19:07:15 +000084 tl_assert(t == False || t == True);
85 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000086}
87
bart86a87df2009-03-04 19:26:47 +000088/** Enables/disables conflict set tracing. */
bart62a784c2009-02-15 13:11:14 +000089void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000090{
bartbedfd232009-03-26 19:07:15 +000091 tl_assert(t == False || t == True);
92 s_trace_conflict_set = t;
bart26f73e12008-02-24 18:37:08 +000093}
94
bart8f822af2009-06-08 18:20:42 +000095/** Enables/disables conflict set bitmap tracing. */
96void DRD_(thread_trace_conflict_set_bm)(const Bool t)
97{
98 tl_assert(t == False || t == True);
99 s_trace_conflict_set_bm = t;
100}
101
bart86a87df2009-03-04 19:26:47 +0000102/** Report whether fork/join tracing is enabled. */
bart09dc13f2009-02-14 15:13:31 +0000103Bool DRD_(thread_get_trace_fork_join)(void)
104{
bartbedfd232009-03-26 19:07:15 +0000105 return s_trace_fork_join;
bart09dc13f2009-02-14 15:13:31 +0000106}
107
bart86a87df2009-03-04 19:26:47 +0000108/** Enables/disables fork/join tracing. */
bart09dc13f2009-02-14 15:13:31 +0000109void DRD_(thread_set_trace_fork_join)(const Bool t)
110{
bartbedfd232009-03-26 19:07:15 +0000111 tl_assert(t == False || t == True);
112 s_trace_fork_join = t;
bart09dc13f2009-02-14 15:13:31 +0000113}
114
bart86a87df2009-03-04 19:26:47 +0000115/** Enables/disables segment merging. */
bart62a784c2009-02-15 13:11:14 +0000116void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000117{
bartbedfd232009-03-26 19:07:15 +0000118 tl_assert(m == False || m == True);
119 s_segment_merging = m;
barta9c37392008-03-22 09:38:48 +0000120}
121
bart8f822af2009-06-08 18:20:42 +0000122/** Get the segment merging interval. */
123int DRD_(thread_get_segment_merge_interval)(void)
124{
125 return s_segment_merge_interval;
126}
127
128/** Set the segment merging interval. */
129void DRD_(thread_set_segment_merge_interval)(const int i)
130{
131 s_segment_merge_interval = i;
132}
133
sewardjaf44c822007-11-25 14:01:38 +0000134/**
bart86a87df2009-03-04 19:26:47 +0000135 * Convert Valgrind's ThreadId into a DrdThreadId.
136 *
137 * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
138 * Valgrind ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000139 */
bart62a784c2009-02-15 13:11:14 +0000140DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000141{
bartbedfd232009-03-26 19:07:15 +0000142 int i;
sewardjaf44c822007-11-25 14:01:38 +0000143
bartbedfd232009-03-26 19:07:15 +0000144 if (tid == VG_INVALID_THREADID)
145 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000146
bartbedfd232009-03-26 19:07:15 +0000147 for (i = 1; i < DRD_N_THREADS; i++)
148 {
149 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
150 && DRD_(g_threadinfo)[i].vg_threadid == tid)
151 {
152 return i;
153 }
154 }
sewardjaf44c822007-11-25 14:01:38 +0000155
bartbedfd232009-03-26 19:07:15 +0000156 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000157}
158
bart86a87df2009-03-04 19:26:47 +0000159/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000160static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000161{
bartbedfd232009-03-26 19:07:15 +0000162 int i;
sewardjaf44c822007-11-25 14:01:38 +0000163
bartbedfd232009-03-26 19:07:15 +0000164 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000165
bartbedfd232009-03-26 19:07:15 +0000166 for (i = 1; i < DRD_N_THREADS; i++)
167 {
168 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
169 && DRD_(g_threadinfo)[i].posix_thread_exists == False
170 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
171 {
172 tl_assert(! DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000173
bartbedfd232009-03-26 19:07:15 +0000174 DRD_(g_threadinfo)[i].vg_thread_exists = True;
175 DRD_(g_threadinfo)[i].vg_threadid = tid;
176 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
177 DRD_(g_threadinfo)[i].stack_min = 0;
178 DRD_(g_threadinfo)[i].stack_min_min = 0;
179 DRD_(g_threadinfo)[i].stack_startup = 0;
180 DRD_(g_threadinfo)[i].stack_max = 0;
bartd45d9952009-05-31 18:53:54 +0000181 DRD_(thread_set_name)(i, "");
182 DRD_(g_threadinfo)[i].is_recording_loads = True;
183 DRD_(g_threadinfo)[i].is_recording_stores = True;
bartbedfd232009-03-26 19:07:15 +0000184 DRD_(g_threadinfo)[i].synchr_nesting = 0;
185 tl_assert(DRD_(g_threadinfo)[i].first == 0);
186 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000187
bartbedfd232009-03-26 19:07:15 +0000188 tl_assert(DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000189
bartbedfd232009-03-26 19:07:15 +0000190 return i;
191 }
192 }
sewardjaf44c822007-11-25 14:01:38 +0000193
bartbedfd232009-03-26 19:07:15 +0000194 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000195
bartbedfd232009-03-26 19:07:15 +0000196 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000197}
198
bart86a87df2009-03-04 19:26:47 +0000199/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000200DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000201{
bartbedfd232009-03-26 19:07:15 +0000202 int i;
sewardjaf44c822007-11-25 14:01:38 +0000203
bartbedfd232009-03-26 19:07:15 +0000204 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000205
bartbedfd232009-03-26 19:07:15 +0000206 for (i = 1; i < DRD_N_THREADS; i++)
207 {
208 if (DRD_(g_threadinfo)[i].posix_thread_exists
209 && DRD_(g_threadinfo)[i].pt_threadid == tid)
210 {
211 return i;
212 }
213 }
214 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000215}
216
bart86a87df2009-03-04 19:26:47 +0000217/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000218ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000219{
bartbedfd232009-03-26 19:07:15 +0000220 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
221 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000222
bartbedfd232009-03-26 19:07:15 +0000223 return (DRD_(g_threadinfo)[tid].vg_thread_exists
224 ? DRD_(g_threadinfo)[tid].vg_threadid
225 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000226}
227
bart8f822af2009-06-08 18:20:42 +0000228#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart324a23b2009-02-15 12:14:52 +0000229/**
230 * Sanity check of the doubly linked list of segments referenced by a
231 * ThreadInfo struct.
232 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000233 */
bart62a784c2009-02-15 13:11:14 +0000234static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000235{
bartbedfd232009-03-26 19:07:15 +0000236 Segment* p;
bart8f822af2009-06-08 18:20:42 +0000237
bartbedfd232009-03-26 19:07:15 +0000238 for (p = ti->first; p; p = p->next) {
239 if (p->next && p->next->prev != p)
240 return False;
241 if (p->next == 0 && p != ti->last)
242 return False;
243 }
244 for (p = ti->last; p; p = p->prev) {
245 if (p->prev && p->prev->next != p)
246 return False;
247 if (p->prev == 0 && p != ti->first)
248 return False;
249 }
250 return True;
sewardjaf44c822007-11-25 14:01:38 +0000251}
bart23d3a4e2008-04-05 12:53:00 +0000252#endif
sewardjaf44c822007-11-25 14:01:38 +0000253
bart439c55f2009-02-15 10:38:37 +0000254/**
255 * Create the first segment for a newly started thread.
256 *
257 * This function is called from the handler installed via
258 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
259 * from the context of the creator thread, before the new thread has been
260 * created.
bart86a87df2009-03-04 19:26:47 +0000261 *
262 * @param[in] creator DRD thread ID of the creator thread.
263 * @param[in] vg_created Valgrind thread ID of the created thread.
264 *
265 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000266 */
bart62a784c2009-02-15 13:11:14 +0000267DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
268 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000269{
bartbedfd232009-03-26 19:07:15 +0000270 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000271
bartbedfd232009-03-26 19:07:15 +0000272 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
273 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
274 tl_assert(0 <= (int)created && created < DRD_N_THREADS
275 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000276
bartbedfd232009-03-26 19:07:15 +0000277 tl_assert(DRD_(g_threadinfo)[created].first == 0);
278 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart8f822af2009-06-08 18:20:42 +0000279 /* Create an initial segment for the newly created thread. */
bartbedfd232009-03-26 19:07:15 +0000280 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000281
bartbedfd232009-03-26 19:07:15 +0000282 return created;
sewardjaf44c822007-11-25 14:01:38 +0000283}
284
bart439c55f2009-02-15 10:38:37 +0000285/**
bart86a87df2009-03-04 19:26:47 +0000286 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
287 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000288 * on the newly created thread, e.g. from the handler installed via
289 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000290 *
291 * @param[in] vg_created Valgrind thread ID of the newly created thread.
292 *
293 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000294 */
bart62a784c2009-02-15 13:11:14 +0000295DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000296{
bartbedfd232009-03-26 19:07:15 +0000297 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000298
bartbedfd232009-03-26 19:07:15 +0000299 tl_assert(0 <= (int)created && created < DRD_N_THREADS
300 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000301
bartbedfd232009-03-26 19:07:15 +0000302 DRD_(g_threadinfo)[created].stack_max
303 = VG_(thread_get_stack_max)(vg_created);
304 DRD_(g_threadinfo)[created].stack_startup
305 = DRD_(g_threadinfo)[created].stack_max;
306 DRD_(g_threadinfo)[created].stack_min
307 = DRD_(g_threadinfo)[created].stack_max;
308 DRD_(g_threadinfo)[created].stack_min_min
309 = DRD_(g_threadinfo)[created].stack_max;
310 DRD_(g_threadinfo)[created].stack_size
311 = VG_(thread_get_stack_size)(vg_created);
312 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000313
bartbedfd232009-03-26 19:07:15 +0000314 return created;
bart439c55f2009-02-15 10:38:37 +0000315}
bart09dc13f2009-02-14 15:13:31 +0000316
bart324a23b2009-02-15 12:14:52 +0000317/**
318 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
319 * after thread drd_joiner joined thread drd_joinee.
320 */
bart09dc13f2009-02-14 15:13:31 +0000321void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
322{
bartbedfd232009-03-26 19:07:15 +0000323 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
324 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
bart7627be32009-06-06 12:26:05 +0000325
bartbedfd232009-03-26 19:07:15 +0000326 DRD_(thread_new_segment)(drd_joiner);
bart8f822af2009-06-08 18:20:42 +0000327 DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
bart7627be32009-06-06 12:26:05 +0000328 DRD_(thread_new_segment)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000329
bartbedfd232009-03-26 19:07:15 +0000330 if (s_trace_fork_join)
331 {
332 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
333 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
334 const unsigned msg_size = 256;
335 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000336
bartbedfd232009-03-26 19:07:15 +0000337 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
338 tl_assert(msg);
339 VG_(snprintf)(msg, msg_size,
340 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
341 joiner, drd_joiner, joinee, drd_joinee);
342 if (joiner)
343 {
bart8f822af2009-06-08 18:20:42 +0000344 char* vc;
345
346 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
bartbedfd232009-03-26 19:07:15 +0000347 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart8f822af2009-06-08 18:20:42 +0000348 ", new vc: %s", vc);
349 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000350 }
351 VG_(message)(Vg_DebugMsg, "%s", msg);
352 VG_(free)(msg);
353 }
bart09dc13f2009-02-14 15:13:31 +0000354
bartbedfd232009-03-26 19:07:15 +0000355 if (! DRD_(get_check_stack_accesses)())
356 {
357 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
358 - DRD_(thread_get_stack_size)(drd_joinee),
359 DRD_(thread_get_stack_max)(drd_joinee));
360 }
361 DRD_(clientobj_delete_thread)(drd_joinee);
362 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000363}
364
bart324a23b2009-02-15 12:14:52 +0000365/**
366 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
367 * and accesses this data structure from multiple threads without locking.
368 * Any conflicting accesses in the range stack_startup..stack_max will be
369 * ignored.
370 */
bart62a784c2009-02-15 13:11:14 +0000371void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
372 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000373{
bartbedfd232009-03-26 19:07:15 +0000374 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
375 && tid != DRD_INVALID_THREADID);
376 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
377 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
378 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000379}
380
bart86a87df2009-03-04 19:26:47 +0000381/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000382Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000383{
bartbedfd232009-03-26 19:07:15 +0000384 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
385 && tid != DRD_INVALID_THREADID);
386 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000387}
388
bart86a87df2009-03-04 19:26:47 +0000389/**
390 * Return the lowest value that was ever assigned to the stack pointer
391 * for the specified thread.
392 */
bart62a784c2009-02-15 13:11:14 +0000393Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000394{
bartbedfd232009-03-26 19:07:15 +0000395 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
396 && tid != DRD_INVALID_THREADID);
397 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000398}
399
bart86a87df2009-03-04 19:26:47 +0000400/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000401Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000402{
bartbedfd232009-03-26 19:07:15 +0000403 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
404 && tid != DRD_INVALID_THREADID);
405 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000406}
407
bart86a87df2009-03-04 19:26:47 +0000408/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000409SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000410{
bartbedfd232009-03-26 19:07:15 +0000411 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
412 && tid != DRD_INVALID_THREADID);
413 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000414}
415
bart09dc13f2009-02-14 15:13:31 +0000416/**
417 * Clean up thread-specific data structures. Call this just after
418 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000419 */
bart62a784c2009-02-15 13:11:14 +0000420void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000421{
bartbedfd232009-03-26 19:07:15 +0000422 Segment* sg;
423 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000424
bartbedfd232009-03-26 19:07:15 +0000425 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000426
bartbedfd232009-03-26 19:07:15 +0000427 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
428 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
429 {
430 sg_prev = sg->prev;
431 sg->prev = 0;
432 sg->next = 0;
433 DRD_(sg_put)(sg);
434 }
435 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
436 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
437 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
438 DRD_(g_threadinfo)[tid].first = 0;
439 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000440
bartbedfd232009-03-26 19:07:15 +0000441 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000442}
443
bart324a23b2009-02-15 12:14:52 +0000444/**
445 * Called after a thread performed its last memory access and before
446 * thread_delete() is called. Note: thread_delete() is only called for
447 * joinable threads, not for detached threads.
448 */
bart62a784c2009-02-15 13:11:14 +0000449void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000450{
bartbedfd232009-03-26 19:07:15 +0000451 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
452 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000453
bartbedfd232009-03-26 19:07:15 +0000454 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000455
bartbedfd232009-03-26 19:07:15 +0000456 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
457 {
458 /*
459 * Once a detached thread has finished, its stack is deallocated and
460 * should no longer be taken into account when computing the conflict set.
461 */
462 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000463
bartbedfd232009-03-26 19:07:15 +0000464 /*
465 * For a detached thread, calling pthread_exit() invalidates the
466 * POSIX thread ID associated with the detached thread. For joinable
467 * POSIX threads however, the POSIX thread ID remains live after the
468 * pthread_exit() call until pthread_join() is called.
469 */
470 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
471 }
sewardjaf44c822007-11-25 14:01:38 +0000472}
473
bart9b2974a2008-09-27 12:35:31 +0000474/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000475void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000476{
bartbedfd232009-03-26 19:07:15 +0000477 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
478 && tid != DRD_INVALID_THREADID);
479 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000480
bartbedfd232009-03-26 19:07:15 +0000481 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000482}
483
barte7dff242009-04-23 17:12:39 +0000484/**
485 * Store the POSIX thread ID for the specified thread.
486 *
487 * @note This function can be called two times for the same thread -- see also
488 * the comment block preceding the pthread_create() wrapper in
489 * drd_pthread_intercepts.c.
490 */
bart62a784c2009-02-15 13:11:14 +0000491void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000492{
bartbedfd232009-03-26 19:07:15 +0000493 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
494 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000495 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
496 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000497 tl_assert(ptid != INVALID_POSIX_THREADID);
498 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
499 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000500}
501
bart86a87df2009-03-04 19:26:47 +0000502/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000503Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000504{
bartbedfd232009-03-26 19:07:15 +0000505 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
506 && tid != DRD_INVALID_THREADID);
507 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000508}
509
bart86a87df2009-03-04 19:26:47 +0000510/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000511void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000512{
bartbedfd232009-03-26 19:07:15 +0000513 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
514 && tid != DRD_INVALID_THREADID);
515 tl_assert(!! joinable == joinable);
516 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bart8f822af2009-06-08 18:20:42 +0000517
bartbedfd232009-03-26 19:07:15 +0000518 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000519}
520
bartd45d9952009-05-31 18:53:54 +0000521/** Obtain the thread number and the user-assigned thread name. */
522const char* DRD_(thread_get_name)(const DrdThreadId tid)
523{
524 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
525 && tid != DRD_INVALID_THREADID);
526
527 return DRD_(g_threadinfo)[tid].name;
528}
529
530/** Set the name of the specified thread. */
531void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
532{
533 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
534 && tid != DRD_INVALID_THREADID);
535
536 if (name == NULL || name[0] == 0)
537 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
538 sizeof(DRD_(g_threadinfo)[tid].name),
539 "Thread %d",
540 tid);
541 else
542 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
543 sizeof(DRD_(g_threadinfo)[tid].name),
544 "Thread %d (%s)",
545 tid, name);
546 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
547}
548
bart86a87df2009-03-04 19:26:47 +0000549/**
550 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
551 * conflict set.
552 */
bart62a784c2009-02-15 13:11:14 +0000553void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000554{
bartbedfd232009-03-26 19:07:15 +0000555 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000556
bartbedfd232009-03-26 19:07:15 +0000557 if (vg_tid != s_vg_running_tid)
558 {
559 DRD_(thread_set_running_tid)(vg_tid,
560 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
561 }
sewardj8b09d4f2007-12-04 21:27:18 +0000562
bartbedfd232009-03-26 19:07:15 +0000563 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
564 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000565}
566
bart86a87df2009-03-04 19:26:47 +0000567/**
568 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
569 * conflict set.
570 */
bart62a784c2009-02-15 13:11:14 +0000571void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
572 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000573{
bartbedfd232009-03-26 19:07:15 +0000574 tl_assert(vg_tid != VG_INVALID_THREADID);
575 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000576
bartbedfd232009-03-26 19:07:15 +0000577 if (vg_tid != s_vg_running_tid)
578 {
579 if (s_trace_context_switches
580 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
581 {
582 VG_(message)(Vg_DebugMsg,
583 "Context switch from thread %d/%d to thread %d/%d;"
584 " segments: %llu",
585 s_vg_running_tid, DRD_(g_drd_running_tid),
586 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
587 DRD_(sg_get_segments_alive_count)());
588 }
589 s_vg_running_tid = vg_tid;
590 DRD_(g_drd_running_tid) = drd_tid;
591 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
592 s_context_switch_count++;
593 }
sewardj8b09d4f2007-12-04 21:27:18 +0000594
bartbedfd232009-03-26 19:07:15 +0000595 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
596 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000597}
598
bart86a87df2009-03-04 19:26:47 +0000599/**
600 * Increase the synchronization nesting counter. Must be called before the
601 * client calls a synchronization function.
602 */
bart62a784c2009-02-15 13:11:14 +0000603int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000604{
bartbedfd232009-03-26 19:07:15 +0000605 tl_assert(DRD_(IsValidDrdThreadId)(tid));
606 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000607}
608
bart86a87df2009-03-04 19:26:47 +0000609/**
610 * Decrease the synchronization nesting counter. Must be called after the
611 * client left a synchronization function.
612 */
bart62a784c2009-02-15 13:11:14 +0000613int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000614{
bartbedfd232009-03-26 19:07:15 +0000615 tl_assert(DRD_(IsValidDrdThreadId)(tid));
616 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
617 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000618}
619
bart86a87df2009-03-04 19:26:47 +0000620/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000621int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000622{
bartbedfd232009-03-26 19:07:15 +0000623 tl_assert(DRD_(IsValidDrdThreadId)(tid));
624 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000625}
626
bart1a473c72008-03-13 19:03:38 +0000627/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000628static
bart86a87df2009-03-04 19:26:47 +0000629void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000630{
bartbedfd232009-03-26 19:07:15 +0000631 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
632 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000633
634#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
635 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
636#endif
637
bartbedfd232009-03-26 19:07:15 +0000638 sg->prev = DRD_(g_threadinfo)[tid].last;
639 sg->next = 0;
640 if (DRD_(g_threadinfo)[tid].last)
641 DRD_(g_threadinfo)[tid].last->next = sg;
642 DRD_(g_threadinfo)[tid].last = sg;
643 if (DRD_(g_threadinfo)[tid].first == 0)
644 DRD_(g_threadinfo)[tid].first = sg;
bart8f822af2009-06-08 18:20:42 +0000645
646#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
647 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
648#endif
sewardjaf44c822007-11-25 14:01:38 +0000649}
650
bart324a23b2009-02-15 12:14:52 +0000651/**
652 * Remove a segment from the segment list of thread threadid, and free the
653 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000654 */
bart62a784c2009-02-15 13:11:14 +0000655static
bart86a87df2009-03-04 19:26:47 +0000656void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000657{
bartbedfd232009-03-26 19:07:15 +0000658 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
659 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000660
661#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
662 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
663#endif
bart26f73e12008-02-24 18:37:08 +0000664
bartbedfd232009-03-26 19:07:15 +0000665 if (sg->prev)
666 sg->prev->next = sg->next;
667 if (sg->next)
668 sg->next->prev = sg->prev;
669 if (sg == DRD_(g_threadinfo)[tid].first)
670 DRD_(g_threadinfo)[tid].first = sg->next;
671 if (sg == DRD_(g_threadinfo)[tid].last)
672 DRD_(g_threadinfo)[tid].last = sg->prev;
673 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000674
bart8f822af2009-06-08 18:20:42 +0000675#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
676 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
677#endif
sewardjaf44c822007-11-25 14:01:38 +0000678}
679
bart86a87df2009-03-04 19:26:47 +0000680/**
681 * Returns a pointer to the vector clock of the most recent segment associated
682 * with thread 'tid'.
683 */
bart62a784c2009-02-15 13:11:14 +0000684VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000685{
bartbedfd232009-03-26 19:07:15 +0000686 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
687 && tid != DRD_INVALID_THREADID);
688 tl_assert(DRD_(g_threadinfo)[tid].last);
689 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000690}
691
bart324a23b2009-02-15 12:14:52 +0000692/**
693 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000694 */
bart62a784c2009-02-15 13:11:14 +0000695void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000696{
bartbedfd232009-03-26 19:07:15 +0000697 tl_assert(sg);
698 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
699 && tid != DRD_INVALID_THREADID);
700 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000701
bartbedfd232009-03-26 19:07:15 +0000702 DRD_(sg_put)(*sg);
703 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000704}
705
sewardjaf44c822007-11-25 14:01:38 +0000706/**
707 * Compute the minimum of all latest vector clocks of all threads
708 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000709 *
sewardjaf44c822007-11-25 14:01:38 +0000710 * @param vc pointer to a vectorclock, holds result upon return.
711 */
bart62a784c2009-02-15 13:11:14 +0000712static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000713{
bartbedfd232009-03-26 19:07:15 +0000714 unsigned i;
715 Bool first;
716 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000717
bartbedfd232009-03-26 19:07:15 +0000718 first = True;
bart8f822af2009-06-08 18:20:42 +0000719 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000720 {
721 latest_sg = DRD_(g_threadinfo)[i].last;
722 if (latest_sg)
723 {
724 if (first)
725 DRD_(vc_assign)(vc, &latest_sg->vc);
726 else
727 DRD_(vc_min)(vc, &latest_sg->vc);
728 first = False;
729 }
730 }
sewardjaf44c822007-11-25 14:01:38 +0000731}
732
bart86a87df2009-03-04 19:26:47 +0000733/**
734 * Compute the maximum of all latest vector clocks of all threads.
735 *
736 * @param vc pointer to a vectorclock, holds result upon return.
737 */
bart62a784c2009-02-15 13:11:14 +0000738static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000739{
bartbedfd232009-03-26 19:07:15 +0000740 unsigned i;
741 Bool first;
742 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000743
bartbedfd232009-03-26 19:07:15 +0000744 first = True;
bart8f822af2009-06-08 18:20:42 +0000745 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000746 {
747 latest_sg = DRD_(g_threadinfo)[i].last;
748 if (latest_sg)
749 {
750 if (first)
751 DRD_(vc_assign)(vc, &latest_sg->vc);
752 else
753 DRD_(vc_combine)(vc, &latest_sg->vc);
754 first = False;
755 }
756 }
sewardjaf44c822007-11-25 14:01:38 +0000757}
758
759/**
bart5bd9f2d2008-03-03 20:31:58 +0000760 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000761 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000762 * data race.
763 */
bart8f822af2009-06-08 18:20:42 +0000764static void thread_discard_ordered_segments(void)
sewardjaf44c822007-11-25 14:01:38 +0000765{
bartbedfd232009-03-26 19:07:15 +0000766 unsigned i;
767 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000768
bartbedfd232009-03-26 19:07:15 +0000769 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000770
bartbedfd232009-03-26 19:07:15 +0000771 DRD_(vc_init)(&thread_vc_min, 0, 0);
772 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
773 if (DRD_(sg_get_trace)())
774 {
bart8f822af2009-06-08 18:20:42 +0000775 char *vc_min, *vc_max;
bartbedfd232009-03-26 19:07:15 +0000776 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000777
bartbedfd232009-03-26 19:07:15 +0000778 DRD_(vc_init)(&thread_vc_max, 0, 0);
779 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart8f822af2009-06-08 18:20:42 +0000780 vc_min = DRD_(vc_aprint)(&thread_vc_min);
781 vc_max = DRD_(vc_aprint)(&thread_vc_max);
782 VG_(message)(Vg_DebugMsg,
783 "Discarding ordered segments -- min vc is %s, max vc is %s",
784 vc_min, vc_max);
785 VG_(free)(vc_min);
786 VG_(free)(vc_max);
bartbedfd232009-03-26 19:07:15 +0000787 DRD_(vc_cleanup)(&thread_vc_max);
788 }
sewardjaf44c822007-11-25 14:01:38 +0000789
bart8f822af2009-06-08 18:20:42 +0000790 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000791 {
792 Segment* sg;
793 Segment* sg_next;
794 for (sg = DRD_(g_threadinfo)[i].first;
795 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
796 sg = sg_next)
797 {
798 thread_discard_segment(i, sg);
799 }
800 }
801 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000802}
803
bart324a23b2009-02-15 12:14:52 +0000804/**
bart8f822af2009-06-08 18:20:42 +0000805 * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
806 * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
807 * all segments in the set CS are ordered consistently against both sg1 and
808 * sg2. The set CS is defined as the set of segments that can immediately
809 * precede future segments via inter-thread synchronization operations. In
810 * DRD the set CS consists of the latest segment of each thread combined with
811 * all segments for which the reference count is strictly greater than one.
812 * The code below is an optimized version of the following:
813 *
814 * for (i = 0; i < DRD_N_THREADS; i++)
815 * {
816 * Segment* sg;
817 *
818 * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
819 * {
820 * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
821 * {
822 * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
823 * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
824 * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
825 * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
826 * {
827 * return False;
828 * }
829 * }
830 * }
831 * }
832 */
833static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
834 Segment* const sg1,
835 Segment* const sg2)
836{
837 unsigned i;
838
839 tl_assert(sg1->next);
840 tl_assert(sg2->next);
841 tl_assert(sg1->next == sg2);
842 tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
843
844 for (i = 0; i < DRD_N_THREADS; i++)
845 {
846 Segment* sg;
847
848 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
849 {
850 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
851 {
852 if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
853 break;
854 if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
855 return False;
856 }
857 }
858 for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
859 {
860 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
861 {
862 if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
863 break;
864 if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
865 return False;
866 }
867 }
868 }
869 return True;
870}
871
872/**
bart324a23b2009-02-15 12:14:52 +0000873 * Merge all segments that may be merged without triggering false positives
874 * or discarding real data races. For the theoretical background of segment
bart8f822af2009-06-08 18:20:42 +0000875 * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
876 * and Koen De Bosschere. Bounding the number of segment histories during
877 * data race detection. Parallel Computing archive, Volume 28, Issue 9,
878 * pp 1221-1238, September 2002. This paper contains a proof that merging
879 * consecutive segments for which the property equiv(s1,s2) holds can be
880 * merged without reducing the accuracy of datarace detection. Furthermore
881 * it is also proven that the total number of all segments will never grow
882 * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
883 * every time a new segment is created. The property equiv(s1, s2) is defined
884 * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
885 * clocks of segments s and s1 are ordered in the same way as those of segments
886 * s and s2. The set CS is defined as the set of existing segments s that have
887 * the potential to conflict with not yet created segments, either because the
888 * segment s is the latest segment of a thread or because it can become the
889 * immediate predecessor of a new segment due to a synchronization operation.
barta9c37392008-03-22 09:38:48 +0000890 */
891static void thread_merge_segments(void)
892{
bartbedfd232009-03-26 19:07:15 +0000893 unsigned i;
barta9c37392008-03-22 09:38:48 +0000894
bart8f822af2009-06-08 18:20:42 +0000895 s_new_segments_since_last_merge = 0;
896
897 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000898 {
899 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000900
bart8f822af2009-06-08 18:20:42 +0000901#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
902 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
903#endif
barta9c37392008-03-22 09:38:48 +0000904
bartbedfd232009-03-26 19:07:15 +0000905 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000906 {
bartbedfd232009-03-26 19:07:15 +0000907 if (DRD_(sg_get_refcnt)(sg) == 1
908 && sg->next
909 && DRD_(sg_get_refcnt)(sg->next) == 1
bart8f822af2009-06-08 18:20:42 +0000910 && sg->next->next
911 && thread_consistent_segment_ordering(i, sg, sg->next))
bartbedfd232009-03-26 19:07:15 +0000912 {
913 /* Merge sg and sg->next into sg. */
914 DRD_(sg_merge)(sg, sg->next);
915 thread_discard_segment(i, sg->next);
916 }
barta9c37392008-03-22 09:38:48 +0000917 }
barta9c37392008-03-22 09:38:48 +0000918
bart8f822af2009-06-08 18:20:42 +0000919#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
920 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
921#endif
bartbedfd232009-03-26 19:07:15 +0000922 }
barta9c37392008-03-22 09:38:48 +0000923}
924
bart324a23b2009-02-15 12:14:52 +0000925/**
bart324a23b2009-02-15 12:14:52 +0000926 * Create a new segment for the specified thread, and discard any segments
927 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000928 */
bart62a784c2009-02-15 13:11:14 +0000929void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000930{
bart8f822af2009-06-08 18:20:42 +0000931 Segment* last_sg;
bartbedfd232009-03-26 19:07:15 +0000932 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000933
bartbedfd232009-03-26 19:07:15 +0000934 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
935 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000936 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000937
bart8f822af2009-06-08 18:20:42 +0000938 last_sg = DRD_(g_threadinfo)[tid].last;
bartbedfd232009-03-26 19:07:15 +0000939 new_sg = DRD_(sg_new)(tid, tid);
940 thread_append_segment(tid, new_sg);
bart8f822af2009-06-08 18:20:42 +0000941 if (tid == DRD_(g_drd_running_tid) && last_sg)
942 DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
bartd66e3a82008-04-06 15:02:17 +0000943
bart8f822af2009-06-08 18:20:42 +0000944 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000945
bart8f822af2009-06-08 18:20:42 +0000946 if (s_segment_merging
947 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
bartbedfd232009-03-26 19:07:15 +0000948 {
bart8f822af2009-06-08 18:20:42 +0000949 thread_discard_ordered_segments();
bartbedfd232009-03-26 19:07:15 +0000950 thread_merge_segments();
951 }
sewardjaf44c822007-11-25 14:01:38 +0000952}
953
bart26f73e12008-02-24 18:37:08 +0000954/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart8f822af2009-06-08 18:20:42 +0000955void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000956{
bartbedfd232009-03-26 19:07:15 +0000957 tl_assert(joiner != joinee);
958 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
959 && joiner != DRD_INVALID_THREADID);
960 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
961 && joinee != DRD_INVALID_THREADID);
962 tl_assert(DRD_(g_threadinfo)[joiner].last);
963 tl_assert(DRD_(g_threadinfo)[joinee].last);
bart8f822af2009-06-08 18:20:42 +0000964
965 if (DRD_(sg_get_trace)())
966 {
967 char *str1, *str2;
968 str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
969 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
970 VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s",
971 str1, str2);
972 VG_(free)(str1);
973 VG_(free)(str2);
974 }
bartbedfd232009-03-26 19:07:15 +0000975 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
976 &DRD_(g_threadinfo)[joinee].last->vc);
bart8f822af2009-06-08 18:20:42 +0000977 if (DRD_(sg_get_trace)())
978 {
979 char* str;
980 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
981 VG_(message)(Vg_DebugMsg, "After join: %s", str);
982 VG_(free)(str);
983 }
984 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000985
bartbedfd232009-03-26 19:07:15 +0000986 if (joiner == DRD_(g_drd_running_tid))
987 {
988 thread_compute_conflict_set(&DRD_(g_conflict_set), joiner);
989 }
sewardjaf44c822007-11-25 14:01:38 +0000990}
991
bart324a23b2009-02-15 12:14:52 +0000992/**
bart8f822af2009-06-08 18:20:42 +0000993 * Update the vector clock of the last segment of thread tid with the
994 * the vector clock of segment sg. Call this function after thread tid had
995 * to wait because of thread synchronization until the memory accesses in the
996 * segment sg finished.
bart26f73e12008-02-24 18:37:08 +0000997 */
bart8f822af2009-06-08 18:20:42 +0000998void DRD_(thread_combine_vc_sync)(DrdThreadId tid, const Segment* sg)
sewardjaf44c822007-11-25 14:01:38 +0000999{
bart8f822af2009-06-08 18:20:42 +00001000 const VectorClock* const vc = &sg->vc;
1001
bartbedfd232009-03-26 19:07:15 +00001002 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1003 && tid != DRD_INVALID_THREADID);
1004 tl_assert(DRD_(g_threadinfo)[tid].last);
bart8f822af2009-06-08 18:20:42 +00001005 tl_assert(sg);
bartbedfd232009-03-26 19:07:15 +00001006 tl_assert(vc);
bart8f822af2009-06-08 18:20:42 +00001007
1008 if (tid != sg->tid)
1009 {
1010 VectorClock old_vc;
1011
1012 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
1013 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
1014 if (DRD_(sg_get_trace)())
1015 {
1016 char *str1, *str2;
1017 str1 = DRD_(vc_aprint)(&old_vc);
1018 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1019 VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s", tid, str1, str2);
1020 VG_(free)(str1);
1021 VG_(free)(str2);
1022 }
1023 thread_discard_ordered_segments();
1024 DRD_(thread_update_conflict_set)(tid, &old_vc);
1025 DRD_(vc_cleanup)(&old_vc);
1026 }
1027 else
1028 {
1029 tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
1030 }
sewardjaf44c822007-11-25 14:01:38 +00001031}
1032
bart324a23b2009-02-15 12:14:52 +00001033/**
1034 * Call this function whenever a thread is no longer using the memory
1035 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1036 * increase.
bart26f73e12008-02-24 18:37:08 +00001037 */
bart62a784c2009-02-15 13:11:14 +00001038void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +00001039{
bartbedfd232009-03-26 19:07:15 +00001040 DrdThreadId other_user;
1041 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001042
bartbedfd232009-03-26 19:07:15 +00001043 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
1044 other_user = DRD_INVALID_THREADID;
bart8f822af2009-06-08 18:20:42 +00001045 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001046 {
1047 Segment* p;
1048 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +00001049 {
bartbedfd232009-03-26 19:07:15 +00001050 if (other_user == DRD_INVALID_THREADID
1051 && i != DRD_(g_drd_running_tid))
1052 {
bart8f822af2009-06-08 18:20:42 +00001053 if (UNLIKELY(DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2)))
bartbedfd232009-03-26 19:07:15 +00001054 {
1055 other_user = i;
1056 }
1057 continue;
1058 }
bart8f822af2009-06-08 18:20:42 +00001059 DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
sewardjaf44c822007-11-25 14:01:38 +00001060 }
bartbedfd232009-03-26 19:07:15 +00001061 }
sewardjaf44c822007-11-25 14:01:38 +00001062
bartbedfd232009-03-26 19:07:15 +00001063 /*
1064 * If any other thread had accessed memory in [ a1, a2 [, update the
1065 * conflict set.
1066 */
1067 if (other_user != DRD_INVALID_THREADID
1068 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
1069 {
1070 thread_compute_conflict_set(&DRD_(g_conflict_set),
1071 DRD_(thread_get_running_tid)());
1072 }
sewardjaf44c822007-11-25 14:01:38 +00001073}
1074
bartd45d9952009-05-31 18:53:54 +00001075/** Specify whether memory loads should be recorded. */
1076void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001077{
bartbedfd232009-03-26 19:07:15 +00001078 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1079 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001080 tl_assert(enabled == !! enabled);
1081
1082 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +00001083}
1084
bartd45d9952009-05-31 18:53:54 +00001085/** Specify whether memory stores should be recorded. */
1086void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001087{
bartbedfd232009-03-26 19:07:15 +00001088 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1089 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001090 tl_assert(enabled == !! enabled);
1091
1092 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +00001093}
1094
bart86a87df2009-03-04 19:26:47 +00001095/**
1096 * Print the segment information for all threads.
1097 *
1098 * This function is only used for debugging purposes.
1099 */
bart62a784c2009-02-15 13:11:14 +00001100void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +00001101{
bartbedfd232009-03-26 19:07:15 +00001102 unsigned i;
1103 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001104
bart8f822af2009-06-08 18:20:42 +00001105 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001106 {
1107 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +00001108 {
bartbedfd232009-03-26 19:07:15 +00001109 VG_(printf)("**************\n"
1110 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
1111 "**************\n",
1112 i,
1113 DRD_(g_threadinfo)[i].vg_thread_exists,
1114 DRD_(g_threadinfo)[i].vg_threadid,
1115 DRD_(g_threadinfo)[i].posix_thread_exists,
1116 DRD_(g_threadinfo)[i].pt_threadid,
1117 DRD_(g_threadinfo)[i].detached_posix_thread);
1118 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1119 {
1120 DRD_(sg_print)(p);
1121 }
sewardjaf44c822007-11-25 14:01:38 +00001122 }
bartbedfd232009-03-26 19:07:15 +00001123 }
sewardjaf44c822007-11-25 14:01:38 +00001124}
1125
bart86a87df2009-03-04 19:26:47 +00001126/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001127static void show_call_stack(const DrdThreadId tid,
1128 const Char* const msg,
1129 ExeContext* const callstack)
1130{
bartbedfd232009-03-26 19:07:15 +00001131 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +00001132
bartbedfd232009-03-26 19:07:15 +00001133 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +00001134
bartbedfd232009-03-26 19:07:15 +00001135 if (vg_tid != VG_INVALID_THREADID)
1136 {
1137 if (callstack)
1138 {
1139 VG_(pp_ExeContext)(callstack);
1140 }
1141 else
1142 {
1143 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1144 }
1145 }
1146 else
1147 {
1148 VG_(message)(Vg_UserMsg,
1149 " (thread finished, call stack no longer available)");
1150 }
sewardjaf44c822007-11-25 14:01:38 +00001151}
1152
bart86a87df2009-03-04 19:26:47 +00001153/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001154static void
1155thread_report_conflicting_segments_segment(const DrdThreadId tid,
1156 const Addr addr,
1157 const SizeT size,
1158 const BmAccessTypeT access_type,
1159 const Segment* const p)
1160{
bartbedfd232009-03-26 19:07:15 +00001161 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001162
bartbedfd232009-03-26 19:07:15 +00001163 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1164 && tid != DRD_INVALID_THREADID);
1165 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001166
bart8f822af2009-06-08 18:20:42 +00001167 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001168 {
1169 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001170 {
bartbedfd232009-03-26 19:07:15 +00001171 Segment* q;
1172 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1173 {
1174 /*
1175 * Since q iterates over the segments of thread i in order of
1176 * decreasing vector clocks, if q->vc <= p->vc, then
1177 * q->next->vc <= p->vc will also hold. Hence, break out of the
1178 * loop once this condition is met.
1179 */
1180 if (DRD_(vc_lte)(&q->vc, &p->vc))
1181 break;
1182 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1183 {
bart8f822af2009-06-08 18:20:42 +00001184 if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
bartbedfd232009-03-26 19:07:15 +00001185 access_type))
1186 {
1187 tl_assert(q->stacktrace);
1188 show_call_stack(i, "Other segment start",
1189 q->stacktrace);
1190 show_call_stack(i, "Other segment end",
1191 q->next ? q->next->stacktrace : 0);
1192 }
1193 }
1194 }
sewardjaf44c822007-11-25 14:01:38 +00001195 }
bartbedfd232009-03-26 19:07:15 +00001196 }
sewardjaf44c822007-11-25 14:01:38 +00001197}
1198
bart86a87df2009-03-04 19:26:47 +00001199/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001200void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1201 const Addr addr,
1202 const SizeT size,
1203 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001204{
bartbedfd232009-03-26 19:07:15 +00001205 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001206
bartbedfd232009-03-26 19:07:15 +00001207 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1208 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001209
bartbedfd232009-03-26 19:07:15 +00001210 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1211 {
bart8f822af2009-06-08 18:20:42 +00001212 if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
bartbedfd232009-03-26 19:07:15 +00001213 {
1214 thread_report_conflicting_segments_segment(tid, addr, size,
1215 access_type, p);
1216 }
1217 }
sewardjaf44c822007-11-25 14:01:38 +00001218}
sewardjaf44c822007-11-25 14:01:38 +00001219
bart324a23b2009-02-15 12:14:52 +00001220/**
bart8f822af2009-06-08 18:20:42 +00001221 * Verify whether the conflict set for thread tid is up to date. Only perform
1222 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1223 */
1224static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1225{
1226 static int do_verify_conflict_set = -1;
1227 Bool result;
1228 struct bitmap* computed_conflict_set = 0;
1229
1230 if (do_verify_conflict_set < 0)
1231 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1232
1233 if (do_verify_conflict_set == 0)
1234 return True;
1235
1236 thread_compute_conflict_set(&computed_conflict_set, tid);
1237 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1238 if (! result)
1239 {
1240 VG_(printf)("actual conflict set:\n");
1241 DRD_(bm_print)(DRD_(g_conflict_set));
1242 VG_(printf)("\n");
1243 VG_(printf)("computed conflict set:\n");
1244 DRD_(bm_print)(computed_conflict_set);
1245 VG_(printf)("\n");
1246 }
1247 DRD_(bm_delete)(computed_conflict_set);
1248 return result;
1249}
1250
1251/**
1252 * Compute the conflict set: a bitmap that represents the union of all memory
1253 * accesses of all segments that are unordered to the current segment of the
1254 * thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001255 */
bart86a87df2009-03-04 19:26:47 +00001256static void thread_compute_conflict_set(struct bitmap** conflict_set,
1257 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001258{
bartbedfd232009-03-26 19:07:15 +00001259 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001260
bartbedfd232009-03-26 19:07:15 +00001261 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1262 && tid != DRD_INVALID_THREADID);
1263 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001264
bart54803fe2009-06-21 09:26:27 +00001265 s_compute_conflict_set_count++;
bartbedfd232009-03-26 19:07:15 +00001266 s_conflict_set_bitmap_creation_count
1267 -= DRD_(bm_get_bitmap_creation_count)();
1268 s_conflict_set_bitmap2_creation_count
1269 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001270
bartbedfd232009-03-26 19:07:15 +00001271 if (*conflict_set)
1272 {
1273 DRD_(bm_delete)(*conflict_set);
1274 }
1275 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001276
bartbedfd232009-03-26 19:07:15 +00001277 if (s_trace_conflict_set)
1278 {
bart8f822af2009-06-08 18:20:42 +00001279 char* str;
bart26f73e12008-02-24 18:37:08 +00001280
bart8f822af2009-06-08 18:20:42 +00001281 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1282 VG_(message)(Vg_DebugMsg,
1283 "computing conflict set for thread %d/%d with vc %s",
1284 DRD_(DrdThreadIdToVgThreadId)(tid), tid, str);
1285 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001286 }
sewardjaf44c822007-11-25 14:01:38 +00001287
bartbedfd232009-03-26 19:07:15 +00001288 p = DRD_(g_threadinfo)[tid].last;
1289 {
1290 unsigned j;
1291
1292 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001293 {
bart8f822af2009-06-08 18:20:42 +00001294 char* vc;
bartbedfd232009-03-26 19:07:15 +00001295
bart8f822af2009-06-08 18:20:42 +00001296 vc = DRD_(vc_aprint)(&p->vc);
1297 VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s",
1298 tid, vc);
1299 VG_(free)(vc);
bart26f73e12008-02-24 18:37:08 +00001300 }
sewardjaf44c822007-11-25 14:01:38 +00001301
bart8f822af2009-06-08 18:20:42 +00001302 for (j = 0; j < DRD_N_THREADS; j++)
bartbedfd232009-03-26 19:07:15 +00001303 {
1304 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1305 {
bart8f822af2009-06-08 18:20:42 +00001306 Segment* q;
bartbedfd232009-03-26 19:07:15 +00001307 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1308 {
1309 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1310 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1311 {
1312 if (s_trace_conflict_set)
1313 {
bart8f822af2009-06-08 18:20:42 +00001314 char* str;
1315
1316 str = DRD_(vc_aprint)(&q->vc);
1317 VG_(message)(Vg_DebugMsg,
1318 "conflict set: [%d] merging segment %s",
1319 j, str);
1320 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001321 }
bart8f822af2009-06-08 18:20:42 +00001322 DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
bartbedfd232009-03-26 19:07:15 +00001323 }
1324 else
1325 {
1326 if (s_trace_conflict_set)
1327 {
bart8f822af2009-06-08 18:20:42 +00001328 char* str;
1329
1330 str = DRD_(vc_aprint)(&q->vc);
1331 VG_(message)(Vg_DebugMsg,
1332 "conflict set: [%d] ignoring segment %s",
1333 j, str);
1334 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001335 }
1336 }
1337 }
1338 }
1339 }
1340 }
sewardjaf44c822007-11-25 14:01:38 +00001341
bartbedfd232009-03-26 19:07:15 +00001342 s_conflict_set_bitmap_creation_count
1343 += DRD_(bm_get_bitmap_creation_count)();
1344 s_conflict_set_bitmap2_creation_count
1345 += DRD_(bm_get_bitmap2_creation_count)();
1346
bart8f822af2009-06-08 18:20:42 +00001347 if (s_trace_conflict_set_bm)
bartbedfd232009-03-26 19:07:15 +00001348 {
bart8f822af2009-06-08 18:20:42 +00001349 VG_(message)(Vg_DebugMsg, "[%d] new conflict set:", tid);
bartbedfd232009-03-26 19:07:15 +00001350 DRD_(bm_print)(*conflict_set);
bart8f822af2009-06-08 18:20:42 +00001351 VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.", tid);
bartbedfd232009-03-26 19:07:15 +00001352 }
sewardjaf44c822007-11-25 14:01:38 +00001353}
1354
bart8f822af2009-06-08 18:20:42 +00001355/**
1356 * Update the conflict set after the vector clock of thread tid has been
1357 * updated from old_vc to its current value, either because a new segment has
1358 * been created or because of a synchronization operation.
1359 */
1360void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1361 const VectorClock* const old_vc)
1362{
1363 const VectorClock* new_vc;
1364 Segment* p;
1365 unsigned j;
1366
1367 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1368 && tid != DRD_INVALID_THREADID);
1369 tl_assert(old_vc);
1370 tl_assert(tid == DRD_(g_drd_running_tid));
1371 tl_assert(DRD_(g_conflict_set));
1372
1373 if (s_trace_conflict_set)
1374 {
1375 char* str;
1376
1377 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1378 VG_(message)(Vg_DebugMsg,
1379 "updating conflict set for thread %d/%d with vc %s",
1380 DRD_(DrdThreadIdToVgThreadId)(tid), tid, str);
1381 VG_(free)(str);
1382 }
1383
1384 new_vc = &DRD_(g_threadinfo)[tid].last->vc;
1385
1386 DRD_(bm_unmark)(DRD_(g_conflict_set));
1387
1388 for (j = 0; j < DRD_N_THREADS; j++)
1389 {
1390 Segment* q;
1391
1392 if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1393 continue;
1394
1395 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1396 {
1397 const int included_in_old_conflict_set
1398 = ! DRD_(vc_lte)(&q->vc, old_vc)
1399 && ! DRD_(vc_lte)(old_vc, &q->vc);
1400 const int included_in_new_conflict_set
1401 = ! DRD_(vc_lte)(&q->vc, new_vc)
1402 && ! DRD_(vc_lte)(new_vc, &q->vc);
1403 if (included_in_old_conflict_set != included_in_new_conflict_set)
1404 {
1405 if (s_trace_conflict_set)
1406 {
1407 char* str;
1408
1409 str = DRD_(vc_aprint)(&q->vc);
1410 VG_(message)(Vg_DebugMsg,
1411 "conflict set: [%d] merging segment %s", j, str);
1412 VG_(free)(str);
1413 }
1414 DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1415 }
1416 else
1417 {
1418 if (s_trace_conflict_set)
1419 {
1420 char* str;
1421
1422 str = DRD_(vc_aprint)(&q->vc);
1423 VG_(message)(Vg_DebugMsg,
1424 "conflict set: [%d] ignoring segment %s", j, str);
1425 VG_(free)(str);
1426 }
1427 }
1428 }
1429 }
1430
1431 DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1432
1433 p = DRD_(g_threadinfo)[tid].last;
1434 {
1435 for (j = 0; j < DRD_N_THREADS; j++)
1436 {
1437 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1438 {
1439 Segment* q;
1440 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1441 {
1442 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1443 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1444 {
1445 DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1446 }
1447 }
1448 }
1449 }
1450 }
1451
1452 DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1453
bart54803fe2009-06-21 09:26:27 +00001454 s_update_conflict_set_count++;
bart8f822af2009-06-08 18:20:42 +00001455
1456 if (s_trace_conflict_set_bm)
1457 {
1458 VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:", tid);
1459 DRD_(bm_print)(DRD_(g_conflict_set));
1460 VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.", tid);
1461 }
1462
1463 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1464}
1465
bart86a87df2009-03-04 19:26:47 +00001466/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001467ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001468{
bartbedfd232009-03-26 19:07:15 +00001469 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001470}
1471
bart86a87df2009-03-04 19:26:47 +00001472/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001473ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001474{
bartbedfd232009-03-26 19:07:15 +00001475 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001476}
1477
bart54803fe2009-06-21 09:26:27 +00001478/** Return how many times the conflict set has been updated entirely. */
1479ULong DRD_(thread_get_compute_conflict_set_count)()
sewardjaf44c822007-11-25 14:01:38 +00001480{
bart54803fe2009-06-21 09:26:27 +00001481 return s_compute_conflict_set_count;
1482}
1483
1484/** Return how many times the conflict set has been updated partially. */
1485ULong DRD_(thread_get_update_conflict_set_count)(void)
1486{
bartbedfd232009-03-26 19:07:15 +00001487 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001488}
1489
bart86a87df2009-03-04 19:26:47 +00001490/**
1491 * Return the number of first-level bitmaps that have been created during
1492 * conflict set updates.
1493 */
bart62a784c2009-02-15 13:11:14 +00001494ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001495{
bartbedfd232009-03-26 19:07:15 +00001496 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001497}
1498
bart86a87df2009-03-04 19:26:47 +00001499/**
1500 * Return the number of second-level bitmaps that have been created during
1501 * conflict set updates.
1502 */
bart62a784c2009-02-15 13:11:14 +00001503ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001504{
bartbedfd232009-03-26 19:07:15 +00001505 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001506}