blob: e497db5e116d7702c95f095feb14b52d6cf803df [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
bart3c9afb12009-07-24 11:11:30 +0000198 VG_(printf)(
199"\nSorry, but the maximum number of threads supported by DRD has been exceeded."
200"Aborting.\n");
201
bartbedfd232009-03-26 19:07:15 +0000202 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000203
bartbedfd232009-03-26 19:07:15 +0000204 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000205}
206
bart86a87df2009-03-04 19:26:47 +0000207/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000208DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000209{
bartbedfd232009-03-26 19:07:15 +0000210 int i;
sewardjaf44c822007-11-25 14:01:38 +0000211
bartb48bde22009-07-31 08:26:17 +0000212 if (tid != INVALID_POSIX_THREADID)
bartbedfd232009-03-26 19:07:15 +0000213 {
bartb48bde22009-07-31 08:26:17 +0000214 for (i = 1; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000215 {
bartb48bde22009-07-31 08:26:17 +0000216 if (DRD_(g_threadinfo)[i].posix_thread_exists
217 && DRD_(g_threadinfo)[i].pt_threadid == tid)
218 {
219 return i;
220 }
bartbedfd232009-03-26 19:07:15 +0000221 }
222 }
223 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000224}
225
bart86a87df2009-03-04 19:26:47 +0000226/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000227ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000228{
bartbedfd232009-03-26 19:07:15 +0000229 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
230 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000231
bartbedfd232009-03-26 19:07:15 +0000232 return (DRD_(g_threadinfo)[tid].vg_thread_exists
233 ? DRD_(g_threadinfo)[tid].vg_threadid
234 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000235}
236
bart8f822af2009-06-08 18:20:42 +0000237#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart324a23b2009-02-15 12:14:52 +0000238/**
239 * Sanity check of the doubly linked list of segments referenced by a
240 * ThreadInfo struct.
241 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000242 */
bart62a784c2009-02-15 13:11:14 +0000243static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000244{
bartbedfd232009-03-26 19:07:15 +0000245 Segment* p;
bart8f822af2009-06-08 18:20:42 +0000246
bartbedfd232009-03-26 19:07:15 +0000247 for (p = ti->first; p; p = p->next) {
248 if (p->next && p->next->prev != p)
249 return False;
250 if (p->next == 0 && p != ti->last)
251 return False;
252 }
253 for (p = ti->last; p; p = p->prev) {
254 if (p->prev && p->prev->next != p)
255 return False;
256 if (p->prev == 0 && p != ti->first)
257 return False;
258 }
259 return True;
sewardjaf44c822007-11-25 14:01:38 +0000260}
bart23d3a4e2008-04-05 12:53:00 +0000261#endif
sewardjaf44c822007-11-25 14:01:38 +0000262
bart439c55f2009-02-15 10:38:37 +0000263/**
264 * Create the first segment for a newly started thread.
265 *
266 * This function is called from the handler installed via
267 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
268 * from the context of the creator thread, before the new thread has been
269 * created.
bart86a87df2009-03-04 19:26:47 +0000270 *
271 * @param[in] creator DRD thread ID of the creator thread.
272 * @param[in] vg_created Valgrind thread ID of the created thread.
273 *
274 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000275 */
bart62a784c2009-02-15 13:11:14 +0000276DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
277 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000278{
bartbedfd232009-03-26 19:07:15 +0000279 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000280
bartbedfd232009-03-26 19:07:15 +0000281 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
282 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
283 tl_assert(0 <= (int)created && created < DRD_N_THREADS
284 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000285
bartbedfd232009-03-26 19:07:15 +0000286 tl_assert(DRD_(g_threadinfo)[created].first == 0);
287 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart8f822af2009-06-08 18:20:42 +0000288 /* Create an initial segment for the newly created thread. */
bartbedfd232009-03-26 19:07:15 +0000289 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000290
bartbedfd232009-03-26 19:07:15 +0000291 return created;
sewardjaf44c822007-11-25 14:01:38 +0000292}
293
bart439c55f2009-02-15 10:38:37 +0000294/**
bart86a87df2009-03-04 19:26:47 +0000295 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
296 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000297 * on the newly created thread, e.g. from the handler installed via
298 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000299 *
300 * @param[in] vg_created Valgrind thread ID of the newly created thread.
301 *
302 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000303 */
bart62a784c2009-02-15 13:11:14 +0000304DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000305{
bartbedfd232009-03-26 19:07:15 +0000306 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000307
bartbedfd232009-03-26 19:07:15 +0000308 tl_assert(0 <= (int)created && created < DRD_N_THREADS
309 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000310
bartbedfd232009-03-26 19:07:15 +0000311 DRD_(g_threadinfo)[created].stack_max
312 = VG_(thread_get_stack_max)(vg_created);
313 DRD_(g_threadinfo)[created].stack_startup
314 = DRD_(g_threadinfo)[created].stack_max;
315 DRD_(g_threadinfo)[created].stack_min
316 = DRD_(g_threadinfo)[created].stack_max;
317 DRD_(g_threadinfo)[created].stack_min_min
318 = DRD_(g_threadinfo)[created].stack_max;
319 DRD_(g_threadinfo)[created].stack_size
320 = VG_(thread_get_stack_size)(vg_created);
321 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000322
bartbedfd232009-03-26 19:07:15 +0000323 return created;
bart439c55f2009-02-15 10:38:37 +0000324}
bart09dc13f2009-02-14 15:13:31 +0000325
bart324a23b2009-02-15 12:14:52 +0000326/**
327 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
328 * after thread drd_joiner joined thread drd_joinee.
329 */
bart09dc13f2009-02-14 15:13:31 +0000330void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
331{
bartbedfd232009-03-26 19:07:15 +0000332 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
333 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
bart7627be32009-06-06 12:26:05 +0000334
bartbedfd232009-03-26 19:07:15 +0000335 DRD_(thread_new_segment)(drd_joiner);
bart8f822af2009-06-08 18:20:42 +0000336 DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
bart7627be32009-06-06 12:26:05 +0000337 DRD_(thread_new_segment)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000338
bartbedfd232009-03-26 19:07:15 +0000339 if (s_trace_fork_join)
340 {
341 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
bartbedfd232009-03-26 19:07:15 +0000342 const unsigned msg_size = 256;
343 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000344
bartbedfd232009-03-26 19:07:15 +0000345 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
346 tl_assert(msg);
347 VG_(snprintf)(msg, msg_size,
bart63c92ea2009-07-19 17:53:56 +0000348 "drd_post_thread_join joiner = %d, joinee = %d",
349 drd_joiner, drd_joinee);
bartbedfd232009-03-26 19:07:15 +0000350 if (joiner)
351 {
bart8f822af2009-06-08 18:20:42 +0000352 char* vc;
353
354 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
bartbedfd232009-03-26 19:07:15 +0000355 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart8f822af2009-06-08 18:20:42 +0000356 ", new vc: %s", vc);
357 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000358 }
sewardj1e29ebc2009-07-15 14:49:17 +0000359 VG_(message)(Vg_DebugMsg, "%s\n", msg);
bartbedfd232009-03-26 19:07:15 +0000360 VG_(free)(msg);
361 }
bart09dc13f2009-02-14 15:13:31 +0000362
bartbedfd232009-03-26 19:07:15 +0000363 if (! DRD_(get_check_stack_accesses)())
364 {
365 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
366 - DRD_(thread_get_stack_size)(drd_joinee),
367 DRD_(thread_get_stack_max)(drd_joinee));
368 }
369 DRD_(clientobj_delete_thread)(drd_joinee);
370 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000371}
372
bart324a23b2009-02-15 12:14:52 +0000373/**
374 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
375 * and accesses this data structure from multiple threads without locking.
376 * Any conflicting accesses in the range stack_startup..stack_max will be
377 * ignored.
378 */
bart62a784c2009-02-15 13:11:14 +0000379void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
380 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000381{
bartbedfd232009-03-26 19:07:15 +0000382 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
383 && tid != DRD_INVALID_THREADID);
384 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
385 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
386 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000387}
388
bart86a87df2009-03-04 19:26:47 +0000389/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000390Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000391{
bartbedfd232009-03-26 19:07:15 +0000392 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
393 && tid != DRD_INVALID_THREADID);
394 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000395}
396
bart86a87df2009-03-04 19:26:47 +0000397/**
398 * Return the lowest value that was ever assigned to the stack pointer
399 * for the specified thread.
400 */
bart62a784c2009-02-15 13:11:14 +0000401Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000402{
bartbedfd232009-03-26 19:07:15 +0000403 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
404 && tid != DRD_INVALID_THREADID);
405 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000406}
407
bart86a87df2009-03-04 19:26:47 +0000408/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000409Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000410{
bartbedfd232009-03-26 19:07:15 +0000411 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
412 && tid != DRD_INVALID_THREADID);
413 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000414}
415
bart86a87df2009-03-04 19:26:47 +0000416/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000417SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000418{
bartbedfd232009-03-26 19:07:15 +0000419 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
420 && tid != DRD_INVALID_THREADID);
421 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000422}
423
bart09dc13f2009-02-14 15:13:31 +0000424/**
425 * Clean up thread-specific data structures. Call this just after
426 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000427 */
bart62a784c2009-02-15 13:11:14 +0000428void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000429{
bartbedfd232009-03-26 19:07:15 +0000430 Segment* sg;
431 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000432
bartbedfd232009-03-26 19:07:15 +0000433 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000434
bartbedfd232009-03-26 19:07:15 +0000435 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
436 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
437 {
438 sg_prev = sg->prev;
439 sg->prev = 0;
440 sg->next = 0;
441 DRD_(sg_put)(sg);
442 }
443 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
444 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
445 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
446 DRD_(g_threadinfo)[tid].first = 0;
447 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000448
bartbedfd232009-03-26 19:07:15 +0000449 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000450}
451
bart324a23b2009-02-15 12:14:52 +0000452/**
453 * Called after a thread performed its last memory access and before
454 * thread_delete() is called. Note: thread_delete() is only called for
455 * joinable threads, not for detached threads.
456 */
bart62a784c2009-02-15 13:11:14 +0000457void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000458{
bartbedfd232009-03-26 19:07:15 +0000459 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
460 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000461
bartbedfd232009-03-26 19:07:15 +0000462 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000463
bartbedfd232009-03-26 19:07:15 +0000464 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
465 {
466 /*
467 * Once a detached thread has finished, its stack is deallocated and
468 * should no longer be taken into account when computing the conflict set.
469 */
470 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000471
bartbedfd232009-03-26 19:07:15 +0000472 /*
473 * For a detached thread, calling pthread_exit() invalidates the
474 * POSIX thread ID associated with the detached thread. For joinable
475 * POSIX threads however, the POSIX thread ID remains live after the
476 * pthread_exit() call until pthread_join() is called.
477 */
478 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
479 }
sewardjaf44c822007-11-25 14:01:38 +0000480}
481
bart9b2974a2008-09-27 12:35:31 +0000482/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000483void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000484{
bartbedfd232009-03-26 19:07:15 +0000485 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
486 && tid != DRD_INVALID_THREADID);
487 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000488
bartbedfd232009-03-26 19:07:15 +0000489 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000490}
491
barte7dff242009-04-23 17:12:39 +0000492/**
493 * Store the POSIX thread ID for the specified thread.
494 *
495 * @note This function can be called two times for the same thread -- see also
496 * the comment block preceding the pthread_create() wrapper in
497 * drd_pthread_intercepts.c.
498 */
bart62a784c2009-02-15 13:11:14 +0000499void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000500{
bartbedfd232009-03-26 19:07:15 +0000501 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
502 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000503 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
504 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000505 tl_assert(ptid != INVALID_POSIX_THREADID);
506 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
507 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000508}
509
bart86a87df2009-03-04 19:26:47 +0000510/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000511Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000512{
bartbedfd232009-03-26 19:07:15 +0000513 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
514 && tid != DRD_INVALID_THREADID);
515 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000516}
517
bart86a87df2009-03-04 19:26:47 +0000518/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000519void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000520{
bartbedfd232009-03-26 19:07:15 +0000521 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
522 && tid != DRD_INVALID_THREADID);
523 tl_assert(!! joinable == joinable);
524 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bart8f822af2009-06-08 18:20:42 +0000525
bartbedfd232009-03-26 19:07:15 +0000526 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000527}
528
bartdd75cdf2009-07-24 08:20:10 +0000529/** Tells DRD that the calling thread is about to enter pthread_create(). */
530void DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
531{
532 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
533 && tid != DRD_INVALID_THREADID);
534 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
535 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
536
537 DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
538}
539
540/** Tells DRD that the calling thread has left pthread_create(). */
541void DRD_(thread_left_pthread_create)(const DrdThreadId tid)
542{
543 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
544 && tid != DRD_INVALID_THREADID);
545 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
546 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
547
548 DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
549}
550
bartd45d9952009-05-31 18:53:54 +0000551/** Obtain the thread number and the user-assigned thread name. */
552const char* DRD_(thread_get_name)(const DrdThreadId tid)
553{
554 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
555 && tid != DRD_INVALID_THREADID);
556
557 return DRD_(g_threadinfo)[tid].name;
558}
559
560/** Set the name of the specified thread. */
561void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
562{
563 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
564 && tid != DRD_INVALID_THREADID);
565
566 if (name == NULL || name[0] == 0)
567 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
568 sizeof(DRD_(g_threadinfo)[tid].name),
569 "Thread %d",
570 tid);
571 else
572 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
573 sizeof(DRD_(g_threadinfo)[tid].name),
574 "Thread %d (%s)",
575 tid, name);
576 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
577}
578
bart86a87df2009-03-04 19:26:47 +0000579/**
580 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
581 * conflict set.
582 */
bart62a784c2009-02-15 13:11:14 +0000583void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000584{
bartbedfd232009-03-26 19:07:15 +0000585 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000586
bartbedfd232009-03-26 19:07:15 +0000587 if (vg_tid != s_vg_running_tid)
588 {
589 DRD_(thread_set_running_tid)(vg_tid,
590 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
591 }
sewardj8b09d4f2007-12-04 21:27:18 +0000592
bartbedfd232009-03-26 19:07:15 +0000593 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
594 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000595}
596
bart86a87df2009-03-04 19:26:47 +0000597/**
598 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
599 * conflict set.
600 */
bart62a784c2009-02-15 13:11:14 +0000601void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
602 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000603{
bartbedfd232009-03-26 19:07:15 +0000604 tl_assert(vg_tid != VG_INVALID_THREADID);
605 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000606
bartbedfd232009-03-26 19:07:15 +0000607 if (vg_tid != s_vg_running_tid)
608 {
609 if (s_trace_context_switches
610 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
611 {
612 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +0000613 "Context switch from thread %d to thread %d;"
sewardj1e29ebc2009-07-15 14:49:17 +0000614 " segments: %llu\n",
bart63c92ea2009-07-19 17:53:56 +0000615 DRD_(g_drd_running_tid), drd_tid,
bartbedfd232009-03-26 19:07:15 +0000616 DRD_(sg_get_segments_alive_count)());
617 }
618 s_vg_running_tid = vg_tid;
619 DRD_(g_drd_running_tid) = drd_tid;
620 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
621 s_context_switch_count++;
622 }
sewardj8b09d4f2007-12-04 21:27:18 +0000623
bartbedfd232009-03-26 19:07:15 +0000624 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
625 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000626}
627
bart86a87df2009-03-04 19:26:47 +0000628/**
629 * Increase the synchronization nesting counter. Must be called before the
630 * client calls a synchronization function.
631 */
bart62a784c2009-02-15 13:11:14 +0000632int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000633{
bartbedfd232009-03-26 19:07:15 +0000634 tl_assert(DRD_(IsValidDrdThreadId)(tid));
635 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000636}
637
bart86a87df2009-03-04 19:26:47 +0000638/**
639 * Decrease the synchronization nesting counter. Must be called after the
640 * client left a synchronization function.
641 */
bart62a784c2009-02-15 13:11:14 +0000642int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000643{
bartbedfd232009-03-26 19:07:15 +0000644 tl_assert(DRD_(IsValidDrdThreadId)(tid));
645 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
646 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000647}
648
bart86a87df2009-03-04 19:26:47 +0000649/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000650int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000651{
bartbedfd232009-03-26 19:07:15 +0000652 tl_assert(DRD_(IsValidDrdThreadId)(tid));
653 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000654}
655
bart1a473c72008-03-13 19:03:38 +0000656/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000657static
bart86a87df2009-03-04 19:26:47 +0000658void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000659{
bartbedfd232009-03-26 19:07:15 +0000660 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
661 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000662
663#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
664 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
665#endif
666
bartbedfd232009-03-26 19:07:15 +0000667 sg->prev = DRD_(g_threadinfo)[tid].last;
668 sg->next = 0;
669 if (DRD_(g_threadinfo)[tid].last)
670 DRD_(g_threadinfo)[tid].last->next = sg;
671 DRD_(g_threadinfo)[tid].last = sg;
672 if (DRD_(g_threadinfo)[tid].first == 0)
673 DRD_(g_threadinfo)[tid].first = sg;
bart8f822af2009-06-08 18:20:42 +0000674
675#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
676 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
677#endif
sewardjaf44c822007-11-25 14:01:38 +0000678}
679
bart324a23b2009-02-15 12:14:52 +0000680/**
681 * Remove a segment from the segment list of thread threadid, and free the
682 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000683 */
bart62a784c2009-02-15 13:11:14 +0000684static
bart86a87df2009-03-04 19:26:47 +0000685void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
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);
bart8f822af2009-06-08 18:20:42 +0000689
690#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
691 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
692#endif
bart26f73e12008-02-24 18:37:08 +0000693
bartbedfd232009-03-26 19:07:15 +0000694 if (sg->prev)
695 sg->prev->next = sg->next;
696 if (sg->next)
697 sg->next->prev = sg->prev;
698 if (sg == DRD_(g_threadinfo)[tid].first)
699 DRD_(g_threadinfo)[tid].first = sg->next;
700 if (sg == DRD_(g_threadinfo)[tid].last)
701 DRD_(g_threadinfo)[tid].last = sg->prev;
702 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000703
bart8f822af2009-06-08 18:20:42 +0000704#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
705 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
706#endif
sewardjaf44c822007-11-25 14:01:38 +0000707}
708
bart86a87df2009-03-04 19:26:47 +0000709/**
710 * Returns a pointer to the vector clock of the most recent segment associated
711 * with thread 'tid'.
712 */
bart62a784c2009-02-15 13:11:14 +0000713VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000714{
bartbedfd232009-03-26 19:07:15 +0000715 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
716 && tid != DRD_INVALID_THREADID);
717 tl_assert(DRD_(g_threadinfo)[tid].last);
718 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000719}
720
bart324a23b2009-02-15 12:14:52 +0000721/**
722 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000723 */
bart62a784c2009-02-15 13:11:14 +0000724void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000725{
bartbedfd232009-03-26 19:07:15 +0000726 tl_assert(sg);
727 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
728 && tid != DRD_INVALID_THREADID);
729 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000730
bartbedfd232009-03-26 19:07:15 +0000731 DRD_(sg_put)(*sg);
732 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000733}
734
sewardjaf44c822007-11-25 14:01:38 +0000735/**
736 * Compute the minimum of all latest vector clocks of all threads
737 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000738 *
sewardjaf44c822007-11-25 14:01:38 +0000739 * @param vc pointer to a vectorclock, holds result upon return.
740 */
bart62a784c2009-02-15 13:11:14 +0000741static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000742{
bartbedfd232009-03-26 19:07:15 +0000743 unsigned i;
744 Bool first;
745 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000746
bartbedfd232009-03-26 19:07:15 +0000747 first = True;
bart8f822af2009-06-08 18:20:42 +0000748 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000749 {
750 latest_sg = DRD_(g_threadinfo)[i].last;
751 if (latest_sg)
752 {
753 if (first)
754 DRD_(vc_assign)(vc, &latest_sg->vc);
755 else
756 DRD_(vc_min)(vc, &latest_sg->vc);
757 first = False;
758 }
759 }
sewardjaf44c822007-11-25 14:01:38 +0000760}
761
bart86a87df2009-03-04 19:26:47 +0000762/**
763 * Compute the maximum of all latest vector clocks of all threads.
764 *
765 * @param vc pointer to a vectorclock, holds result upon return.
766 */
bart62a784c2009-02-15 13:11:14 +0000767static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000768{
bartbedfd232009-03-26 19:07:15 +0000769 unsigned i;
770 Bool first;
771 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000772
bartbedfd232009-03-26 19:07:15 +0000773 first = True;
bart8f822af2009-06-08 18:20:42 +0000774 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000775 {
776 latest_sg = DRD_(g_threadinfo)[i].last;
777 if (latest_sg)
778 {
779 if (first)
780 DRD_(vc_assign)(vc, &latest_sg->vc);
781 else
782 DRD_(vc_combine)(vc, &latest_sg->vc);
783 first = False;
784 }
785 }
sewardjaf44c822007-11-25 14:01:38 +0000786}
787
788/**
bart5bd9f2d2008-03-03 20:31:58 +0000789 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000790 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000791 * data race.
792 */
bart8f822af2009-06-08 18:20:42 +0000793static void thread_discard_ordered_segments(void)
sewardjaf44c822007-11-25 14:01:38 +0000794{
bartbedfd232009-03-26 19:07:15 +0000795 unsigned i;
796 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000797
bartbedfd232009-03-26 19:07:15 +0000798 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000799
bartbedfd232009-03-26 19:07:15 +0000800 DRD_(vc_init)(&thread_vc_min, 0, 0);
801 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
802 if (DRD_(sg_get_trace)())
803 {
bart8f822af2009-06-08 18:20:42 +0000804 char *vc_min, *vc_max;
bartbedfd232009-03-26 19:07:15 +0000805 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000806
bartbedfd232009-03-26 19:07:15 +0000807 DRD_(vc_init)(&thread_vc_max, 0, 0);
808 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart8f822af2009-06-08 18:20:42 +0000809 vc_min = DRD_(vc_aprint)(&thread_vc_min);
810 vc_max = DRD_(vc_aprint)(&thread_vc_max);
811 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000812 "Discarding ordered segments -- min vc is %s, max vc is %s\n",
bart8f822af2009-06-08 18:20:42 +0000813 vc_min, vc_max);
814 VG_(free)(vc_min);
815 VG_(free)(vc_max);
bartbedfd232009-03-26 19:07:15 +0000816 DRD_(vc_cleanup)(&thread_vc_max);
817 }
sewardjaf44c822007-11-25 14:01:38 +0000818
bart8f822af2009-06-08 18:20:42 +0000819 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000820 {
821 Segment* sg;
822 Segment* sg_next;
823 for (sg = DRD_(g_threadinfo)[i].first;
824 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
825 sg = sg_next)
826 {
827 thread_discard_segment(i, sg);
828 }
829 }
830 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000831}
832
bart324a23b2009-02-15 12:14:52 +0000833/**
bart8f822af2009-06-08 18:20:42 +0000834 * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
835 * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
836 * all segments in the set CS are ordered consistently against both sg1 and
837 * sg2. The set CS is defined as the set of segments that can immediately
838 * precede future segments via inter-thread synchronization operations. In
839 * DRD the set CS consists of the latest segment of each thread combined with
840 * all segments for which the reference count is strictly greater than one.
841 * The code below is an optimized version of the following:
842 *
843 * for (i = 0; i < DRD_N_THREADS; i++)
844 * {
845 * Segment* sg;
846 *
847 * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
848 * {
849 * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
850 * {
851 * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
852 * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
853 * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
854 * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
855 * {
856 * return False;
857 * }
858 * }
859 * }
860 * }
861 */
862static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
863 Segment* const sg1,
864 Segment* const sg2)
865{
866 unsigned i;
867
868 tl_assert(sg1->next);
869 tl_assert(sg2->next);
870 tl_assert(sg1->next == sg2);
871 tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
872
873 for (i = 0; i < DRD_N_THREADS; i++)
874 {
875 Segment* sg;
876
877 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
878 {
879 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
880 {
881 if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
882 break;
883 if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
884 return False;
885 }
886 }
887 for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
888 {
889 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
890 {
891 if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
892 break;
893 if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
894 return False;
895 }
896 }
897 }
898 return True;
899}
900
901/**
bart324a23b2009-02-15 12:14:52 +0000902 * Merge all segments that may be merged without triggering false positives
903 * or discarding real data races. For the theoretical background of segment
bart8f822af2009-06-08 18:20:42 +0000904 * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
905 * and Koen De Bosschere. Bounding the number of segment histories during
906 * data race detection. Parallel Computing archive, Volume 28, Issue 9,
907 * pp 1221-1238, September 2002. This paper contains a proof that merging
908 * consecutive segments for which the property equiv(s1,s2) holds can be
909 * merged without reducing the accuracy of datarace detection. Furthermore
910 * it is also proven that the total number of all segments will never grow
911 * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
912 * every time a new segment is created. The property equiv(s1, s2) is defined
913 * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
914 * clocks of segments s and s1 are ordered in the same way as those of segments
915 * s and s2. The set CS is defined as the set of existing segments s that have
916 * the potential to conflict with not yet created segments, either because the
917 * segment s is the latest segment of a thread or because it can become the
918 * immediate predecessor of a new segment due to a synchronization operation.
barta9c37392008-03-22 09:38:48 +0000919 */
920static void thread_merge_segments(void)
921{
bartbedfd232009-03-26 19:07:15 +0000922 unsigned i;
barta9c37392008-03-22 09:38:48 +0000923
bart8f822af2009-06-08 18:20:42 +0000924 s_new_segments_since_last_merge = 0;
925
926 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000927 {
928 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000929
bart8f822af2009-06-08 18:20:42 +0000930#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
931 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
932#endif
barta9c37392008-03-22 09:38:48 +0000933
bartbedfd232009-03-26 19:07:15 +0000934 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000935 {
bartbedfd232009-03-26 19:07:15 +0000936 if (DRD_(sg_get_refcnt)(sg) == 1
937 && sg->next
938 && DRD_(sg_get_refcnt)(sg->next) == 1
bart8f822af2009-06-08 18:20:42 +0000939 && sg->next->next
940 && thread_consistent_segment_ordering(i, sg, sg->next))
bartbedfd232009-03-26 19:07:15 +0000941 {
942 /* Merge sg and sg->next into sg. */
943 DRD_(sg_merge)(sg, sg->next);
944 thread_discard_segment(i, sg->next);
945 }
barta9c37392008-03-22 09:38:48 +0000946 }
barta9c37392008-03-22 09:38:48 +0000947
bart8f822af2009-06-08 18:20:42 +0000948#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
949 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
950#endif
bartbedfd232009-03-26 19:07:15 +0000951 }
barta9c37392008-03-22 09:38:48 +0000952}
953
bart324a23b2009-02-15 12:14:52 +0000954/**
bart324a23b2009-02-15 12:14:52 +0000955 * Create a new segment for the specified thread, and discard any segments
956 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000957 */
bart62a784c2009-02-15 13:11:14 +0000958void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000959{
bart8f822af2009-06-08 18:20:42 +0000960 Segment* last_sg;
bartbedfd232009-03-26 19:07:15 +0000961 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000962
bartbedfd232009-03-26 19:07:15 +0000963 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
964 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000965 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000966
bart8f822af2009-06-08 18:20:42 +0000967 last_sg = DRD_(g_threadinfo)[tid].last;
bartbedfd232009-03-26 19:07:15 +0000968 new_sg = DRD_(sg_new)(tid, tid);
969 thread_append_segment(tid, new_sg);
bart8f822af2009-06-08 18:20:42 +0000970 if (tid == DRD_(g_drd_running_tid) && last_sg)
barte5214662009-06-21 11:51:23 +0000971 {
bart8f822af2009-06-08 18:20:42 +0000972 DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
barte5214662009-06-21 11:51:23 +0000973 s_update_conflict_set_new_sg_count++;
974 }
bartd66e3a82008-04-06 15:02:17 +0000975
bart8f822af2009-06-08 18:20:42 +0000976 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000977
bart8f822af2009-06-08 18:20:42 +0000978 if (s_segment_merging
979 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
bartbedfd232009-03-26 19:07:15 +0000980 {
bart8f822af2009-06-08 18:20:42 +0000981 thread_discard_ordered_segments();
bartbedfd232009-03-26 19:07:15 +0000982 thread_merge_segments();
983 }
sewardjaf44c822007-11-25 14:01:38 +0000984}
985
bart26f73e12008-02-24 18:37:08 +0000986/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart8f822af2009-06-08 18:20:42 +0000987void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000988{
bartbedfd232009-03-26 19:07:15 +0000989 tl_assert(joiner != joinee);
990 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
991 && joiner != DRD_INVALID_THREADID);
992 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
993 && joinee != DRD_INVALID_THREADID);
994 tl_assert(DRD_(g_threadinfo)[joiner].last);
995 tl_assert(DRD_(g_threadinfo)[joinee].last);
bart8f822af2009-06-08 18:20:42 +0000996
997 if (DRD_(sg_get_trace)())
998 {
999 char *str1, *str2;
1000 str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
1001 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001002 VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
bart8f822af2009-06-08 18:20:42 +00001003 str1, str2);
1004 VG_(free)(str1);
1005 VG_(free)(str2);
1006 }
barte5214662009-06-21 11:51:23 +00001007 if (joiner == DRD_(g_drd_running_tid))
1008 {
1009 VectorClock old_vc;
1010
1011 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[joiner].last->vc);
1012 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001013 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001014 DRD_(thread_update_conflict_set)(joiner, &old_vc);
1015 s_update_conflict_set_join_count++;
1016 DRD_(vc_cleanup)(&old_vc);
1017 }
1018 else
1019 {
1020 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001021 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001022 }
1023
1024 thread_discard_ordered_segments();
1025
bart8f822af2009-06-08 18:20:42 +00001026 if (DRD_(sg_get_trace)())
1027 {
1028 char* str;
1029 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001030 VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
bart8f822af2009-06-08 18:20:42 +00001031 VG_(free)(str);
1032 }
sewardjaf44c822007-11-25 14:01:38 +00001033}
1034
bart324a23b2009-02-15 12:14:52 +00001035/**
bart8f822af2009-06-08 18:20:42 +00001036 * Update the vector clock of the last segment of thread tid with the
bartf6ec1fe2009-06-21 18:07:35 +00001037 * the vector clock of segment sg.
bart26f73e12008-02-24 18:37:08 +00001038 */
bartf6ec1fe2009-06-21 18:07:35 +00001039static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
sewardjaf44c822007-11-25 14:01:38 +00001040{
bart8f822af2009-06-08 18:20:42 +00001041 const VectorClock* const vc = &sg->vc;
1042
bartbedfd232009-03-26 19:07:15 +00001043 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1044 && tid != DRD_INVALID_THREADID);
1045 tl_assert(DRD_(g_threadinfo)[tid].last);
bart8f822af2009-06-08 18:20:42 +00001046 tl_assert(sg);
bartbedfd232009-03-26 19:07:15 +00001047 tl_assert(vc);
bart8f822af2009-06-08 18:20:42 +00001048
1049 if (tid != sg->tid)
1050 {
1051 VectorClock old_vc;
1052
1053 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
1054 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
1055 if (DRD_(sg_get_trace)())
1056 {
1057 char *str1, *str2;
1058 str1 = DRD_(vc_aprint)(&old_vc);
1059 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001060 VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
bart8f822af2009-06-08 18:20:42 +00001061 VG_(free)(str1);
1062 VG_(free)(str2);
1063 }
barte5214662009-06-21 11:51:23 +00001064
bart8f822af2009-06-08 18:20:42 +00001065 thread_discard_ordered_segments();
barte5214662009-06-21 11:51:23 +00001066
bart8f822af2009-06-08 18:20:42 +00001067 DRD_(thread_update_conflict_set)(tid, &old_vc);
barte5214662009-06-21 11:51:23 +00001068 s_update_conflict_set_sync_count++;
1069
bart8f822af2009-06-08 18:20:42 +00001070 DRD_(vc_cleanup)(&old_vc);
1071 }
1072 else
1073 {
1074 tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
1075 }
sewardjaf44c822007-11-25 14:01:38 +00001076}
1077
bart324a23b2009-02-15 12:14:52 +00001078/**
bartf6ec1fe2009-06-21 18:07:35 +00001079 * Create a new segment for thread tid and update the vector clock of the last
1080 * segment of this thread with the the vector clock of segment sg. Call this
1081 * function after thread tid had to wait because of thread synchronization
1082 * until the memory accesses in the segment sg finished.
1083 */
1084void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
1085{
1086 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1087 && tid != DRD_INVALID_THREADID);
1088 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1089 tl_assert(sg);
1090
1091 thread_append_segment(tid, DRD_(sg_new)(tid, tid));
1092
1093 thread_combine_vc_sync(tid, sg);
1094
1095 if (s_segment_merging
1096 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1097 {
1098 thread_discard_ordered_segments();
1099 thread_merge_segments();
1100 }
1101}
1102
1103/**
bart324a23b2009-02-15 12:14:52 +00001104 * Call this function whenever a thread is no longer using the memory
1105 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1106 * increase.
bart26f73e12008-02-24 18:37:08 +00001107 */
bart62a784c2009-02-15 13:11:14 +00001108void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +00001109{
bartbedfd232009-03-26 19:07:15 +00001110 DrdThreadId other_user;
1111 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001112
bartbedfd232009-03-26 19:07:15 +00001113 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
1114 other_user = DRD_INVALID_THREADID;
bart8f822af2009-06-08 18:20:42 +00001115 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001116 {
1117 Segment* p;
1118 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +00001119 {
bartbedfd232009-03-26 19:07:15 +00001120 if (other_user == DRD_INVALID_THREADID
1121 && i != DRD_(g_drd_running_tid))
1122 {
bart8f822af2009-06-08 18:20:42 +00001123 if (UNLIKELY(DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2)))
bartbedfd232009-03-26 19:07:15 +00001124 {
1125 other_user = i;
1126 }
1127 continue;
1128 }
bart8f822af2009-06-08 18:20:42 +00001129 DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
sewardjaf44c822007-11-25 14:01:38 +00001130 }
bartbedfd232009-03-26 19:07:15 +00001131 }
sewardjaf44c822007-11-25 14:01:38 +00001132
bartbedfd232009-03-26 19:07:15 +00001133 /*
1134 * If any other thread had accessed memory in [ a1, a2 [, update the
1135 * conflict set.
1136 */
1137 if (other_user != DRD_INVALID_THREADID
1138 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
1139 {
1140 thread_compute_conflict_set(&DRD_(g_conflict_set),
1141 DRD_(thread_get_running_tid)());
1142 }
sewardjaf44c822007-11-25 14:01:38 +00001143}
1144
bartd45d9952009-05-31 18:53:54 +00001145/** Specify whether memory loads should be recorded. */
1146void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001147{
bartbedfd232009-03-26 19:07:15 +00001148 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1149 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001150 tl_assert(enabled == !! enabled);
1151
1152 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +00001153}
1154
bartd45d9952009-05-31 18:53:54 +00001155/** Specify whether memory stores should be recorded. */
1156void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001157{
bartbedfd232009-03-26 19:07:15 +00001158 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1159 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001160 tl_assert(enabled == !! enabled);
1161
1162 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +00001163}
1164
bart86a87df2009-03-04 19:26:47 +00001165/**
1166 * Print the segment information for all threads.
1167 *
1168 * This function is only used for debugging purposes.
1169 */
bart62a784c2009-02-15 13:11:14 +00001170void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +00001171{
bartbedfd232009-03-26 19:07:15 +00001172 unsigned i;
1173 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001174
bart8f822af2009-06-08 18:20:42 +00001175 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001176 {
1177 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +00001178 {
bartbedfd232009-03-26 19:07:15 +00001179 VG_(printf)("**************\n"
1180 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
1181 "**************\n",
1182 i,
1183 DRD_(g_threadinfo)[i].vg_thread_exists,
1184 DRD_(g_threadinfo)[i].vg_threadid,
1185 DRD_(g_threadinfo)[i].posix_thread_exists,
1186 DRD_(g_threadinfo)[i].pt_threadid,
1187 DRD_(g_threadinfo)[i].detached_posix_thread);
1188 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1189 {
1190 DRD_(sg_print)(p);
1191 }
sewardjaf44c822007-11-25 14:01:38 +00001192 }
bartbedfd232009-03-26 19:07:15 +00001193 }
sewardjaf44c822007-11-25 14:01:38 +00001194}
1195
bart86a87df2009-03-04 19:26:47 +00001196/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001197static void show_call_stack(const DrdThreadId tid,
1198 const Char* const msg,
1199 ExeContext* const callstack)
1200{
bartbedfd232009-03-26 19:07:15 +00001201 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +00001202
bart63c92ea2009-07-19 17:53:56 +00001203 VG_(message)(Vg_UserMsg, "%s (thread %d)\n", msg, tid);
sewardjaf44c822007-11-25 14:01:38 +00001204
bartbedfd232009-03-26 19:07:15 +00001205 if (vg_tid != VG_INVALID_THREADID)
1206 {
1207 if (callstack)
1208 {
1209 VG_(pp_ExeContext)(callstack);
1210 }
1211 else
1212 {
1213 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1214 }
1215 }
1216 else
1217 {
1218 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001219 " (thread finished, call stack no longer available)\n");
bartbedfd232009-03-26 19:07:15 +00001220 }
sewardjaf44c822007-11-25 14:01:38 +00001221}
1222
bart86a87df2009-03-04 19:26:47 +00001223/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001224static void
1225thread_report_conflicting_segments_segment(const DrdThreadId tid,
1226 const Addr addr,
1227 const SizeT size,
1228 const BmAccessTypeT access_type,
1229 const Segment* const p)
1230{
bartbedfd232009-03-26 19:07:15 +00001231 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001232
bartbedfd232009-03-26 19:07:15 +00001233 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1234 && tid != DRD_INVALID_THREADID);
1235 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001236
bart8f822af2009-06-08 18:20:42 +00001237 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001238 {
1239 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001240 {
bartbedfd232009-03-26 19:07:15 +00001241 Segment* q;
1242 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1243 {
1244 /*
1245 * Since q iterates over the segments of thread i in order of
1246 * decreasing vector clocks, if q->vc <= p->vc, then
1247 * q->next->vc <= p->vc will also hold. Hence, break out of the
1248 * loop once this condition is met.
1249 */
1250 if (DRD_(vc_lte)(&q->vc, &p->vc))
1251 break;
1252 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1253 {
bart8f822af2009-06-08 18:20:42 +00001254 if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
bartbedfd232009-03-26 19:07:15 +00001255 access_type))
1256 {
1257 tl_assert(q->stacktrace);
1258 show_call_stack(i, "Other segment start",
1259 q->stacktrace);
1260 show_call_stack(i, "Other segment end",
1261 q->next ? q->next->stacktrace : 0);
1262 }
1263 }
1264 }
sewardjaf44c822007-11-25 14:01:38 +00001265 }
bartbedfd232009-03-26 19:07:15 +00001266 }
sewardjaf44c822007-11-25 14:01:38 +00001267}
1268
bart86a87df2009-03-04 19:26:47 +00001269/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001270void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1271 const Addr addr,
1272 const SizeT size,
1273 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001274{
bartbedfd232009-03-26 19:07:15 +00001275 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001276
bartbedfd232009-03-26 19:07:15 +00001277 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1278 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001279
bartbedfd232009-03-26 19:07:15 +00001280 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1281 {
bart8f822af2009-06-08 18:20:42 +00001282 if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
bartbedfd232009-03-26 19:07:15 +00001283 {
1284 thread_report_conflicting_segments_segment(tid, addr, size,
1285 access_type, p);
1286 }
1287 }
sewardjaf44c822007-11-25 14:01:38 +00001288}
sewardjaf44c822007-11-25 14:01:38 +00001289
bart324a23b2009-02-15 12:14:52 +00001290/**
bart8f822af2009-06-08 18:20:42 +00001291 * Verify whether the conflict set for thread tid is up to date. Only perform
1292 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1293 */
1294static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1295{
1296 static int do_verify_conflict_set = -1;
1297 Bool result;
1298 struct bitmap* computed_conflict_set = 0;
1299
1300 if (do_verify_conflict_set < 0)
1301 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1302
1303 if (do_verify_conflict_set == 0)
1304 return True;
1305
1306 thread_compute_conflict_set(&computed_conflict_set, tid);
1307 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1308 if (! result)
1309 {
1310 VG_(printf)("actual conflict set:\n");
1311 DRD_(bm_print)(DRD_(g_conflict_set));
1312 VG_(printf)("\n");
1313 VG_(printf)("computed conflict set:\n");
1314 DRD_(bm_print)(computed_conflict_set);
1315 VG_(printf)("\n");
1316 }
1317 DRD_(bm_delete)(computed_conflict_set);
1318 return result;
1319}
1320
1321/**
1322 * Compute the conflict set: a bitmap that represents the union of all memory
1323 * accesses of all segments that are unordered to the current segment of the
1324 * thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001325 */
bart86a87df2009-03-04 19:26:47 +00001326static void thread_compute_conflict_set(struct bitmap** conflict_set,
1327 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001328{
bartbedfd232009-03-26 19:07:15 +00001329 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001330
bartbedfd232009-03-26 19:07:15 +00001331 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1332 && tid != DRD_INVALID_THREADID);
1333 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001334
bart54803fe2009-06-21 09:26:27 +00001335 s_compute_conflict_set_count++;
bartbedfd232009-03-26 19:07:15 +00001336 s_conflict_set_bitmap_creation_count
1337 -= DRD_(bm_get_bitmap_creation_count)();
1338 s_conflict_set_bitmap2_creation_count
1339 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001340
bartbedfd232009-03-26 19:07:15 +00001341 if (*conflict_set)
1342 {
bartf6ec1fe2009-06-21 18:07:35 +00001343 DRD_(bm_cleanup)(*conflict_set);
1344 DRD_(bm_init)(*conflict_set);
bartbedfd232009-03-26 19:07:15 +00001345 }
bartf6ec1fe2009-06-21 18:07:35 +00001346 else
1347 {
1348 *conflict_set = DRD_(bm_new)();
1349 }
bart26f73e12008-02-24 18:37:08 +00001350
bartbedfd232009-03-26 19:07:15 +00001351 if (s_trace_conflict_set)
1352 {
bart8f822af2009-06-08 18:20:42 +00001353 char* str;
bart26f73e12008-02-24 18:37:08 +00001354
bart8f822af2009-06-08 18:20:42 +00001355 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1356 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001357 "computing conflict set for thread %d with vc %s\n",
1358 tid, str);
bart8f822af2009-06-08 18:20:42 +00001359 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001360 }
sewardjaf44c822007-11-25 14:01:38 +00001361
bartbedfd232009-03-26 19:07:15 +00001362 p = DRD_(g_threadinfo)[tid].last;
1363 {
1364 unsigned j;
1365
1366 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001367 {
bart8f822af2009-06-08 18:20:42 +00001368 char* vc;
bartbedfd232009-03-26 19:07:15 +00001369
bart8f822af2009-06-08 18:20:42 +00001370 vc = DRD_(vc_aprint)(&p->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001371 VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
bart8f822af2009-06-08 18:20:42 +00001372 tid, vc);
1373 VG_(free)(vc);
bart26f73e12008-02-24 18:37:08 +00001374 }
sewardjaf44c822007-11-25 14:01:38 +00001375
bart8f822af2009-06-08 18:20:42 +00001376 for (j = 0; j < DRD_N_THREADS; j++)
bartbedfd232009-03-26 19:07:15 +00001377 {
1378 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1379 {
bart8f822af2009-06-08 18:20:42 +00001380 Segment* q;
bartbedfd232009-03-26 19:07:15 +00001381 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1382 {
1383 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1384 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1385 {
1386 if (s_trace_conflict_set)
1387 {
bart8f822af2009-06-08 18:20:42 +00001388 char* str;
1389
1390 str = DRD_(vc_aprint)(&q->vc);
1391 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001392 "conflict set: [%d] merging segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001393 j, str);
1394 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001395 }
bart8f822af2009-06-08 18:20:42 +00001396 DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
bartbedfd232009-03-26 19:07:15 +00001397 }
1398 else
1399 {
1400 if (s_trace_conflict_set)
1401 {
bart8f822af2009-06-08 18:20:42 +00001402 char* str;
1403
1404 str = DRD_(vc_aprint)(&q->vc);
1405 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001406 "conflict set: [%d] ignoring segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001407 j, str);
1408 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001409 }
1410 }
1411 }
1412 }
1413 }
1414 }
sewardjaf44c822007-11-25 14:01:38 +00001415
bartbedfd232009-03-26 19:07:15 +00001416 s_conflict_set_bitmap_creation_count
1417 += DRD_(bm_get_bitmap_creation_count)();
1418 s_conflict_set_bitmap2_creation_count
1419 += DRD_(bm_get_bitmap2_creation_count)();
1420
bart8f822af2009-06-08 18:20:42 +00001421 if (s_trace_conflict_set_bm)
bartbedfd232009-03-26 19:07:15 +00001422 {
sewardj1e29ebc2009-07-15 14:49:17 +00001423 VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
bartbedfd232009-03-26 19:07:15 +00001424 DRD_(bm_print)(*conflict_set);
sewardj1e29ebc2009-07-15 14:49:17 +00001425 VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
bartbedfd232009-03-26 19:07:15 +00001426 }
sewardjaf44c822007-11-25 14:01:38 +00001427}
1428
bart8f822af2009-06-08 18:20:42 +00001429/**
1430 * Update the conflict set after the vector clock of thread tid has been
1431 * updated from old_vc to its current value, either because a new segment has
1432 * been created or because of a synchronization operation.
1433 */
1434void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1435 const VectorClock* const old_vc)
1436{
1437 const VectorClock* new_vc;
1438 Segment* p;
1439 unsigned j;
1440
1441 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1442 && tid != DRD_INVALID_THREADID);
1443 tl_assert(old_vc);
1444 tl_assert(tid == DRD_(g_drd_running_tid));
1445 tl_assert(DRD_(g_conflict_set));
1446
1447 if (s_trace_conflict_set)
1448 {
1449 char* str;
1450
1451 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1452 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001453 "updating conflict set for thread %d with vc %s\n",
1454 tid, str);
bart8f822af2009-06-08 18:20:42 +00001455 VG_(free)(str);
1456 }
1457
1458 new_vc = &DRD_(g_threadinfo)[tid].last->vc;
1459
1460 DRD_(bm_unmark)(DRD_(g_conflict_set));
1461
1462 for (j = 0; j < DRD_N_THREADS; j++)
1463 {
1464 Segment* q;
1465
1466 if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1467 continue;
1468
1469 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1470 {
1471 const int included_in_old_conflict_set
1472 = ! DRD_(vc_lte)(&q->vc, old_vc)
1473 && ! DRD_(vc_lte)(old_vc, &q->vc);
1474 const int included_in_new_conflict_set
1475 = ! DRD_(vc_lte)(&q->vc, new_vc)
1476 && ! DRD_(vc_lte)(new_vc, &q->vc);
1477 if (included_in_old_conflict_set != included_in_new_conflict_set)
1478 {
1479 if (s_trace_conflict_set)
1480 {
1481 char* str;
1482
1483 str = DRD_(vc_aprint)(&q->vc);
1484 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001485 "conflict set: [%d] merging segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001486 VG_(free)(str);
1487 }
1488 DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1489 }
1490 else
1491 {
1492 if (s_trace_conflict_set)
1493 {
1494 char* str;
1495
1496 str = DRD_(vc_aprint)(&q->vc);
1497 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001498 "conflict set: [%d] ignoring segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001499 VG_(free)(str);
1500 }
1501 }
1502 }
1503 }
1504
1505 DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1506
1507 p = DRD_(g_threadinfo)[tid].last;
1508 {
1509 for (j = 0; j < DRD_N_THREADS; j++)
1510 {
1511 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1512 {
1513 Segment* q;
1514 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1515 {
1516 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1517 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1518 {
1519 DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1520 }
1521 }
1522 }
1523 }
1524 }
1525
1526 DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1527
bart54803fe2009-06-21 09:26:27 +00001528 s_update_conflict_set_count++;
bart8f822af2009-06-08 18:20:42 +00001529
1530 if (s_trace_conflict_set_bm)
1531 {
sewardj1e29ebc2009-07-15 14:49:17 +00001532 VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
bart8f822af2009-06-08 18:20:42 +00001533 DRD_(bm_print)(DRD_(g_conflict_set));
sewardj1e29ebc2009-07-15 14:49:17 +00001534 VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
bart8f822af2009-06-08 18:20:42 +00001535 }
1536
1537 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1538}
1539
bart86a87df2009-03-04 19:26:47 +00001540/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001541ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001542{
bartbedfd232009-03-26 19:07:15 +00001543 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001544}
1545
bart86a87df2009-03-04 19:26:47 +00001546/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001547ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001548{
bartbedfd232009-03-26 19:07:15 +00001549 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001550}
1551
bart54803fe2009-06-21 09:26:27 +00001552/** Return how many times the conflict set has been updated entirely. */
1553ULong DRD_(thread_get_compute_conflict_set_count)()
sewardjaf44c822007-11-25 14:01:38 +00001554{
bart54803fe2009-06-21 09:26:27 +00001555 return s_compute_conflict_set_count;
1556}
1557
1558/** Return how many times the conflict set has been updated partially. */
1559ULong DRD_(thread_get_update_conflict_set_count)(void)
1560{
bartbedfd232009-03-26 19:07:15 +00001561 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001562}
1563
bart86a87df2009-03-04 19:26:47 +00001564/**
barte5214662009-06-21 11:51:23 +00001565 * Return how many times the conflict set has been updated partially
1566 * because a new segment has been created.
1567 */
1568ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
1569{
1570 return s_update_conflict_set_new_sg_count;
1571}
1572
1573/**
1574 * Return how many times the conflict set has been updated partially
1575 * because of combining vector clocks due to synchronization operations
1576 * other than reader/writer lock or barrier operations.
1577 */
1578ULong DRD_(thread_get_update_conflict_set_sync_count)(void)
1579{
1580 return s_update_conflict_set_sync_count;
1581}
1582
1583/**
1584 * Return how many times the conflict set has been updated partially
1585 * because of thread joins.
1586 */
1587ULong DRD_(thread_get_update_conflict_set_join_count)(void)
1588{
1589 return s_update_conflict_set_join_count;
1590}
1591
1592/**
bart86a87df2009-03-04 19:26:47 +00001593 * Return the number of first-level bitmaps that have been created during
1594 * conflict set updates.
1595 */
bart62a784c2009-02-15 13:11:14 +00001596ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001597{
bartbedfd232009-03-26 19:07:15 +00001598 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001599}
1600
bart86a87df2009-03-04 19:26:47 +00001601/**
1602 * Return the number of second-level bitmaps that have been created during
1603 * conflict set updates.
1604 */
bart62a784c2009-02-15 13:11:14 +00001605ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001606{
bartbedfd232009-03-26 19:07:15 +00001607 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001608}