blob: 7a802308ba2d5296bf7163912aa2851163836d30 [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;
bartd45d9952009-05-31 18:53:54 +0000159 DRD_(thread_set_name)(i, "");
160 DRD_(g_threadinfo)[i].is_recording_loads = True;
161 DRD_(g_threadinfo)[i].is_recording_stores = True;
bartbedfd232009-03-26 19:07:15 +0000162 DRD_(g_threadinfo)[i].synchr_nesting = 0;
163 tl_assert(DRD_(g_threadinfo)[i].first == 0);
164 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000165
bartbedfd232009-03-26 19:07:15 +0000166 tl_assert(DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000167
bartbedfd232009-03-26 19:07:15 +0000168 return i;
169 }
170 }
sewardjaf44c822007-11-25 14:01:38 +0000171
bartbedfd232009-03-26 19:07:15 +0000172 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000173
bartbedfd232009-03-26 19:07:15 +0000174 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000175}
176
bart86a87df2009-03-04 19:26:47 +0000177/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000178DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000179{
bartbedfd232009-03-26 19:07:15 +0000180 int i;
sewardjaf44c822007-11-25 14:01:38 +0000181
bartbedfd232009-03-26 19:07:15 +0000182 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000183
bartbedfd232009-03-26 19:07:15 +0000184 for (i = 1; i < DRD_N_THREADS; i++)
185 {
186 if (DRD_(g_threadinfo)[i].posix_thread_exists
187 && DRD_(g_threadinfo)[i].pt_threadid == tid)
188 {
189 return i;
190 }
191 }
192 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000193}
194
bart86a87df2009-03-04 19:26:47 +0000195/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000196ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000197{
bartbedfd232009-03-26 19:07:15 +0000198 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
199 && tid != DRD_INVALID_THREADID);
200 return (DRD_(g_threadinfo)[tid].vg_thread_exists
201 ? DRD_(g_threadinfo)[tid].vg_threadid
202 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000203}
204
bart23d3a4e2008-04-05 12:53:00 +0000205#if 0
bart324a23b2009-02-15 12:14:52 +0000206/**
207 * Sanity check of the doubly linked list of segments referenced by a
208 * ThreadInfo struct.
209 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000210 */
bart62a784c2009-02-15 13:11:14 +0000211static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000212{
bartbedfd232009-03-26 19:07:15 +0000213 Segment* p;
214 for (p = ti->first; p; p = p->next) {
215 if (p->next && p->next->prev != p)
216 return False;
217 if (p->next == 0 && p != ti->last)
218 return False;
219 }
220 for (p = ti->last; p; p = p->prev) {
221 if (p->prev && p->prev->next != p)
222 return False;
223 if (p->prev == 0 && p != ti->first)
224 return False;
225 }
226 return True;
sewardjaf44c822007-11-25 14:01:38 +0000227}
bart23d3a4e2008-04-05 12:53:00 +0000228#endif
sewardjaf44c822007-11-25 14:01:38 +0000229
bart439c55f2009-02-15 10:38:37 +0000230/**
231 * Create the first segment for a newly started thread.
232 *
233 * This function is called from the handler installed via
234 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
235 * from the context of the creator thread, before the new thread has been
236 * created.
bart86a87df2009-03-04 19:26:47 +0000237 *
238 * @param[in] creator DRD thread ID of the creator thread.
239 * @param[in] vg_created Valgrind thread ID of the created thread.
240 *
241 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000242 */
bart62a784c2009-02-15 13:11:14 +0000243DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
244 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000245{
bartbedfd232009-03-26 19:07:15 +0000246 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000247
bartbedfd232009-03-26 19:07:15 +0000248 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
249 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
250 tl_assert(0 <= (int)created && created < DRD_N_THREADS
251 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000252
bartbedfd232009-03-26 19:07:15 +0000253 tl_assert(DRD_(g_threadinfo)[created].first == 0);
254 tl_assert(DRD_(g_threadinfo)[created].last == 0);
255 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000256
bartbedfd232009-03-26 19:07:15 +0000257 return created;
sewardjaf44c822007-11-25 14:01:38 +0000258}
259
bart439c55f2009-02-15 10:38:37 +0000260/**
bart86a87df2009-03-04 19:26:47 +0000261 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
262 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000263 * on the newly created thread, e.g. from the handler installed via
264 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000265 *
266 * @param[in] vg_created Valgrind thread ID of the newly created thread.
267 *
268 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000269 */
bart62a784c2009-02-15 13:11:14 +0000270DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000271{
bartbedfd232009-03-26 19:07:15 +0000272 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000273
bartbedfd232009-03-26 19:07:15 +0000274 tl_assert(0 <= (int)created && created < DRD_N_THREADS
275 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000276
bartbedfd232009-03-26 19:07:15 +0000277 DRD_(g_threadinfo)[created].stack_max
278 = VG_(thread_get_stack_max)(vg_created);
279 DRD_(g_threadinfo)[created].stack_startup
280 = DRD_(g_threadinfo)[created].stack_max;
281 DRD_(g_threadinfo)[created].stack_min
282 = DRD_(g_threadinfo)[created].stack_max;
283 DRD_(g_threadinfo)[created].stack_min_min
284 = DRD_(g_threadinfo)[created].stack_max;
285 DRD_(g_threadinfo)[created].stack_size
286 = VG_(thread_get_stack_size)(vg_created);
287 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000288
bartbedfd232009-03-26 19:07:15 +0000289 return created;
bart439c55f2009-02-15 10:38:37 +0000290}
bart09dc13f2009-02-14 15:13:31 +0000291
bart324a23b2009-02-15 12:14:52 +0000292/**
293 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
294 * after thread drd_joiner joined thread drd_joinee.
295 */
bart09dc13f2009-02-14 15:13:31 +0000296void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
297{
bartbedfd232009-03-26 19:07:15 +0000298 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
299 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
bart7627be32009-06-06 12:26:05 +0000300
bartbedfd232009-03-26 19:07:15 +0000301 DRD_(thread_new_segment)(drd_joiner);
bart7627be32009-06-06 12:26:05 +0000302 DRD_(thread_combine_vc)(drd_joiner, drd_joinee);
303 DRD_(thread_new_segment)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000304
bartbedfd232009-03-26 19:07:15 +0000305 if (s_trace_fork_join)
306 {
307 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
308 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
309 const unsigned msg_size = 256;
310 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000311
bartbedfd232009-03-26 19:07:15 +0000312 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
313 tl_assert(msg);
314 VG_(snprintf)(msg, msg_size,
315 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
316 joiner, drd_joiner, joinee, drd_joinee);
317 if (joiner)
318 {
319 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
320 ", new vc: ");
321 DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
322 DRD_(thread_get_vc)(drd_joiner));
323 }
324 VG_(message)(Vg_DebugMsg, "%s", msg);
325 VG_(free)(msg);
326 }
bart09dc13f2009-02-14 15:13:31 +0000327
bartbedfd232009-03-26 19:07:15 +0000328 if (! DRD_(get_check_stack_accesses)())
329 {
330 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
331 - DRD_(thread_get_stack_size)(drd_joinee),
332 DRD_(thread_get_stack_max)(drd_joinee));
333 }
334 DRD_(clientobj_delete_thread)(drd_joinee);
335 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000336}
337
bart324a23b2009-02-15 12:14:52 +0000338/**
339 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
340 * and accesses this data structure from multiple threads without locking.
341 * Any conflicting accesses in the range stack_startup..stack_max will be
342 * ignored.
343 */
bart62a784c2009-02-15 13:11:14 +0000344void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
345 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000346{
bartbedfd232009-03-26 19:07:15 +0000347 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
348 && tid != DRD_INVALID_THREADID);
349 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
350 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
351 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000352}
353
bart86a87df2009-03-04 19:26:47 +0000354/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000355Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000356{
bartbedfd232009-03-26 19:07:15 +0000357 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
358 && tid != DRD_INVALID_THREADID);
359 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000360}
361
bart86a87df2009-03-04 19:26:47 +0000362/**
363 * Return the lowest value that was ever assigned to the stack pointer
364 * for the specified thread.
365 */
bart62a784c2009-02-15 13:11:14 +0000366Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000367{
bartbedfd232009-03-26 19:07:15 +0000368 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
369 && tid != DRD_INVALID_THREADID);
370 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000371}
372
bart86a87df2009-03-04 19:26:47 +0000373/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000374Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000375{
bartbedfd232009-03-26 19:07:15 +0000376 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
377 && tid != DRD_INVALID_THREADID);
378 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000379}
380
bart86a87df2009-03-04 19:26:47 +0000381/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000382SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000383{
bartbedfd232009-03-26 19:07:15 +0000384 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
385 && tid != DRD_INVALID_THREADID);
386 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000387}
388
bart09dc13f2009-02-14 15:13:31 +0000389/**
390 * Clean up thread-specific data structures. Call this just after
391 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000392 */
bart62a784c2009-02-15 13:11:14 +0000393void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000394{
bartbedfd232009-03-26 19:07:15 +0000395 Segment* sg;
396 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000397
bartbedfd232009-03-26 19:07:15 +0000398 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000399
bartbedfd232009-03-26 19:07:15 +0000400 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
401 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
402 {
403 sg_prev = sg->prev;
404 sg->prev = 0;
405 sg->next = 0;
406 DRD_(sg_put)(sg);
407 }
408 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
409 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
410 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
411 DRD_(g_threadinfo)[tid].first = 0;
412 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000413
bartbedfd232009-03-26 19:07:15 +0000414 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000415}
416
bart324a23b2009-02-15 12:14:52 +0000417/**
418 * Called after a thread performed its last memory access and before
419 * thread_delete() is called. Note: thread_delete() is only called for
420 * joinable threads, not for detached threads.
421 */
bart62a784c2009-02-15 13:11:14 +0000422void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000423{
bartbedfd232009-03-26 19:07:15 +0000424 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
425 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000426
bartbedfd232009-03-26 19:07:15 +0000427 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000428
bartbedfd232009-03-26 19:07:15 +0000429 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
430 {
431 /*
432 * Once a detached thread has finished, its stack is deallocated and
433 * should no longer be taken into account when computing the conflict set.
434 */
435 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000436
bartbedfd232009-03-26 19:07:15 +0000437 /*
438 * For a detached thread, calling pthread_exit() invalidates the
439 * POSIX thread ID associated with the detached thread. For joinable
440 * POSIX threads however, the POSIX thread ID remains live after the
441 * pthread_exit() call until pthread_join() is called.
442 */
443 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
444 }
sewardjaf44c822007-11-25 14:01:38 +0000445}
446
bart9b2974a2008-09-27 12:35:31 +0000447/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000448void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000449{
bartbedfd232009-03-26 19:07:15 +0000450 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
451 && tid != DRD_INVALID_THREADID);
452 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000453
bartbedfd232009-03-26 19:07:15 +0000454 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000455}
456
barte7dff242009-04-23 17:12:39 +0000457/**
458 * Store the POSIX thread ID for the specified thread.
459 *
460 * @note This function can be called two times for the same thread -- see also
461 * the comment block preceding the pthread_create() wrapper in
462 * drd_pthread_intercepts.c.
463 */
bart62a784c2009-02-15 13:11:14 +0000464void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000465{
bartbedfd232009-03-26 19:07:15 +0000466 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
467 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000468 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
469 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000470 tl_assert(ptid != INVALID_POSIX_THREADID);
471 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
472 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000473}
474
bart86a87df2009-03-04 19:26:47 +0000475/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000476Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000477{
bartbedfd232009-03-26 19:07:15 +0000478 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
479 && tid != DRD_INVALID_THREADID);
480 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000481}
482
bart86a87df2009-03-04 19:26:47 +0000483/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000484void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000485{
bartbedfd232009-03-26 19:07:15 +0000486 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
487 && tid != DRD_INVALID_THREADID);
488 tl_assert(!! joinable == joinable);
489 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000490#if 0
bartbedfd232009-03-26 19:07:15 +0000491 VG_(message)(Vg_DebugMsg,
492 "thread_set_joinable(%d/%d, %s)",
493 tid,
494 DRD_(g_threadinfo)[tid].vg_threadid,
495 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000496#endif
bartbedfd232009-03-26 19:07:15 +0000497 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000498}
499
bartd45d9952009-05-31 18:53:54 +0000500/** Obtain the thread number and the user-assigned thread name. */
501const char* DRD_(thread_get_name)(const DrdThreadId tid)
502{
503 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
504 && tid != DRD_INVALID_THREADID);
505
506 return DRD_(g_threadinfo)[tid].name;
507}
508
509/** Set the name of the specified thread. */
510void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
511{
512 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
513 && tid != DRD_INVALID_THREADID);
514
515 if (name == NULL || name[0] == 0)
516 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
517 sizeof(DRD_(g_threadinfo)[tid].name),
518 "Thread %d",
519 tid);
520 else
521 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
522 sizeof(DRD_(g_threadinfo)[tid].name),
523 "Thread %d (%s)",
524 tid, name);
525 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
526}
527
bart86a87df2009-03-04 19:26:47 +0000528/**
529 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
530 * conflict set.
531 */
bart62a784c2009-02-15 13:11:14 +0000532void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000533{
bartbedfd232009-03-26 19:07:15 +0000534 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000535
bartbedfd232009-03-26 19:07:15 +0000536 if (vg_tid != s_vg_running_tid)
537 {
538 DRD_(thread_set_running_tid)(vg_tid,
539 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
540 }
sewardj8b09d4f2007-12-04 21:27:18 +0000541
bartbedfd232009-03-26 19:07:15 +0000542 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
543 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000544}
545
bart86a87df2009-03-04 19:26:47 +0000546/**
547 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
548 * conflict set.
549 */
bart62a784c2009-02-15 13:11:14 +0000550void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
551 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000552{
bartbedfd232009-03-26 19:07:15 +0000553 tl_assert(vg_tid != VG_INVALID_THREADID);
554 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000555
bartbedfd232009-03-26 19:07:15 +0000556 if (vg_tid != s_vg_running_tid)
557 {
558 if (s_trace_context_switches
559 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
560 {
561 VG_(message)(Vg_DebugMsg,
562 "Context switch from thread %d/%d to thread %d/%d;"
563 " segments: %llu",
564 s_vg_running_tid, DRD_(g_drd_running_tid),
565 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
566 DRD_(sg_get_segments_alive_count)());
567 }
568 s_vg_running_tid = vg_tid;
569 DRD_(g_drd_running_tid) = drd_tid;
570 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
571 s_context_switch_count++;
572 }
sewardj8b09d4f2007-12-04 21:27:18 +0000573
bartbedfd232009-03-26 19:07:15 +0000574 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
575 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000576}
577
bart86a87df2009-03-04 19:26:47 +0000578/**
579 * Increase the synchronization nesting counter. Must be called before the
580 * client calls a synchronization function.
581 */
bart62a784c2009-02-15 13:11:14 +0000582int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000583{
bartbedfd232009-03-26 19:07:15 +0000584 tl_assert(DRD_(IsValidDrdThreadId)(tid));
585 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000586}
587
bart86a87df2009-03-04 19:26:47 +0000588/**
589 * Decrease the synchronization nesting counter. Must be called after the
590 * client left a synchronization function.
591 */
bart62a784c2009-02-15 13:11:14 +0000592int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000593{
bartbedfd232009-03-26 19:07:15 +0000594 tl_assert(DRD_(IsValidDrdThreadId)(tid));
595 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
596 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000597}
598
bart86a87df2009-03-04 19:26:47 +0000599/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000600int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000601{
bartbedfd232009-03-26 19:07:15 +0000602 tl_assert(DRD_(IsValidDrdThreadId)(tid));
603 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000604}
605
bart1a473c72008-03-13 19:03:38 +0000606/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000607static
bart86a87df2009-03-04 19:26:47 +0000608void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000609{
bartbedfd232009-03-26 19:07:15 +0000610 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
611 && tid != DRD_INVALID_THREADID);
612 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
613 sg->prev = DRD_(g_threadinfo)[tid].last;
614 sg->next = 0;
615 if (DRD_(g_threadinfo)[tid].last)
616 DRD_(g_threadinfo)[tid].last->next = sg;
617 DRD_(g_threadinfo)[tid].last = sg;
618 if (DRD_(g_threadinfo)[tid].first == 0)
619 DRD_(g_threadinfo)[tid].first = sg;
620 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000621}
622
bart324a23b2009-02-15 12:14:52 +0000623/**
624 * Remove a segment from the segment list of thread threadid, and free the
625 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000626 */
bart62a784c2009-02-15 13:11:14 +0000627static
bart86a87df2009-03-04 19:26:47 +0000628void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000629{
bartbedfd232009-03-26 19:07:15 +0000630 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
631 && tid != DRD_INVALID_THREADID);
632 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart26f73e12008-02-24 18:37:08 +0000633
bartbedfd232009-03-26 19:07:15 +0000634 if (sg->prev)
635 sg->prev->next = sg->next;
636 if (sg->next)
637 sg->next->prev = sg->prev;
638 if (sg == DRD_(g_threadinfo)[tid].first)
639 DRD_(g_threadinfo)[tid].first = sg->next;
640 if (sg == DRD_(g_threadinfo)[tid].last)
641 DRD_(g_threadinfo)[tid].last = sg->prev;
642 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000643
bartbedfd232009-03-26 19:07:15 +0000644 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000645}
646
bart86a87df2009-03-04 19:26:47 +0000647/**
648 * Returns a pointer to the vector clock of the most recent segment associated
649 * with thread 'tid'.
650 */
bart62a784c2009-02-15 13:11:14 +0000651VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000652{
bartbedfd232009-03-26 19:07:15 +0000653 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
654 && tid != DRD_INVALID_THREADID);
655 tl_assert(DRD_(g_threadinfo)[tid].last);
656 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000657}
658
bart324a23b2009-02-15 12:14:52 +0000659/**
660 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000661 */
bart62a784c2009-02-15 13:11:14 +0000662void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000663{
bartbedfd232009-03-26 19:07:15 +0000664 tl_assert(sg);
665 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
666 && tid != DRD_INVALID_THREADID);
667 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000668
bartbedfd232009-03-26 19:07:15 +0000669 DRD_(sg_put)(*sg);
670 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000671}
672
sewardjaf44c822007-11-25 14:01:38 +0000673/**
674 * Compute the minimum of all latest vector clocks of all threads
675 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000676 *
sewardjaf44c822007-11-25 14:01:38 +0000677 * @param vc pointer to a vectorclock, holds result upon return.
678 */
bart62a784c2009-02-15 13:11:14 +0000679static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000680{
bartbedfd232009-03-26 19:07:15 +0000681 unsigned i;
682 Bool first;
683 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000684
bartbedfd232009-03-26 19:07:15 +0000685 first = True;
686 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
687 i++)
688 {
689 latest_sg = DRD_(g_threadinfo)[i].last;
690 if (latest_sg)
691 {
692 if (first)
693 DRD_(vc_assign)(vc, &latest_sg->vc);
694 else
695 DRD_(vc_min)(vc, &latest_sg->vc);
696 first = False;
697 }
698 }
sewardjaf44c822007-11-25 14:01:38 +0000699}
700
bart86a87df2009-03-04 19:26:47 +0000701/**
702 * Compute the maximum of all latest vector clocks of all threads.
703 *
704 * @param vc pointer to a vectorclock, holds result upon return.
705 */
bart62a784c2009-02-15 13:11:14 +0000706static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000707{
bartbedfd232009-03-26 19:07:15 +0000708 unsigned i;
709 Bool first;
710 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000711
bartbedfd232009-03-26 19:07:15 +0000712 first = True;
713 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
714 i++)
715 {
716 latest_sg = DRD_(g_threadinfo)[i].last;
717 if (latest_sg)
718 {
719 if (first)
720 DRD_(vc_assign)(vc, &latest_sg->vc);
721 else
722 DRD_(vc_combine)(vc, &latest_sg->vc);
723 first = False;
724 }
725 }
sewardjaf44c822007-11-25 14:01:38 +0000726}
727
728/**
bart5bd9f2d2008-03-03 20:31:58 +0000729 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000730 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000731 * data race.
732 */
bart62a784c2009-02-15 13:11:14 +0000733static void DRD_(thread_discard_ordered_segments)(void)
sewardjaf44c822007-11-25 14:01:38 +0000734{
bartbedfd232009-03-26 19:07:15 +0000735 unsigned i;
736 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000737
bartbedfd232009-03-26 19:07:15 +0000738 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000739
bartbedfd232009-03-26 19:07:15 +0000740 DRD_(vc_init)(&thread_vc_min, 0, 0);
741 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
742 if (DRD_(sg_get_trace)())
743 {
744 char msg[256];
745 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000746
bartbedfd232009-03-26 19:07:15 +0000747 DRD_(vc_init)(&thread_vc_max, 0, 0);
748 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
749 VG_(snprintf)(msg, sizeof(msg),
750 "Discarding ordered segments -- min vc is ");
751 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
752 &thread_vc_min);
753 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
754 ", max vc is ");
755 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
756 &thread_vc_max);
757 VG_(message)(Vg_UserMsg, "%s", msg);
758 DRD_(vc_cleanup)(&thread_vc_max);
759 }
sewardjaf44c822007-11-25 14:01:38 +0000760
bartbedfd232009-03-26 19:07:15 +0000761 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
762 i++)
763 {
764 Segment* sg;
765 Segment* sg_next;
766 for (sg = DRD_(g_threadinfo)[i].first;
767 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
768 sg = sg_next)
769 {
770 thread_discard_segment(i, sg);
771 }
772 }
773 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000774}
775
bart324a23b2009-02-15 12:14:52 +0000776/**
777 * Merge all segments that may be merged without triggering false positives
778 * or discarding real data races. For the theoretical background of segment
779 * merging, see also the following paper:
780 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
781 * Bounding the number of segment histories during data race detection.
782 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
783 * September 2002.
barta9c37392008-03-22 09:38:48 +0000784 */
785static void thread_merge_segments(void)
786{
bartbedfd232009-03-26 19:07:15 +0000787 unsigned i;
barta9c37392008-03-22 09:38:48 +0000788
bartbedfd232009-03-26 19:07:15 +0000789 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
790 i++)
791 {
792 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000793
bartbedfd232009-03-26 19:07:15 +0000794 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000795
bartbedfd232009-03-26 19:07:15 +0000796 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000797 {
bartbedfd232009-03-26 19:07:15 +0000798 if (DRD_(sg_get_refcnt)(sg) == 1
799 && sg->next
800 && DRD_(sg_get_refcnt)(sg->next) == 1
801 && sg->next->next)
802 {
803 /* Merge sg and sg->next into sg. */
804 DRD_(sg_merge)(sg, sg->next);
805 thread_discard_segment(i, sg->next);
806 }
barta9c37392008-03-22 09:38:48 +0000807 }
barta9c37392008-03-22 09:38:48 +0000808
bartbedfd232009-03-26 19:07:15 +0000809 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
810 }
barta9c37392008-03-22 09:38:48 +0000811}
812
bart324a23b2009-02-15 12:14:52 +0000813/**
bart324a23b2009-02-15 12:14:52 +0000814 * Create a new segment for the specified thread, and discard any segments
815 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000816 */
bart62a784c2009-02-15 13:11:14 +0000817void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000818{
bartbedfd232009-03-26 19:07:15 +0000819 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000820
bartbedfd232009-03-26 19:07:15 +0000821 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
822 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000823
bartbedfd232009-03-26 19:07:15 +0000824 new_sg = DRD_(sg_new)(tid, tid);
825 thread_append_segment(tid, new_sg);
bartd66e3a82008-04-06 15:02:17 +0000826
bartbedfd232009-03-26 19:07:15 +0000827 thread_compute_conflict_set(&DRD_(g_conflict_set), DRD_(g_drd_running_tid));
828 s_conflict_set_new_segment_count++;
sewardjaf44c822007-11-25 14:01:38 +0000829
bartbedfd232009-03-26 19:07:15 +0000830 DRD_(thread_discard_ordered_segments)();
bart26f73e12008-02-24 18:37:08 +0000831
bartbedfd232009-03-26 19:07:15 +0000832 if (s_segment_merging)
833 {
834 thread_merge_segments();
835 }
sewardjaf44c822007-11-25 14:01:38 +0000836}
837
bart26f73e12008-02-24 18:37:08 +0000838/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart62a784c2009-02-15 13:11:14 +0000839void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000840{
bartbedfd232009-03-26 19:07:15 +0000841 tl_assert(joiner != joinee);
842 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
843 && joiner != DRD_INVALID_THREADID);
844 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
845 && joinee != DRD_INVALID_THREADID);
846 tl_assert(DRD_(g_threadinfo)[joiner].last);
847 tl_assert(DRD_(g_threadinfo)[joinee].last);
848 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
849 &DRD_(g_threadinfo)[joinee].last->vc);
850 DRD_(thread_discard_ordered_segments)();
sewardjaf44c822007-11-25 14:01:38 +0000851
bartbedfd232009-03-26 19:07:15 +0000852 if (joiner == DRD_(g_drd_running_tid))
853 {
854 thread_compute_conflict_set(&DRD_(g_conflict_set), joiner);
855 }
sewardjaf44c822007-11-25 14:01:38 +0000856}
857
bart324a23b2009-02-15 12:14:52 +0000858/**
859 * Call this function after thread 'tid' had to wait because of thread
860 * synchronization until the memory accesses in the segment with vector clock
861 * 'vc' finished.
bart26f73e12008-02-24 18:37:08 +0000862 */
bart62a784c2009-02-15 13:11:14 +0000863void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc)
sewardjaf44c822007-11-25 14:01:38 +0000864{
bartbedfd232009-03-26 19:07:15 +0000865 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
866 && tid != DRD_INVALID_THREADID);
867 tl_assert(DRD_(g_threadinfo)[tid].last);
868 tl_assert(vc);
869 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
870 thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
871 DRD_(thread_discard_ordered_segments)();
872 s_conflict_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000873}
874
bart324a23b2009-02-15 12:14:52 +0000875/**
876 * Call this function whenever a thread is no longer using the memory
877 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
878 * increase.
bart26f73e12008-02-24 18:37:08 +0000879 */
bart62a784c2009-02-15 13:11:14 +0000880void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000881{
bartbedfd232009-03-26 19:07:15 +0000882 DrdThreadId other_user;
883 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000884
bartbedfd232009-03-26 19:07:15 +0000885 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
886 other_user = DRD_INVALID_THREADID;
887 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
888 i++)
889 {
890 Segment* p;
891 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000892 {
bartbedfd232009-03-26 19:07:15 +0000893 if (other_user == DRD_INVALID_THREADID
894 && i != DRD_(g_drd_running_tid))
895 {
896 if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2)))
897 {
898 other_user = i;
899 }
900 continue;
901 }
902 DRD_(bm_clear)(p->bm, a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000903 }
bartbedfd232009-03-26 19:07:15 +0000904 }
sewardjaf44c822007-11-25 14:01:38 +0000905
bartbedfd232009-03-26 19:07:15 +0000906 /*
907 * If any other thread had accessed memory in [ a1, a2 [, update the
908 * conflict set.
909 */
910 if (other_user != DRD_INVALID_THREADID
911 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
912 {
913 thread_compute_conflict_set(&DRD_(g_conflict_set),
914 DRD_(thread_get_running_tid)());
915 }
sewardjaf44c822007-11-25 14:01:38 +0000916}
917
bartd45d9952009-05-31 18:53:54 +0000918/** Specify whether memory loads should be recorded. */
919void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +0000920{
bartbedfd232009-03-26 19:07:15 +0000921 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
922 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +0000923 tl_assert(enabled == !! enabled);
924
925 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +0000926}
927
bartd45d9952009-05-31 18:53:54 +0000928/** Specify whether memory stores should be recorded. */
929void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +0000930{
bartbedfd232009-03-26 19:07:15 +0000931 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
932 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +0000933 tl_assert(enabled == !! enabled);
934
935 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +0000936}
937
bart86a87df2009-03-04 19:26:47 +0000938/**
939 * Print the segment information for all threads.
940 *
941 * This function is only used for debugging purposes.
942 */
bart62a784c2009-02-15 13:11:14 +0000943void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +0000944{
bartbedfd232009-03-26 19:07:15 +0000945 unsigned i;
946 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000947
bartbedfd232009-03-26 19:07:15 +0000948 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
949 i++)
950 {
951 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +0000952 {
bartbedfd232009-03-26 19:07:15 +0000953 VG_(printf)("**************\n"
954 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
955 "**************\n",
956 i,
957 DRD_(g_threadinfo)[i].vg_thread_exists,
958 DRD_(g_threadinfo)[i].vg_threadid,
959 DRD_(g_threadinfo)[i].posix_thread_exists,
960 DRD_(g_threadinfo)[i].pt_threadid,
961 DRD_(g_threadinfo)[i].detached_posix_thread);
962 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
963 {
964 DRD_(sg_print)(p);
965 }
sewardjaf44c822007-11-25 14:01:38 +0000966 }
bartbedfd232009-03-26 19:07:15 +0000967 }
sewardjaf44c822007-11-25 14:01:38 +0000968}
969
bart86a87df2009-03-04 19:26:47 +0000970/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000971static void show_call_stack(const DrdThreadId tid,
972 const Char* const msg,
973 ExeContext* const callstack)
974{
bartbedfd232009-03-26 19:07:15 +0000975 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +0000976
bartbedfd232009-03-26 19:07:15 +0000977 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000978
bartbedfd232009-03-26 19:07:15 +0000979 if (vg_tid != VG_INVALID_THREADID)
980 {
981 if (callstack)
982 {
983 VG_(pp_ExeContext)(callstack);
984 }
985 else
986 {
987 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
988 }
989 }
990 else
991 {
992 VG_(message)(Vg_UserMsg,
993 " (thread finished, call stack no longer available)");
994 }
sewardjaf44c822007-11-25 14:01:38 +0000995}
996
bart86a87df2009-03-04 19:26:47 +0000997/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000998static void
999thread_report_conflicting_segments_segment(const DrdThreadId tid,
1000 const Addr addr,
1001 const SizeT size,
1002 const BmAccessTypeT access_type,
1003 const Segment* const p)
1004{
bartbedfd232009-03-26 19:07:15 +00001005 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001006
bartbedfd232009-03-26 19:07:15 +00001007 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1008 && tid != DRD_INVALID_THREADID);
1009 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001010
bartbedfd232009-03-26 19:07:15 +00001011 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
1012 i++)
1013 {
1014 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001015 {
bartbedfd232009-03-26 19:07:15 +00001016 Segment* q;
1017 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1018 {
1019 /*
1020 * Since q iterates over the segments of thread i in order of
1021 * decreasing vector clocks, if q->vc <= p->vc, then
1022 * q->next->vc <= p->vc will also hold. Hence, break out of the
1023 * loop once this condition is met.
1024 */
1025 if (DRD_(vc_lte)(&q->vc, &p->vc))
1026 break;
1027 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1028 {
1029 if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size,
1030 access_type))
1031 {
1032 tl_assert(q->stacktrace);
1033 show_call_stack(i, "Other segment start",
1034 q->stacktrace);
1035 show_call_stack(i, "Other segment end",
1036 q->next ? q->next->stacktrace : 0);
1037 }
1038 }
1039 }
sewardjaf44c822007-11-25 14:01:38 +00001040 }
bartbedfd232009-03-26 19:07:15 +00001041 }
sewardjaf44c822007-11-25 14:01:38 +00001042}
1043
bart86a87df2009-03-04 19:26:47 +00001044/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001045void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1046 const Addr addr,
1047 const SizeT size,
1048 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001049{
bartbedfd232009-03-26 19:07:15 +00001050 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001051
bartbedfd232009-03-26 19:07:15 +00001052 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1053 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001054
bartbedfd232009-03-26 19:07:15 +00001055 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1056 {
1057 if (DRD_(bm_has)(p->bm, addr, addr + size, access_type))
1058 {
1059 thread_report_conflicting_segments_segment(tid, addr, size,
1060 access_type, p);
1061 }
1062 }
sewardjaf44c822007-11-25 14:01:38 +00001063}
sewardjaf44c822007-11-25 14:01:38 +00001064
bart324a23b2009-02-15 12:14:52 +00001065/**
bart324a23b2009-02-15 12:14:52 +00001066 * Compute a bitmap that represents the union of all memory accesses of all
1067 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001068 */
bart86a87df2009-03-04 19:26:47 +00001069static void thread_compute_conflict_set(struct bitmap** conflict_set,
1070 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001071{
bartbedfd232009-03-26 19:07:15 +00001072 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001073
bartbedfd232009-03-26 19:07:15 +00001074 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1075 && tid != DRD_INVALID_THREADID);
1076 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001077
bartbedfd232009-03-26 19:07:15 +00001078 s_update_conflict_set_count++;
1079 s_conflict_set_bitmap_creation_count
1080 -= DRD_(bm_get_bitmap_creation_count)();
1081 s_conflict_set_bitmap2_creation_count
1082 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001083
bartbedfd232009-03-26 19:07:15 +00001084 if (*conflict_set)
1085 {
1086 DRD_(bm_delete)(*conflict_set);
1087 }
1088 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001089
bartbedfd232009-03-26 19:07:15 +00001090 if (s_trace_conflict_set)
1091 {
bart26f73e12008-02-24 18:37:08 +00001092 char msg[256];
1093
1094 VG_(snprintf)(msg, sizeof(msg),
bartbedfd232009-03-26 19:07:15 +00001095 "computing conflict set for thread %d/%d with vc ",
1096 DRD_(DrdThreadIdToVgThreadId)(tid), tid);
bart41b226c2009-02-14 16:55:19 +00001097 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1098 sizeof(msg) - VG_(strlen)(msg),
bartbedfd232009-03-26 19:07:15 +00001099 &DRD_(g_threadinfo)[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +00001100 VG_(message)(Vg_UserMsg, "%s", msg);
bartbedfd232009-03-26 19:07:15 +00001101 }
sewardjaf44c822007-11-25 14:01:38 +00001102
bartbedfd232009-03-26 19:07:15 +00001103 p = DRD_(g_threadinfo)[tid].last;
1104 {
1105 unsigned j;
1106
1107 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001108 {
bartbedfd232009-03-26 19:07:15 +00001109 char msg[256];
1110
1111 VG_(snprintf)(msg, sizeof(msg),
1112 "conflict set: thread [%d] at vc ",
1113 tid);
1114 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1115 sizeof(msg) - VG_(strlen)(msg),
1116 &p->vc);
1117 VG_(message)(Vg_UserMsg, "%s", msg);
bart26f73e12008-02-24 18:37:08 +00001118 }
sewardjaf44c822007-11-25 14:01:38 +00001119
bartbedfd232009-03-26 19:07:15 +00001120 for (j = 0;
1121 j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
1122 j++)
1123 {
1124 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1125 {
1126 const Segment* q;
1127 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1128 {
1129 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1130 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1131 {
1132 if (s_trace_conflict_set)
1133 {
1134 char msg[256];
1135 VG_(snprintf)(msg, sizeof(msg),
1136 "conflict set: [%d] merging segment ", j);
1137 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1138 sizeof(msg) - VG_(strlen)(msg),
1139 &q->vc);
1140 VG_(message)(Vg_UserMsg, "%s", msg);
1141 }
1142 DRD_(bm_merge2)(*conflict_set, q->bm);
1143 }
1144 else
1145 {
1146 if (s_trace_conflict_set)
1147 {
1148 char msg[256];
1149 VG_(snprintf)(msg, sizeof(msg),
1150 "conflict set: [%d] ignoring segment ", j);
1151 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1152 sizeof(msg) - VG_(strlen)(msg),
1153 &q->vc);
1154 VG_(message)(Vg_UserMsg, "%s", msg);
1155 }
1156 }
1157 }
1158 }
1159 }
1160 }
sewardjaf44c822007-11-25 14:01:38 +00001161
bartbedfd232009-03-26 19:07:15 +00001162 s_conflict_set_bitmap_creation_count
1163 += DRD_(bm_get_bitmap_creation_count)();
1164 s_conflict_set_bitmap2_creation_count
1165 += DRD_(bm_get_bitmap2_creation_count)();
1166
1167 if (0 && s_trace_conflict_set)
1168 {
1169 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
1170 DRD_(bm_print)(*conflict_set);
1171 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
1172 }
sewardjaf44c822007-11-25 14:01:38 +00001173}
1174
bart86a87df2009-03-04 19:26:47 +00001175/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001176ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001177{
bartbedfd232009-03-26 19:07:15 +00001178 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001179}
1180
bart86a87df2009-03-04 19:26:47 +00001181/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001182ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001183{
bartbedfd232009-03-26 19:07:15 +00001184 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001185}
1186
bart86a87df2009-03-04 19:26:47 +00001187/** Return how many times the conflict set has been updated. */
bart62a784c2009-02-15 13:11:14 +00001188ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001189{
bartbedfd232009-03-26 19:07:15 +00001190 tl_assert(dsnsc);
1191 tl_assert(dscvc);
1192 *dsnsc = s_conflict_set_new_segment_count;
1193 *dscvc = s_conflict_set_combine_vc_count;
1194 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001195}
1196
bart86a87df2009-03-04 19:26:47 +00001197/**
1198 * Return the number of first-level bitmaps that have been created during
1199 * conflict set updates.
1200 */
bart62a784c2009-02-15 13:11:14 +00001201ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001202{
bartbedfd232009-03-26 19:07:15 +00001203 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001204}
1205
bart86a87df2009-03-04 19:26:47 +00001206/**
1207 * Return the number of second-level bitmaps that have been created during
1208 * conflict set updates.
1209 */
bart62a784c2009-02-15 13:11:14 +00001210ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001211{
bartbedfd232009-03-26 19:07:15 +00001212 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001213}