blob: 4f34334dc4b5442c777fe5a945440790c53c78fa [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"
27#include "drd_segment.h"
28#include "drd_suppression.h"
29#include "drd_thread.h"
bart82195c12008-04-13 17:35:08 +000030#include "pub_tool_vki.h"
sewardjaf44c822007-11-25 14:01:38 +000031#include "pub_tool_basics.h" // Addr, SizeT
32#include "pub_tool_errormgr.h" // VG_(unique_error)()
33#include "pub_tool_libcassert.h" // tl_assert()
34#include "pub_tool_libcbase.h" // VG_(strlen)()
35#include "pub_tool_libcprint.h" // VG_(printf)()
bart82195c12008-04-13 17:35:08 +000036#include "pub_tool_libcproc.h" // VG_(getenv)()
sewardjaf44c822007-11-25 14:01:38 +000037#include "pub_tool_machine.h"
38#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
sewardj85642922008-01-14 11:54:56 +000039#include "pub_tool_options.h" // VG_(clo_backtrace_size)
sewardjaf44c822007-11-25 14:01:38 +000040#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
41
42
sewardjaf44c822007-11-25 14:01:38 +000043// Local functions.
44
45static void thread_append_segment(const DrdThreadId tid,
46 Segment* const sg);
barta2b6e1b2008-03-17 18:32:39 +000047static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
bart82195c12008-04-13 17:35:08 +000048static Bool thread_danger_set_up_to_date(const DrdThreadId tid);
bart4af812e2008-04-13 15:39:38 +000049static void thread_compute_danger_set(struct bitmap** danger_set,
50 const DrdThreadId tid);
sewardjaf44c822007-11-25 14:01:38 +000051
52
53// Local variables.
54
55static ULong s_context_switch_count;
56static ULong s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +000057static ULong s_update_danger_set_count;
bartd66e3a82008-04-06 15:02:17 +000058static ULong s_danger_set_new_segment_count;
59static ULong s_danger_set_combine_vc_count;
sewardjaf44c822007-11-25 14:01:38 +000060static ULong s_danger_set_bitmap_creation_count;
61static ULong s_danger_set_bitmap2_creation_count;
sewardj8b09d4f2007-12-04 21:27:18 +000062static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bartf00a85b2008-03-13 18:49:23 +000063DrdThreadId s_drd_running_tid = DRD_INVALID_THREADID;
64ThreadInfo s_threadinfo[DRD_N_THREADS];
bart1a473c72008-03-13 19:03:38 +000065struct bitmap* s_danger_set;
bart26f73e12008-02-24 18:37:08 +000066static Bool s_trace_context_switches = False;
67static Bool s_trace_danger_set = False;
barta9c37392008-03-22 09:38:48 +000068static Bool s_segment_merging = True;
sewardjaf44c822007-11-25 14:01:38 +000069
70
71// Function definitions.
72
bart26f73e12008-02-24 18:37:08 +000073void thread_trace_context_switches(const Bool t)
74{
bart3772a982008-03-15 08:11:03 +000075 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000076}
77
78void thread_trace_danger_set(const Bool t)
79{
bart3772a982008-03-15 08:11:03 +000080 s_trace_danger_set = t;
bart26f73e12008-02-24 18:37:08 +000081}
82
barta9c37392008-03-22 09:38:48 +000083void thread_set_segment_merging(const Bool m)
84{
85 s_segment_merging = m;
86}
87
sewardjaf44c822007-11-25 14:01:38 +000088__inline__ Bool IsValidDrdThreadId(const DrdThreadId tid)
89{
bart3772a982008-03-15 08:11:03 +000090 return (0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID
91 && ! (s_threadinfo[tid].vg_thread_exists == False
92 && s_threadinfo[tid].posix_thread_exists == False
93 && s_threadinfo[tid].detached_posix_thread == False));
sewardjaf44c822007-11-25 14:01:38 +000094}
95
96/**
97 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
98 * Valgrind's ThreadId does not yet exist.
99 **/
100DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid)
101{
bart3772a982008-03-15 08:11:03 +0000102 int i;
sewardjaf44c822007-11-25 14:01:38 +0000103
bart3772a982008-03-15 08:11:03 +0000104 if (tid == VG_INVALID_THREADID)
105 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000106
bart3772a982008-03-15 08:11:03 +0000107 for (i = 1; i < DRD_N_THREADS; i++)
108 {
109 if (s_threadinfo[i].vg_thread_exists == True
110 && s_threadinfo[i].vg_threadid == tid)
111 {
112 return i;
113 }
114 }
sewardjaf44c822007-11-25 14:01:38 +0000115
bart3772a982008-03-15 08:11:03 +0000116 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000117}
118
119static
120DrdThreadId VgThreadIdToNewDrdThreadId(const ThreadId tid)
121{
bart3772a982008-03-15 08:11:03 +0000122 int i;
sewardjaf44c822007-11-25 14:01:38 +0000123
bart3772a982008-03-15 08:11:03 +0000124 tl_assert(VgThreadIdToDrdThreadId(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000125
bart3772a982008-03-15 08:11:03 +0000126 for (i = 1; i < DRD_N_THREADS; i++)
127 {
128 if (s_threadinfo[i].vg_thread_exists == False
129 && s_threadinfo[i].posix_thread_exists == False
130 && s_threadinfo[i].detached_posix_thread == False)
131 {
132 s_threadinfo[i].vg_thread_exists = True;
133 s_threadinfo[i].vg_threadid = tid;
134 s_threadinfo[i].pt_threadid = INVALID_POSIX_THREADID;
bart3772a982008-03-15 08:11:03 +0000135 s_threadinfo[i].stack_min = 0;
bartcac53462008-03-29 09:27:08 +0000136 s_threadinfo[i].stack_min_min = 0;
bart3772a982008-03-15 08:11:03 +0000137 s_threadinfo[i].stack_startup = 0;
138 s_threadinfo[i].stack_max = 0;
bart3772a982008-03-15 08:11:03 +0000139 s_threadinfo[i].is_recording = True;
140 s_threadinfo[i].synchr_nesting = 0;
141 if (s_threadinfo[i].first != 0)
142 VG_(printf)("drd thread id = %d\n", i);
143 tl_assert(s_threadinfo[i].first == 0);
144 tl_assert(s_threadinfo[i].last == 0);
145 return i;
146 }
147 }
sewardjaf44c822007-11-25 14:01:38 +0000148
bart3772a982008-03-15 08:11:03 +0000149 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000150
bart3772a982008-03-15 08:11:03 +0000151 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000152}
153
154DrdThreadId PtThreadIdToDrdThreadId(const PThreadId tid)
155{
bart3772a982008-03-15 08:11:03 +0000156 int i;
sewardjaf44c822007-11-25 14:01:38 +0000157
bart3772a982008-03-15 08:11:03 +0000158 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000159
bart3772a982008-03-15 08:11:03 +0000160 for (i = 1; i < DRD_N_THREADS; i++)
161 {
162 if (s_threadinfo[i].posix_thread_exists
163 && s_threadinfo[i].pt_threadid == tid)
164 {
165 return i;
166 }
167 }
168 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000169}
170
171ThreadId DrdThreadIdToVgThreadId(const DrdThreadId tid)
172{
bart3772a982008-03-15 08:11:03 +0000173 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
174 return (s_threadinfo[tid].vg_thread_exists
175 ? s_threadinfo[tid].vg_threadid
176 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000177}
178
bart23d3a4e2008-04-05 12:53:00 +0000179#if 0
bart26f73e12008-02-24 18:37:08 +0000180/** Sanity check of the doubly linked list of segments referenced by a
181 * ThreadInfo struct.
182 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000183 */
184static Bool sane_ThreadInfo(const ThreadInfo* const ti)
185{
bart3772a982008-03-15 08:11:03 +0000186 Segment* p;
187 for (p = ti->first; p; p = p->next) {
188 if (p->next && p->next->prev != p)
189 return False;
190 if (p->next == 0 && p != ti->last)
191 return False;
192 }
193 for (p = ti->last; p; p = p->prev) {
194 if (p->prev && p->prev->next != p)
195 return False;
196 if (p->prev == 0 && p != ti->first)
197 return False;
198 }
199 return True;
sewardjaf44c822007-11-25 14:01:38 +0000200}
bart23d3a4e2008-04-05 12:53:00 +0000201#endif
sewardjaf44c822007-11-25 14:01:38 +0000202
203DrdThreadId thread_pre_create(const DrdThreadId creator,
204 const ThreadId vg_created)
205{
bart3772a982008-03-15 08:11:03 +0000206 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000207
bart3772a982008-03-15 08:11:03 +0000208 tl_assert(VgThreadIdToDrdThreadId(vg_created) == DRD_INVALID_THREADID);
209 created = VgThreadIdToNewDrdThreadId(vg_created);
210 tl_assert(0 <= created && created < DRD_N_THREADS
211 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000212
bart3772a982008-03-15 08:11:03 +0000213 tl_assert(s_threadinfo[created].first == 0);
214 tl_assert(s_threadinfo[created].last == 0);
215 thread_append_segment(created, sg_new(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000216
bart3772a982008-03-15 08:11:03 +0000217 return created;
sewardjaf44c822007-11-25 14:01:38 +0000218}
219
bart26f73e12008-02-24 18:37:08 +0000220/** Allocate the first segment for a thread. Call this just after
221 * pthread_create().
sewardjaf44c822007-11-25 14:01:38 +0000222 */
223DrdThreadId thread_post_create(const ThreadId vg_created)
224{
bart3772a982008-03-15 08:11:03 +0000225 const DrdThreadId created = VgThreadIdToDrdThreadId(vg_created);
sewardjaf44c822007-11-25 14:01:38 +0000226
bart3772a982008-03-15 08:11:03 +0000227 tl_assert(0 <= created && created < DRD_N_THREADS
228 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000229
bart3772a982008-03-15 08:11:03 +0000230 s_threadinfo[created].stack_max = VG_(thread_get_stack_max)(vg_created);
231 s_threadinfo[created].stack_startup = s_threadinfo[created].stack_max;
232 s_threadinfo[created].stack_min = s_threadinfo[created].stack_max;
bartcac53462008-03-29 09:27:08 +0000233 s_threadinfo[created].stack_min_min = s_threadinfo[created].stack_max;
234 s_threadinfo[created].stack_size = VG_(thread_get_stack_size)(vg_created);
bart3772a982008-03-15 08:11:03 +0000235 tl_assert(s_threadinfo[created].stack_max != 0);
sewardjaf44c822007-11-25 14:01:38 +0000236
bart3772a982008-03-15 08:11:03 +0000237 return created;
sewardjaf44c822007-11-25 14:01:38 +0000238}
239
240/* NPTL hack: NPTL allocates the 'struct pthread' on top of the stack, */
241/* and accesses this data structure from multiple threads without locking. */
242/* Any conflicting accesses in the range stack_startup..stack_max will be */
243/* ignored. */
244void thread_set_stack_startup(const DrdThreadId tid, const Addr stack_startup)
245{
bart3772a982008-03-15 08:11:03 +0000246 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
247 tl_assert(s_threadinfo[tid].stack_min <= stack_startup);
248 tl_assert(stack_startup <= s_threadinfo[tid].stack_max);
249 s_threadinfo[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000250}
251
252Addr thread_get_stack_min(const DrdThreadId tid)
253{
bart3772a982008-03-15 08:11:03 +0000254 tl_assert(0 <= tid && tid < DRD_N_THREADS
255 && tid != DRD_INVALID_THREADID);
256 return s_threadinfo[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000257}
258
bartcac53462008-03-29 09:27:08 +0000259Addr thread_get_stack_min_min(const DrdThreadId tid)
260{
261 tl_assert(0 <= tid && tid < DRD_N_THREADS
262 && tid != DRD_INVALID_THREADID);
263 return s_threadinfo[tid].stack_min_min;
264}
265
bartd43f8d32008-03-16 17:29:20 +0000266Addr thread_get_stack_max(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000267{
bartd43f8d32008-03-16 17:29:20 +0000268 tl_assert(0 <= tid && tid < DRD_N_THREADS
269 && tid != DRD_INVALID_THREADID);
270 return s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000271}
272
bartcac53462008-03-29 09:27:08 +0000273SizeT thread_get_stack_size(const DrdThreadId tid)
274{
275 tl_assert(0 <= tid && tid < DRD_N_THREADS
276 && tid != DRD_INVALID_THREADID);
277 return s_threadinfo[tid].stack_size;
278}
279
barta2b6e1b2008-03-17 18:32:39 +0000280/** Clean up thread-specific data structures. Call this just after
281 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000282 */
283void thread_delete(const DrdThreadId tid)
284{
bart3772a982008-03-15 08:11:03 +0000285 Segment* sg;
286 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000287
bart3772a982008-03-15 08:11:03 +0000288 tl_assert(0 <= tid && tid < DRD_N_THREADS
289 && tid != DRD_INVALID_THREADID);
290 tl_assert(s_threadinfo[tid].synchr_nesting == 0);
291 for (sg = s_threadinfo[tid].last; sg; sg = sg_prev)
292 {
293 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000294 sg->prev = 0;
295 sg->next = 0;
296 sg_put(sg);
bart3772a982008-03-15 08:11:03 +0000297 }
298 s_threadinfo[tid].vg_thread_exists = False;
299 s_threadinfo[tid].posix_thread_exists = False;
300 tl_assert(s_threadinfo[tid].detached_posix_thread == False);
301 s_threadinfo[tid].first = 0;
302 s_threadinfo[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000303}
304
305/* Called after a thread performed its last memory access and before */
306/* thread_delete() is called. Note: thread_delete() is only called for */
307/* joinable threads, not for detached threads. */
308void thread_finished(const DrdThreadId tid)
309{
bart3772a982008-03-15 08:11:03 +0000310 tl_assert(0 <= tid && tid < DRD_N_THREADS
311 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000312
bart3772a982008-03-15 08:11:03 +0000313 s_threadinfo[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000314
bart3772a982008-03-15 08:11:03 +0000315 if (s_threadinfo[tid].detached_posix_thread)
316 {
317 /* Once a detached thread has finished, its stack is deallocated and */
318 /* should no longer be taken into account when computing the danger set*/
319 s_threadinfo[tid].stack_min = s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000320
bart3772a982008-03-15 08:11:03 +0000321 /* For a detached thread, calling pthread_exit() invalidates the */
322 /* POSIX thread ID associated with the detached thread. For joinable */
323 /* POSIX threads however, the POSIX thread ID remains live after the */
324 /* pthread_exit() call until pthread_join() is called. */
325 s_threadinfo[tid].posix_thread_exists = False;
326 }
sewardjaf44c822007-11-25 14:01:38 +0000327}
328
329void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
330{
bart3772a982008-03-15 08:11:03 +0000331 tl_assert(0 <= tid && tid < DRD_N_THREADS
332 && tid != DRD_INVALID_THREADID);
333 tl_assert(s_threadinfo[tid].pt_threadid == INVALID_POSIX_THREADID);
334 tl_assert(ptid != INVALID_POSIX_THREADID);
335 s_threadinfo[tid].posix_thread_exists = True;
336 s_threadinfo[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000337}
338
339Bool thread_get_joinable(const DrdThreadId tid)
340{
bart3772a982008-03-15 08:11:03 +0000341 tl_assert(0 <= tid && tid < DRD_N_THREADS
342 && tid != DRD_INVALID_THREADID);
343 return ! s_threadinfo[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000344}
345
346void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
347{
bart3772a982008-03-15 08:11:03 +0000348 tl_assert(0 <= tid && tid < DRD_N_THREADS
349 && tid != DRD_INVALID_THREADID);
350 tl_assert(!! joinable == joinable);
351 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000352#if 0
bart3772a982008-03-15 08:11:03 +0000353 VG_(message)(Vg_DebugMsg,
354 "thread_set_joinable(%d/%d, %s)",
355 tid,
356 s_threadinfo[tid].vg_threadid,
357 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000358#endif
bart3772a982008-03-15 08:11:03 +0000359 s_threadinfo[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000360}
361
sewardj8b09d4f2007-12-04 21:27:18 +0000362void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000363{
bart3772a982008-03-15 08:11:03 +0000364 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000365
bart3772a982008-03-15 08:11:03 +0000366 if (vg_tid != s_vg_running_tid)
367 {
368 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
369 }
sewardj8b09d4f2007-12-04 21:27:18 +0000370
bart3772a982008-03-15 08:11:03 +0000371 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
372 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000373}
374
375void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
376{
bart3772a982008-03-15 08:11:03 +0000377 tl_assert(vg_tid != VG_INVALID_THREADID);
378 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000379
bart3772a982008-03-15 08:11:03 +0000380 if (vg_tid != s_vg_running_tid)
381 {
382 if (s_trace_context_switches
383 && s_drd_running_tid != DRD_INVALID_THREADID)
384 {
385 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000386 "Context switch from thread %d/%d to thread %d/%d;"
387 " segments: %llu",
bartaa97a542008-03-16 17:57:01 +0000388 s_vg_running_tid, s_drd_running_tid,
barta2b6e1b2008-03-17 18:32:39 +0000389 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
390 sg_get_alive_segments_count());
bart3772a982008-03-15 08:11:03 +0000391 }
392 s_vg_running_tid = vg_tid;
393 s_drd_running_tid = drd_tid;
bart4af812e2008-04-13 15:39:38 +0000394 thread_compute_danger_set(&s_danger_set, drd_tid);
bart3772a982008-03-15 08:11:03 +0000395 s_context_switch_count++;
396 }
sewardj8b09d4f2007-12-04 21:27:18 +0000397
bart3772a982008-03-15 08:11:03 +0000398 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
399 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000400}
401
bart0268dfa2008-03-11 20:10:21 +0000402int thread_enter_synchr(const DrdThreadId tid)
403{
bart3772a982008-03-15 08:11:03 +0000404 tl_assert(IsValidDrdThreadId(tid));
405 return s_threadinfo[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000406}
407
408int thread_leave_synchr(const DrdThreadId tid)
409{
bart3772a982008-03-15 08:11:03 +0000410 tl_assert(IsValidDrdThreadId(tid));
411 tl_assert(s_threadinfo[tid].synchr_nesting >= 1);
412 return --s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000413}
414
415int thread_get_synchr_nesting_count(const DrdThreadId tid)
416{
bart3772a982008-03-15 08:11:03 +0000417 tl_assert(IsValidDrdThreadId(tid));
418 return s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000419}
420
bart1a473c72008-03-13 19:03:38 +0000421/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000422static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000423{
bart3772a982008-03-15 08:11:03 +0000424 tl_assert(0 <= tid && tid < DRD_N_THREADS
425 && tid != DRD_INVALID_THREADID);
bart23d3a4e2008-04-05 12:53:00 +0000426 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart3772a982008-03-15 08:11:03 +0000427 sg->prev = s_threadinfo[tid].last;
428 sg->next = 0;
429 if (s_threadinfo[tid].last)
430 s_threadinfo[tid].last->next = sg;
431 s_threadinfo[tid].last = sg;
432 if (s_threadinfo[tid].first == 0)
433 s_threadinfo[tid].first = sg;
bart23d3a4e2008-04-05 12:53:00 +0000434 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000435}
436
bart26f73e12008-02-24 18:37:08 +0000437/** Remove a segment from the segment list of thread threadid, and free the
438 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000439 */
bart26f73e12008-02-24 18:37:08 +0000440static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000441{
bart3772a982008-03-15 08:11:03 +0000442 tl_assert(0 <= tid && tid < DRD_N_THREADS
443 && tid != DRD_INVALID_THREADID);
bart3f749672008-03-22 09:49:40 +0000444 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart26f73e12008-02-24 18:37:08 +0000445
bart3772a982008-03-15 08:11:03 +0000446 if (sg->prev)
447 sg->prev->next = sg->next;
448 if (sg->next)
449 sg->next->prev = sg->prev;
450 if (sg == s_threadinfo[tid].first)
451 s_threadinfo[tid].first = sg->next;
452 if (sg == s_threadinfo[tid].last)
453 s_threadinfo[tid].last = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000454 sg_put(sg);
bart3f749672008-03-22 09:49:40 +0000455
456 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000457}
458
459VectorClock* thread_get_vc(const DrdThreadId tid)
460{
barta2b6e1b2008-03-17 18:32:39 +0000461 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000462 tl_assert(s_threadinfo[tid].last);
463 return &s_threadinfo[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000464}
465
barta2b6e1b2008-03-17 18:32:39 +0000466/** Return the latest segment of thread 'tid' and increment its reference
467 * count.
468 */
469void thread_get_latest_segment(Segment** sg, const DrdThreadId tid)
470{
471 tl_assert(sg);
472 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
473 tl_assert(s_threadinfo[tid].last);
474
475 sg_put(*sg);
476 *sg = sg_get(s_threadinfo[tid].last);
477}
478
sewardjaf44c822007-11-25 14:01:38 +0000479/**
480 * Compute the minimum of all latest vector clocks of all threads
481 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
482 * @param vc pointer to a vectorclock, holds result upon return.
483 */
484static void thread_compute_minimum_vc(VectorClock* vc)
485{
bart3772a982008-03-15 08:11:03 +0000486 unsigned i;
487 Bool first;
488 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000489
bart3772a982008-03-15 08:11:03 +0000490 first = True;
491 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
492 {
493 latest_sg = s_threadinfo[i].last;
494 if (latest_sg)
495 {
496 if (first)
497 vc_assign(vc, &latest_sg->vc);
498 else
499 vc_min(vc, &latest_sg->vc);
500 first = False;
501 }
502 }
sewardjaf44c822007-11-25 14:01:38 +0000503}
504
505static void thread_compute_maximum_vc(VectorClock* vc)
506{
bart3772a982008-03-15 08:11:03 +0000507 unsigned i;
508 Bool first;
509 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000510
bart3772a982008-03-15 08:11:03 +0000511 first = True;
512 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
513 {
514 latest_sg = s_threadinfo[i].last;
515 if (latest_sg)
516 {
517 if (first)
518 vc_assign(vc, &latest_sg->vc);
519 else
520 vc_combine(vc, &latest_sg->vc);
521 first = False;
522 }
523 }
sewardjaf44c822007-11-25 14:01:38 +0000524}
525
526/**
bart5bd9f2d2008-03-03 20:31:58 +0000527 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000528 * clock of every thread -- these segments can no longer be involved in a
529 * data race.
530 */
531static void thread_discard_ordered_segments(void)
532{
bart3772a982008-03-15 08:11:03 +0000533 unsigned i;
534 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000535
bart3772a982008-03-15 08:11:03 +0000536 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000537
bart3772a982008-03-15 08:11:03 +0000538 vc_init(&thread_vc_min, 0, 0);
539 thread_compute_minimum_vc(&thread_vc_min);
540 if (sg_get_trace())
541 {
542 char msg[256];
543 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000544
bart3772a982008-03-15 08:11:03 +0000545 vc_init(&thread_vc_max, 0, 0);
546 thread_compute_maximum_vc(&thread_vc_max);
547 VG_(snprintf)(msg, sizeof(msg),
548 "Discarding ordered segments -- min vc is ");
549 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
550 &thread_vc_min);
551 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
552 ", max vc is ");
553 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
554 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000555 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000556 vc_cleanup(&thread_vc_max);
557 }
sewardjaf44c822007-11-25 14:01:38 +0000558
bart3772a982008-03-15 08:11:03 +0000559 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
560 {
561 Segment* sg;
562 Segment* sg_next;
563 for (sg = s_threadinfo[i].first;
564 sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
565 sg = sg_next)
566 {
567 thread_discard_segment(i, sg);
568 }
569 }
570 vc_cleanup(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000571}
572
barta9c37392008-03-22 09:38:48 +0000573/** Merge all segments that may be merged without triggering false positives
574 * or discarding real data races. For the theoretical background of segment
575 * merging, see also the following paper:
576 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
577 * Bounding the number of segment histories during data race detection.
578 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
579 * September 2002.
580 */
581static void thread_merge_segments(void)
582{
583 unsigned i;
584
585 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
586 {
587 Segment* sg;
588
bart23d3a4e2008-04-05 12:53:00 +0000589 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000590
591 for (sg = s_threadinfo[i].first; sg; sg = sg->next)
592 {
593 if (sg_get_refcnt(sg) == 1
594 && sg->next
595 && sg_get_refcnt(sg->next) == 1
596 && sg->next->next)
597 {
598 /* Merge sg and sg->next into sg. */
599 sg_merge(sg, sg->next);
600 thread_discard_segment(i, sg->next);
601 }
602 }
603
bart23d3a4e2008-04-05 12:53:00 +0000604 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000605 }
606}
607
bartd66e3a82008-04-06 15:02:17 +0000608/** Every change in the vector clock of a thread may cause segments that
609 * were previously ordered to this thread to become unordered. Hence,
610 * it may be necessary to recalculate the danger set if the vector clock
611 * of the current thread is updated. This function check whether such a
612 * recalculation is necessary.
613 *
614 * @param tid Thread ID of the thread to which a new segment has been
615 * appended.
616 * @param new_sg Pointer to the most recent segment of thread tid.
617 */
618static Bool danger_set_update_needed(const DrdThreadId tid,
619 const Segment* const new_sg)
620{
bart5d421ba2008-04-19 15:15:12 +0000621#if 0
bartd66e3a82008-04-06 15:02:17 +0000622 unsigned i;
623 const Segment* old_sg;
624
625 tl_assert(new_sg);
626
627 /* If a new segment was added to another thread than the running thread, */
628 /* just tell the caller to update the danger set. */
629 if (tid != s_drd_running_tid)
630 return True;
631
632 /* Always let the caller update the danger set after creation of the */
633 /* first segment. */
634 old_sg = new_sg->prev;
635 if (old_sg == 0)
636 return True;
637
638 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
639 {
640 Segment* q;
641
642 if (i == s_drd_running_tid)
643 continue;
644
645 for (q = s_threadinfo[i].last; q; q = q->prev)
646 {
647 /* If the expression below evaluates to false, this expression will */
648 /* also evaluate to false for all subsequent iterations. So stop */
649 /* iterating. */
650 if (vc_lte(&q->vc, &old_sg->vc))
651 break;
652 /* If the vector clock of the 2nd the last segment is not ordered */
653 /* to the vector clock of segment q, and the last segment is, ask */
654 /* the caller to update the danger set. */
655 if (! vc_lte(&old_sg->vc, &q->vc))
656 {
657 return True;
658 }
659 /* If the vector clock of the last segment is not ordered to the */
660 /* vector clock of segment q, ask the caller to update the danger */
661 /* set. */
662 if (! vc_lte(&q->vc, &new_sg->vc) && ! vc_lte(&new_sg->vc, &q->vc))
663 {
664 return True;
665 }
666 }
667 }
668
669 return False;
bart5d421ba2008-04-19 15:15:12 +0000670#else
671 return True;
672#endif
bartd66e3a82008-04-06 15:02:17 +0000673}
674
barta2b6e1b2008-03-17 18:32:39 +0000675/** Create a new segment for the specified thread, and discard any segments
676 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000677 */
678void thread_new_segment(const DrdThreadId tid)
679{
bartd66e3a82008-04-06 15:02:17 +0000680 Segment* new_sg;
681
barta2b6e1b2008-03-17 18:32:39 +0000682 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000683
bartd66e3a82008-04-06 15:02:17 +0000684 new_sg = sg_new(tid, tid);
685 thread_append_segment(tid, new_sg);
686
687 if (danger_set_update_needed(tid, new_sg))
688 {
bart4af812e2008-04-13 15:39:38 +0000689 thread_compute_danger_set(&s_danger_set, s_drd_running_tid);
bartd66e3a82008-04-06 15:02:17 +0000690 s_danger_set_new_segment_count++;
691 }
bart82195c12008-04-13 17:35:08 +0000692 else if (tid == s_drd_running_tid)
693 {
694 tl_assert(thread_danger_set_up_to_date(s_drd_running_tid));
695 }
sewardjaf44c822007-11-25 14:01:38 +0000696
bart3772a982008-03-15 08:11:03 +0000697 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000698
barta9c37392008-03-22 09:38:48 +0000699 if (s_segment_merging)
700 thread_merge_segments();
sewardjaf44c822007-11-25 14:01:38 +0000701}
702
bart26f73e12008-02-24 18:37:08 +0000703/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000704void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
705{
bart3772a982008-03-15 08:11:03 +0000706 tl_assert(joiner != joinee);
707 tl_assert(0 <= joiner && joiner < DRD_N_THREADS
708 && joiner != DRD_INVALID_THREADID);
709 tl_assert(0 <= joinee && joinee < DRD_N_THREADS
710 && joinee != DRD_INVALID_THREADID);
711 tl_assert(s_threadinfo[joiner].last);
712 tl_assert(s_threadinfo[joinee].last);
713 vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
714 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000715
bart3772a982008-03-15 08:11:03 +0000716 if (joiner == s_drd_running_tid)
717 {
bart4af812e2008-04-13 15:39:38 +0000718 thread_compute_danger_set(&s_danger_set, joiner);
bart3772a982008-03-15 08:11:03 +0000719 }
sewardjaf44c822007-11-25 14:01:38 +0000720}
721
bart26f73e12008-02-24 18:37:08 +0000722/** Call this function after thread 'tid' had to wait because of thread
723 * synchronization until the memory accesses in the segment with vector clock
724 * 'vc' finished.
725 */
sewardjaf44c822007-11-25 14:01:38 +0000726void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
727{
bart3772a982008-03-15 08:11:03 +0000728 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
729 tl_assert(s_threadinfo[tid].last);
730 tl_assert(vc);
731 vc_combine(&s_threadinfo[tid].last->vc, vc);
bart4af812e2008-04-13 15:39:38 +0000732 thread_compute_danger_set(&s_danger_set, tid);
bart3772a982008-03-15 08:11:03 +0000733 thread_discard_ordered_segments();
bartd66e3a82008-04-06 15:02:17 +0000734 s_danger_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000735}
736
bart26f73e12008-02-24 18:37:08 +0000737/** Call this function whenever a thread is no longer using the memory
738 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
739 * increase.
740 */
sewardjaf44c822007-11-25 14:01:38 +0000741void thread_stop_using_mem(const Addr a1, const Addr a2)
742{
bartd43f8d32008-03-16 17:29:20 +0000743 DrdThreadId other_user;
744 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000745
bart3772a982008-03-15 08:11:03 +0000746 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000747 other_user = DRD_INVALID_THREADID;
bart3772a982008-03-15 08:11:03 +0000748 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
749 {
750 Segment* p;
751 for (p = s_threadinfo[i].first; p; p = p->next)
752 {
753 if (other_user == DRD_INVALID_THREADID
bart8bf2f8b2008-03-30 17:56:43 +0000754 && i != s_drd_running_tid)
sewardjaf44c822007-11-25 14:01:38 +0000755 {
bart8bf2f8b2008-03-30 17:56:43 +0000756 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
757 {
758 other_user = i;
759 }
760 continue;
sewardjaf44c822007-11-25 14:01:38 +0000761 }
bart3772a982008-03-15 08:11:03 +0000762 bm_clear(p->bm, a1, a2);
763 }
764 }
sewardjaf44c822007-11-25 14:01:38 +0000765
bart3772a982008-03-15 08:11:03 +0000766 /* If any other thread had accessed memory in [ a1, a2 [, update the */
767 /* danger set. */
768 if (other_user != DRD_INVALID_THREADID
769 && bm_has_any_access(s_danger_set, a1, a2))
770 {
bart4af812e2008-04-13 15:39:38 +0000771 thread_compute_danger_set(&s_danger_set, thread_get_running_tid());
bart3772a982008-03-15 08:11:03 +0000772 }
sewardjaf44c822007-11-25 14:01:38 +0000773}
774
bart0268dfa2008-03-11 20:10:21 +0000775void thread_start_recording(const DrdThreadId tid)
776{
bart3772a982008-03-15 08:11:03 +0000777 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
778 tl_assert(! s_threadinfo[tid].is_recording);
779 s_threadinfo[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000780}
781
782void thread_stop_recording(const DrdThreadId tid)
783{
bart3772a982008-03-15 08:11:03 +0000784 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
785 tl_assert(s_threadinfo[tid].is_recording);
786 s_threadinfo[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000787}
788
sewardjaf44c822007-11-25 14:01:38 +0000789void thread_print_all(void)
790{
bart3772a982008-03-15 08:11:03 +0000791 unsigned i;
792 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000793
bart3772a982008-03-15 08:11:03 +0000794 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
795 {
796 if (s_threadinfo[i].first)
797 {
798 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000799 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000800 "**************\n",
801 i,
802 s_threadinfo[i].vg_thread_exists,
803 s_threadinfo[i].vg_threadid,
804 s_threadinfo[i].posix_thread_exists,
805 s_threadinfo[i].pt_threadid,
bart354009c2008-03-16 10:42:33 +0000806 s_threadinfo[i].detached_posix_thread);
bart3772a982008-03-15 08:11:03 +0000807 for (p = s_threadinfo[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000808 {
bart3772a982008-03-15 08:11:03 +0000809 sg_print(p);
sewardjaf44c822007-11-25 14:01:38 +0000810 }
bart3772a982008-03-15 08:11:03 +0000811 }
812 }
sewardjaf44c822007-11-25 14:01:38 +0000813}
814
815static void show_call_stack(const DrdThreadId tid,
816 const Char* const msg,
817 ExeContext* const callstack)
818{
bart3772a982008-03-15 08:11:03 +0000819 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000820
bartaa97a542008-03-16 17:57:01 +0000821 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000822
bart3772a982008-03-15 08:11:03 +0000823 if (vg_tid != VG_INVALID_THREADID)
824 {
825 if (callstack)
826 {
827 VG_(pp_ExeContext)(callstack);
828 }
829 else
830 {
831 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
832 }
833 }
834 else
835 {
836 VG_(message)(Vg_UserMsg,
837 " (thread finished, call stack no longer available)");
838 }
sewardjaf44c822007-11-25 14:01:38 +0000839}
840
sewardjaf44c822007-11-25 14:01:38 +0000841static void
842thread_report_conflicting_segments_segment(const DrdThreadId tid,
843 const Addr addr,
844 const SizeT size,
845 const BmAccessTypeT access_type,
846 const Segment* const p)
847{
bart3772a982008-03-15 08:11:03 +0000848 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000849
bart3772a982008-03-15 08:11:03 +0000850 tl_assert(0 <= tid && tid < DRD_N_THREADS
851 && tid != DRD_INVALID_THREADID);
852 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000853
bart3772a982008-03-15 08:11:03 +0000854 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
855 {
856 if (i != tid)
857 {
858 Segment* q;
859 for (q = s_threadinfo[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000860 {
bart3772a982008-03-15 08:11:03 +0000861 // Since q iterates over the segments of thread i in order of
862 // decreasing vector clocks, if q->vc <= p->vc, then
863 // q->next->vc <= p->vc will also hold. Hence, break out of the
864 // loop once this condition is met.
865 if (vc_lte(&q->vc, &p->vc))
866 break;
867 if (! vc_lte(&p->vc, &q->vc))
868 {
869 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
870 {
871 tl_assert(q->stacktrace);
872 show_call_stack(i, "Other segment start",
873 q->stacktrace);
874 show_call_stack(i, "Other segment end",
875 q->next ? q->next->stacktrace : 0);
876 }
877 }
sewardjaf44c822007-11-25 14:01:38 +0000878 }
bart3772a982008-03-15 08:11:03 +0000879 }
880 }
sewardjaf44c822007-11-25 14:01:38 +0000881}
882
883void thread_report_conflicting_segments(const DrdThreadId tid,
884 const Addr addr,
885 const SizeT size,
886 const BmAccessTypeT access_type)
887{
bart3772a982008-03-15 08:11:03 +0000888 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000889
bart3772a982008-03-15 08:11:03 +0000890 tl_assert(0 <= tid && tid < DRD_N_THREADS
891 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000892
bart3772a982008-03-15 08:11:03 +0000893 for (p = s_threadinfo[tid].first; p; p = p->next)
894 {
895 if (bm_has(p->bm, addr, addr + size, access_type))
896 {
897 thread_report_conflicting_segments_segment(tid, addr, size,
898 access_type, p);
899 }
900 }
sewardjaf44c822007-11-25 14:01:38 +0000901}
sewardjaf44c822007-11-25 14:01:38 +0000902
bart82195c12008-04-13 17:35:08 +0000903/** Verify whether the danger set for thread tid is up to date. Only perform
904 * the check if the environment variable DRD_VERIFY_DANGER_SET has been set.
905 */
906static Bool thread_danger_set_up_to_date(const DrdThreadId tid)
907{
908 static int do_verify_danger_set = -1;
909 Bool result;
910 struct bitmap* computed_danger_set = 0;
911
912 if (do_verify_danger_set < 0)
913 {
914 //VG_(message)(Vg_DebugMsg, "%s", VG_(getenv)("DRD_VERIFY_DANGER_SET"));
915 do_verify_danger_set = VG_(getenv)("DRD_VERIFY_DANGER_SET") != 0;
916 }
917 if (do_verify_danger_set == 0)
918 return True;
919
920 thread_compute_danger_set(&computed_danger_set, tid);
barta3f61092008-05-04 07:46:20 +0000921 result = bm_equal(s_danger_set, computed_danger_set);
bart82195c12008-04-13 17:35:08 +0000922 bm_delete(computed_danger_set);
923 return result;
924}
925
bart26f73e12008-02-24 18:37:08 +0000926/** Compute a bitmap that represents the union of all memory accesses of all
927 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +0000928 */
bart4af812e2008-04-13 15:39:38 +0000929static void thread_compute_danger_set(struct bitmap** danger_set,
930 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000931{
bart3772a982008-03-15 08:11:03 +0000932 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000933
bart3772a982008-03-15 08:11:03 +0000934 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
935 tl_assert(tid == s_drd_running_tid);
sewardjaf44c822007-11-25 14:01:38 +0000936
bart3772a982008-03-15 08:11:03 +0000937 s_update_danger_set_count++;
938 s_danger_set_bitmap_creation_count -= bm_get_bitmap_creation_count();
939 s_danger_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000940
bart4af812e2008-04-13 15:39:38 +0000941 if (*danger_set)
bart3772a982008-03-15 08:11:03 +0000942 {
bart4af812e2008-04-13 15:39:38 +0000943 bm_delete(*danger_set);
bart3772a982008-03-15 08:11:03 +0000944 }
bart4af812e2008-04-13 15:39:38 +0000945 *danger_set = bm_new();
bart26f73e12008-02-24 18:37:08 +0000946
bart3772a982008-03-15 08:11:03 +0000947 if (s_trace_danger_set)
948 {
949 char msg[256];
950
951 VG_(snprintf)(msg, sizeof(msg),
bartaa97a542008-03-16 17:57:01 +0000952 "computing danger set for thread %d/%d with vc ",
953 DrdThreadIdToVgThreadId(tid), tid);
bart3772a982008-03-15 08:11:03 +0000954 vc_snprint(msg + VG_(strlen)(msg),
955 sizeof(msg) - VG_(strlen)(msg),
956 &s_threadinfo[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +0000957 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000958 }
959
960 p = s_threadinfo[tid].last;
961 {
962 unsigned j;
963
964 if (s_trace_danger_set)
965 {
bart26f73e12008-02-24 18:37:08 +0000966 char msg[256];
967
968 VG_(snprintf)(msg, sizeof(msg),
bart3772a982008-03-15 08:11:03 +0000969 "danger set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +0000970 tid);
971 vc_snprint(msg + VG_(strlen)(msg),
972 sizeof(msg) - VG_(strlen)(msg),
bart3772a982008-03-15 08:11:03 +0000973 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +0000974 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000975 }
sewardjaf44c822007-11-25 14:01:38 +0000976
bart3772a982008-03-15 08:11:03 +0000977 for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++)
978 {
bartd66e3a82008-04-06 15:02:17 +0000979 if (j != tid && IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +0000980 {
bart3772a982008-03-15 08:11:03 +0000981 const Segment* q;
982 for (q = s_threadinfo[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000983 {
984 if (! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000985 {
986 if (s_trace_danger_set)
987 {
988 char msg[256];
989 VG_(snprintf)(msg, sizeof(msg),
990 "danger set: [%d] merging segment ", j);
991 vc_snprint(msg + VG_(strlen)(msg),
992 sizeof(msg) - VG_(strlen)(msg),
993 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000994 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000995 }
bart4af812e2008-04-13 15:39:38 +0000996 bm_merge2(*danger_set, q->bm);
bart3772a982008-03-15 08:11:03 +0000997 }
998 else
999 {
1000 if (s_trace_danger_set)
1001 {
1002 char msg[256];
1003 VG_(snprintf)(msg, sizeof(msg),
1004 "danger set: [%d] ignoring segment ", j);
1005 vc_snprint(msg + VG_(strlen)(msg),
1006 sizeof(msg) - VG_(strlen)(msg),
1007 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001008 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001009 }
1010 }
bartd66e3a82008-04-06 15:02:17 +00001011 }
bart26f73e12008-02-24 18:37:08 +00001012 }
bart3772a982008-03-15 08:11:03 +00001013 }
bart3772a982008-03-15 08:11:03 +00001014 }
sewardjaf44c822007-11-25 14:01:38 +00001015
bart3772a982008-03-15 08:11:03 +00001016 s_danger_set_bitmap_creation_count += bm_get_bitmap_creation_count();
1017 s_danger_set_bitmap2_creation_count += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +00001018
bart3772a982008-03-15 08:11:03 +00001019 if (0 && s_trace_danger_set)
1020 {
barta2b6e1b2008-03-17 18:32:39 +00001021 VG_(message)(Vg_UserMsg, "[%d] new danger set:", tid);
bart4af812e2008-04-13 15:39:38 +00001022 bm_print(*danger_set);
barta2b6e1b2008-03-17 18:32:39 +00001023 VG_(message)(Vg_UserMsg, "[%d] end of new danger set.", tid);
bart3772a982008-03-15 08:11:03 +00001024 }
sewardjaf44c822007-11-25 14:01:38 +00001025}
1026
sewardjaf44c822007-11-25 14:01:38 +00001027ULong thread_get_context_switch_count(void)
1028{
bart3772a982008-03-15 08:11:03 +00001029 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001030}
1031
sewardjaf44c822007-11-25 14:01:38 +00001032ULong thread_get_discard_ordered_segments_count(void)
1033{
bart3772a982008-03-15 08:11:03 +00001034 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001035}
1036
bartd66e3a82008-04-06 15:02:17 +00001037ULong thread_get_update_danger_set_count(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001038{
bartd66e3a82008-04-06 15:02:17 +00001039 tl_assert(dsnsc);
1040 tl_assert(dscvc);
1041 *dsnsc = s_danger_set_new_segment_count;
1042 *dscvc = s_danger_set_combine_vc_count;
bart3772a982008-03-15 08:11:03 +00001043 return s_update_danger_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001044}
1045
1046ULong thread_get_danger_set_bitmap_creation_count(void)
1047{
bart3772a982008-03-15 08:11:03 +00001048 return s_danger_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001049}
1050
1051ULong thread_get_danger_set_bitmap2_creation_count(void)
1052{
bart3772a982008-03-15 08:11:03 +00001053 return s_danger_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001054}