blob: cf22859a53afebe1b23eb2bf21b70d0bd652312e [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);
sewardjaf44c822007-11-25 14:01:38 +000055
56
bart324a23b2009-02-15 12:14:52 +000057/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000058
bart86a87df2009-03-04 19:26:47 +000059static ULong s_context_switch_count;
60static ULong s_discard_ordered_segments_count;
61static ULong s_update_conflict_set_count;
62static ULong s_conflict_set_new_segment_count;
63static ULong s_conflict_set_combine_vc_count;
64static ULong s_conflict_set_bitmap_creation_count;
65static ULong s_conflict_set_bitmap2_creation_count;
66static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bart324a23b2009-02-15 12:14:52 +000067DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
68ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
69struct bitmap* DRD_(g_conflict_set);
bart86a87df2009-03-04 19:26:47 +000070static Bool s_trace_context_switches = False;
71static Bool s_trace_conflict_set = False;
72static Bool s_trace_fork_join = False;
73static Bool s_segment_merging = True;
sewardjaf44c822007-11-25 14:01:38 +000074
75
bart324a23b2009-02-15 12:14:52 +000076/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000077
bart86a87df2009-03-04 19:26:47 +000078/** Enables/disables context switch tracing. */
bart62a784c2009-02-15 13:11:14 +000079void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000080{
bartbedfd232009-03-26 19:07:15 +000081 tl_assert(t == False || t == True);
82 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000083}
84
bart86a87df2009-03-04 19:26:47 +000085/** Enables/disables conflict set tracing. */
bart62a784c2009-02-15 13:11:14 +000086void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000087{
bartbedfd232009-03-26 19:07:15 +000088 tl_assert(t == False || t == True);
89 s_trace_conflict_set = t;
bart26f73e12008-02-24 18:37:08 +000090}
91
bart86a87df2009-03-04 19:26:47 +000092/** Report whether fork/join tracing is enabled. */
bart09dc13f2009-02-14 15:13:31 +000093Bool DRD_(thread_get_trace_fork_join)(void)
94{
bartbedfd232009-03-26 19:07:15 +000095 return s_trace_fork_join;
bart09dc13f2009-02-14 15:13:31 +000096}
97
bart86a87df2009-03-04 19:26:47 +000098/** Enables/disables fork/join tracing. */
bart09dc13f2009-02-14 15:13:31 +000099void DRD_(thread_set_trace_fork_join)(const Bool t)
100{
bartbedfd232009-03-26 19:07:15 +0000101 tl_assert(t == False || t == True);
102 s_trace_fork_join = t;
bart09dc13f2009-02-14 15:13:31 +0000103}
104
bart86a87df2009-03-04 19:26:47 +0000105/** Enables/disables segment merging. */
bart62a784c2009-02-15 13:11:14 +0000106void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000107{
bartbedfd232009-03-26 19:07:15 +0000108 tl_assert(m == False || m == True);
109 s_segment_merging = m;
barta9c37392008-03-22 09:38:48 +0000110}
111
sewardjaf44c822007-11-25 14:01:38 +0000112/**
bart86a87df2009-03-04 19:26:47 +0000113 * Convert Valgrind's ThreadId into a DrdThreadId.
114 *
115 * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
116 * Valgrind ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000117 */
bart62a784c2009-02-15 13:11:14 +0000118DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000119{
bartbedfd232009-03-26 19:07:15 +0000120 int i;
sewardjaf44c822007-11-25 14:01:38 +0000121
bartbedfd232009-03-26 19:07:15 +0000122 if (tid == VG_INVALID_THREADID)
123 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000124
bartbedfd232009-03-26 19:07:15 +0000125 for (i = 1; i < DRD_N_THREADS; i++)
126 {
127 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
128 && DRD_(g_threadinfo)[i].vg_threadid == tid)
129 {
130 return i;
131 }
132 }
sewardjaf44c822007-11-25 14:01:38 +0000133
bartbedfd232009-03-26 19:07:15 +0000134 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000135}
136
bart86a87df2009-03-04 19:26:47 +0000137/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000138static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000139{
bartbedfd232009-03-26 19:07:15 +0000140 int i;
sewardjaf44c822007-11-25 14:01:38 +0000141
bartbedfd232009-03-26 19:07:15 +0000142 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000143
bartbedfd232009-03-26 19:07:15 +0000144 for (i = 1; i < DRD_N_THREADS; i++)
145 {
146 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
147 && DRD_(g_threadinfo)[i].posix_thread_exists == False
148 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
149 {
150 tl_assert(! DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000151
bartbedfd232009-03-26 19:07:15 +0000152 DRD_(g_threadinfo)[i].vg_thread_exists = True;
153 DRD_(g_threadinfo)[i].vg_threadid = tid;
154 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
155 DRD_(g_threadinfo)[i].stack_min = 0;
156 DRD_(g_threadinfo)[i].stack_min_min = 0;
157 DRD_(g_threadinfo)[i].stack_startup = 0;
158 DRD_(g_threadinfo)[i].stack_max = 0;
159 DRD_(g_threadinfo)[i].is_recording = True;
160 DRD_(g_threadinfo)[i].synchr_nesting = 0;
161 tl_assert(DRD_(g_threadinfo)[i].first == 0);
162 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000163
bartbedfd232009-03-26 19:07:15 +0000164 tl_assert(DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000165
bartbedfd232009-03-26 19:07:15 +0000166 return i;
167 }
168 }
sewardjaf44c822007-11-25 14:01:38 +0000169
bartbedfd232009-03-26 19:07:15 +0000170 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000171
bartbedfd232009-03-26 19:07:15 +0000172 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000173}
174
bart86a87df2009-03-04 19:26:47 +0000175/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000176DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000177{
bartbedfd232009-03-26 19:07:15 +0000178 int i;
sewardjaf44c822007-11-25 14:01:38 +0000179
bartbedfd232009-03-26 19:07:15 +0000180 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000181
bartbedfd232009-03-26 19:07:15 +0000182 for (i = 1; i < DRD_N_THREADS; i++)
183 {
184 if (DRD_(g_threadinfo)[i].posix_thread_exists
185 && DRD_(g_threadinfo)[i].pt_threadid == tid)
186 {
187 return i;
188 }
189 }
190 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000191}
192
bart86a87df2009-03-04 19:26:47 +0000193/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000194ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000195{
bartbedfd232009-03-26 19:07:15 +0000196 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
197 && tid != DRD_INVALID_THREADID);
198 return (DRD_(g_threadinfo)[tid].vg_thread_exists
199 ? DRD_(g_threadinfo)[tid].vg_threadid
200 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000201}
202
bart23d3a4e2008-04-05 12:53:00 +0000203#if 0
bart324a23b2009-02-15 12:14:52 +0000204/**
205 * Sanity check of the doubly linked list of segments referenced by a
206 * ThreadInfo struct.
207 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000208 */
bart62a784c2009-02-15 13:11:14 +0000209static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000210{
bartbedfd232009-03-26 19:07:15 +0000211 Segment* p;
212 for (p = ti->first; p; p = p->next) {
213 if (p->next && p->next->prev != p)
214 return False;
215 if (p->next == 0 && p != ti->last)
216 return False;
217 }
218 for (p = ti->last; p; p = p->prev) {
219 if (p->prev && p->prev->next != p)
220 return False;
221 if (p->prev == 0 && p != ti->first)
222 return False;
223 }
224 return True;
sewardjaf44c822007-11-25 14:01:38 +0000225}
bart23d3a4e2008-04-05 12:53:00 +0000226#endif
sewardjaf44c822007-11-25 14:01:38 +0000227
bart439c55f2009-02-15 10:38:37 +0000228/**
229 * Create the first segment for a newly started thread.
230 *
231 * This function is called from the handler installed via
232 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
233 * from the context of the creator thread, before the new thread has been
234 * created.
bart86a87df2009-03-04 19:26:47 +0000235 *
236 * @param[in] creator DRD thread ID of the creator thread.
237 * @param[in] vg_created Valgrind thread ID of the created thread.
238 *
239 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000240 */
bart62a784c2009-02-15 13:11:14 +0000241DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
242 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000243{
bartbedfd232009-03-26 19:07:15 +0000244 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000245
bartbedfd232009-03-26 19:07:15 +0000246 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
247 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
248 tl_assert(0 <= (int)created && created < DRD_N_THREADS
249 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000250
bartbedfd232009-03-26 19:07:15 +0000251 tl_assert(DRD_(g_threadinfo)[created].first == 0);
252 tl_assert(DRD_(g_threadinfo)[created].last == 0);
253 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000254
bartbedfd232009-03-26 19:07:15 +0000255 return created;
sewardjaf44c822007-11-25 14:01:38 +0000256}
257
bart439c55f2009-02-15 10:38:37 +0000258/**
bart86a87df2009-03-04 19:26:47 +0000259 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
260 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000261 * on the newly created thread, e.g. from the handler installed via
262 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000263 *
264 * @param[in] vg_created Valgrind thread ID of the newly created thread.
265 *
266 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000267 */
bart62a784c2009-02-15 13:11:14 +0000268DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000269{
bartbedfd232009-03-26 19:07:15 +0000270 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000271
bartbedfd232009-03-26 19:07:15 +0000272 tl_assert(0 <= (int)created && created < DRD_N_THREADS
273 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000274
bartbedfd232009-03-26 19:07:15 +0000275 DRD_(g_threadinfo)[created].stack_max
276 = VG_(thread_get_stack_max)(vg_created);
277 DRD_(g_threadinfo)[created].stack_startup
278 = DRD_(g_threadinfo)[created].stack_max;
279 DRD_(g_threadinfo)[created].stack_min
280 = DRD_(g_threadinfo)[created].stack_max;
281 DRD_(g_threadinfo)[created].stack_min_min
282 = DRD_(g_threadinfo)[created].stack_max;
283 DRD_(g_threadinfo)[created].stack_size
284 = VG_(thread_get_stack_size)(vg_created);
285 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000286
bartbedfd232009-03-26 19:07:15 +0000287 return created;
bart439c55f2009-02-15 10:38:37 +0000288}
bart09dc13f2009-02-14 15:13:31 +0000289
bart324a23b2009-02-15 12:14:52 +0000290/**
291 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
292 * after thread drd_joiner joined thread drd_joinee.
293 */
bart09dc13f2009-02-14 15:13:31 +0000294void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
295{
bartbedfd232009-03-26 19:07:15 +0000296 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
297 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
298 DRD_(thread_new_segment)(drd_joinee);
299 DRD_(thread_combine_vc)(drd_joiner, drd_joinee);
300 DRD_(thread_new_segment)(drd_joiner);
bart09dc13f2009-02-14 15:13:31 +0000301
bartbedfd232009-03-26 19:07:15 +0000302 if (s_trace_fork_join)
303 {
304 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
305 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
306 const unsigned msg_size = 256;
307 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000308
bartbedfd232009-03-26 19:07:15 +0000309 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
310 tl_assert(msg);
311 VG_(snprintf)(msg, msg_size,
312 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
313 joiner, drd_joiner, joinee, drd_joinee);
314 if (joiner)
315 {
316 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
317 ", new vc: ");
318 DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
319 DRD_(thread_get_vc)(drd_joiner));
320 }
321 VG_(message)(Vg_DebugMsg, "%s", msg);
322 VG_(free)(msg);
323 }
bart09dc13f2009-02-14 15:13:31 +0000324
bartbedfd232009-03-26 19:07:15 +0000325 if (! DRD_(get_check_stack_accesses)())
326 {
327 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
328 - DRD_(thread_get_stack_size)(drd_joinee),
329 DRD_(thread_get_stack_max)(drd_joinee));
330 }
331 DRD_(clientobj_delete_thread)(drd_joinee);
332 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000333}
334
bart324a23b2009-02-15 12:14:52 +0000335/**
336 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
337 * and accesses this data structure from multiple threads without locking.
338 * Any conflicting accesses in the range stack_startup..stack_max will be
339 * ignored.
340 */
bart62a784c2009-02-15 13:11:14 +0000341void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
342 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000343{
bartbedfd232009-03-26 19:07:15 +0000344 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
345 && tid != DRD_INVALID_THREADID);
346 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
347 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
348 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000349}
350
bart86a87df2009-03-04 19:26:47 +0000351/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000352Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000353{
bartbedfd232009-03-26 19:07:15 +0000354 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
355 && tid != DRD_INVALID_THREADID);
356 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000357}
358
bart86a87df2009-03-04 19:26:47 +0000359/**
360 * Return the lowest value that was ever assigned to the stack pointer
361 * for the specified thread.
362 */
bart62a784c2009-02-15 13:11:14 +0000363Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000364{
bartbedfd232009-03-26 19:07:15 +0000365 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
366 && tid != DRD_INVALID_THREADID);
367 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000368}
369
bart86a87df2009-03-04 19:26:47 +0000370/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000371Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000372{
bartbedfd232009-03-26 19:07:15 +0000373 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
374 && tid != DRD_INVALID_THREADID);
375 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000376}
377
bart86a87df2009-03-04 19:26:47 +0000378/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000379SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000380{
bartbedfd232009-03-26 19:07:15 +0000381 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
382 && tid != DRD_INVALID_THREADID);
383 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000384}
385
bart09dc13f2009-02-14 15:13:31 +0000386/**
387 * Clean up thread-specific data structures. Call this just after
388 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000389 */
bart62a784c2009-02-15 13:11:14 +0000390void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000391{
bartbedfd232009-03-26 19:07:15 +0000392 Segment* sg;
393 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000394
bartbedfd232009-03-26 19:07:15 +0000395 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000396
bartbedfd232009-03-26 19:07:15 +0000397 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
398 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
399 {
400 sg_prev = sg->prev;
401 sg->prev = 0;
402 sg->next = 0;
403 DRD_(sg_put)(sg);
404 }
405 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
406 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
407 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
408 DRD_(g_threadinfo)[tid].first = 0;
409 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000410
bartbedfd232009-03-26 19:07:15 +0000411 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000412}
413
bart324a23b2009-02-15 12:14:52 +0000414/**
415 * Called after a thread performed its last memory access and before
416 * thread_delete() is called. Note: thread_delete() is only called for
417 * joinable threads, not for detached threads.
418 */
bart62a784c2009-02-15 13:11:14 +0000419void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000420{
bartbedfd232009-03-26 19:07:15 +0000421 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
422 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000423
bartbedfd232009-03-26 19:07:15 +0000424 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000425
bartbedfd232009-03-26 19:07:15 +0000426 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
427 {
428 /*
429 * Once a detached thread has finished, its stack is deallocated and
430 * should no longer be taken into account when computing the conflict set.
431 */
432 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000433
bartbedfd232009-03-26 19:07:15 +0000434 /*
435 * For a detached thread, calling pthread_exit() invalidates the
436 * POSIX thread ID associated with the detached thread. For joinable
437 * POSIX threads however, the POSIX thread ID remains live after the
438 * pthread_exit() call until pthread_join() is called.
439 */
440 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
441 }
sewardjaf44c822007-11-25 14:01:38 +0000442}
443
bart9b2974a2008-09-27 12:35:31 +0000444/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000445void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000446{
bartbedfd232009-03-26 19:07:15 +0000447 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
448 && tid != DRD_INVALID_THREADID);
449 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000450
bartbedfd232009-03-26 19:07:15 +0000451 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000452}
453
barte7dff242009-04-23 17:12:39 +0000454/**
455 * Store the POSIX thread ID for the specified thread.
456 *
457 * @note This function can be called two times for the same thread -- see also
458 * the comment block preceding the pthread_create() wrapper in
459 * drd_pthread_intercepts.c.
460 */
bart62a784c2009-02-15 13:11:14 +0000461void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000462{
bartbedfd232009-03-26 19:07:15 +0000463 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
464 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000465 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
466 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000467 tl_assert(ptid != INVALID_POSIX_THREADID);
468 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
469 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000470}
471
bart86a87df2009-03-04 19:26:47 +0000472/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000473Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000474{
bartbedfd232009-03-26 19:07:15 +0000475 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
476 && tid != DRD_INVALID_THREADID);
477 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000478}
479
bart86a87df2009-03-04 19:26:47 +0000480/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000481void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000482{
bartbedfd232009-03-26 19:07:15 +0000483 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
484 && tid != DRD_INVALID_THREADID);
485 tl_assert(!! joinable == joinable);
486 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000487#if 0
bartbedfd232009-03-26 19:07:15 +0000488 VG_(message)(Vg_DebugMsg,
489 "thread_set_joinable(%d/%d, %s)",
490 tid,
491 DRD_(g_threadinfo)[tid].vg_threadid,
492 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000493#endif
bartbedfd232009-03-26 19:07:15 +0000494 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000495}
496
bart86a87df2009-03-04 19:26:47 +0000497/**
498 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
499 * conflict set.
500 */
bart62a784c2009-02-15 13:11:14 +0000501void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000502{
bartbedfd232009-03-26 19:07:15 +0000503 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000504
bartbedfd232009-03-26 19:07:15 +0000505 if (vg_tid != s_vg_running_tid)
506 {
507 DRD_(thread_set_running_tid)(vg_tid,
508 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
509 }
sewardj8b09d4f2007-12-04 21:27:18 +0000510
bartbedfd232009-03-26 19:07:15 +0000511 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
512 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000513}
514
bart86a87df2009-03-04 19:26:47 +0000515/**
516 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
517 * conflict set.
518 */
bart62a784c2009-02-15 13:11:14 +0000519void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
520 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000521{
bartbedfd232009-03-26 19:07:15 +0000522 tl_assert(vg_tid != VG_INVALID_THREADID);
523 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000524
bartbedfd232009-03-26 19:07:15 +0000525 if (vg_tid != s_vg_running_tid)
526 {
527 if (s_trace_context_switches
528 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
529 {
530 VG_(message)(Vg_DebugMsg,
531 "Context switch from thread %d/%d to thread %d/%d;"
532 " segments: %llu",
533 s_vg_running_tid, DRD_(g_drd_running_tid),
534 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
535 DRD_(sg_get_segments_alive_count)());
536 }
537 s_vg_running_tid = vg_tid;
538 DRD_(g_drd_running_tid) = drd_tid;
539 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
540 s_context_switch_count++;
541 }
sewardj8b09d4f2007-12-04 21:27:18 +0000542
bartbedfd232009-03-26 19:07:15 +0000543 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
544 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000545}
546
bart86a87df2009-03-04 19:26:47 +0000547/**
548 * Increase the synchronization nesting counter. Must be called before the
549 * client calls a synchronization function.
550 */
bart62a784c2009-02-15 13:11:14 +0000551int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000552{
bartbedfd232009-03-26 19:07:15 +0000553 tl_assert(DRD_(IsValidDrdThreadId)(tid));
554 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000555}
556
bart86a87df2009-03-04 19:26:47 +0000557/**
558 * Decrease the synchronization nesting counter. Must be called after the
559 * client left a synchronization function.
560 */
bart62a784c2009-02-15 13:11:14 +0000561int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000562{
bartbedfd232009-03-26 19:07:15 +0000563 tl_assert(DRD_(IsValidDrdThreadId)(tid));
564 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
565 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000566}
567
bart86a87df2009-03-04 19:26:47 +0000568/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000569int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000570{
bartbedfd232009-03-26 19:07:15 +0000571 tl_assert(DRD_(IsValidDrdThreadId)(tid));
572 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000573}
574
bart1a473c72008-03-13 19:03:38 +0000575/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000576static
bart86a87df2009-03-04 19:26:47 +0000577void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000578{
bartbedfd232009-03-26 19:07:15 +0000579 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
580 && tid != DRD_INVALID_THREADID);
581 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
582 sg->prev = DRD_(g_threadinfo)[tid].last;
583 sg->next = 0;
584 if (DRD_(g_threadinfo)[tid].last)
585 DRD_(g_threadinfo)[tid].last->next = sg;
586 DRD_(g_threadinfo)[tid].last = sg;
587 if (DRD_(g_threadinfo)[tid].first == 0)
588 DRD_(g_threadinfo)[tid].first = sg;
589 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000590}
591
bart324a23b2009-02-15 12:14:52 +0000592/**
593 * Remove a segment from the segment list of thread threadid, and free the
594 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000595 */
bart62a784c2009-02-15 13:11:14 +0000596static
bart86a87df2009-03-04 19:26:47 +0000597void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000598{
bartbedfd232009-03-26 19:07:15 +0000599 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
600 && tid != DRD_INVALID_THREADID);
601 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart26f73e12008-02-24 18:37:08 +0000602
bartbedfd232009-03-26 19:07:15 +0000603 if (sg->prev)
604 sg->prev->next = sg->next;
605 if (sg->next)
606 sg->next->prev = sg->prev;
607 if (sg == DRD_(g_threadinfo)[tid].first)
608 DRD_(g_threadinfo)[tid].first = sg->next;
609 if (sg == DRD_(g_threadinfo)[tid].last)
610 DRD_(g_threadinfo)[tid].last = sg->prev;
611 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000612
bartbedfd232009-03-26 19:07:15 +0000613 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000614}
615
bart86a87df2009-03-04 19:26:47 +0000616/**
617 * Returns a pointer to the vector clock of the most recent segment associated
618 * with thread 'tid'.
619 */
bart62a784c2009-02-15 13:11:14 +0000620VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000621{
bartbedfd232009-03-26 19:07:15 +0000622 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
623 && tid != DRD_INVALID_THREADID);
624 tl_assert(DRD_(g_threadinfo)[tid].last);
625 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000626}
627
bart324a23b2009-02-15 12:14:52 +0000628/**
629 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000630 */
bart62a784c2009-02-15 13:11:14 +0000631void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000632{
bartbedfd232009-03-26 19:07:15 +0000633 tl_assert(sg);
634 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
635 && tid != DRD_INVALID_THREADID);
636 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000637
bartbedfd232009-03-26 19:07:15 +0000638 DRD_(sg_put)(*sg);
639 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000640}
641
sewardjaf44c822007-11-25 14:01:38 +0000642/**
643 * Compute the minimum of all latest vector clocks of all threads
644 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000645 *
sewardjaf44c822007-11-25 14:01:38 +0000646 * @param vc pointer to a vectorclock, holds result upon return.
647 */
bart62a784c2009-02-15 13:11:14 +0000648static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000649{
bartbedfd232009-03-26 19:07:15 +0000650 unsigned i;
651 Bool first;
652 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000653
bartbedfd232009-03-26 19:07:15 +0000654 first = True;
655 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
656 i++)
657 {
658 latest_sg = DRD_(g_threadinfo)[i].last;
659 if (latest_sg)
660 {
661 if (first)
662 DRD_(vc_assign)(vc, &latest_sg->vc);
663 else
664 DRD_(vc_min)(vc, &latest_sg->vc);
665 first = False;
666 }
667 }
sewardjaf44c822007-11-25 14:01:38 +0000668}
669
bart86a87df2009-03-04 19:26:47 +0000670/**
671 * Compute the maximum of all latest vector clocks of all threads.
672 *
673 * @param vc pointer to a vectorclock, holds result upon return.
674 */
bart62a784c2009-02-15 13:11:14 +0000675static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000676{
bartbedfd232009-03-26 19:07:15 +0000677 unsigned i;
678 Bool first;
679 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000680
bartbedfd232009-03-26 19:07:15 +0000681 first = True;
682 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
683 i++)
684 {
685 latest_sg = DRD_(g_threadinfo)[i].last;
686 if (latest_sg)
687 {
688 if (first)
689 DRD_(vc_assign)(vc, &latest_sg->vc);
690 else
691 DRD_(vc_combine)(vc, &latest_sg->vc);
692 first = False;
693 }
694 }
sewardjaf44c822007-11-25 14:01:38 +0000695}
696
697/**
bart5bd9f2d2008-03-03 20:31:58 +0000698 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000699 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000700 * data race.
701 */
bart62a784c2009-02-15 13:11:14 +0000702static void DRD_(thread_discard_ordered_segments)(void)
sewardjaf44c822007-11-25 14:01:38 +0000703{
bartbedfd232009-03-26 19:07:15 +0000704 unsigned i;
705 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000706
bartbedfd232009-03-26 19:07:15 +0000707 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000708
bartbedfd232009-03-26 19:07:15 +0000709 DRD_(vc_init)(&thread_vc_min, 0, 0);
710 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
711 if (DRD_(sg_get_trace)())
712 {
713 char msg[256];
714 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000715
bartbedfd232009-03-26 19:07:15 +0000716 DRD_(vc_init)(&thread_vc_max, 0, 0);
717 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
718 VG_(snprintf)(msg, sizeof(msg),
719 "Discarding ordered segments -- min vc is ");
720 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
721 &thread_vc_min);
722 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
723 ", max vc is ");
724 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
725 &thread_vc_max);
726 VG_(message)(Vg_UserMsg, "%s", msg);
727 DRD_(vc_cleanup)(&thread_vc_max);
728 }
sewardjaf44c822007-11-25 14:01:38 +0000729
bartbedfd232009-03-26 19:07:15 +0000730 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
731 i++)
732 {
733 Segment* sg;
734 Segment* sg_next;
735 for (sg = DRD_(g_threadinfo)[i].first;
736 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
737 sg = sg_next)
738 {
739 thread_discard_segment(i, sg);
740 }
741 }
742 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000743}
744
bart324a23b2009-02-15 12:14:52 +0000745/**
746 * Merge all segments that may be merged without triggering false positives
747 * or discarding real data races. For the theoretical background of segment
748 * merging, see also the following paper:
749 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
750 * Bounding the number of segment histories during data race detection.
751 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
752 * September 2002.
barta9c37392008-03-22 09:38:48 +0000753 */
754static void thread_merge_segments(void)
755{
bartbedfd232009-03-26 19:07:15 +0000756 unsigned i;
barta9c37392008-03-22 09:38:48 +0000757
bartbedfd232009-03-26 19:07:15 +0000758 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
759 i++)
760 {
761 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000762
bartbedfd232009-03-26 19:07:15 +0000763 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000764
bartbedfd232009-03-26 19:07:15 +0000765 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000766 {
bartbedfd232009-03-26 19:07:15 +0000767 if (DRD_(sg_get_refcnt)(sg) == 1
768 && sg->next
769 && DRD_(sg_get_refcnt)(sg->next) == 1
770 && sg->next->next)
771 {
772 /* Merge sg and sg->next into sg. */
773 DRD_(sg_merge)(sg, sg->next);
774 thread_discard_segment(i, sg->next);
775 }
barta9c37392008-03-22 09:38:48 +0000776 }
barta9c37392008-03-22 09:38:48 +0000777
bartbedfd232009-03-26 19:07:15 +0000778 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
779 }
barta9c37392008-03-22 09:38:48 +0000780}
781
bart324a23b2009-02-15 12:14:52 +0000782/**
bart324a23b2009-02-15 12:14:52 +0000783 * Create a new segment for the specified thread, and discard any segments
784 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000785 */
bart62a784c2009-02-15 13:11:14 +0000786void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000787{
bartbedfd232009-03-26 19:07:15 +0000788 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000789
bartbedfd232009-03-26 19:07:15 +0000790 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
791 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000792
bartbedfd232009-03-26 19:07:15 +0000793 new_sg = DRD_(sg_new)(tid, tid);
794 thread_append_segment(tid, new_sg);
bartd66e3a82008-04-06 15:02:17 +0000795
bartbedfd232009-03-26 19:07:15 +0000796 thread_compute_conflict_set(&DRD_(g_conflict_set), DRD_(g_drd_running_tid));
797 s_conflict_set_new_segment_count++;
sewardjaf44c822007-11-25 14:01:38 +0000798
bartbedfd232009-03-26 19:07:15 +0000799 DRD_(thread_discard_ordered_segments)();
bart26f73e12008-02-24 18:37:08 +0000800
bartbedfd232009-03-26 19:07:15 +0000801 if (s_segment_merging)
802 {
803 thread_merge_segments();
804 }
sewardjaf44c822007-11-25 14:01:38 +0000805}
806
bart26f73e12008-02-24 18:37:08 +0000807/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart62a784c2009-02-15 13:11:14 +0000808void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000809{
bartbedfd232009-03-26 19:07:15 +0000810 tl_assert(joiner != joinee);
811 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
812 && joiner != DRD_INVALID_THREADID);
813 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
814 && joinee != DRD_INVALID_THREADID);
815 tl_assert(DRD_(g_threadinfo)[joiner].last);
816 tl_assert(DRD_(g_threadinfo)[joinee].last);
817 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
818 &DRD_(g_threadinfo)[joinee].last->vc);
819 DRD_(thread_discard_ordered_segments)();
sewardjaf44c822007-11-25 14:01:38 +0000820
bartbedfd232009-03-26 19:07:15 +0000821 if (joiner == DRD_(g_drd_running_tid))
822 {
823 thread_compute_conflict_set(&DRD_(g_conflict_set), joiner);
824 }
sewardjaf44c822007-11-25 14:01:38 +0000825}
826
bart324a23b2009-02-15 12:14:52 +0000827/**
828 * Call this function after thread 'tid' had to wait because of thread
829 * synchronization until the memory accesses in the segment with vector clock
830 * 'vc' finished.
bart26f73e12008-02-24 18:37:08 +0000831 */
bart62a784c2009-02-15 13:11:14 +0000832void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc)
sewardjaf44c822007-11-25 14:01:38 +0000833{
bartbedfd232009-03-26 19:07:15 +0000834 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
835 && tid != DRD_INVALID_THREADID);
836 tl_assert(DRD_(g_threadinfo)[tid].last);
837 tl_assert(vc);
838 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
839 thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
840 DRD_(thread_discard_ordered_segments)();
841 s_conflict_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000842}
843
bart324a23b2009-02-15 12:14:52 +0000844/**
845 * Call this function whenever a thread is no longer using the memory
846 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
847 * increase.
bart26f73e12008-02-24 18:37:08 +0000848 */
bart62a784c2009-02-15 13:11:14 +0000849void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000850{
bartbedfd232009-03-26 19:07:15 +0000851 DrdThreadId other_user;
852 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000853
bartbedfd232009-03-26 19:07:15 +0000854 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
855 other_user = DRD_INVALID_THREADID;
856 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
857 i++)
858 {
859 Segment* p;
860 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000861 {
bartbedfd232009-03-26 19:07:15 +0000862 if (other_user == DRD_INVALID_THREADID
863 && i != DRD_(g_drd_running_tid))
864 {
865 if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2)))
866 {
867 other_user = i;
868 }
869 continue;
870 }
871 DRD_(bm_clear)(p->bm, a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000872 }
bartbedfd232009-03-26 19:07:15 +0000873 }
sewardjaf44c822007-11-25 14:01:38 +0000874
bartbedfd232009-03-26 19:07:15 +0000875 /*
876 * If any other thread had accessed memory in [ a1, a2 [, update the
877 * conflict set.
878 */
879 if (other_user != DRD_INVALID_THREADID
880 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
881 {
882 thread_compute_conflict_set(&DRD_(g_conflict_set),
883 DRD_(thread_get_running_tid)());
884 }
sewardjaf44c822007-11-25 14:01:38 +0000885}
886
bart86a87df2009-03-04 19:26:47 +0000887/** Start recording memory access information. */
bart62a784c2009-02-15 13:11:14 +0000888void DRD_(thread_start_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000889{
bartbedfd232009-03-26 19:07:15 +0000890 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
891 && tid != DRD_INVALID_THREADID);
892 tl_assert(! DRD_(g_threadinfo)[tid].is_recording);
893 DRD_(g_threadinfo)[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000894}
895
bart86a87df2009-03-04 19:26:47 +0000896/** Stop recording memory access information. */
bart62a784c2009-02-15 13:11:14 +0000897void DRD_(thread_stop_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000898{
bartbedfd232009-03-26 19:07:15 +0000899 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
900 && tid != DRD_INVALID_THREADID);
901 tl_assert(DRD_(g_threadinfo)[tid].is_recording);
902 DRD_(g_threadinfo)[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000903}
904
bart86a87df2009-03-04 19:26:47 +0000905/**
906 * Print the segment information for all threads.
907 *
908 * This function is only used for debugging purposes.
909 */
bart62a784c2009-02-15 13:11:14 +0000910void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +0000911{
bartbedfd232009-03-26 19:07:15 +0000912 unsigned i;
913 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000914
bartbedfd232009-03-26 19:07:15 +0000915 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
916 i++)
917 {
918 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +0000919 {
bartbedfd232009-03-26 19:07:15 +0000920 VG_(printf)("**************\n"
921 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
922 "**************\n",
923 i,
924 DRD_(g_threadinfo)[i].vg_thread_exists,
925 DRD_(g_threadinfo)[i].vg_threadid,
926 DRD_(g_threadinfo)[i].posix_thread_exists,
927 DRD_(g_threadinfo)[i].pt_threadid,
928 DRD_(g_threadinfo)[i].detached_posix_thread);
929 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
930 {
931 DRD_(sg_print)(p);
932 }
sewardjaf44c822007-11-25 14:01:38 +0000933 }
bartbedfd232009-03-26 19:07:15 +0000934 }
sewardjaf44c822007-11-25 14:01:38 +0000935}
936
bart86a87df2009-03-04 19:26:47 +0000937/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000938static void show_call_stack(const DrdThreadId tid,
939 const Char* const msg,
940 ExeContext* const callstack)
941{
bartbedfd232009-03-26 19:07:15 +0000942 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +0000943
bartbedfd232009-03-26 19:07:15 +0000944 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000945
bartbedfd232009-03-26 19:07:15 +0000946 if (vg_tid != VG_INVALID_THREADID)
947 {
948 if (callstack)
949 {
950 VG_(pp_ExeContext)(callstack);
951 }
952 else
953 {
954 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
955 }
956 }
957 else
958 {
959 VG_(message)(Vg_UserMsg,
960 " (thread finished, call stack no longer available)");
961 }
sewardjaf44c822007-11-25 14:01:38 +0000962}
963
bart86a87df2009-03-04 19:26:47 +0000964/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000965static void
966thread_report_conflicting_segments_segment(const DrdThreadId tid,
967 const Addr addr,
968 const SizeT size,
969 const BmAccessTypeT access_type,
970 const Segment* const p)
971{
bartbedfd232009-03-26 19:07:15 +0000972 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000973
bartbedfd232009-03-26 19:07:15 +0000974 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
975 && tid != DRD_INVALID_THREADID);
976 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000977
bartbedfd232009-03-26 19:07:15 +0000978 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
979 i++)
980 {
981 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +0000982 {
bartbedfd232009-03-26 19:07:15 +0000983 Segment* q;
984 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
985 {
986 /*
987 * Since q iterates over the segments of thread i in order of
988 * decreasing vector clocks, if q->vc <= p->vc, then
989 * q->next->vc <= p->vc will also hold. Hence, break out of the
990 * loop once this condition is met.
991 */
992 if (DRD_(vc_lte)(&q->vc, &p->vc))
993 break;
994 if (! DRD_(vc_lte)(&p->vc, &q->vc))
995 {
996 if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size,
997 access_type))
998 {
999 tl_assert(q->stacktrace);
1000 show_call_stack(i, "Other segment start",
1001 q->stacktrace);
1002 show_call_stack(i, "Other segment end",
1003 q->next ? q->next->stacktrace : 0);
1004 }
1005 }
1006 }
sewardjaf44c822007-11-25 14:01:38 +00001007 }
bartbedfd232009-03-26 19:07:15 +00001008 }
sewardjaf44c822007-11-25 14:01:38 +00001009}
1010
bart86a87df2009-03-04 19:26:47 +00001011/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001012void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1013 const Addr addr,
1014 const SizeT size,
1015 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001016{
bartbedfd232009-03-26 19:07:15 +00001017 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001018
bartbedfd232009-03-26 19:07:15 +00001019 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1020 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001021
bartbedfd232009-03-26 19:07:15 +00001022 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1023 {
1024 if (DRD_(bm_has)(p->bm, addr, addr + size, access_type))
1025 {
1026 thread_report_conflicting_segments_segment(tid, addr, size,
1027 access_type, p);
1028 }
1029 }
sewardjaf44c822007-11-25 14:01:38 +00001030}
sewardjaf44c822007-11-25 14:01:38 +00001031
bart324a23b2009-02-15 12:14:52 +00001032/**
bart324a23b2009-02-15 12:14:52 +00001033 * Compute a bitmap that represents the union of all memory accesses of all
1034 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001035 */
bart86a87df2009-03-04 19:26:47 +00001036static void thread_compute_conflict_set(struct bitmap** conflict_set,
1037 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001038{
bartbedfd232009-03-26 19:07:15 +00001039 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001040
bartbedfd232009-03-26 19:07:15 +00001041 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1042 && tid != DRD_INVALID_THREADID);
1043 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001044
bartbedfd232009-03-26 19:07:15 +00001045 s_update_conflict_set_count++;
1046 s_conflict_set_bitmap_creation_count
1047 -= DRD_(bm_get_bitmap_creation_count)();
1048 s_conflict_set_bitmap2_creation_count
1049 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001050
bartbedfd232009-03-26 19:07:15 +00001051 if (*conflict_set)
1052 {
1053 DRD_(bm_delete)(*conflict_set);
1054 }
1055 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001056
bartbedfd232009-03-26 19:07:15 +00001057 if (s_trace_conflict_set)
1058 {
bart26f73e12008-02-24 18:37:08 +00001059 char msg[256];
1060
1061 VG_(snprintf)(msg, sizeof(msg),
bartbedfd232009-03-26 19:07:15 +00001062 "computing conflict set for thread %d/%d with vc ",
1063 DRD_(DrdThreadIdToVgThreadId)(tid), tid);
bart41b226c2009-02-14 16:55:19 +00001064 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1065 sizeof(msg) - VG_(strlen)(msg),
bartbedfd232009-03-26 19:07:15 +00001066 &DRD_(g_threadinfo)[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +00001067 VG_(message)(Vg_UserMsg, "%s", msg);
bartbedfd232009-03-26 19:07:15 +00001068 }
sewardjaf44c822007-11-25 14:01:38 +00001069
bartbedfd232009-03-26 19:07:15 +00001070 p = DRD_(g_threadinfo)[tid].last;
1071 {
1072 unsigned j;
1073
1074 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001075 {
bartbedfd232009-03-26 19:07:15 +00001076 char msg[256];
1077
1078 VG_(snprintf)(msg, sizeof(msg),
1079 "conflict set: thread [%d] at vc ",
1080 tid);
1081 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1082 sizeof(msg) - VG_(strlen)(msg),
1083 &p->vc);
1084 VG_(message)(Vg_UserMsg, "%s", msg);
bart26f73e12008-02-24 18:37:08 +00001085 }
sewardjaf44c822007-11-25 14:01:38 +00001086
bartbedfd232009-03-26 19:07:15 +00001087 for (j = 0;
1088 j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
1089 j++)
1090 {
1091 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1092 {
1093 const Segment* q;
1094 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1095 {
1096 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1097 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1098 {
1099 if (s_trace_conflict_set)
1100 {
1101 char msg[256];
1102 VG_(snprintf)(msg, sizeof(msg),
1103 "conflict set: [%d] merging segment ", j);
1104 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1105 sizeof(msg) - VG_(strlen)(msg),
1106 &q->vc);
1107 VG_(message)(Vg_UserMsg, "%s", msg);
1108 }
1109 DRD_(bm_merge2)(*conflict_set, q->bm);
1110 }
1111 else
1112 {
1113 if (s_trace_conflict_set)
1114 {
1115 char msg[256];
1116 VG_(snprintf)(msg, sizeof(msg),
1117 "conflict set: [%d] ignoring segment ", j);
1118 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1119 sizeof(msg) - VG_(strlen)(msg),
1120 &q->vc);
1121 VG_(message)(Vg_UserMsg, "%s", msg);
1122 }
1123 }
1124 }
1125 }
1126 }
1127 }
sewardjaf44c822007-11-25 14:01:38 +00001128
bartbedfd232009-03-26 19:07:15 +00001129 s_conflict_set_bitmap_creation_count
1130 += DRD_(bm_get_bitmap_creation_count)();
1131 s_conflict_set_bitmap2_creation_count
1132 += DRD_(bm_get_bitmap2_creation_count)();
1133
1134 if (0 && s_trace_conflict_set)
1135 {
1136 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
1137 DRD_(bm_print)(*conflict_set);
1138 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
1139 }
sewardjaf44c822007-11-25 14:01:38 +00001140}
1141
bart86a87df2009-03-04 19:26:47 +00001142/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001143ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001144{
bartbedfd232009-03-26 19:07:15 +00001145 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001146}
1147
bart86a87df2009-03-04 19:26:47 +00001148/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001149ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001150{
bartbedfd232009-03-26 19:07:15 +00001151 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001152}
1153
bart86a87df2009-03-04 19:26:47 +00001154/** Return how many times the conflict set has been updated. */
bart62a784c2009-02-15 13:11:14 +00001155ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001156{
bartbedfd232009-03-26 19:07:15 +00001157 tl_assert(dsnsc);
1158 tl_assert(dscvc);
1159 *dsnsc = s_conflict_set_new_segment_count;
1160 *dscvc = s_conflict_set_combine_vc_count;
1161 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001162}
1163
bart86a87df2009-03-04 19:26:47 +00001164/**
1165 * Return the number of first-level bitmaps that have been created during
1166 * conflict set updates.
1167 */
bart62a784c2009-02-15 13:11:14 +00001168ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001169{
bartbedfd232009-03-26 19:07:15 +00001170 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001171}
1172
bart86a87df2009-03-04 19:26:47 +00001173/**
1174 * Return the number of second-level bitmaps that have been created during
1175 * conflict set updates.
1176 */
bart62a784c2009-02-15 13:11:14 +00001177ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001178{
bartbedfd232009-03-26 19:07:15 +00001179 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001180}