blob: 2737b1351f9a81fa6cd192773899e3fad54187ab [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);
sewardjaf44c822007-11-25 14:01:38 +000046static void thread_update_danger_set(const DrdThreadId tid);
47
48
49// Local variables.
50
51static ULong s_context_switch_count;
52static ULong s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +000053static ULong s_update_danger_set_count;
bartd66e3a82008-04-06 15:02:17 +000054static ULong s_danger_set_new_segment_count;
55static ULong s_danger_set_combine_vc_count;
sewardjaf44c822007-11-25 14:01:38 +000056static ULong s_danger_set_bitmap_creation_count;
57static ULong s_danger_set_bitmap2_creation_count;
sewardj8b09d4f2007-12-04 21:27:18 +000058static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bartf00a85b2008-03-13 18:49:23 +000059DrdThreadId s_drd_running_tid = DRD_INVALID_THREADID;
60ThreadInfo s_threadinfo[DRD_N_THREADS];
bart1a473c72008-03-13 19:03:38 +000061struct bitmap* s_danger_set;
bart26f73e12008-02-24 18:37:08 +000062static Bool s_trace_context_switches = False;
63static Bool s_trace_danger_set = False;
barta9c37392008-03-22 09:38:48 +000064static Bool s_segment_merging = True;
sewardjaf44c822007-11-25 14:01:38 +000065
66
67// Function definitions.
68
bart26f73e12008-02-24 18:37:08 +000069void thread_trace_context_switches(const Bool t)
70{
bart3772a982008-03-15 08:11:03 +000071 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000072}
73
74void thread_trace_danger_set(const Bool t)
75{
bart3772a982008-03-15 08:11:03 +000076 s_trace_danger_set = t;
bart26f73e12008-02-24 18:37:08 +000077}
78
barta9c37392008-03-22 09:38:48 +000079void thread_set_segment_merging(const Bool m)
80{
81 s_segment_merging = m;
82}
83
sewardjaf44c822007-11-25 14:01:38 +000084__inline__ Bool IsValidDrdThreadId(const DrdThreadId tid)
85{
bart3772a982008-03-15 08:11:03 +000086 return (0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID
87 && ! (s_threadinfo[tid].vg_thread_exists == False
88 && s_threadinfo[tid].posix_thread_exists == False
89 && s_threadinfo[tid].detached_posix_thread == False));
sewardjaf44c822007-11-25 14:01:38 +000090}
91
92/**
93 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
94 * Valgrind's ThreadId does not yet exist.
95 **/
96DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid)
97{
bart3772a982008-03-15 08:11:03 +000098 int i;
sewardjaf44c822007-11-25 14:01:38 +000099
bart3772a982008-03-15 08:11:03 +0000100 if (tid == VG_INVALID_THREADID)
101 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000102
bart3772a982008-03-15 08:11:03 +0000103 for (i = 1; i < DRD_N_THREADS; i++)
104 {
105 if (s_threadinfo[i].vg_thread_exists == True
106 && s_threadinfo[i].vg_threadid == tid)
107 {
108 return i;
109 }
110 }
sewardjaf44c822007-11-25 14:01:38 +0000111
bart3772a982008-03-15 08:11:03 +0000112 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000113}
114
115static
116DrdThreadId VgThreadIdToNewDrdThreadId(const ThreadId tid)
117{
bart3772a982008-03-15 08:11:03 +0000118 int i;
sewardjaf44c822007-11-25 14:01:38 +0000119
bart3772a982008-03-15 08:11:03 +0000120 tl_assert(VgThreadIdToDrdThreadId(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000121
bart3772a982008-03-15 08:11:03 +0000122 for (i = 1; i < DRD_N_THREADS; i++)
123 {
124 if (s_threadinfo[i].vg_thread_exists == False
125 && s_threadinfo[i].posix_thread_exists == False
126 && s_threadinfo[i].detached_posix_thread == False)
127 {
128 s_threadinfo[i].vg_thread_exists = True;
129 s_threadinfo[i].vg_threadid = tid;
130 s_threadinfo[i].pt_threadid = INVALID_POSIX_THREADID;
bart3772a982008-03-15 08:11:03 +0000131 s_threadinfo[i].stack_min = 0;
bartcac53462008-03-29 09:27:08 +0000132 s_threadinfo[i].stack_min_min = 0;
bart3772a982008-03-15 08:11:03 +0000133 s_threadinfo[i].stack_startup = 0;
134 s_threadinfo[i].stack_max = 0;
bart3772a982008-03-15 08:11:03 +0000135 s_threadinfo[i].is_recording = True;
136 s_threadinfo[i].synchr_nesting = 0;
137 if (s_threadinfo[i].first != 0)
138 VG_(printf)("drd thread id = %d\n", i);
139 tl_assert(s_threadinfo[i].first == 0);
140 tl_assert(s_threadinfo[i].last == 0);
141 return i;
142 }
143 }
sewardjaf44c822007-11-25 14:01:38 +0000144
bart3772a982008-03-15 08:11:03 +0000145 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000146
bart3772a982008-03-15 08:11:03 +0000147 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000148}
149
150DrdThreadId PtThreadIdToDrdThreadId(const PThreadId tid)
151{
bart3772a982008-03-15 08:11:03 +0000152 int i;
sewardjaf44c822007-11-25 14:01:38 +0000153
bart3772a982008-03-15 08:11:03 +0000154 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000155
bart3772a982008-03-15 08:11:03 +0000156 for (i = 1; i < DRD_N_THREADS; i++)
157 {
158 if (s_threadinfo[i].posix_thread_exists
159 && s_threadinfo[i].pt_threadid == tid)
160 {
161 return i;
162 }
163 }
164 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000165}
166
167ThreadId DrdThreadIdToVgThreadId(const DrdThreadId tid)
168{
bart3772a982008-03-15 08:11:03 +0000169 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
170 return (s_threadinfo[tid].vg_thread_exists
171 ? s_threadinfo[tid].vg_threadid
172 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000173}
174
bart23d3a4e2008-04-05 12:53:00 +0000175#if 0
bart26f73e12008-02-24 18:37:08 +0000176/** Sanity check of the doubly linked list of segments referenced by a
177 * ThreadInfo struct.
178 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000179 */
180static Bool sane_ThreadInfo(const ThreadInfo* const ti)
181{
bart3772a982008-03-15 08:11:03 +0000182 Segment* p;
183 for (p = ti->first; p; p = p->next) {
184 if (p->next && p->next->prev != p)
185 return False;
186 if (p->next == 0 && p != ti->last)
187 return False;
188 }
189 for (p = ti->last; p; p = p->prev) {
190 if (p->prev && p->prev->next != p)
191 return False;
192 if (p->prev == 0 && p != ti->first)
193 return False;
194 }
195 return True;
sewardjaf44c822007-11-25 14:01:38 +0000196}
bart23d3a4e2008-04-05 12:53:00 +0000197#endif
sewardjaf44c822007-11-25 14:01:38 +0000198
199DrdThreadId thread_pre_create(const DrdThreadId creator,
200 const ThreadId vg_created)
201{
bart3772a982008-03-15 08:11:03 +0000202 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000203
bart3772a982008-03-15 08:11:03 +0000204 tl_assert(VgThreadIdToDrdThreadId(vg_created) == DRD_INVALID_THREADID);
205 created = VgThreadIdToNewDrdThreadId(vg_created);
206 tl_assert(0 <= created && created < DRD_N_THREADS
207 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000208
bart3772a982008-03-15 08:11:03 +0000209 tl_assert(s_threadinfo[created].first == 0);
210 tl_assert(s_threadinfo[created].last == 0);
211 thread_append_segment(created, sg_new(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000212
bart3772a982008-03-15 08:11:03 +0000213 return created;
sewardjaf44c822007-11-25 14:01:38 +0000214}
215
bart26f73e12008-02-24 18:37:08 +0000216/** Allocate the first segment for a thread. Call this just after
217 * pthread_create().
sewardjaf44c822007-11-25 14:01:38 +0000218 */
219DrdThreadId thread_post_create(const ThreadId vg_created)
220{
bart3772a982008-03-15 08:11:03 +0000221 const DrdThreadId created = VgThreadIdToDrdThreadId(vg_created);
sewardjaf44c822007-11-25 14:01:38 +0000222
bart3772a982008-03-15 08:11:03 +0000223 tl_assert(0 <= created && created < DRD_N_THREADS
224 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000225
bart3772a982008-03-15 08:11:03 +0000226 s_threadinfo[created].stack_max = VG_(thread_get_stack_max)(vg_created);
227 s_threadinfo[created].stack_startup = s_threadinfo[created].stack_max;
228 s_threadinfo[created].stack_min = s_threadinfo[created].stack_max;
bartcac53462008-03-29 09:27:08 +0000229 s_threadinfo[created].stack_min_min = s_threadinfo[created].stack_max;
230 s_threadinfo[created].stack_size = VG_(thread_get_stack_size)(vg_created);
bart3772a982008-03-15 08:11:03 +0000231 tl_assert(s_threadinfo[created].stack_max != 0);
sewardjaf44c822007-11-25 14:01:38 +0000232
bart3772a982008-03-15 08:11:03 +0000233 return created;
sewardjaf44c822007-11-25 14:01:38 +0000234}
235
236/* NPTL hack: NPTL allocates the 'struct pthread' on top of the stack, */
237/* and accesses this data structure from multiple threads without locking. */
238/* Any conflicting accesses in the range stack_startup..stack_max will be */
239/* ignored. */
240void thread_set_stack_startup(const DrdThreadId tid, const Addr stack_startup)
241{
bart3772a982008-03-15 08:11:03 +0000242 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
243 tl_assert(s_threadinfo[tid].stack_min <= stack_startup);
244 tl_assert(stack_startup <= s_threadinfo[tid].stack_max);
245 s_threadinfo[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000246}
247
248Addr thread_get_stack_min(const DrdThreadId tid)
249{
bart3772a982008-03-15 08:11:03 +0000250 tl_assert(0 <= tid && tid < DRD_N_THREADS
251 && tid != DRD_INVALID_THREADID);
252 return s_threadinfo[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000253}
254
bartcac53462008-03-29 09:27:08 +0000255Addr thread_get_stack_min_min(const DrdThreadId tid)
256{
257 tl_assert(0 <= tid && tid < DRD_N_THREADS
258 && tid != DRD_INVALID_THREADID);
259 return s_threadinfo[tid].stack_min_min;
260}
261
bartd43f8d32008-03-16 17:29:20 +0000262Addr thread_get_stack_max(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000263{
bartd43f8d32008-03-16 17:29:20 +0000264 tl_assert(0 <= tid && tid < DRD_N_THREADS
265 && tid != DRD_INVALID_THREADID);
266 return s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000267}
268
bartcac53462008-03-29 09:27:08 +0000269SizeT thread_get_stack_size(const DrdThreadId tid)
270{
271 tl_assert(0 <= tid && tid < DRD_N_THREADS
272 && tid != DRD_INVALID_THREADID);
273 return s_threadinfo[tid].stack_size;
274}
275
barta2b6e1b2008-03-17 18:32:39 +0000276/** Clean up thread-specific data structures. Call this just after
277 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000278 */
279void thread_delete(const DrdThreadId tid)
280{
bart3772a982008-03-15 08:11:03 +0000281 Segment* sg;
282 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000283
bart3772a982008-03-15 08:11:03 +0000284 tl_assert(0 <= tid && tid < DRD_N_THREADS
285 && tid != DRD_INVALID_THREADID);
286 tl_assert(s_threadinfo[tid].synchr_nesting == 0);
287 for (sg = s_threadinfo[tid].last; sg; sg = sg_prev)
288 {
289 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000290 sg->prev = 0;
291 sg->next = 0;
292 sg_put(sg);
bart3772a982008-03-15 08:11:03 +0000293 }
294 s_threadinfo[tid].vg_thread_exists = False;
295 s_threadinfo[tid].posix_thread_exists = False;
296 tl_assert(s_threadinfo[tid].detached_posix_thread == False);
297 s_threadinfo[tid].first = 0;
298 s_threadinfo[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000299}
300
301/* Called after a thread performed its last memory access and before */
302/* thread_delete() is called. Note: thread_delete() is only called for */
303/* joinable threads, not for detached threads. */
304void thread_finished(const DrdThreadId tid)
305{
bart3772a982008-03-15 08:11:03 +0000306 tl_assert(0 <= tid && tid < DRD_N_THREADS
307 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000308
bart3772a982008-03-15 08:11:03 +0000309 s_threadinfo[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000310
bart3772a982008-03-15 08:11:03 +0000311 if (s_threadinfo[tid].detached_posix_thread)
312 {
313 /* Once a detached thread has finished, its stack is deallocated and */
314 /* should no longer be taken into account when computing the danger set*/
315 s_threadinfo[tid].stack_min = s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000316
bart3772a982008-03-15 08:11:03 +0000317 /* For a detached thread, calling pthread_exit() invalidates the */
318 /* POSIX thread ID associated with the detached thread. For joinable */
319 /* POSIX threads however, the POSIX thread ID remains live after the */
320 /* pthread_exit() call until pthread_join() is called. */
321 s_threadinfo[tid].posix_thread_exists = False;
322 }
sewardjaf44c822007-11-25 14:01:38 +0000323}
324
325void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
326{
bart3772a982008-03-15 08:11:03 +0000327 tl_assert(0 <= tid && tid < DRD_N_THREADS
328 && tid != DRD_INVALID_THREADID);
329 tl_assert(s_threadinfo[tid].pt_threadid == INVALID_POSIX_THREADID);
330 tl_assert(ptid != INVALID_POSIX_THREADID);
331 s_threadinfo[tid].posix_thread_exists = True;
332 s_threadinfo[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000333}
334
335Bool thread_get_joinable(const DrdThreadId tid)
336{
bart3772a982008-03-15 08:11:03 +0000337 tl_assert(0 <= tid && tid < DRD_N_THREADS
338 && tid != DRD_INVALID_THREADID);
339 return ! s_threadinfo[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000340}
341
342void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
343{
bart3772a982008-03-15 08:11:03 +0000344 tl_assert(0 <= tid && tid < DRD_N_THREADS
345 && tid != DRD_INVALID_THREADID);
346 tl_assert(!! joinable == joinable);
347 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000348#if 0
bart3772a982008-03-15 08:11:03 +0000349 VG_(message)(Vg_DebugMsg,
350 "thread_set_joinable(%d/%d, %s)",
351 tid,
352 s_threadinfo[tid].vg_threadid,
353 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000354#endif
bart3772a982008-03-15 08:11:03 +0000355 s_threadinfo[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000356}
357
sewardj8b09d4f2007-12-04 21:27:18 +0000358void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000359{
bart3772a982008-03-15 08:11:03 +0000360 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000361
bart3772a982008-03-15 08:11:03 +0000362 if (vg_tid != s_vg_running_tid)
363 {
364 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
365 }
sewardj8b09d4f2007-12-04 21:27:18 +0000366
bart3772a982008-03-15 08:11:03 +0000367 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
368 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000369}
370
371void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
372{
bart3772a982008-03-15 08:11:03 +0000373 tl_assert(vg_tid != VG_INVALID_THREADID);
374 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000375
bart3772a982008-03-15 08:11:03 +0000376 if (vg_tid != s_vg_running_tid)
377 {
378 if (s_trace_context_switches
379 && s_drd_running_tid != DRD_INVALID_THREADID)
380 {
381 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000382 "Context switch from thread %d/%d to thread %d/%d;"
383 " segments: %llu",
bartaa97a542008-03-16 17:57:01 +0000384 s_vg_running_tid, s_drd_running_tid,
barta2b6e1b2008-03-17 18:32:39 +0000385 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
386 sg_get_alive_segments_count());
bart3772a982008-03-15 08:11:03 +0000387 }
388 s_vg_running_tid = vg_tid;
389 s_drd_running_tid = drd_tid;
390 thread_update_danger_set(drd_tid);
391 s_context_switch_count++;
392 }
sewardj8b09d4f2007-12-04 21:27:18 +0000393
bart3772a982008-03-15 08:11:03 +0000394 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
395 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000396}
397
bart0268dfa2008-03-11 20:10:21 +0000398int thread_enter_synchr(const DrdThreadId tid)
399{
bart3772a982008-03-15 08:11:03 +0000400 tl_assert(IsValidDrdThreadId(tid));
401 return s_threadinfo[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000402}
403
404int thread_leave_synchr(const DrdThreadId tid)
405{
bart3772a982008-03-15 08:11:03 +0000406 tl_assert(IsValidDrdThreadId(tid));
407 tl_assert(s_threadinfo[tid].synchr_nesting >= 1);
408 return --s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000409}
410
411int thread_get_synchr_nesting_count(const DrdThreadId tid)
412{
bart3772a982008-03-15 08:11:03 +0000413 tl_assert(IsValidDrdThreadId(tid));
414 return s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000415}
416
bart1a473c72008-03-13 19:03:38 +0000417/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000418static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000419{
bart3772a982008-03-15 08:11:03 +0000420 tl_assert(0 <= tid && tid < DRD_N_THREADS
421 && tid != DRD_INVALID_THREADID);
bart23d3a4e2008-04-05 12:53:00 +0000422 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart3772a982008-03-15 08:11:03 +0000423 sg->prev = s_threadinfo[tid].last;
424 sg->next = 0;
425 if (s_threadinfo[tid].last)
426 s_threadinfo[tid].last->next = sg;
427 s_threadinfo[tid].last = sg;
428 if (s_threadinfo[tid].first == 0)
429 s_threadinfo[tid].first = sg;
bart23d3a4e2008-04-05 12:53:00 +0000430 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000431}
432
bart26f73e12008-02-24 18:37:08 +0000433/** Remove a segment from the segment list of thread threadid, and free the
434 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000435 */
bart26f73e12008-02-24 18:37:08 +0000436static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000437{
bart3772a982008-03-15 08:11:03 +0000438 tl_assert(0 <= tid && tid < DRD_N_THREADS
439 && tid != DRD_INVALID_THREADID);
bart3f749672008-03-22 09:49:40 +0000440 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart26f73e12008-02-24 18:37:08 +0000441
bart3772a982008-03-15 08:11:03 +0000442 if (sg->prev)
443 sg->prev->next = sg->next;
444 if (sg->next)
445 sg->next->prev = sg->prev;
446 if (sg == s_threadinfo[tid].first)
447 s_threadinfo[tid].first = sg->next;
448 if (sg == s_threadinfo[tid].last)
449 s_threadinfo[tid].last = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000450 sg_put(sg);
bart3f749672008-03-22 09:49:40 +0000451
452 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000453}
454
455VectorClock* thread_get_vc(const DrdThreadId tid)
456{
barta2b6e1b2008-03-17 18:32:39 +0000457 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000458 tl_assert(s_threadinfo[tid].last);
459 return &s_threadinfo[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000460}
461
barta2b6e1b2008-03-17 18:32:39 +0000462/** Return the latest segment of thread 'tid' and increment its reference
463 * count.
464 */
465void thread_get_latest_segment(Segment** sg, const DrdThreadId tid)
466{
467 tl_assert(sg);
468 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
469 tl_assert(s_threadinfo[tid].last);
470
471 sg_put(*sg);
472 *sg = sg_get(s_threadinfo[tid].last);
473}
474
sewardjaf44c822007-11-25 14:01:38 +0000475/**
476 * Compute the minimum of all latest vector clocks of all threads
477 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
478 * @param vc pointer to a vectorclock, holds result upon return.
479 */
480static void thread_compute_minimum_vc(VectorClock* vc)
481{
bart3772a982008-03-15 08:11:03 +0000482 unsigned i;
483 Bool first;
484 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000485
bart3772a982008-03-15 08:11:03 +0000486 first = True;
487 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
488 {
489 latest_sg = s_threadinfo[i].last;
490 if (latest_sg)
491 {
492 if (first)
493 vc_assign(vc, &latest_sg->vc);
494 else
495 vc_min(vc, &latest_sg->vc);
496 first = False;
497 }
498 }
sewardjaf44c822007-11-25 14:01:38 +0000499}
500
501static void thread_compute_maximum_vc(VectorClock* vc)
502{
bart3772a982008-03-15 08:11:03 +0000503 unsigned i;
504 Bool first;
505 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000506
bart3772a982008-03-15 08:11:03 +0000507 first = True;
508 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
509 {
510 latest_sg = s_threadinfo[i].last;
511 if (latest_sg)
512 {
513 if (first)
514 vc_assign(vc, &latest_sg->vc);
515 else
516 vc_combine(vc, &latest_sg->vc);
517 first = False;
518 }
519 }
sewardjaf44c822007-11-25 14:01:38 +0000520}
521
522/**
bart5bd9f2d2008-03-03 20:31:58 +0000523 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000524 * clock of every thread -- these segments can no longer be involved in a
525 * data race.
526 */
527static void thread_discard_ordered_segments(void)
528{
bart3772a982008-03-15 08:11:03 +0000529 unsigned i;
530 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000531
bart3772a982008-03-15 08:11:03 +0000532 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000533
bart3772a982008-03-15 08:11:03 +0000534 vc_init(&thread_vc_min, 0, 0);
535 thread_compute_minimum_vc(&thread_vc_min);
536 if (sg_get_trace())
537 {
538 char msg[256];
539 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000540
bart3772a982008-03-15 08:11:03 +0000541 vc_init(&thread_vc_max, 0, 0);
542 thread_compute_maximum_vc(&thread_vc_max);
543 VG_(snprintf)(msg, sizeof(msg),
544 "Discarding ordered segments -- min vc is ");
545 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
546 &thread_vc_min);
547 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
548 ", max vc is ");
549 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
550 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000551 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000552 vc_cleanup(&thread_vc_max);
553 }
sewardjaf44c822007-11-25 14:01:38 +0000554
bart3772a982008-03-15 08:11:03 +0000555 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
556 {
557 Segment* sg;
558 Segment* sg_next;
559 for (sg = s_threadinfo[i].first;
560 sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
561 sg = sg_next)
562 {
563 thread_discard_segment(i, sg);
564 }
565 }
566 vc_cleanup(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000567}
568
barta9c37392008-03-22 09:38:48 +0000569/** Merge all segments that may be merged without triggering false positives
570 * or discarding real data races. For the theoretical background of segment
571 * merging, see also the following paper:
572 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
573 * Bounding the number of segment histories during data race detection.
574 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
575 * September 2002.
576 */
577static void thread_merge_segments(void)
578{
579 unsigned i;
580
581 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
582 {
583 Segment* sg;
584
bart23d3a4e2008-04-05 12:53:00 +0000585 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000586
587 for (sg = s_threadinfo[i].first; sg; sg = sg->next)
588 {
589 if (sg_get_refcnt(sg) == 1
590 && sg->next
591 && sg_get_refcnt(sg->next) == 1
592 && sg->next->next)
593 {
594 /* Merge sg and sg->next into sg. */
595 sg_merge(sg, sg->next);
596 thread_discard_segment(i, sg->next);
597 }
598 }
599
bart23d3a4e2008-04-05 12:53:00 +0000600 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000601 }
602}
603
bartd66e3a82008-04-06 15:02:17 +0000604/** Every change in the vector clock of a thread may cause segments that
605 * were previously ordered to this thread to become unordered. Hence,
606 * it may be necessary to recalculate the danger set if the vector clock
607 * of the current thread is updated. This function check whether such a
608 * recalculation is necessary.
609 *
610 * @param tid Thread ID of the thread to which a new segment has been
611 * appended.
612 * @param new_sg Pointer to the most recent segment of thread tid.
613 */
614static Bool danger_set_update_needed(const DrdThreadId tid,
615 const Segment* const new_sg)
616{
617 unsigned i;
618 const Segment* old_sg;
619
620 tl_assert(new_sg);
621
622 /* If a new segment was added to another thread than the running thread, */
623 /* just tell the caller to update the danger set. */
624 if (tid != s_drd_running_tid)
625 return True;
626
627 /* Always let the caller update the danger set after creation of the */
628 /* first segment. */
629 old_sg = new_sg->prev;
630 if (old_sg == 0)
631 return True;
632
633 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
634 {
635 Segment* q;
636
637 if (i == s_drd_running_tid)
638 continue;
639
640 for (q = s_threadinfo[i].last; q; q = q->prev)
641 {
642 /* If the expression below evaluates to false, this expression will */
643 /* also evaluate to false for all subsequent iterations. So stop */
644 /* iterating. */
645 if (vc_lte(&q->vc, &old_sg->vc))
646 break;
647 /* If the vector clock of the 2nd the last segment is not ordered */
648 /* to the vector clock of segment q, and the last segment is, ask */
649 /* the caller to update the danger set. */
650 if (! vc_lte(&old_sg->vc, &q->vc))
651 {
652 return True;
653 }
654 /* If the vector clock of the last segment is not ordered to the */
655 /* vector clock of segment q, ask the caller to update the danger */
656 /* set. */
657 if (! vc_lte(&q->vc, &new_sg->vc) && ! vc_lte(&new_sg->vc, &q->vc))
658 {
659 return True;
660 }
661 }
662 }
663
664 return False;
665}
666
barta2b6e1b2008-03-17 18:32:39 +0000667/** Create a new segment for the specified thread, and discard any segments
668 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000669 */
670void thread_new_segment(const DrdThreadId tid)
671{
bartd66e3a82008-04-06 15:02:17 +0000672 Segment* new_sg;
673
barta2b6e1b2008-03-17 18:32:39 +0000674 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000675
bartd66e3a82008-04-06 15:02:17 +0000676 new_sg = sg_new(tid, tid);
677 thread_append_segment(tid, new_sg);
678
679 if (danger_set_update_needed(tid, new_sg))
680 {
681 thread_update_danger_set(s_drd_running_tid);
682 s_danger_set_new_segment_count++;
683 }
sewardjaf44c822007-11-25 14:01:38 +0000684
bart3772a982008-03-15 08:11:03 +0000685 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000686
barta9c37392008-03-22 09:38:48 +0000687 if (s_segment_merging)
688 thread_merge_segments();
sewardjaf44c822007-11-25 14:01:38 +0000689}
690
bart26f73e12008-02-24 18:37:08 +0000691/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000692void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
693{
bart3772a982008-03-15 08:11:03 +0000694 tl_assert(joiner != joinee);
695 tl_assert(0 <= joiner && joiner < DRD_N_THREADS
696 && joiner != DRD_INVALID_THREADID);
697 tl_assert(0 <= joinee && joinee < DRD_N_THREADS
698 && joinee != DRD_INVALID_THREADID);
699 tl_assert(s_threadinfo[joiner].last);
700 tl_assert(s_threadinfo[joinee].last);
701 vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
702 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000703
bart3772a982008-03-15 08:11:03 +0000704 if (joiner == s_drd_running_tid)
705 {
706 thread_update_danger_set(joiner);
707 }
sewardjaf44c822007-11-25 14:01:38 +0000708}
709
bart26f73e12008-02-24 18:37:08 +0000710/** Call this function after thread 'tid' had to wait because of thread
711 * synchronization until the memory accesses in the segment with vector clock
712 * 'vc' finished.
713 */
sewardjaf44c822007-11-25 14:01:38 +0000714void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
715{
bart3772a982008-03-15 08:11:03 +0000716 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
717 tl_assert(s_threadinfo[tid].last);
718 tl_assert(vc);
719 vc_combine(&s_threadinfo[tid].last->vc, vc);
bartd66e3a82008-04-06 15:02:17 +0000720 thread_update_danger_set(tid);
bart3772a982008-03-15 08:11:03 +0000721 thread_discard_ordered_segments();
bartd66e3a82008-04-06 15:02:17 +0000722 s_danger_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000723}
724
bart26f73e12008-02-24 18:37:08 +0000725/** Call this function whenever a thread is no longer using the memory
726 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
727 * increase.
728 */
sewardjaf44c822007-11-25 14:01:38 +0000729void thread_stop_using_mem(const Addr a1, const Addr a2)
730{
bartd43f8d32008-03-16 17:29:20 +0000731 DrdThreadId other_user;
732 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000733
bart3772a982008-03-15 08:11:03 +0000734 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000735 other_user = DRD_INVALID_THREADID;
bart3772a982008-03-15 08:11:03 +0000736 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
737 {
738 Segment* p;
739 for (p = s_threadinfo[i].first; p; p = p->next)
740 {
741 if (other_user == DRD_INVALID_THREADID
bart8bf2f8b2008-03-30 17:56:43 +0000742 && i != s_drd_running_tid)
sewardjaf44c822007-11-25 14:01:38 +0000743 {
bart8bf2f8b2008-03-30 17:56:43 +0000744 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
745 {
746 other_user = i;
747 }
748 continue;
sewardjaf44c822007-11-25 14:01:38 +0000749 }
bart3772a982008-03-15 08:11:03 +0000750 bm_clear(p->bm, a1, a2);
751 }
752 }
sewardjaf44c822007-11-25 14:01:38 +0000753
bart3772a982008-03-15 08:11:03 +0000754 /* If any other thread had accessed memory in [ a1, a2 [, update the */
755 /* danger set. */
756 if (other_user != DRD_INVALID_THREADID
757 && bm_has_any_access(s_danger_set, a1, a2))
758 {
759 thread_update_danger_set(thread_get_running_tid());
760 }
sewardjaf44c822007-11-25 14:01:38 +0000761}
762
bart0268dfa2008-03-11 20:10:21 +0000763void thread_start_recording(const DrdThreadId tid)
764{
bart3772a982008-03-15 08:11:03 +0000765 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
766 tl_assert(! s_threadinfo[tid].is_recording);
767 s_threadinfo[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000768}
769
770void thread_stop_recording(const DrdThreadId tid)
771{
bart3772a982008-03-15 08:11:03 +0000772 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
773 tl_assert(s_threadinfo[tid].is_recording);
774 s_threadinfo[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000775}
776
sewardjaf44c822007-11-25 14:01:38 +0000777void thread_print_all(void)
778{
bart3772a982008-03-15 08:11:03 +0000779 unsigned i;
780 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000781
bart3772a982008-03-15 08:11:03 +0000782 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
783 {
784 if (s_threadinfo[i].first)
785 {
786 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000787 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000788 "**************\n",
789 i,
790 s_threadinfo[i].vg_thread_exists,
791 s_threadinfo[i].vg_threadid,
792 s_threadinfo[i].posix_thread_exists,
793 s_threadinfo[i].pt_threadid,
bart354009c2008-03-16 10:42:33 +0000794 s_threadinfo[i].detached_posix_thread);
bart3772a982008-03-15 08:11:03 +0000795 for (p = s_threadinfo[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000796 {
bart3772a982008-03-15 08:11:03 +0000797 sg_print(p);
sewardjaf44c822007-11-25 14:01:38 +0000798 }
bart3772a982008-03-15 08:11:03 +0000799 }
800 }
sewardjaf44c822007-11-25 14:01:38 +0000801}
802
803static void show_call_stack(const DrdThreadId tid,
804 const Char* const msg,
805 ExeContext* const callstack)
806{
bart3772a982008-03-15 08:11:03 +0000807 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000808
bartaa97a542008-03-16 17:57:01 +0000809 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000810
bart3772a982008-03-15 08:11:03 +0000811 if (vg_tid != VG_INVALID_THREADID)
812 {
813 if (callstack)
814 {
815 VG_(pp_ExeContext)(callstack);
816 }
817 else
818 {
819 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
820 }
821 }
822 else
823 {
824 VG_(message)(Vg_UserMsg,
825 " (thread finished, call stack no longer available)");
826 }
sewardjaf44c822007-11-25 14:01:38 +0000827}
828
sewardjaf44c822007-11-25 14:01:38 +0000829static void
830thread_report_conflicting_segments_segment(const DrdThreadId tid,
831 const Addr addr,
832 const SizeT size,
833 const BmAccessTypeT access_type,
834 const Segment* const p)
835{
bart3772a982008-03-15 08:11:03 +0000836 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000837
bart3772a982008-03-15 08:11:03 +0000838 tl_assert(0 <= tid && tid < DRD_N_THREADS
839 && tid != DRD_INVALID_THREADID);
840 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000841
bart3772a982008-03-15 08:11:03 +0000842 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
843 {
844 if (i != tid)
845 {
846 Segment* q;
847 for (q = s_threadinfo[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000848 {
bart3772a982008-03-15 08:11:03 +0000849 // Since q iterates over the segments of thread i in order of
850 // decreasing vector clocks, if q->vc <= p->vc, then
851 // q->next->vc <= p->vc will also hold. Hence, break out of the
852 // loop once this condition is met.
853 if (vc_lte(&q->vc, &p->vc))
854 break;
855 if (! vc_lte(&p->vc, &q->vc))
856 {
857 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
858 {
859 tl_assert(q->stacktrace);
860 show_call_stack(i, "Other segment start",
861 q->stacktrace);
862 show_call_stack(i, "Other segment end",
863 q->next ? q->next->stacktrace : 0);
864 }
865 }
sewardjaf44c822007-11-25 14:01:38 +0000866 }
bart3772a982008-03-15 08:11:03 +0000867 }
868 }
sewardjaf44c822007-11-25 14:01:38 +0000869}
870
871void thread_report_conflicting_segments(const DrdThreadId tid,
872 const Addr addr,
873 const SizeT size,
874 const BmAccessTypeT access_type)
875{
bart3772a982008-03-15 08:11:03 +0000876 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000877
bart3772a982008-03-15 08:11:03 +0000878 tl_assert(0 <= tid && tid < DRD_N_THREADS
879 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000880
bart3772a982008-03-15 08:11:03 +0000881 for (p = s_threadinfo[tid].first; p; p = p->next)
882 {
883 if (bm_has(p->bm, addr, addr + size, access_type))
884 {
885 thread_report_conflicting_segments_segment(tid, addr, size,
886 access_type, p);
887 }
888 }
sewardjaf44c822007-11-25 14:01:38 +0000889}
sewardjaf44c822007-11-25 14:01:38 +0000890
bart26f73e12008-02-24 18:37:08 +0000891/** Compute a bitmap that represents the union of all memory accesses of all
892 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +0000893 */
894static void thread_update_danger_set(const DrdThreadId tid)
895{
bart3772a982008-03-15 08:11:03 +0000896 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000897
bart3772a982008-03-15 08:11:03 +0000898 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
899 tl_assert(tid == s_drd_running_tid);
sewardjaf44c822007-11-25 14:01:38 +0000900
bart3772a982008-03-15 08:11:03 +0000901 s_update_danger_set_count++;
902 s_danger_set_bitmap_creation_count -= bm_get_bitmap_creation_count();
903 s_danger_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000904
bart3772a982008-03-15 08:11:03 +0000905 if (s_danger_set)
906 {
bart1ea5fff2008-03-16 08:36:23 +0000907 bm_delete(s_danger_set);
bart3772a982008-03-15 08:11:03 +0000908 }
bart1ea5fff2008-03-16 08:36:23 +0000909 s_danger_set = bm_new();
bart26f73e12008-02-24 18:37:08 +0000910
bart3772a982008-03-15 08:11:03 +0000911 if (s_trace_danger_set)
912 {
913 char msg[256];
914
915 VG_(snprintf)(msg, sizeof(msg),
bartaa97a542008-03-16 17:57:01 +0000916 "computing danger set for thread %d/%d with vc ",
917 DrdThreadIdToVgThreadId(tid), tid);
bart3772a982008-03-15 08:11:03 +0000918 vc_snprint(msg + VG_(strlen)(msg),
919 sizeof(msg) - VG_(strlen)(msg),
920 &s_threadinfo[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +0000921 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000922 }
923
924 p = s_threadinfo[tid].last;
925 {
926 unsigned j;
927
928 if (s_trace_danger_set)
929 {
bart26f73e12008-02-24 18:37:08 +0000930 char msg[256];
931
932 VG_(snprintf)(msg, sizeof(msg),
bart3772a982008-03-15 08:11:03 +0000933 "danger set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +0000934 tid);
935 vc_snprint(msg + VG_(strlen)(msg),
936 sizeof(msg) - VG_(strlen)(msg),
bart3772a982008-03-15 08:11:03 +0000937 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +0000938 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000939 }
sewardjaf44c822007-11-25 14:01:38 +0000940
bart3772a982008-03-15 08:11:03 +0000941 for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++)
942 {
bartd66e3a82008-04-06 15:02:17 +0000943 if (j != tid && IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +0000944 {
bart3772a982008-03-15 08:11:03 +0000945 const Segment* q;
946 for (q = s_threadinfo[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000947 {
948 if (! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000949 {
950 if (s_trace_danger_set)
951 {
952 char msg[256];
953 VG_(snprintf)(msg, sizeof(msg),
954 "danger set: [%d] merging segment ", j);
955 vc_snprint(msg + VG_(strlen)(msg),
956 sizeof(msg) - VG_(strlen)(msg),
957 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000958 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000959 }
960 bm_merge2(s_danger_set, q->bm);
961 }
962 else
963 {
964 if (s_trace_danger_set)
965 {
966 char msg[256];
967 VG_(snprintf)(msg, sizeof(msg),
968 "danger set: [%d] ignoring segment ", j);
969 vc_snprint(msg + VG_(strlen)(msg),
970 sizeof(msg) - VG_(strlen)(msg),
971 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000972 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000973 }
974 }
bartd66e3a82008-04-06 15:02:17 +0000975 }
bart26f73e12008-02-24 18:37:08 +0000976 }
bart3772a982008-03-15 08:11:03 +0000977 }
bart3772a982008-03-15 08:11:03 +0000978 }
sewardjaf44c822007-11-25 14:01:38 +0000979
bart3772a982008-03-15 08:11:03 +0000980 s_danger_set_bitmap_creation_count += bm_get_bitmap_creation_count();
981 s_danger_set_bitmap2_creation_count += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000982
bart3772a982008-03-15 08:11:03 +0000983 if (0 && s_trace_danger_set)
984 {
barta2b6e1b2008-03-17 18:32:39 +0000985 VG_(message)(Vg_UserMsg, "[%d] new danger set:", tid);
bart3772a982008-03-15 08:11:03 +0000986 bm_print(s_danger_set);
barta2b6e1b2008-03-17 18:32:39 +0000987 VG_(message)(Vg_UserMsg, "[%d] end of new danger set.", tid);
bart3772a982008-03-15 08:11:03 +0000988 }
sewardjaf44c822007-11-25 14:01:38 +0000989}
990
sewardjaf44c822007-11-25 14:01:38 +0000991ULong thread_get_context_switch_count(void)
992{
bart3772a982008-03-15 08:11:03 +0000993 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +0000994}
995
sewardjaf44c822007-11-25 14:01:38 +0000996ULong thread_get_discard_ordered_segments_count(void)
997{
bart3772a982008-03-15 08:11:03 +0000998 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +0000999}
1000
bartd66e3a82008-04-06 15:02:17 +00001001ULong thread_get_update_danger_set_count(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001002{
bartd66e3a82008-04-06 15:02:17 +00001003 tl_assert(dsnsc);
1004 tl_assert(dscvc);
1005 *dsnsc = s_danger_set_new_segment_count;
1006 *dscvc = s_danger_set_combine_vc_count;
bart3772a982008-03-15 08:11:03 +00001007 return s_update_danger_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001008}
1009
1010ULong thread_get_danger_set_bitmap_creation_count(void)
1011{
bart3772a982008-03-15 08:11:03 +00001012 return s_danger_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001013}
1014
1015ULong thread_get_danger_set_bitmap2_creation_count(void)
1016{
bart3772a982008-03-15 08:11:03 +00001017 return s_danger_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001018}