blob: a996732250e716d0949561328333e21d76bea585 [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"
sewardjaf44c822007-11-25 14:01:38 +000030#include "pub_tool_basics.h" // Addr, SizeT
31#include "pub_tool_errormgr.h" // VG_(unique_error)()
32#include "pub_tool_libcassert.h" // tl_assert()
33#include "pub_tool_libcbase.h" // VG_(strlen)()
34#include "pub_tool_libcprint.h" // VG_(printf)()
35#include "pub_tool_machine.h"
36#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
sewardj85642922008-01-14 11:54:56 +000037#include "pub_tool_options.h" // VG_(clo_backtrace_size)
sewardjaf44c822007-11-25 14:01:38 +000038#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
39
40
sewardjaf44c822007-11-25 14:01:38 +000041// Local functions.
42
43static void thread_append_segment(const DrdThreadId tid,
44 Segment* const sg);
barta2b6e1b2008-03-17 18:32:39 +000045static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
bart4af812e2008-04-13 15:39:38 +000046static void thread_compute_danger_set(struct bitmap** danger_set,
47 const DrdThreadId tid);
sewardjaf44c822007-11-25 14:01:38 +000048
49
50// Local variables.
51
52static ULong s_context_switch_count;
53static ULong s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +000054static ULong s_update_danger_set_count;
bartd66e3a82008-04-06 15:02:17 +000055static ULong s_danger_set_new_segment_count;
56static ULong s_danger_set_combine_vc_count;
sewardjaf44c822007-11-25 14:01:38 +000057static ULong s_danger_set_bitmap_creation_count;
58static ULong s_danger_set_bitmap2_creation_count;
sewardj8b09d4f2007-12-04 21:27:18 +000059static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bartf00a85b2008-03-13 18:49:23 +000060DrdThreadId s_drd_running_tid = DRD_INVALID_THREADID;
61ThreadInfo s_threadinfo[DRD_N_THREADS];
bart1a473c72008-03-13 19:03:38 +000062struct bitmap* s_danger_set;
bart26f73e12008-02-24 18:37:08 +000063static Bool s_trace_context_switches = False;
64static Bool s_trace_danger_set = False;
barta9c37392008-03-22 09:38:48 +000065static Bool s_segment_merging = True;
sewardjaf44c822007-11-25 14:01:38 +000066
67
68// Function definitions.
69
bart26f73e12008-02-24 18:37:08 +000070void thread_trace_context_switches(const Bool t)
71{
bart3772a982008-03-15 08:11:03 +000072 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000073}
74
75void thread_trace_danger_set(const Bool t)
76{
bart3772a982008-03-15 08:11:03 +000077 s_trace_danger_set = t;
bart26f73e12008-02-24 18:37:08 +000078}
79
barta9c37392008-03-22 09:38:48 +000080void thread_set_segment_merging(const Bool m)
81{
82 s_segment_merging = m;
83}
84
sewardjaf44c822007-11-25 14:01:38 +000085__inline__ Bool IsValidDrdThreadId(const DrdThreadId tid)
86{
bart3772a982008-03-15 08:11:03 +000087 return (0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID
88 && ! (s_threadinfo[tid].vg_thread_exists == False
89 && s_threadinfo[tid].posix_thread_exists == False
90 && s_threadinfo[tid].detached_posix_thread == False));
sewardjaf44c822007-11-25 14:01:38 +000091}
92
93/**
94 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
95 * Valgrind's ThreadId does not yet exist.
96 **/
97DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid)
98{
bart3772a982008-03-15 08:11:03 +000099 int i;
sewardjaf44c822007-11-25 14:01:38 +0000100
bart3772a982008-03-15 08:11:03 +0000101 if (tid == VG_INVALID_THREADID)
102 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000103
bart3772a982008-03-15 08:11:03 +0000104 for (i = 1; i < DRD_N_THREADS; i++)
105 {
106 if (s_threadinfo[i].vg_thread_exists == True
107 && s_threadinfo[i].vg_threadid == tid)
108 {
109 return i;
110 }
111 }
sewardjaf44c822007-11-25 14:01:38 +0000112
bart3772a982008-03-15 08:11:03 +0000113 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000114}
115
116static
117DrdThreadId VgThreadIdToNewDrdThreadId(const ThreadId tid)
118{
bart3772a982008-03-15 08:11:03 +0000119 int i;
sewardjaf44c822007-11-25 14:01:38 +0000120
bart3772a982008-03-15 08:11:03 +0000121 tl_assert(VgThreadIdToDrdThreadId(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000122
bart3772a982008-03-15 08:11:03 +0000123 for (i = 1; i < DRD_N_THREADS; i++)
124 {
125 if (s_threadinfo[i].vg_thread_exists == False
126 && s_threadinfo[i].posix_thread_exists == False
127 && s_threadinfo[i].detached_posix_thread == False)
128 {
129 s_threadinfo[i].vg_thread_exists = True;
130 s_threadinfo[i].vg_threadid = tid;
131 s_threadinfo[i].pt_threadid = INVALID_POSIX_THREADID;
bart3772a982008-03-15 08:11:03 +0000132 s_threadinfo[i].stack_min = 0;
bartcac53462008-03-29 09:27:08 +0000133 s_threadinfo[i].stack_min_min = 0;
bart3772a982008-03-15 08:11:03 +0000134 s_threadinfo[i].stack_startup = 0;
135 s_threadinfo[i].stack_max = 0;
bart3772a982008-03-15 08:11:03 +0000136 s_threadinfo[i].is_recording = True;
137 s_threadinfo[i].synchr_nesting = 0;
138 if (s_threadinfo[i].first != 0)
139 VG_(printf)("drd thread id = %d\n", i);
140 tl_assert(s_threadinfo[i].first == 0);
141 tl_assert(s_threadinfo[i].last == 0);
142 return i;
143 }
144 }
sewardjaf44c822007-11-25 14:01:38 +0000145
bart3772a982008-03-15 08:11:03 +0000146 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000147
bart3772a982008-03-15 08:11:03 +0000148 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000149}
150
151DrdThreadId PtThreadIdToDrdThreadId(const PThreadId tid)
152{
bart3772a982008-03-15 08:11:03 +0000153 int i;
sewardjaf44c822007-11-25 14:01:38 +0000154
bart3772a982008-03-15 08:11:03 +0000155 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000156
bart3772a982008-03-15 08:11:03 +0000157 for (i = 1; i < DRD_N_THREADS; i++)
158 {
159 if (s_threadinfo[i].posix_thread_exists
160 && s_threadinfo[i].pt_threadid == tid)
161 {
162 return i;
163 }
164 }
165 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000166}
167
168ThreadId DrdThreadIdToVgThreadId(const DrdThreadId tid)
169{
bart3772a982008-03-15 08:11:03 +0000170 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
171 return (s_threadinfo[tid].vg_thread_exists
172 ? s_threadinfo[tid].vg_threadid
173 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000174}
175
bart23d3a4e2008-04-05 12:53:00 +0000176#if 0
bart26f73e12008-02-24 18:37:08 +0000177/** Sanity check of the doubly linked list of segments referenced by a
178 * ThreadInfo struct.
179 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000180 */
181static Bool sane_ThreadInfo(const ThreadInfo* const ti)
182{
bart3772a982008-03-15 08:11:03 +0000183 Segment* p;
184 for (p = ti->first; p; p = p->next) {
185 if (p->next && p->next->prev != p)
186 return False;
187 if (p->next == 0 && p != ti->last)
188 return False;
189 }
190 for (p = ti->last; p; p = p->prev) {
191 if (p->prev && p->prev->next != p)
192 return False;
193 if (p->prev == 0 && p != ti->first)
194 return False;
195 }
196 return True;
sewardjaf44c822007-11-25 14:01:38 +0000197}
bart23d3a4e2008-04-05 12:53:00 +0000198#endif
sewardjaf44c822007-11-25 14:01:38 +0000199
200DrdThreadId thread_pre_create(const DrdThreadId creator,
201 const ThreadId vg_created)
202{
bart3772a982008-03-15 08:11:03 +0000203 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000204
bart3772a982008-03-15 08:11:03 +0000205 tl_assert(VgThreadIdToDrdThreadId(vg_created) == DRD_INVALID_THREADID);
206 created = VgThreadIdToNewDrdThreadId(vg_created);
207 tl_assert(0 <= created && created < DRD_N_THREADS
208 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000209
bart3772a982008-03-15 08:11:03 +0000210 tl_assert(s_threadinfo[created].first == 0);
211 tl_assert(s_threadinfo[created].last == 0);
212 thread_append_segment(created, sg_new(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000213
bart3772a982008-03-15 08:11:03 +0000214 return created;
sewardjaf44c822007-11-25 14:01:38 +0000215}
216
bart26f73e12008-02-24 18:37:08 +0000217/** Allocate the first segment for a thread. Call this just after
218 * pthread_create().
sewardjaf44c822007-11-25 14:01:38 +0000219 */
220DrdThreadId thread_post_create(const ThreadId vg_created)
221{
bart3772a982008-03-15 08:11:03 +0000222 const DrdThreadId created = VgThreadIdToDrdThreadId(vg_created);
sewardjaf44c822007-11-25 14:01:38 +0000223
bart3772a982008-03-15 08:11:03 +0000224 tl_assert(0 <= created && created < DRD_N_THREADS
225 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000226
bart3772a982008-03-15 08:11:03 +0000227 s_threadinfo[created].stack_max = VG_(thread_get_stack_max)(vg_created);
228 s_threadinfo[created].stack_startup = s_threadinfo[created].stack_max;
229 s_threadinfo[created].stack_min = s_threadinfo[created].stack_max;
bartcac53462008-03-29 09:27:08 +0000230 s_threadinfo[created].stack_min_min = s_threadinfo[created].stack_max;
231 s_threadinfo[created].stack_size = VG_(thread_get_stack_size)(vg_created);
bart3772a982008-03-15 08:11:03 +0000232 tl_assert(s_threadinfo[created].stack_max != 0);
sewardjaf44c822007-11-25 14:01:38 +0000233
bart3772a982008-03-15 08:11:03 +0000234 return created;
sewardjaf44c822007-11-25 14:01:38 +0000235}
236
237/* NPTL hack: NPTL allocates the 'struct pthread' on top of the stack, */
238/* and accesses this data structure from multiple threads without locking. */
239/* Any conflicting accesses in the range stack_startup..stack_max will be */
240/* ignored. */
241void thread_set_stack_startup(const DrdThreadId tid, const Addr stack_startup)
242{
bart3772a982008-03-15 08:11:03 +0000243 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
244 tl_assert(s_threadinfo[tid].stack_min <= stack_startup);
245 tl_assert(stack_startup <= s_threadinfo[tid].stack_max);
246 s_threadinfo[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000247}
248
249Addr thread_get_stack_min(const DrdThreadId tid)
250{
bart3772a982008-03-15 08:11:03 +0000251 tl_assert(0 <= tid && tid < DRD_N_THREADS
252 && tid != DRD_INVALID_THREADID);
253 return s_threadinfo[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000254}
255
bartcac53462008-03-29 09:27:08 +0000256Addr thread_get_stack_min_min(const DrdThreadId tid)
257{
258 tl_assert(0 <= tid && tid < DRD_N_THREADS
259 && tid != DRD_INVALID_THREADID);
260 return s_threadinfo[tid].stack_min_min;
261}
262
bartd43f8d32008-03-16 17:29:20 +0000263Addr thread_get_stack_max(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000264{
bartd43f8d32008-03-16 17:29:20 +0000265 tl_assert(0 <= tid && tid < DRD_N_THREADS
266 && tid != DRD_INVALID_THREADID);
267 return s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000268}
269
bartcac53462008-03-29 09:27:08 +0000270SizeT thread_get_stack_size(const DrdThreadId tid)
271{
272 tl_assert(0 <= tid && tid < DRD_N_THREADS
273 && tid != DRD_INVALID_THREADID);
274 return s_threadinfo[tid].stack_size;
275}
276
barta2b6e1b2008-03-17 18:32:39 +0000277/** Clean up thread-specific data structures. Call this just after
278 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000279 */
280void thread_delete(const DrdThreadId tid)
281{
bart3772a982008-03-15 08:11:03 +0000282 Segment* sg;
283 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000284
bart3772a982008-03-15 08:11:03 +0000285 tl_assert(0 <= tid && tid < DRD_N_THREADS
286 && tid != DRD_INVALID_THREADID);
287 tl_assert(s_threadinfo[tid].synchr_nesting == 0);
288 for (sg = s_threadinfo[tid].last; sg; sg = sg_prev)
289 {
290 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000291 sg->prev = 0;
292 sg->next = 0;
293 sg_put(sg);
bart3772a982008-03-15 08:11:03 +0000294 }
295 s_threadinfo[tid].vg_thread_exists = False;
296 s_threadinfo[tid].posix_thread_exists = False;
297 tl_assert(s_threadinfo[tid].detached_posix_thread == False);
298 s_threadinfo[tid].first = 0;
299 s_threadinfo[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000300}
301
302/* Called after a thread performed its last memory access and before */
303/* thread_delete() is called. Note: thread_delete() is only called for */
304/* joinable threads, not for detached threads. */
305void thread_finished(const DrdThreadId tid)
306{
bart3772a982008-03-15 08:11:03 +0000307 tl_assert(0 <= tid && tid < DRD_N_THREADS
308 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000309
bart3772a982008-03-15 08:11:03 +0000310 s_threadinfo[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000311
bart3772a982008-03-15 08:11:03 +0000312 if (s_threadinfo[tid].detached_posix_thread)
313 {
314 /* Once a detached thread has finished, its stack is deallocated and */
315 /* should no longer be taken into account when computing the danger set*/
316 s_threadinfo[tid].stack_min = s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000317
bart3772a982008-03-15 08:11:03 +0000318 /* For a detached thread, calling pthread_exit() invalidates the */
319 /* POSIX thread ID associated with the detached thread. For joinable */
320 /* POSIX threads however, the POSIX thread ID remains live after the */
321 /* pthread_exit() call until pthread_join() is called. */
322 s_threadinfo[tid].posix_thread_exists = False;
323 }
sewardjaf44c822007-11-25 14:01:38 +0000324}
325
326void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
327{
bart3772a982008-03-15 08:11:03 +0000328 tl_assert(0 <= tid && tid < DRD_N_THREADS
329 && tid != DRD_INVALID_THREADID);
330 tl_assert(s_threadinfo[tid].pt_threadid == INVALID_POSIX_THREADID);
331 tl_assert(ptid != INVALID_POSIX_THREADID);
332 s_threadinfo[tid].posix_thread_exists = True;
333 s_threadinfo[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000334}
335
336Bool thread_get_joinable(const DrdThreadId tid)
337{
bart3772a982008-03-15 08:11:03 +0000338 tl_assert(0 <= tid && tid < DRD_N_THREADS
339 && tid != DRD_INVALID_THREADID);
340 return ! s_threadinfo[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000341}
342
343void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
344{
bart3772a982008-03-15 08:11:03 +0000345 tl_assert(0 <= tid && tid < DRD_N_THREADS
346 && tid != DRD_INVALID_THREADID);
347 tl_assert(!! joinable == joinable);
348 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000349#if 0
bart3772a982008-03-15 08:11:03 +0000350 VG_(message)(Vg_DebugMsg,
351 "thread_set_joinable(%d/%d, %s)",
352 tid,
353 s_threadinfo[tid].vg_threadid,
354 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000355#endif
bart3772a982008-03-15 08:11:03 +0000356 s_threadinfo[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000357}
358
sewardj8b09d4f2007-12-04 21:27:18 +0000359void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000360{
bart3772a982008-03-15 08:11:03 +0000361 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000362
bart3772a982008-03-15 08:11:03 +0000363 if (vg_tid != s_vg_running_tid)
364 {
365 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
366 }
sewardj8b09d4f2007-12-04 21:27:18 +0000367
bart3772a982008-03-15 08:11:03 +0000368 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
369 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000370}
371
372void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
373{
bart3772a982008-03-15 08:11:03 +0000374 tl_assert(vg_tid != VG_INVALID_THREADID);
375 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000376
bart3772a982008-03-15 08:11:03 +0000377 if (vg_tid != s_vg_running_tid)
378 {
379 if (s_trace_context_switches
380 && s_drd_running_tid != DRD_INVALID_THREADID)
381 {
382 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000383 "Context switch from thread %d/%d to thread %d/%d;"
384 " segments: %llu",
bartaa97a542008-03-16 17:57:01 +0000385 s_vg_running_tid, s_drd_running_tid,
barta2b6e1b2008-03-17 18:32:39 +0000386 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
387 sg_get_alive_segments_count());
bart3772a982008-03-15 08:11:03 +0000388 }
389 s_vg_running_tid = vg_tid;
390 s_drd_running_tid = drd_tid;
bart4af812e2008-04-13 15:39:38 +0000391 thread_compute_danger_set(&s_danger_set, drd_tid);
bart3772a982008-03-15 08:11:03 +0000392 s_context_switch_count++;
393 }
sewardj8b09d4f2007-12-04 21:27:18 +0000394
bart3772a982008-03-15 08:11:03 +0000395 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
396 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000397}
398
bart0268dfa2008-03-11 20:10:21 +0000399int thread_enter_synchr(const DrdThreadId tid)
400{
bart3772a982008-03-15 08:11:03 +0000401 tl_assert(IsValidDrdThreadId(tid));
402 return s_threadinfo[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000403}
404
405int thread_leave_synchr(const DrdThreadId tid)
406{
bart3772a982008-03-15 08:11:03 +0000407 tl_assert(IsValidDrdThreadId(tid));
408 tl_assert(s_threadinfo[tid].synchr_nesting >= 1);
409 return --s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000410}
411
412int thread_get_synchr_nesting_count(const DrdThreadId tid)
413{
bart3772a982008-03-15 08:11:03 +0000414 tl_assert(IsValidDrdThreadId(tid));
415 return s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000416}
417
bart1a473c72008-03-13 19:03:38 +0000418/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000419static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000420{
bart3772a982008-03-15 08:11:03 +0000421 tl_assert(0 <= tid && tid < DRD_N_THREADS
422 && tid != DRD_INVALID_THREADID);
bart23d3a4e2008-04-05 12:53:00 +0000423 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart3772a982008-03-15 08:11:03 +0000424 sg->prev = s_threadinfo[tid].last;
425 sg->next = 0;
426 if (s_threadinfo[tid].last)
427 s_threadinfo[tid].last->next = sg;
428 s_threadinfo[tid].last = sg;
429 if (s_threadinfo[tid].first == 0)
430 s_threadinfo[tid].first = sg;
bart23d3a4e2008-04-05 12:53:00 +0000431 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000432}
433
bart26f73e12008-02-24 18:37:08 +0000434/** Remove a segment from the segment list of thread threadid, and free the
435 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000436 */
bart26f73e12008-02-24 18:37:08 +0000437static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000438{
bart3772a982008-03-15 08:11:03 +0000439 tl_assert(0 <= tid && tid < DRD_N_THREADS
440 && tid != DRD_INVALID_THREADID);
bart3f749672008-03-22 09:49:40 +0000441 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart26f73e12008-02-24 18:37:08 +0000442
bart3772a982008-03-15 08:11:03 +0000443 if (sg->prev)
444 sg->prev->next = sg->next;
445 if (sg->next)
446 sg->next->prev = sg->prev;
447 if (sg == s_threadinfo[tid].first)
448 s_threadinfo[tid].first = sg->next;
449 if (sg == s_threadinfo[tid].last)
450 s_threadinfo[tid].last = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000451 sg_put(sg);
bart3f749672008-03-22 09:49:40 +0000452
453 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000454}
455
456VectorClock* thread_get_vc(const DrdThreadId tid)
457{
barta2b6e1b2008-03-17 18:32:39 +0000458 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000459 tl_assert(s_threadinfo[tid].last);
460 return &s_threadinfo[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000461}
462
barta2b6e1b2008-03-17 18:32:39 +0000463/** Return the latest segment of thread 'tid' and increment its reference
464 * count.
465 */
466void thread_get_latest_segment(Segment** sg, const DrdThreadId tid)
467{
468 tl_assert(sg);
469 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
470 tl_assert(s_threadinfo[tid].last);
471
472 sg_put(*sg);
473 *sg = sg_get(s_threadinfo[tid].last);
474}
475
sewardjaf44c822007-11-25 14:01:38 +0000476/**
477 * Compute the minimum of all latest vector clocks of all threads
478 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
479 * @param vc pointer to a vectorclock, holds result upon return.
480 */
481static void thread_compute_minimum_vc(VectorClock* vc)
482{
bart3772a982008-03-15 08:11:03 +0000483 unsigned i;
484 Bool first;
485 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000486
bart3772a982008-03-15 08:11:03 +0000487 first = True;
488 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
489 {
490 latest_sg = s_threadinfo[i].last;
491 if (latest_sg)
492 {
493 if (first)
494 vc_assign(vc, &latest_sg->vc);
495 else
496 vc_min(vc, &latest_sg->vc);
497 first = False;
498 }
499 }
sewardjaf44c822007-11-25 14:01:38 +0000500}
501
502static void thread_compute_maximum_vc(VectorClock* vc)
503{
bart3772a982008-03-15 08:11:03 +0000504 unsigned i;
505 Bool first;
506 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000507
bart3772a982008-03-15 08:11:03 +0000508 first = True;
509 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
510 {
511 latest_sg = s_threadinfo[i].last;
512 if (latest_sg)
513 {
514 if (first)
515 vc_assign(vc, &latest_sg->vc);
516 else
517 vc_combine(vc, &latest_sg->vc);
518 first = False;
519 }
520 }
sewardjaf44c822007-11-25 14:01:38 +0000521}
522
523/**
bart5bd9f2d2008-03-03 20:31:58 +0000524 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000525 * clock of every thread -- these segments can no longer be involved in a
526 * data race.
527 */
528static void thread_discard_ordered_segments(void)
529{
bart3772a982008-03-15 08:11:03 +0000530 unsigned i;
531 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000532
bart3772a982008-03-15 08:11:03 +0000533 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000534
bart3772a982008-03-15 08:11:03 +0000535 vc_init(&thread_vc_min, 0, 0);
536 thread_compute_minimum_vc(&thread_vc_min);
537 if (sg_get_trace())
538 {
539 char msg[256];
540 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000541
bart3772a982008-03-15 08:11:03 +0000542 vc_init(&thread_vc_max, 0, 0);
543 thread_compute_maximum_vc(&thread_vc_max);
544 VG_(snprintf)(msg, sizeof(msg),
545 "Discarding ordered segments -- min vc is ");
546 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
547 &thread_vc_min);
548 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
549 ", max vc is ");
550 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
551 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000552 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000553 vc_cleanup(&thread_vc_max);
554 }
sewardjaf44c822007-11-25 14:01:38 +0000555
bart3772a982008-03-15 08:11:03 +0000556 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
557 {
558 Segment* sg;
559 Segment* sg_next;
560 for (sg = s_threadinfo[i].first;
561 sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
562 sg = sg_next)
563 {
564 thread_discard_segment(i, sg);
565 }
566 }
567 vc_cleanup(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000568}
569
barta9c37392008-03-22 09:38:48 +0000570/** Merge all segments that may be merged without triggering false positives
571 * or discarding real data races. For the theoretical background of segment
572 * merging, see also the following paper:
573 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
574 * Bounding the number of segment histories during data race detection.
575 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
576 * September 2002.
577 */
578static void thread_merge_segments(void)
579{
580 unsigned i;
581
582 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
583 {
584 Segment* sg;
585
bart23d3a4e2008-04-05 12:53:00 +0000586 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000587
588 for (sg = s_threadinfo[i].first; sg; sg = sg->next)
589 {
590 if (sg_get_refcnt(sg) == 1
591 && sg->next
592 && sg_get_refcnt(sg->next) == 1
593 && sg->next->next)
594 {
595 /* Merge sg and sg->next into sg. */
596 sg_merge(sg, sg->next);
597 thread_discard_segment(i, sg->next);
598 }
599 }
600
bart23d3a4e2008-04-05 12:53:00 +0000601 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000602 }
603}
604
bartd66e3a82008-04-06 15:02:17 +0000605/** Every change in the vector clock of a thread may cause segments that
606 * were previously ordered to this thread to become unordered. Hence,
607 * it may be necessary to recalculate the danger set if the vector clock
608 * of the current thread is updated. This function check whether such a
609 * recalculation is necessary.
610 *
611 * @param tid Thread ID of the thread to which a new segment has been
612 * appended.
613 * @param new_sg Pointer to the most recent segment of thread tid.
614 */
615static Bool danger_set_update_needed(const DrdThreadId tid,
616 const Segment* const new_sg)
617{
618 unsigned i;
619 const Segment* old_sg;
620
621 tl_assert(new_sg);
622
623 /* If a new segment was added to another thread than the running thread, */
624 /* just tell the caller to update the danger set. */
625 if (tid != s_drd_running_tid)
626 return True;
627
628 /* Always let the caller update the danger set after creation of the */
629 /* first segment. */
630 old_sg = new_sg->prev;
631 if (old_sg == 0)
632 return True;
633
634 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
635 {
636 Segment* q;
637
638 if (i == s_drd_running_tid)
639 continue;
640
641 for (q = s_threadinfo[i].last; q; q = q->prev)
642 {
643 /* If the expression below evaluates to false, this expression will */
644 /* also evaluate to false for all subsequent iterations. So stop */
645 /* iterating. */
646 if (vc_lte(&q->vc, &old_sg->vc))
647 break;
648 /* If the vector clock of the 2nd the last segment is not ordered */
649 /* to the vector clock of segment q, and the last segment is, ask */
650 /* the caller to update the danger set. */
651 if (! vc_lte(&old_sg->vc, &q->vc))
652 {
653 return True;
654 }
655 /* If the vector clock of the last segment is not ordered to the */
656 /* vector clock of segment q, ask the caller to update the danger */
657 /* set. */
658 if (! vc_lte(&q->vc, &new_sg->vc) && ! vc_lte(&new_sg->vc, &q->vc))
659 {
660 return True;
661 }
662 }
663 }
664
665 return False;
666}
667
barta2b6e1b2008-03-17 18:32:39 +0000668/** Create a new segment for the specified thread, and discard any segments
669 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000670 */
671void thread_new_segment(const DrdThreadId tid)
672{
bartd66e3a82008-04-06 15:02:17 +0000673 Segment* new_sg;
674
barta2b6e1b2008-03-17 18:32:39 +0000675 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000676
bartd66e3a82008-04-06 15:02:17 +0000677 new_sg = sg_new(tid, tid);
678 thread_append_segment(tid, new_sg);
679
680 if (danger_set_update_needed(tid, new_sg))
681 {
bart4af812e2008-04-13 15:39:38 +0000682 thread_compute_danger_set(&s_danger_set, s_drd_running_tid);
bartd66e3a82008-04-06 15:02:17 +0000683 s_danger_set_new_segment_count++;
684 }
sewardjaf44c822007-11-25 14:01:38 +0000685
bart3772a982008-03-15 08:11:03 +0000686 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000687
barta9c37392008-03-22 09:38:48 +0000688 if (s_segment_merging)
689 thread_merge_segments();
sewardjaf44c822007-11-25 14:01:38 +0000690}
691
bart26f73e12008-02-24 18:37:08 +0000692/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000693void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
694{
bart3772a982008-03-15 08:11:03 +0000695 tl_assert(joiner != joinee);
696 tl_assert(0 <= joiner && joiner < DRD_N_THREADS
697 && joiner != DRD_INVALID_THREADID);
698 tl_assert(0 <= joinee && joinee < DRD_N_THREADS
699 && joinee != DRD_INVALID_THREADID);
700 tl_assert(s_threadinfo[joiner].last);
701 tl_assert(s_threadinfo[joinee].last);
702 vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
703 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000704
bart3772a982008-03-15 08:11:03 +0000705 if (joiner == s_drd_running_tid)
706 {
bart4af812e2008-04-13 15:39:38 +0000707 thread_compute_danger_set(&s_danger_set, joiner);
bart3772a982008-03-15 08:11:03 +0000708 }
sewardjaf44c822007-11-25 14:01:38 +0000709}
710
bart26f73e12008-02-24 18:37:08 +0000711/** Call this function after thread 'tid' had to wait because of thread
712 * synchronization until the memory accesses in the segment with vector clock
713 * 'vc' finished.
714 */
sewardjaf44c822007-11-25 14:01:38 +0000715void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
716{
bart3772a982008-03-15 08:11:03 +0000717 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
718 tl_assert(s_threadinfo[tid].last);
719 tl_assert(vc);
720 vc_combine(&s_threadinfo[tid].last->vc, vc);
bart4af812e2008-04-13 15:39:38 +0000721 thread_compute_danger_set(&s_danger_set, tid);
bart3772a982008-03-15 08:11:03 +0000722 thread_discard_ordered_segments();
bartd66e3a82008-04-06 15:02:17 +0000723 s_danger_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000724}
725
bart26f73e12008-02-24 18:37:08 +0000726/** Call this function whenever a thread is no longer using the memory
727 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
728 * increase.
729 */
sewardjaf44c822007-11-25 14:01:38 +0000730void thread_stop_using_mem(const Addr a1, const Addr a2)
731{
bartd43f8d32008-03-16 17:29:20 +0000732 DrdThreadId other_user;
733 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000734
bart3772a982008-03-15 08:11:03 +0000735 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000736 other_user = DRD_INVALID_THREADID;
bart3772a982008-03-15 08:11:03 +0000737 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
738 {
739 Segment* p;
740 for (p = s_threadinfo[i].first; p; p = p->next)
741 {
742 if (other_user == DRD_INVALID_THREADID
bart8bf2f8b2008-03-30 17:56:43 +0000743 && i != s_drd_running_tid)
sewardjaf44c822007-11-25 14:01:38 +0000744 {
bart8bf2f8b2008-03-30 17:56:43 +0000745 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
746 {
747 other_user = i;
748 }
749 continue;
sewardjaf44c822007-11-25 14:01:38 +0000750 }
bart3772a982008-03-15 08:11:03 +0000751 bm_clear(p->bm, a1, a2);
752 }
753 }
sewardjaf44c822007-11-25 14:01:38 +0000754
bart3772a982008-03-15 08:11:03 +0000755 /* If any other thread had accessed memory in [ a1, a2 [, update the */
756 /* danger set. */
757 if (other_user != DRD_INVALID_THREADID
758 && bm_has_any_access(s_danger_set, a1, a2))
759 {
bart4af812e2008-04-13 15:39:38 +0000760 thread_compute_danger_set(&s_danger_set, thread_get_running_tid());
bart3772a982008-03-15 08:11:03 +0000761 }
sewardjaf44c822007-11-25 14:01:38 +0000762}
763
bart0268dfa2008-03-11 20:10:21 +0000764void thread_start_recording(const DrdThreadId tid)
765{
bart3772a982008-03-15 08:11:03 +0000766 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
767 tl_assert(! s_threadinfo[tid].is_recording);
768 s_threadinfo[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000769}
770
771void thread_stop_recording(const DrdThreadId tid)
772{
bart3772a982008-03-15 08:11:03 +0000773 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
774 tl_assert(s_threadinfo[tid].is_recording);
775 s_threadinfo[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000776}
777
sewardjaf44c822007-11-25 14:01:38 +0000778void thread_print_all(void)
779{
bart3772a982008-03-15 08:11:03 +0000780 unsigned i;
781 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000782
bart3772a982008-03-15 08:11:03 +0000783 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
784 {
785 if (s_threadinfo[i].first)
786 {
787 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000788 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000789 "**************\n",
790 i,
791 s_threadinfo[i].vg_thread_exists,
792 s_threadinfo[i].vg_threadid,
793 s_threadinfo[i].posix_thread_exists,
794 s_threadinfo[i].pt_threadid,
bart354009c2008-03-16 10:42:33 +0000795 s_threadinfo[i].detached_posix_thread);
bart3772a982008-03-15 08:11:03 +0000796 for (p = s_threadinfo[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000797 {
bart3772a982008-03-15 08:11:03 +0000798 sg_print(p);
sewardjaf44c822007-11-25 14:01:38 +0000799 }
bart3772a982008-03-15 08:11:03 +0000800 }
801 }
sewardjaf44c822007-11-25 14:01:38 +0000802}
803
804static void show_call_stack(const DrdThreadId tid,
805 const Char* const msg,
806 ExeContext* const callstack)
807{
bart3772a982008-03-15 08:11:03 +0000808 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000809
bartaa97a542008-03-16 17:57:01 +0000810 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000811
bart3772a982008-03-15 08:11:03 +0000812 if (vg_tid != VG_INVALID_THREADID)
813 {
814 if (callstack)
815 {
816 VG_(pp_ExeContext)(callstack);
817 }
818 else
819 {
820 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
821 }
822 }
823 else
824 {
825 VG_(message)(Vg_UserMsg,
826 " (thread finished, call stack no longer available)");
827 }
sewardjaf44c822007-11-25 14:01:38 +0000828}
829
sewardjaf44c822007-11-25 14:01:38 +0000830static void
831thread_report_conflicting_segments_segment(const DrdThreadId tid,
832 const Addr addr,
833 const SizeT size,
834 const BmAccessTypeT access_type,
835 const Segment* const p)
836{
bart3772a982008-03-15 08:11:03 +0000837 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000838
bart3772a982008-03-15 08:11:03 +0000839 tl_assert(0 <= tid && tid < DRD_N_THREADS
840 && tid != DRD_INVALID_THREADID);
841 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000842
bart3772a982008-03-15 08:11:03 +0000843 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
844 {
845 if (i != tid)
846 {
847 Segment* q;
848 for (q = s_threadinfo[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000849 {
bart3772a982008-03-15 08:11:03 +0000850 // Since q iterates over the segments of thread i in order of
851 // decreasing vector clocks, if q->vc <= p->vc, then
852 // q->next->vc <= p->vc will also hold. Hence, break out of the
853 // loop once this condition is met.
854 if (vc_lte(&q->vc, &p->vc))
855 break;
856 if (! vc_lte(&p->vc, &q->vc))
857 {
858 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
859 {
860 tl_assert(q->stacktrace);
861 show_call_stack(i, "Other segment start",
862 q->stacktrace);
863 show_call_stack(i, "Other segment end",
864 q->next ? q->next->stacktrace : 0);
865 }
866 }
sewardjaf44c822007-11-25 14:01:38 +0000867 }
bart3772a982008-03-15 08:11:03 +0000868 }
869 }
sewardjaf44c822007-11-25 14:01:38 +0000870}
871
872void thread_report_conflicting_segments(const DrdThreadId tid,
873 const Addr addr,
874 const SizeT size,
875 const BmAccessTypeT access_type)
876{
bart3772a982008-03-15 08:11:03 +0000877 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000878
bart3772a982008-03-15 08:11:03 +0000879 tl_assert(0 <= tid && tid < DRD_N_THREADS
880 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000881
bart3772a982008-03-15 08:11:03 +0000882 for (p = s_threadinfo[tid].first; p; p = p->next)
883 {
884 if (bm_has(p->bm, addr, addr + size, access_type))
885 {
886 thread_report_conflicting_segments_segment(tid, addr, size,
887 access_type, p);
888 }
889 }
sewardjaf44c822007-11-25 14:01:38 +0000890}
sewardjaf44c822007-11-25 14:01:38 +0000891
bart26f73e12008-02-24 18:37:08 +0000892/** Compute a bitmap that represents the union of all memory accesses of all
893 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +0000894 */
bart4af812e2008-04-13 15:39:38 +0000895static void thread_compute_danger_set(struct bitmap** danger_set,
896 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000897{
bart3772a982008-03-15 08:11:03 +0000898 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000899
bart3772a982008-03-15 08:11:03 +0000900 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
901 tl_assert(tid == s_drd_running_tid);
sewardjaf44c822007-11-25 14:01:38 +0000902
bart3772a982008-03-15 08:11:03 +0000903 s_update_danger_set_count++;
904 s_danger_set_bitmap_creation_count -= bm_get_bitmap_creation_count();
905 s_danger_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000906
bart4af812e2008-04-13 15:39:38 +0000907 if (*danger_set)
bart3772a982008-03-15 08:11:03 +0000908 {
bart4af812e2008-04-13 15:39:38 +0000909 bm_delete(*danger_set);
bart3772a982008-03-15 08:11:03 +0000910 }
bart4af812e2008-04-13 15:39:38 +0000911 *danger_set = bm_new();
bart26f73e12008-02-24 18:37:08 +0000912
bart3772a982008-03-15 08:11:03 +0000913 if (s_trace_danger_set)
914 {
915 char msg[256];
916
917 VG_(snprintf)(msg, sizeof(msg),
bartaa97a542008-03-16 17:57:01 +0000918 "computing danger set for thread %d/%d with vc ",
919 DrdThreadIdToVgThreadId(tid), tid);
bart3772a982008-03-15 08:11:03 +0000920 vc_snprint(msg + VG_(strlen)(msg),
921 sizeof(msg) - VG_(strlen)(msg),
922 &s_threadinfo[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +0000923 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000924 }
925
926 p = s_threadinfo[tid].last;
927 {
928 unsigned j;
929
930 if (s_trace_danger_set)
931 {
bart26f73e12008-02-24 18:37:08 +0000932 char msg[256];
933
934 VG_(snprintf)(msg, sizeof(msg),
bart3772a982008-03-15 08:11:03 +0000935 "danger set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +0000936 tid);
937 vc_snprint(msg + VG_(strlen)(msg),
938 sizeof(msg) - VG_(strlen)(msg),
bart3772a982008-03-15 08:11:03 +0000939 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +0000940 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000941 }
sewardjaf44c822007-11-25 14:01:38 +0000942
bart3772a982008-03-15 08:11:03 +0000943 for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++)
944 {
bartd66e3a82008-04-06 15:02:17 +0000945 if (j != tid && IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +0000946 {
bart3772a982008-03-15 08:11:03 +0000947 const Segment* q;
948 for (q = s_threadinfo[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000949 {
950 if (! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000951 {
952 if (s_trace_danger_set)
953 {
954 char msg[256];
955 VG_(snprintf)(msg, sizeof(msg),
956 "danger set: [%d] merging segment ", j);
957 vc_snprint(msg + VG_(strlen)(msg),
958 sizeof(msg) - VG_(strlen)(msg),
959 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000960 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000961 }
bart4af812e2008-04-13 15:39:38 +0000962 bm_merge2(*danger_set, q->bm);
bart3772a982008-03-15 08:11:03 +0000963 }
964 else
965 {
966 if (s_trace_danger_set)
967 {
968 char msg[256];
969 VG_(snprintf)(msg, sizeof(msg),
970 "danger set: [%d] ignoring segment ", j);
971 vc_snprint(msg + VG_(strlen)(msg),
972 sizeof(msg) - VG_(strlen)(msg),
973 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000974 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000975 }
976 }
bartd66e3a82008-04-06 15:02:17 +0000977 }
bart26f73e12008-02-24 18:37:08 +0000978 }
bart3772a982008-03-15 08:11:03 +0000979 }
bart3772a982008-03-15 08:11:03 +0000980 }
sewardjaf44c822007-11-25 14:01:38 +0000981
bart3772a982008-03-15 08:11:03 +0000982 s_danger_set_bitmap_creation_count += bm_get_bitmap_creation_count();
983 s_danger_set_bitmap2_creation_count += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000984
bart3772a982008-03-15 08:11:03 +0000985 if (0 && s_trace_danger_set)
986 {
barta2b6e1b2008-03-17 18:32:39 +0000987 VG_(message)(Vg_UserMsg, "[%d] new danger set:", tid);
bart4af812e2008-04-13 15:39:38 +0000988 bm_print(*danger_set);
barta2b6e1b2008-03-17 18:32:39 +0000989 VG_(message)(Vg_UserMsg, "[%d] end of new danger set.", tid);
bart3772a982008-03-15 08:11:03 +0000990 }
sewardjaf44c822007-11-25 14:01:38 +0000991}
992
sewardjaf44c822007-11-25 14:01:38 +0000993ULong thread_get_context_switch_count(void)
994{
bart3772a982008-03-15 08:11:03 +0000995 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +0000996}
997
sewardjaf44c822007-11-25 14:01:38 +0000998ULong thread_get_discard_ordered_segments_count(void)
999{
bart3772a982008-03-15 08:11:03 +00001000 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001001}
1002
bartd66e3a82008-04-06 15:02:17 +00001003ULong thread_get_update_danger_set_count(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001004{
bartd66e3a82008-04-06 15:02:17 +00001005 tl_assert(dsnsc);
1006 tl_assert(dscvc);
1007 *dsnsc = s_danger_set_new_segment_count;
1008 *dscvc = s_danger_set_combine_vc_count;
bart3772a982008-03-15 08:11:03 +00001009 return s_update_danger_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001010}
1011
1012ULong thread_get_danger_set_bitmap_creation_count(void)
1013{
bart3772a982008-03-15 08:11:03 +00001014 return s_danger_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001015}
1016
1017ULong thread_get_danger_set_bitmap2_creation_count(void)
1018{
bart3772a982008-03-15 08:11:03 +00001019 return s_danger_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001020}