blob: 11c5ca8201534c8f6974b3463ea9ec5b2c6beed9 [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
bart876cafd2010-10-10 18:07:31 +00005 Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
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, "");
bart383d6132010-09-02 14:43:18 +0000184 DRD_(g_threadinfo)[i].on_alt_stack = False;
bartd45d9952009-05-31 18:53:54 +0000185 DRD_(g_threadinfo)[i].is_recording_loads = True;
186 DRD_(g_threadinfo)[i].is_recording_stores = True;
bartdd75cdf2009-07-24 08:20:10 +0000187 DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
bartbedfd232009-03-26 19:07:15 +0000188 DRD_(g_threadinfo)[i].synchr_nesting = 0;
189 tl_assert(DRD_(g_threadinfo)[i].first == 0);
190 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000191
bartbedfd232009-03-26 19:07:15 +0000192 tl_assert(DRD_(IsValidDrdThreadId)(i));
bart86a87df2009-03-04 19:26:47 +0000193
bartbedfd232009-03-26 19:07:15 +0000194 return i;
195 }
196 }
sewardjaf44c822007-11-25 14:01:38 +0000197
bart3c9afb12009-07-24 11:11:30 +0000198 VG_(printf)(
199"\nSorry, but the maximum number of threads supported by DRD has been exceeded."
200"Aborting.\n");
201
bartbedfd232009-03-26 19:07:15 +0000202 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000203
bartbedfd232009-03-26 19:07:15 +0000204 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000205}
206
bart86a87df2009-03-04 19:26:47 +0000207/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000208DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000209{
bartbedfd232009-03-26 19:07:15 +0000210 int i;
sewardjaf44c822007-11-25 14:01:38 +0000211
bartb48bde22009-07-31 08:26:17 +0000212 if (tid != INVALID_POSIX_THREADID)
bartbedfd232009-03-26 19:07:15 +0000213 {
bartb48bde22009-07-31 08:26:17 +0000214 for (i = 1; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000215 {
bartb48bde22009-07-31 08:26:17 +0000216 if (DRD_(g_threadinfo)[i].posix_thread_exists
217 && DRD_(g_threadinfo)[i].pt_threadid == tid)
218 {
219 return i;
220 }
bartbedfd232009-03-26 19:07:15 +0000221 }
222 }
223 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000224}
225
bart86a87df2009-03-04 19:26:47 +0000226/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000227ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000228{
bartbedfd232009-03-26 19:07:15 +0000229 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
230 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000231
bartbedfd232009-03-26 19:07:15 +0000232 return (DRD_(g_threadinfo)[tid].vg_thread_exists
233 ? DRD_(g_threadinfo)[tid].vg_threadid
234 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000235}
236
bart8f822af2009-06-08 18:20:42 +0000237#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart324a23b2009-02-15 12:14:52 +0000238/**
239 * Sanity check of the doubly linked list of segments referenced by a
240 * ThreadInfo struct.
241 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000242 */
bart62a784c2009-02-15 13:11:14 +0000243static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000244{
bartbedfd232009-03-26 19:07:15 +0000245 Segment* p;
bart8f822af2009-06-08 18:20:42 +0000246
bartbedfd232009-03-26 19:07:15 +0000247 for (p = ti->first; p; p = p->next) {
248 if (p->next && p->next->prev != p)
249 return False;
250 if (p->next == 0 && p != ti->last)
251 return False;
252 }
253 for (p = ti->last; p; p = p->prev) {
254 if (p->prev && p->prev->next != p)
255 return False;
256 if (p->prev == 0 && p != ti->first)
257 return False;
258 }
259 return True;
sewardjaf44c822007-11-25 14:01:38 +0000260}
bart23d3a4e2008-04-05 12:53:00 +0000261#endif
sewardjaf44c822007-11-25 14:01:38 +0000262
bart439c55f2009-02-15 10:38:37 +0000263/**
264 * Create the first segment for a newly started thread.
265 *
266 * This function is called from the handler installed via
267 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
268 * from the context of the creator thread, before the new thread has been
269 * created.
bart86a87df2009-03-04 19:26:47 +0000270 *
271 * @param[in] creator DRD thread ID of the creator thread.
272 * @param[in] vg_created Valgrind thread ID of the created thread.
273 *
274 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000275 */
bart62a784c2009-02-15 13:11:14 +0000276DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
277 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000278{
bartbedfd232009-03-26 19:07:15 +0000279 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000280
bartbedfd232009-03-26 19:07:15 +0000281 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
282 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
283 tl_assert(0 <= (int)created && created < DRD_N_THREADS
284 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000285
bartbedfd232009-03-26 19:07:15 +0000286 tl_assert(DRD_(g_threadinfo)[created].first == 0);
287 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart8f822af2009-06-08 18:20:42 +0000288 /* Create an initial segment for the newly created thread. */
bartbedfd232009-03-26 19:07:15 +0000289 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000290
bartbedfd232009-03-26 19:07:15 +0000291 return created;
sewardjaf44c822007-11-25 14:01:38 +0000292}
293
bart439c55f2009-02-15 10:38:37 +0000294/**
bart86a87df2009-03-04 19:26:47 +0000295 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
296 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000297 * on the newly created thread, e.g. from the handler installed via
298 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000299 *
300 * @param[in] vg_created Valgrind thread ID of the newly created thread.
301 *
302 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000303 */
bart62a784c2009-02-15 13:11:14 +0000304DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000305{
bartbedfd232009-03-26 19:07:15 +0000306 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000307
bartbedfd232009-03-26 19:07:15 +0000308 tl_assert(0 <= (int)created && created < DRD_N_THREADS
309 && created != DRD_INVALID_THREADID);
bart439c55f2009-02-15 10:38:37 +0000310
bartbedfd232009-03-26 19:07:15 +0000311 DRD_(g_threadinfo)[created].stack_max
312 = VG_(thread_get_stack_max)(vg_created);
313 DRD_(g_threadinfo)[created].stack_startup
314 = DRD_(g_threadinfo)[created].stack_max;
315 DRD_(g_threadinfo)[created].stack_min
316 = DRD_(g_threadinfo)[created].stack_max;
317 DRD_(g_threadinfo)[created].stack_min_min
318 = DRD_(g_threadinfo)[created].stack_max;
319 DRD_(g_threadinfo)[created].stack_size
320 = VG_(thread_get_stack_size)(vg_created);
321 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000322
bartbedfd232009-03-26 19:07:15 +0000323 return created;
bart439c55f2009-02-15 10:38:37 +0000324}
bart09dc13f2009-02-14 15:13:31 +0000325
bart324a23b2009-02-15 12:14:52 +0000326/**
327 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
328 * after thread drd_joiner joined thread drd_joinee.
329 */
bart09dc13f2009-02-14 15:13:31 +0000330void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
331{
bartbedfd232009-03-26 19:07:15 +0000332 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
333 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
bart7627be32009-06-06 12:26:05 +0000334
bartbedfd232009-03-26 19:07:15 +0000335 DRD_(thread_new_segment)(drd_joiner);
bart8f822af2009-06-08 18:20:42 +0000336 DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
bart7627be32009-06-06 12:26:05 +0000337 DRD_(thread_new_segment)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000338
bartbedfd232009-03-26 19:07:15 +0000339 if (s_trace_fork_join)
340 {
341 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
bartbedfd232009-03-26 19:07:15 +0000342 const unsigned msg_size = 256;
343 char* msg;
bart09dc13f2009-02-14 15:13:31 +0000344
bartbedfd232009-03-26 19:07:15 +0000345 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
346 tl_assert(msg);
347 VG_(snprintf)(msg, msg_size,
bart63c92ea2009-07-19 17:53:56 +0000348 "drd_post_thread_join joiner = %d, joinee = %d",
349 drd_joiner, drd_joinee);
bartbedfd232009-03-26 19:07:15 +0000350 if (joiner)
351 {
bart8f822af2009-06-08 18:20:42 +0000352 char* vc;
353
354 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
bartbedfd232009-03-26 19:07:15 +0000355 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart8f822af2009-06-08 18:20:42 +0000356 ", new vc: %s", vc);
357 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000358 }
sewardj1e29ebc2009-07-15 14:49:17 +0000359 VG_(message)(Vg_DebugMsg, "%s\n", msg);
bartbedfd232009-03-26 19:07:15 +0000360 VG_(free)(msg);
361 }
bart09dc13f2009-02-14 15:13:31 +0000362
bartbedfd232009-03-26 19:07:15 +0000363 if (! DRD_(get_check_stack_accesses)())
364 {
365 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
366 - DRD_(thread_get_stack_size)(drd_joinee),
367 DRD_(thread_get_stack_max)(drd_joinee));
368 }
369 DRD_(clientobj_delete_thread)(drd_joinee);
bart9194e932011-02-09 11:55:12 +0000370 DRD_(thread_delete)(drd_joinee, False);
bart09dc13f2009-02-14 15:13:31 +0000371}
372
bart324a23b2009-02-15 12:14:52 +0000373/**
374 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
375 * and accesses this data structure from multiple threads without locking.
376 * Any conflicting accesses in the range stack_startup..stack_max will be
377 * ignored.
378 */
bart62a784c2009-02-15 13:11:14 +0000379void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
380 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000381{
bartbedfd232009-03-26 19:07:15 +0000382 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
383 && tid != DRD_INVALID_THREADID);
384 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
385 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
386 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000387}
388
bart86a87df2009-03-04 19:26:47 +0000389/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000390Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000391{
bartbedfd232009-03-26 19:07:15 +0000392 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
393 && tid != DRD_INVALID_THREADID);
394 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000395}
396
bart86a87df2009-03-04 19:26:47 +0000397/**
398 * Return the lowest value that was ever assigned to the stack pointer
399 * for the specified thread.
400 */
bart62a784c2009-02-15 13:11:14 +0000401Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000402{
bartbedfd232009-03-26 19:07:15 +0000403 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
404 && tid != DRD_INVALID_THREADID);
405 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000406}
407
bart86a87df2009-03-04 19:26:47 +0000408/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000409Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000410{
bartbedfd232009-03-26 19:07:15 +0000411 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
412 && tid != DRD_INVALID_THREADID);
413 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000414}
415
bart86a87df2009-03-04 19:26:47 +0000416/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000417SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000418{
bartbedfd232009-03-26 19:07:15 +0000419 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
420 && tid != DRD_INVALID_THREADID);
421 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000422}
423
bart383d6132010-09-02 14:43:18 +0000424Bool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid)
425{
426 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
427 && tid != DRD_INVALID_THREADID);
428 return DRD_(g_threadinfo)[tid].on_alt_stack;
429}
430
431void DRD_(thread_set_on_alt_stack)(const DrdThreadId tid,
432 const Bool on_alt_stack)
433{
434 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
435 && tid != DRD_INVALID_THREADID);
436 tl_assert(on_alt_stack == !!on_alt_stack);
437 DRD_(g_threadinfo)[tid].on_alt_stack = on_alt_stack;
438}
439
440Int DRD_(thread_get_threads_on_alt_stack)(void)
441{
442 int i, n = 0;
443
444 for (i = 1; i < DRD_N_THREADS; i++)
445 n += DRD_(g_threadinfo)[i].on_alt_stack;
446 return n;
447}
448
bart09dc13f2009-02-14 15:13:31 +0000449/**
bart31b983d2010-02-21 14:52:59 +0000450 * Clean up thread-specific data structures. Call this just after
bart09dc13f2009-02-14 15:13:31 +0000451 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000452 */
bart9194e932011-02-09 11:55:12 +0000453void DRD_(thread_delete)(const DrdThreadId tid, const Bool detached)
sewardjaf44c822007-11-25 14:01:38 +0000454{
bartbedfd232009-03-26 19:07:15 +0000455 Segment* sg;
456 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000457
bartbedfd232009-03-26 19:07:15 +0000458 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart86a87df2009-03-04 19:26:47 +0000459
bartbedfd232009-03-26 19:07:15 +0000460 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
461 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
462 {
463 sg_prev = sg->prev;
464 sg->prev = 0;
465 sg->next = 0;
466 DRD_(sg_put)(sg);
467 }
468 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
469 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
bart9194e932011-02-09 11:55:12 +0000470 if (detached)
471 DRD_(g_threadinfo)[tid].detached_posix_thread = False;
472 else
473 tl_assert(!DRD_(g_threadinfo)[tid].detached_posix_thread);
bartbedfd232009-03-26 19:07:15 +0000474 DRD_(g_threadinfo)[tid].first = 0;
475 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000476
bartbedfd232009-03-26 19:07:15 +0000477 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000478}
479
bart324a23b2009-02-15 12:14:52 +0000480/**
481 * Called after a thread performed its last memory access and before
482 * thread_delete() is called. Note: thread_delete() is only called for
483 * joinable threads, not for detached threads.
484 */
bart62a784c2009-02-15 13:11:14 +0000485void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000486{
bartbedfd232009-03-26 19:07:15 +0000487 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
488 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000489
bartbedfd232009-03-26 19:07:15 +0000490 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000491
bartbedfd232009-03-26 19:07:15 +0000492 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
493 {
494 /*
495 * Once a detached thread has finished, its stack is deallocated and
496 * should no longer be taken into account when computing the conflict set.
497 */
498 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000499
bartbedfd232009-03-26 19:07:15 +0000500 /*
501 * For a detached thread, calling pthread_exit() invalidates the
502 * POSIX thread ID associated with the detached thread. For joinable
503 * POSIX threads however, the POSIX thread ID remains live after the
504 * pthread_exit() call until pthread_join() is called.
505 */
506 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
507 }
sewardjaf44c822007-11-25 14:01:38 +0000508}
509
bart5c7e6b62011-02-03 17:47:50 +0000510/** Called just after fork() in the child process. */
511void DRD_(drd_thread_atfork_child)(const DrdThreadId tid)
512{
513 unsigned i;
514
515 for (i = 1; i < DRD_N_THREADS; i++)
516 {
517 if (i == tid)
518 continue;
519 if (DRD_(IsValidDrdThreadId(i)))
bart9194e932011-02-09 11:55:12 +0000520 DRD_(thread_delete)(i, True);
bart5c7e6b62011-02-03 17:47:50 +0000521 tl_assert(!DRD_(IsValidDrdThreadId(i)));
522 }
523}
524
bart9b2974a2008-09-27 12:35:31 +0000525/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000526void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000527{
bartbedfd232009-03-26 19:07:15 +0000528 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
529 && tid != DRD_INVALID_THREADID);
530 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000531
bart0c0cd772011-03-03 19:59:20 +0000532 if (DRD_(thread_get_trace_fork_join)())
533 VG_(message)(Vg_UserMsg, "[%d] drd_thread_pre_cancel %d\n",
534 DRD_(g_drd_running_tid), tid);
bartaf0691b2008-09-27 12:26:50 +0000535}
536
barte7dff242009-04-23 17:12:39 +0000537/**
538 * Store the POSIX thread ID for the specified thread.
539 *
540 * @note This function can be called two times for the same thread -- see also
541 * the comment block preceding the pthread_create() wrapper in
542 * drd_pthread_intercepts.c.
543 */
bart62a784c2009-02-15 13:11:14 +0000544void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000545{
bartbedfd232009-03-26 19:07:15 +0000546 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
547 && tid != DRD_INVALID_THREADID);
barte7dff242009-04-23 17:12:39 +0000548 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
549 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
bartbedfd232009-03-26 19:07:15 +0000550 tl_assert(ptid != INVALID_POSIX_THREADID);
551 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
552 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000553}
554
bart86a87df2009-03-04 19:26:47 +0000555/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000556Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000557{
bartbedfd232009-03-26 19:07:15 +0000558 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
559 && tid != DRD_INVALID_THREADID);
560 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000561}
562
bart86a87df2009-03-04 19:26:47 +0000563/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000564void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000565{
bartbedfd232009-03-26 19:07:15 +0000566 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
567 && tid != DRD_INVALID_THREADID);
568 tl_assert(!! joinable == joinable);
569 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bart8f822af2009-06-08 18:20:42 +0000570
bartbedfd232009-03-26 19:07:15 +0000571 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000572}
573
bartdd75cdf2009-07-24 08:20:10 +0000574/** Tells DRD that the calling thread is about to enter pthread_create(). */
575void DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
576{
577 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
578 && tid != DRD_INVALID_THREADID);
579 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
580 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
581
582 DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
583}
584
585/** Tells DRD that the calling thread has left pthread_create(). */
586void DRD_(thread_left_pthread_create)(const DrdThreadId tid)
587{
588 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
589 && tid != DRD_INVALID_THREADID);
590 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
591 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
592
593 DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
594}
595
bartd45d9952009-05-31 18:53:54 +0000596/** Obtain the thread number and the user-assigned thread name. */
597const char* DRD_(thread_get_name)(const DrdThreadId tid)
598{
599 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
600 && tid != DRD_INVALID_THREADID);
601
602 return DRD_(g_threadinfo)[tid].name;
603}
604
605/** Set the name of the specified thread. */
606void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
607{
608 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
609 && tid != DRD_INVALID_THREADID);
bart31b983d2010-02-21 14:52:59 +0000610
bartd45d9952009-05-31 18:53:54 +0000611 if (name == NULL || name[0] == 0)
612 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
613 sizeof(DRD_(g_threadinfo)[tid].name),
614 "Thread %d",
615 tid);
616 else
617 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
618 sizeof(DRD_(g_threadinfo)[tid].name),
619 "Thread %d (%s)",
620 tid, name);
621 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
622}
623
bart86a87df2009-03-04 19:26:47 +0000624/**
625 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
626 * conflict set.
627 */
bart62a784c2009-02-15 13:11:14 +0000628void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000629{
bartbedfd232009-03-26 19:07:15 +0000630 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000631
bartbedfd232009-03-26 19:07:15 +0000632 if (vg_tid != s_vg_running_tid)
633 {
634 DRD_(thread_set_running_tid)(vg_tid,
635 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
636 }
sewardj8b09d4f2007-12-04 21:27:18 +0000637
bartbedfd232009-03-26 19:07:15 +0000638 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
639 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000640}
641
bart86a87df2009-03-04 19:26:47 +0000642/**
643 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
644 * conflict set.
645 */
bart62a784c2009-02-15 13:11:14 +0000646void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
647 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000648{
bartbedfd232009-03-26 19:07:15 +0000649 tl_assert(vg_tid != VG_INVALID_THREADID);
650 tl_assert(drd_tid != DRD_INVALID_THREADID);
bart31b983d2010-02-21 14:52:59 +0000651
bartbedfd232009-03-26 19:07:15 +0000652 if (vg_tid != s_vg_running_tid)
653 {
654 if (s_trace_context_switches
655 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
656 {
657 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +0000658 "Context switch from thread %d to thread %d;"
sewardj1e29ebc2009-07-15 14:49:17 +0000659 " segments: %llu\n",
bart63c92ea2009-07-19 17:53:56 +0000660 DRD_(g_drd_running_tid), drd_tid,
bartbedfd232009-03-26 19:07:15 +0000661 DRD_(sg_get_segments_alive_count)());
662 }
663 s_vg_running_tid = vg_tid;
664 DRD_(g_drd_running_tid) = drd_tid;
665 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
666 s_context_switch_count++;
667 }
sewardj8b09d4f2007-12-04 21:27:18 +0000668
bartbedfd232009-03-26 19:07:15 +0000669 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
670 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000671}
672
bart86a87df2009-03-04 19:26:47 +0000673/**
674 * Increase the synchronization nesting counter. Must be called before the
675 * client calls a synchronization function.
676 */
bart62a784c2009-02-15 13:11:14 +0000677int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000678{
bartbedfd232009-03-26 19:07:15 +0000679 tl_assert(DRD_(IsValidDrdThreadId)(tid));
680 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000681}
682
bart86a87df2009-03-04 19:26:47 +0000683/**
684 * Decrease the synchronization nesting counter. Must be called after the
685 * client left a synchronization function.
686 */
bart62a784c2009-02-15 13:11:14 +0000687int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000688{
bartbedfd232009-03-26 19:07:15 +0000689 tl_assert(DRD_(IsValidDrdThreadId)(tid));
690 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
691 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000692}
693
bart86a87df2009-03-04 19:26:47 +0000694/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000695int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000696{
bartbedfd232009-03-26 19:07:15 +0000697 tl_assert(DRD_(IsValidDrdThreadId)(tid));
698 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000699}
700
bart1a473c72008-03-13 19:03:38 +0000701/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000702static
bart86a87df2009-03-04 19:26:47 +0000703void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000704{
bartbedfd232009-03-26 19:07:15 +0000705 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
706 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000707
708#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
709 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
710#endif
711
bartbedfd232009-03-26 19:07:15 +0000712 sg->prev = DRD_(g_threadinfo)[tid].last;
713 sg->next = 0;
714 if (DRD_(g_threadinfo)[tid].last)
715 DRD_(g_threadinfo)[tid].last->next = sg;
716 DRD_(g_threadinfo)[tid].last = sg;
717 if (DRD_(g_threadinfo)[tid].first == 0)
718 DRD_(g_threadinfo)[tid].first = sg;
bart8f822af2009-06-08 18:20:42 +0000719
720#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
721 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
722#endif
sewardjaf44c822007-11-25 14:01:38 +0000723}
724
bart324a23b2009-02-15 12:14:52 +0000725/**
726 * Remove a segment from the segment list of thread threadid, and free the
727 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000728 */
bart62a784c2009-02-15 13:11:14 +0000729static
bart86a87df2009-03-04 19:26:47 +0000730void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000731{
bartbedfd232009-03-26 19:07:15 +0000732 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
733 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +0000734
735#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
736 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
737#endif
bart26f73e12008-02-24 18:37:08 +0000738
bartbedfd232009-03-26 19:07:15 +0000739 if (sg->prev)
740 sg->prev->next = sg->next;
741 if (sg->next)
742 sg->next->prev = sg->prev;
743 if (sg == DRD_(g_threadinfo)[tid].first)
744 DRD_(g_threadinfo)[tid].first = sg->next;
745 if (sg == DRD_(g_threadinfo)[tid].last)
746 DRD_(g_threadinfo)[tid].last = sg->prev;
747 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000748
bart8f822af2009-06-08 18:20:42 +0000749#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
750 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
751#endif
sewardjaf44c822007-11-25 14:01:38 +0000752}
753
bart86a87df2009-03-04 19:26:47 +0000754/**
755 * Returns a pointer to the vector clock of the most recent segment associated
756 * with thread 'tid'.
757 */
bart62a784c2009-02-15 13:11:14 +0000758VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000759{
bartbedfd232009-03-26 19:07:15 +0000760 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
761 && tid != DRD_INVALID_THREADID);
762 tl_assert(DRD_(g_threadinfo)[tid].last);
763 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000764}
765
bart324a23b2009-02-15 12:14:52 +0000766/**
767 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000768 */
bart62a784c2009-02-15 13:11:14 +0000769void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000770{
bartbedfd232009-03-26 19:07:15 +0000771 tl_assert(sg);
772 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
773 && tid != DRD_INVALID_THREADID);
774 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000775
bartbedfd232009-03-26 19:07:15 +0000776 DRD_(sg_put)(*sg);
777 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000778}
779
sewardjaf44c822007-11-25 14:01:38 +0000780/**
781 * Compute the minimum of all latest vector clocks of all threads
782 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000783 *
sewardjaf44c822007-11-25 14:01:38 +0000784 * @param vc pointer to a vectorclock, holds result upon return.
785 */
bart62a784c2009-02-15 13:11:14 +0000786static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000787{
bartbedfd232009-03-26 19:07:15 +0000788 unsigned i;
789 Bool first;
790 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000791
bartbedfd232009-03-26 19:07:15 +0000792 first = True;
bart8f822af2009-06-08 18:20:42 +0000793 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000794 {
795 latest_sg = DRD_(g_threadinfo)[i].last;
796 if (latest_sg)
797 {
798 if (first)
799 DRD_(vc_assign)(vc, &latest_sg->vc);
800 else
801 DRD_(vc_min)(vc, &latest_sg->vc);
802 first = False;
803 }
804 }
sewardjaf44c822007-11-25 14:01:38 +0000805}
806
bart86a87df2009-03-04 19:26:47 +0000807/**
808 * Compute the maximum of all latest vector clocks of all threads.
809 *
810 * @param vc pointer to a vectorclock, holds result upon return.
811 */
bart62a784c2009-02-15 13:11:14 +0000812static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000813{
bartbedfd232009-03-26 19:07:15 +0000814 unsigned i;
815 Bool first;
816 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000817
bartbedfd232009-03-26 19:07:15 +0000818 first = True;
bart8f822af2009-06-08 18:20:42 +0000819 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000820 {
821 latest_sg = DRD_(g_threadinfo)[i].last;
822 if (latest_sg)
823 {
824 if (first)
825 DRD_(vc_assign)(vc, &latest_sg->vc);
826 else
827 DRD_(vc_combine)(vc, &latest_sg->vc);
828 first = False;
829 }
830 }
sewardjaf44c822007-11-25 14:01:38 +0000831}
832
833/**
bart5bd9f2d2008-03-03 20:31:58 +0000834 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000835 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000836 * data race.
837 */
bart8f822af2009-06-08 18:20:42 +0000838static void thread_discard_ordered_segments(void)
sewardjaf44c822007-11-25 14:01:38 +0000839{
bartbedfd232009-03-26 19:07:15 +0000840 unsigned i;
841 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000842
bartbedfd232009-03-26 19:07:15 +0000843 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000844
bartbedfd232009-03-26 19:07:15 +0000845 DRD_(vc_init)(&thread_vc_min, 0, 0);
846 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
847 if (DRD_(sg_get_trace)())
848 {
bart8f822af2009-06-08 18:20:42 +0000849 char *vc_min, *vc_max;
bartbedfd232009-03-26 19:07:15 +0000850 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000851
bartbedfd232009-03-26 19:07:15 +0000852 DRD_(vc_init)(&thread_vc_max, 0, 0);
853 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart8f822af2009-06-08 18:20:42 +0000854 vc_min = DRD_(vc_aprint)(&thread_vc_min);
855 vc_max = DRD_(vc_aprint)(&thread_vc_max);
856 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000857 "Discarding ordered segments -- min vc is %s, max vc is %s\n",
bart8f822af2009-06-08 18:20:42 +0000858 vc_min, vc_max);
859 VG_(free)(vc_min);
860 VG_(free)(vc_max);
bartbedfd232009-03-26 19:07:15 +0000861 DRD_(vc_cleanup)(&thread_vc_max);
862 }
sewardjaf44c822007-11-25 14:01:38 +0000863
bart8f822af2009-06-08 18:20:42 +0000864 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000865 {
866 Segment* sg;
867 Segment* sg_next;
868 for (sg = DRD_(g_threadinfo)[i].first;
869 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
870 sg = sg_next)
871 {
872 thread_discard_segment(i, sg);
873 }
874 }
875 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000876}
877
bart324a23b2009-02-15 12:14:52 +0000878/**
bart8f822af2009-06-08 18:20:42 +0000879 * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
880 * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
881 * all segments in the set CS are ordered consistently against both sg1 and
882 * sg2. The set CS is defined as the set of segments that can immediately
883 * precede future segments via inter-thread synchronization operations. In
884 * DRD the set CS consists of the latest segment of each thread combined with
885 * all segments for which the reference count is strictly greater than one.
886 * The code below is an optimized version of the following:
887 *
888 * for (i = 0; i < DRD_N_THREADS; i++)
889 * {
890 * Segment* sg;
891 *
892 * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
893 * {
894 * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
895 * {
896 * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
897 * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
898 * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
899 * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
900 * {
901 * return False;
902 * }
903 * }
904 * }
905 * }
906 */
907static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
908 Segment* const sg1,
909 Segment* const sg2)
910{
911 unsigned i;
912
913 tl_assert(sg1->next);
914 tl_assert(sg2->next);
915 tl_assert(sg1->next == sg2);
916 tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
917
918 for (i = 0; i < DRD_N_THREADS; i++)
919 {
920 Segment* sg;
921
922 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
923 {
924 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
925 {
926 if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
927 break;
928 if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
929 return False;
930 }
931 }
932 for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
933 {
934 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
935 {
936 if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
937 break;
938 if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
939 return False;
940 }
941 }
942 }
943 return True;
944}
945
946/**
bart324a23b2009-02-15 12:14:52 +0000947 * Merge all segments that may be merged without triggering false positives
948 * or discarding real data races. For the theoretical background of segment
bart8f822af2009-06-08 18:20:42 +0000949 * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
950 * and Koen De Bosschere. Bounding the number of segment histories during
951 * data race detection. Parallel Computing archive, Volume 28, Issue 9,
952 * pp 1221-1238, September 2002. This paper contains a proof that merging
953 * consecutive segments for which the property equiv(s1,s2) holds can be
954 * merged without reducing the accuracy of datarace detection. Furthermore
955 * it is also proven that the total number of all segments will never grow
956 * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
957 * every time a new segment is created. The property equiv(s1, s2) is defined
958 * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
959 * clocks of segments s and s1 are ordered in the same way as those of segments
960 * s and s2. The set CS is defined as the set of existing segments s that have
961 * the potential to conflict with not yet created segments, either because the
962 * segment s is the latest segment of a thread or because it can become the
963 * immediate predecessor of a new segment due to a synchronization operation.
barta9c37392008-03-22 09:38:48 +0000964 */
965static void thread_merge_segments(void)
966{
bartbedfd232009-03-26 19:07:15 +0000967 unsigned i;
barta9c37392008-03-22 09:38:48 +0000968
bart8f822af2009-06-08 18:20:42 +0000969 s_new_segments_since_last_merge = 0;
970
971 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +0000972 {
973 Segment* sg;
barta9c37392008-03-22 09:38:48 +0000974
bart8f822af2009-06-08 18:20:42 +0000975#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
976 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
977#endif
barta9c37392008-03-22 09:38:48 +0000978
bartbedfd232009-03-26 19:07:15 +0000979 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000980 {
bartbedfd232009-03-26 19:07:15 +0000981 if (DRD_(sg_get_refcnt)(sg) == 1
982 && sg->next
983 && DRD_(sg_get_refcnt)(sg->next) == 1
bart8f822af2009-06-08 18:20:42 +0000984 && sg->next->next
985 && thread_consistent_segment_ordering(i, sg, sg->next))
bartbedfd232009-03-26 19:07:15 +0000986 {
987 /* Merge sg and sg->next into sg. */
988 DRD_(sg_merge)(sg, sg->next);
989 thread_discard_segment(i, sg->next);
990 }
barta9c37392008-03-22 09:38:48 +0000991 }
barta9c37392008-03-22 09:38:48 +0000992
bart8f822af2009-06-08 18:20:42 +0000993#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
994 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
995#endif
bartbedfd232009-03-26 19:07:15 +0000996 }
barta9c37392008-03-22 09:38:48 +0000997}
998
bart324a23b2009-02-15 12:14:52 +0000999/**
bart324a23b2009-02-15 12:14:52 +00001000 * Create a new segment for the specified thread, and discard any segments
1001 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +00001002 */
bart62a784c2009-02-15 13:11:14 +00001003void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001004{
bart8f822af2009-06-08 18:20:42 +00001005 Segment* last_sg;
bartbedfd232009-03-26 19:07:15 +00001006 Segment* new_sg;
bartd66e3a82008-04-06 15:02:17 +00001007
bartbedfd232009-03-26 19:07:15 +00001008 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1009 && tid != DRD_INVALID_THREADID);
bart8f822af2009-06-08 18:20:42 +00001010 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +00001011
bart8f822af2009-06-08 18:20:42 +00001012 last_sg = DRD_(g_threadinfo)[tid].last;
bartbedfd232009-03-26 19:07:15 +00001013 new_sg = DRD_(sg_new)(tid, tid);
1014 thread_append_segment(tid, new_sg);
bart8f822af2009-06-08 18:20:42 +00001015 if (tid == DRD_(g_drd_running_tid) && last_sg)
barte5214662009-06-21 11:51:23 +00001016 {
bart8f822af2009-06-08 18:20:42 +00001017 DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
barte5214662009-06-21 11:51:23 +00001018 s_update_conflict_set_new_sg_count++;
1019 }
bartd66e3a82008-04-06 15:02:17 +00001020
bart8f822af2009-06-08 18:20:42 +00001021 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
sewardjaf44c822007-11-25 14:01:38 +00001022
bart8f822af2009-06-08 18:20:42 +00001023 if (s_segment_merging
1024 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
bartbedfd232009-03-26 19:07:15 +00001025 {
bart8f822af2009-06-08 18:20:42 +00001026 thread_discard_ordered_segments();
bartbedfd232009-03-26 19:07:15 +00001027 thread_merge_segments();
1028 }
sewardjaf44c822007-11-25 14:01:38 +00001029}
1030
bart26f73e12008-02-24 18:37:08 +00001031/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart8f822af2009-06-08 18:20:42 +00001032void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +00001033{
bartbedfd232009-03-26 19:07:15 +00001034 tl_assert(joiner != joinee);
1035 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
1036 && joiner != DRD_INVALID_THREADID);
1037 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
1038 && joinee != DRD_INVALID_THREADID);
1039 tl_assert(DRD_(g_threadinfo)[joiner].last);
1040 tl_assert(DRD_(g_threadinfo)[joinee].last);
bart8f822af2009-06-08 18:20:42 +00001041
1042 if (DRD_(sg_get_trace)())
1043 {
1044 char *str1, *str2;
1045 str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
1046 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001047 VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
bart8f822af2009-06-08 18:20:42 +00001048 str1, str2);
1049 VG_(free)(str1);
1050 VG_(free)(str2);
1051 }
barte5214662009-06-21 11:51:23 +00001052 if (joiner == DRD_(g_drd_running_tid))
1053 {
1054 VectorClock old_vc;
1055
1056 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[joiner].last->vc);
1057 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001058 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001059 DRD_(thread_update_conflict_set)(joiner, &old_vc);
1060 s_update_conflict_set_join_count++;
1061 DRD_(vc_cleanup)(&old_vc);
1062 }
1063 else
1064 {
1065 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
bartf6ec1fe2009-06-21 18:07:35 +00001066 &DRD_(g_threadinfo)[joinee].last->vc);
barte5214662009-06-21 11:51:23 +00001067 }
1068
1069 thread_discard_ordered_segments();
1070
bart8f822af2009-06-08 18:20:42 +00001071 if (DRD_(sg_get_trace)())
1072 {
1073 char* str;
1074 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001075 VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
bart8f822af2009-06-08 18:20:42 +00001076 VG_(free)(str);
1077 }
sewardjaf44c822007-11-25 14:01:38 +00001078}
1079
bart324a23b2009-02-15 12:14:52 +00001080/**
bart8f822af2009-06-08 18:20:42 +00001081 * Update the vector clock of the last segment of thread tid with the
bartf6ec1fe2009-06-21 18:07:35 +00001082 * the vector clock of segment sg.
bart26f73e12008-02-24 18:37:08 +00001083 */
bartf6ec1fe2009-06-21 18:07:35 +00001084static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
sewardjaf44c822007-11-25 14:01:38 +00001085{
bart8f822af2009-06-08 18:20:42 +00001086 const VectorClock* const vc = &sg->vc;
1087
bartbedfd232009-03-26 19:07:15 +00001088 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1089 && tid != DRD_INVALID_THREADID);
1090 tl_assert(DRD_(g_threadinfo)[tid].last);
bart8f822af2009-06-08 18:20:42 +00001091 tl_assert(sg);
bartbedfd232009-03-26 19:07:15 +00001092 tl_assert(vc);
bart8f822af2009-06-08 18:20:42 +00001093
1094 if (tid != sg->tid)
1095 {
1096 VectorClock old_vc;
1097
1098 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
1099 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
1100 if (DRD_(sg_get_trace)())
1101 {
1102 char *str1, *str2;
1103 str1 = DRD_(vc_aprint)(&old_vc);
1104 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001105 VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
bart8f822af2009-06-08 18:20:42 +00001106 VG_(free)(str1);
1107 VG_(free)(str2);
1108 }
barte5214662009-06-21 11:51:23 +00001109
bart8f822af2009-06-08 18:20:42 +00001110 thread_discard_ordered_segments();
barte5214662009-06-21 11:51:23 +00001111
bart8f822af2009-06-08 18:20:42 +00001112 DRD_(thread_update_conflict_set)(tid, &old_vc);
barte5214662009-06-21 11:51:23 +00001113 s_update_conflict_set_sync_count++;
1114
bart8f822af2009-06-08 18:20:42 +00001115 DRD_(vc_cleanup)(&old_vc);
1116 }
1117 else
1118 {
1119 tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
1120 }
sewardjaf44c822007-11-25 14:01:38 +00001121}
1122
bart324a23b2009-02-15 12:14:52 +00001123/**
bartf6ec1fe2009-06-21 18:07:35 +00001124 * Create a new segment for thread tid and update the vector clock of the last
1125 * segment of this thread with the the vector clock of segment sg. Call this
1126 * function after thread tid had to wait because of thread synchronization
1127 * until the memory accesses in the segment sg finished.
1128 */
1129void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
1130{
1131 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1132 && tid != DRD_INVALID_THREADID);
1133 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1134 tl_assert(sg);
1135
1136 thread_append_segment(tid, DRD_(sg_new)(tid, tid));
1137
1138 thread_combine_vc_sync(tid, sg);
1139
1140 if (s_segment_merging
1141 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1142 {
1143 thread_discard_ordered_segments();
1144 thread_merge_segments();
1145 }
1146}
1147
1148/**
bart324a23b2009-02-15 12:14:52 +00001149 * Call this function whenever a thread is no longer using the memory
1150 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1151 * increase.
bart26f73e12008-02-24 18:37:08 +00001152 */
bart23ef19d2011-03-12 12:34:44 +00001153void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +00001154{
bartbedfd232009-03-26 19:07:15 +00001155 DrdThreadId other_user;
1156 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001157
bartbedfd232009-03-26 19:07:15 +00001158 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
1159 other_user = DRD_INVALID_THREADID;
bart8f822af2009-06-08 18:20:42 +00001160 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001161 {
1162 Segment* p;
bart23ef19d2011-03-12 12:34:44 +00001163 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next) {
bartbedfd232009-03-26 19:07:15 +00001164 if (other_user == DRD_INVALID_THREADID
bart23ef19d2011-03-12 12:34:44 +00001165 && i != DRD_(g_drd_running_tid)) {
1166 if (UNLIKELY(DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2)))
bartbedfd232009-03-26 19:07:15 +00001167 other_user = i;
bart23ef19d2011-03-12 12:34:44 +00001168 } else
bartf9427fd2010-08-29 09:19:07 +00001169 DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
sewardjaf44c822007-11-25 14:01:38 +00001170 }
bartbedfd232009-03-26 19:07:15 +00001171 }
sewardjaf44c822007-11-25 14:01:38 +00001172
bartbedfd232009-03-26 19:07:15 +00001173 /*
1174 * If any other thread had accessed memory in [ a1, a2 [, update the
1175 * conflict set.
1176 */
1177 if (other_user != DRD_INVALID_THREADID
1178 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
1179 {
1180 thread_compute_conflict_set(&DRD_(g_conflict_set),
1181 DRD_(thread_get_running_tid)());
1182 }
sewardjaf44c822007-11-25 14:01:38 +00001183}
1184
bartd45d9952009-05-31 18:53:54 +00001185/** Specify whether memory loads should be recorded. */
1186void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001187{
bartbedfd232009-03-26 19:07:15 +00001188 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1189 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001190 tl_assert(enabled == !! enabled);
1191
1192 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
bart0268dfa2008-03-11 20:10:21 +00001193}
1194
bartd45d9952009-05-31 18:53:54 +00001195/** Specify whether memory stores should be recorded. */
1196void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
bart0268dfa2008-03-11 20:10:21 +00001197{
bartbedfd232009-03-26 19:07:15 +00001198 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1199 && tid != DRD_INVALID_THREADID);
bartd45d9952009-05-31 18:53:54 +00001200 tl_assert(enabled == !! enabled);
1201
1202 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
bart0268dfa2008-03-11 20:10:21 +00001203}
1204
bart86a87df2009-03-04 19:26:47 +00001205/**
1206 * Print the segment information for all threads.
1207 *
1208 * This function is only used for debugging purposes.
1209 */
bart62a784c2009-02-15 13:11:14 +00001210void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +00001211{
bartbedfd232009-03-26 19:07:15 +00001212 unsigned i;
1213 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001214
bart8f822af2009-06-08 18:20:42 +00001215 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001216 {
1217 if (DRD_(g_threadinfo)[i].first)
sewardjaf44c822007-11-25 14:01:38 +00001218 {
bartbedfd232009-03-26 19:07:15 +00001219 VG_(printf)("**************\n"
1220 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
1221 "**************\n",
1222 i,
1223 DRD_(g_threadinfo)[i].vg_thread_exists,
1224 DRD_(g_threadinfo)[i].vg_threadid,
1225 DRD_(g_threadinfo)[i].posix_thread_exists,
1226 DRD_(g_threadinfo)[i].pt_threadid,
1227 DRD_(g_threadinfo)[i].detached_posix_thread);
1228 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1229 {
1230 DRD_(sg_print)(p);
1231 }
sewardjaf44c822007-11-25 14:01:38 +00001232 }
bartbedfd232009-03-26 19:07:15 +00001233 }
sewardjaf44c822007-11-25 14:01:38 +00001234}
1235
bart86a87df2009-03-04 19:26:47 +00001236/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001237static void show_call_stack(const DrdThreadId tid,
1238 const Char* const msg,
1239 ExeContext* const callstack)
1240{
bartbedfd232009-03-26 19:07:15 +00001241 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +00001242
bart63c92ea2009-07-19 17:53:56 +00001243 VG_(message)(Vg_UserMsg, "%s (thread %d)\n", msg, tid);
sewardjaf44c822007-11-25 14:01:38 +00001244
bartbedfd232009-03-26 19:07:15 +00001245 if (vg_tid != VG_INVALID_THREADID)
1246 {
1247 if (callstack)
1248 {
1249 VG_(pp_ExeContext)(callstack);
1250 }
1251 else
1252 {
1253 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1254 }
1255 }
1256 else
1257 {
1258 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001259 " (thread finished, call stack no longer available)\n");
bartbedfd232009-03-26 19:07:15 +00001260 }
sewardjaf44c822007-11-25 14:01:38 +00001261}
1262
bart86a87df2009-03-04 19:26:47 +00001263/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +00001264static void
1265thread_report_conflicting_segments_segment(const DrdThreadId tid,
1266 const Addr addr,
1267 const SizeT size,
1268 const BmAccessTypeT access_type,
1269 const Segment* const p)
1270{
bartbedfd232009-03-26 19:07:15 +00001271 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +00001272
bartbedfd232009-03-26 19:07:15 +00001273 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1274 && tid != DRD_INVALID_THREADID);
1275 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +00001276
bart8f822af2009-06-08 18:20:42 +00001277 for (i = 0; i < DRD_N_THREADS; i++)
bartbedfd232009-03-26 19:07:15 +00001278 {
1279 if (i != tid)
sewardjaf44c822007-11-25 14:01:38 +00001280 {
bartbedfd232009-03-26 19:07:15 +00001281 Segment* q;
1282 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1283 {
1284 /*
bart31b983d2010-02-21 14:52:59 +00001285 * Since q iterates over the segments of thread i in order of
1286 * decreasing vector clocks, if q->vc <= p->vc, then
bartbedfd232009-03-26 19:07:15 +00001287 * q->next->vc <= p->vc will also hold. Hence, break out of the
1288 * loop once this condition is met.
1289 */
1290 if (DRD_(vc_lte)(&q->vc, &p->vc))
1291 break;
1292 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1293 {
bart8f822af2009-06-08 18:20:42 +00001294 if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
bartbedfd232009-03-26 19:07:15 +00001295 access_type))
1296 {
1297 tl_assert(q->stacktrace);
1298 show_call_stack(i, "Other segment start",
1299 q->stacktrace);
1300 show_call_stack(i, "Other segment end",
1301 q->next ? q->next->stacktrace : 0);
1302 }
1303 }
1304 }
sewardjaf44c822007-11-25 14:01:38 +00001305 }
bartbedfd232009-03-26 19:07:15 +00001306 }
sewardjaf44c822007-11-25 14:01:38 +00001307}
1308
bart86a87df2009-03-04 19:26:47 +00001309/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +00001310void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1311 const Addr addr,
1312 const SizeT size,
1313 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001314{
bartbedfd232009-03-26 19:07:15 +00001315 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001316
bartbedfd232009-03-26 19:07:15 +00001317 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1318 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001319
bartbedfd232009-03-26 19:07:15 +00001320 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1321 {
bart8f822af2009-06-08 18:20:42 +00001322 if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
bartbedfd232009-03-26 19:07:15 +00001323 {
1324 thread_report_conflicting_segments_segment(tid, addr, size,
1325 access_type, p);
1326 }
1327 }
sewardjaf44c822007-11-25 14:01:38 +00001328}
sewardjaf44c822007-11-25 14:01:38 +00001329
bart324a23b2009-02-15 12:14:52 +00001330/**
bart8f822af2009-06-08 18:20:42 +00001331 * Verify whether the conflict set for thread tid is up to date. Only perform
1332 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1333 */
1334static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1335{
1336 static int do_verify_conflict_set = -1;
1337 Bool result;
1338 struct bitmap* computed_conflict_set = 0;
1339
1340 if (do_verify_conflict_set < 0)
1341 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1342
1343 if (do_verify_conflict_set == 0)
1344 return True;
1345
1346 thread_compute_conflict_set(&computed_conflict_set, tid);
1347 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1348 if (! result)
1349 {
1350 VG_(printf)("actual conflict set:\n");
1351 DRD_(bm_print)(DRD_(g_conflict_set));
1352 VG_(printf)("\n");
1353 VG_(printf)("computed conflict set:\n");
1354 DRD_(bm_print)(computed_conflict_set);
1355 VG_(printf)("\n");
1356 }
1357 DRD_(bm_delete)(computed_conflict_set);
1358 return result;
1359}
1360
1361/**
1362 * Compute the conflict set: a bitmap that represents the union of all memory
1363 * accesses of all segments that are unordered to the current segment of the
1364 * thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001365 */
bart86a87df2009-03-04 19:26:47 +00001366static void thread_compute_conflict_set(struct bitmap** conflict_set,
1367 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001368{
bartbedfd232009-03-26 19:07:15 +00001369 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001370
bartbedfd232009-03-26 19:07:15 +00001371 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1372 && tid != DRD_INVALID_THREADID);
1373 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001374
bart54803fe2009-06-21 09:26:27 +00001375 s_compute_conflict_set_count++;
bartbedfd232009-03-26 19:07:15 +00001376 s_conflict_set_bitmap_creation_count
1377 -= DRD_(bm_get_bitmap_creation_count)();
1378 s_conflict_set_bitmap2_creation_count
1379 -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001380
bartbedfd232009-03-26 19:07:15 +00001381 if (*conflict_set)
1382 {
bartf6ec1fe2009-06-21 18:07:35 +00001383 DRD_(bm_cleanup)(*conflict_set);
1384 DRD_(bm_init)(*conflict_set);
bartbedfd232009-03-26 19:07:15 +00001385 }
bartf6ec1fe2009-06-21 18:07:35 +00001386 else
1387 {
1388 *conflict_set = DRD_(bm_new)();
1389 }
bart26f73e12008-02-24 18:37:08 +00001390
bartbedfd232009-03-26 19:07:15 +00001391 if (s_trace_conflict_set)
1392 {
bart8f822af2009-06-08 18:20:42 +00001393 char* str;
bart26f73e12008-02-24 18:37:08 +00001394
bart8f822af2009-06-08 18:20:42 +00001395 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1396 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001397 "computing conflict set for thread %d with vc %s\n",
1398 tid, str);
bart8f822af2009-06-08 18:20:42 +00001399 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001400 }
sewardjaf44c822007-11-25 14:01:38 +00001401
bartbedfd232009-03-26 19:07:15 +00001402 p = DRD_(g_threadinfo)[tid].last;
1403 {
1404 unsigned j;
1405
1406 if (s_trace_conflict_set)
bart26f73e12008-02-24 18:37:08 +00001407 {
bart8f822af2009-06-08 18:20:42 +00001408 char* vc;
bartbedfd232009-03-26 19:07:15 +00001409
bart8f822af2009-06-08 18:20:42 +00001410 vc = DRD_(vc_aprint)(&p->vc);
sewardj1e29ebc2009-07-15 14:49:17 +00001411 VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
bart8f822af2009-06-08 18:20:42 +00001412 tid, vc);
1413 VG_(free)(vc);
bart26f73e12008-02-24 18:37:08 +00001414 }
sewardjaf44c822007-11-25 14:01:38 +00001415
bart8f822af2009-06-08 18:20:42 +00001416 for (j = 0; j < DRD_N_THREADS; j++)
bartbedfd232009-03-26 19:07:15 +00001417 {
1418 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1419 {
bart8f822af2009-06-08 18:20:42 +00001420 Segment* q;
bartbedfd232009-03-26 19:07:15 +00001421 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1422 {
1423 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1424 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1425 {
1426 if (s_trace_conflict_set)
1427 {
bart8f822af2009-06-08 18:20:42 +00001428 char* str;
1429
1430 str = DRD_(vc_aprint)(&q->vc);
1431 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001432 "conflict set: [%d] merging segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001433 j, str);
1434 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001435 }
bart8f822af2009-06-08 18:20:42 +00001436 DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
bartbedfd232009-03-26 19:07:15 +00001437 }
1438 else
1439 {
1440 if (s_trace_conflict_set)
1441 {
bart8f822af2009-06-08 18:20:42 +00001442 char* str;
1443
1444 str = DRD_(vc_aprint)(&q->vc);
1445 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001446 "conflict set: [%d] ignoring segment %s\n",
bart8f822af2009-06-08 18:20:42 +00001447 j, str);
1448 VG_(free)(str);
bartbedfd232009-03-26 19:07:15 +00001449 }
1450 }
1451 }
1452 }
1453 }
1454 }
sewardjaf44c822007-11-25 14:01:38 +00001455
bartbedfd232009-03-26 19:07:15 +00001456 s_conflict_set_bitmap_creation_count
1457 += DRD_(bm_get_bitmap_creation_count)();
1458 s_conflict_set_bitmap2_creation_count
1459 += DRD_(bm_get_bitmap2_creation_count)();
1460
bart8f822af2009-06-08 18:20:42 +00001461 if (s_trace_conflict_set_bm)
bartbedfd232009-03-26 19:07:15 +00001462 {
sewardj1e29ebc2009-07-15 14:49:17 +00001463 VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
bartbedfd232009-03-26 19:07:15 +00001464 DRD_(bm_print)(*conflict_set);
sewardj1e29ebc2009-07-15 14:49:17 +00001465 VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
bartbedfd232009-03-26 19:07:15 +00001466 }
sewardjaf44c822007-11-25 14:01:38 +00001467}
1468
bart8f822af2009-06-08 18:20:42 +00001469/**
1470 * Update the conflict set after the vector clock of thread tid has been
1471 * updated from old_vc to its current value, either because a new segment has
1472 * been created or because of a synchronization operation.
1473 */
1474void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1475 const VectorClock* const old_vc)
1476{
1477 const VectorClock* new_vc;
1478 Segment* p;
1479 unsigned j;
1480
1481 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1482 && tid != DRD_INVALID_THREADID);
1483 tl_assert(old_vc);
1484 tl_assert(tid == DRD_(g_drd_running_tid));
1485 tl_assert(DRD_(g_conflict_set));
1486
1487 if (s_trace_conflict_set)
1488 {
1489 char* str;
1490
1491 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1492 VG_(message)(Vg_DebugMsg,
bart63c92ea2009-07-19 17:53:56 +00001493 "updating conflict set for thread %d with vc %s\n",
1494 tid, str);
bart8f822af2009-06-08 18:20:42 +00001495 VG_(free)(str);
1496 }
1497
1498 new_vc = &DRD_(g_threadinfo)[tid].last->vc;
1499
1500 DRD_(bm_unmark)(DRD_(g_conflict_set));
1501
1502 for (j = 0; j < DRD_N_THREADS; j++)
1503 {
1504 Segment* q;
1505
1506 if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1507 continue;
1508
1509 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1510 {
1511 const int included_in_old_conflict_set
1512 = ! DRD_(vc_lte)(&q->vc, old_vc)
1513 && ! DRD_(vc_lte)(old_vc, &q->vc);
1514 const int included_in_new_conflict_set
1515 = ! DRD_(vc_lte)(&q->vc, new_vc)
1516 && ! DRD_(vc_lte)(new_vc, &q->vc);
1517 if (included_in_old_conflict_set != included_in_new_conflict_set)
1518 {
1519 if (s_trace_conflict_set)
1520 {
1521 char* str;
1522
1523 str = DRD_(vc_aprint)(&q->vc);
1524 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001525 "conflict set: [%d] merging segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001526 VG_(free)(str);
1527 }
1528 DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1529 }
1530 else
1531 {
1532 if (s_trace_conflict_set)
1533 {
1534 char* str;
1535
1536 str = DRD_(vc_aprint)(&q->vc);
1537 VG_(message)(Vg_DebugMsg,
sewardj1e29ebc2009-07-15 14:49:17 +00001538 "conflict set: [%d] ignoring segment %s\n", j, str);
bart8f822af2009-06-08 18:20:42 +00001539 VG_(free)(str);
1540 }
1541 }
1542 }
1543 }
1544
1545 DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1546
1547 p = DRD_(g_threadinfo)[tid].last;
1548 {
1549 for (j = 0; j < DRD_N_THREADS; j++)
1550 {
1551 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1552 {
1553 Segment* q;
1554 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1555 {
1556 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1557 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1558 {
1559 DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1560 }
1561 }
1562 }
1563 }
1564 }
1565
1566 DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1567
bart54803fe2009-06-21 09:26:27 +00001568 s_update_conflict_set_count++;
bart8f822af2009-06-08 18:20:42 +00001569
1570 if (s_trace_conflict_set_bm)
1571 {
sewardj1e29ebc2009-07-15 14:49:17 +00001572 VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
bart8f822af2009-06-08 18:20:42 +00001573 DRD_(bm_print)(DRD_(g_conflict_set));
sewardj1e29ebc2009-07-15 14:49:17 +00001574 VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
bart8f822af2009-06-08 18:20:42 +00001575 }
1576
1577 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1578}
1579
bart86a87df2009-03-04 19:26:47 +00001580/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001581ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001582{
bartbedfd232009-03-26 19:07:15 +00001583 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001584}
1585
bart86a87df2009-03-04 19:26:47 +00001586/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001587ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001588{
bartbedfd232009-03-26 19:07:15 +00001589 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001590}
1591
bart54803fe2009-06-21 09:26:27 +00001592/** Return how many times the conflict set has been updated entirely. */
1593ULong DRD_(thread_get_compute_conflict_set_count)()
sewardjaf44c822007-11-25 14:01:38 +00001594{
bart54803fe2009-06-21 09:26:27 +00001595 return s_compute_conflict_set_count;
1596}
1597
1598/** Return how many times the conflict set has been updated partially. */
1599ULong DRD_(thread_get_update_conflict_set_count)(void)
1600{
bartbedfd232009-03-26 19:07:15 +00001601 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001602}
1603
bart86a87df2009-03-04 19:26:47 +00001604/**
barte5214662009-06-21 11:51:23 +00001605 * Return how many times the conflict set has been updated partially
1606 * because a new segment has been created.
1607 */
1608ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
1609{
1610 return s_update_conflict_set_new_sg_count;
1611}
1612
1613/**
1614 * Return how many times the conflict set has been updated partially
1615 * because of combining vector clocks due to synchronization operations
1616 * other than reader/writer lock or barrier operations.
1617 */
1618ULong DRD_(thread_get_update_conflict_set_sync_count)(void)
1619{
1620 return s_update_conflict_set_sync_count;
1621}
1622
1623/**
1624 * Return how many times the conflict set has been updated partially
1625 * because of thread joins.
1626 */
1627ULong DRD_(thread_get_update_conflict_set_join_count)(void)
1628{
1629 return s_update_conflict_set_join_count;
1630}
1631
1632/**
bart86a87df2009-03-04 19:26:47 +00001633 * Return the number of first-level bitmaps that have been created during
1634 * conflict set updates.
1635 */
bart62a784c2009-02-15 13:11:14 +00001636ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001637{
bartbedfd232009-03-26 19:07:15 +00001638 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001639}
1640
bart86a87df2009-03-04 19:26:47 +00001641/**
1642 * Return the number of second-level bitmaps that have been created during
1643 * conflict set updates.
1644 */
bart62a784c2009-02-15 13:11:14 +00001645ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001646{
bartbedfd232009-03-26 19:07:15 +00001647 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001648}