blob: cdb02822e34a1c0485bfe58182ca95eee41b90d7 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
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"
28#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
50static void thread_append_segment(const DrdThreadId tid,
51 Segment* const sg);
barta2b6e1b2008-03-17 18:32:39 +000052static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
barte73b0aa2008-06-28 07:19:56 +000053static Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
54static void thread_compute_conflict_set(struct bitmap** conflict_set,
55 const DrdThreadId tid);
sewardjaf44c822007-11-25 14:01:38 +000056
57
bart324a23b2009-02-15 12:14:52 +000058/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000059
bart324a23b2009-02-15 12:14:52 +000060static ULong DRD_(s_context_switch_count);
61static ULong DRD_(s_discard_ordered_segments_count);
62static ULong DRD_(s_update_conflict_set_count);
63static ULong DRD_(s_conflict_set_new_segment_count);
64static ULong DRD_(s_conflict_set_combine_vc_count);
65static ULong DRD_(s_conflict_set_bitmap_creation_count);
66static ULong DRD_(s_conflict_set_bitmap2_creation_count);
67static ThreadId DRD_(s_vg_running_tid) = VG_INVALID_THREADID;
68DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
69ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
70struct bitmap* DRD_(g_conflict_set);
71static Bool DRD_(s_trace_context_switches) = False;
72static Bool DRD_(s_trace_conflict_set) = False;
73static Bool DRD_(s_trace_fork_join) = False;
74static Bool DRD_(s_segment_merging) = True;
sewardjaf44c822007-11-25 14:01:38 +000075
76
bart324a23b2009-02-15 12:14:52 +000077/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000078
bart26f73e12008-02-24 18:37:08 +000079void thread_trace_context_switches(const Bool t)
80{
bart09dc13f2009-02-14 15:13:31 +000081 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +000082 DRD_(s_trace_context_switches) = t;
bart26f73e12008-02-24 18:37:08 +000083}
84
barte73b0aa2008-06-28 07:19:56 +000085void 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);
bart324a23b2009-02-15 12:14:52 +000088 DRD_(s_trace_conflict_set) = t;
bart26f73e12008-02-24 18:37:08 +000089}
90
bart09dc13f2009-02-14 15:13:31 +000091Bool DRD_(thread_get_trace_fork_join)(void)
92{
bart324a23b2009-02-15 12:14:52 +000093 return DRD_(s_trace_fork_join);
bart09dc13f2009-02-14 15:13:31 +000094}
95
96void DRD_(thread_set_trace_fork_join)(const Bool t)
97{
98 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +000099 DRD_(s_trace_fork_join) = t;
bart09dc13f2009-02-14 15:13:31 +0000100}
101
barta9c37392008-03-22 09:38:48 +0000102void thread_set_segment_merging(const Bool m)
103{
bart09dc13f2009-02-14 15:13:31 +0000104 tl_assert(m == False || m == True);
bart324a23b2009-02-15 12:14:52 +0000105 DRD_(s_segment_merging) = m;
barta9c37392008-03-22 09:38:48 +0000106}
107
sewardjaf44c822007-11-25 14:01:38 +0000108/**
109 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
110 * Valgrind's ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000111 */
sewardjaf44c822007-11-25 14:01:38 +0000112DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid)
113{
bart3772a982008-03-15 08:11:03 +0000114 int i;
sewardjaf44c822007-11-25 14:01:38 +0000115
bart3772a982008-03-15 08:11:03 +0000116 if (tid == VG_INVALID_THREADID)
117 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000118
bart3772a982008-03-15 08:11:03 +0000119 for (i = 1; i < DRD_N_THREADS; i++)
120 {
bart324a23b2009-02-15 12:14:52 +0000121 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
122 && DRD_(g_threadinfo)[i].vg_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000123 {
124 return i;
125 }
126 }
sewardjaf44c822007-11-25 14:01:38 +0000127
bart3772a982008-03-15 08:11:03 +0000128 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000129}
130
131static
132DrdThreadId VgThreadIdToNewDrdThreadId(const ThreadId tid)
133{
bart3772a982008-03-15 08:11:03 +0000134 int i;
sewardjaf44c822007-11-25 14:01:38 +0000135
bart3772a982008-03-15 08:11:03 +0000136 tl_assert(VgThreadIdToDrdThreadId(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000137
bart3772a982008-03-15 08:11:03 +0000138 for (i = 1; i < DRD_N_THREADS; i++)
139 {
bart324a23b2009-02-15 12:14:52 +0000140 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
141 && DRD_(g_threadinfo)[i].posix_thread_exists == False
142 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
bart3772a982008-03-15 08:11:03 +0000143 {
bart324a23b2009-02-15 12:14:52 +0000144 DRD_(g_threadinfo)[i].vg_thread_exists = True;
145 DRD_(g_threadinfo)[i].vg_threadid = tid;
146 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
147 DRD_(g_threadinfo)[i].stack_min = 0;
148 DRD_(g_threadinfo)[i].stack_min_min = 0;
149 DRD_(g_threadinfo)[i].stack_startup = 0;
150 DRD_(g_threadinfo)[i].stack_max = 0;
151 DRD_(g_threadinfo)[i].is_recording = True;
152 DRD_(g_threadinfo)[i].synchr_nesting = 0;
153 if (DRD_(g_threadinfo)[i].first != 0)
bart3772a982008-03-15 08:11:03 +0000154 VG_(printf)("drd thread id = %d\n", i);
bart324a23b2009-02-15 12:14:52 +0000155 tl_assert(DRD_(g_threadinfo)[i].first == 0);
156 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart3772a982008-03-15 08:11:03 +0000157 return i;
158 }
159 }
sewardjaf44c822007-11-25 14:01:38 +0000160
bart3772a982008-03-15 08:11:03 +0000161 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000162
bart3772a982008-03-15 08:11:03 +0000163 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000164}
165
166DrdThreadId PtThreadIdToDrdThreadId(const PThreadId tid)
167{
bart3772a982008-03-15 08:11:03 +0000168 int i;
sewardjaf44c822007-11-25 14:01:38 +0000169
bart3772a982008-03-15 08:11:03 +0000170 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000171
bart3772a982008-03-15 08:11:03 +0000172 for (i = 1; i < DRD_N_THREADS; i++)
173 {
bart324a23b2009-02-15 12:14:52 +0000174 if (DRD_(g_threadinfo)[i].posix_thread_exists
175 && DRD_(g_threadinfo)[i].pt_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000176 {
177 return i;
178 }
179 }
180 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000181}
182
183ThreadId DrdThreadIdToVgThreadId(const DrdThreadId tid)
184{
bart74a5f212008-05-11 06:43:07 +0000185 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
186 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000187 return (DRD_(g_threadinfo)[tid].vg_thread_exists
188 ? DRD_(g_threadinfo)[tid].vg_threadid
bart3772a982008-03-15 08:11:03 +0000189 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000190}
191
bart23d3a4e2008-04-05 12:53:00 +0000192#if 0
bart324a23b2009-02-15 12:14:52 +0000193/**
194 * Sanity check of the doubly linked list of segments referenced by a
195 * ThreadInfo struct.
196 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000197 */
198static Bool sane_ThreadInfo(const ThreadInfo* const ti)
199{
bart3772a982008-03-15 08:11:03 +0000200 Segment* p;
201 for (p = ti->first; p; p = p->next) {
202 if (p->next && p->next->prev != p)
203 return False;
204 if (p->next == 0 && p != ti->last)
205 return False;
206 }
207 for (p = ti->last; p; p = p->prev) {
208 if (p->prev && p->prev->next != p)
209 return False;
210 if (p->prev == 0 && p != ti->first)
211 return False;
212 }
213 return True;
sewardjaf44c822007-11-25 14:01:38 +0000214}
bart23d3a4e2008-04-05 12:53:00 +0000215#endif
sewardjaf44c822007-11-25 14:01:38 +0000216
bart439c55f2009-02-15 10:38:37 +0000217/**
218 * Create the first segment for a newly started thread.
219 *
220 * This function is called from the handler installed via
221 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
222 * from the context of the creator thread, before the new thread has been
223 * created.
224 */
sewardjaf44c822007-11-25 14:01:38 +0000225DrdThreadId thread_pre_create(const DrdThreadId creator,
226 const ThreadId vg_created)
227{
bart3772a982008-03-15 08:11:03 +0000228 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000229
bart3772a982008-03-15 08:11:03 +0000230 tl_assert(VgThreadIdToDrdThreadId(vg_created) == DRD_INVALID_THREADID);
231 created = VgThreadIdToNewDrdThreadId(vg_created);
bart74a5f212008-05-11 06:43:07 +0000232 tl_assert(0 <= (int)created && created < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000233 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000234
bart324a23b2009-02-15 12:14:52 +0000235 tl_assert(DRD_(g_threadinfo)[created].first == 0);
236 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart62ada3f2009-02-14 17:19:58 +0000237 thread_append_segment(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000238
bart3772a982008-03-15 08:11:03 +0000239 return created;
sewardjaf44c822007-11-25 14:01:38 +0000240}
241
bart439c55f2009-02-15 10:38:37 +0000242/**
bart324a23b2009-02-15 12:14:52 +0000243 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called after
bart439c55f2009-02-15 10:38:37 +0000244 * the thread has been created and before any client instructioins are run
245 * on the newly created thread, e.g. from the handler installed via
246 * VG_(track_pre_thread_first_insn)().
247 */
248DrdThreadId thread_post_create(const ThreadId vg_created)
249{
250 const DrdThreadId created = VgThreadIdToDrdThreadId(vg_created);
251
252 tl_assert(0 <= (int)created && created < DRD_N_THREADS
253 && created != DRD_INVALID_THREADID);
254
bart324a23b2009-02-15 12:14:52 +0000255 DRD_(g_threadinfo)[created].stack_max = VG_(thread_get_stack_max)(vg_created);
256 DRD_(g_threadinfo)[created].stack_startup = DRD_(g_threadinfo)[created].stack_max;
257 DRD_(g_threadinfo)[created].stack_min = DRD_(g_threadinfo)[created].stack_max;
258 DRD_(g_threadinfo)[created].stack_min_min = DRD_(g_threadinfo)[created].stack_max;
259 DRD_(g_threadinfo)[created].stack_size = VG_(thread_get_stack_size)(vg_created);
260 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000261
262 return created;
263}
bart09dc13f2009-02-14 15:13:31 +0000264
bart324a23b2009-02-15 12:14:52 +0000265/**
266 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
267 * after thread drd_joiner joined thread drd_joinee.
268 */
bart09dc13f2009-02-14 15:13:31 +0000269void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
270{
271 tl_assert(IsValidDrdThreadId(drd_joiner));
272 tl_assert(IsValidDrdThreadId(drd_joinee));
273 thread_new_segment(drd_joinee);
274 thread_combine_vc(drd_joiner, drd_joinee);
275 thread_new_segment(drd_joiner);
276
bart324a23b2009-02-15 12:14:52 +0000277 if (DRD_(s_trace_fork_join))
bart09dc13f2009-02-14 15:13:31 +0000278 {
279 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
280 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
281 const unsigned msg_size = 256;
282 char* msg;
283
284 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
285 tl_assert(msg);
286 VG_(snprintf)(msg, msg_size,
287 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
288 joiner, drd_joiner, joinee, drd_joinee);
289 if (joiner)
290 {
291 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
292 ", new vc: ");
bart41b226c2009-02-14 16:55:19 +0000293 DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
294 thread_get_vc(drd_joiner));
bart09dc13f2009-02-14 15:13:31 +0000295 }
296 VG_(message)(Vg_DebugMsg, "%s", msg);
297 VG_(free)(msg);
298 }
299
300 if (! DRD_(get_check_stack_accesses)())
301 {
bart1335ecc2009-02-14 16:10:53 +0000302 DRD_(finish_suppression)(thread_get_stack_max(drd_joinee)
303 - thread_get_stack_size(drd_joinee),
304 thread_get_stack_max(drd_joinee));
bart09dc13f2009-02-14 15:13:31 +0000305 }
306 thread_delete(drd_joinee);
307 mutex_thread_delete(drd_joinee);
308 cond_thread_delete(drd_joinee);
309 semaphore_thread_delete(drd_joinee);
barta8cf7652009-02-15 11:00:29 +0000310 DRD_(barrier_thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000311}
312
bart324a23b2009-02-15 12:14:52 +0000313/**
314 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
315 * and accesses this data structure from multiple threads without locking.
316 * Any conflicting accesses in the range stack_startup..stack_max will be
317 * ignored.
318 */
sewardjaf44c822007-11-25 14:01:38 +0000319void thread_set_stack_startup(const DrdThreadId tid, const Addr stack_startup)
320{
bart74a5f212008-05-11 06:43:07 +0000321 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
322 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000323 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
324 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
325 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000326}
327
328Addr thread_get_stack_min(const DrdThreadId tid)
329{
bart74a5f212008-05-11 06:43:07 +0000330 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000331 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000332 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000333}
334
bartcac53462008-03-29 09:27:08 +0000335Addr thread_get_stack_min_min(const DrdThreadId tid)
336{
bart74a5f212008-05-11 06:43:07 +0000337 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000338 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000339 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000340}
341
bartd43f8d32008-03-16 17:29:20 +0000342Addr thread_get_stack_max(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000343{
bart74a5f212008-05-11 06:43:07 +0000344 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartd43f8d32008-03-16 17:29:20 +0000345 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000346 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000347}
348
bartcac53462008-03-29 09:27:08 +0000349SizeT thread_get_stack_size(const DrdThreadId tid)
350{
bart74a5f212008-05-11 06:43:07 +0000351 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000352 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000353 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000354}
355
bart09dc13f2009-02-14 15:13:31 +0000356/**
357 * Clean up thread-specific data structures. Call this just after
358 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000359 */
360void thread_delete(const DrdThreadId tid)
361{
bart3772a982008-03-15 08:11:03 +0000362 Segment* sg;
363 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000364
bart74a5f212008-05-11 06:43:07 +0000365 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000366 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000367 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
368 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
bart3772a982008-03-15 08:11:03 +0000369 {
370 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000371 sg->prev = 0;
372 sg->next = 0;
bart62ada3f2009-02-14 17:19:58 +0000373 DRD_(sg_put)(sg);
bart3772a982008-03-15 08:11:03 +0000374 }
bart324a23b2009-02-15 12:14:52 +0000375 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
376 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
377 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
378 DRD_(g_threadinfo)[tid].first = 0;
379 DRD_(g_threadinfo)[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000380}
381
bart324a23b2009-02-15 12:14:52 +0000382/**
383 * Called after a thread performed its last memory access and before
384 * thread_delete() is called. Note: thread_delete() is only called for
385 * joinable threads, not for detached threads.
386 */
sewardjaf44c822007-11-25 14:01:38 +0000387void thread_finished(const DrdThreadId tid)
388{
bart74a5f212008-05-11 06:43:07 +0000389 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000390 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000391
bart324a23b2009-02-15 12:14:52 +0000392 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000393
bart324a23b2009-02-15 12:14:52 +0000394 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
bart3772a982008-03-15 08:11:03 +0000395 {
396 /* Once a detached thread has finished, its stack is deallocated and */
barte73b0aa2008-06-28 07:19:56 +0000397 /* should no longer be taken into account when computing the conflict set*/
bart324a23b2009-02-15 12:14:52 +0000398 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000399
bart3772a982008-03-15 08:11:03 +0000400 /* For a detached thread, calling pthread_exit() invalidates the */
401 /* POSIX thread ID associated with the detached thread. For joinable */
402 /* POSIX threads however, the POSIX thread ID remains live after the */
403 /* pthread_exit() call until pthread_join() is called. */
bart324a23b2009-02-15 12:14:52 +0000404 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
bart3772a982008-03-15 08:11:03 +0000405 }
sewardjaf44c822007-11-25 14:01:38 +0000406}
407
bart9b2974a2008-09-27 12:35:31 +0000408/** Called just before pthread_cancel(). */
bartaf0691b2008-09-27 12:26:50 +0000409void thread_pre_cancel(const DrdThreadId tid)
410{
411 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
412 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000413 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000414
bart324a23b2009-02-15 12:14:52 +0000415 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000416}
417
sewardjaf44c822007-11-25 14:01:38 +0000418void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
419{
bart74a5f212008-05-11 06:43:07 +0000420 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000421 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000422 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID);
bart3772a982008-03-15 08:11:03 +0000423 tl_assert(ptid != INVALID_POSIX_THREADID);
bart324a23b2009-02-15 12:14:52 +0000424 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
425 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000426}
427
428Bool thread_get_joinable(const DrdThreadId tid)
429{
bart74a5f212008-05-11 06:43:07 +0000430 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000431 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000432 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000433}
434
435void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
436{
bart74a5f212008-05-11 06:43:07 +0000437 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000438 && tid != DRD_INVALID_THREADID);
439 tl_assert(!! joinable == joinable);
bart324a23b2009-02-15 12:14:52 +0000440 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000441#if 0
bart3772a982008-03-15 08:11:03 +0000442 VG_(message)(Vg_DebugMsg,
443 "thread_set_joinable(%d/%d, %s)",
444 tid,
bart324a23b2009-02-15 12:14:52 +0000445 DRD_(g_threadinfo)[tid].vg_threadid,
bart3772a982008-03-15 08:11:03 +0000446 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000447#endif
bart324a23b2009-02-15 12:14:52 +0000448 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000449}
450
sewardj8b09d4f2007-12-04 21:27:18 +0000451void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000452{
bart3772a982008-03-15 08:11:03 +0000453 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000454
bart324a23b2009-02-15 12:14:52 +0000455 if (vg_tid != DRD_(s_vg_running_tid))
bart3772a982008-03-15 08:11:03 +0000456 {
457 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
458 }
sewardj8b09d4f2007-12-04 21:27:18 +0000459
bart324a23b2009-02-15 12:14:52 +0000460 tl_assert(DRD_(s_vg_running_tid) != VG_INVALID_THREADID);
461 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000462}
463
464void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
465{
bart3772a982008-03-15 08:11:03 +0000466 tl_assert(vg_tid != VG_INVALID_THREADID);
467 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000468
bart324a23b2009-02-15 12:14:52 +0000469 if (vg_tid != DRD_(s_vg_running_tid))
bart3772a982008-03-15 08:11:03 +0000470 {
bart324a23b2009-02-15 12:14:52 +0000471 if (DRD_(s_trace_context_switches)
472 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
bart3772a982008-03-15 08:11:03 +0000473 {
474 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000475 "Context switch from thread %d/%d to thread %d/%d;"
476 " segments: %llu",
bart324a23b2009-02-15 12:14:52 +0000477 DRD_(s_vg_running_tid), DRD_(g_drd_running_tid),
barta2b6e1b2008-03-17 18:32:39 +0000478 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
bart62ada3f2009-02-14 17:19:58 +0000479 DRD_(sg_get_segments_alive_count)());
bart3772a982008-03-15 08:11:03 +0000480 }
bart324a23b2009-02-15 12:14:52 +0000481 DRD_(s_vg_running_tid) = vg_tid;
482 DRD_(g_drd_running_tid) = drd_tid;
483 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
484 DRD_(s_context_switch_count)++;
bart3772a982008-03-15 08:11:03 +0000485 }
sewardj8b09d4f2007-12-04 21:27:18 +0000486
bart324a23b2009-02-15 12:14:52 +0000487 tl_assert(DRD_(s_vg_running_tid) != VG_INVALID_THREADID);
488 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000489}
490
bart0268dfa2008-03-11 20:10:21 +0000491int thread_enter_synchr(const DrdThreadId tid)
492{
bart3772a982008-03-15 08:11:03 +0000493 tl_assert(IsValidDrdThreadId(tid));
bart324a23b2009-02-15 12:14:52 +0000494 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000495}
496
497int thread_leave_synchr(const DrdThreadId tid)
498{
bart3772a982008-03-15 08:11:03 +0000499 tl_assert(IsValidDrdThreadId(tid));
bart324a23b2009-02-15 12:14:52 +0000500 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
501 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000502}
503
504int thread_get_synchr_nesting_count(const DrdThreadId tid)
505{
bart3772a982008-03-15 08:11:03 +0000506 tl_assert(IsValidDrdThreadId(tid));
bart324a23b2009-02-15 12:14:52 +0000507 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000508}
509
bart1a473c72008-03-13 19:03:38 +0000510/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000511static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000512{
bart74a5f212008-05-11 06:43:07 +0000513 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000514 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000515 // tl_assert(sane_ThreadInfo(&DRD_(g_threadinfo)[tid]));
516 sg->prev = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +0000517 sg->next = 0;
bart324a23b2009-02-15 12:14:52 +0000518 if (DRD_(g_threadinfo)[tid].last)
519 DRD_(g_threadinfo)[tid].last->next = sg;
520 DRD_(g_threadinfo)[tid].last = sg;
521 if (DRD_(g_threadinfo)[tid].first == 0)
522 DRD_(g_threadinfo)[tid].first = sg;
523 // tl_assert(sane_ThreadInfo(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000524}
525
bart324a23b2009-02-15 12:14:52 +0000526/**
527 * Remove a segment from the segment list of thread threadid, and free the
528 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000529 */
bart26f73e12008-02-24 18:37:08 +0000530static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000531{
bart74a5f212008-05-11 06:43:07 +0000532 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000533 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000534 //tl_assert(sane_ThreadInfo(&DRD_(g_threadinfo)[tid]));
bart26f73e12008-02-24 18:37:08 +0000535
bart3772a982008-03-15 08:11:03 +0000536 if (sg->prev)
537 sg->prev->next = sg->next;
538 if (sg->next)
539 sg->next->prev = sg->prev;
bart324a23b2009-02-15 12:14:52 +0000540 if (sg == DRD_(g_threadinfo)[tid].first)
541 DRD_(g_threadinfo)[tid].first = sg->next;
542 if (sg == DRD_(g_threadinfo)[tid].last)
543 DRD_(g_threadinfo)[tid].last = sg->prev;
bart62ada3f2009-02-14 17:19:58 +0000544 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000545
bart324a23b2009-02-15 12:14:52 +0000546 //tl_assert(sane_ThreadInfo(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000547}
548
549VectorClock* thread_get_vc(const DrdThreadId tid)
550{
bart74a5f212008-05-11 06:43:07 +0000551 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
552 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000553 tl_assert(DRD_(g_threadinfo)[tid].last);
554 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000555}
556
bart324a23b2009-02-15 12:14:52 +0000557/**
558 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000559 */
560void thread_get_latest_segment(Segment** sg, const DrdThreadId tid)
561{
562 tl_assert(sg);
bart74a5f212008-05-11 06:43:07 +0000563 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
564 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000565 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000566
bart62ada3f2009-02-14 17:19:58 +0000567 DRD_(sg_put)(*sg);
bart324a23b2009-02-15 12:14:52 +0000568 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000569}
570
sewardjaf44c822007-11-25 14:01:38 +0000571/**
572 * Compute the minimum of all latest vector clocks of all threads
573 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
574 * @param vc pointer to a vectorclock, holds result upon return.
575 */
576static void thread_compute_minimum_vc(VectorClock* vc)
577{
bart3772a982008-03-15 08:11:03 +0000578 unsigned i;
579 Bool first;
580 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000581
bart3772a982008-03-15 08:11:03 +0000582 first = True;
bart324a23b2009-02-15 12:14:52 +0000583 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
bart3772a982008-03-15 08:11:03 +0000584 {
bart324a23b2009-02-15 12:14:52 +0000585 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000586 if (latest_sg)
587 {
588 if (first)
bart41b226c2009-02-14 16:55:19 +0000589 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000590 else
bart41b226c2009-02-14 16:55:19 +0000591 DRD_(vc_min)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000592 first = False;
593 }
594 }
sewardjaf44c822007-11-25 14:01:38 +0000595}
596
597static void thread_compute_maximum_vc(VectorClock* vc)
598{
bart3772a982008-03-15 08:11:03 +0000599 unsigned i;
600 Bool first;
601 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000602
bart3772a982008-03-15 08:11:03 +0000603 first = True;
bart324a23b2009-02-15 12:14:52 +0000604 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
bart3772a982008-03-15 08:11:03 +0000605 {
bart324a23b2009-02-15 12:14:52 +0000606 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000607 if (latest_sg)
608 {
609 if (first)
bart41b226c2009-02-14 16:55:19 +0000610 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000611 else
bart41b226c2009-02-14 16:55:19 +0000612 DRD_(vc_combine)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000613 first = False;
614 }
615 }
sewardjaf44c822007-11-25 14:01:38 +0000616}
617
618/**
bart5bd9f2d2008-03-03 20:31:58 +0000619 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000620 * clock of every thread -- these segments can no longer be involved in a
621 * data race.
622 */
623static void thread_discard_ordered_segments(void)
624{
bart3772a982008-03-15 08:11:03 +0000625 unsigned i;
626 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000627
bart324a23b2009-02-15 12:14:52 +0000628 DRD_(s_discard_ordered_segments_count)++;
sewardjaf44c822007-11-25 14:01:38 +0000629
bart41b226c2009-02-14 16:55:19 +0000630 DRD_(vc_init)(&thread_vc_min, 0, 0);
bart3772a982008-03-15 08:11:03 +0000631 thread_compute_minimum_vc(&thread_vc_min);
bart62ada3f2009-02-14 17:19:58 +0000632 if (DRD_(sg_get_trace)())
bart3772a982008-03-15 08:11:03 +0000633 {
634 char msg[256];
635 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000636
bart41b226c2009-02-14 16:55:19 +0000637 DRD_(vc_init)(&thread_vc_max, 0, 0);
bart3772a982008-03-15 08:11:03 +0000638 thread_compute_maximum_vc(&thread_vc_max);
639 VG_(snprintf)(msg, sizeof(msg),
640 "Discarding ordered segments -- min vc is ");
bart41b226c2009-02-14 16:55:19 +0000641 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
642 &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000643 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
644 ", max vc is ");
bart41b226c2009-02-14 16:55:19 +0000645 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
646 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000647 VG_(message)(Vg_UserMsg, "%s", msg);
bart41b226c2009-02-14 16:55:19 +0000648 DRD_(vc_cleanup)(&thread_vc_max);
bart3772a982008-03-15 08:11:03 +0000649 }
sewardjaf44c822007-11-25 14:01:38 +0000650
bart324a23b2009-02-15 12:14:52 +0000651 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
bart3772a982008-03-15 08:11:03 +0000652 {
653 Segment* sg;
654 Segment* sg_next;
bart324a23b2009-02-15 12:14:52 +0000655 for (sg = DRD_(g_threadinfo)[i].first;
bart41b226c2009-02-14 16:55:19 +0000656 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000657 sg = sg_next)
658 {
659 thread_discard_segment(i, sg);
660 }
661 }
bart41b226c2009-02-14 16:55:19 +0000662 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000663}
664
bart324a23b2009-02-15 12:14:52 +0000665/**
666 * Merge all segments that may be merged without triggering false positives
667 * or discarding real data races. For the theoretical background of segment
668 * merging, see also the following paper:
669 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
670 * Bounding the number of segment histories during data race detection.
671 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
672 * September 2002.
barta9c37392008-03-22 09:38:48 +0000673 */
674static void thread_merge_segments(void)
675{
676 unsigned i;
677
bart324a23b2009-02-15 12:14:52 +0000678 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
barta9c37392008-03-22 09:38:48 +0000679 {
680 Segment* sg;
681
bart324a23b2009-02-15 12:14:52 +0000682 // tl_assert(sane_ThreadInfo(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000683
bart324a23b2009-02-15 12:14:52 +0000684 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000685 {
bart62ada3f2009-02-14 17:19:58 +0000686 if (DRD_(sg_get_refcnt)(sg) == 1
barta9c37392008-03-22 09:38:48 +0000687 && sg->next
bart62ada3f2009-02-14 17:19:58 +0000688 && DRD_(sg_get_refcnt)(sg->next) == 1
barta9c37392008-03-22 09:38:48 +0000689 && sg->next->next)
690 {
691 /* Merge sg and sg->next into sg. */
bart62ada3f2009-02-14 17:19:58 +0000692 DRD_(sg_merge)(sg, sg->next);
barta9c37392008-03-22 09:38:48 +0000693 thread_discard_segment(i, sg->next);
694 }
695 }
696
bart324a23b2009-02-15 12:14:52 +0000697 // tl_assert(sane_ThreadInfo(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000698 }
699}
700
bart324a23b2009-02-15 12:14:52 +0000701/**
702 * Every change in the vector clock of a thread may cause segments that
703 * were previously ordered to this thread to become unordered. Hence,
704 * it may be necessary to recalculate the conflict set if the vector clock
705 * of the current thread is updated. This function check whether such a
706 * recalculation is necessary.
bartd66e3a82008-04-06 15:02:17 +0000707 *
bart324a23b2009-02-15 12:14:52 +0000708 * @param tid Thread ID of the thread to which a new segment has been
709 * appended.
710 * @param new_sg Pointer to the most recent segment of thread tid.
bartd66e3a82008-04-06 15:02:17 +0000711 */
barte73b0aa2008-06-28 07:19:56 +0000712static Bool conflict_set_update_needed(const DrdThreadId tid,
bart41b226c2009-02-14 16:55:19 +0000713 const Segment* const new_sg)
bartd66e3a82008-04-06 15:02:17 +0000714{
bart5d421ba2008-04-19 15:15:12 +0000715#if 0
bartd66e3a82008-04-06 15:02:17 +0000716 unsigned i;
717 const Segment* old_sg;
718
719 tl_assert(new_sg);
720
721 /* If a new segment was added to another thread than the running thread, */
barte73b0aa2008-06-28 07:19:56 +0000722 /* just tell the caller to update the conflict set. */
bart324a23b2009-02-15 12:14:52 +0000723 if (tid != DRD_(g_drd_running_tid))
bartd66e3a82008-04-06 15:02:17 +0000724 return True;
725
barte73b0aa2008-06-28 07:19:56 +0000726 /* Always let the caller update the conflict set after creation of the */
bartd66e3a82008-04-06 15:02:17 +0000727 /* first segment. */
728 old_sg = new_sg->prev;
729 if (old_sg == 0)
730 return True;
731
bart324a23b2009-02-15 12:14:52 +0000732 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
bartd66e3a82008-04-06 15:02:17 +0000733 {
734 Segment* q;
735
bart324a23b2009-02-15 12:14:52 +0000736 if (i == DRD_(g_drd_running_tid))
bartd66e3a82008-04-06 15:02:17 +0000737 continue;
738
bart324a23b2009-02-15 12:14:52 +0000739 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000740 {
741 /* If the expression below evaluates to false, this expression will */
742 /* also evaluate to false for all subsequent iterations. So stop */
743 /* iterating. */
bart41b226c2009-02-14 16:55:19 +0000744 if (DRD_(vc_lte)(&q->vc, &old_sg->vc))
bartd66e3a82008-04-06 15:02:17 +0000745 break;
746 /* If the vector clock of the 2nd the last segment is not ordered */
747 /* to the vector clock of segment q, and the last segment is, ask */
barte73b0aa2008-06-28 07:19:56 +0000748 /* the caller to update the conflict set. */
bart41b226c2009-02-14 16:55:19 +0000749 if (! DRD_(vc_lte)(&old_sg->vc, &q->vc))
bartd66e3a82008-04-06 15:02:17 +0000750 {
751 return True;
752 }
753 /* If the vector clock of the last segment is not ordered to the */
barte73b0aa2008-06-28 07:19:56 +0000754 /* vector clock of segment q, ask the caller to update the conflict */
bartd66e3a82008-04-06 15:02:17 +0000755 /* set. */
bart41b226c2009-02-14 16:55:19 +0000756 if (! DRD_(vc_lte)(&q->vc, &new_sg->vc) && ! DRD_(vc_lte)(&new_sg->vc, &q->vc))
bartd66e3a82008-04-06 15:02:17 +0000757 {
758 return True;
759 }
760 }
761 }
762
763 return False;
bart5d421ba2008-04-19 15:15:12 +0000764#else
765 return True;
766#endif
bartd66e3a82008-04-06 15:02:17 +0000767}
768
bart324a23b2009-02-15 12:14:52 +0000769/**
770 * 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 */
773void thread_new_segment(const DrdThreadId tid)
774{
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);
bartd66e3a82008-04-06 15:02:17 +0000781 thread_append_segment(tid, new_sg);
782
barte73b0aa2008-06-28 07:19:56 +0000783 if (conflict_set_update_needed(tid, new_sg))
bartd66e3a82008-04-06 15:02:17 +0000784 {
bart324a23b2009-02-15 12:14:52 +0000785 thread_compute_conflict_set(&DRD_(g_conflict_set),
786 DRD_(g_drd_running_tid));
787 DRD_(s_conflict_set_new_segment_count)++;
bartd66e3a82008-04-06 15:02:17 +0000788 }
bart324a23b2009-02-15 12:14:52 +0000789 else if (tid == DRD_(g_drd_running_tid))
bart82195c12008-04-13 17:35:08 +0000790 {
bart324a23b2009-02-15 12:14:52 +0000791 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
bart82195c12008-04-13 17:35:08 +0000792 }
sewardjaf44c822007-11-25 14:01:38 +0000793
bart3772a982008-03-15 08:11:03 +0000794 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000795
bart324a23b2009-02-15 12:14:52 +0000796 if (DRD_(s_segment_merging))
797 {
barta9c37392008-03-22 09:38:48 +0000798 thread_merge_segments();
bart324a23b2009-02-15 12:14:52 +0000799 }
sewardjaf44c822007-11-25 14:01:38 +0000800}
801
bart26f73e12008-02-24 18:37:08 +0000802/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000803void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
804{
bart3772a982008-03-15 08:11:03 +0000805 tl_assert(joiner != joinee);
bart74a5f212008-05-11 06:43:07 +0000806 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000807 && joiner != DRD_INVALID_THREADID);
bart74a5f212008-05-11 06:43:07 +0000808 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000809 && joinee != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000810 tl_assert(DRD_(g_threadinfo)[joiner].last);
811 tl_assert(DRD_(g_threadinfo)[joinee].last);
812 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
813 &DRD_(g_threadinfo)[joinee].last->vc);
bart3772a982008-03-15 08:11:03 +0000814 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000815
bart324a23b2009-02-15 12:14:52 +0000816 if (joiner == DRD_(g_drd_running_tid))
bart3772a982008-03-15 08:11:03 +0000817 {
bart324a23b2009-02-15 12:14:52 +0000818 thread_compute_conflict_set(&DRD_(g_conflict_set), joiner);
bart3772a982008-03-15 08:11:03 +0000819 }
sewardjaf44c822007-11-25 14:01:38 +0000820}
821
bart324a23b2009-02-15 12:14:52 +0000822/**
823 * Call this function after thread 'tid' had to wait because of thread
824 * synchronization until the memory accesses in the segment with vector clock
825 * 'vc' finished.
bart26f73e12008-02-24 18:37:08 +0000826 */
sewardjaf44c822007-11-25 14:01:38 +0000827void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
828{
bart74a5f212008-05-11 06:43:07 +0000829 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
830 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000831 tl_assert(DRD_(g_threadinfo)[tid].last);
bart3772a982008-03-15 08:11:03 +0000832 tl_assert(vc);
bart324a23b2009-02-15 12:14:52 +0000833 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
834 thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
bart3772a982008-03-15 08:11:03 +0000835 thread_discard_ordered_segments();
bart324a23b2009-02-15 12:14:52 +0000836 DRD_(s_conflict_set_combine_vc_count)++;
sewardjaf44c822007-11-25 14:01:38 +0000837}
838
bart324a23b2009-02-15 12:14:52 +0000839/**
840 * Call this function whenever a thread is no longer using the memory
841 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
842 * increase.
bart26f73e12008-02-24 18:37:08 +0000843 */
sewardjaf44c822007-11-25 14:01:38 +0000844void thread_stop_using_mem(const Addr a1, const Addr a2)
845{
bartd43f8d32008-03-16 17:29:20 +0000846 DrdThreadId other_user;
847 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000848
bart3772a982008-03-15 08:11:03 +0000849 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000850 other_user = DRD_INVALID_THREADID;
bart324a23b2009-02-15 12:14:52 +0000851 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
bart3772a982008-03-15 08:11:03 +0000852 {
853 Segment* p;
bart324a23b2009-02-15 12:14:52 +0000854 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +0000855 {
856 if (other_user == DRD_INVALID_THREADID
bart324a23b2009-02-15 12:14:52 +0000857 && i != DRD_(g_drd_running_tid))
sewardjaf44c822007-11-25 14:01:38 +0000858 {
bart8bf2f8b2008-03-30 17:56:43 +0000859 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
860 {
861 other_user = i;
862 }
863 continue;
sewardjaf44c822007-11-25 14:01:38 +0000864 }
bart3772a982008-03-15 08:11:03 +0000865 bm_clear(p->bm, a1, a2);
866 }
867 }
sewardjaf44c822007-11-25 14:01:38 +0000868
bart324a23b2009-02-15 12:14:52 +0000869 /*
870 * If any other thread had accessed memory in [ a1, a2 [, update the
871 * conflict set.
872 */
bart3772a982008-03-15 08:11:03 +0000873 if (other_user != DRD_INVALID_THREADID
bart324a23b2009-02-15 12:14:52 +0000874 && bm_has_any_access(DRD_(g_conflict_set), a1, a2))
bart3772a982008-03-15 08:11:03 +0000875 {
bart324a23b2009-02-15 12:14:52 +0000876 thread_compute_conflict_set(&DRD_(g_conflict_set), thread_get_running_tid());
bart3772a982008-03-15 08:11:03 +0000877 }
sewardjaf44c822007-11-25 14:01:38 +0000878}
879
bart0268dfa2008-03-11 20:10:21 +0000880void thread_start_recording(const DrdThreadId tid)
881{
bart74a5f212008-05-11 06:43:07 +0000882 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
883 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000884 tl_assert(! DRD_(g_threadinfo)[tid].is_recording);
885 DRD_(g_threadinfo)[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000886}
887
888void thread_stop_recording(const DrdThreadId tid)
889{
bart74a5f212008-05-11 06:43:07 +0000890 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
891 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000892 tl_assert(DRD_(g_threadinfo)[tid].is_recording);
893 DRD_(g_threadinfo)[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000894}
895
sewardjaf44c822007-11-25 14:01:38 +0000896void thread_print_all(void)
897{
bart3772a982008-03-15 08:11:03 +0000898 unsigned i;
899 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000900
bart324a23b2009-02-15 12:14:52 +0000901 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
bart3772a982008-03-15 08:11:03 +0000902 {
bart324a23b2009-02-15 12:14:52 +0000903 if (DRD_(g_threadinfo)[i].first)
bart3772a982008-03-15 08:11:03 +0000904 {
905 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000906 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000907 "**************\n",
908 i,
bart324a23b2009-02-15 12:14:52 +0000909 DRD_(g_threadinfo)[i].vg_thread_exists,
910 DRD_(g_threadinfo)[i].vg_threadid,
911 DRD_(g_threadinfo)[i].posix_thread_exists,
912 DRD_(g_threadinfo)[i].pt_threadid,
913 DRD_(g_threadinfo)[i].detached_posix_thread);
914 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000915 {
bart62ada3f2009-02-14 17:19:58 +0000916 DRD_(sg_print)(p);
sewardjaf44c822007-11-25 14:01:38 +0000917 }
bart3772a982008-03-15 08:11:03 +0000918 }
919 }
sewardjaf44c822007-11-25 14:01:38 +0000920}
921
922static void show_call_stack(const DrdThreadId tid,
923 const Char* const msg,
924 ExeContext* const callstack)
925{
bart3772a982008-03-15 08:11:03 +0000926 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000927
bartaa97a542008-03-16 17:57:01 +0000928 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000929
bart3772a982008-03-15 08:11:03 +0000930 if (vg_tid != VG_INVALID_THREADID)
931 {
932 if (callstack)
933 {
934 VG_(pp_ExeContext)(callstack);
935 }
936 else
937 {
938 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
939 }
940 }
941 else
942 {
943 VG_(message)(Vg_UserMsg,
944 " (thread finished, call stack no longer available)");
945 }
sewardjaf44c822007-11-25 14:01:38 +0000946}
947
sewardjaf44c822007-11-25 14:01:38 +0000948static void
949thread_report_conflicting_segments_segment(const DrdThreadId tid,
950 const Addr addr,
951 const SizeT size,
952 const BmAccessTypeT access_type,
953 const Segment* const p)
954{
bart3772a982008-03-15 08:11:03 +0000955 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000956
bart74a5f212008-05-11 06:43:07 +0000957 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000958 && tid != DRD_INVALID_THREADID);
959 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000960
bart324a23b2009-02-15 12:14:52 +0000961 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); i++)
bart3772a982008-03-15 08:11:03 +0000962 {
963 if (i != tid)
964 {
965 Segment* q;
bart324a23b2009-02-15 12:14:52 +0000966 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000967 {
bart324a23b2009-02-15 12:14:52 +0000968 /*
969 * Since q iterates over the segments of thread i in order of
970 * decreasing vector clocks, if q->vc <= p->vc, then
971 * q->next->vc <= p->vc will also hold. Hence, break out of the
972 * loop once this condition is met.
973 */
bart41b226c2009-02-14 16:55:19 +0000974 if (DRD_(vc_lte)(&q->vc, &p->vc))
bart3772a982008-03-15 08:11:03 +0000975 break;
bart41b226c2009-02-14 16:55:19 +0000976 if (! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000977 {
978 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
979 {
980 tl_assert(q->stacktrace);
981 show_call_stack(i, "Other segment start",
982 q->stacktrace);
983 show_call_stack(i, "Other segment end",
984 q->next ? q->next->stacktrace : 0);
985 }
986 }
sewardjaf44c822007-11-25 14:01:38 +0000987 }
bart3772a982008-03-15 08:11:03 +0000988 }
989 }
sewardjaf44c822007-11-25 14:01:38 +0000990}
991
992void thread_report_conflicting_segments(const DrdThreadId tid,
993 const Addr addr,
994 const SizeT size,
995 const BmAccessTypeT access_type)
996{
bart3772a982008-03-15 08:11:03 +0000997 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000998
bart74a5f212008-05-11 06:43:07 +0000999 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +00001000 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001001
bart324a23b2009-02-15 12:14:52 +00001002 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +00001003 {
1004 if (bm_has(p->bm, addr, addr + size, access_type))
1005 {
1006 thread_report_conflicting_segments_segment(tid, addr, size,
1007 access_type, p);
1008 }
1009 }
sewardjaf44c822007-11-25 14:01:38 +00001010}
sewardjaf44c822007-11-25 14:01:38 +00001011
bart324a23b2009-02-15 12:14:52 +00001012/**
1013 * Verify whether the conflict set for thread tid is up to date. Only perform
1014 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
bart82195c12008-04-13 17:35:08 +00001015 */
barte73b0aa2008-06-28 07:19:56 +00001016static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
bart82195c12008-04-13 17:35:08 +00001017{
barte73b0aa2008-06-28 07:19:56 +00001018 static int do_verify_conflict_set = -1;
bart82195c12008-04-13 17:35:08 +00001019 Bool result;
barte73b0aa2008-06-28 07:19:56 +00001020 struct bitmap* computed_conflict_set = 0;
bart82195c12008-04-13 17:35:08 +00001021
barte73b0aa2008-06-28 07:19:56 +00001022 if (do_verify_conflict_set < 0)
bart82195c12008-04-13 17:35:08 +00001023 {
barte73b0aa2008-06-28 07:19:56 +00001024 //VG_(message)(Vg_DebugMsg, "%s", VG_(getenv)("DRD_VERIFY_CONFLICT_SET"));
1025 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
bart82195c12008-04-13 17:35:08 +00001026 }
barte73b0aa2008-06-28 07:19:56 +00001027 if (do_verify_conflict_set == 0)
bart82195c12008-04-13 17:35:08 +00001028 return True;
1029
barte73b0aa2008-06-28 07:19:56 +00001030 thread_compute_conflict_set(&computed_conflict_set, tid);
bart324a23b2009-02-15 12:14:52 +00001031 result = bm_equal(DRD_(g_conflict_set), computed_conflict_set);
barte73b0aa2008-06-28 07:19:56 +00001032 bm_delete(computed_conflict_set);
bart82195c12008-04-13 17:35:08 +00001033 return result;
1034}
1035
bart324a23b2009-02-15 12:14:52 +00001036/**
1037 * Compute a bitmap that represents the union of all memory accesses of all
1038 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001039 */
barte73b0aa2008-06-28 07:19:56 +00001040static void thread_compute_conflict_set(struct bitmap** conflict_set,
1041 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001042{
bart3772a982008-03-15 08:11:03 +00001043 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001044
bart74a5f212008-05-11 06:43:07 +00001045 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1046 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +00001047 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001048
bart324a23b2009-02-15 12:14:52 +00001049 DRD_(s_update_conflict_set_count)++;
1050 DRD_(s_conflict_set_bitmap_creation_count) -= bm_get_bitmap_creation_count();
1051 DRD_(s_conflict_set_bitmap2_creation_count) -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +00001052
barte73b0aa2008-06-28 07:19:56 +00001053 if (*conflict_set)
bart3772a982008-03-15 08:11:03 +00001054 {
barte73b0aa2008-06-28 07:19:56 +00001055 bm_delete(*conflict_set);
bart3772a982008-03-15 08:11:03 +00001056 }
barte73b0aa2008-06-28 07:19:56 +00001057 *conflict_set = bm_new();
bart26f73e12008-02-24 18:37:08 +00001058
bart324a23b2009-02-15 12:14:52 +00001059 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001060 {
1061 char msg[256];
1062
1063 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001064 "computing conflict set for thread %d/%d with vc ",
bartaa97a542008-03-16 17:57:01 +00001065 DrdThreadIdToVgThreadId(tid), tid);
bart41b226c2009-02-14 16:55:19 +00001066 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1067 sizeof(msg) - VG_(strlen)(msg),
bart324a23b2009-02-15 12:14:52 +00001068 &DRD_(g_threadinfo)[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +00001069 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001070 }
1071
bart324a23b2009-02-15 12:14:52 +00001072 p = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +00001073 {
1074 unsigned j;
1075
bart324a23b2009-02-15 12:14:52 +00001076 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001077 {
bart26f73e12008-02-24 18:37:08 +00001078 char msg[256];
1079
1080 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001081 "conflict set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +00001082 tid);
bart41b226c2009-02-14 16:55:19 +00001083 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1084 sizeof(msg) - VG_(strlen)(msg),
1085 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +00001086 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001087 }
sewardjaf44c822007-11-25 14:01:38 +00001088
bart324a23b2009-02-15 12:14:52 +00001089 for (j = 0; j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); j++)
bart3772a982008-03-15 08:11:03 +00001090 {
bartd66e3a82008-04-06 15:02:17 +00001091 if (j != tid && IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +00001092 {
bart3772a982008-03-15 08:11:03 +00001093 const Segment* q;
bart324a23b2009-02-15 12:14:52 +00001094 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +00001095 {
bart41b226c2009-02-14 16:55:19 +00001096 if (! DRD_(vc_lte)(&q->vc, &p->vc) && ! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +00001097 {
bart324a23b2009-02-15 12:14:52 +00001098 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001099 {
1100 char msg[256];
1101 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001102 "conflict set: [%d] merging segment ", j);
bart41b226c2009-02-14 16:55:19 +00001103 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1104 sizeof(msg) - VG_(strlen)(msg),
1105 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001106 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001107 }
barte73b0aa2008-06-28 07:19:56 +00001108 bm_merge2(*conflict_set, q->bm);
bart3772a982008-03-15 08:11:03 +00001109 }
1110 else
1111 {
bart324a23b2009-02-15 12:14:52 +00001112 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001113 {
1114 char msg[256];
1115 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001116 "conflict set: [%d] ignoring segment ", j);
bart41b226c2009-02-14 16:55:19 +00001117 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1118 sizeof(msg) - VG_(strlen)(msg),
1119 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001120 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001121 }
1122 }
bartd66e3a82008-04-06 15:02:17 +00001123 }
bart26f73e12008-02-24 18:37:08 +00001124 }
bart3772a982008-03-15 08:11:03 +00001125 }
bart3772a982008-03-15 08:11:03 +00001126 }
sewardjaf44c822007-11-25 14:01:38 +00001127
bart324a23b2009-02-15 12:14:52 +00001128 DRD_(s_conflict_set_bitmap_creation_count) += bm_get_bitmap_creation_count();
1129 DRD_(s_conflict_set_bitmap2_creation_count) += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +00001130
bart324a23b2009-02-15 12:14:52 +00001131 if (0 && DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001132 {
barte73b0aa2008-06-28 07:19:56 +00001133 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
1134 bm_print(*conflict_set);
1135 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
bart3772a982008-03-15 08:11:03 +00001136 }
sewardjaf44c822007-11-25 14:01:38 +00001137}
1138
sewardjaf44c822007-11-25 14:01:38 +00001139ULong thread_get_context_switch_count(void)
1140{
bart324a23b2009-02-15 12:14:52 +00001141 return DRD_(s_context_switch_count);
sewardjaf44c822007-11-25 14:01:38 +00001142}
1143
sewardjaf44c822007-11-25 14:01:38 +00001144ULong thread_get_discard_ordered_segments_count(void)
1145{
bart324a23b2009-02-15 12:14:52 +00001146 return DRD_(s_discard_ordered_segments_count);
sewardjaf44c822007-11-25 14:01:38 +00001147}
1148
barte73b0aa2008-06-28 07:19:56 +00001149ULong thread_get_update_conflict_set_count(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001150{
bartd66e3a82008-04-06 15:02:17 +00001151 tl_assert(dsnsc);
1152 tl_assert(dscvc);
bart324a23b2009-02-15 12:14:52 +00001153 *dsnsc = DRD_(s_conflict_set_new_segment_count);
1154 *dscvc = DRD_(s_conflict_set_combine_vc_count);
1155 return DRD_(s_update_conflict_set_count);
sewardjaf44c822007-11-25 14:01:38 +00001156}
1157
barte73b0aa2008-06-28 07:19:56 +00001158ULong thread_get_conflict_set_bitmap_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001159{
bart324a23b2009-02-15 12:14:52 +00001160 return DRD_(s_conflict_set_bitmap_creation_count);
sewardjaf44c822007-11-25 14:01:38 +00001161}
1162
barte73b0aa2008-06-28 07:19:56 +00001163ULong thread_get_conflict_set_bitmap2_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001164{
bart324a23b2009-02-15 12:14:52 +00001165 return DRD_(s_conflict_set_bitmap2_creation_count);
sewardjaf44c822007-11-25 14:01:38 +00001166}