blob: 5fc12981d5cff307cad7582df6cd16e858b5eb0a [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;
62static ULong s_update_conflict_set_count;
63static ULong s_conflict_set_new_segment_count;
64static ULong s_conflict_set_combine_vc_count;
65static ULong s_conflict_set_bitmap_creation_count;
66static ULong s_conflict_set_bitmap2_creation_count;
67static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bart324a23b2009-02-15 12:14:52 +000068DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
69ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
70struct bitmap* DRD_(g_conflict_set);
bart86a87df2009-03-04 19:26:47 +000071static Bool s_trace_context_switches = False;
72static Bool s_trace_conflict_set = False;
bart8f822af2009-06-08 18:20:42 +000073static Bool s_trace_conflict_set_bm = False;
bart86a87df2009-03-04 19:26:47 +000074static Bool s_trace_fork_join = False;
75static Bool s_segment_merging = True;
bart8f822af2009-06-08 18:20:42 +000076static Bool s_new_segments_since_last_merge;
77static int s_segment_merge_interval = 64;
sewardjaf44c822007-11-25 14:01:38 +000078
79
bart324a23b2009-02-15 12:14:52 +000080/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000081
bart86a87df2009-03-04 19:26:47 +000082/** Enables/disables context switch tracing. */
bart62a784c2009-02-15 13:11:14 +000083void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000084{
bartbedfd232009-03-26 19:07:15 +000085 tl_assert(t == False || t == True);
86 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000087}
88
bart86a87df2009-03-04 19:26:47 +000089/** Enables/disables conflict set tracing. */
bart62a784c2009-02-15 13:11:14 +000090void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000091{
bartbedfd232009-03-26 19:07:15 +000092 tl_assert(t == False || t == True);
93 s_trace_conflict_set = t;
bart26f73e12008-02-24 18:37:08 +000094}
95
bart8f822af2009-06-08 18:20:42 +000096/** Enables/disables conflict set bitmap tracing. */
97void DRD_(thread_trace_conflict_set_bm)(const Bool t)
98{
99 tl_assert(t == False || t == True);
100 s_trace_conflict_set_bm = t;
101}
102
bart86a87df2009-03-04 19:26:47 +0000103/** Report whether fork/join tracing is enabled. */
bart09dc13f2009-02-14 15:13:31 +0000104Bool DRD_(thread_get_trace_fork_join)(void)
105{
bartbedfd232009-03-26 19:07:15 +0000106 return s_trace_fork_join;
bart09dc13f2009-02-14 15:13:31 +0000107}
108
bart86a87df2009-03-04 19:26:47 +0000109/** Enables/disables fork/join tracing. */
bart09dc13f2009-02-14 15:13:31 +0000110void DRD_(thread_set_trace_fork_join)(const Bool t)
111{
bartbedfd232009-03-26 19:07:15 +0000112 tl_assert(t == False || t == True);
113 s_trace_fork_join = t;
bart09dc13f2009-02-14 15:13:31 +0000114}
115
bart86a87df2009-03-04 19:26:47 +0000116/** Enables/disables segment merging. */
bart62a784c2009-02-15 13:11:14 +0000117void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000118{
bartbedfd232009-03-26 19:07:15 +0000119 tl_assert(m == False || m == True);
120 s_segment_merging = m;
barta9c37392008-03-22 09:38:48 +0000121}
122
bart8f822af2009-06-08 18:20:42 +0000123/** Get the segment merging interval. */
124int DRD_(thread_get_segment_merge_interval)(void)
125{
126 return s_segment_merge_interval;
127}
128
129/** Set the segment merging interval. */
130void DRD_(thread_set_segment_merge_interval)(const int i)
131{
132 s_segment_merge_interval = i;
133}
134
sewardjaf44c822007-11-25 14:01:38 +0000135/**
bart86a87df2009-03-04 19:26:47 +0000136 * Convert Valgrind's ThreadId into a DrdThreadId.
137 *
138 * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
139 * Valgrind ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000140 */
bart62a784c2009-02-15 13:11:14 +0000141DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000142{
bartbedfd232009-03-26 19:07:15 +0000143 int i;
sewardjaf44c822007-11-25 14:01:38 +0000144
bartbedfd232009-03-26 19:07:15 +0000145 if (tid == VG_INVALID_THREADID)
146 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000147
bartbedfd232009-03-26 19:07:15 +0000148 for (i = 1; i < DRD_N_THREADS; i++)
149 {
150 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
151 && DRD_(g_threadinfo)[i].vg_threadid == tid)
152 {
153 return i;
154 }
155 }
sewardjaf44c822007-11-25 14:01:38 +0000156
bartbedfd232009-03-26 19:07:15 +0000157 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000158}
159
bart86a87df2009-03-04 19:26:47 +0000160/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000161static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000162{
bartbedfd232009-03-26 19:07:15 +0000163 int i;
sewardjaf44c822007-11-25 14:01:38 +0000164
bartbedfd232009-03-26 19:07:15 +0000165 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000166
bartbedfd232009-03-26 19:07:15 +0000167 for (i = 1; i < DRD_N_THREADS; i++)
168 {
169 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
170 && DRD_(g_threadinfo)[i].posix_thread_exists == False
171 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
172 {
173 tl_assert(! DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000174
bartbedfd232009-03-26 19:07:15 +0000175 DRD_(g_threadinfo)[i].vg_thread_exists = True;
176 DRD_(g_threadinfo)[i].vg_threadid = tid;
177 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
178 DRD_(g_threadinfo)[i].stack_min = 0;
179 DRD_(g_threadinfo)[i].stack_min_min = 0;
180 DRD_(g_threadinfo)[i].stack_startup = 0;
181 DRD_(g_threadinfo)[i].stack_max = 0;
bartd45d9952009-05-31 18:53:54 +0000182 DRD_(thread_set_name)(i, "");
183 DRD_(g_threadinfo)[i].is_recording_loads = True;
184 DRD_(g_threadinfo)[i].is_recording_stores = True;
bartbedfd232009-03-26 19:07:15 +0000185 DRD_(g_threadinfo)[i].synchr_nesting = 0;
186 tl_assert(DRD_(g_threadinfo)[i].first == 0);
187 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000188
bartbedfd232009-03-26 19:07:15 +0000189 tl_assert(DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000190
bartbedfd232009-03-26 19:07:15 +0000191 return i;
192 }
193 }
sewardjaf44c822007-11-25 14:01:38 +0000194
bartbedfd232009-03-26 19:07:15 +0000195 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000196
bartbedfd232009-03-26 19:07:15 +0000197 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000198}
199
bart86a87df2009-03-04 19:26:47 +0000200/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000201DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000202{
bartbedfd232009-03-26 19:07:15 +0000203 int i;
sewardjaf44c822007-11-25 14:01:38 +0000204
bartbedfd232009-03-26 19:07:15 +0000205 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000206
bartbedfd232009-03-26 19:07:15 +0000207 for (i = 1; i < DRD_N_THREADS; i++)
208 {
209 if (DRD_(g_threadinfo)[i].posix_thread_exists
210 && DRD_(g_threadinfo)[i].pt_threadid == tid)
211 {
212 return i;
213 }
214 }
215 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000216}
217
bart86a87df2009-03-04 19:26:47 +0000218/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000219ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000220{
bartbedfd232009-03-26 19:07:15 +0000221 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
222 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000223
bartbedfd232009-03-26 19:07:15 +0000224 return (DRD_(g_threadinfo)[tid].vg_thread_exists
225 ? DRD_(g_threadinfo)[tid].vg_threadid
226 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000227}
228
bart8f822af2009-06-08 18:20:42 +0000229#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart324a23b2009-02-15 12:14:52 +0000230/**
231 * Sanity check of the doubly linked list of segments referenced by a
232 * ThreadInfo struct.
233 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000234 */
bart62a784c2009-02-15 13:11:14 +0000235static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000236{
bartbedfd232009-03-26 19:07:15 +0000237 Segment* p;
bart8f822af2009-06-08 18:20:42 +0000238
bartbedfd232009-03-26 19:07:15 +0000239 for (p = ti->first; p; p = p->next) {
240 if (p->next && p->next->prev != p)
241 return False;
242 if (p->next == 0 && p != ti->last)
243 return False;
244 }
245 for (p = ti->last; p; p = p->prev) {
246 if (p->prev && p->prev->next != p)
247 return False;
248 if (p->prev == 0 && p != ti->first)
249 return False;
250 }
251 return True;
sewardjaf44c822007-11-25 14:01:38 +0000252}
bart23d3a4e2008-04-05 12:53:00 +0000253#endif
sewardjaf44c822007-11-25 14:01:38 +0000254
bart439c55f2009-02-15 10:38:37 +0000255/**
256 * Create the first segment for a newly started thread.
257 *
258 * This function is called from the handler installed via
259 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
260 * from the context of the creator thread, before the new thread has been
261 * created.
bart86a87df2009-03-04 19:26:47 +0000262 *
263 * @param[in] creator DRD thread ID of the creator thread.
264 * @param[in] vg_created Valgrind thread ID of the created thread.
265 *
266 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000267 */
bart62a784c2009-02-15 13:11:14 +0000268DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
269 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000270{
bartbedfd232009-03-26 19:07:15 +0000271 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000272
bartbedfd232009-03-26 19:07:15 +0000273 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
274 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
275 tl_assert(0 <= (int)created && created < DRD_N_THREADS
276 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000277
bartbedfd232009-03-26 19:07:15 +0000278 tl_assert(DRD_(g_threadinfo)[created].first == 0);
279 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart8f822af2009-06-08 18:20:42 +0000280 /* Create an initial segment for the newly created thread. */
bartbedfd232009-03-26 19:07:15 +0000281 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000282
bartbedfd232009-03-26 19:07:15 +0000283 return created;
sewardjaf44c822007-11-25 14:01:38 +0000284}
285
bart439c55f2009-02-15 10:38:37 +0000286/**
bart86a87df2009-03-04 19:26:47 +0000287 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
288 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000289 * on the newly created thread, e.g. from the handler installed via
290 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000291 *
292 * @param[in] vg_created Valgrind thread ID of the newly created thread.
293 *
294 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000295 */
bart62a784c2009-02-15 13:11:14 +0000296DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000297{
bartbedfd232009-03-26 19:07:15 +0000298 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000299
bartbedfd232009-03-26 19:07:15 +0000300 tl_assert(0 <= (int)created && created < DRD_N_THREADS
301 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000302
bartbedfd232009-03-26 19:07:15 +0000303 DRD_(g_threadinfo)[created].stack_max
304 = VG_(thread_get_stack_max)(vg_created);
305 DRD_(g_threadinfo)[created].stack_startup
306 = DRD_(g_threadinfo)[created].stack_max;
307 DRD_(g_threadinfo)[created].stack_min
308 = DRD_(g_threadinfo)[created].stack_max;
309 DRD_(g_threadinfo)[created].stack_min_min
310 = DRD_(g_threadinfo)[created].stack_max;
311 DRD_(g_threadinfo)[created].stack_size
312 = VG_(thread_get_stack_size)(vg_created);
313 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000314
bartbedfd232009-03-26 19:07:15 +0000315 return created;
bart439c55f2009-02-15 10:38:37 +0000316}
bart09dc13f2009-02-14 15:13:31 +0000317
bart324a23b2009-02-15 12:14:52 +0000318/**
319 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
320 * after thread drd_joiner joined thread drd_joinee.
321 */
bart09dc13f2009-02-14 15:13:31 +0000322void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
323{
bartbedfd232009-03-26 19:07:15 +0000324 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
325 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
bart7627be32009-06-06 12:26:05 +0000326
bartbedfd232009-03-26 19:07:15 +0000327 DRD_(thread_new_segment)(drd_joiner);
bart8f822af2009-06-08 18:20:42 +0000328 DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
bart7627be32009-06-06 12:26:05 +0000329 DRD_(thread_new_segment)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000330
bartbedfd232009-03-26 19:07:15 +0000331 if (s_trace_fork_join)
332 {
333 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
334 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
335 const unsigned msg_size = 256;
336 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000337
bartbedfd232009-03-26 19:07:15 +0000338 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
339 tl_assert(msg);
340 VG_(snprintf)(msg, msg_size,
341 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
342 joiner, drd_joiner, joinee, drd_joinee);
343 if (joiner)
344 {
bart8f822af2009-06-08 18:20:42 +0000345 char* vc;
346
347 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
bartbedfd232009-03-26 19:07:15 +0000348 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart8f822af2009-06-08 18:20:42 +0000349 ", new vc: %s", vc);
350 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000351 }
352 VG_(message)(Vg_DebugMsg, "%s", msg);
353 VG_(free)(msg);
354 }
bart09dc13f2009-02-14 15:13:31 +0000355
bartbedfd232009-03-26 19:07:15 +0000356 if (! DRD_(get_check_stack_accesses)())
357 {
358 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
359 - DRD_(thread_get_stack_size)(drd_joinee),
360 DRD_(thread_get_stack_max)(drd_joinee));
361 }
362 DRD_(clientobj_delete_thread)(drd_joinee);
363 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000364}
365
bart324a23b2009-02-15 12:14:52 +0000366/**
367 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
368 * and accesses this data structure from multiple threads without locking.
369 * Any conflicting accesses in the range stack_startup..stack_max will be
370 * ignored.
371 */
bart62a784c2009-02-15 13:11:14 +0000372void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
373 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000374{
bartbedfd232009-03-26 19:07:15 +0000375 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
376 && tid != DRD_INVALID_THREADID);
377 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
378 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
379 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000380}
381
bart86a87df2009-03-04 19:26:47 +0000382/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000383Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000384{
bartbedfd232009-03-26 19:07:15 +0000385 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
386 && tid != DRD_INVALID_THREADID);
387 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000388}
389
bart86a87df2009-03-04 19:26:47 +0000390/**
391 * Return the lowest value that was ever assigned to the stack pointer
392 * for the specified thread.
393 */
bart62a784c2009-02-15 13:11:14 +0000394Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000395{
bartbedfd232009-03-26 19:07:15 +0000396 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
397 && tid != DRD_INVALID_THREADID);
398 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000399}
400
bart86a87df2009-03-04 19:26:47 +0000401/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000402Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000403{
bartbedfd232009-03-26 19:07:15 +0000404 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
405 && tid != DRD_INVALID_THREADID);
406 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000407}
408
bart86a87df2009-03-04 19:26:47 +0000409/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000410SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000411{
bartbedfd232009-03-26 19:07:15 +0000412 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
413 && tid != DRD_INVALID_THREADID);
414 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000415}
416
bart09dc13f2009-02-14 15:13:31 +0000417/**
418 * Clean up thread-specific data structures. Call this just after
419 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000420 */
bart62a784c2009-02-15 13:11:14 +0000421void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000422{
bartbedfd232009-03-26 19:07:15 +0000423 Segment* sg;
424 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000425
bartbedfd232009-03-26 19:07:15 +0000426 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000427
bartbedfd232009-03-26 19:07:15 +0000428 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
429 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
430 {
431 sg_prev = sg->prev;
432 sg->prev = 0;
433 sg->next = 0;
434 DRD_(sg_put)(sg);
435 }
436 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
437 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
438 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
439 DRD_(g_threadinfo)[tid].first = 0;
440 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000441
bartbedfd232009-03-26 19:07:15 +0000442 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000443}
444
bart324a23b2009-02-15 12:14:52 +0000445/**
446 * Called after a thread performed its last memory access and before
447 * thread_delete() is called. Note: thread_delete() is only called for
448 * joinable threads, not for detached threads.
449 */
bart62a784c2009-02-15 13:11:14 +0000450void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000451{
bartbedfd232009-03-26 19:07:15 +0000452 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
453 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000454
bartbedfd232009-03-26 19:07:15 +0000455 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000456
bartbedfd232009-03-26 19:07:15 +0000457 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
458 {
459 /*
460 * Once a detached thread has finished, its stack is deallocated and
461 * should no longer be taken into account when computing the conflict set.
462 */
463 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000464
bartbedfd232009-03-26 19:07:15 +0000465 /*
466 * For a detached thread, calling pthread_exit() invalidates the
467 * POSIX thread ID associated with the detached thread. For joinable
468 * POSIX threads however, the POSIX thread ID remains live after the
469 * pthread_exit() call until pthread_join() is called.
470 */
471 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
472 }
sewardjaf44c822007-11-25 14:01:38 +0000473}
474
bart9b2974a2008-09-27 12:35:31 +0000475/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000476void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000477{
bartbedfd232009-03-26 19:07:15 +0000478 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
479 && tid != DRD_INVALID_THREADID);
480 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000481
bartbedfd232009-03-26 19:07:15 +0000482 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000483}
484
barte7dff242009-04-23 17:12:39 +0000485/**
486 * Store the POSIX thread ID for the specified thread.
487 *
488 * @note This function can be called two times for the same thread -- see also
489 * the comment block preceding the pthread_create() wrapper in
490 * drd_pthread_intercepts.c.
491 */
bart62a784c2009-02-15 13:11:14 +0000492void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000493{
bartbedfd232009-03-26 19:07:15 +0000494 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
495 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000496 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
497 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000498 tl_assert(ptid != INVALID_POSIX_THREADID);
499 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
500 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000501}
502
bart86a87df2009-03-04 19:26:47 +0000503/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000504Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000505{
bartbedfd232009-03-26 19:07:15 +0000506 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
507 && tid != DRD_INVALID_THREADID);
508 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000509}
510
bart86a87df2009-03-04 19:26:47 +0000511/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000512void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000513{
bartbedfd232009-03-26 19:07:15 +0000514 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
515 && tid != DRD_INVALID_THREADID);
516 tl_assert(!! joinable == joinable);
517 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bart8f822af2009-06-08 18:20:42 +0000518
bartbedfd232009-03-26 19:07:15 +0000519 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000520}
521
bartd45d9952009-05-31 18:53:54 +0000522/** Obtain the thread number and the user-assigned thread name. */
523const char* DRD_(thread_get_name)(const DrdThreadId tid)
524{
525 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
526 && tid != DRD_INVALID_THREADID);
527
528 return DRD_(g_threadinfo)[tid].name;
529}
530
531/** Set the name of the specified thread. */
532void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
533{
534 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
535 && tid != DRD_INVALID_THREADID);
536
537 if (name == NULL || name[0] == 0)
538 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
539 sizeof(DRD_(g_threadinfo)[tid].name),
540 "Thread %d",
541 tid);
542 else
543 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
544 sizeof(DRD_(g_threadinfo)[tid].name),
545 "Thread %d (%s)",
546 tid, name);
547 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
548}
549
bart86a87df2009-03-04 19:26:47 +0000550/**
551 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
552 * conflict set.
553 */
bart62a784c2009-02-15 13:11:14 +0000554void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000555{
bartbedfd232009-03-26 19:07:15 +0000556 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000557
bartbedfd232009-03-26 19:07:15 +0000558 if (vg_tid != s_vg_running_tid)
559 {
560 DRD_(thread_set_running_tid)(vg_tid,
561 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
562 }
sewardj8b09d4f2007-12-04 21:27:18 +0000563
bartbedfd232009-03-26 19:07:15 +0000564 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
565 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000566}
567
bart86a87df2009-03-04 19:26:47 +0000568/**
569 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
570 * conflict set.
571 */
bart62a784c2009-02-15 13:11:14 +0000572void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
573 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000574{
bartbedfd232009-03-26 19:07:15 +0000575 tl_assert(vg_tid != VG_INVALID_THREADID);
576 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000577
bartbedfd232009-03-26 19:07:15 +0000578 if (vg_tid != s_vg_running_tid)
579 {
580 if (s_trace_context_switches
581 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
582 {
583 VG_(message)(Vg_DebugMsg,
584 "Context switch from thread %d/%d to thread %d/%d;"
585 " segments: %llu",
586 s_vg_running_tid, DRD_(g_drd_running_tid),
587 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
588 DRD_(sg_get_segments_alive_count)());
589 }
590 s_vg_running_tid = vg_tid;
591 DRD_(g_drd_running_tid) = drd_tid;
592 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
593 s_context_switch_count++;
594 }
sewardj8b09d4f2007-12-04 21:27:18 +0000595
bartbedfd232009-03-26 19:07:15 +0000596 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
597 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000598}
599
bart86a87df2009-03-04 19:26:47 +0000600/**
601 * Increase the synchronization nesting counter. Must be called before the
602 * client calls a synchronization function.
603 */
bart62a784c2009-02-15 13:11:14 +0000604int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000605{
bartbedfd232009-03-26 19:07:15 +0000606 tl_assert(DRD_(IsValidDrdThreadId)(tid));
607 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000608}
609
bart86a87df2009-03-04 19:26:47 +0000610/**
611 * Decrease the synchronization nesting counter. Must be called after the
612 * client left a synchronization function.
613 */
bart62a784c2009-02-15 13:11:14 +0000614int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000615{
bartbedfd232009-03-26 19:07:15 +0000616 tl_assert(DRD_(IsValidDrdThreadId)(tid));
617 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
618 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000619}
620
bart86a87df2009-03-04 19:26:47 +0000621/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000622int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000623{
bartbedfd232009-03-26 19:07:15 +0000624 tl_assert(DRD_(IsValidDrdThreadId)(tid));
625 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000626}
627
bart1a473c72008-03-13 19:03:38 +0000628/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000629static
bart86a87df2009-03-04 19:26:47 +0000630void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000631{
bartbedfd232009-03-26 19:07:15 +0000632 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
633 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000634
635#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
636 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
637#endif
638
bartbedfd232009-03-26 19:07:15 +0000639 sg->prev = DRD_(g_threadinfo)[tid].last;
640 sg->next = 0;
641 if (DRD_(g_threadinfo)[tid].last)
642 DRD_(g_threadinfo)[tid].last->next = sg;
643 DRD_(g_threadinfo)[tid].last = sg;
644 if (DRD_(g_threadinfo)[tid].first == 0)
645 DRD_(g_threadinfo)[tid].first = sg;
bart8f822af2009-06-08 18:20:42 +0000646
647#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
648 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
649#endif
sewardjaf44c822007-11-25 14:01:38 +0000650}
651
bart324a23b2009-02-15 12:14:52 +0000652/**
653 * Remove a segment from the segment list of thread threadid, and free the
654 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000655 */
bart62a784c2009-02-15 13:11:14 +0000656static
bart86a87df2009-03-04 19:26:47 +0000657void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000658{
bartbedfd232009-03-26 19:07:15 +0000659 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
660 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000661
662#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
663 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
664#endif
bart26f73e12008-02-24 18:37:08 +0000665
bartbedfd232009-03-26 19:07:15 +0000666 if (sg->prev)
667 sg->prev->next = sg->next;
668 if (sg->next)
669 sg->next->prev = sg->prev;
670 if (sg == DRD_(g_threadinfo)[tid].first)
671 DRD_(g_threadinfo)[tid].first = sg->next;
672 if (sg == DRD_(g_threadinfo)[tid].last)
673 DRD_(g_threadinfo)[tid].last = sg->prev;
674 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000675
bart8f822af2009-06-08 18:20:42 +0000676#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
677 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
678#endif
sewardjaf44c822007-11-25 14:01:38 +0000679}
680
bart86a87df2009-03-04 19:26:47 +0000681/**
682 * Returns a pointer to the vector clock of the most recent segment associated
683 * with thread 'tid'.
684 */
bart62a784c2009-02-15 13:11:14 +0000685VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000686{
bartbedfd232009-03-26 19:07:15 +0000687 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
688 && tid != DRD_INVALID_THREADID);
689 tl_assert(DRD_(g_threadinfo)[tid].last);
690 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000691}
692
bart324a23b2009-02-15 12:14:52 +0000693/**
694 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000695 */
bart62a784c2009-02-15 13:11:14 +0000696void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000697{
bartbedfd232009-03-26 19:07:15 +0000698 tl_assert(sg);
699 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
700 && tid != DRD_INVALID_THREADID);
701 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000702
bartbedfd232009-03-26 19:07:15 +0000703 DRD_(sg_put)(*sg);
704 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000705}
706
sewardjaf44c822007-11-25 14:01:38 +0000707/**
708 * Compute the minimum of all latest vector clocks of all threads
709 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000710 *
sewardjaf44c822007-11-25 14:01:38 +0000711 * @param vc pointer to a vectorclock, holds result upon return.
712 */
bart62a784c2009-02-15 13:11:14 +0000713static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000714{
bartbedfd232009-03-26 19:07:15 +0000715 unsigned i;
716 Bool first;
717 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000718
bartbedfd232009-03-26 19:07:15 +0000719 first = True;
bart8f822af2009-06-08 18:20:42 +0000720 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000721 {
722 latest_sg = DRD_(g_threadinfo)[i].last;
723 if (latest_sg)
724 {
725 if (first)
726 DRD_(vc_assign)(vc, &latest_sg->vc);
727 else
728 DRD_(vc_min)(vc, &latest_sg->vc);
729 first = False;
730 }
731 }
sewardjaf44c822007-11-25 14:01:38 +0000732}
733
bart86a87df2009-03-04 19:26:47 +0000734/**
735 * Compute the maximum of all latest vector clocks of all threads.
736 *
737 * @param vc pointer to a vectorclock, holds result upon return.
738 */
bart62a784c2009-02-15 13:11:14 +0000739static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000740{
bartbedfd232009-03-26 19:07:15 +0000741 unsigned i;
742 Bool first;
743 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000744
bartbedfd232009-03-26 19:07:15 +0000745 first = True;
bart8f822af2009-06-08 18:20:42 +0000746 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000747 {
748 latest_sg = DRD_(g_threadinfo)[i].last;
749 if (latest_sg)
750 {
751 if (first)
752 DRD_(vc_assign)(vc, &latest_sg->vc);
753 else
754 DRD_(vc_combine)(vc, &latest_sg->vc);
755 first = False;
756 }
757 }
sewardjaf44c822007-11-25 14:01:38 +0000758}
759
760/**
bart5bd9f2d2008-03-03 20:31:58 +0000761 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000762 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000763 * data race.
764 */
bart8f822af2009-06-08 18:20:42 +0000765static void thread_discard_ordered_segments(void)
sewardjaf44c822007-11-25 14:01:38 +0000766{
bartbedfd232009-03-26 19:07:15 +0000767 unsigned i;
768 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000769
bartbedfd232009-03-26 19:07:15 +0000770 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000771
bartbedfd232009-03-26 19:07:15 +0000772 DRD_(vc_init)(&thread_vc_min, 0, 0);
773 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
774 if (DRD_(sg_get_trace)())
775 {
bart8f822af2009-06-08 18:20:42 +0000776 char *vc_min, *vc_max;
bartbedfd232009-03-26 19:07:15 +0000777 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000778
bartbedfd232009-03-26 19:07:15 +0000779 DRD_(vc_init)(&thread_vc_max, 0, 0);
780 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart8f822af2009-06-08 18:20:42 +0000781 vc_min = DRD_(vc_aprint)(&thread_vc_min);
782 vc_max = DRD_(vc_aprint)(&thread_vc_max);
783 VG_(message)(Vg_DebugMsg,
784 "Discarding ordered segments -- min vc is %s, max vc is %s",
785 vc_min, vc_max);
786 VG_(free)(vc_min);
787 VG_(free)(vc_max);
bartbedfd232009-03-26 19:07:15 +0000788 DRD_(vc_cleanup)(&thread_vc_max);
789 }
sewardjaf44c822007-11-25 14:01:38 +0000790
bart8f822af2009-06-08 18:20:42 +0000791 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000792 {
793 Segment* sg;
794 Segment* sg_next;
795 for (sg = DRD_(g_threadinfo)[i].first;
796 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
797 sg = sg_next)
798 {
799 thread_discard_segment(i, sg);
800 }
801 }
802 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000803}
804
bart324a23b2009-02-15 12:14:52 +0000805/**
bart8f822af2009-06-08 18:20:42 +0000806 * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
807 * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
808 * all segments in the set CS are ordered consistently against both sg1 and
809 * sg2. The set CS is defined as the set of segments that can immediately
810 * precede future segments via inter-thread synchronization operations. In
811 * DRD the set CS consists of the latest segment of each thread combined with
812 * all segments for which the reference count is strictly greater than one.
813 * The code below is an optimized version of the following:
814 *
815 * for (i = 0; i < DRD_N_THREADS; i++)
816 * {
817 * Segment* sg;
818 *
819 * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
820 * {
821 * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
822 * {
823 * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
824 * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
825 * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
826 * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
827 * {
828 * return False;
829 * }
830 * }
831 * }
832 * }
833 */
834static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
835 Segment* const sg1,
836 Segment* const sg2)
837{
838 unsigned i;
839
840 tl_assert(sg1->next);
841 tl_assert(sg2->next);
842 tl_assert(sg1->next == sg2);
843 tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
844
845 for (i = 0; i < DRD_N_THREADS; i++)
846 {
847 Segment* sg;
848
849 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
850 {
851 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
852 {
853 if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
854 break;
855 if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
856 return False;
857 }
858 }
859 for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
860 {
861 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
862 {
863 if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
864 break;
865 if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
866 return False;
867 }
868 }
869 }
870 return True;
871}
872
873/**
bart324a23b2009-02-15 12:14:52 +0000874 * Merge all segments that may be merged without triggering false positives
875 * or discarding real data races. For the theoretical background of segment
bart8f822af2009-06-08 18:20:42 +0000876 * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
877 * and Koen De Bosschere. Bounding the number of segment histories during
878 * data race detection. Parallel Computing archive, Volume 28, Issue 9,
879 * pp 1221-1238, September 2002. This paper contains a proof that merging
880 * consecutive segments for which the property equiv(s1,s2) holds can be
881 * merged without reducing the accuracy of datarace detection. Furthermore
882 * it is also proven that the total number of all segments will never grow
883 * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
884 * every time a new segment is created. The property equiv(s1, s2) is defined
885 * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
886 * clocks of segments s and s1 are ordered in the same way as those of segments
887 * s and s2. The set CS is defined as the set of existing segments s that have
888 * the potential to conflict with not yet created segments, either because the
889 * segment s is the latest segment of a thread or because it can become the
890 * immediate predecessor of a new segment due to a synchronization operation.
barta9c37392008-03-22 09:38:48 +0000891 */
892static void thread_merge_segments(void)
893{
bartbedfd232009-03-26 19:07:15 +0000894 unsigned i;
barta9c37392008-03-22 09:38:48 +0000895
bart8f822af2009-06-08 18:20:42 +0000896 s_new_segments_since_last_merge = 0;
897
898 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000899 {
900 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000901
bart8f822af2009-06-08 18:20:42 +0000902#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
903 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
904#endif
barta9c37392008-03-22 09:38:48 +0000905
bartbedfd232009-03-26 19:07:15 +0000906 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000907 {
bartbedfd232009-03-26 19:07:15 +0000908 if (DRD_(sg_get_refcnt)(sg) == 1
909 && sg->next
910 && DRD_(sg_get_refcnt)(sg->next) == 1
bart8f822af2009-06-08 18:20:42 +0000911 && sg->next->next
912 && thread_consistent_segment_ordering(i, sg, sg->next))
bartbedfd232009-03-26 19:07:15 +0000913 {
914 /* Merge sg and sg->next into sg. */
915 DRD_(sg_merge)(sg, sg->next);
916 thread_discard_segment(i, sg->next);
917 }
barta9c37392008-03-22 09:38:48 +0000918 }
barta9c37392008-03-22 09:38:48 +0000919
bart8f822af2009-06-08 18:20:42 +0000920#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
921 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
922#endif
bartbedfd232009-03-26 19:07:15 +0000923 }
barta9c37392008-03-22 09:38:48 +0000924}
925
bart324a23b2009-02-15 12:14:52 +0000926/**
bart324a23b2009-02-15 12:14:52 +0000927 * Create a new segment for the specified thread, and discard any segments
928 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000929 */
bart62a784c2009-02-15 13:11:14 +0000930void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000931{
bart8f822af2009-06-08 18:20:42 +0000932 Segment* last_sg;
bartbedfd232009-03-26 19:07:15 +0000933 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000934
bartbedfd232009-03-26 19:07:15 +0000935 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
936 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000937 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000938
bart8f822af2009-06-08 18:20:42 +0000939 last_sg = DRD_(g_threadinfo)[tid].last;
bartbedfd232009-03-26 19:07:15 +0000940 new_sg = DRD_(sg_new)(tid, tid);
941 thread_append_segment(tid, new_sg);
bart8f822af2009-06-08 18:20:42 +0000942 if (tid == DRD_(g_drd_running_tid) && last_sg)
943 DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
bartd66e3a82008-04-06 15:02:17 +0000944
bart8f822af2009-06-08 18:20:42 +0000945 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000946
bart8f822af2009-06-08 18:20:42 +0000947 if (s_segment_merging
948 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
bartbedfd232009-03-26 19:07:15 +0000949 {
bart8f822af2009-06-08 18:20:42 +0000950 thread_discard_ordered_segments();
bartbedfd232009-03-26 19:07:15 +0000951 thread_merge_segments();
952 }
sewardjaf44c822007-11-25 14:01:38 +0000953}
954
bart26f73e12008-02-24 18:37:08 +0000955/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart8f822af2009-06-08 18:20:42 +0000956void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000957{
bartbedfd232009-03-26 19:07:15 +0000958 tl_assert(joiner != joinee);
959 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
960 && joiner != DRD_INVALID_THREADID);
961 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
962 && joinee != DRD_INVALID_THREADID);
963 tl_assert(DRD_(g_threadinfo)[joiner].last);
964 tl_assert(DRD_(g_threadinfo)[joinee].last);
bart8f822af2009-06-08 18:20:42 +0000965
966 if (DRD_(sg_get_trace)())
967 {
968 char *str1, *str2;
969 str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
970 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
971 VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s",
972 str1, str2);
973 VG_(free)(str1);
974 VG_(free)(str2);
975 }
bartbedfd232009-03-26 19:07:15 +0000976 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
977 &DRD_(g_threadinfo)[joinee].last->vc);
bart8f822af2009-06-08 18:20:42 +0000978 if (DRD_(sg_get_trace)())
979 {
980 char* str;
981 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
982 VG_(message)(Vg_DebugMsg, "After join: %s", str);
983 VG_(free)(str);
984 }
985 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000986
bartbedfd232009-03-26 19:07:15 +0000987 if (joiner == DRD_(g_drd_running_tid))
988 {
989 thread_compute_conflict_set(&DRD_(g_conflict_set), joiner);
990 }
sewardjaf44c822007-11-25 14:01:38 +0000991}
992
bart324a23b2009-02-15 12:14:52 +0000993/**
bart8f822af2009-06-08 18:20:42 +0000994 * Update the vector clock of the last segment of thread tid with the
995 * the vector clock of segment sg. Call this function after thread tid had
996 * to wait because of thread synchronization until the memory accesses in the
997 * segment sg finished.
bart26f73e12008-02-24 18:37:08 +0000998 */
bart8f822af2009-06-08 18:20:42 +0000999void DRD_(thread_combine_vc_sync)(DrdThreadId tid, const Segment* sg)
sewardjaf44c822007-11-25 14:01:38 +00001000{
bart8f822af2009-06-08 18:20:42 +00001001 const VectorClock* const vc = &sg->vc;
1002
bartbedfd232009-03-26 19:07:15 +00001003 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1004 && tid != DRD_INVALID_THREADID);
1005 tl_assert(DRD_(g_threadinfo)[tid].last);
bart8f822af2009-06-08 18:20:42 +00001006 tl_assert(sg);
bartbedfd232009-03-26 19:07:15 +00001007 tl_assert(vc);
bart8f822af2009-06-08 18:20:42 +00001008
1009 if (tid != sg->tid)
1010 {
1011 VectorClock old_vc;
1012
1013 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
1014 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
1015 if (DRD_(sg_get_trace)())
1016 {
1017 char *str1, *str2;
1018 str1 = DRD_(vc_aprint)(&old_vc);
1019 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1020 VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s", tid, str1, str2);
1021 VG_(free)(str1);
1022 VG_(free)(str2);
1023 }
1024 thread_discard_ordered_segments();
1025 DRD_(thread_update_conflict_set)(tid, &old_vc);
1026 DRD_(vc_cleanup)(&old_vc);
1027 }
1028 else
1029 {
1030 tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
1031 }
sewardjaf44c822007-11-25 14:01:38 +00001032}
1033
bart324a23b2009-02-15 12:14:52 +00001034/**
1035 * Call this function whenever a thread is no longer using the memory
1036 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1037 * increase.
bart26f73e12008-02-24 18:37:08 +00001038 */
bart62a784c2009-02-15 13:11:14 +00001039void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +00001040{
bartbedfd232009-03-26 19:07:15 +00001041 DrdThreadId other_user;
1042 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001043
bartbedfd232009-03-26 19:07:15 +00001044 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
1045 other_user = DRD_INVALID_THREADID;
bart8f822af2009-06-08 18:20:42 +00001046 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001047 {
1048 Segment* p;
1049 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +00001050 {
bartbedfd232009-03-26 19:07:15 +00001051 if (other_user == DRD_INVALID_THREADID
1052 && i != DRD_(g_drd_running_tid))
1053 {
bart8f822af2009-06-08 18:20:42 +00001054 if (UNLIKELY(DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2)))
bartbedfd232009-03-26 19:07:15 +00001055 {
1056 other_user = i;
1057 }
1058 continue;
1059 }
bart8f822af2009-06-08 18:20:42 +00001060 DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
sewardjaf44c822007-11-25 14:01:38 +00001061 }
bartbedfd232009-03-26 19:07:15 +00001062 }
sewardjaf44c822007-11-25 14:01:38 +00001063
bartbedfd232009-03-26 19:07:15 +00001064 /*
1065 * If any other thread had accessed memory in [ a1, a2 [, update the
1066 * conflict set.
1067 */
1068 if (other_user != DRD_INVALID_THREADID
1069 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
1070 {
1071 thread_compute_conflict_set(&DRD_(g_conflict_set),
1072 DRD_(thread_get_running_tid)());
1073 }
sewardjaf44c822007-11-25 14:01:38 +00001074}
1075
bartd45d9952009-05-31 18:53:54 +00001076/** Specify whether memory loads should be recorded. */
1077void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001078{
bartbedfd232009-03-26 19:07:15 +00001079 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1080 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001081 tl_assert(enabled == !! enabled);
1082
1083 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +00001084}
1085
bartd45d9952009-05-31 18:53:54 +00001086/** Specify whether memory stores should be recorded. */
1087void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001088{
bartbedfd232009-03-26 19:07:15 +00001089 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1090 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001091 tl_assert(enabled == !! enabled);
1092
1093 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +00001094}
1095
bart86a87df2009-03-04 19:26:47 +00001096/**
1097 * Print the segment information for all threads.
1098 *
1099 * This function is only used for debugging purposes.
1100 */
bart62a784c2009-02-15 13:11:14 +00001101void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +00001102{
bartbedfd232009-03-26 19:07:15 +00001103 unsigned i;
1104 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001105
bart8f822af2009-06-08 18:20:42 +00001106 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001107 {
1108 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +00001109 {
bartbedfd232009-03-26 19:07:15 +00001110 VG_(printf)("**************\n"
1111 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
1112 "**************\n",
1113 i,
1114 DRD_(g_threadinfo)[i].vg_thread_exists,
1115 DRD_(g_threadinfo)[i].vg_threadid,
1116 DRD_(g_threadinfo)[i].posix_thread_exists,
1117 DRD_(g_threadinfo)[i].pt_threadid,
1118 DRD_(g_threadinfo)[i].detached_posix_thread);
1119 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1120 {
1121 DRD_(sg_print)(p);
1122 }
sewardjaf44c822007-11-25 14:01:38 +00001123 }
bartbedfd232009-03-26 19:07:15 +00001124 }
sewardjaf44c822007-11-25 14:01:38 +00001125}
1126
bart86a87df2009-03-04 19:26:47 +00001127/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001128static void show_call_stack(const DrdThreadId tid,
1129 const Char* const msg,
1130 ExeContext* const callstack)
1131{
bartbedfd232009-03-26 19:07:15 +00001132 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +00001133
bartbedfd232009-03-26 19:07:15 +00001134 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +00001135
bartbedfd232009-03-26 19:07:15 +00001136 if (vg_tid != VG_INVALID_THREADID)
1137 {
1138 if (callstack)
1139 {
1140 VG_(pp_ExeContext)(callstack);
1141 }
1142 else
1143 {
1144 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1145 }
1146 }
1147 else
1148 {
1149 VG_(message)(Vg_UserMsg,
1150 " (thread finished, call stack no longer available)");
1151 }
sewardjaf44c822007-11-25 14:01:38 +00001152}
1153
bart86a87df2009-03-04 19:26:47 +00001154/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001155static void
1156thread_report_conflicting_segments_segment(const DrdThreadId tid,
1157 const Addr addr,
1158 const SizeT size,
1159 const BmAccessTypeT access_type,
1160 const Segment* const p)
1161{
bartbedfd232009-03-26 19:07:15 +00001162 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001163
bartbedfd232009-03-26 19:07:15 +00001164 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1165 && tid != DRD_INVALID_THREADID);
1166 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001167
bart8f822af2009-06-08 18:20:42 +00001168 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001169 {
1170 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001171 {
bartbedfd232009-03-26 19:07:15 +00001172 Segment* q;
1173 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1174 {
1175 /*
1176 * Since q iterates over the segments of thread i in order of
1177 * decreasing vector clocks, if q->vc <= p->vc, then
1178 * q->next->vc <= p->vc will also hold. Hence, break out of the
1179 * loop once this condition is met.
1180 */
1181 if (DRD_(vc_lte)(&q->vc, &p->vc))
1182 break;
1183 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1184 {
bart8f822af2009-06-08 18:20:42 +00001185 if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
bartbedfd232009-03-26 19:07:15 +00001186 access_type))
1187 {
1188 tl_assert(q->stacktrace);
1189 show_call_stack(i, "Other segment start",
1190 q->stacktrace);
1191 show_call_stack(i, "Other segment end",
1192 q->next ? q->next->stacktrace : 0);
1193 }
1194 }
1195 }
sewardjaf44c822007-11-25 14:01:38 +00001196 }
bartbedfd232009-03-26 19:07:15 +00001197 }
sewardjaf44c822007-11-25 14:01:38 +00001198}
1199
bart86a87df2009-03-04 19:26:47 +00001200/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001201void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1202 const Addr addr,
1203 const SizeT size,
1204 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001205{
bartbedfd232009-03-26 19:07:15 +00001206 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001207
bartbedfd232009-03-26 19:07:15 +00001208 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1209 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001210
bartbedfd232009-03-26 19:07:15 +00001211 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1212 {
bart8f822af2009-06-08 18:20:42 +00001213 if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
bartbedfd232009-03-26 19:07:15 +00001214 {
1215 thread_report_conflicting_segments_segment(tid, addr, size,
1216 access_type, p);
1217 }
1218 }
sewardjaf44c822007-11-25 14:01:38 +00001219}
sewardjaf44c822007-11-25 14:01:38 +00001220
bart324a23b2009-02-15 12:14:52 +00001221/**
bart8f822af2009-06-08 18:20:42 +00001222 * Verify whether the conflict set for thread tid is up to date. Only perform
1223 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1224 */
1225static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1226{
1227 static int do_verify_conflict_set = -1;
1228 Bool result;
1229 struct bitmap* computed_conflict_set = 0;
1230
1231 if (do_verify_conflict_set < 0)
1232 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1233
1234 if (do_verify_conflict_set == 0)
1235 return True;
1236
1237 thread_compute_conflict_set(&computed_conflict_set, tid);
1238 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1239 if (! result)
1240 {
1241 VG_(printf)("actual conflict set:\n");
1242 DRD_(bm_print)(DRD_(g_conflict_set));
1243 VG_(printf)("\n");
1244 VG_(printf)("computed conflict set:\n");
1245 DRD_(bm_print)(computed_conflict_set);
1246 VG_(printf)("\n");
1247 }
1248 DRD_(bm_delete)(computed_conflict_set);
1249 return result;
1250}
1251
1252/**
1253 * Compute the conflict set: a bitmap that represents the union of all memory
1254 * accesses of all segments that are unordered to the current segment of the
1255 * thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001256 */
bart86a87df2009-03-04 19:26:47 +00001257static void thread_compute_conflict_set(struct bitmap** conflict_set,
1258 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001259{
bartbedfd232009-03-26 19:07:15 +00001260 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001261
bartbedfd232009-03-26 19:07:15 +00001262 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1263 && tid != DRD_INVALID_THREADID);
1264 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001265
bartbedfd232009-03-26 19:07:15 +00001266 s_update_conflict_set_count++;
1267 s_conflict_set_bitmap_creation_count
1268 -= DRD_(bm_get_bitmap_creation_count)();
1269 s_conflict_set_bitmap2_creation_count
1270 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001271
bartbedfd232009-03-26 19:07:15 +00001272 if (*conflict_set)
1273 {
1274 DRD_(bm_delete)(*conflict_set);
1275 }
1276 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001277
bartbedfd232009-03-26 19:07:15 +00001278 if (s_trace_conflict_set)
1279 {
bart8f822af2009-06-08 18:20:42 +00001280 char* str;
bart26f73e12008-02-24 18:37:08 +00001281
bart8f822af2009-06-08 18:20:42 +00001282 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1283 VG_(message)(Vg_DebugMsg,
1284 "computing conflict set for thread %d/%d with vc %s",
1285 DRD_(DrdThreadIdToVgThreadId)(tid), tid, str);
1286 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001287 }
sewardjaf44c822007-11-25 14:01:38 +00001288
bartbedfd232009-03-26 19:07:15 +00001289 p = DRD_(g_threadinfo)[tid].last;
1290 {
1291 unsigned j;
1292
1293 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001294 {
bart8f822af2009-06-08 18:20:42 +00001295 char* vc;
bartbedfd232009-03-26 19:07:15 +00001296
bart8f822af2009-06-08 18:20:42 +00001297 vc = DRD_(vc_aprint)(&p->vc);
1298 VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s",
1299 tid, vc);
1300 VG_(free)(vc);
bart26f73e12008-02-24 18:37:08 +00001301 }
sewardjaf44c822007-11-25 14:01:38 +00001302
bart8f822af2009-06-08 18:20:42 +00001303 for (j = 0; j < DRD_N_THREADS; j++)
bartbedfd232009-03-26 19:07:15 +00001304 {
1305 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1306 {
bart8f822af2009-06-08 18:20:42 +00001307 Segment* q;
bartbedfd232009-03-26 19:07:15 +00001308 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1309 {
1310 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1311 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1312 {
1313 if (s_trace_conflict_set)
1314 {
bart8f822af2009-06-08 18:20:42 +00001315 char* str;
1316
1317 str = DRD_(vc_aprint)(&q->vc);
1318 VG_(message)(Vg_DebugMsg,
1319 "conflict set: [%d] merging segment %s",
1320 j, str);
1321 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001322 }
bart8f822af2009-06-08 18:20:42 +00001323 DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
bartbedfd232009-03-26 19:07:15 +00001324 }
1325 else
1326 {
1327 if (s_trace_conflict_set)
1328 {
bart8f822af2009-06-08 18:20:42 +00001329 char* str;
1330
1331 str = DRD_(vc_aprint)(&q->vc);
1332 VG_(message)(Vg_DebugMsg,
1333 "conflict set: [%d] ignoring segment %s",
1334 j, str);
1335 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001336 }
1337 }
1338 }
1339 }
1340 }
1341 }
sewardjaf44c822007-11-25 14:01:38 +00001342
bartbedfd232009-03-26 19:07:15 +00001343 s_conflict_set_bitmap_creation_count
1344 += DRD_(bm_get_bitmap_creation_count)();
1345 s_conflict_set_bitmap2_creation_count
1346 += DRD_(bm_get_bitmap2_creation_count)();
1347
bart8f822af2009-06-08 18:20:42 +00001348 if (s_trace_conflict_set_bm)
bartbedfd232009-03-26 19:07:15 +00001349 {
bart8f822af2009-06-08 18:20:42 +00001350 VG_(message)(Vg_DebugMsg, "[%d] new conflict set:", tid);
bartbedfd232009-03-26 19:07:15 +00001351 DRD_(bm_print)(*conflict_set);
bart8f822af2009-06-08 18:20:42 +00001352 VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.", tid);
bartbedfd232009-03-26 19:07:15 +00001353 }
sewardjaf44c822007-11-25 14:01:38 +00001354}
1355
bart8f822af2009-06-08 18:20:42 +00001356/**
1357 * Update the conflict set after the vector clock of thread tid has been
1358 * updated from old_vc to its current value, either because a new segment has
1359 * been created or because of a synchronization operation.
1360 */
1361void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1362 const VectorClock* const old_vc)
1363{
1364 const VectorClock* new_vc;
1365 Segment* p;
1366 unsigned j;
1367
1368 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1369 && tid != DRD_INVALID_THREADID);
1370 tl_assert(old_vc);
1371 tl_assert(tid == DRD_(g_drd_running_tid));
1372 tl_assert(DRD_(g_conflict_set));
1373
1374 if (s_trace_conflict_set)
1375 {
1376 char* str;
1377
1378 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1379 VG_(message)(Vg_DebugMsg,
1380 "updating conflict set for thread %d/%d with vc %s",
1381 DRD_(DrdThreadIdToVgThreadId)(tid), tid, str);
1382 VG_(free)(str);
1383 }
1384
1385 new_vc = &DRD_(g_threadinfo)[tid].last->vc;
1386
1387 DRD_(bm_unmark)(DRD_(g_conflict_set));
1388
1389 for (j = 0; j < DRD_N_THREADS; j++)
1390 {
1391 Segment* q;
1392
1393 if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1394 continue;
1395
1396 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1397 {
1398 const int included_in_old_conflict_set
1399 = ! DRD_(vc_lte)(&q->vc, old_vc)
1400 && ! DRD_(vc_lte)(old_vc, &q->vc);
1401 const int included_in_new_conflict_set
1402 = ! DRD_(vc_lte)(&q->vc, new_vc)
1403 && ! DRD_(vc_lte)(new_vc, &q->vc);
1404 if (included_in_old_conflict_set != included_in_new_conflict_set)
1405 {
1406 if (s_trace_conflict_set)
1407 {
1408 char* str;
1409
1410 str = DRD_(vc_aprint)(&q->vc);
1411 VG_(message)(Vg_DebugMsg,
1412 "conflict set: [%d] merging segment %s", j, str);
1413 VG_(free)(str);
1414 }
1415 DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1416 }
1417 else
1418 {
1419 if (s_trace_conflict_set)
1420 {
1421 char* str;
1422
1423 str = DRD_(vc_aprint)(&q->vc);
1424 VG_(message)(Vg_DebugMsg,
1425 "conflict set: [%d] ignoring segment %s", j, str);
1426 VG_(free)(str);
1427 }
1428 }
1429 }
1430 }
1431
1432 DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1433
1434 p = DRD_(g_threadinfo)[tid].last;
1435 {
1436 for (j = 0; j < DRD_N_THREADS; j++)
1437 {
1438 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1439 {
1440 Segment* q;
1441 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1442 {
1443 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1444 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1445 {
1446 DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1447 }
1448 }
1449 }
1450 }
1451 }
1452
1453 DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1454
1455 s_conflict_set_combine_vc_count++;
1456
1457 if (s_trace_conflict_set_bm)
1458 {
1459 VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:", tid);
1460 DRD_(bm_print)(DRD_(g_conflict_set));
1461 VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.", tid);
1462 }
1463
1464 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1465}
1466
bart86a87df2009-03-04 19:26:47 +00001467/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001468ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001469{
bartbedfd232009-03-26 19:07:15 +00001470 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001471}
1472
bart86a87df2009-03-04 19:26:47 +00001473/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001474ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001475{
bartbedfd232009-03-26 19:07:15 +00001476 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001477}
1478
bart86a87df2009-03-04 19:26:47 +00001479/** Return how many times the conflict set has been updated. */
bart62a784c2009-02-15 13:11:14 +00001480ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001481{
bartbedfd232009-03-26 19:07:15 +00001482 tl_assert(dsnsc);
1483 tl_assert(dscvc);
1484 *dsnsc = s_conflict_set_new_segment_count;
1485 *dscvc = s_conflict_set_combine_vc_count;
1486 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001487}
1488
bart86a87df2009-03-04 19:26:47 +00001489/**
1490 * Return the number of first-level bitmaps that have been created during
1491 * conflict set updates.
1492 */
bart62a784c2009-02-15 13:11:14 +00001493ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001494{
bartbedfd232009-03-26 19:07:15 +00001495 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001496}
1497
bart86a87df2009-03-04 19:26:47 +00001498/**
1499 * Return the number of second-level bitmaps that have been created during
1500 * conflict set updates.
1501 */
bart62a784c2009-02-15 13:11:14 +00001502ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001503{
bartbedfd232009-03-26 19:07:15 +00001504 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001505}