blob: c8740e3cc0450c3b622afa9f81a3e6e3d304e14b [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));
300 DRD_(thread_new_segment)(drd_joinee);
301 DRD_(thread_combine_vc)(drd_joiner, drd_joinee);
302 DRD_(thread_new_segment)(drd_joiner);
bart09dc13f2009-02-14 15:13:31 +0000303
bartbedfd232009-03-26 19:07:15 +0000304 if (s_trace_fork_join)
305 {
306 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
307 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
308 const unsigned msg_size = 256;
309 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000310
bartbedfd232009-03-26 19:07:15 +0000311 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
312 tl_assert(msg);
313 VG_(snprintf)(msg, msg_size,
314 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
315 joiner, drd_joiner, joinee, drd_joinee);
316 if (joiner)
317 {
318 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
319 ", new vc: ");
320 DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
321 DRD_(thread_get_vc)(drd_joiner));
322 }
323 VG_(message)(Vg_DebugMsg, "%s", msg);
324 VG_(free)(msg);
325 }
bart09dc13f2009-02-14 15:13:31 +0000326
bartbedfd232009-03-26 19:07:15 +0000327 if (! DRD_(get_check_stack_accesses)())
328 {
329 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
330 - DRD_(thread_get_stack_size)(drd_joinee),
331 DRD_(thread_get_stack_max)(drd_joinee));
332 }
333 DRD_(clientobj_delete_thread)(drd_joinee);
334 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000335}
336
bart324a23b2009-02-15 12:14:52 +0000337/**
338 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
339 * and accesses this data structure from multiple threads without locking.
340 * Any conflicting accesses in the range stack_startup..stack_max will be
341 * ignored.
342 */
bart62a784c2009-02-15 13:11:14 +0000343void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
344 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000345{
bartbedfd232009-03-26 19:07:15 +0000346 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
347 && tid != DRD_INVALID_THREADID);
348 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
349 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
350 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000351}
352
bart86a87df2009-03-04 19:26:47 +0000353/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000354Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000355{
bartbedfd232009-03-26 19:07:15 +0000356 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
357 && tid != DRD_INVALID_THREADID);
358 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000359}
360
bart86a87df2009-03-04 19:26:47 +0000361/**
362 * Return the lowest value that was ever assigned to the stack pointer
363 * for the specified thread.
364 */
bart62a784c2009-02-15 13:11:14 +0000365Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000366{
bartbedfd232009-03-26 19:07:15 +0000367 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
368 && tid != DRD_INVALID_THREADID);
369 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000370}
371
bart86a87df2009-03-04 19:26:47 +0000372/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000373Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000374{
bartbedfd232009-03-26 19:07:15 +0000375 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
376 && tid != DRD_INVALID_THREADID);
377 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000378}
379
bart86a87df2009-03-04 19:26:47 +0000380/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000381SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000382{
bartbedfd232009-03-26 19:07:15 +0000383 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
384 && tid != DRD_INVALID_THREADID);
385 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000386}
387
bart09dc13f2009-02-14 15:13:31 +0000388/**
389 * Clean up thread-specific data structures. Call this just after
390 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000391 */
bart62a784c2009-02-15 13:11:14 +0000392void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000393{
bartbedfd232009-03-26 19:07:15 +0000394 Segment* sg;
395 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000396
bartbedfd232009-03-26 19:07:15 +0000397 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000398
bartbedfd232009-03-26 19:07:15 +0000399 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
400 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
401 {
402 sg_prev = sg->prev;
403 sg->prev = 0;
404 sg->next = 0;
405 DRD_(sg_put)(sg);
406 }
407 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
408 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
409 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
410 DRD_(g_threadinfo)[tid].first = 0;
411 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000412
bartbedfd232009-03-26 19:07:15 +0000413 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000414}
415
bart324a23b2009-02-15 12:14:52 +0000416/**
417 * Called after a thread performed its last memory access and before
418 * thread_delete() is called. Note: thread_delete() is only called for
419 * joinable threads, not for detached threads.
420 */
bart62a784c2009-02-15 13:11:14 +0000421void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000422{
bartbedfd232009-03-26 19:07:15 +0000423 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
424 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000425
bartbedfd232009-03-26 19:07:15 +0000426 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000427
bartbedfd232009-03-26 19:07:15 +0000428 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
429 {
430 /*
431 * Once a detached thread has finished, its stack is deallocated and
432 * should no longer be taken into account when computing the conflict set.
433 */
434 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000435
bartbedfd232009-03-26 19:07:15 +0000436 /*
437 * For a detached thread, calling pthread_exit() invalidates the
438 * POSIX thread ID associated with the detached thread. For joinable
439 * POSIX threads however, the POSIX thread ID remains live after the
440 * pthread_exit() call until pthread_join() is called.
441 */
442 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
443 }
sewardjaf44c822007-11-25 14:01:38 +0000444}
445
bart9b2974a2008-09-27 12:35:31 +0000446/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000447void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000448{
bartbedfd232009-03-26 19:07:15 +0000449 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
450 && tid != DRD_INVALID_THREADID);
451 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000452
bartbedfd232009-03-26 19:07:15 +0000453 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000454}
455
barte7dff242009-04-23 17:12:39 +0000456/**
457 * Store the POSIX thread ID for the specified thread.
458 *
459 * @note This function can be called two times for the same thread -- see also
460 * the comment block preceding the pthread_create() wrapper in
461 * drd_pthread_intercepts.c.
462 */
bart62a784c2009-02-15 13:11:14 +0000463void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000464{
bartbedfd232009-03-26 19:07:15 +0000465 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
466 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000467 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
468 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000469 tl_assert(ptid != INVALID_POSIX_THREADID);
470 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
471 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000472}
473
bart86a87df2009-03-04 19:26:47 +0000474/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000475Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000476{
bartbedfd232009-03-26 19:07:15 +0000477 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
478 && tid != DRD_INVALID_THREADID);
479 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000480}
481
bart86a87df2009-03-04 19:26:47 +0000482/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000483void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000484{
bartbedfd232009-03-26 19:07:15 +0000485 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
486 && tid != DRD_INVALID_THREADID);
487 tl_assert(!! joinable == joinable);
488 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000489#if 0
bartbedfd232009-03-26 19:07:15 +0000490 VG_(message)(Vg_DebugMsg,
491 "thread_set_joinable(%d/%d, %s)",
492 tid,
493 DRD_(g_threadinfo)[tid].vg_threadid,
494 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000495#endif
bartbedfd232009-03-26 19:07:15 +0000496 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000497}
498
bartd45d9952009-05-31 18:53:54 +0000499/** Obtain the thread number and the user-assigned thread name. */
500const char* DRD_(thread_get_name)(const DrdThreadId tid)
501{
502 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
503 && tid != DRD_INVALID_THREADID);
504
505 return DRD_(g_threadinfo)[tid].name;
506}
507
508/** Set the name of the specified thread. */
509void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
510{
511 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
512 && tid != DRD_INVALID_THREADID);
513
514 if (name == NULL || name[0] == 0)
515 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
516 sizeof(DRD_(g_threadinfo)[tid].name),
517 "Thread %d",
518 tid);
519 else
520 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
521 sizeof(DRD_(g_threadinfo)[tid].name),
522 "Thread %d (%s)",
523 tid, name);
524 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
525}
526
bart86a87df2009-03-04 19:26:47 +0000527/**
528 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
529 * conflict set.
530 */
bart62a784c2009-02-15 13:11:14 +0000531void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000532{
bartbedfd232009-03-26 19:07:15 +0000533 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000534
bartbedfd232009-03-26 19:07:15 +0000535 if (vg_tid != s_vg_running_tid)
536 {
537 DRD_(thread_set_running_tid)(vg_tid,
538 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
539 }
sewardj8b09d4f2007-12-04 21:27:18 +0000540
bartbedfd232009-03-26 19:07:15 +0000541 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
542 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000543}
544
bart86a87df2009-03-04 19:26:47 +0000545/**
546 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
547 * conflict set.
548 */
bart62a784c2009-02-15 13:11:14 +0000549void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
550 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000551{
bartbedfd232009-03-26 19:07:15 +0000552 tl_assert(vg_tid != VG_INVALID_THREADID);
553 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000554
bartbedfd232009-03-26 19:07:15 +0000555 if (vg_tid != s_vg_running_tid)
556 {
557 if (s_trace_context_switches
558 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
559 {
560 VG_(message)(Vg_DebugMsg,
561 "Context switch from thread %d/%d to thread %d/%d;"
562 " segments: %llu",
563 s_vg_running_tid, DRD_(g_drd_running_tid),
564 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
565 DRD_(sg_get_segments_alive_count)());
566 }
567 s_vg_running_tid = vg_tid;
568 DRD_(g_drd_running_tid) = drd_tid;
569 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
570 s_context_switch_count++;
571 }
sewardj8b09d4f2007-12-04 21:27:18 +0000572
bartbedfd232009-03-26 19:07:15 +0000573 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
574 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000575}
576
bart86a87df2009-03-04 19:26:47 +0000577/**
578 * Increase the synchronization nesting counter. Must be called before the
579 * client calls a synchronization function.
580 */
bart62a784c2009-02-15 13:11:14 +0000581int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000582{
bartbedfd232009-03-26 19:07:15 +0000583 tl_assert(DRD_(IsValidDrdThreadId)(tid));
584 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000585}
586
bart86a87df2009-03-04 19:26:47 +0000587/**
588 * Decrease the synchronization nesting counter. Must be called after the
589 * client left a synchronization function.
590 */
bart62a784c2009-02-15 13:11:14 +0000591int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000592{
bartbedfd232009-03-26 19:07:15 +0000593 tl_assert(DRD_(IsValidDrdThreadId)(tid));
594 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
595 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000596}
597
bart86a87df2009-03-04 19:26:47 +0000598/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000599int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000600{
bartbedfd232009-03-26 19:07:15 +0000601 tl_assert(DRD_(IsValidDrdThreadId)(tid));
602 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000603}
604
bart1a473c72008-03-13 19:03:38 +0000605/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000606static
bart86a87df2009-03-04 19:26:47 +0000607void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000608{
bartbedfd232009-03-26 19:07:15 +0000609 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
610 && tid != DRD_INVALID_THREADID);
611 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
612 sg->prev = DRD_(g_threadinfo)[tid].last;
613 sg->next = 0;
614 if (DRD_(g_threadinfo)[tid].last)
615 DRD_(g_threadinfo)[tid].last->next = sg;
616 DRD_(g_threadinfo)[tid].last = sg;
617 if (DRD_(g_threadinfo)[tid].first == 0)
618 DRD_(g_threadinfo)[tid].first = sg;
619 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000620}
621
bart324a23b2009-02-15 12:14:52 +0000622/**
623 * Remove a segment from the segment list of thread threadid, and free the
624 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000625 */
bart62a784c2009-02-15 13:11:14 +0000626static
bart86a87df2009-03-04 19:26:47 +0000627void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000628{
bartbedfd232009-03-26 19:07:15 +0000629 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
630 && tid != DRD_INVALID_THREADID);
631 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart26f73e12008-02-24 18:37:08 +0000632
bartbedfd232009-03-26 19:07:15 +0000633 if (sg->prev)
634 sg->prev->next = sg->next;
635 if (sg->next)
636 sg->next->prev = sg->prev;
637 if (sg == DRD_(g_threadinfo)[tid].first)
638 DRD_(g_threadinfo)[tid].first = sg->next;
639 if (sg == DRD_(g_threadinfo)[tid].last)
640 DRD_(g_threadinfo)[tid].last = sg->prev;
641 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000642
bartbedfd232009-03-26 19:07:15 +0000643 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000644}
645
bart86a87df2009-03-04 19:26:47 +0000646/**
647 * Returns a pointer to the vector clock of the most recent segment associated
648 * with thread 'tid'.
649 */
bart62a784c2009-02-15 13:11:14 +0000650VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000651{
bartbedfd232009-03-26 19:07:15 +0000652 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
653 && tid != DRD_INVALID_THREADID);
654 tl_assert(DRD_(g_threadinfo)[tid].last);
655 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000656}
657
bart324a23b2009-02-15 12:14:52 +0000658/**
659 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000660 */
bart62a784c2009-02-15 13:11:14 +0000661void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000662{
bartbedfd232009-03-26 19:07:15 +0000663 tl_assert(sg);
664 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
665 && tid != DRD_INVALID_THREADID);
666 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000667
bartbedfd232009-03-26 19:07:15 +0000668 DRD_(sg_put)(*sg);
669 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000670}
671
sewardjaf44c822007-11-25 14:01:38 +0000672/**
673 * Compute the minimum of all latest vector clocks of all threads
674 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000675 *
sewardjaf44c822007-11-25 14:01:38 +0000676 * @param vc pointer to a vectorclock, holds result upon return.
677 */
bart62a784c2009-02-15 13:11:14 +0000678static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000679{
bartbedfd232009-03-26 19:07:15 +0000680 unsigned i;
681 Bool first;
682 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000683
bartbedfd232009-03-26 19:07:15 +0000684 first = True;
685 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
686 i++)
687 {
688 latest_sg = DRD_(g_threadinfo)[i].last;
689 if (latest_sg)
690 {
691 if (first)
692 DRD_(vc_assign)(vc, &latest_sg->vc);
693 else
694 DRD_(vc_min)(vc, &latest_sg->vc);
695 first = False;
696 }
697 }
sewardjaf44c822007-11-25 14:01:38 +0000698}
699
bart86a87df2009-03-04 19:26:47 +0000700/**
701 * Compute the maximum of all latest vector clocks of all threads.
702 *
703 * @param vc pointer to a vectorclock, holds result upon return.
704 */
bart62a784c2009-02-15 13:11:14 +0000705static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000706{
bartbedfd232009-03-26 19:07:15 +0000707 unsigned i;
708 Bool first;
709 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000710
bartbedfd232009-03-26 19:07:15 +0000711 first = True;
712 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
713 i++)
714 {
715 latest_sg = DRD_(g_threadinfo)[i].last;
716 if (latest_sg)
717 {
718 if (first)
719 DRD_(vc_assign)(vc, &latest_sg->vc);
720 else
721 DRD_(vc_combine)(vc, &latest_sg->vc);
722 first = False;
723 }
724 }
sewardjaf44c822007-11-25 14:01:38 +0000725}
726
727/**
bart5bd9f2d2008-03-03 20:31:58 +0000728 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000729 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000730 * data race.
731 */
bart62a784c2009-02-15 13:11:14 +0000732static void DRD_(thread_discard_ordered_segments)(void)
sewardjaf44c822007-11-25 14:01:38 +0000733{
bartbedfd232009-03-26 19:07:15 +0000734 unsigned i;
735 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000736
bartbedfd232009-03-26 19:07:15 +0000737 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000738
bartbedfd232009-03-26 19:07:15 +0000739 DRD_(vc_init)(&thread_vc_min, 0, 0);
740 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
741 if (DRD_(sg_get_trace)())
742 {
743 char msg[256];
744 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000745
bartbedfd232009-03-26 19:07:15 +0000746 DRD_(vc_init)(&thread_vc_max, 0, 0);
747 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
748 VG_(snprintf)(msg, sizeof(msg),
749 "Discarding ordered segments -- min vc is ");
750 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
751 &thread_vc_min);
752 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
753 ", max vc is ");
754 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
755 &thread_vc_max);
756 VG_(message)(Vg_UserMsg, "%s", msg);
757 DRD_(vc_cleanup)(&thread_vc_max);
758 }
sewardjaf44c822007-11-25 14:01:38 +0000759
bartbedfd232009-03-26 19:07:15 +0000760 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
761 i++)
762 {
763 Segment* sg;
764 Segment* sg_next;
765 for (sg = DRD_(g_threadinfo)[i].first;
766 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
767 sg = sg_next)
768 {
769 thread_discard_segment(i, sg);
770 }
771 }
772 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000773}
774
bart324a23b2009-02-15 12:14:52 +0000775/**
776 * Merge all segments that may be merged without triggering false positives
777 * or discarding real data races. For the theoretical background of segment
778 * merging, see also the following paper:
779 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
780 * Bounding the number of segment histories during data race detection.
781 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
782 * September 2002.
barta9c37392008-03-22 09:38:48 +0000783 */
784static void thread_merge_segments(void)
785{
bartbedfd232009-03-26 19:07:15 +0000786 unsigned i;
barta9c37392008-03-22 09:38:48 +0000787
bartbedfd232009-03-26 19:07:15 +0000788 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
789 i++)
790 {
791 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000792
bartbedfd232009-03-26 19:07:15 +0000793 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000794
bartbedfd232009-03-26 19:07:15 +0000795 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000796 {
bartbedfd232009-03-26 19:07:15 +0000797 if (DRD_(sg_get_refcnt)(sg) == 1
798 && sg->next
799 && DRD_(sg_get_refcnt)(sg->next) == 1
800 && sg->next->next)
801 {
802 /* Merge sg and sg->next into sg. */
803 DRD_(sg_merge)(sg, sg->next);
804 thread_discard_segment(i, sg->next);
805 }
barta9c37392008-03-22 09:38:48 +0000806 }
barta9c37392008-03-22 09:38:48 +0000807
bartbedfd232009-03-26 19:07:15 +0000808 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
809 }
barta9c37392008-03-22 09:38:48 +0000810}
811
bart324a23b2009-02-15 12:14:52 +0000812/**
bart324a23b2009-02-15 12:14:52 +0000813 * Create a new segment for the specified thread, and discard any segments
814 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000815 */
bart62a784c2009-02-15 13:11:14 +0000816void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000817{
bartbedfd232009-03-26 19:07:15 +0000818 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000819
bartbedfd232009-03-26 19:07:15 +0000820 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
821 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000822
bartbedfd232009-03-26 19:07:15 +0000823 new_sg = DRD_(sg_new)(tid, tid);
824 thread_append_segment(tid, new_sg);
bartd66e3a82008-04-06 15:02:17 +0000825
bartbedfd232009-03-26 19:07:15 +0000826 thread_compute_conflict_set(&DRD_(g_conflict_set), DRD_(g_drd_running_tid));
827 s_conflict_set_new_segment_count++;
sewardjaf44c822007-11-25 14:01:38 +0000828
bartbedfd232009-03-26 19:07:15 +0000829 DRD_(thread_discard_ordered_segments)();
bart26f73e12008-02-24 18:37:08 +0000830
bartbedfd232009-03-26 19:07:15 +0000831 if (s_segment_merging)
832 {
833 thread_merge_segments();
834 }
sewardjaf44c822007-11-25 14:01:38 +0000835}
836
bart26f73e12008-02-24 18:37:08 +0000837/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart62a784c2009-02-15 13:11:14 +0000838void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000839{
bartbedfd232009-03-26 19:07:15 +0000840 tl_assert(joiner != joinee);
841 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
842 && joiner != DRD_INVALID_THREADID);
843 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
844 && joinee != DRD_INVALID_THREADID);
845 tl_assert(DRD_(g_threadinfo)[joiner].last);
846 tl_assert(DRD_(g_threadinfo)[joinee].last);
847 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
848 &DRD_(g_threadinfo)[joinee].last->vc);
849 DRD_(thread_discard_ordered_segments)();
sewardjaf44c822007-11-25 14:01:38 +0000850
bartbedfd232009-03-26 19:07:15 +0000851 if (joiner == DRD_(g_drd_running_tid))
852 {
853 thread_compute_conflict_set(&DRD_(g_conflict_set), joiner);
854 }
sewardjaf44c822007-11-25 14:01:38 +0000855}
856
bart324a23b2009-02-15 12:14:52 +0000857/**
858 * Call this function after thread 'tid' had to wait because of thread
859 * synchronization until the memory accesses in the segment with vector clock
860 * 'vc' finished.
bart26f73e12008-02-24 18:37:08 +0000861 */
bart62a784c2009-02-15 13:11:14 +0000862void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc)
sewardjaf44c822007-11-25 14:01:38 +0000863{
bartbedfd232009-03-26 19:07:15 +0000864 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
865 && tid != DRD_INVALID_THREADID);
866 tl_assert(DRD_(g_threadinfo)[tid].last);
867 tl_assert(vc);
868 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
869 thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
870 DRD_(thread_discard_ordered_segments)();
871 s_conflict_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000872}
873
bart324a23b2009-02-15 12:14:52 +0000874/**
875 * Call this function whenever a thread is no longer using the memory
876 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
877 * increase.
bart26f73e12008-02-24 18:37:08 +0000878 */
bart62a784c2009-02-15 13:11:14 +0000879void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000880{
bartbedfd232009-03-26 19:07:15 +0000881 DrdThreadId other_user;
882 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000883
bartbedfd232009-03-26 19:07:15 +0000884 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
885 other_user = DRD_INVALID_THREADID;
886 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
887 i++)
888 {
889 Segment* p;
890 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000891 {
bartbedfd232009-03-26 19:07:15 +0000892 if (other_user == DRD_INVALID_THREADID
893 && i != DRD_(g_drd_running_tid))
894 {
895 if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2)))
896 {
897 other_user = i;
898 }
899 continue;
900 }
901 DRD_(bm_clear)(p->bm, a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000902 }
bartbedfd232009-03-26 19:07:15 +0000903 }
sewardjaf44c822007-11-25 14:01:38 +0000904
bartbedfd232009-03-26 19:07:15 +0000905 /*
906 * If any other thread had accessed memory in [ a1, a2 [, update the
907 * conflict set.
908 */
909 if (other_user != DRD_INVALID_THREADID
910 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
911 {
912 thread_compute_conflict_set(&DRD_(g_conflict_set),
913 DRD_(thread_get_running_tid)());
914 }
sewardjaf44c822007-11-25 14:01:38 +0000915}
916
bartd45d9952009-05-31 18:53:54 +0000917/** Specify whether memory loads should be recorded. */
918void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +0000919{
bartbedfd232009-03-26 19:07:15 +0000920 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
921 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +0000922 tl_assert(enabled == !! enabled);
923
924 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +0000925}
926
bartd45d9952009-05-31 18:53:54 +0000927/** Specify whether memory stores should be recorded. */
928void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +0000929{
bartbedfd232009-03-26 19:07:15 +0000930 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
931 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +0000932 tl_assert(enabled == !! enabled);
933
934 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +0000935}
936
bart86a87df2009-03-04 19:26:47 +0000937/**
938 * Print the segment information for all threads.
939 *
940 * This function is only used for debugging purposes.
941 */
bart62a784c2009-02-15 13:11:14 +0000942void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +0000943{
bartbedfd232009-03-26 19:07:15 +0000944 unsigned i;
945 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000946
bartbedfd232009-03-26 19:07:15 +0000947 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
948 i++)
949 {
950 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +0000951 {
bartbedfd232009-03-26 19:07:15 +0000952 VG_(printf)("**************\n"
953 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
954 "**************\n",
955 i,
956 DRD_(g_threadinfo)[i].vg_thread_exists,
957 DRD_(g_threadinfo)[i].vg_threadid,
958 DRD_(g_threadinfo)[i].posix_thread_exists,
959 DRD_(g_threadinfo)[i].pt_threadid,
960 DRD_(g_threadinfo)[i].detached_posix_thread);
961 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
962 {
963 DRD_(sg_print)(p);
964 }
sewardjaf44c822007-11-25 14:01:38 +0000965 }
bartbedfd232009-03-26 19:07:15 +0000966 }
sewardjaf44c822007-11-25 14:01:38 +0000967}
968
bart86a87df2009-03-04 19:26:47 +0000969/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000970static void show_call_stack(const DrdThreadId tid,
971 const Char* const msg,
972 ExeContext* const callstack)
973{
bartbedfd232009-03-26 19:07:15 +0000974 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +0000975
bartbedfd232009-03-26 19:07:15 +0000976 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000977
bartbedfd232009-03-26 19:07:15 +0000978 if (vg_tid != VG_INVALID_THREADID)
979 {
980 if (callstack)
981 {
982 VG_(pp_ExeContext)(callstack);
983 }
984 else
985 {
986 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
987 }
988 }
989 else
990 {
991 VG_(message)(Vg_UserMsg,
992 " (thread finished, call stack no longer available)");
993 }
sewardjaf44c822007-11-25 14:01:38 +0000994}
995
bart86a87df2009-03-04 19:26:47 +0000996/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000997static void
998thread_report_conflicting_segments_segment(const DrdThreadId tid,
999 const Addr addr,
1000 const SizeT size,
1001 const BmAccessTypeT access_type,
1002 const Segment* const p)
1003{
bartbedfd232009-03-26 19:07:15 +00001004 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001005
bartbedfd232009-03-26 19:07:15 +00001006 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1007 && tid != DRD_INVALID_THREADID);
1008 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001009
bartbedfd232009-03-26 19:07:15 +00001010 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
1011 i++)
1012 {
1013 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001014 {
bartbedfd232009-03-26 19:07:15 +00001015 Segment* q;
1016 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1017 {
1018 /*
1019 * Since q iterates over the segments of thread i in order of
1020 * decreasing vector clocks, if q->vc <= p->vc, then
1021 * q->next->vc <= p->vc will also hold. Hence, break out of the
1022 * loop once this condition is met.
1023 */
1024 if (DRD_(vc_lte)(&q->vc, &p->vc))
1025 break;
1026 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1027 {
1028 if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size,
1029 access_type))
1030 {
1031 tl_assert(q->stacktrace);
1032 show_call_stack(i, "Other segment start",
1033 q->stacktrace);
1034 show_call_stack(i, "Other segment end",
1035 q->next ? q->next->stacktrace : 0);
1036 }
1037 }
1038 }
sewardjaf44c822007-11-25 14:01:38 +00001039 }
bartbedfd232009-03-26 19:07:15 +00001040 }
sewardjaf44c822007-11-25 14:01:38 +00001041}
1042
bart86a87df2009-03-04 19:26:47 +00001043/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001044void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1045 const Addr addr,
1046 const SizeT size,
1047 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001048{
bartbedfd232009-03-26 19:07:15 +00001049 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001050
bartbedfd232009-03-26 19:07:15 +00001051 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1052 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001053
bartbedfd232009-03-26 19:07:15 +00001054 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1055 {
1056 if (DRD_(bm_has)(p->bm, addr, addr + size, access_type))
1057 {
1058 thread_report_conflicting_segments_segment(tid, addr, size,
1059 access_type, p);
1060 }
1061 }
sewardjaf44c822007-11-25 14:01:38 +00001062}
sewardjaf44c822007-11-25 14:01:38 +00001063
bart324a23b2009-02-15 12:14:52 +00001064/**
bart324a23b2009-02-15 12:14:52 +00001065 * Compute a bitmap that represents the union of all memory accesses of all
1066 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001067 */
bart86a87df2009-03-04 19:26:47 +00001068static void thread_compute_conflict_set(struct bitmap** conflict_set,
1069 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001070{
bartbedfd232009-03-26 19:07:15 +00001071 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001072
bartbedfd232009-03-26 19:07:15 +00001073 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1074 && tid != DRD_INVALID_THREADID);
1075 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001076
bartbedfd232009-03-26 19:07:15 +00001077 s_update_conflict_set_count++;
1078 s_conflict_set_bitmap_creation_count
1079 -= DRD_(bm_get_bitmap_creation_count)();
1080 s_conflict_set_bitmap2_creation_count
1081 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001082
bartbedfd232009-03-26 19:07:15 +00001083 if (*conflict_set)
1084 {
1085 DRD_(bm_delete)(*conflict_set);
1086 }
1087 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001088
bartbedfd232009-03-26 19:07:15 +00001089 if (s_trace_conflict_set)
1090 {
bart26f73e12008-02-24 18:37:08 +00001091 char msg[256];
1092
1093 VG_(snprintf)(msg, sizeof(msg),
bartbedfd232009-03-26 19:07:15 +00001094 "computing conflict set for thread %d/%d with vc ",
1095 DRD_(DrdThreadIdToVgThreadId)(tid), tid);
bart41b226c2009-02-14 16:55:19 +00001096 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1097 sizeof(msg) - VG_(strlen)(msg),
bartbedfd232009-03-26 19:07:15 +00001098 &DRD_(g_threadinfo)[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +00001099 VG_(message)(Vg_UserMsg, "%s", msg);
bartbedfd232009-03-26 19:07:15 +00001100 }
sewardjaf44c822007-11-25 14:01:38 +00001101
bartbedfd232009-03-26 19:07:15 +00001102 p = DRD_(g_threadinfo)[tid].last;
1103 {
1104 unsigned j;
1105
1106 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001107 {
bartbedfd232009-03-26 19:07:15 +00001108 char msg[256];
1109
1110 VG_(snprintf)(msg, sizeof(msg),
1111 "conflict set: thread [%d] at vc ",
1112 tid);
1113 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1114 sizeof(msg) - VG_(strlen)(msg),
1115 &p->vc);
1116 VG_(message)(Vg_UserMsg, "%s", msg);
bart26f73e12008-02-24 18:37:08 +00001117 }
sewardjaf44c822007-11-25 14:01:38 +00001118
bartbedfd232009-03-26 19:07:15 +00001119 for (j = 0;
1120 j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
1121 j++)
1122 {
1123 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1124 {
1125 const Segment* q;
1126 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1127 {
1128 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1129 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1130 {
1131 if (s_trace_conflict_set)
1132 {
1133 char msg[256];
1134 VG_(snprintf)(msg, sizeof(msg),
1135 "conflict set: [%d] merging segment ", j);
1136 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1137 sizeof(msg) - VG_(strlen)(msg),
1138 &q->vc);
1139 VG_(message)(Vg_UserMsg, "%s", msg);
1140 }
1141 DRD_(bm_merge2)(*conflict_set, q->bm);
1142 }
1143 else
1144 {
1145 if (s_trace_conflict_set)
1146 {
1147 char msg[256];
1148 VG_(snprintf)(msg, sizeof(msg),
1149 "conflict set: [%d] ignoring segment ", j);
1150 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1151 sizeof(msg) - VG_(strlen)(msg),
1152 &q->vc);
1153 VG_(message)(Vg_UserMsg, "%s", msg);
1154 }
1155 }
1156 }
1157 }
1158 }
1159 }
sewardjaf44c822007-11-25 14:01:38 +00001160
bartbedfd232009-03-26 19:07:15 +00001161 s_conflict_set_bitmap_creation_count
1162 += DRD_(bm_get_bitmap_creation_count)();
1163 s_conflict_set_bitmap2_creation_count
1164 += DRD_(bm_get_bitmap2_creation_count)();
1165
1166 if (0 && s_trace_conflict_set)
1167 {
1168 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
1169 DRD_(bm_print)(*conflict_set);
1170 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
1171 }
sewardjaf44c822007-11-25 14:01:38 +00001172}
1173
bart86a87df2009-03-04 19:26:47 +00001174/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001175ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001176{
bartbedfd232009-03-26 19:07:15 +00001177 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001178}
1179
bart86a87df2009-03-04 19:26:47 +00001180/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001181ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001182{
bartbedfd232009-03-26 19:07:15 +00001183 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001184}
1185
bart86a87df2009-03-04 19:26:47 +00001186/** Return how many times the conflict set has been updated. */
bart62a784c2009-02-15 13:11:14 +00001187ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001188{
bartbedfd232009-03-26 19:07:15 +00001189 tl_assert(dsnsc);
1190 tl_assert(dscvc);
1191 *dsnsc = s_conflict_set_new_segment_count;
1192 *dscvc = s_conflict_set_combine_vc_count;
1193 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001194}
1195
bart86a87df2009-03-04 19:26:47 +00001196/**
1197 * Return the number of first-level bitmaps that have been created during
1198 * conflict set updates.
1199 */
bart62a784c2009-02-15 13:11:14 +00001200ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001201{
bartbedfd232009-03-26 19:07:15 +00001202 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001203}
1204
bart86a87df2009-03-04 19:26:47 +00001205/**
1206 * Return the number of second-level bitmaps that have been created during
1207 * conflict set updates.
1208 */
bart62a784c2009-02-15 13:11:14 +00001209ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001210{
bartbedfd232009-03-26 19:07:15 +00001211 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001212}