blob: 528b7b37eb4b91138c613c5ef2195b5724c8166b [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;
barte5214662009-06-21 11:51:23 +000064static ULong s_update_conflict_set_new_sg_count;
65static ULong s_update_conflict_set_sync_count;
66static ULong s_update_conflict_set_join_count;
bart86a87df2009-03-04 19:26:47 +000067static ULong s_conflict_set_bitmap_creation_count;
68static ULong s_conflict_set_bitmap2_creation_count;
69static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bart324a23b2009-02-15 12:14:52 +000070DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
71ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
72struct bitmap* DRD_(g_conflict_set);
bart86a87df2009-03-04 19:26:47 +000073static Bool s_trace_context_switches = False;
74static Bool s_trace_conflict_set = False;
bart8f822af2009-06-08 18:20:42 +000075static Bool s_trace_conflict_set_bm = False;
bart86a87df2009-03-04 19:26:47 +000076static Bool s_trace_fork_join = False;
77static Bool s_segment_merging = True;
bart8f822af2009-06-08 18:20:42 +000078static Bool s_new_segments_since_last_merge;
bart6f1d7162009-06-24 18:34:10 +000079static int s_segment_merge_interval = 10;
sewardjaf44c822007-11-25 14:01:38 +000080
81
bart324a23b2009-02-15 12:14:52 +000082/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000083
bart86a87df2009-03-04 19:26:47 +000084/** Enables/disables context switch tracing. */
bart62a784c2009-02-15 13:11:14 +000085void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000086{
bartbedfd232009-03-26 19:07:15 +000087 tl_assert(t == False || t == True);
88 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000089}
90
bart86a87df2009-03-04 19:26:47 +000091/** Enables/disables conflict set tracing. */
bart62a784c2009-02-15 13:11:14 +000092void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000093{
bartbedfd232009-03-26 19:07:15 +000094 tl_assert(t == False || t == True);
95 s_trace_conflict_set = t;
bart26f73e12008-02-24 18:37:08 +000096}
97
bart8f822af2009-06-08 18:20:42 +000098/** Enables/disables conflict set bitmap tracing. */
99void DRD_(thread_trace_conflict_set_bm)(const Bool t)
100{
101 tl_assert(t == False || t == True);
102 s_trace_conflict_set_bm = t;
103}
104
bart86a87df2009-03-04 19:26:47 +0000105/** Report whether fork/join tracing is enabled. */
bart09dc13f2009-02-14 15:13:31 +0000106Bool DRD_(thread_get_trace_fork_join)(void)
107{
bartbedfd232009-03-26 19:07:15 +0000108 return s_trace_fork_join;
bart09dc13f2009-02-14 15:13:31 +0000109}
110
bart86a87df2009-03-04 19:26:47 +0000111/** Enables/disables fork/join tracing. */
bart09dc13f2009-02-14 15:13:31 +0000112void DRD_(thread_set_trace_fork_join)(const Bool t)
113{
bartbedfd232009-03-26 19:07:15 +0000114 tl_assert(t == False || t == True);
115 s_trace_fork_join = t;
bart09dc13f2009-02-14 15:13:31 +0000116}
117
bart86a87df2009-03-04 19:26:47 +0000118/** Enables/disables segment merging. */
bart62a784c2009-02-15 13:11:14 +0000119void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000120{
bartbedfd232009-03-26 19:07:15 +0000121 tl_assert(m == False || m == True);
122 s_segment_merging = m;
barta9c37392008-03-22 09:38:48 +0000123}
124
bart8f822af2009-06-08 18:20:42 +0000125/** Get the segment merging interval. */
126int DRD_(thread_get_segment_merge_interval)(void)
127{
128 return s_segment_merge_interval;
129}
130
131/** Set the segment merging interval. */
132void DRD_(thread_set_segment_merge_interval)(const int i)
133{
134 s_segment_merge_interval = i;
135}
136
sewardjaf44c822007-11-25 14:01:38 +0000137/**
bart86a87df2009-03-04 19:26:47 +0000138 * Convert Valgrind's ThreadId into a DrdThreadId.
139 *
140 * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
141 * Valgrind ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000142 */
bart62a784c2009-02-15 13:11:14 +0000143DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000144{
bartbedfd232009-03-26 19:07:15 +0000145 int i;
sewardjaf44c822007-11-25 14:01:38 +0000146
bartbedfd232009-03-26 19:07:15 +0000147 if (tid == VG_INVALID_THREADID)
148 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000149
bartbedfd232009-03-26 19:07:15 +0000150 for (i = 1; i < DRD_N_THREADS; i++)
151 {
152 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
153 && DRD_(g_threadinfo)[i].vg_threadid == tid)
154 {
155 return i;
156 }
157 }
sewardjaf44c822007-11-25 14:01:38 +0000158
bartbedfd232009-03-26 19:07:15 +0000159 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000160}
161
bart86a87df2009-03-04 19:26:47 +0000162/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000163static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000164{
bartbedfd232009-03-26 19:07:15 +0000165 int i;
sewardjaf44c822007-11-25 14:01:38 +0000166
bartbedfd232009-03-26 19:07:15 +0000167 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000168
bartbedfd232009-03-26 19:07:15 +0000169 for (i = 1; i < DRD_N_THREADS; i++)
170 {
171 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
172 && DRD_(g_threadinfo)[i].posix_thread_exists == False
173 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
174 {
175 tl_assert(! DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000176
bartbedfd232009-03-26 19:07:15 +0000177 DRD_(g_threadinfo)[i].vg_thread_exists = True;
178 DRD_(g_threadinfo)[i].vg_threadid = tid;
179 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
180 DRD_(g_threadinfo)[i].stack_min = 0;
181 DRD_(g_threadinfo)[i].stack_min_min = 0;
182 DRD_(g_threadinfo)[i].stack_startup = 0;
183 DRD_(g_threadinfo)[i].stack_max = 0;
bartd45d9952009-05-31 18:53:54 +0000184 DRD_(thread_set_name)(i, "");
185 DRD_(g_threadinfo)[i].is_recording_loads = True;
186 DRD_(g_threadinfo)[i].is_recording_stores = True;
bartdd75cdf2009-07-24 08:20:10 +0000187 DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
bartbedfd232009-03-26 19:07:15 +0000188 DRD_(g_threadinfo)[i].synchr_nesting = 0;
189 tl_assert(DRD_(g_threadinfo)[i].first == 0);
190 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000191
bartbedfd232009-03-26 19:07:15 +0000192 tl_assert(DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000193
bartbedfd232009-03-26 19:07:15 +0000194 return i;
195 }
196 }
sewardjaf44c822007-11-25 14:01:38 +0000197
bartbedfd232009-03-26 19:07:15 +0000198 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000199
bartbedfd232009-03-26 19:07:15 +0000200 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000201}
202
bart86a87df2009-03-04 19:26:47 +0000203/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000204DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000205{
bartbedfd232009-03-26 19:07:15 +0000206 int i;
sewardjaf44c822007-11-25 14:01:38 +0000207
bartbedfd232009-03-26 19:07:15 +0000208 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000209
bartbedfd232009-03-26 19:07:15 +0000210 for (i = 1; i < DRD_N_THREADS; i++)
211 {
212 if (DRD_(g_threadinfo)[i].posix_thread_exists
213 && DRD_(g_threadinfo)[i].pt_threadid == tid)
214 {
215 return i;
216 }
217 }
218 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000219}
220
bart86a87df2009-03-04 19:26:47 +0000221/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000222ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000223{
bartbedfd232009-03-26 19:07:15 +0000224 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
225 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000226
bartbedfd232009-03-26 19:07:15 +0000227 return (DRD_(g_threadinfo)[tid].vg_thread_exists
228 ? DRD_(g_threadinfo)[tid].vg_threadid
229 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000230}
231
bart8f822af2009-06-08 18:20:42 +0000232#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart324a23b2009-02-15 12:14:52 +0000233/**
234 * Sanity check of the doubly linked list of segments referenced by a
235 * ThreadInfo struct.
236 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000237 */
bart62a784c2009-02-15 13:11:14 +0000238static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000239{
bartbedfd232009-03-26 19:07:15 +0000240 Segment* p;
bart8f822af2009-06-08 18:20:42 +0000241
bartbedfd232009-03-26 19:07:15 +0000242 for (p = ti->first; p; p = p->next) {
243 if (p->next && p->next->prev != p)
244 return False;
245 if (p->next == 0 && p != ti->last)
246 return False;
247 }
248 for (p = ti->last; p; p = p->prev) {
249 if (p->prev && p->prev->next != p)
250 return False;
251 if (p->prev == 0 && p != ti->first)
252 return False;
253 }
254 return True;
sewardjaf44c822007-11-25 14:01:38 +0000255}
bart23d3a4e2008-04-05 12:53:00 +0000256#endif
sewardjaf44c822007-11-25 14:01:38 +0000257
bart439c55f2009-02-15 10:38:37 +0000258/**
259 * Create the first segment for a newly started thread.
260 *
261 * This function is called from the handler installed via
262 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
263 * from the context of the creator thread, before the new thread has been
264 * created.
bart86a87df2009-03-04 19:26:47 +0000265 *
266 * @param[in] creator DRD thread ID of the creator thread.
267 * @param[in] vg_created Valgrind thread ID of the created thread.
268 *
269 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000270 */
bart62a784c2009-02-15 13:11:14 +0000271DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
272 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000273{
bartbedfd232009-03-26 19:07:15 +0000274 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000275
bartbedfd232009-03-26 19:07:15 +0000276 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
277 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
278 tl_assert(0 <= (int)created && created < DRD_N_THREADS
279 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000280
bartbedfd232009-03-26 19:07:15 +0000281 tl_assert(DRD_(g_threadinfo)[created].first == 0);
282 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart8f822af2009-06-08 18:20:42 +0000283 /* Create an initial segment for the newly created thread. */
bartbedfd232009-03-26 19:07:15 +0000284 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000285
bartbedfd232009-03-26 19:07:15 +0000286 return created;
sewardjaf44c822007-11-25 14:01:38 +0000287}
288
bart439c55f2009-02-15 10:38:37 +0000289/**
bart86a87df2009-03-04 19:26:47 +0000290 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
291 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000292 * on the newly created thread, e.g. from the handler installed via
293 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000294 *
295 * @param[in] vg_created Valgrind thread ID of the newly created thread.
296 *
297 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000298 */
bart62a784c2009-02-15 13:11:14 +0000299DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000300{
bartbedfd232009-03-26 19:07:15 +0000301 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000302
bartbedfd232009-03-26 19:07:15 +0000303 tl_assert(0 <= (int)created && created < DRD_N_THREADS
304 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000305
bartbedfd232009-03-26 19:07:15 +0000306 DRD_(g_threadinfo)[created].stack_max
307 = VG_(thread_get_stack_max)(vg_created);
308 DRD_(g_threadinfo)[created].stack_startup
309 = DRD_(g_threadinfo)[created].stack_max;
310 DRD_(g_threadinfo)[created].stack_min
311 = DRD_(g_threadinfo)[created].stack_max;
312 DRD_(g_threadinfo)[created].stack_min_min
313 = DRD_(g_threadinfo)[created].stack_max;
314 DRD_(g_threadinfo)[created].stack_size
315 = VG_(thread_get_stack_size)(vg_created);
316 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000317
bartbedfd232009-03-26 19:07:15 +0000318 return created;
bart439c55f2009-02-15 10:38:37 +0000319}
bart09dc13f2009-02-14 15:13:31 +0000320
bart324a23b2009-02-15 12:14:52 +0000321/**
322 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
323 * after thread drd_joiner joined thread drd_joinee.
324 */
bart09dc13f2009-02-14 15:13:31 +0000325void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
326{
bartbedfd232009-03-26 19:07:15 +0000327 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
328 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
bart7627be32009-06-06 12:26:05 +0000329
bartbedfd232009-03-26 19:07:15 +0000330 DRD_(thread_new_segment)(drd_joiner);
bart8f822af2009-06-08 18:20:42 +0000331 DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
bart7627be32009-06-06 12:26:05 +0000332 DRD_(thread_new_segment)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000333
bartbedfd232009-03-26 19:07:15 +0000334 if (s_trace_fork_join)
335 {
336 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
bartbedfd232009-03-26 19:07:15 +0000337 const unsigned msg_size = 256;
338 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000339
bartbedfd232009-03-26 19:07:15 +0000340 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
341 tl_assert(msg);
342 VG_(snprintf)(msg, msg_size,
bart63c92ea2009-07-19 17:53:56 +0000343 "drd_post_thread_join joiner = %d, joinee = %d",
344 drd_joiner, drd_joinee);
bartbedfd232009-03-26 19:07:15 +0000345 if (joiner)
346 {
bart8f822af2009-06-08 18:20:42 +0000347 char* vc;
348
349 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
bartbedfd232009-03-26 19:07:15 +0000350 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart8f822af2009-06-08 18:20:42 +0000351 ", new vc: %s", vc);
352 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000353 }
sewardj1e29ebc2009-07-15 14:49:17 +0000354 VG_(message)(Vg_DebugMsg, "%s\n", msg);
bartbedfd232009-03-26 19:07:15 +0000355 VG_(free)(msg);
356 }
bart09dc13f2009-02-14 15:13:31 +0000357
bartbedfd232009-03-26 19:07:15 +0000358 if (! DRD_(get_check_stack_accesses)())
359 {
360 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
361 - DRD_(thread_get_stack_size)(drd_joinee),
362 DRD_(thread_get_stack_max)(drd_joinee));
363 }
364 DRD_(clientobj_delete_thread)(drd_joinee);
365 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000366}
367
bart324a23b2009-02-15 12:14:52 +0000368/**
369 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
370 * and accesses this data structure from multiple threads without locking.
371 * Any conflicting accesses in the range stack_startup..stack_max will be
372 * ignored.
373 */
bart62a784c2009-02-15 13:11:14 +0000374void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
375 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000376{
bartbedfd232009-03-26 19:07:15 +0000377 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
378 && tid != DRD_INVALID_THREADID);
379 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
380 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
381 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000382}
383
bart86a87df2009-03-04 19:26:47 +0000384/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000385Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000386{
bartbedfd232009-03-26 19:07:15 +0000387 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
388 && tid != DRD_INVALID_THREADID);
389 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000390}
391
bart86a87df2009-03-04 19:26:47 +0000392/**
393 * Return the lowest value that was ever assigned to the stack pointer
394 * for the specified thread.
395 */
bart62a784c2009-02-15 13:11:14 +0000396Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000397{
bartbedfd232009-03-26 19:07:15 +0000398 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
399 && tid != DRD_INVALID_THREADID);
400 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000401}
402
bart86a87df2009-03-04 19:26:47 +0000403/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000404Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000405{
bartbedfd232009-03-26 19:07:15 +0000406 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
407 && tid != DRD_INVALID_THREADID);
408 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000409}
410
bart86a87df2009-03-04 19:26:47 +0000411/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000412SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000413{
bartbedfd232009-03-26 19:07:15 +0000414 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
415 && tid != DRD_INVALID_THREADID);
416 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000417}
418
bart09dc13f2009-02-14 15:13:31 +0000419/**
420 * Clean up thread-specific data structures. Call this just after
421 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000422 */
bart62a784c2009-02-15 13:11:14 +0000423void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000424{
bartbedfd232009-03-26 19:07:15 +0000425 Segment* sg;
426 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000427
bartbedfd232009-03-26 19:07:15 +0000428 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000429
bartbedfd232009-03-26 19:07:15 +0000430 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
431 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
432 {
433 sg_prev = sg->prev;
434 sg->prev = 0;
435 sg->next = 0;
436 DRD_(sg_put)(sg);
437 }
438 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
439 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
440 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
441 DRD_(g_threadinfo)[tid].first = 0;
442 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000443
bartbedfd232009-03-26 19:07:15 +0000444 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000445}
446
bart324a23b2009-02-15 12:14:52 +0000447/**
448 * Called after a thread performed its last memory access and before
449 * thread_delete() is called. Note: thread_delete() is only called for
450 * joinable threads, not for detached threads.
451 */
bart62a784c2009-02-15 13:11:14 +0000452void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000453{
bartbedfd232009-03-26 19:07:15 +0000454 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
455 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000456
bartbedfd232009-03-26 19:07:15 +0000457 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000458
bartbedfd232009-03-26 19:07:15 +0000459 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
460 {
461 /*
462 * Once a detached thread has finished, its stack is deallocated and
463 * should no longer be taken into account when computing the conflict set.
464 */
465 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000466
bartbedfd232009-03-26 19:07:15 +0000467 /*
468 * For a detached thread, calling pthread_exit() invalidates the
469 * POSIX thread ID associated with the detached thread. For joinable
470 * POSIX threads however, the POSIX thread ID remains live after the
471 * pthread_exit() call until pthread_join() is called.
472 */
473 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
474 }
sewardjaf44c822007-11-25 14:01:38 +0000475}
476
bart9b2974a2008-09-27 12:35:31 +0000477/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000478void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000479{
bartbedfd232009-03-26 19:07:15 +0000480 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
481 && tid != DRD_INVALID_THREADID);
482 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000483
bartbedfd232009-03-26 19:07:15 +0000484 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000485}
486
barte7dff242009-04-23 17:12:39 +0000487/**
488 * Store the POSIX thread ID for the specified thread.
489 *
490 * @note This function can be called two times for the same thread -- see also
491 * the comment block preceding the pthread_create() wrapper in
492 * drd_pthread_intercepts.c.
493 */
bart62a784c2009-02-15 13:11:14 +0000494void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000495{
bartbedfd232009-03-26 19:07:15 +0000496 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
497 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000498 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
499 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000500 tl_assert(ptid != INVALID_POSIX_THREADID);
501 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
502 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000503}
504
bart86a87df2009-03-04 19:26:47 +0000505/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000506Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000507{
bartbedfd232009-03-26 19:07:15 +0000508 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
509 && tid != DRD_INVALID_THREADID);
510 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000511}
512
bart86a87df2009-03-04 19:26:47 +0000513/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000514void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000515{
bartbedfd232009-03-26 19:07:15 +0000516 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
517 && tid != DRD_INVALID_THREADID);
518 tl_assert(!! joinable == joinable);
519 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bart8f822af2009-06-08 18:20:42 +0000520
bartbedfd232009-03-26 19:07:15 +0000521 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000522}
523
bartdd75cdf2009-07-24 08:20:10 +0000524/** Tells DRD that the calling thread is about to enter pthread_create(). */
525void DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
526{
527 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
528 && tid != DRD_INVALID_THREADID);
529 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
530 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
531
532 DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
533}
534
535/** Tells DRD that the calling thread has left pthread_create(). */
536void DRD_(thread_left_pthread_create)(const DrdThreadId tid)
537{
538 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
539 && tid != DRD_INVALID_THREADID);
540 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
541 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
542
543 DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
544}
545
bartd45d9952009-05-31 18:53:54 +0000546/** Obtain the thread number and the user-assigned thread name. */
547const char* DRD_(thread_get_name)(const DrdThreadId tid)
548{
549 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
550 && tid != DRD_INVALID_THREADID);
551
552 return DRD_(g_threadinfo)[tid].name;
553}
554
555/** Set the name of the specified thread. */
556void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
557{
558 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
559 && tid != DRD_INVALID_THREADID);
560
561 if (name == NULL || name[0] == 0)
562 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
563 sizeof(DRD_(g_threadinfo)[tid].name),
564 "Thread %d",
565 tid);
566 else
567 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
568 sizeof(DRD_(g_threadinfo)[tid].name),
569 "Thread %d (%s)",
570 tid, name);
571 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
572}
573
bart86a87df2009-03-04 19:26:47 +0000574/**
575 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
576 * conflict set.
577 */
bart62a784c2009-02-15 13:11:14 +0000578void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000579{
bartbedfd232009-03-26 19:07:15 +0000580 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000581
bartbedfd232009-03-26 19:07:15 +0000582 if (vg_tid != s_vg_running_tid)
583 {
584 DRD_(thread_set_running_tid)(vg_tid,
585 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
586 }
sewardj8b09d4f2007-12-04 21:27:18 +0000587
bartbedfd232009-03-26 19:07:15 +0000588 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
589 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000590}
591
bart86a87df2009-03-04 19:26:47 +0000592/**
593 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
594 * conflict set.
595 */
bart62a784c2009-02-15 13:11:14 +0000596void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
597 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000598{
bartbedfd232009-03-26 19:07:15 +0000599 tl_assert(vg_tid != VG_INVALID_THREADID);
600 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000601
bartbedfd232009-03-26 19:07:15 +0000602 if (vg_tid != s_vg_running_tid)
603 {
604 if (s_trace_context_switches
605 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
606 {
607 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +0000608 "Context switch from thread %d to thread %d;"
sewardj1e29ebc2009-07-15 14:49:17 +0000609 " segments: %llu\n",
bart63c92ea2009-07-19 17:53:56 +0000610 DRD_(g_drd_running_tid), drd_tid,
bartbedfd232009-03-26 19:07:15 +0000611 DRD_(sg_get_segments_alive_count)());
612 }
613 s_vg_running_tid = vg_tid;
614 DRD_(g_drd_running_tid) = drd_tid;
615 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
616 s_context_switch_count++;
617 }
sewardj8b09d4f2007-12-04 21:27:18 +0000618
bartbedfd232009-03-26 19:07:15 +0000619 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
620 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000621}
622
bart86a87df2009-03-04 19:26:47 +0000623/**
624 * Increase the synchronization nesting counter. Must be called before the
625 * client calls a synchronization function.
626 */
bart62a784c2009-02-15 13:11:14 +0000627int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000628{
bartbedfd232009-03-26 19:07:15 +0000629 tl_assert(DRD_(IsValidDrdThreadId)(tid));
630 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000631}
632
bart86a87df2009-03-04 19:26:47 +0000633/**
634 * Decrease the synchronization nesting counter. Must be called after the
635 * client left a synchronization function.
636 */
bart62a784c2009-02-15 13:11:14 +0000637int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000638{
bartbedfd232009-03-26 19:07:15 +0000639 tl_assert(DRD_(IsValidDrdThreadId)(tid));
640 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
641 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000642}
643
bart86a87df2009-03-04 19:26:47 +0000644/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000645int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000646{
bartbedfd232009-03-26 19:07:15 +0000647 tl_assert(DRD_(IsValidDrdThreadId)(tid));
648 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000649}
650
bart1a473c72008-03-13 19:03:38 +0000651/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000652static
bart86a87df2009-03-04 19:26:47 +0000653void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000654{
bartbedfd232009-03-26 19:07:15 +0000655 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
656 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000657
658#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
659 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
660#endif
661
bartbedfd232009-03-26 19:07:15 +0000662 sg->prev = DRD_(g_threadinfo)[tid].last;
663 sg->next = 0;
664 if (DRD_(g_threadinfo)[tid].last)
665 DRD_(g_threadinfo)[tid].last->next = sg;
666 DRD_(g_threadinfo)[tid].last = sg;
667 if (DRD_(g_threadinfo)[tid].first == 0)
668 DRD_(g_threadinfo)[tid].first = sg;
bart8f822af2009-06-08 18:20:42 +0000669
670#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
671 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
672#endif
sewardjaf44c822007-11-25 14:01:38 +0000673}
674
bart324a23b2009-02-15 12:14:52 +0000675/**
676 * Remove a segment from the segment list of thread threadid, and free the
677 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000678 */
bart62a784c2009-02-15 13:11:14 +0000679static
bart86a87df2009-03-04 19:26:47 +0000680void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000681{
bartbedfd232009-03-26 19:07:15 +0000682 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
683 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000684
685#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
686 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
687#endif
bart26f73e12008-02-24 18:37:08 +0000688
bartbedfd232009-03-26 19:07:15 +0000689 if (sg->prev)
690 sg->prev->next = sg->next;
691 if (sg->next)
692 sg->next->prev = sg->prev;
693 if (sg == DRD_(g_threadinfo)[tid].first)
694 DRD_(g_threadinfo)[tid].first = sg->next;
695 if (sg == DRD_(g_threadinfo)[tid].last)
696 DRD_(g_threadinfo)[tid].last = sg->prev;
697 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000698
bart8f822af2009-06-08 18:20:42 +0000699#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
700 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
701#endif
sewardjaf44c822007-11-25 14:01:38 +0000702}
703
bart86a87df2009-03-04 19:26:47 +0000704/**
705 * Returns a pointer to the vector clock of the most recent segment associated
706 * with thread 'tid'.
707 */
bart62a784c2009-02-15 13:11:14 +0000708VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000709{
bartbedfd232009-03-26 19:07:15 +0000710 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
711 && tid != DRD_INVALID_THREADID);
712 tl_assert(DRD_(g_threadinfo)[tid].last);
713 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000714}
715
bart324a23b2009-02-15 12:14:52 +0000716/**
717 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000718 */
bart62a784c2009-02-15 13:11:14 +0000719void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000720{
bartbedfd232009-03-26 19:07:15 +0000721 tl_assert(sg);
722 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
723 && tid != DRD_INVALID_THREADID);
724 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000725
bartbedfd232009-03-26 19:07:15 +0000726 DRD_(sg_put)(*sg);
727 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000728}
729
sewardjaf44c822007-11-25 14:01:38 +0000730/**
731 * Compute the minimum of all latest vector clocks of all threads
732 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000733 *
sewardjaf44c822007-11-25 14:01:38 +0000734 * @param vc pointer to a vectorclock, holds result upon return.
735 */
bart62a784c2009-02-15 13:11:14 +0000736static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000737{
bartbedfd232009-03-26 19:07:15 +0000738 unsigned i;
739 Bool first;
740 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000741
bartbedfd232009-03-26 19:07:15 +0000742 first = True;
bart8f822af2009-06-08 18:20:42 +0000743 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000744 {
745 latest_sg = DRD_(g_threadinfo)[i].last;
746 if (latest_sg)
747 {
748 if (first)
749 DRD_(vc_assign)(vc, &latest_sg->vc);
750 else
751 DRD_(vc_min)(vc, &latest_sg->vc);
752 first = False;
753 }
754 }
sewardjaf44c822007-11-25 14:01:38 +0000755}
756
bart86a87df2009-03-04 19:26:47 +0000757/**
758 * Compute the maximum of all latest vector clocks of all threads.
759 *
760 * @param vc pointer to a vectorclock, holds result upon return.
761 */
bart62a784c2009-02-15 13:11:14 +0000762static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000763{
bartbedfd232009-03-26 19:07:15 +0000764 unsigned i;
765 Bool first;
766 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000767
bartbedfd232009-03-26 19:07:15 +0000768 first = True;
bart8f822af2009-06-08 18:20:42 +0000769 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000770 {
771 latest_sg = DRD_(g_threadinfo)[i].last;
772 if (latest_sg)
773 {
774 if (first)
775 DRD_(vc_assign)(vc, &latest_sg->vc);
776 else
777 DRD_(vc_combine)(vc, &latest_sg->vc);
778 first = False;
779 }
780 }
sewardjaf44c822007-11-25 14:01:38 +0000781}
782
783/**
bart5bd9f2d2008-03-03 20:31:58 +0000784 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000785 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000786 * data race.
787 */
bart8f822af2009-06-08 18:20:42 +0000788static void thread_discard_ordered_segments(void)
sewardjaf44c822007-11-25 14:01:38 +0000789{
bartbedfd232009-03-26 19:07:15 +0000790 unsigned i;
791 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000792
bartbedfd232009-03-26 19:07:15 +0000793 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000794
bartbedfd232009-03-26 19:07:15 +0000795 DRD_(vc_init)(&thread_vc_min, 0, 0);
796 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
797 if (DRD_(sg_get_trace)())
798 {
bart8f822af2009-06-08 18:20:42 +0000799 char *vc_min, *vc_max;
bartbedfd232009-03-26 19:07:15 +0000800 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000801
bartbedfd232009-03-26 19:07:15 +0000802 DRD_(vc_init)(&thread_vc_max, 0, 0);
803 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart8f822af2009-06-08 18:20:42 +0000804 vc_min = DRD_(vc_aprint)(&thread_vc_min);
805 vc_max = DRD_(vc_aprint)(&thread_vc_max);
806 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000807 "Discarding ordered segments -- min vc is %s, max vc is %s\n",
bart8f822af2009-06-08 18:20:42 +0000808 vc_min, vc_max);
809 VG_(free)(vc_min);
810 VG_(free)(vc_max);
bartbedfd232009-03-26 19:07:15 +0000811 DRD_(vc_cleanup)(&thread_vc_max);
812 }
sewardjaf44c822007-11-25 14:01:38 +0000813
bart8f822af2009-06-08 18:20:42 +0000814 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000815 {
816 Segment* sg;
817 Segment* sg_next;
818 for (sg = DRD_(g_threadinfo)[i].first;
819 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
820 sg = sg_next)
821 {
822 thread_discard_segment(i, sg);
823 }
824 }
825 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000826}
827
bart324a23b2009-02-15 12:14:52 +0000828/**
bart8f822af2009-06-08 18:20:42 +0000829 * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
830 * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
831 * all segments in the set CS are ordered consistently against both sg1 and
832 * sg2. The set CS is defined as the set of segments that can immediately
833 * precede future segments via inter-thread synchronization operations. In
834 * DRD the set CS consists of the latest segment of each thread combined with
835 * all segments for which the reference count is strictly greater than one.
836 * The code below is an optimized version of the following:
837 *
838 * for (i = 0; i < DRD_N_THREADS; i++)
839 * {
840 * Segment* sg;
841 *
842 * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
843 * {
844 * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
845 * {
846 * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
847 * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
848 * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
849 * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
850 * {
851 * return False;
852 * }
853 * }
854 * }
855 * }
856 */
857static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
858 Segment* const sg1,
859 Segment* const sg2)
860{
861 unsigned i;
862
863 tl_assert(sg1->next);
864 tl_assert(sg2->next);
865 tl_assert(sg1->next == sg2);
866 tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
867
868 for (i = 0; i < DRD_N_THREADS; i++)
869 {
870 Segment* sg;
871
872 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
873 {
874 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
875 {
876 if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
877 break;
878 if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
879 return False;
880 }
881 }
882 for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
883 {
884 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
885 {
886 if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
887 break;
888 if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
889 return False;
890 }
891 }
892 }
893 return True;
894}
895
896/**
bart324a23b2009-02-15 12:14:52 +0000897 * Merge all segments that may be merged without triggering false positives
898 * or discarding real data races. For the theoretical background of segment
bart8f822af2009-06-08 18:20:42 +0000899 * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
900 * and Koen De Bosschere. Bounding the number of segment histories during
901 * data race detection. Parallel Computing archive, Volume 28, Issue 9,
902 * pp 1221-1238, September 2002. This paper contains a proof that merging
903 * consecutive segments for which the property equiv(s1,s2) holds can be
904 * merged without reducing the accuracy of datarace detection. Furthermore
905 * it is also proven that the total number of all segments will never grow
906 * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
907 * every time a new segment is created. The property equiv(s1, s2) is defined
908 * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
909 * clocks of segments s and s1 are ordered in the same way as those of segments
910 * s and s2. The set CS is defined as the set of existing segments s that have
911 * the potential to conflict with not yet created segments, either because the
912 * segment s is the latest segment of a thread or because it can become the
913 * immediate predecessor of a new segment due to a synchronization operation.
barta9c37392008-03-22 09:38:48 +0000914 */
915static void thread_merge_segments(void)
916{
bartbedfd232009-03-26 19:07:15 +0000917 unsigned i;
barta9c37392008-03-22 09:38:48 +0000918
bart8f822af2009-06-08 18:20:42 +0000919 s_new_segments_since_last_merge = 0;
920
921 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000922 {
923 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000924
bart8f822af2009-06-08 18:20:42 +0000925#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
926 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
927#endif
barta9c37392008-03-22 09:38:48 +0000928
bartbedfd232009-03-26 19:07:15 +0000929 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000930 {
bartbedfd232009-03-26 19:07:15 +0000931 if (DRD_(sg_get_refcnt)(sg) == 1
932 && sg->next
933 && DRD_(sg_get_refcnt)(sg->next) == 1
bart8f822af2009-06-08 18:20:42 +0000934 && sg->next->next
935 && thread_consistent_segment_ordering(i, sg, sg->next))
bartbedfd232009-03-26 19:07:15 +0000936 {
937 /* Merge sg and sg->next into sg. */
938 DRD_(sg_merge)(sg, sg->next);
939 thread_discard_segment(i, sg->next);
940 }
barta9c37392008-03-22 09:38:48 +0000941 }
barta9c37392008-03-22 09:38:48 +0000942
bart8f822af2009-06-08 18:20:42 +0000943#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
944 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
945#endif
bartbedfd232009-03-26 19:07:15 +0000946 }
barta9c37392008-03-22 09:38:48 +0000947}
948
bart324a23b2009-02-15 12:14:52 +0000949/**
bart324a23b2009-02-15 12:14:52 +0000950 * Create a new segment for the specified thread, and discard any segments
951 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000952 */
bart62a784c2009-02-15 13:11:14 +0000953void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000954{
bart8f822af2009-06-08 18:20:42 +0000955 Segment* last_sg;
bartbedfd232009-03-26 19:07:15 +0000956 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000957
bartbedfd232009-03-26 19:07:15 +0000958 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
959 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000960 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000961
bart8f822af2009-06-08 18:20:42 +0000962 last_sg = DRD_(g_threadinfo)[tid].last;
bartbedfd232009-03-26 19:07:15 +0000963 new_sg = DRD_(sg_new)(tid, tid);
964 thread_append_segment(tid, new_sg);
bart8f822af2009-06-08 18:20:42 +0000965 if (tid == DRD_(g_drd_running_tid) && last_sg)
barte5214662009-06-21 11:51:23 +0000966 {
bart8f822af2009-06-08 18:20:42 +0000967 DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
barte5214662009-06-21 11:51:23 +0000968 s_update_conflict_set_new_sg_count++;
969 }
bartd66e3a82008-04-06 15:02:17 +0000970
bart8f822af2009-06-08 18:20:42 +0000971 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000972
bart8f822af2009-06-08 18:20:42 +0000973 if (s_segment_merging
974 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
bartbedfd232009-03-26 19:07:15 +0000975 {
bart8f822af2009-06-08 18:20:42 +0000976 thread_discard_ordered_segments();
bartbedfd232009-03-26 19:07:15 +0000977 thread_merge_segments();
978 }
sewardjaf44c822007-11-25 14:01:38 +0000979}
980
bart26f73e12008-02-24 18:37:08 +0000981/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart8f822af2009-06-08 18:20:42 +0000982void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000983{
bartbedfd232009-03-26 19:07:15 +0000984 tl_assert(joiner != joinee);
985 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
986 && joiner != DRD_INVALID_THREADID);
987 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
988 && joinee != DRD_INVALID_THREADID);
989 tl_assert(DRD_(g_threadinfo)[joiner].last);
990 tl_assert(DRD_(g_threadinfo)[joinee].last);
bart8f822af2009-06-08 18:20:42 +0000991
992 if (DRD_(sg_get_trace)())
993 {
994 char *str1, *str2;
995 str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
996 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +0000997 VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
bart8f822af2009-06-08 18:20:42 +0000998 str1, str2);
999 VG_(free)(str1);
1000 VG_(free)(str2);
1001 }
barte5214662009-06-21 11:51:23 +00001002 if (joiner == DRD_(g_drd_running_tid))
1003 {
1004 VectorClock old_vc;
1005
1006 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[joiner].last->vc);
1007 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001008 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001009 DRD_(thread_update_conflict_set)(joiner, &old_vc);
1010 s_update_conflict_set_join_count++;
1011 DRD_(vc_cleanup)(&old_vc);
1012 }
1013 else
1014 {
1015 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001016 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001017 }
1018
1019 thread_discard_ordered_segments();
1020
bart8f822af2009-06-08 18:20:42 +00001021 if (DRD_(sg_get_trace)())
1022 {
1023 char* str;
1024 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001025 VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
bart8f822af2009-06-08 18:20:42 +00001026 VG_(free)(str);
1027 }
sewardjaf44c822007-11-25 14:01:38 +00001028}
1029
bart324a23b2009-02-15 12:14:52 +00001030/**
bart8f822af2009-06-08 18:20:42 +00001031 * Update the vector clock of the last segment of thread tid with the
bartf6ec1fe2009-06-21 18:07:35 +00001032 * the vector clock of segment sg.
bart26f73e12008-02-24 18:37:08 +00001033 */
bartf6ec1fe2009-06-21 18:07:35 +00001034static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
sewardjaf44c822007-11-25 14:01:38 +00001035{
bart8f822af2009-06-08 18:20:42 +00001036 const VectorClock* const vc = &sg->vc;
1037
bartbedfd232009-03-26 19:07:15 +00001038 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1039 && tid != DRD_INVALID_THREADID);
1040 tl_assert(DRD_(g_threadinfo)[tid].last);
bart8f822af2009-06-08 18:20:42 +00001041 tl_assert(sg);
bartbedfd232009-03-26 19:07:15 +00001042 tl_assert(vc);
bart8f822af2009-06-08 18:20:42 +00001043
1044 if (tid != sg->tid)
1045 {
1046 VectorClock old_vc;
1047
1048 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
1049 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
1050 if (DRD_(sg_get_trace)())
1051 {
1052 char *str1, *str2;
1053 str1 = DRD_(vc_aprint)(&old_vc);
1054 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001055 VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
bart8f822af2009-06-08 18:20:42 +00001056 VG_(free)(str1);
1057 VG_(free)(str2);
1058 }
barte5214662009-06-21 11:51:23 +00001059
bart8f822af2009-06-08 18:20:42 +00001060 thread_discard_ordered_segments();
barte5214662009-06-21 11:51:23 +00001061
bart8f822af2009-06-08 18:20:42 +00001062 DRD_(thread_update_conflict_set)(tid, &old_vc);
barte5214662009-06-21 11:51:23 +00001063 s_update_conflict_set_sync_count++;
1064
bart8f822af2009-06-08 18:20:42 +00001065 DRD_(vc_cleanup)(&old_vc);
1066 }
1067 else
1068 {
1069 tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
1070 }
sewardjaf44c822007-11-25 14:01:38 +00001071}
1072
bart324a23b2009-02-15 12:14:52 +00001073/**
bartf6ec1fe2009-06-21 18:07:35 +00001074 * Create a new segment for thread tid and update the vector clock of the last
1075 * segment of this thread with the the vector clock of segment sg. Call this
1076 * function after thread tid had to wait because of thread synchronization
1077 * until the memory accesses in the segment sg finished.
1078 */
1079void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
1080{
1081 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1082 && tid != DRD_INVALID_THREADID);
1083 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1084 tl_assert(sg);
1085
1086 thread_append_segment(tid, DRD_(sg_new)(tid, tid));
1087
1088 thread_combine_vc_sync(tid, sg);
1089
1090 if (s_segment_merging
1091 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1092 {
1093 thread_discard_ordered_segments();
1094 thread_merge_segments();
1095 }
1096}
1097
1098/**
bart324a23b2009-02-15 12:14:52 +00001099 * Call this function whenever a thread is no longer using the memory
1100 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1101 * increase.
bart26f73e12008-02-24 18:37:08 +00001102 */
bart62a784c2009-02-15 13:11:14 +00001103void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +00001104{
bartbedfd232009-03-26 19:07:15 +00001105 DrdThreadId other_user;
1106 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001107
bartbedfd232009-03-26 19:07:15 +00001108 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
1109 other_user = DRD_INVALID_THREADID;
bart8f822af2009-06-08 18:20:42 +00001110 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001111 {
1112 Segment* p;
1113 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +00001114 {
bartbedfd232009-03-26 19:07:15 +00001115 if (other_user == DRD_INVALID_THREADID
1116 && i != DRD_(g_drd_running_tid))
1117 {
bart8f822af2009-06-08 18:20:42 +00001118 if (UNLIKELY(DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2)))
bartbedfd232009-03-26 19:07:15 +00001119 {
1120 other_user = i;
1121 }
1122 continue;
1123 }
bart8f822af2009-06-08 18:20:42 +00001124 DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
sewardjaf44c822007-11-25 14:01:38 +00001125 }
bartbedfd232009-03-26 19:07:15 +00001126 }
sewardjaf44c822007-11-25 14:01:38 +00001127
bartbedfd232009-03-26 19:07:15 +00001128 /*
1129 * If any other thread had accessed memory in [ a1, a2 [, update the
1130 * conflict set.
1131 */
1132 if (other_user != DRD_INVALID_THREADID
1133 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
1134 {
1135 thread_compute_conflict_set(&DRD_(g_conflict_set),
1136 DRD_(thread_get_running_tid)());
1137 }
sewardjaf44c822007-11-25 14:01:38 +00001138}
1139
bartd45d9952009-05-31 18:53:54 +00001140/** Specify whether memory loads should be recorded. */
1141void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001142{
bartbedfd232009-03-26 19:07:15 +00001143 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1144 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001145 tl_assert(enabled == !! enabled);
1146
1147 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +00001148}
1149
bartd45d9952009-05-31 18:53:54 +00001150/** Specify whether memory stores should be recorded. */
1151void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001152{
bartbedfd232009-03-26 19:07:15 +00001153 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1154 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001155 tl_assert(enabled == !! enabled);
1156
1157 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +00001158}
1159
bart86a87df2009-03-04 19:26:47 +00001160/**
1161 * Print the segment information for all threads.
1162 *
1163 * This function is only used for debugging purposes.
1164 */
bart62a784c2009-02-15 13:11:14 +00001165void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +00001166{
bartbedfd232009-03-26 19:07:15 +00001167 unsigned i;
1168 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001169
bart8f822af2009-06-08 18:20:42 +00001170 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001171 {
1172 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +00001173 {
bartbedfd232009-03-26 19:07:15 +00001174 VG_(printf)("**************\n"
1175 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
1176 "**************\n",
1177 i,
1178 DRD_(g_threadinfo)[i].vg_thread_exists,
1179 DRD_(g_threadinfo)[i].vg_threadid,
1180 DRD_(g_threadinfo)[i].posix_thread_exists,
1181 DRD_(g_threadinfo)[i].pt_threadid,
1182 DRD_(g_threadinfo)[i].detached_posix_thread);
1183 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1184 {
1185 DRD_(sg_print)(p);
1186 }
sewardjaf44c822007-11-25 14:01:38 +00001187 }
bartbedfd232009-03-26 19:07:15 +00001188 }
sewardjaf44c822007-11-25 14:01:38 +00001189}
1190
bart86a87df2009-03-04 19:26:47 +00001191/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001192static void show_call_stack(const DrdThreadId tid,
1193 const Char* const msg,
1194 ExeContext* const callstack)
1195{
bartbedfd232009-03-26 19:07:15 +00001196 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +00001197
bart63c92ea2009-07-19 17:53:56 +00001198 VG_(message)(Vg_UserMsg, "%s (thread %d)\n", msg, tid);
sewardjaf44c822007-11-25 14:01:38 +00001199
bartbedfd232009-03-26 19:07:15 +00001200 if (vg_tid != VG_INVALID_THREADID)
1201 {
1202 if (callstack)
1203 {
1204 VG_(pp_ExeContext)(callstack);
1205 }
1206 else
1207 {
1208 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1209 }
1210 }
1211 else
1212 {
1213 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001214 " (thread finished, call stack no longer available)\n");
bartbedfd232009-03-26 19:07:15 +00001215 }
sewardjaf44c822007-11-25 14:01:38 +00001216}
1217
bart86a87df2009-03-04 19:26:47 +00001218/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001219static void
1220thread_report_conflicting_segments_segment(const DrdThreadId tid,
1221 const Addr addr,
1222 const SizeT size,
1223 const BmAccessTypeT access_type,
1224 const Segment* const p)
1225{
bartbedfd232009-03-26 19:07:15 +00001226 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001227
bartbedfd232009-03-26 19:07:15 +00001228 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1229 && tid != DRD_INVALID_THREADID);
1230 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001231
bart8f822af2009-06-08 18:20:42 +00001232 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001233 {
1234 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001235 {
bartbedfd232009-03-26 19:07:15 +00001236 Segment* q;
1237 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1238 {
1239 /*
1240 * Since q iterates over the segments of thread i in order of
1241 * decreasing vector clocks, if q->vc <= p->vc, then
1242 * q->next->vc <= p->vc will also hold. Hence, break out of the
1243 * loop once this condition is met.
1244 */
1245 if (DRD_(vc_lte)(&q->vc, &p->vc))
1246 break;
1247 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1248 {
bart8f822af2009-06-08 18:20:42 +00001249 if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
bartbedfd232009-03-26 19:07:15 +00001250 access_type))
1251 {
1252 tl_assert(q->stacktrace);
1253 show_call_stack(i, "Other segment start",
1254 q->stacktrace);
1255 show_call_stack(i, "Other segment end",
1256 q->next ? q->next->stacktrace : 0);
1257 }
1258 }
1259 }
sewardjaf44c822007-11-25 14:01:38 +00001260 }
bartbedfd232009-03-26 19:07:15 +00001261 }
sewardjaf44c822007-11-25 14:01:38 +00001262}
1263
bart86a87df2009-03-04 19:26:47 +00001264/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001265void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1266 const Addr addr,
1267 const SizeT size,
1268 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001269{
bartbedfd232009-03-26 19:07:15 +00001270 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001271
bartbedfd232009-03-26 19:07:15 +00001272 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1273 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001274
bartbedfd232009-03-26 19:07:15 +00001275 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1276 {
bart8f822af2009-06-08 18:20:42 +00001277 if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
bartbedfd232009-03-26 19:07:15 +00001278 {
1279 thread_report_conflicting_segments_segment(tid, addr, size,
1280 access_type, p);
1281 }
1282 }
sewardjaf44c822007-11-25 14:01:38 +00001283}
sewardjaf44c822007-11-25 14:01:38 +00001284
bart324a23b2009-02-15 12:14:52 +00001285/**
bart8f822af2009-06-08 18:20:42 +00001286 * Verify whether the conflict set for thread tid is up to date. Only perform
1287 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1288 */
1289static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1290{
1291 static int do_verify_conflict_set = -1;
1292 Bool result;
1293 struct bitmap* computed_conflict_set = 0;
1294
1295 if (do_verify_conflict_set < 0)
1296 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1297
1298 if (do_verify_conflict_set == 0)
1299 return True;
1300
1301 thread_compute_conflict_set(&computed_conflict_set, tid);
1302 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1303 if (! result)
1304 {
1305 VG_(printf)("actual conflict set:\n");
1306 DRD_(bm_print)(DRD_(g_conflict_set));
1307 VG_(printf)("\n");
1308 VG_(printf)("computed conflict set:\n");
1309 DRD_(bm_print)(computed_conflict_set);
1310 VG_(printf)("\n");
1311 }
1312 DRD_(bm_delete)(computed_conflict_set);
1313 return result;
1314}
1315
1316/**
1317 * Compute the conflict set: a bitmap that represents the union of all memory
1318 * accesses of all segments that are unordered to the current segment of the
1319 * thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001320 */
bart86a87df2009-03-04 19:26:47 +00001321static void thread_compute_conflict_set(struct bitmap** conflict_set,
1322 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001323{
bartbedfd232009-03-26 19:07:15 +00001324 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001325
bartbedfd232009-03-26 19:07:15 +00001326 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1327 && tid != DRD_INVALID_THREADID);
1328 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001329
bart54803fe2009-06-21 09:26:27 +00001330 s_compute_conflict_set_count++;
bartbedfd232009-03-26 19:07:15 +00001331 s_conflict_set_bitmap_creation_count
1332 -= DRD_(bm_get_bitmap_creation_count)();
1333 s_conflict_set_bitmap2_creation_count
1334 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001335
bartbedfd232009-03-26 19:07:15 +00001336 if (*conflict_set)
1337 {
bartf6ec1fe2009-06-21 18:07:35 +00001338 DRD_(bm_cleanup)(*conflict_set);
1339 DRD_(bm_init)(*conflict_set);
bartbedfd232009-03-26 19:07:15 +00001340 }
bartf6ec1fe2009-06-21 18:07:35 +00001341 else
1342 {
1343 *conflict_set = DRD_(bm_new)();
1344 }
bart26f73e12008-02-24 18:37:08 +00001345
bartbedfd232009-03-26 19:07:15 +00001346 if (s_trace_conflict_set)
1347 {
bart8f822af2009-06-08 18:20:42 +00001348 char* str;
bart26f73e12008-02-24 18:37:08 +00001349
bart8f822af2009-06-08 18:20:42 +00001350 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1351 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001352 "computing conflict set for thread %d with vc %s\n",
1353 tid, str);
bart8f822af2009-06-08 18:20:42 +00001354 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001355 }
sewardjaf44c822007-11-25 14:01:38 +00001356
bartbedfd232009-03-26 19:07:15 +00001357 p = DRD_(g_threadinfo)[tid].last;
1358 {
1359 unsigned j;
1360
1361 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001362 {
bart8f822af2009-06-08 18:20:42 +00001363 char* vc;
bartbedfd232009-03-26 19:07:15 +00001364
bart8f822af2009-06-08 18:20:42 +00001365 vc = DRD_(vc_aprint)(&p->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001366 VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
bart8f822af2009-06-08 18:20:42 +00001367 tid, vc);
1368 VG_(free)(vc);
bart26f73e12008-02-24 18:37:08 +00001369 }
sewardjaf44c822007-11-25 14:01:38 +00001370
bart8f822af2009-06-08 18:20:42 +00001371 for (j = 0; j < DRD_N_THREADS; j++)
bartbedfd232009-03-26 19:07:15 +00001372 {
1373 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1374 {
bart8f822af2009-06-08 18:20:42 +00001375 Segment* q;
bartbedfd232009-03-26 19:07:15 +00001376 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1377 {
1378 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1379 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1380 {
1381 if (s_trace_conflict_set)
1382 {
bart8f822af2009-06-08 18:20:42 +00001383 char* str;
1384
1385 str = DRD_(vc_aprint)(&q->vc);
1386 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001387 "conflict set: [%d] merging segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001388 j, str);
1389 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001390 }
bart8f822af2009-06-08 18:20:42 +00001391 DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
bartbedfd232009-03-26 19:07:15 +00001392 }
1393 else
1394 {
1395 if (s_trace_conflict_set)
1396 {
bart8f822af2009-06-08 18:20:42 +00001397 char* str;
1398
1399 str = DRD_(vc_aprint)(&q->vc);
1400 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001401 "conflict set: [%d] ignoring segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001402 j, str);
1403 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001404 }
1405 }
1406 }
1407 }
1408 }
1409 }
sewardjaf44c822007-11-25 14:01:38 +00001410
bartbedfd232009-03-26 19:07:15 +00001411 s_conflict_set_bitmap_creation_count
1412 += DRD_(bm_get_bitmap_creation_count)();
1413 s_conflict_set_bitmap2_creation_count
1414 += DRD_(bm_get_bitmap2_creation_count)();
1415
bart8f822af2009-06-08 18:20:42 +00001416 if (s_trace_conflict_set_bm)
bartbedfd232009-03-26 19:07:15 +00001417 {
sewardj1e29ebc2009-07-15 14:49:17 +00001418 VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
bartbedfd232009-03-26 19:07:15 +00001419 DRD_(bm_print)(*conflict_set);
sewardj1e29ebc2009-07-15 14:49:17 +00001420 VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
bartbedfd232009-03-26 19:07:15 +00001421 }
sewardjaf44c822007-11-25 14:01:38 +00001422}
1423
bart8f822af2009-06-08 18:20:42 +00001424/**
1425 * Update the conflict set after the vector clock of thread tid has been
1426 * updated from old_vc to its current value, either because a new segment has
1427 * been created or because of a synchronization operation.
1428 */
1429void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1430 const VectorClock* const old_vc)
1431{
1432 const VectorClock* new_vc;
1433 Segment* p;
1434 unsigned j;
1435
1436 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1437 && tid != DRD_INVALID_THREADID);
1438 tl_assert(old_vc);
1439 tl_assert(tid == DRD_(g_drd_running_tid));
1440 tl_assert(DRD_(g_conflict_set));
1441
1442 if (s_trace_conflict_set)
1443 {
1444 char* str;
1445
1446 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1447 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001448 "updating conflict set for thread %d with vc %s\n",
1449 tid, str);
bart8f822af2009-06-08 18:20:42 +00001450 VG_(free)(str);
1451 }
1452
1453 new_vc = &DRD_(g_threadinfo)[tid].last->vc;
1454
1455 DRD_(bm_unmark)(DRD_(g_conflict_set));
1456
1457 for (j = 0; j < DRD_N_THREADS; j++)
1458 {
1459 Segment* q;
1460
1461 if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1462 continue;
1463
1464 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1465 {
1466 const int included_in_old_conflict_set
1467 = ! DRD_(vc_lte)(&q->vc, old_vc)
1468 && ! DRD_(vc_lte)(old_vc, &q->vc);
1469 const int included_in_new_conflict_set
1470 = ! DRD_(vc_lte)(&q->vc, new_vc)
1471 && ! DRD_(vc_lte)(new_vc, &q->vc);
1472 if (included_in_old_conflict_set != included_in_new_conflict_set)
1473 {
1474 if (s_trace_conflict_set)
1475 {
1476 char* str;
1477
1478 str = DRD_(vc_aprint)(&q->vc);
1479 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001480 "conflict set: [%d] merging segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001481 VG_(free)(str);
1482 }
1483 DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1484 }
1485 else
1486 {
1487 if (s_trace_conflict_set)
1488 {
1489 char* str;
1490
1491 str = DRD_(vc_aprint)(&q->vc);
1492 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001493 "conflict set: [%d] ignoring segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001494 VG_(free)(str);
1495 }
1496 }
1497 }
1498 }
1499
1500 DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1501
1502 p = DRD_(g_threadinfo)[tid].last;
1503 {
1504 for (j = 0; j < DRD_N_THREADS; j++)
1505 {
1506 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1507 {
1508 Segment* q;
1509 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1510 {
1511 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1512 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1513 {
1514 DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1515 }
1516 }
1517 }
1518 }
1519 }
1520
1521 DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1522
bart54803fe2009-06-21 09:26:27 +00001523 s_update_conflict_set_count++;
bart8f822af2009-06-08 18:20:42 +00001524
1525 if (s_trace_conflict_set_bm)
1526 {
sewardj1e29ebc2009-07-15 14:49:17 +00001527 VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
bart8f822af2009-06-08 18:20:42 +00001528 DRD_(bm_print)(DRD_(g_conflict_set));
sewardj1e29ebc2009-07-15 14:49:17 +00001529 VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
bart8f822af2009-06-08 18:20:42 +00001530 }
1531
1532 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1533}
1534
bart86a87df2009-03-04 19:26:47 +00001535/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001536ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001537{
bartbedfd232009-03-26 19:07:15 +00001538 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001539}
1540
bart86a87df2009-03-04 19:26:47 +00001541/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001542ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001543{
bartbedfd232009-03-26 19:07:15 +00001544 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001545}
1546
bart54803fe2009-06-21 09:26:27 +00001547/** Return how many times the conflict set has been updated entirely. */
1548ULong DRD_(thread_get_compute_conflict_set_count)()
sewardjaf44c822007-11-25 14:01:38 +00001549{
bart54803fe2009-06-21 09:26:27 +00001550 return s_compute_conflict_set_count;
1551}
1552
1553/** Return how many times the conflict set has been updated partially. */
1554ULong DRD_(thread_get_update_conflict_set_count)(void)
1555{
bartbedfd232009-03-26 19:07:15 +00001556 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001557}
1558
bart86a87df2009-03-04 19:26:47 +00001559/**
barte5214662009-06-21 11:51:23 +00001560 * Return how many times the conflict set has been updated partially
1561 * because a new segment has been created.
1562 */
1563ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
1564{
1565 return s_update_conflict_set_new_sg_count;
1566}
1567
1568/**
1569 * Return how many times the conflict set has been updated partially
1570 * because of combining vector clocks due to synchronization operations
1571 * other than reader/writer lock or barrier operations.
1572 */
1573ULong DRD_(thread_get_update_conflict_set_sync_count)(void)
1574{
1575 return s_update_conflict_set_sync_count;
1576}
1577
1578/**
1579 * Return how many times the conflict set has been updated partially
1580 * because of thread joins.
1581 */
1582ULong DRD_(thread_get_update_conflict_set_join_count)(void)
1583{
1584 return s_update_conflict_set_join_count;
1585}
1586
1587/**
bart86a87df2009-03-04 19:26:47 +00001588 * Return the number of first-level bitmaps that have been created during
1589 * conflict set updates.
1590 */
bart62a784c2009-02-15 13:11:14 +00001591ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001592{
bartbedfd232009-03-26 19:07:15 +00001593 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001594}
1595
bart86a87df2009-03-04 19:26:47 +00001596/**
1597 * Return the number of second-level bitmaps that have been created during
1598 * conflict set updates.
1599 */
bart62a784c2009-02-15 13:11:14 +00001600ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001601{
bartbedfd232009-03-26 19:07:15 +00001602 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001603}