blob: 90bd110afc89877f73933449eeea98e3cefdcfd0 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
bart86562bd2009-02-16 19:43:56 +00002 This file is part of drd, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00003
bart86562bd2009-02-16 19:43:56 +00004 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
sewardjaf44c822007-11-25 14:01:38 +00005
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307, USA.
20
21 The GNU General Public License is contained in the file COPYING.
22*/
23
24
25#include "drd_error.h"
bart09dc13f2009-02-14 15:13:31 +000026#include "drd_barrier.h"
bartd2c5eae2009-02-21 15:27:04 +000027#include "drd_clientobj.h"
bart09dc13f2009-02-14 15:13:31 +000028#include "drd_cond.h"
29#include "drd_mutex.h"
sewardjaf44c822007-11-25 14:01:38 +000030#include "drd_segment.h"
bart09dc13f2009-02-14 15:13:31 +000031#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000032#include "drd_suppression.h"
33#include "drd_thread.h"
bart82195c12008-04-13 17:35:08 +000034#include "pub_tool_vki.h"
sewardjaf44c822007-11-25 14:01:38 +000035#include "pub_tool_basics.h" // Addr, SizeT
36#include "pub_tool_errormgr.h" // VG_(unique_error)()
37#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);
sewardjaf44c822007-11-25 14:01:38 +000054
55
bart324a23b2009-02-15 12:14:52 +000056/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000057
bart86a87df2009-03-04 19:26:47 +000058static ULong s_context_switch_count;
59static ULong s_discard_ordered_segments_count;
60static ULong s_update_conflict_set_count;
61static ULong s_conflict_set_new_segment_count;
62static ULong s_conflict_set_combine_vc_count;
63static ULong s_conflict_set_bitmap_creation_count;
64static ULong s_conflict_set_bitmap2_creation_count;
65static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bart324a23b2009-02-15 12:14:52 +000066DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
67ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
68struct bitmap* DRD_(g_conflict_set);
bart86a87df2009-03-04 19:26:47 +000069static Bool s_trace_context_switches = False;
70static Bool s_trace_conflict_set = False;
71static Bool s_trace_fork_join = False;
72static Bool s_segment_merging = True;
sewardjaf44c822007-11-25 14:01:38 +000073
74
bart324a23b2009-02-15 12:14:52 +000075/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000076
bart86a87df2009-03-04 19:26:47 +000077/** Enables/disables context switch tracing. */
bart62a784c2009-02-15 13:11:14 +000078void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000079{
bart09dc13f2009-02-14 15:13:31 +000080 tl_assert(t == False || t == True);
bart86a87df2009-03-04 19:26:47 +000081 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000082}
83
bart86a87df2009-03-04 19:26:47 +000084/** Enables/disables conflict set tracing. */
bart62a784c2009-02-15 13:11:14 +000085void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000086{
bart09dc13f2009-02-14 15:13:31 +000087 tl_assert(t == False || t == True);
bart86a87df2009-03-04 19:26:47 +000088 s_trace_conflict_set = t;
bart26f73e12008-02-24 18:37:08 +000089}
90
bart86a87df2009-03-04 19:26:47 +000091/** Report whether fork/join tracing is enabled. */
bart09dc13f2009-02-14 15:13:31 +000092Bool DRD_(thread_get_trace_fork_join)(void)
93{
bart86a87df2009-03-04 19:26:47 +000094 return s_trace_fork_join;
bart09dc13f2009-02-14 15:13:31 +000095}
96
bart86a87df2009-03-04 19:26:47 +000097/** Enables/disables fork/join tracing. */
bart09dc13f2009-02-14 15:13:31 +000098void DRD_(thread_set_trace_fork_join)(const Bool t)
99{
100 tl_assert(t == False || t == True);
bart86a87df2009-03-04 19:26:47 +0000101 s_trace_fork_join = t;
bart09dc13f2009-02-14 15:13:31 +0000102}
103
bart86a87df2009-03-04 19:26:47 +0000104/** Enables/disables segment merging. */
bart62a784c2009-02-15 13:11:14 +0000105void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000106{
bart09dc13f2009-02-14 15:13:31 +0000107 tl_assert(m == False || m == True);
bart86a87df2009-03-04 19:26:47 +0000108 s_segment_merging = m;
barta9c37392008-03-22 09:38:48 +0000109}
110
sewardjaf44c822007-11-25 14:01:38 +0000111/**
bart86a87df2009-03-04 19:26:47 +0000112 * Convert Valgrind's ThreadId into a DrdThreadId.
113 *
114 * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
115 * Valgrind ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000116 */
bart62a784c2009-02-15 13:11:14 +0000117DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000118{
bart3772a982008-03-15 08:11:03 +0000119 int i;
sewardjaf44c822007-11-25 14:01:38 +0000120
bart3772a982008-03-15 08:11:03 +0000121 if (tid == VG_INVALID_THREADID)
122 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000123
bart3772a982008-03-15 08:11:03 +0000124 for (i = 1; i < DRD_N_THREADS; i++)
125 {
bart324a23b2009-02-15 12:14:52 +0000126 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
127 && DRD_(g_threadinfo)[i].vg_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000128 {
129 return i;
130 }
131 }
sewardjaf44c822007-11-25 14:01:38 +0000132
bart3772a982008-03-15 08:11:03 +0000133 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000134}
135
bart86a87df2009-03-04 19:26:47 +0000136/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000137static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000138{
bart3772a982008-03-15 08:11:03 +0000139 int i;
sewardjaf44c822007-11-25 14:01:38 +0000140
bart62a784c2009-02-15 13:11:14 +0000141 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000142
bart3772a982008-03-15 08:11:03 +0000143 for (i = 1; i < DRD_N_THREADS; i++)
144 {
bart324a23b2009-02-15 12:14:52 +0000145 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
146 && DRD_(g_threadinfo)[i].posix_thread_exists == False
147 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
bart3772a982008-03-15 08:11:03 +0000148 {
bart86a87df2009-03-04 19:26:47 +0000149 tl_assert(! DRD_(IsValidDrdThreadId)(i));
150
bart324a23b2009-02-15 12:14:52 +0000151 DRD_(g_threadinfo)[i].vg_thread_exists = True;
152 DRD_(g_threadinfo)[i].vg_threadid = tid;
153 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
154 DRD_(g_threadinfo)[i].stack_min = 0;
155 DRD_(g_threadinfo)[i].stack_min_min = 0;
156 DRD_(g_threadinfo)[i].stack_startup = 0;
157 DRD_(g_threadinfo)[i].stack_max = 0;
158 DRD_(g_threadinfo)[i].is_recording = True;
159 DRD_(g_threadinfo)[i].synchr_nesting = 0;
bart324a23b2009-02-15 12:14:52 +0000160 tl_assert(DRD_(g_threadinfo)[i].first == 0);
161 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart86a87df2009-03-04 19:26:47 +0000162
163 tl_assert(DRD_(IsValidDrdThreadId)(i));
164
bart3772a982008-03-15 08:11:03 +0000165 return i;
166 }
167 }
sewardjaf44c822007-11-25 14:01:38 +0000168
bart3772a982008-03-15 08:11:03 +0000169 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000170
bart3772a982008-03-15 08:11:03 +0000171 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000172}
173
bart86a87df2009-03-04 19:26:47 +0000174/** Convert a POSIX thread ID into a DRD thread ID. */
bart62a784c2009-02-15 13:11:14 +0000175DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000176{
bart3772a982008-03-15 08:11:03 +0000177 int i;
sewardjaf44c822007-11-25 14:01:38 +0000178
bart3772a982008-03-15 08:11:03 +0000179 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000180
bart3772a982008-03-15 08:11:03 +0000181 for (i = 1; i < DRD_N_THREADS; i++)
182 {
bart324a23b2009-02-15 12:14:52 +0000183 if (DRD_(g_threadinfo)[i].posix_thread_exists
184 && DRD_(g_threadinfo)[i].pt_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000185 {
186 return i;
187 }
188 }
189 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000190}
191
bart86a87df2009-03-04 19:26:47 +0000192/** Convert a DRD thread ID into a Valgrind thread ID. */
bart62a784c2009-02-15 13:11:14 +0000193ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000194{
bart74a5f212008-05-11 06:43:07 +0000195 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
196 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000197 return (DRD_(g_threadinfo)[tid].vg_thread_exists
198 ? DRD_(g_threadinfo)[tid].vg_threadid
bart3772a982008-03-15 08:11:03 +0000199 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000200}
201
bart23d3a4e2008-04-05 12:53:00 +0000202#if 0
bart324a23b2009-02-15 12:14:52 +0000203/**
204 * Sanity check of the doubly linked list of segments referenced by a
205 * ThreadInfo struct.
206 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000207 */
bart62a784c2009-02-15 13:11:14 +0000208static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000209{
bart3772a982008-03-15 08:11:03 +0000210 Segment* p;
211 for (p = ti->first; p; p = p->next) {
212 if (p->next && p->next->prev != p)
213 return False;
214 if (p->next == 0 && p != ti->last)
215 return False;
216 }
217 for (p = ti->last; p; p = p->prev) {
218 if (p->prev && p->prev->next != p)
219 return False;
220 if (p->prev == 0 && p != ti->first)
221 return False;
222 }
223 return True;
sewardjaf44c822007-11-25 14:01:38 +0000224}
bart23d3a4e2008-04-05 12:53:00 +0000225#endif
sewardjaf44c822007-11-25 14:01:38 +0000226
bart439c55f2009-02-15 10:38:37 +0000227/**
228 * Create the first segment for a newly started thread.
229 *
230 * This function is called from the handler installed via
231 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
232 * from the context of the creator thread, before the new thread has been
233 * created.
bart86a87df2009-03-04 19:26:47 +0000234 *
235 * @param[in] creator DRD thread ID of the creator thread.
236 * @param[in] vg_created Valgrind thread ID of the created thread.
237 *
238 * @return DRD thread ID of the created thread.
bart439c55f2009-02-15 10:38:37 +0000239 */
bart62a784c2009-02-15 13:11:14 +0000240DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
241 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000242{
bart3772a982008-03-15 08:11:03 +0000243 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000244
bart62a784c2009-02-15 13:11:14 +0000245 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
246 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
bart74a5f212008-05-11 06:43:07 +0000247 tl_assert(0 <= (int)created && created < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000248 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000249
bart324a23b2009-02-15 12:14:52 +0000250 tl_assert(DRD_(g_threadinfo)[created].first == 0);
251 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart86a87df2009-03-04 19:26:47 +0000252 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000253
bart3772a982008-03-15 08:11:03 +0000254 return created;
sewardjaf44c822007-11-25 14:01:38 +0000255}
256
bart439c55f2009-02-15 10:38:37 +0000257/**
bart86a87df2009-03-04 19:26:47 +0000258 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
259 * after the thread has been created and before any client instructions are run
bart439c55f2009-02-15 10:38:37 +0000260 * on the newly created thread, e.g. from the handler installed via
261 * VG_(track_pre_thread_first_insn)().
bart86a87df2009-03-04 19:26:47 +0000262 *
263 * @param[in] vg_created Valgrind thread ID of the newly created thread.
264 *
265 * @return DRD thread ID for the new thread.
bart439c55f2009-02-15 10:38:37 +0000266 */
bart62a784c2009-02-15 13:11:14 +0000267DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000268{
bart62a784c2009-02-15 13:11:14 +0000269 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000270
271 tl_assert(0 <= (int)created && created < DRD_N_THREADS
272 && created != DRD_INVALID_THREADID);
273
bart324a23b2009-02-15 12:14:52 +0000274 DRD_(g_threadinfo)[created].stack_max = VG_(thread_get_stack_max)(vg_created);
275 DRD_(g_threadinfo)[created].stack_startup = DRD_(g_threadinfo)[created].stack_max;
276 DRD_(g_threadinfo)[created].stack_min = DRD_(g_threadinfo)[created].stack_max;
277 DRD_(g_threadinfo)[created].stack_min_min = DRD_(g_threadinfo)[created].stack_max;
278 DRD_(g_threadinfo)[created].stack_size = VG_(thread_get_stack_size)(vg_created);
279 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000280
281 return created;
282}
bart09dc13f2009-02-14 15:13:31 +0000283
bart324a23b2009-02-15 12:14:52 +0000284/**
285 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
286 * after thread drd_joiner joined thread drd_joinee.
287 */
bart09dc13f2009-02-14 15:13:31 +0000288void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
289{
bart62a784c2009-02-15 13:11:14 +0000290 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
291 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
292 DRD_(thread_new_segment)(drd_joinee);
293 DRD_(thread_combine_vc)(drd_joiner, drd_joinee);
294 DRD_(thread_new_segment)(drd_joiner);
bart09dc13f2009-02-14 15:13:31 +0000295
bart86a87df2009-03-04 19:26:47 +0000296 if (s_trace_fork_join)
bart09dc13f2009-02-14 15:13:31 +0000297 {
bart62a784c2009-02-15 13:11:14 +0000298 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
299 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000300 const unsigned msg_size = 256;
301 char* msg;
302
303 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
304 tl_assert(msg);
305 VG_(snprintf)(msg, msg_size,
306 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
307 joiner, drd_joiner, joinee, drd_joinee);
308 if (joiner)
309 {
310 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
311 ", new vc: ");
bart41b226c2009-02-14 16:55:19 +0000312 DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart62a784c2009-02-15 13:11:14 +0000313 DRD_(thread_get_vc)(drd_joiner));
bart09dc13f2009-02-14 15:13:31 +0000314 }
315 VG_(message)(Vg_DebugMsg, "%s", msg);
316 VG_(free)(msg);
317 }
318
319 if (! DRD_(get_check_stack_accesses)())
320 {
bart62a784c2009-02-15 13:11:14 +0000321 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
322 - DRD_(thread_get_stack_size)(drd_joinee),
323 DRD_(thread_get_stack_max)(drd_joinee));
bart09dc13f2009-02-14 15:13:31 +0000324 }
bartd2c5eae2009-02-21 15:27:04 +0000325 DRD_(clientobj_delete_thread)(drd_joinee);
bart62a784c2009-02-15 13:11:14 +0000326 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000327}
328
bart324a23b2009-02-15 12:14:52 +0000329/**
330 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
331 * and accesses this data structure from multiple threads without locking.
332 * Any conflicting accesses in the range stack_startup..stack_max will be
333 * ignored.
334 */
bart62a784c2009-02-15 13:11:14 +0000335void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
336 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000337{
bart74a5f212008-05-11 06:43:07 +0000338 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
339 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000340 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
341 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
342 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000343}
344
bart86a87df2009-03-04 19:26:47 +0000345/** Return the stack pointer for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000346Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000347{
bart74a5f212008-05-11 06:43:07 +0000348 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000349 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000350 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000351}
352
bart86a87df2009-03-04 19:26:47 +0000353/**
354 * Return the lowest value that was ever assigned to the stack pointer
355 * for the specified thread.
356 */
bart62a784c2009-02-15 13:11:14 +0000357Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000358{
bart74a5f212008-05-11 06:43:07 +0000359 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000360 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000361 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000362}
363
bart86a87df2009-03-04 19:26:47 +0000364/** Return the top address for the stack of the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000365Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000366{
bart74a5f212008-05-11 06:43:07 +0000367 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartd43f8d32008-03-16 17:29:20 +0000368 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000369 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000370}
371
bart86a87df2009-03-04 19:26:47 +0000372/** Return the maximum stack size for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000373SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000374{
bart74a5f212008-05-11 06:43:07 +0000375 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000376 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000377 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000378}
379
bart09dc13f2009-02-14 15:13:31 +0000380/**
381 * Clean up thread-specific data structures. Call this just after
382 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000383 */
bart62a784c2009-02-15 13:11:14 +0000384void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000385{
bart3772a982008-03-15 08:11:03 +0000386 Segment* sg;
387 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000388
bart86a87df2009-03-04 19:26:47 +0000389 tl_assert(DRD_(IsValidDrdThreadId)(tid));
390
bart324a23b2009-02-15 12:14:52 +0000391 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
392 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
bart3772a982008-03-15 08:11:03 +0000393 {
394 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000395 sg->prev = 0;
396 sg->next = 0;
bart62ada3f2009-02-14 17:19:58 +0000397 DRD_(sg_put)(sg);
bart3772a982008-03-15 08:11:03 +0000398 }
bart324a23b2009-02-15 12:14:52 +0000399 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
400 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
401 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
402 DRD_(g_threadinfo)[tid].first = 0;
403 DRD_(g_threadinfo)[tid].last = 0;
bart86a87df2009-03-04 19:26:47 +0000404
405 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
sewardjaf44c822007-11-25 14:01:38 +0000406}
407
bart324a23b2009-02-15 12:14:52 +0000408/**
409 * Called after a thread performed its last memory access and before
410 * thread_delete() is called. Note: thread_delete() is only called for
411 * joinable threads, not for detached threads.
412 */
bart62a784c2009-02-15 13:11:14 +0000413void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000414{
bart74a5f212008-05-11 06:43:07 +0000415 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000416 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000417
bart324a23b2009-02-15 12:14:52 +0000418 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000419
bart324a23b2009-02-15 12:14:52 +0000420 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
bart3772a982008-03-15 08:11:03 +0000421 {
bart0d3bbd32009-03-12 18:35:44 +0000422 /*
423 * Once a detached thread has finished, its stack is deallocated and
424 * should no longer be taken into account when computing the conflict set.
425 */
bart324a23b2009-02-15 12:14:52 +0000426 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000427
bart0d3bbd32009-03-12 18:35:44 +0000428 /*
429 * For a detached thread, calling pthread_exit() invalidates the
430 * POSIX thread ID associated with the detached thread. For joinable
431 * POSIX threads however, the POSIX thread ID remains live after the
432 * pthread_exit() call until pthread_join() is called.
433 */
bart324a23b2009-02-15 12:14:52 +0000434 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
bart3772a982008-03-15 08:11:03 +0000435 }
sewardjaf44c822007-11-25 14:01:38 +0000436}
437
bart9b2974a2008-09-27 12:35:31 +0000438/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000439void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000440{
441 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
442 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000443 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000444
bart324a23b2009-02-15 12:14:52 +0000445 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000446}
447
bart86a87df2009-03-04 19:26:47 +0000448/** Store the POSIX thread ID for the specified thread. */
bart62a784c2009-02-15 13:11:14 +0000449void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000450{
bart74a5f212008-05-11 06:43:07 +0000451 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000452 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000453 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID);
bart3772a982008-03-15 08:11:03 +0000454 tl_assert(ptid != INVALID_POSIX_THREADID);
bart324a23b2009-02-15 12:14:52 +0000455 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
456 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000457}
458
bart86a87df2009-03-04 19:26:47 +0000459/** Returns true for joinable threads and false for detached threads. */
bart62a784c2009-02-15 13:11:14 +0000460Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000461{
bart74a5f212008-05-11 06:43:07 +0000462 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000463 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000464 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000465}
466
bart86a87df2009-03-04 19:26:47 +0000467/** Store the thread mode: joinable or detached. */
bart62a784c2009-02-15 13:11:14 +0000468void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000469{
bart74a5f212008-05-11 06:43:07 +0000470 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000471 && tid != DRD_INVALID_THREADID);
472 tl_assert(!! joinable == joinable);
bart324a23b2009-02-15 12:14:52 +0000473 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000474#if 0
bart3772a982008-03-15 08:11:03 +0000475 VG_(message)(Vg_DebugMsg,
476 "thread_set_joinable(%d/%d, %s)",
477 tid,
bart324a23b2009-02-15 12:14:52 +0000478 DRD_(g_threadinfo)[tid].vg_threadid,
bart3772a982008-03-15 08:11:03 +0000479 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000480#endif
bart324a23b2009-02-15 12:14:52 +0000481 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000482}
483
bart86a87df2009-03-04 19:26:47 +0000484/**
485 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
486 * conflict set.
487 */
bart62a784c2009-02-15 13:11:14 +0000488void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000489{
bart3772a982008-03-15 08:11:03 +0000490 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000491
bart86a87df2009-03-04 19:26:47 +0000492 if (vg_tid != s_vg_running_tid)
bart3772a982008-03-15 08:11:03 +0000493 {
bart62a784c2009-02-15 13:11:14 +0000494 DRD_(thread_set_running_tid)(vg_tid,
495 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
bart3772a982008-03-15 08:11:03 +0000496 }
sewardj8b09d4f2007-12-04 21:27:18 +0000497
bart86a87df2009-03-04 19:26:47 +0000498 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000499 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000500}
501
bart86a87df2009-03-04 19:26:47 +0000502/**
503 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
504 * conflict set.
505 */
bart62a784c2009-02-15 13:11:14 +0000506void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
507 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000508{
bart3772a982008-03-15 08:11:03 +0000509 tl_assert(vg_tid != VG_INVALID_THREADID);
510 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000511
bart86a87df2009-03-04 19:26:47 +0000512 if (vg_tid != s_vg_running_tid)
bart3772a982008-03-15 08:11:03 +0000513 {
bart86a87df2009-03-04 19:26:47 +0000514 if (s_trace_context_switches
bart324a23b2009-02-15 12:14:52 +0000515 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
bart3772a982008-03-15 08:11:03 +0000516 {
517 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000518 "Context switch from thread %d/%d to thread %d/%d;"
519 " segments: %llu",
bart86a87df2009-03-04 19:26:47 +0000520 s_vg_running_tid, DRD_(g_drd_running_tid),
bart62a784c2009-02-15 13:11:14 +0000521 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
bart62ada3f2009-02-14 17:19:58 +0000522 DRD_(sg_get_segments_alive_count)());
bart3772a982008-03-15 08:11:03 +0000523 }
bart86a87df2009-03-04 19:26:47 +0000524 s_vg_running_tid = vg_tid;
bart324a23b2009-02-15 12:14:52 +0000525 DRD_(g_drd_running_tid) = drd_tid;
bart86a87df2009-03-04 19:26:47 +0000526 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
527 s_context_switch_count++;
bart3772a982008-03-15 08:11:03 +0000528 }
sewardj8b09d4f2007-12-04 21:27:18 +0000529
bart86a87df2009-03-04 19:26:47 +0000530 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000531 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000532}
533
bart86a87df2009-03-04 19:26:47 +0000534/**
535 * Increase the synchronization nesting counter. Must be called before the
536 * client calls a synchronization function.
537 */
bart62a784c2009-02-15 13:11:14 +0000538int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000539{
bart62a784c2009-02-15 13:11:14 +0000540 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000541 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000542}
543
bart86a87df2009-03-04 19:26:47 +0000544/**
545 * Decrease the synchronization nesting counter. Must be called after the
546 * client left a synchronization function.
547 */
bart62a784c2009-02-15 13:11:14 +0000548int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000549{
bart62a784c2009-02-15 13:11:14 +0000550 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000551 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
552 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000553}
554
bart86a87df2009-03-04 19:26:47 +0000555/** Returns the synchronization nesting counter. */
bart62a784c2009-02-15 13:11:14 +0000556int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000557{
bart62a784c2009-02-15 13:11:14 +0000558 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000559 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000560}
561
bart1a473c72008-03-13 19:03:38 +0000562/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000563static
bart86a87df2009-03-04 19:26:47 +0000564void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000565{
bart74a5f212008-05-11 06:43:07 +0000566 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000567 && tid != DRD_INVALID_THREADID);
bart62a784c2009-02-15 13:11:14 +0000568 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart324a23b2009-02-15 12:14:52 +0000569 sg->prev = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +0000570 sg->next = 0;
bart324a23b2009-02-15 12:14:52 +0000571 if (DRD_(g_threadinfo)[tid].last)
572 DRD_(g_threadinfo)[tid].last->next = sg;
573 DRD_(g_threadinfo)[tid].last = sg;
574 if (DRD_(g_threadinfo)[tid].first == 0)
575 DRD_(g_threadinfo)[tid].first = sg;
bart62a784c2009-02-15 13:11:14 +0000576 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000577}
578
bart324a23b2009-02-15 12:14:52 +0000579/**
580 * Remove a segment from the segment list of thread threadid, and free the
581 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000582 */
bart62a784c2009-02-15 13:11:14 +0000583static
bart86a87df2009-03-04 19:26:47 +0000584void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000585{
bart74a5f212008-05-11 06:43:07 +0000586 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000587 && tid != DRD_INVALID_THREADID);
bart62a784c2009-02-15 13:11:14 +0000588 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart26f73e12008-02-24 18:37:08 +0000589
bart3772a982008-03-15 08:11:03 +0000590 if (sg->prev)
591 sg->prev->next = sg->next;
592 if (sg->next)
593 sg->next->prev = sg->prev;
bart324a23b2009-02-15 12:14:52 +0000594 if (sg == DRD_(g_threadinfo)[tid].first)
595 DRD_(g_threadinfo)[tid].first = sg->next;
596 if (sg == DRD_(g_threadinfo)[tid].last)
597 DRD_(g_threadinfo)[tid].last = sg->prev;
bart62ada3f2009-02-14 17:19:58 +0000598 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000599
bart62a784c2009-02-15 13:11:14 +0000600 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000601}
602
bart86a87df2009-03-04 19:26:47 +0000603/**
604 * Returns a pointer to the vector clock of the most recent segment associated
605 * with thread 'tid'.
606 */
bart62a784c2009-02-15 13:11:14 +0000607VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000608{
bart74a5f212008-05-11 06:43:07 +0000609 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
610 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000611 tl_assert(DRD_(g_threadinfo)[tid].last);
612 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000613}
614
bart324a23b2009-02-15 12:14:52 +0000615/**
616 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000617 */
bart62a784c2009-02-15 13:11:14 +0000618void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000619{
620 tl_assert(sg);
bart74a5f212008-05-11 06:43:07 +0000621 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
622 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000623 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000624
bart62ada3f2009-02-14 17:19:58 +0000625 DRD_(sg_put)(*sg);
bart324a23b2009-02-15 12:14:52 +0000626 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000627}
628
sewardjaf44c822007-11-25 14:01:38 +0000629/**
630 * Compute the minimum of all latest vector clocks of all threads
631 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
bart86a87df2009-03-04 19:26:47 +0000632 *
sewardjaf44c822007-11-25 14:01:38 +0000633 * @param vc pointer to a vectorclock, holds result upon return.
634 */
bart62a784c2009-02-15 13:11:14 +0000635static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000636{
bart3772a982008-03-15 08:11:03 +0000637 unsigned i;
638 Bool first;
639 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000640
bart3772a982008-03-15 08:11:03 +0000641 first = True;
bart62a784c2009-02-15 13:11:14 +0000642 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
643 i++)
bart3772a982008-03-15 08:11:03 +0000644 {
bart324a23b2009-02-15 12:14:52 +0000645 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000646 if (latest_sg)
647 {
648 if (first)
bart41b226c2009-02-14 16:55:19 +0000649 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000650 else
bart41b226c2009-02-14 16:55:19 +0000651 DRD_(vc_min)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000652 first = False;
653 }
654 }
sewardjaf44c822007-11-25 14:01:38 +0000655}
656
bart86a87df2009-03-04 19:26:47 +0000657/**
658 * Compute the maximum of all latest vector clocks of all threads.
659 *
660 * @param vc pointer to a vectorclock, holds result upon return.
661 */
bart62a784c2009-02-15 13:11:14 +0000662static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000663{
bart3772a982008-03-15 08:11:03 +0000664 unsigned i;
665 Bool first;
666 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000667
bart3772a982008-03-15 08:11:03 +0000668 first = True;
bart62a784c2009-02-15 13:11:14 +0000669 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
670 i++)
bart3772a982008-03-15 08:11:03 +0000671 {
bart324a23b2009-02-15 12:14:52 +0000672 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000673 if (latest_sg)
674 {
675 if (first)
bart41b226c2009-02-14 16:55:19 +0000676 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000677 else
bart41b226c2009-02-14 16:55:19 +0000678 DRD_(vc_combine)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000679 first = False;
680 }
681 }
sewardjaf44c822007-11-25 14:01:38 +0000682}
683
684/**
bart5bd9f2d2008-03-03 20:31:58 +0000685 * Discard all segments that have a defined order against the latest vector
bart86a87df2009-03-04 19:26:47 +0000686 * clock of all threads -- these segments can no longer be involved in a
sewardjaf44c822007-11-25 14:01:38 +0000687 * data race.
688 */
bart62a784c2009-02-15 13:11:14 +0000689static void DRD_(thread_discard_ordered_segments)(void)
sewardjaf44c822007-11-25 14:01:38 +0000690{
bart3772a982008-03-15 08:11:03 +0000691 unsigned i;
692 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000693
bart86a87df2009-03-04 19:26:47 +0000694 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000695
bart41b226c2009-02-14 16:55:19 +0000696 DRD_(vc_init)(&thread_vc_min, 0, 0);
bart62a784c2009-02-15 13:11:14 +0000697 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
bart62ada3f2009-02-14 17:19:58 +0000698 if (DRD_(sg_get_trace)())
bart3772a982008-03-15 08:11:03 +0000699 {
700 char msg[256];
701 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000702
bart41b226c2009-02-14 16:55:19 +0000703 DRD_(vc_init)(&thread_vc_max, 0, 0);
bart62a784c2009-02-15 13:11:14 +0000704 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart3772a982008-03-15 08:11:03 +0000705 VG_(snprintf)(msg, sizeof(msg),
706 "Discarding ordered segments -- min vc is ");
bart41b226c2009-02-14 16:55:19 +0000707 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
708 &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000709 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
710 ", max vc is ");
bart41b226c2009-02-14 16:55:19 +0000711 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
712 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000713 VG_(message)(Vg_UserMsg, "%s", msg);
bart41b226c2009-02-14 16:55:19 +0000714 DRD_(vc_cleanup)(&thread_vc_max);
bart3772a982008-03-15 08:11:03 +0000715 }
sewardjaf44c822007-11-25 14:01:38 +0000716
bart62a784c2009-02-15 13:11:14 +0000717 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
718 i++)
bart3772a982008-03-15 08:11:03 +0000719 {
720 Segment* sg;
721 Segment* sg_next;
bart324a23b2009-02-15 12:14:52 +0000722 for (sg = DRD_(g_threadinfo)[i].first;
bart41b226c2009-02-14 16:55:19 +0000723 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000724 sg = sg_next)
725 {
bart86a87df2009-03-04 19:26:47 +0000726 thread_discard_segment(i, sg);
bart3772a982008-03-15 08:11:03 +0000727 }
728 }
bart41b226c2009-02-14 16:55:19 +0000729 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000730}
731
bart324a23b2009-02-15 12:14:52 +0000732/**
733 * Merge all segments that may be merged without triggering false positives
734 * or discarding real data races. For the theoretical background of segment
735 * merging, see also the following paper:
736 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
737 * Bounding the number of segment histories during data race detection.
738 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
739 * September 2002.
barta9c37392008-03-22 09:38:48 +0000740 */
741static void thread_merge_segments(void)
742{
743 unsigned i;
744
bart62a784c2009-02-15 13:11:14 +0000745 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
746 i++)
barta9c37392008-03-22 09:38:48 +0000747 {
748 Segment* sg;
749
bart62a784c2009-02-15 13:11:14 +0000750 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000751
bart324a23b2009-02-15 12:14:52 +0000752 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000753 {
bart62ada3f2009-02-14 17:19:58 +0000754 if (DRD_(sg_get_refcnt)(sg) == 1
barta9c37392008-03-22 09:38:48 +0000755 && sg->next
bart62ada3f2009-02-14 17:19:58 +0000756 && DRD_(sg_get_refcnt)(sg->next) == 1
barta9c37392008-03-22 09:38:48 +0000757 && sg->next->next)
758 {
759 /* Merge sg and sg->next into sg. */
bart62ada3f2009-02-14 17:19:58 +0000760 DRD_(sg_merge)(sg, sg->next);
bart86a87df2009-03-04 19:26:47 +0000761 thread_discard_segment(i, sg->next);
barta9c37392008-03-22 09:38:48 +0000762 }
763 }
764
bart62a784c2009-02-15 13:11:14 +0000765 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000766 }
767}
768
bart324a23b2009-02-15 12:14:52 +0000769/**
bart324a23b2009-02-15 12:14:52 +0000770 * Create a new segment for the specified thread, and discard any segments
771 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000772 */
bart62a784c2009-02-15 13:11:14 +0000773void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000774{
bartd66e3a82008-04-06 15:02:17 +0000775 Segment* new_sg;
776
bart74a5f212008-05-11 06:43:07 +0000777 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
778 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000779
bart62ada3f2009-02-14 17:19:58 +0000780 new_sg = DRD_(sg_new)(tid, tid);
bart86a87df2009-03-04 19:26:47 +0000781 thread_append_segment(tid, new_sg);
bartd66e3a82008-04-06 15:02:17 +0000782
bart86a87df2009-03-04 19:26:47 +0000783 thread_compute_conflict_set(&DRD_(g_conflict_set), DRD_(g_drd_running_tid));
784 s_conflict_set_new_segment_count++;
sewardjaf44c822007-11-25 14:01:38 +0000785
bart62a784c2009-02-15 13:11:14 +0000786 DRD_(thread_discard_ordered_segments)();
bart26f73e12008-02-24 18:37:08 +0000787
bart86a87df2009-03-04 19:26:47 +0000788 if (s_segment_merging)
bart324a23b2009-02-15 12:14:52 +0000789 {
barta9c37392008-03-22 09:38:48 +0000790 thread_merge_segments();
bart324a23b2009-02-15 12:14:52 +0000791 }
sewardjaf44c822007-11-25 14:01:38 +0000792}
793
bart26f73e12008-02-24 18:37:08 +0000794/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart62a784c2009-02-15 13:11:14 +0000795void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000796{
bart3772a982008-03-15 08:11:03 +0000797 tl_assert(joiner != joinee);
bart74a5f212008-05-11 06:43:07 +0000798 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000799 && joiner != DRD_INVALID_THREADID);
bart74a5f212008-05-11 06:43:07 +0000800 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000801 && joinee != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000802 tl_assert(DRD_(g_threadinfo)[joiner].last);
803 tl_assert(DRD_(g_threadinfo)[joinee].last);
804 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
805 &DRD_(g_threadinfo)[joinee].last->vc);
bart62a784c2009-02-15 13:11:14 +0000806 DRD_(thread_discard_ordered_segments)();
sewardjaf44c822007-11-25 14:01:38 +0000807
bart324a23b2009-02-15 12:14:52 +0000808 if (joiner == DRD_(g_drd_running_tid))
bart3772a982008-03-15 08:11:03 +0000809 {
bart86a87df2009-03-04 19:26:47 +0000810 thread_compute_conflict_set(&DRD_(g_conflict_set), joiner);
bart3772a982008-03-15 08:11:03 +0000811 }
sewardjaf44c822007-11-25 14:01:38 +0000812}
813
bart324a23b2009-02-15 12:14:52 +0000814/**
815 * Call this function after thread 'tid' had to wait because of thread
816 * synchronization until the memory accesses in the segment with vector clock
817 * 'vc' finished.
bart26f73e12008-02-24 18:37:08 +0000818 */
bart62a784c2009-02-15 13:11:14 +0000819void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc)
sewardjaf44c822007-11-25 14:01:38 +0000820{
bart74a5f212008-05-11 06:43:07 +0000821 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
822 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000823 tl_assert(DRD_(g_threadinfo)[tid].last);
bart3772a982008-03-15 08:11:03 +0000824 tl_assert(vc);
bart324a23b2009-02-15 12:14:52 +0000825 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
bart86a87df2009-03-04 19:26:47 +0000826 thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
bart62a784c2009-02-15 13:11:14 +0000827 DRD_(thread_discard_ordered_segments)();
bart86a87df2009-03-04 19:26:47 +0000828 s_conflict_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000829}
830
bart324a23b2009-02-15 12:14:52 +0000831/**
832 * Call this function whenever a thread is no longer using the memory
833 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
834 * increase.
bart26f73e12008-02-24 18:37:08 +0000835 */
bart62a784c2009-02-15 13:11:14 +0000836void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000837{
bartd43f8d32008-03-16 17:29:20 +0000838 DrdThreadId other_user;
839 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000840
bart3772a982008-03-15 08:11:03 +0000841 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000842 other_user = DRD_INVALID_THREADID;
bart62a784c2009-02-15 13:11:14 +0000843 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
844 i++)
bart3772a982008-03-15 08:11:03 +0000845 {
846 Segment* p;
bart324a23b2009-02-15 12:14:52 +0000847 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +0000848 {
849 if (other_user == DRD_INVALID_THREADID
bart324a23b2009-02-15 12:14:52 +0000850 && i != DRD_(g_drd_running_tid))
sewardjaf44c822007-11-25 14:01:38 +0000851 {
bart99edb292009-02-15 15:59:20 +0000852 if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2)))
bart8bf2f8b2008-03-30 17:56:43 +0000853 {
854 other_user = i;
855 }
856 continue;
sewardjaf44c822007-11-25 14:01:38 +0000857 }
bart99edb292009-02-15 15:59:20 +0000858 DRD_(bm_clear)(p->bm, a1, a2);
bart3772a982008-03-15 08:11:03 +0000859 }
860 }
sewardjaf44c822007-11-25 14:01:38 +0000861
bart324a23b2009-02-15 12:14:52 +0000862 /*
863 * If any other thread had accessed memory in [ a1, a2 [, update the
864 * conflict set.
865 */
bart3772a982008-03-15 08:11:03 +0000866 if (other_user != DRD_INVALID_THREADID
bart99edb292009-02-15 15:59:20 +0000867 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
bart3772a982008-03-15 08:11:03 +0000868 {
bart86a87df2009-03-04 19:26:47 +0000869 thread_compute_conflict_set(&DRD_(g_conflict_set),
bart62a784c2009-02-15 13:11:14 +0000870 DRD_(thread_get_running_tid)());
bart3772a982008-03-15 08:11:03 +0000871 }
sewardjaf44c822007-11-25 14:01:38 +0000872}
873
bart86a87df2009-03-04 19:26:47 +0000874/** Start recording memory access information. */
bart62a784c2009-02-15 13:11:14 +0000875void DRD_(thread_start_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000876{
bart74a5f212008-05-11 06:43:07 +0000877 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
878 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000879 tl_assert(! DRD_(g_threadinfo)[tid].is_recording);
880 DRD_(g_threadinfo)[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000881}
882
bart86a87df2009-03-04 19:26:47 +0000883/** Stop recording memory access information. */
bart62a784c2009-02-15 13:11:14 +0000884void DRD_(thread_stop_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000885{
bart74a5f212008-05-11 06:43:07 +0000886 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
887 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000888 tl_assert(DRD_(g_threadinfo)[tid].is_recording);
889 DRD_(g_threadinfo)[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000890}
891
bart86a87df2009-03-04 19:26:47 +0000892/**
893 * Print the segment information for all threads.
894 *
895 * This function is only used for debugging purposes.
896 */
bart62a784c2009-02-15 13:11:14 +0000897void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +0000898{
bart3772a982008-03-15 08:11:03 +0000899 unsigned i;
900 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000901
bart62a784c2009-02-15 13:11:14 +0000902 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
903 i++)
bart3772a982008-03-15 08:11:03 +0000904 {
bart324a23b2009-02-15 12:14:52 +0000905 if (DRD_(g_threadinfo)[i].first)
bart3772a982008-03-15 08:11:03 +0000906 {
907 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000908 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000909 "**************\n",
910 i,
bart324a23b2009-02-15 12:14:52 +0000911 DRD_(g_threadinfo)[i].vg_thread_exists,
912 DRD_(g_threadinfo)[i].vg_threadid,
913 DRD_(g_threadinfo)[i].posix_thread_exists,
914 DRD_(g_threadinfo)[i].pt_threadid,
915 DRD_(g_threadinfo)[i].detached_posix_thread);
916 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000917 {
bart62ada3f2009-02-14 17:19:58 +0000918 DRD_(sg_print)(p);
sewardjaf44c822007-11-25 14:01:38 +0000919 }
bart3772a982008-03-15 08:11:03 +0000920 }
921 }
sewardjaf44c822007-11-25 14:01:38 +0000922}
923
bart86a87df2009-03-04 19:26:47 +0000924/** Show a call stack involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000925static void show_call_stack(const DrdThreadId tid,
926 const Char* const msg,
927 ExeContext* const callstack)
928{
bart62a784c2009-02-15 13:11:14 +0000929 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +0000930
bartaa97a542008-03-16 17:57:01 +0000931 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000932
bart3772a982008-03-15 08:11:03 +0000933 if (vg_tid != VG_INVALID_THREADID)
934 {
935 if (callstack)
936 {
937 VG_(pp_ExeContext)(callstack);
938 }
939 else
940 {
941 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
942 }
943 }
944 else
945 {
946 VG_(message)(Vg_UserMsg,
947 " (thread finished, call stack no longer available)");
948 }
sewardjaf44c822007-11-25 14:01:38 +0000949}
950
bart86a87df2009-03-04 19:26:47 +0000951/** Print information about the segments involved in a data race. */
sewardjaf44c822007-11-25 14:01:38 +0000952static void
953thread_report_conflicting_segments_segment(const DrdThreadId tid,
954 const Addr addr,
955 const SizeT size,
956 const BmAccessTypeT access_type,
957 const Segment* const p)
958{
bart3772a982008-03-15 08:11:03 +0000959 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000960
bart74a5f212008-05-11 06:43:07 +0000961 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000962 && tid != DRD_INVALID_THREADID);
963 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000964
bart62a784c2009-02-15 13:11:14 +0000965 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
966 i++)
bart3772a982008-03-15 08:11:03 +0000967 {
968 if (i != tid)
969 {
970 Segment* q;
bart324a23b2009-02-15 12:14:52 +0000971 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000972 {
bart324a23b2009-02-15 12:14:52 +0000973 /*
974 * Since q iterates over the segments of thread i in order of
975 * decreasing vector clocks, if q->vc <= p->vc, then
976 * q->next->vc <= p->vc will also hold. Hence, break out of the
977 * loop once this condition is met.
978 */
bart41b226c2009-02-14 16:55:19 +0000979 if (DRD_(vc_lte)(&q->vc, &p->vc))
bart3772a982008-03-15 08:11:03 +0000980 break;
bart41b226c2009-02-14 16:55:19 +0000981 if (! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000982 {
bart99edb292009-02-15 15:59:20 +0000983 if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size,
984 access_type))
bart3772a982008-03-15 08:11:03 +0000985 {
986 tl_assert(q->stacktrace);
987 show_call_stack(i, "Other segment start",
988 q->stacktrace);
989 show_call_stack(i, "Other segment end",
990 q->next ? q->next->stacktrace : 0);
991 }
992 }
sewardjaf44c822007-11-25 14:01:38 +0000993 }
bart3772a982008-03-15 08:11:03 +0000994 }
995 }
sewardjaf44c822007-11-25 14:01:38 +0000996}
997
bart86a87df2009-03-04 19:26:47 +0000998/** Print information about all segments involved in a data race. */
bart62a784c2009-02-15 13:11:14 +0000999void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1000 const Addr addr,
1001 const SizeT size,
1002 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001003{
bart3772a982008-03-15 08:11:03 +00001004 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001005
bart74a5f212008-05-11 06:43:07 +00001006 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +00001007 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001008
bart324a23b2009-02-15 12:14:52 +00001009 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +00001010 {
bart99edb292009-02-15 15:59:20 +00001011 if (DRD_(bm_has)(p->bm, addr, addr + size, access_type))
bart3772a982008-03-15 08:11:03 +00001012 {
1013 thread_report_conflicting_segments_segment(tid, addr, size,
1014 access_type, p);
1015 }
1016 }
sewardjaf44c822007-11-25 14:01:38 +00001017}
sewardjaf44c822007-11-25 14:01:38 +00001018
bart324a23b2009-02-15 12:14:52 +00001019/**
bart324a23b2009-02-15 12:14:52 +00001020 * Compute a bitmap that represents the union of all memory accesses of all
1021 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001022 */
bart86a87df2009-03-04 19:26:47 +00001023static void thread_compute_conflict_set(struct bitmap** conflict_set,
1024 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001025{
bart3772a982008-03-15 08:11:03 +00001026 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001027
bart74a5f212008-05-11 06:43:07 +00001028 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1029 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +00001030 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001031
bart86a87df2009-03-04 19:26:47 +00001032 s_update_conflict_set_count++;
1033 s_conflict_set_bitmap_creation_count -= DRD_(bm_get_bitmap_creation_count)();
1034 s_conflict_set_bitmap2_creation_count -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001035
barte73b0aa2008-06-28 07:19:56 +00001036 if (*conflict_set)
bart3772a982008-03-15 08:11:03 +00001037 {
bart99edb292009-02-15 15:59:20 +00001038 DRD_(bm_delete)(*conflict_set);
bart3772a982008-03-15 08:11:03 +00001039 }
bart99edb292009-02-15 15:59:20 +00001040 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001041
bart86a87df2009-03-04 19:26:47 +00001042 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001043 {
1044 char msg[256];
1045
1046 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001047 "computing conflict set for thread %d/%d with vc ",
bart62a784c2009-02-15 13:11:14 +00001048 DRD_(DrdThreadIdToVgThreadId)(tid), tid);
bart41b226c2009-02-14 16:55:19 +00001049 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1050 sizeof(msg) - VG_(strlen)(msg),
bart324a23b2009-02-15 12:14:52 +00001051 &DRD_(g_threadinfo)[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +00001052 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001053 }
1054
bart324a23b2009-02-15 12:14:52 +00001055 p = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +00001056 {
1057 unsigned j;
1058
bart86a87df2009-03-04 19:26:47 +00001059 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001060 {
bart26f73e12008-02-24 18:37:08 +00001061 char msg[256];
1062
1063 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001064 "conflict set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +00001065 tid);
bart41b226c2009-02-14 16:55:19 +00001066 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1067 sizeof(msg) - VG_(strlen)(msg),
1068 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +00001069 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001070 }
sewardjaf44c822007-11-25 14:01:38 +00001071
bart0d3bbd32009-03-12 18:35:44 +00001072 for (j = 0; j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
1073 j++)
bart3772a982008-03-15 08:11:03 +00001074 {
bart62a784c2009-02-15 13:11:14 +00001075 if (j != tid && DRD_(IsValidDrdThreadId)(j))
bart26f73e12008-02-24 18:37:08 +00001076 {
bart3772a982008-03-15 08:11:03 +00001077 const Segment* q;
bart324a23b2009-02-15 12:14:52 +00001078 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +00001079 {
bart41b226c2009-02-14 16:55:19 +00001080 if (! DRD_(vc_lte)(&q->vc, &p->vc) && ! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +00001081 {
bart86a87df2009-03-04 19:26:47 +00001082 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001083 {
1084 char msg[256];
1085 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001086 "conflict set: [%d] merging segment ", j);
bart41b226c2009-02-14 16:55:19 +00001087 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1088 sizeof(msg) - VG_(strlen)(msg),
1089 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001090 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001091 }
bart99edb292009-02-15 15:59:20 +00001092 DRD_(bm_merge2)(*conflict_set, q->bm);
bart3772a982008-03-15 08:11:03 +00001093 }
1094 else
1095 {
bart86a87df2009-03-04 19:26:47 +00001096 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001097 {
1098 char msg[256];
1099 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001100 "conflict set: [%d] ignoring segment ", j);
bart41b226c2009-02-14 16:55:19 +00001101 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1102 sizeof(msg) - VG_(strlen)(msg),
1103 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001104 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001105 }
1106 }
bartd66e3a82008-04-06 15:02:17 +00001107 }
bart26f73e12008-02-24 18:37:08 +00001108 }
bart3772a982008-03-15 08:11:03 +00001109 }
bart3772a982008-03-15 08:11:03 +00001110 }
sewardjaf44c822007-11-25 14:01:38 +00001111
bart86a87df2009-03-04 19:26:47 +00001112 s_conflict_set_bitmap_creation_count += DRD_(bm_get_bitmap_creation_count)();
1113 s_conflict_set_bitmap2_creation_count += DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001114
bart86a87df2009-03-04 19:26:47 +00001115 if (0 && s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001116 {
barte73b0aa2008-06-28 07:19:56 +00001117 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
bart99edb292009-02-15 15:59:20 +00001118 DRD_(bm_print)(*conflict_set);
barte73b0aa2008-06-28 07:19:56 +00001119 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
bart3772a982008-03-15 08:11:03 +00001120 }
sewardjaf44c822007-11-25 14:01:38 +00001121}
1122
bart86a87df2009-03-04 19:26:47 +00001123/** Report the number of context switches performed. */
bart62a784c2009-02-15 13:11:14 +00001124ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001125{
bart86a87df2009-03-04 19:26:47 +00001126 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001127}
1128
bart86a87df2009-03-04 19:26:47 +00001129/** Report the number of ordered segments that have been discarded. */
bart62a784c2009-02-15 13:11:14 +00001130ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001131{
bart86a87df2009-03-04 19:26:47 +00001132 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001133}
1134
bart86a87df2009-03-04 19:26:47 +00001135/** Return how many times the conflict set has been updated. */
bart62a784c2009-02-15 13:11:14 +00001136ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001137{
bartd66e3a82008-04-06 15:02:17 +00001138 tl_assert(dsnsc);
1139 tl_assert(dscvc);
bart86a87df2009-03-04 19:26:47 +00001140 *dsnsc = s_conflict_set_new_segment_count;
1141 *dscvc = s_conflict_set_combine_vc_count;
1142 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001143}
1144
bart86a87df2009-03-04 19:26:47 +00001145/**
1146 * Return the number of first-level bitmaps that have been created during
1147 * conflict set updates.
1148 */
bart62a784c2009-02-15 13:11:14 +00001149ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001150{
bart86a87df2009-03-04 19:26:47 +00001151 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001152}
1153
bart86a87df2009-03-04 19:26:47 +00001154/**
1155 * Return the number of second-level bitmaps that have been created during
1156 * conflict set updates.
1157 */
bart62a784c2009-02-15 13:11:14 +00001158ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001159{
bart86a87df2009-03-04 19:26:47 +00001160 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001161}