blob: 2c759c15f8f2f91d7fb1ea280a39e5537e02896a [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
sewardjaf44c822007-11-25 14:01:38 +000037#include "pub_tool_libcassert.h" // tl_assert()
38#include "pub_tool_libcbase.h" // VG_(strlen)()
39#include "pub_tool_libcprint.h" // VG_(printf)()
bart82195c12008-04-13 17:35:08 +000040#include "pub_tool_libcproc.h" // VG_(getenv)()
sewardjaf44c822007-11-25 14:01:38 +000041#include "pub_tool_machine.h"
42#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
sewardj85642922008-01-14 11:54:56 +000043#include "pub_tool_options.h" // VG_(clo_backtrace_size)
sewardjaf44c822007-11-25 14:01:38 +000044#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
45
bart32ba2082008-06-05 08:53:42 +000046
sewardjaf44c822007-11-25 14:01:38 +000047
bart324a23b2009-02-15 12:14:52 +000048/* Local functions. */
sewardjaf44c822007-11-25 14:01:38 +000049
bart86a87df2009-03-04 19:26:47 +000050static void thread_append_segment(const DrdThreadId tid, Segment* const sg);
51static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
52static void thread_compute_conflict_set(struct bitmap** conflict_set,
53 const DrdThreadId tid);
bart8f822af2009-06-08 18:20:42 +000054static Bool thread_conflict_set_up_to_date(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;
bart54803fe2009-06-21 09:26:27 +000061static ULong s_compute_conflict_set_count;
bart86a87df2009-03-04 19:26:47 +000062static ULong s_update_conflict_set_count;
barte5214662009-06-21 11:51:23 +000063static ULong s_update_conflict_set_new_sg_count;
64static ULong s_update_conflict_set_sync_count;
65static ULong s_update_conflict_set_join_count;
bart86a87df2009-03-04 19:26:47 +000066static ULong s_conflict_set_bitmap_creation_count;
67static ULong s_conflict_set_bitmap2_creation_count;
68static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bart324a23b2009-02-15 12:14:52 +000069DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
70ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
71struct bitmap* DRD_(g_conflict_set);
bart86a87df2009-03-04 19:26:47 +000072static Bool s_trace_context_switches = False;
73static Bool s_trace_conflict_set = False;
bart8f822af2009-06-08 18:20:42 +000074static Bool s_trace_conflict_set_bm = False;
bart86a87df2009-03-04 19:26:47 +000075static Bool s_trace_fork_join = False;
76static Bool s_segment_merging = True;
bart8f822af2009-06-08 18:20:42 +000077static Bool s_new_segments_since_last_merge;
bart6f1d7162009-06-24 18:34:10 +000078static int s_segment_merge_interval = 10;
sewardjaf44c822007-11-25 14:01:38 +000079
80
bart324a23b2009-02-15 12:14:52 +000081/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000082
bart86a87df2009-03-04 19:26:47 +000083/** Enables/disables context switch tracing. */
bart62a784c2009-02-15 13:11:14 +000084void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000085{
bartbedfd232009-03-26 19:07:15 +000086 tl_assert(t == False || t == True);
87 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000088}
89
bart86a87df2009-03-04 19:26:47 +000090/** Enables/disables conflict set tracing. */
bart62a784c2009-02-15 13:11:14 +000091void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000092{
bartbedfd232009-03-26 19:07:15 +000093 tl_assert(t == False || t == True);
94 s_trace_conflict_set = t;
bart26f73e12008-02-24 18:37:08 +000095}
96
bart8f822af2009-06-08 18:20:42 +000097/** Enables/disables conflict set bitmap tracing. */
98void DRD_(thread_trace_conflict_set_bm)(const Bool t)
99{
100 tl_assert(t == False || t == True);
101 s_trace_conflict_set_bm = t;
102}
103
bart86a87df2009-03-04 19:26:47 +0000104/** Report whether fork/join tracing is enabled. */
bart09dc13f2009-02-14 15:13:31 +0000105Bool DRD_(thread_get_trace_fork_join)(void)
106{
bartbedfd232009-03-26 19:07:15 +0000107 return s_trace_fork_join;
bart09dc13f2009-02-14 15:13:31 +0000108}
109
bart86a87df2009-03-04 19:26:47 +0000110/** Enables/disables fork/join tracing. */
bart09dc13f2009-02-14 15:13:31 +0000111void DRD_(thread_set_trace_fork_join)(const Bool t)
112{
bartbedfd232009-03-26 19:07:15 +0000113 tl_assert(t == False || t == True);
114 s_trace_fork_join = t;
bart09dc13f2009-02-14 15:13:31 +0000115}
116
bart86a87df2009-03-04 19:26:47 +0000117/** Enables/disables segment merging. */
bart62a784c2009-02-15 13:11:14 +0000118void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000119{
bartbedfd232009-03-26 19:07:15 +0000120 tl_assert(m == False || m == True);
121 s_segment_merging = m;
barta9c37392008-03-22 09:38:48 +0000122}
123
bart8f822af2009-06-08 18:20:42 +0000124/** Get the segment merging interval. */
125int DRD_(thread_get_segment_merge_interval)(void)
126{
127 return s_segment_merge_interval;
128}
129
130/** Set the segment merging interval. */
131void DRD_(thread_set_segment_merge_interval)(const int i)
132{
133 s_segment_merge_interval = i;
134}
135
sewardjaf44c822007-11-25 14:01:38 +0000136/**
bart86a87df2009-03-04 19:26:47 +0000137 * Convert Valgrind's ThreadId into a DrdThreadId.
138 *
139 * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
140 * Valgrind ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000141 */
bart62a784c2009-02-15 13:11:14 +0000142DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000143{
bartbedfd232009-03-26 19:07:15 +0000144 int i;
sewardjaf44c822007-11-25 14:01:38 +0000145
bartbedfd232009-03-26 19:07:15 +0000146 if (tid == VG_INVALID_THREADID)
147 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000148
bartbedfd232009-03-26 19:07:15 +0000149 for (i = 1; i < DRD_N_THREADS; i++)
150 {
151 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
152 && DRD_(g_threadinfo)[i].vg_threadid == tid)
153 {
154 return i;
155 }
156 }
sewardjaf44c822007-11-25 14:01:38 +0000157
bartbedfd232009-03-26 19:07:15 +0000158 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000159}
160
bart86a87df2009-03-04 19:26:47 +0000161/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000162static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000163{
bartbedfd232009-03-26 19:07:15 +0000164 int i;
sewardjaf44c822007-11-25 14:01:38 +0000165
bartbedfd232009-03-26 19:07:15 +0000166 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000167
bartbedfd232009-03-26 19:07:15 +0000168 for (i = 1; i < DRD_N_THREADS; i++)
169 {
170 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
171 && DRD_(g_threadinfo)[i].posix_thread_exists == False
172 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
173 {
174 tl_assert(! DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000175
bartbedfd232009-03-26 19:07:15 +0000176 DRD_(g_threadinfo)[i].vg_thread_exists = True;
177 DRD_(g_threadinfo)[i].vg_threadid = tid;
178 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
179 DRD_(g_threadinfo)[i].stack_min = 0;
180 DRD_(g_threadinfo)[i].stack_min_min = 0;
181 DRD_(g_threadinfo)[i].stack_startup = 0;
182 DRD_(g_threadinfo)[i].stack_max = 0;
bartd45d9952009-05-31 18:53:54 +0000183 DRD_(thread_set_name)(i, "");
184 DRD_(g_threadinfo)[i].is_recording_loads = True;
185 DRD_(g_threadinfo)[i].is_recording_stores = True;
bartdd75cdf2009-07-24 08:20:10 +0000186 DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
bartbedfd232009-03-26 19:07:15 +0000187 DRD_(g_threadinfo)[i].synchr_nesting = 0;
188 tl_assert(DRD_(g_threadinfo)[i].first == 0);
189 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000190
bartbedfd232009-03-26 19:07:15 +0000191 tl_assert(DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000192
bartbedfd232009-03-26 19:07:15 +0000193 return i;
194 }
195 }
sewardjaf44c822007-11-25 14:01:38 +0000196
bart3c9afb12009-07-24 11:11:30 +0000197 VG_(printf)(
198"\nSorry, but the maximum number of threads supported by DRD has been exceeded."
199"Aborting.\n");
200
bartbedfd232009-03-26 19:07:15 +0000201 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000202
bartbedfd232009-03-26 19:07:15 +0000203 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000204}
205
bart86a87df2009-03-04 19:26:47 +0000206/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000207DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000208{
bartbedfd232009-03-26 19:07:15 +0000209 int i;
sewardjaf44c822007-11-25 14:01:38 +0000210
bartb48bde22009-07-31 08:26:17 +0000211 if (tid != INVALID_POSIX_THREADID)
bartbedfd232009-03-26 19:07:15 +0000212 {
bartb48bde22009-07-31 08:26:17 +0000213 for (i = 1; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000214 {
bartb48bde22009-07-31 08:26:17 +0000215 if (DRD_(g_threadinfo)[i].posix_thread_exists
216 && DRD_(g_threadinfo)[i].pt_threadid == tid)
217 {
218 return i;
219 }
bartbedfd232009-03-26 19:07:15 +0000220 }
221 }
222 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000223}
224
bart86a87df2009-03-04 19:26:47 +0000225/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000226ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000227{
bartbedfd232009-03-26 19:07:15 +0000228 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
229 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000230
bartbedfd232009-03-26 19:07:15 +0000231 return (DRD_(g_threadinfo)[tid].vg_thread_exists
232 ? DRD_(g_threadinfo)[tid].vg_threadid
233 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000234}
235
bart8f822af2009-06-08 18:20:42 +0000236#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart324a23b2009-02-15 12:14:52 +0000237/**
238 * Sanity check of the doubly linked list of segments referenced by a
239 * ThreadInfo struct.
240 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000241 */
bart62a784c2009-02-15 13:11:14 +0000242static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000243{
bartbedfd232009-03-26 19:07:15 +0000244 Segment* p;
bart8f822af2009-06-08 18:20:42 +0000245
bartbedfd232009-03-26 19:07:15 +0000246 for (p = ti->first; p; p = p->next) {
247 if (p->next && p->next->prev != p)
248 return False;
249 if (p->next == 0 && p != ti->last)
250 return False;
251 }
252 for (p = ti->last; p; p = p->prev) {
253 if (p->prev && p->prev->next != p)
254 return False;
255 if (p->prev == 0 && p != ti->first)
256 return False;
257 }
258 return True;
sewardjaf44c822007-11-25 14:01:38 +0000259}
bart23d3a4e2008-04-05 12:53:00 +0000260#endif
sewardjaf44c822007-11-25 14:01:38 +0000261
bart439c55f2009-02-15 10:38:37 +0000262/**
263 * Create the first segment for a newly started thread.
264 *
265 * This function is called from the handler installed via
266 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
267 * from the context of the creator thread, before the new thread has been
268 * created.
bart86a87df2009-03-04 19:26:47 +0000269 *
270 * @param[in] creator DRD thread ID of the creator thread.
271 * @param[in] vg_created Valgrind thread ID of the created thread.
272 *
273 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000274 */
bart62a784c2009-02-15 13:11:14 +0000275DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
276 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000277{
bartbedfd232009-03-26 19:07:15 +0000278 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000279
bartbedfd232009-03-26 19:07:15 +0000280 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
281 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
282 tl_assert(0 <= (int)created && created < DRD_N_THREADS
283 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000284
bartbedfd232009-03-26 19:07:15 +0000285 tl_assert(DRD_(g_threadinfo)[created].first == 0);
286 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart8f822af2009-06-08 18:20:42 +0000287 /* Create an initial segment for the newly created thread. */
bartbedfd232009-03-26 19:07:15 +0000288 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000289
bartbedfd232009-03-26 19:07:15 +0000290 return created;
sewardjaf44c822007-11-25 14:01:38 +0000291}
292
bart439c55f2009-02-15 10:38:37 +0000293/**
bart86a87df2009-03-04 19:26:47 +0000294 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
295 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000296 * on the newly created thread, e.g. from the handler installed via
297 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000298 *
299 * @param[in] vg_created Valgrind thread ID of the newly created thread.
300 *
301 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000302 */
bart62a784c2009-02-15 13:11:14 +0000303DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000304{
bartbedfd232009-03-26 19:07:15 +0000305 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000306
bartbedfd232009-03-26 19:07:15 +0000307 tl_assert(0 <= (int)created && created < DRD_N_THREADS
308 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000309
bartbedfd232009-03-26 19:07:15 +0000310 DRD_(g_threadinfo)[created].stack_max
311 = VG_(thread_get_stack_max)(vg_created);
312 DRD_(g_threadinfo)[created].stack_startup
313 = DRD_(g_threadinfo)[created].stack_max;
314 DRD_(g_threadinfo)[created].stack_min
315 = DRD_(g_threadinfo)[created].stack_max;
316 DRD_(g_threadinfo)[created].stack_min_min
317 = DRD_(g_threadinfo)[created].stack_max;
318 DRD_(g_threadinfo)[created].stack_size
319 = VG_(thread_get_stack_size)(vg_created);
320 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000321
bartbedfd232009-03-26 19:07:15 +0000322 return created;
bart439c55f2009-02-15 10:38:37 +0000323}
bart09dc13f2009-02-14 15:13:31 +0000324
bart324a23b2009-02-15 12:14:52 +0000325/**
326 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
327 * after thread drd_joiner joined thread drd_joinee.
328 */
bart09dc13f2009-02-14 15:13:31 +0000329void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
330{
bartbedfd232009-03-26 19:07:15 +0000331 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
332 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
bart7627be32009-06-06 12:26:05 +0000333
bartbedfd232009-03-26 19:07:15 +0000334 DRD_(thread_new_segment)(drd_joiner);
bart8f822af2009-06-08 18:20:42 +0000335 DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
bart7627be32009-06-06 12:26:05 +0000336 DRD_(thread_new_segment)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000337
bartbedfd232009-03-26 19:07:15 +0000338 if (s_trace_fork_join)
339 {
340 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
bartbedfd232009-03-26 19:07:15 +0000341 const unsigned msg_size = 256;
342 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000343
bartbedfd232009-03-26 19:07:15 +0000344 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
345 tl_assert(msg);
346 VG_(snprintf)(msg, msg_size,
bart63c92ea2009-07-19 17:53:56 +0000347 "drd_post_thread_join joiner = %d, joinee = %d",
348 drd_joiner, drd_joinee);
bartbedfd232009-03-26 19:07:15 +0000349 if (joiner)
350 {
bart8f822af2009-06-08 18:20:42 +0000351 char* vc;
352
353 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
bartbedfd232009-03-26 19:07:15 +0000354 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart8f822af2009-06-08 18:20:42 +0000355 ", new vc: %s", vc);
356 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000357 }
sewardj1e29ebc2009-07-15 14:49:17 +0000358 VG_(message)(Vg_DebugMsg, "%s\n", msg);
bartbedfd232009-03-26 19:07:15 +0000359 VG_(free)(msg);
360 }
bart09dc13f2009-02-14 15:13:31 +0000361
bartbedfd232009-03-26 19:07:15 +0000362 if (! DRD_(get_check_stack_accesses)())
363 {
364 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
365 - DRD_(thread_get_stack_size)(drd_joinee),
366 DRD_(thread_get_stack_max)(drd_joinee));
367 }
368 DRD_(clientobj_delete_thread)(drd_joinee);
369 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000370}
371
bart324a23b2009-02-15 12:14:52 +0000372/**
373 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
374 * and accesses this data structure from multiple threads without locking.
375 * Any conflicting accesses in the range stack_startup..stack_max will be
376 * ignored.
377 */
bart62a784c2009-02-15 13:11:14 +0000378void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
379 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000380{
bartbedfd232009-03-26 19:07:15 +0000381 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
382 && tid != DRD_INVALID_THREADID);
383 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
384 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
385 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000386}
387
bart86a87df2009-03-04 19:26:47 +0000388/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000389Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000390{
bartbedfd232009-03-26 19:07:15 +0000391 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
392 && tid != DRD_INVALID_THREADID);
393 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000394}
395
bart86a87df2009-03-04 19:26:47 +0000396/**
397 * Return the lowest value that was ever assigned to the stack pointer
398 * for the specified thread.
399 */
bart62a784c2009-02-15 13:11:14 +0000400Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000401{
bartbedfd232009-03-26 19:07:15 +0000402 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
403 && tid != DRD_INVALID_THREADID);
404 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000405}
406
bart86a87df2009-03-04 19:26:47 +0000407/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000408Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000409{
bartbedfd232009-03-26 19:07:15 +0000410 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
411 && tid != DRD_INVALID_THREADID);
412 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000413}
414
bart86a87df2009-03-04 19:26:47 +0000415/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000416SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000417{
bartbedfd232009-03-26 19:07:15 +0000418 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
419 && tid != DRD_INVALID_THREADID);
420 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000421}
422
bart09dc13f2009-02-14 15:13:31 +0000423/**
424 * Clean up thread-specific data structures. Call this just after
425 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000426 */
bart62a784c2009-02-15 13:11:14 +0000427void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000428{
bartbedfd232009-03-26 19:07:15 +0000429 Segment* sg;
430 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000431
bartbedfd232009-03-26 19:07:15 +0000432 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000433
bartbedfd232009-03-26 19:07:15 +0000434 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
435 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
436 {
437 sg_prev = sg->prev;
438 sg->prev = 0;
439 sg->next = 0;
440 DRD_(sg_put)(sg);
441 }
442 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
443 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
444 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
445 DRD_(g_threadinfo)[tid].first = 0;
446 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000447
bartbedfd232009-03-26 19:07:15 +0000448 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000449}
450
bart324a23b2009-02-15 12:14:52 +0000451/**
452 * Called after a thread performed its last memory access and before
453 * thread_delete() is called. Note: thread_delete() is only called for
454 * joinable threads, not for detached threads.
455 */
bart62a784c2009-02-15 13:11:14 +0000456void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000457{
bartbedfd232009-03-26 19:07:15 +0000458 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
459 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000460
bartbedfd232009-03-26 19:07:15 +0000461 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000462
bartbedfd232009-03-26 19:07:15 +0000463 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
464 {
465 /*
466 * Once a detached thread has finished, its stack is deallocated and
467 * should no longer be taken into account when computing the conflict set.
468 */
469 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000470
bartbedfd232009-03-26 19:07:15 +0000471 /*
472 * For a detached thread, calling pthread_exit() invalidates the
473 * POSIX thread ID associated with the detached thread. For joinable
474 * POSIX threads however, the POSIX thread ID remains live after the
475 * pthread_exit() call until pthread_join() is called.
476 */
477 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
478 }
sewardjaf44c822007-11-25 14:01:38 +0000479}
480
bart9b2974a2008-09-27 12:35:31 +0000481/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000482void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000483{
bartbedfd232009-03-26 19:07:15 +0000484 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
485 && tid != DRD_INVALID_THREADID);
486 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000487
bartbedfd232009-03-26 19:07:15 +0000488 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000489}
490
barte7dff242009-04-23 17:12:39 +0000491/**
492 * Store the POSIX thread ID for the specified thread.
493 *
494 * @note This function can be called two times for the same thread -- see also
495 * the comment block preceding the pthread_create() wrapper in
496 * drd_pthread_intercepts.c.
497 */
bart62a784c2009-02-15 13:11:14 +0000498void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000499{
bartbedfd232009-03-26 19:07:15 +0000500 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
501 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000502 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
503 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000504 tl_assert(ptid != INVALID_POSIX_THREADID);
505 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
506 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000507}
508
bart86a87df2009-03-04 19:26:47 +0000509/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000510Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000511{
bartbedfd232009-03-26 19:07:15 +0000512 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
513 && tid != DRD_INVALID_THREADID);
514 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000515}
516
bart86a87df2009-03-04 19:26:47 +0000517/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000518void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000519{
bartbedfd232009-03-26 19:07:15 +0000520 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
521 && tid != DRD_INVALID_THREADID);
522 tl_assert(!! joinable == joinable);
523 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bart8f822af2009-06-08 18:20:42 +0000524
bartbedfd232009-03-26 19:07:15 +0000525 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000526}
527
bartdd75cdf2009-07-24 08:20:10 +0000528/** Tells DRD that the calling thread is about to enter pthread_create(). */
529void DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
530{
531 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
532 && tid != DRD_INVALID_THREADID);
533 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
534 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
535
536 DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
537}
538
539/** Tells DRD that the calling thread has left pthread_create(). */
540void DRD_(thread_left_pthread_create)(const DrdThreadId tid)
541{
542 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
543 && tid != DRD_INVALID_THREADID);
544 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
545 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
546
547 DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
548}
549
bartd45d9952009-05-31 18:53:54 +0000550/** Obtain the thread number and the user-assigned thread name. */
551const char* DRD_(thread_get_name)(const DrdThreadId tid)
552{
553 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
554 && tid != DRD_INVALID_THREADID);
555
556 return DRD_(g_threadinfo)[tid].name;
557}
558
559/** Set the name of the specified thread. */
560void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
561{
562 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
563 && tid != DRD_INVALID_THREADID);
564
565 if (name == NULL || name[0] == 0)
566 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
567 sizeof(DRD_(g_threadinfo)[tid].name),
568 "Thread %d",
569 tid);
570 else
571 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
572 sizeof(DRD_(g_threadinfo)[tid].name),
573 "Thread %d (%s)",
574 tid, name);
575 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
576}
577
bart86a87df2009-03-04 19:26:47 +0000578/**
579 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
580 * conflict set.
581 */
bart62a784c2009-02-15 13:11:14 +0000582void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000583{
bartbedfd232009-03-26 19:07:15 +0000584 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000585
bartbedfd232009-03-26 19:07:15 +0000586 if (vg_tid != s_vg_running_tid)
587 {
588 DRD_(thread_set_running_tid)(vg_tid,
589 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
590 }
sewardj8b09d4f2007-12-04 21:27:18 +0000591
bartbedfd232009-03-26 19:07:15 +0000592 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
593 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000594}
595
bart86a87df2009-03-04 19:26:47 +0000596/**
597 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
598 * conflict set.
599 */
bart62a784c2009-02-15 13:11:14 +0000600void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
601 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000602{
bartbedfd232009-03-26 19:07:15 +0000603 tl_assert(vg_tid != VG_INVALID_THREADID);
604 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000605
bartbedfd232009-03-26 19:07:15 +0000606 if (vg_tid != s_vg_running_tid)
607 {
608 if (s_trace_context_switches
609 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
610 {
611 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +0000612 "Context switch from thread %d to thread %d;"
sewardj1e29ebc2009-07-15 14:49:17 +0000613 " segments: %llu\n",
bart63c92ea2009-07-19 17:53:56 +0000614 DRD_(g_drd_running_tid), drd_tid,
bartbedfd232009-03-26 19:07:15 +0000615 DRD_(sg_get_segments_alive_count)());
616 }
617 s_vg_running_tid = vg_tid;
618 DRD_(g_drd_running_tid) = drd_tid;
619 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
620 s_context_switch_count++;
621 }
sewardj8b09d4f2007-12-04 21:27:18 +0000622
bartbedfd232009-03-26 19:07:15 +0000623 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
624 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000625}
626
bart86a87df2009-03-04 19:26:47 +0000627/**
628 * Increase the synchronization nesting counter. Must be called before the
629 * client calls a synchronization function.
630 */
bart62a784c2009-02-15 13:11:14 +0000631int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000632{
bartbedfd232009-03-26 19:07:15 +0000633 tl_assert(DRD_(IsValidDrdThreadId)(tid));
634 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000635}
636
bart86a87df2009-03-04 19:26:47 +0000637/**
638 * Decrease the synchronization nesting counter. Must be called after the
639 * client left a synchronization function.
640 */
bart62a784c2009-02-15 13:11:14 +0000641int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000642{
bartbedfd232009-03-26 19:07:15 +0000643 tl_assert(DRD_(IsValidDrdThreadId)(tid));
644 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
645 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000646}
647
bart86a87df2009-03-04 19:26:47 +0000648/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000649int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000650{
bartbedfd232009-03-26 19:07:15 +0000651 tl_assert(DRD_(IsValidDrdThreadId)(tid));
652 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000653}
654
bart1a473c72008-03-13 19:03:38 +0000655/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000656static
bart86a87df2009-03-04 19:26:47 +0000657void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000658{
bartbedfd232009-03-26 19:07:15 +0000659 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
660 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000661
662#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
663 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
664#endif
665
bartbedfd232009-03-26 19:07:15 +0000666 sg->prev = DRD_(g_threadinfo)[tid].last;
667 sg->next = 0;
668 if (DRD_(g_threadinfo)[tid].last)
669 DRD_(g_threadinfo)[tid].last->next = sg;
670 DRD_(g_threadinfo)[tid].last = sg;
671 if (DRD_(g_threadinfo)[tid].first == 0)
672 DRD_(g_threadinfo)[tid].first = sg;
bart8f822af2009-06-08 18:20:42 +0000673
674#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
675 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
676#endif
sewardjaf44c822007-11-25 14:01:38 +0000677}
678
bart324a23b2009-02-15 12:14:52 +0000679/**
680 * Remove a segment from the segment list of thread threadid, and free the
681 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000682 */
bart62a784c2009-02-15 13:11:14 +0000683static
bart86a87df2009-03-04 19:26:47 +0000684void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000685{
bartbedfd232009-03-26 19:07:15 +0000686 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
687 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000688
689#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
690 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
691#endif
bart26f73e12008-02-24 18:37:08 +0000692
bartbedfd232009-03-26 19:07:15 +0000693 if (sg->prev)
694 sg->prev->next = sg->next;
695 if (sg->next)
696 sg->next->prev = sg->prev;
697 if (sg == DRD_(g_threadinfo)[tid].first)
698 DRD_(g_threadinfo)[tid].first = sg->next;
699 if (sg == DRD_(g_threadinfo)[tid].last)
700 DRD_(g_threadinfo)[tid].last = sg->prev;
701 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000702
bart8f822af2009-06-08 18:20:42 +0000703#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
704 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
705#endif
sewardjaf44c822007-11-25 14:01:38 +0000706}
707
bart86a87df2009-03-04 19:26:47 +0000708/**
709 * Returns a pointer to the vector clock of the most recent segment associated
710 * with thread 'tid'.
711 */
bart62a784c2009-02-15 13:11:14 +0000712VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000713{
bartbedfd232009-03-26 19:07:15 +0000714 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
715 && tid != DRD_INVALID_THREADID);
716 tl_assert(DRD_(g_threadinfo)[tid].last);
717 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000718}
719
bart324a23b2009-02-15 12:14:52 +0000720/**
721 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000722 */
bart62a784c2009-02-15 13:11:14 +0000723void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000724{
bartbedfd232009-03-26 19:07:15 +0000725 tl_assert(sg);
726 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
727 && tid != DRD_INVALID_THREADID);
728 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000729
bartbedfd232009-03-26 19:07:15 +0000730 DRD_(sg_put)(*sg);
731 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000732}
733
sewardjaf44c822007-11-25 14:01:38 +0000734/**
735 * Compute the minimum of all latest vector clocks of all threads
736 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000737 *
sewardjaf44c822007-11-25 14:01:38 +0000738 * @param vc pointer to a vectorclock, holds result upon return.
739 */
bart62a784c2009-02-15 13:11:14 +0000740static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000741{
bartbedfd232009-03-26 19:07:15 +0000742 unsigned i;
743 Bool first;
744 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000745
bartbedfd232009-03-26 19:07:15 +0000746 first = True;
bart8f822af2009-06-08 18:20:42 +0000747 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000748 {
749 latest_sg = DRD_(g_threadinfo)[i].last;
750 if (latest_sg)
751 {
752 if (first)
753 DRD_(vc_assign)(vc, &latest_sg->vc);
754 else
755 DRD_(vc_min)(vc, &latest_sg->vc);
756 first = False;
757 }
758 }
sewardjaf44c822007-11-25 14:01:38 +0000759}
760
bart86a87df2009-03-04 19:26:47 +0000761/**
762 * Compute the maximum of all latest vector clocks of all threads.
763 *
764 * @param vc pointer to a vectorclock, holds result upon return.
765 */
bart62a784c2009-02-15 13:11:14 +0000766static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000767{
bartbedfd232009-03-26 19:07:15 +0000768 unsigned i;
769 Bool first;
770 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000771
bartbedfd232009-03-26 19:07:15 +0000772 first = True;
bart8f822af2009-06-08 18:20:42 +0000773 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000774 {
775 latest_sg = DRD_(g_threadinfo)[i].last;
776 if (latest_sg)
777 {
778 if (first)
779 DRD_(vc_assign)(vc, &latest_sg->vc);
780 else
781 DRD_(vc_combine)(vc, &latest_sg->vc);
782 first = False;
783 }
784 }
sewardjaf44c822007-11-25 14:01:38 +0000785}
786
787/**
bart5bd9f2d2008-03-03 20:31:58 +0000788 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000789 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000790 * data race.
791 */
bart8f822af2009-06-08 18:20:42 +0000792static void thread_discard_ordered_segments(void)
sewardjaf44c822007-11-25 14:01:38 +0000793{
bartbedfd232009-03-26 19:07:15 +0000794 unsigned i;
795 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000796
bartbedfd232009-03-26 19:07:15 +0000797 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000798
bartbedfd232009-03-26 19:07:15 +0000799 DRD_(vc_init)(&thread_vc_min, 0, 0);
800 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
801 if (DRD_(sg_get_trace)())
802 {
bart8f822af2009-06-08 18:20:42 +0000803 char *vc_min, *vc_max;
bartbedfd232009-03-26 19:07:15 +0000804 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000805
bartbedfd232009-03-26 19:07:15 +0000806 DRD_(vc_init)(&thread_vc_max, 0, 0);
807 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart8f822af2009-06-08 18:20:42 +0000808 vc_min = DRD_(vc_aprint)(&thread_vc_min);
809 vc_max = DRD_(vc_aprint)(&thread_vc_max);
810 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000811 "Discarding ordered segments -- min vc is %s, max vc is %s\n",
bart8f822af2009-06-08 18:20:42 +0000812 vc_min, vc_max);
813 VG_(free)(vc_min);
814 VG_(free)(vc_max);
bartbedfd232009-03-26 19:07:15 +0000815 DRD_(vc_cleanup)(&thread_vc_max);
816 }
sewardjaf44c822007-11-25 14:01:38 +0000817
bart8f822af2009-06-08 18:20:42 +0000818 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000819 {
820 Segment* sg;
821 Segment* sg_next;
822 for (sg = DRD_(g_threadinfo)[i].first;
823 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
824 sg = sg_next)
825 {
826 thread_discard_segment(i, sg);
827 }
828 }
829 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000830}
831
bart324a23b2009-02-15 12:14:52 +0000832/**
bart8f822af2009-06-08 18:20:42 +0000833 * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
834 * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
835 * all segments in the set CS are ordered consistently against both sg1 and
836 * sg2. The set CS is defined as the set of segments that can immediately
837 * precede future segments via inter-thread synchronization operations. In
838 * DRD the set CS consists of the latest segment of each thread combined with
839 * all segments for which the reference count is strictly greater than one.
840 * The code below is an optimized version of the following:
841 *
842 * for (i = 0; i < DRD_N_THREADS; i++)
843 * {
844 * Segment* sg;
845 *
846 * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
847 * {
848 * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
849 * {
850 * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
851 * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
852 * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
853 * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
854 * {
855 * return False;
856 * }
857 * }
858 * }
859 * }
860 */
861static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
862 Segment* const sg1,
863 Segment* const sg2)
864{
865 unsigned i;
866
867 tl_assert(sg1->next);
868 tl_assert(sg2->next);
869 tl_assert(sg1->next == sg2);
870 tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
871
872 for (i = 0; i < DRD_N_THREADS; i++)
873 {
874 Segment* sg;
875
876 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
877 {
878 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
879 {
880 if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
881 break;
882 if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
883 return False;
884 }
885 }
886 for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
887 {
888 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
889 {
890 if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
891 break;
892 if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
893 return False;
894 }
895 }
896 }
897 return True;
898}
899
900/**
bart324a23b2009-02-15 12:14:52 +0000901 * Merge all segments that may be merged without triggering false positives
902 * or discarding real data races. For the theoretical background of segment
bart8f822af2009-06-08 18:20:42 +0000903 * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
904 * and Koen De Bosschere. Bounding the number of segment histories during
905 * data race detection. Parallel Computing archive, Volume 28, Issue 9,
906 * pp 1221-1238, September 2002. This paper contains a proof that merging
907 * consecutive segments for which the property equiv(s1,s2) holds can be
908 * merged without reducing the accuracy of datarace detection. Furthermore
909 * it is also proven that the total number of all segments will never grow
910 * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
911 * every time a new segment is created. The property equiv(s1, s2) is defined
912 * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
913 * clocks of segments s and s1 are ordered in the same way as those of segments
914 * s and s2. The set CS is defined as the set of existing segments s that have
915 * the potential to conflict with not yet created segments, either because the
916 * segment s is the latest segment of a thread or because it can become the
917 * immediate predecessor of a new segment due to a synchronization operation.
barta9c37392008-03-22 09:38:48 +0000918 */
919static void thread_merge_segments(void)
920{
bartbedfd232009-03-26 19:07:15 +0000921 unsigned i;
barta9c37392008-03-22 09:38:48 +0000922
bart8f822af2009-06-08 18:20:42 +0000923 s_new_segments_since_last_merge = 0;
924
925 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000926 {
927 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000928
bart8f822af2009-06-08 18:20:42 +0000929#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
930 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
931#endif
barta9c37392008-03-22 09:38:48 +0000932
bartbedfd232009-03-26 19:07:15 +0000933 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000934 {
bartbedfd232009-03-26 19:07:15 +0000935 if (DRD_(sg_get_refcnt)(sg) == 1
936 && sg->next
937 && DRD_(sg_get_refcnt)(sg->next) == 1
bart8f822af2009-06-08 18:20:42 +0000938 && sg->next->next
939 && thread_consistent_segment_ordering(i, sg, sg->next))
bartbedfd232009-03-26 19:07:15 +0000940 {
941 /* Merge sg and sg->next into sg. */
942 DRD_(sg_merge)(sg, sg->next);
943 thread_discard_segment(i, sg->next);
944 }
barta9c37392008-03-22 09:38:48 +0000945 }
barta9c37392008-03-22 09:38:48 +0000946
bart8f822af2009-06-08 18:20:42 +0000947#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
948 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
949#endif
bartbedfd232009-03-26 19:07:15 +0000950 }
barta9c37392008-03-22 09:38:48 +0000951}
952
bart324a23b2009-02-15 12:14:52 +0000953/**
bart324a23b2009-02-15 12:14:52 +0000954 * Create a new segment for the specified thread, and discard any segments
955 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000956 */
bart62a784c2009-02-15 13:11:14 +0000957void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000958{
bart8f822af2009-06-08 18:20:42 +0000959 Segment* last_sg;
bartbedfd232009-03-26 19:07:15 +0000960 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +0000961
bartbedfd232009-03-26 19:07:15 +0000962 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
963 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000964 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000965
bart8f822af2009-06-08 18:20:42 +0000966 last_sg = DRD_(g_threadinfo)[tid].last;
bartbedfd232009-03-26 19:07:15 +0000967 new_sg = DRD_(sg_new)(tid, tid);
968 thread_append_segment(tid, new_sg);
bart8f822af2009-06-08 18:20:42 +0000969 if (tid == DRD_(g_drd_running_tid) && last_sg)
barte5214662009-06-21 11:51:23 +0000970 {
bart8f822af2009-06-08 18:20:42 +0000971 DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
barte5214662009-06-21 11:51:23 +0000972 s_update_conflict_set_new_sg_count++;
973 }
bartd66e3a82008-04-06 15:02:17 +0000974
bart8f822af2009-06-08 18:20:42 +0000975 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +0000976
bart8f822af2009-06-08 18:20:42 +0000977 if (s_segment_merging
978 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
bartbedfd232009-03-26 19:07:15 +0000979 {
bart8f822af2009-06-08 18:20:42 +0000980 thread_discard_ordered_segments();
bartbedfd232009-03-26 19:07:15 +0000981 thread_merge_segments();
982 }
sewardjaf44c822007-11-25 14:01:38 +0000983}
984
bart26f73e12008-02-24 18:37:08 +0000985/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart8f822af2009-06-08 18:20:42 +0000986void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000987{
bartbedfd232009-03-26 19:07:15 +0000988 tl_assert(joiner != joinee);
989 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
990 && joiner != DRD_INVALID_THREADID);
991 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
992 && joinee != DRD_INVALID_THREADID);
993 tl_assert(DRD_(g_threadinfo)[joiner].last);
994 tl_assert(DRD_(g_threadinfo)[joinee].last);
bart8f822af2009-06-08 18:20:42 +0000995
996 if (DRD_(sg_get_trace)())
997 {
998 char *str1, *str2;
999 str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
1000 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001001 VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
bart8f822af2009-06-08 18:20:42 +00001002 str1, str2);
1003 VG_(free)(str1);
1004 VG_(free)(str2);
1005 }
barte5214662009-06-21 11:51:23 +00001006 if (joiner == DRD_(g_drd_running_tid))
1007 {
1008 VectorClock old_vc;
1009
1010 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[joiner].last->vc);
1011 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001012 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001013 DRD_(thread_update_conflict_set)(joiner, &old_vc);
1014 s_update_conflict_set_join_count++;
1015 DRD_(vc_cleanup)(&old_vc);
1016 }
1017 else
1018 {
1019 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001020 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001021 }
1022
1023 thread_discard_ordered_segments();
1024
bart8f822af2009-06-08 18:20:42 +00001025 if (DRD_(sg_get_trace)())
1026 {
1027 char* str;
1028 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001029 VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
bart8f822af2009-06-08 18:20:42 +00001030 VG_(free)(str);
1031 }
sewardjaf44c822007-11-25 14:01:38 +00001032}
1033
bart324a23b2009-02-15 12:14:52 +00001034/**
bart8f822af2009-06-08 18:20:42 +00001035 * Update the vector clock of the last segment of thread tid with the
bartf6ec1fe2009-06-21 18:07:35 +00001036 * the vector clock of segment sg.
bart26f73e12008-02-24 18:37:08 +00001037 */
bartf6ec1fe2009-06-21 18:07:35 +00001038static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
sewardjaf44c822007-11-25 14:01:38 +00001039{
bart8f822af2009-06-08 18:20:42 +00001040 const VectorClock* const vc = &sg->vc;
1041
bartbedfd232009-03-26 19:07:15 +00001042 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1043 && tid != DRD_INVALID_THREADID);
1044 tl_assert(DRD_(g_threadinfo)[tid].last);
bart8f822af2009-06-08 18:20:42 +00001045 tl_assert(sg);
bartbedfd232009-03-26 19:07:15 +00001046 tl_assert(vc);
bart8f822af2009-06-08 18:20:42 +00001047
1048 if (tid != sg->tid)
1049 {
1050 VectorClock old_vc;
1051
1052 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
1053 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
1054 if (DRD_(sg_get_trace)())
1055 {
1056 char *str1, *str2;
1057 str1 = DRD_(vc_aprint)(&old_vc);
1058 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001059 VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
bart8f822af2009-06-08 18:20:42 +00001060 VG_(free)(str1);
1061 VG_(free)(str2);
1062 }
barte5214662009-06-21 11:51:23 +00001063
bart8f822af2009-06-08 18:20:42 +00001064 thread_discard_ordered_segments();
barte5214662009-06-21 11:51:23 +00001065
bart8f822af2009-06-08 18:20:42 +00001066 DRD_(thread_update_conflict_set)(tid, &old_vc);
barte5214662009-06-21 11:51:23 +00001067 s_update_conflict_set_sync_count++;
1068
bart8f822af2009-06-08 18:20:42 +00001069 DRD_(vc_cleanup)(&old_vc);
1070 }
1071 else
1072 {
1073 tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
1074 }
sewardjaf44c822007-11-25 14:01:38 +00001075}
1076
bart324a23b2009-02-15 12:14:52 +00001077/**
bartf6ec1fe2009-06-21 18:07:35 +00001078 * Create a new segment for thread tid and update the vector clock of the last
1079 * segment of this thread with the the vector clock of segment sg. Call this
1080 * function after thread tid had to wait because of thread synchronization
1081 * until the memory accesses in the segment sg finished.
1082 */
1083void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
1084{
1085 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1086 && tid != DRD_INVALID_THREADID);
1087 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1088 tl_assert(sg);
1089
1090 thread_append_segment(tid, DRD_(sg_new)(tid, tid));
1091
1092 thread_combine_vc_sync(tid, sg);
1093
1094 if (s_segment_merging
1095 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1096 {
1097 thread_discard_ordered_segments();
1098 thread_merge_segments();
1099 }
1100}
1101
1102/**
bart324a23b2009-02-15 12:14:52 +00001103 * Call this function whenever a thread is no longer using the memory
1104 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1105 * increase.
bart26f73e12008-02-24 18:37:08 +00001106 */
bart62a784c2009-02-15 13:11:14 +00001107void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +00001108{
bartbedfd232009-03-26 19:07:15 +00001109 DrdThreadId other_user;
1110 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001111
bartbedfd232009-03-26 19:07:15 +00001112 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
1113 other_user = DRD_INVALID_THREADID;
bart8f822af2009-06-08 18:20:42 +00001114 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001115 {
1116 Segment* p;
1117 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +00001118 {
bartbedfd232009-03-26 19:07:15 +00001119 if (other_user == DRD_INVALID_THREADID
1120 && i != DRD_(g_drd_running_tid))
1121 {
bart8f822af2009-06-08 18:20:42 +00001122 if (UNLIKELY(DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2)))
bartbedfd232009-03-26 19:07:15 +00001123 {
1124 other_user = i;
1125 }
1126 continue;
1127 }
bart8f822af2009-06-08 18:20:42 +00001128 DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
sewardjaf44c822007-11-25 14:01:38 +00001129 }
bartbedfd232009-03-26 19:07:15 +00001130 }
sewardjaf44c822007-11-25 14:01:38 +00001131
bartbedfd232009-03-26 19:07:15 +00001132 /*
1133 * If any other thread had accessed memory in [ a1, a2 [, update the
1134 * conflict set.
1135 */
1136 if (other_user != DRD_INVALID_THREADID
1137 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
1138 {
1139 thread_compute_conflict_set(&DRD_(g_conflict_set),
1140 DRD_(thread_get_running_tid)());
1141 }
sewardjaf44c822007-11-25 14:01:38 +00001142}
1143
bartd45d9952009-05-31 18:53:54 +00001144/** Specify whether memory loads should be recorded. */
1145void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001146{
bartbedfd232009-03-26 19:07:15 +00001147 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1148 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001149 tl_assert(enabled == !! enabled);
1150
1151 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +00001152}
1153
bartd45d9952009-05-31 18:53:54 +00001154/** Specify whether memory stores should be recorded. */
1155void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001156{
bartbedfd232009-03-26 19:07:15 +00001157 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1158 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001159 tl_assert(enabled == !! enabled);
1160
1161 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +00001162}
1163
bart86a87df2009-03-04 19:26:47 +00001164/**
1165 * Print the segment information for all threads.
1166 *
1167 * This function is only used for debugging purposes.
1168 */
bart62a784c2009-02-15 13:11:14 +00001169void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +00001170{
bartbedfd232009-03-26 19:07:15 +00001171 unsigned i;
1172 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001173
bart8f822af2009-06-08 18:20:42 +00001174 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001175 {
1176 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +00001177 {
bartbedfd232009-03-26 19:07:15 +00001178 VG_(printf)("**************\n"
1179 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
1180 "**************\n",
1181 i,
1182 DRD_(g_threadinfo)[i].vg_thread_exists,
1183 DRD_(g_threadinfo)[i].vg_threadid,
1184 DRD_(g_threadinfo)[i].posix_thread_exists,
1185 DRD_(g_threadinfo)[i].pt_threadid,
1186 DRD_(g_threadinfo)[i].detached_posix_thread);
1187 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1188 {
1189 DRD_(sg_print)(p);
1190 }
sewardjaf44c822007-11-25 14:01:38 +00001191 }
bartbedfd232009-03-26 19:07:15 +00001192 }
sewardjaf44c822007-11-25 14:01:38 +00001193}
1194
bart86a87df2009-03-04 19:26:47 +00001195/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001196static void show_call_stack(const DrdThreadId tid,
1197 const Char* const msg,
1198 ExeContext* const callstack)
1199{
bartbedfd232009-03-26 19:07:15 +00001200 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +00001201
bart63c92ea2009-07-19 17:53:56 +00001202 VG_(message)(Vg_UserMsg, "%s (thread %d)\n", msg, tid);
sewardjaf44c822007-11-25 14:01:38 +00001203
bartbedfd232009-03-26 19:07:15 +00001204 if (vg_tid != VG_INVALID_THREADID)
1205 {
1206 if (callstack)
1207 {
1208 VG_(pp_ExeContext)(callstack);
1209 }
1210 else
1211 {
1212 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1213 }
1214 }
1215 else
1216 {
1217 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001218 " (thread finished, call stack no longer available)\n");
bartbedfd232009-03-26 19:07:15 +00001219 }
sewardjaf44c822007-11-25 14:01:38 +00001220}
1221
bart86a87df2009-03-04 19:26:47 +00001222/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001223static void
1224thread_report_conflicting_segments_segment(const DrdThreadId tid,
1225 const Addr addr,
1226 const SizeT size,
1227 const BmAccessTypeT access_type,
1228 const Segment* const p)
1229{
bartbedfd232009-03-26 19:07:15 +00001230 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001231
bartbedfd232009-03-26 19:07:15 +00001232 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1233 && tid != DRD_INVALID_THREADID);
1234 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001235
bart8f822af2009-06-08 18:20:42 +00001236 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001237 {
1238 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001239 {
bartbedfd232009-03-26 19:07:15 +00001240 Segment* q;
1241 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1242 {
1243 /*
1244 * Since q iterates over the segments of thread i in order of
1245 * decreasing vector clocks, if q->vc <= p->vc, then
1246 * q->next->vc <= p->vc will also hold. Hence, break out of the
1247 * loop once this condition is met.
1248 */
1249 if (DRD_(vc_lte)(&q->vc, &p->vc))
1250 break;
1251 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1252 {
bart8f822af2009-06-08 18:20:42 +00001253 if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
bartbedfd232009-03-26 19:07:15 +00001254 access_type))
1255 {
1256 tl_assert(q->stacktrace);
1257 show_call_stack(i, "Other segment start",
1258 q->stacktrace);
1259 show_call_stack(i, "Other segment end",
1260 q->next ? q->next->stacktrace : 0);
1261 }
1262 }
1263 }
sewardjaf44c822007-11-25 14:01:38 +00001264 }
bartbedfd232009-03-26 19:07:15 +00001265 }
sewardjaf44c822007-11-25 14:01:38 +00001266}
1267
bart86a87df2009-03-04 19:26:47 +00001268/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001269void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1270 const Addr addr,
1271 const SizeT size,
1272 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001273{
bartbedfd232009-03-26 19:07:15 +00001274 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001275
bartbedfd232009-03-26 19:07:15 +00001276 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1277 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001278
bartbedfd232009-03-26 19:07:15 +00001279 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1280 {
bart8f822af2009-06-08 18:20:42 +00001281 if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
bartbedfd232009-03-26 19:07:15 +00001282 {
1283 thread_report_conflicting_segments_segment(tid, addr, size,
1284 access_type, p);
1285 }
1286 }
sewardjaf44c822007-11-25 14:01:38 +00001287}
sewardjaf44c822007-11-25 14:01:38 +00001288
bart324a23b2009-02-15 12:14:52 +00001289/**
bart8f822af2009-06-08 18:20:42 +00001290 * Verify whether the conflict set for thread tid is up to date. Only perform
1291 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1292 */
1293static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1294{
1295 static int do_verify_conflict_set = -1;
1296 Bool result;
1297 struct bitmap* computed_conflict_set = 0;
1298
1299 if (do_verify_conflict_set < 0)
1300 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1301
1302 if (do_verify_conflict_set == 0)
1303 return True;
1304
1305 thread_compute_conflict_set(&computed_conflict_set, tid);
1306 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1307 if (! result)
1308 {
1309 VG_(printf)("actual conflict set:\n");
1310 DRD_(bm_print)(DRD_(g_conflict_set));
1311 VG_(printf)("\n");
1312 VG_(printf)("computed conflict set:\n");
1313 DRD_(bm_print)(computed_conflict_set);
1314 VG_(printf)("\n");
1315 }
1316 DRD_(bm_delete)(computed_conflict_set);
1317 return result;
1318}
1319
1320/**
1321 * Compute the conflict set: a bitmap that represents the union of all memory
1322 * accesses of all segments that are unordered to the current segment of the
1323 * thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001324 */
bart86a87df2009-03-04 19:26:47 +00001325static void thread_compute_conflict_set(struct bitmap** conflict_set,
1326 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001327{
bartbedfd232009-03-26 19:07:15 +00001328 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001329
bartbedfd232009-03-26 19:07:15 +00001330 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1331 && tid != DRD_INVALID_THREADID);
1332 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001333
bart54803fe2009-06-21 09:26:27 +00001334 s_compute_conflict_set_count++;
bartbedfd232009-03-26 19:07:15 +00001335 s_conflict_set_bitmap_creation_count
1336 -= DRD_(bm_get_bitmap_creation_count)();
1337 s_conflict_set_bitmap2_creation_count
1338 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001339
bartbedfd232009-03-26 19:07:15 +00001340 if (*conflict_set)
1341 {
bartf6ec1fe2009-06-21 18:07:35 +00001342 DRD_(bm_cleanup)(*conflict_set);
1343 DRD_(bm_init)(*conflict_set);
bartbedfd232009-03-26 19:07:15 +00001344 }
bartf6ec1fe2009-06-21 18:07:35 +00001345 else
1346 {
1347 *conflict_set = DRD_(bm_new)();
1348 }
bart26f73e12008-02-24 18:37:08 +00001349
bartbedfd232009-03-26 19:07:15 +00001350 if (s_trace_conflict_set)
1351 {
bart8f822af2009-06-08 18:20:42 +00001352 char* str;
bart26f73e12008-02-24 18:37:08 +00001353
bart8f822af2009-06-08 18:20:42 +00001354 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1355 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001356 "computing conflict set for thread %d with vc %s\n",
1357 tid, str);
bart8f822af2009-06-08 18:20:42 +00001358 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001359 }
sewardjaf44c822007-11-25 14:01:38 +00001360
bartbedfd232009-03-26 19:07:15 +00001361 p = DRD_(g_threadinfo)[tid].last;
1362 {
1363 unsigned j;
1364
1365 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001366 {
bart8f822af2009-06-08 18:20:42 +00001367 char* vc;
bartbedfd232009-03-26 19:07:15 +00001368
bart8f822af2009-06-08 18:20:42 +00001369 vc = DRD_(vc_aprint)(&p->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001370 VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
bart8f822af2009-06-08 18:20:42 +00001371 tid, vc);
1372 VG_(free)(vc);
bart26f73e12008-02-24 18:37:08 +00001373 }
sewardjaf44c822007-11-25 14:01:38 +00001374
bart8f822af2009-06-08 18:20:42 +00001375 for (j = 0; j < DRD_N_THREADS; j++)
bartbedfd232009-03-26 19:07:15 +00001376 {
1377 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1378 {
bart8f822af2009-06-08 18:20:42 +00001379 Segment* q;
bartbedfd232009-03-26 19:07:15 +00001380 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1381 {
1382 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1383 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1384 {
1385 if (s_trace_conflict_set)
1386 {
bart8f822af2009-06-08 18:20:42 +00001387 char* str;
1388
1389 str = DRD_(vc_aprint)(&q->vc);
1390 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001391 "conflict set: [%d] merging segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001392 j, str);
1393 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001394 }
bart8f822af2009-06-08 18:20:42 +00001395 DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
bartbedfd232009-03-26 19:07:15 +00001396 }
1397 else
1398 {
1399 if (s_trace_conflict_set)
1400 {
bart8f822af2009-06-08 18:20:42 +00001401 char* str;
1402
1403 str = DRD_(vc_aprint)(&q->vc);
1404 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001405 "conflict set: [%d] ignoring segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001406 j, str);
1407 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001408 }
1409 }
1410 }
1411 }
1412 }
1413 }
sewardjaf44c822007-11-25 14:01:38 +00001414
bartbedfd232009-03-26 19:07:15 +00001415 s_conflict_set_bitmap_creation_count
1416 += DRD_(bm_get_bitmap_creation_count)();
1417 s_conflict_set_bitmap2_creation_count
1418 += DRD_(bm_get_bitmap2_creation_count)();
1419
bart8f822af2009-06-08 18:20:42 +00001420 if (s_trace_conflict_set_bm)
bartbedfd232009-03-26 19:07:15 +00001421 {
sewardj1e29ebc2009-07-15 14:49:17 +00001422 VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
bartbedfd232009-03-26 19:07:15 +00001423 DRD_(bm_print)(*conflict_set);
sewardj1e29ebc2009-07-15 14:49:17 +00001424 VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
bartbedfd232009-03-26 19:07:15 +00001425 }
sewardjaf44c822007-11-25 14:01:38 +00001426}
1427
bart8f822af2009-06-08 18:20:42 +00001428/**
1429 * Update the conflict set after the vector clock of thread tid has been
1430 * updated from old_vc to its current value, either because a new segment has
1431 * been created or because of a synchronization operation.
1432 */
1433void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1434 const VectorClock* const old_vc)
1435{
1436 const VectorClock* new_vc;
1437 Segment* p;
1438 unsigned j;
1439
1440 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1441 && tid != DRD_INVALID_THREADID);
1442 tl_assert(old_vc);
1443 tl_assert(tid == DRD_(g_drd_running_tid));
1444 tl_assert(DRD_(g_conflict_set));
1445
1446 if (s_trace_conflict_set)
1447 {
1448 char* str;
1449
1450 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1451 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001452 "updating conflict set for thread %d with vc %s\n",
1453 tid, str);
bart8f822af2009-06-08 18:20:42 +00001454 VG_(free)(str);
1455 }
1456
1457 new_vc = &DRD_(g_threadinfo)[tid].last->vc;
1458
1459 DRD_(bm_unmark)(DRD_(g_conflict_set));
1460
1461 for (j = 0; j < DRD_N_THREADS; j++)
1462 {
1463 Segment* q;
1464
1465 if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1466 continue;
1467
1468 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1469 {
1470 const int included_in_old_conflict_set
1471 = ! DRD_(vc_lte)(&q->vc, old_vc)
1472 && ! DRD_(vc_lte)(old_vc, &q->vc);
1473 const int included_in_new_conflict_set
1474 = ! DRD_(vc_lte)(&q->vc, new_vc)
1475 && ! DRD_(vc_lte)(new_vc, &q->vc);
1476 if (included_in_old_conflict_set != included_in_new_conflict_set)
1477 {
1478 if (s_trace_conflict_set)
1479 {
1480 char* str;
1481
1482 str = DRD_(vc_aprint)(&q->vc);
1483 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001484 "conflict set: [%d] merging segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001485 VG_(free)(str);
1486 }
1487 DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1488 }
1489 else
1490 {
1491 if (s_trace_conflict_set)
1492 {
1493 char* str;
1494
1495 str = DRD_(vc_aprint)(&q->vc);
1496 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001497 "conflict set: [%d] ignoring segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001498 VG_(free)(str);
1499 }
1500 }
1501 }
1502 }
1503
1504 DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1505
1506 p = DRD_(g_threadinfo)[tid].last;
1507 {
1508 for (j = 0; j < DRD_N_THREADS; j++)
1509 {
1510 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1511 {
1512 Segment* q;
1513 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1514 {
1515 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1516 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1517 {
1518 DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1519 }
1520 }
1521 }
1522 }
1523 }
1524
1525 DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1526
bart54803fe2009-06-21 09:26:27 +00001527 s_update_conflict_set_count++;
bart8f822af2009-06-08 18:20:42 +00001528
1529 if (s_trace_conflict_set_bm)
1530 {
sewardj1e29ebc2009-07-15 14:49:17 +00001531 VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
bart8f822af2009-06-08 18:20:42 +00001532 DRD_(bm_print)(DRD_(g_conflict_set));
sewardj1e29ebc2009-07-15 14:49:17 +00001533 VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
bart8f822af2009-06-08 18:20:42 +00001534 }
1535
1536 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1537}
1538
bart86a87df2009-03-04 19:26:47 +00001539/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001540ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001541{
bartbedfd232009-03-26 19:07:15 +00001542 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001543}
1544
bart86a87df2009-03-04 19:26:47 +00001545/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001546ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001547{
bartbedfd232009-03-26 19:07:15 +00001548 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001549}
1550
bart54803fe2009-06-21 09:26:27 +00001551/** Return how many times the conflict set has been updated entirely. */
1552ULong DRD_(thread_get_compute_conflict_set_count)()
sewardjaf44c822007-11-25 14:01:38 +00001553{
bart54803fe2009-06-21 09:26:27 +00001554 return s_compute_conflict_set_count;
1555}
1556
1557/** Return how many times the conflict set has been updated partially. */
1558ULong DRD_(thread_get_update_conflict_set_count)(void)
1559{
bartbedfd232009-03-26 19:07:15 +00001560 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001561}
1562
bart86a87df2009-03-04 19:26:47 +00001563/**
barte5214662009-06-21 11:51:23 +00001564 * Return how many times the conflict set has been updated partially
1565 * because a new segment has been created.
1566 */
1567ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
1568{
1569 return s_update_conflict_set_new_sg_count;
1570}
1571
1572/**
1573 * Return how many times the conflict set has been updated partially
1574 * because of combining vector clocks due to synchronization operations
1575 * other than reader/writer lock or barrier operations.
1576 */
1577ULong DRD_(thread_get_update_conflict_set_sync_count)(void)
1578{
1579 return s_update_conflict_set_sync_count;
1580}
1581
1582/**
1583 * Return how many times the conflict set has been updated partially
1584 * because of thread joins.
1585 */
1586ULong DRD_(thread_get_update_conflict_set_join_count)(void)
1587{
1588 return s_update_conflict_set_join_count;
1589}
1590
1591/**
bart86a87df2009-03-04 19:26:47 +00001592 * Return the number of first-level bitmaps that have been created during
1593 * conflict set updates.
1594 */
bart62a784c2009-02-15 13:11:14 +00001595ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001596{
bartbedfd232009-03-26 19:07:15 +00001597 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001598}
1599
bart86a87df2009-03-04 19:26:47 +00001600/**
1601 * Return the number of second-level bitmaps that have been created during
1602 * conflict set updates.
1603 */
bart62a784c2009-02-15 13:11:14 +00001604ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001605{
bartbedfd232009-03-26 19:07:15 +00001606 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001607}