blob: fc4e363e110ee2a3c558dfda50ba50ae701fdc6f [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;
54static ULong s_danger_set_bitmap_creation_count;
55static ULong s_danger_set_bitmap2_creation_count;
sewardj8b09d4f2007-12-04 21:27:18 +000056static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bartf00a85b2008-03-13 18:49:23 +000057DrdThreadId s_drd_running_tid = DRD_INVALID_THREADID;
58ThreadInfo s_threadinfo[DRD_N_THREADS];
bart1a473c72008-03-13 19:03:38 +000059struct bitmap* s_danger_set;
bart26f73e12008-02-24 18:37:08 +000060static Bool s_trace_context_switches = False;
61static Bool s_trace_danger_set = False;
barta9c37392008-03-22 09:38:48 +000062static Bool s_segment_merging = True;
sewardjaf44c822007-11-25 14:01:38 +000063
64
65// Function definitions.
66
bart26f73e12008-02-24 18:37:08 +000067void thread_trace_context_switches(const Bool t)
68{
bart3772a982008-03-15 08:11:03 +000069 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000070}
71
72void thread_trace_danger_set(const Bool t)
73{
bart3772a982008-03-15 08:11:03 +000074 s_trace_danger_set = t;
bart26f73e12008-02-24 18:37:08 +000075}
76
barta9c37392008-03-22 09:38:48 +000077void thread_set_segment_merging(const Bool m)
78{
79 s_segment_merging = m;
80}
81
sewardjaf44c822007-11-25 14:01:38 +000082__inline__ Bool IsValidDrdThreadId(const DrdThreadId tid)
83{
bart3772a982008-03-15 08:11:03 +000084 return (0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID
85 && ! (s_threadinfo[tid].vg_thread_exists == False
86 && s_threadinfo[tid].posix_thread_exists == False
87 && s_threadinfo[tid].detached_posix_thread == False));
sewardjaf44c822007-11-25 14:01:38 +000088}
89
90/**
91 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
92 * Valgrind's ThreadId does not yet exist.
93 **/
94DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid)
95{
bart3772a982008-03-15 08:11:03 +000096 int i;
sewardjaf44c822007-11-25 14:01:38 +000097
bart3772a982008-03-15 08:11:03 +000098 if (tid == VG_INVALID_THREADID)
99 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000100
bart3772a982008-03-15 08:11:03 +0000101 for (i = 1; i < DRD_N_THREADS; i++)
102 {
103 if (s_threadinfo[i].vg_thread_exists == True
104 && s_threadinfo[i].vg_threadid == tid)
105 {
106 return i;
107 }
108 }
sewardjaf44c822007-11-25 14:01:38 +0000109
bart3772a982008-03-15 08:11:03 +0000110 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000111}
112
113static
114DrdThreadId VgThreadIdToNewDrdThreadId(const ThreadId tid)
115{
bart3772a982008-03-15 08:11:03 +0000116 int i;
sewardjaf44c822007-11-25 14:01:38 +0000117
bart3772a982008-03-15 08:11:03 +0000118 tl_assert(VgThreadIdToDrdThreadId(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000119
bart3772a982008-03-15 08:11:03 +0000120 for (i = 1; i < DRD_N_THREADS; i++)
121 {
122 if (s_threadinfo[i].vg_thread_exists == False
123 && s_threadinfo[i].posix_thread_exists == False
124 && s_threadinfo[i].detached_posix_thread == False)
125 {
126 s_threadinfo[i].vg_thread_exists = True;
127 s_threadinfo[i].vg_threadid = tid;
128 s_threadinfo[i].pt_threadid = INVALID_POSIX_THREADID;
bart3772a982008-03-15 08:11:03 +0000129 s_threadinfo[i].stack_min = 0;
bartcac53462008-03-29 09:27:08 +0000130 s_threadinfo[i].stack_min_min = 0;
bart3772a982008-03-15 08:11:03 +0000131 s_threadinfo[i].stack_startup = 0;
132 s_threadinfo[i].stack_max = 0;
bart3772a982008-03-15 08:11:03 +0000133 s_threadinfo[i].is_recording = True;
134 s_threadinfo[i].synchr_nesting = 0;
135 if (s_threadinfo[i].first != 0)
136 VG_(printf)("drd thread id = %d\n", i);
137 tl_assert(s_threadinfo[i].first == 0);
138 tl_assert(s_threadinfo[i].last == 0);
139 return i;
140 }
141 }
sewardjaf44c822007-11-25 14:01:38 +0000142
bart3772a982008-03-15 08:11:03 +0000143 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000144
bart3772a982008-03-15 08:11:03 +0000145 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000146}
147
148DrdThreadId PtThreadIdToDrdThreadId(const PThreadId tid)
149{
bart3772a982008-03-15 08:11:03 +0000150 int i;
sewardjaf44c822007-11-25 14:01:38 +0000151
bart3772a982008-03-15 08:11:03 +0000152 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000153
bart3772a982008-03-15 08:11:03 +0000154 for (i = 1; i < DRD_N_THREADS; i++)
155 {
156 if (s_threadinfo[i].posix_thread_exists
157 && s_threadinfo[i].pt_threadid == tid)
158 {
159 return i;
160 }
161 }
162 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000163}
164
165ThreadId DrdThreadIdToVgThreadId(const DrdThreadId tid)
166{
bart3772a982008-03-15 08:11:03 +0000167 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
168 return (s_threadinfo[tid].vg_thread_exists
169 ? s_threadinfo[tid].vg_threadid
170 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000171}
172
bart23d3a4e2008-04-05 12:53:00 +0000173#if 0
bart26f73e12008-02-24 18:37:08 +0000174/** Sanity check of the doubly linked list of segments referenced by a
175 * ThreadInfo struct.
176 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000177 */
178static Bool sane_ThreadInfo(const ThreadInfo* const ti)
179{
bart3772a982008-03-15 08:11:03 +0000180 Segment* p;
181 for (p = ti->first; p; p = p->next) {
182 if (p->next && p->next->prev != p)
183 return False;
184 if (p->next == 0 && p != ti->last)
185 return False;
186 }
187 for (p = ti->last; p; p = p->prev) {
188 if (p->prev && p->prev->next != p)
189 return False;
190 if (p->prev == 0 && p != ti->first)
191 return False;
192 }
193 return True;
sewardjaf44c822007-11-25 14:01:38 +0000194}
bart23d3a4e2008-04-05 12:53:00 +0000195#endif
sewardjaf44c822007-11-25 14:01:38 +0000196
197DrdThreadId thread_pre_create(const DrdThreadId creator,
198 const ThreadId vg_created)
199{
bart3772a982008-03-15 08:11:03 +0000200 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000201
bart3772a982008-03-15 08:11:03 +0000202 tl_assert(VgThreadIdToDrdThreadId(vg_created) == DRD_INVALID_THREADID);
203 created = VgThreadIdToNewDrdThreadId(vg_created);
204 tl_assert(0 <= created && created < DRD_N_THREADS
205 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000206
bart3772a982008-03-15 08:11:03 +0000207 tl_assert(s_threadinfo[created].first == 0);
208 tl_assert(s_threadinfo[created].last == 0);
209 thread_append_segment(created, sg_new(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000210
bart3772a982008-03-15 08:11:03 +0000211 return created;
sewardjaf44c822007-11-25 14:01:38 +0000212}
213
bart26f73e12008-02-24 18:37:08 +0000214/** Allocate the first segment for a thread. Call this just after
215 * pthread_create().
sewardjaf44c822007-11-25 14:01:38 +0000216 */
217DrdThreadId thread_post_create(const ThreadId vg_created)
218{
bart3772a982008-03-15 08:11:03 +0000219 const DrdThreadId created = VgThreadIdToDrdThreadId(vg_created);
sewardjaf44c822007-11-25 14:01:38 +0000220
bart3772a982008-03-15 08:11:03 +0000221 tl_assert(0 <= created && created < DRD_N_THREADS
222 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000223
bart3772a982008-03-15 08:11:03 +0000224 s_threadinfo[created].stack_max = VG_(thread_get_stack_max)(vg_created);
225 s_threadinfo[created].stack_startup = s_threadinfo[created].stack_max;
226 s_threadinfo[created].stack_min = s_threadinfo[created].stack_max;
bartcac53462008-03-29 09:27:08 +0000227 s_threadinfo[created].stack_min_min = s_threadinfo[created].stack_max;
228 s_threadinfo[created].stack_size = VG_(thread_get_stack_size)(vg_created);
bart3772a982008-03-15 08:11:03 +0000229 tl_assert(s_threadinfo[created].stack_max != 0);
sewardjaf44c822007-11-25 14:01:38 +0000230
bart3772a982008-03-15 08:11:03 +0000231 return created;
sewardjaf44c822007-11-25 14:01:38 +0000232}
233
234/* NPTL hack: NPTL allocates the 'struct pthread' on top of the stack, */
235/* and accesses this data structure from multiple threads without locking. */
236/* Any conflicting accesses in the range stack_startup..stack_max will be */
237/* ignored. */
238void thread_set_stack_startup(const DrdThreadId tid, const Addr stack_startup)
239{
bart3772a982008-03-15 08:11:03 +0000240 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
241 tl_assert(s_threadinfo[tid].stack_min <= stack_startup);
242 tl_assert(stack_startup <= s_threadinfo[tid].stack_max);
243 s_threadinfo[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000244}
245
246Addr thread_get_stack_min(const DrdThreadId tid)
247{
bart3772a982008-03-15 08:11:03 +0000248 tl_assert(0 <= tid && tid < DRD_N_THREADS
249 && tid != DRD_INVALID_THREADID);
250 return s_threadinfo[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000251}
252
bartcac53462008-03-29 09:27:08 +0000253Addr thread_get_stack_min_min(const DrdThreadId tid)
254{
255 tl_assert(0 <= tid && tid < DRD_N_THREADS
256 && tid != DRD_INVALID_THREADID);
257 return s_threadinfo[tid].stack_min_min;
258}
259
bartd43f8d32008-03-16 17:29:20 +0000260Addr thread_get_stack_max(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000261{
bartd43f8d32008-03-16 17:29:20 +0000262 tl_assert(0 <= tid && tid < DRD_N_THREADS
263 && tid != DRD_INVALID_THREADID);
264 return s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000265}
266
bartcac53462008-03-29 09:27:08 +0000267SizeT thread_get_stack_size(const DrdThreadId tid)
268{
269 tl_assert(0 <= tid && tid < DRD_N_THREADS
270 && tid != DRD_INVALID_THREADID);
271 return s_threadinfo[tid].stack_size;
272}
273
barta2b6e1b2008-03-17 18:32:39 +0000274/** Clean up thread-specific data structures. Call this just after
275 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000276 */
277void thread_delete(const DrdThreadId tid)
278{
bart3772a982008-03-15 08:11:03 +0000279 Segment* sg;
280 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000281
bart3772a982008-03-15 08:11:03 +0000282 tl_assert(0 <= tid && tid < DRD_N_THREADS
283 && tid != DRD_INVALID_THREADID);
284 tl_assert(s_threadinfo[tid].synchr_nesting == 0);
285 for (sg = s_threadinfo[tid].last; sg; sg = sg_prev)
286 {
287 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000288 sg->prev = 0;
289 sg->next = 0;
290 sg_put(sg);
bart3772a982008-03-15 08:11:03 +0000291 }
292 s_threadinfo[tid].vg_thread_exists = False;
293 s_threadinfo[tid].posix_thread_exists = False;
294 tl_assert(s_threadinfo[tid].detached_posix_thread == False);
295 s_threadinfo[tid].first = 0;
296 s_threadinfo[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000297}
298
299/* Called after a thread performed its last memory access and before */
300/* thread_delete() is called. Note: thread_delete() is only called for */
301/* joinable threads, not for detached threads. */
302void thread_finished(const DrdThreadId tid)
303{
bart3772a982008-03-15 08:11:03 +0000304 tl_assert(0 <= tid && tid < DRD_N_THREADS
305 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000306
bart3772a982008-03-15 08:11:03 +0000307 s_threadinfo[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000308
bart3772a982008-03-15 08:11:03 +0000309 if (s_threadinfo[tid].detached_posix_thread)
310 {
311 /* Once a detached thread has finished, its stack is deallocated and */
312 /* should no longer be taken into account when computing the danger set*/
313 s_threadinfo[tid].stack_min = s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000314
bart3772a982008-03-15 08:11:03 +0000315 /* For a detached thread, calling pthread_exit() invalidates the */
316 /* POSIX thread ID associated with the detached thread. For joinable */
317 /* POSIX threads however, the POSIX thread ID remains live after the */
318 /* pthread_exit() call until pthread_join() is called. */
319 s_threadinfo[tid].posix_thread_exists = False;
320 }
sewardjaf44c822007-11-25 14:01:38 +0000321}
322
323void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
324{
bart3772a982008-03-15 08:11:03 +0000325 tl_assert(0 <= tid && tid < DRD_N_THREADS
326 && tid != DRD_INVALID_THREADID);
327 tl_assert(s_threadinfo[tid].pt_threadid == INVALID_POSIX_THREADID);
328 tl_assert(ptid != INVALID_POSIX_THREADID);
329 s_threadinfo[tid].posix_thread_exists = True;
330 s_threadinfo[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000331}
332
333Bool thread_get_joinable(const DrdThreadId tid)
334{
bart3772a982008-03-15 08:11:03 +0000335 tl_assert(0 <= tid && tid < DRD_N_THREADS
336 && tid != DRD_INVALID_THREADID);
337 return ! s_threadinfo[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000338}
339
340void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
341{
bart3772a982008-03-15 08:11:03 +0000342 tl_assert(0 <= tid && tid < DRD_N_THREADS
343 && tid != DRD_INVALID_THREADID);
344 tl_assert(!! joinable == joinable);
345 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000346#if 0
bart3772a982008-03-15 08:11:03 +0000347 VG_(message)(Vg_DebugMsg,
348 "thread_set_joinable(%d/%d, %s)",
349 tid,
350 s_threadinfo[tid].vg_threadid,
351 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000352#endif
bart3772a982008-03-15 08:11:03 +0000353 s_threadinfo[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000354}
355
sewardj8b09d4f2007-12-04 21:27:18 +0000356void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000357{
bart3772a982008-03-15 08:11:03 +0000358 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000359
bart3772a982008-03-15 08:11:03 +0000360 if (vg_tid != s_vg_running_tid)
361 {
362 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
363 }
sewardj8b09d4f2007-12-04 21:27:18 +0000364
bart3772a982008-03-15 08:11:03 +0000365 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
366 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000367}
368
369void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
370{
bart3772a982008-03-15 08:11:03 +0000371 tl_assert(vg_tid != VG_INVALID_THREADID);
372 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000373
bart3772a982008-03-15 08:11:03 +0000374 if (vg_tid != s_vg_running_tid)
375 {
376 if (s_trace_context_switches
377 && s_drd_running_tid != DRD_INVALID_THREADID)
378 {
379 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000380 "Context switch from thread %d/%d to thread %d/%d;"
381 " segments: %llu",
bartaa97a542008-03-16 17:57:01 +0000382 s_vg_running_tid, s_drd_running_tid,
barta2b6e1b2008-03-17 18:32:39 +0000383 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
384 sg_get_alive_segments_count());
bart3772a982008-03-15 08:11:03 +0000385 }
386 s_vg_running_tid = vg_tid;
387 s_drd_running_tid = drd_tid;
388 thread_update_danger_set(drd_tid);
389 s_context_switch_count++;
390 }
sewardj8b09d4f2007-12-04 21:27:18 +0000391
bart3772a982008-03-15 08:11:03 +0000392 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
393 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000394}
395
bart0268dfa2008-03-11 20:10:21 +0000396int thread_enter_synchr(const DrdThreadId tid)
397{
bart3772a982008-03-15 08:11:03 +0000398 tl_assert(IsValidDrdThreadId(tid));
399 return s_threadinfo[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000400}
401
402int thread_leave_synchr(const DrdThreadId tid)
403{
bart3772a982008-03-15 08:11:03 +0000404 tl_assert(IsValidDrdThreadId(tid));
405 tl_assert(s_threadinfo[tid].synchr_nesting >= 1);
406 return --s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000407}
408
409int thread_get_synchr_nesting_count(const DrdThreadId tid)
410{
bart3772a982008-03-15 08:11:03 +0000411 tl_assert(IsValidDrdThreadId(tid));
412 return s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000413}
414
bart1a473c72008-03-13 19:03:38 +0000415/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000416static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000417{
bart3772a982008-03-15 08:11:03 +0000418 tl_assert(0 <= tid && tid < DRD_N_THREADS
419 && tid != DRD_INVALID_THREADID);
bart23d3a4e2008-04-05 12:53:00 +0000420 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart3772a982008-03-15 08:11:03 +0000421 sg->prev = s_threadinfo[tid].last;
422 sg->next = 0;
423 if (s_threadinfo[tid].last)
424 s_threadinfo[tid].last->next = sg;
425 s_threadinfo[tid].last = sg;
426 if (s_threadinfo[tid].first == 0)
427 s_threadinfo[tid].first = sg;
bart23d3a4e2008-04-05 12:53:00 +0000428 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000429}
430
bart26f73e12008-02-24 18:37:08 +0000431/** Remove a segment from the segment list of thread threadid, and free the
432 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000433 */
bart26f73e12008-02-24 18:37:08 +0000434static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000435{
bart3772a982008-03-15 08:11:03 +0000436 tl_assert(0 <= tid && tid < DRD_N_THREADS
437 && tid != DRD_INVALID_THREADID);
bart3f749672008-03-22 09:49:40 +0000438 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart26f73e12008-02-24 18:37:08 +0000439
bart3772a982008-03-15 08:11:03 +0000440 if (sg->prev)
441 sg->prev->next = sg->next;
442 if (sg->next)
443 sg->next->prev = sg->prev;
444 if (sg == s_threadinfo[tid].first)
445 s_threadinfo[tid].first = sg->next;
446 if (sg == s_threadinfo[tid].last)
447 s_threadinfo[tid].last = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000448 sg_put(sg);
bart3f749672008-03-22 09:49:40 +0000449
450 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000451}
452
453VectorClock* thread_get_vc(const DrdThreadId tid)
454{
barta2b6e1b2008-03-17 18:32:39 +0000455 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000456 tl_assert(s_threadinfo[tid].last);
457 return &s_threadinfo[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000458}
459
barta2b6e1b2008-03-17 18:32:39 +0000460/** Return the latest segment of thread 'tid' and increment its reference
461 * count.
462 */
463void thread_get_latest_segment(Segment** sg, const DrdThreadId tid)
464{
465 tl_assert(sg);
466 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
467 tl_assert(s_threadinfo[tid].last);
468
469 sg_put(*sg);
470 *sg = sg_get(s_threadinfo[tid].last);
471}
472
sewardjaf44c822007-11-25 14:01:38 +0000473/**
474 * Compute the minimum of all latest vector clocks of all threads
475 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
476 * @param vc pointer to a vectorclock, holds result upon return.
477 */
478static void thread_compute_minimum_vc(VectorClock* vc)
479{
bart3772a982008-03-15 08:11:03 +0000480 unsigned i;
481 Bool first;
482 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000483
bart3772a982008-03-15 08:11:03 +0000484 first = True;
485 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
486 {
487 latest_sg = s_threadinfo[i].last;
488 if (latest_sg)
489 {
490 if (first)
491 vc_assign(vc, &latest_sg->vc);
492 else
493 vc_min(vc, &latest_sg->vc);
494 first = False;
495 }
496 }
sewardjaf44c822007-11-25 14:01:38 +0000497}
498
499static void thread_compute_maximum_vc(VectorClock* vc)
500{
bart3772a982008-03-15 08:11:03 +0000501 unsigned i;
502 Bool first;
503 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000504
bart3772a982008-03-15 08:11:03 +0000505 first = True;
506 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
507 {
508 latest_sg = s_threadinfo[i].last;
509 if (latest_sg)
510 {
511 if (first)
512 vc_assign(vc, &latest_sg->vc);
513 else
514 vc_combine(vc, &latest_sg->vc);
515 first = False;
516 }
517 }
sewardjaf44c822007-11-25 14:01:38 +0000518}
519
520/**
bart5bd9f2d2008-03-03 20:31:58 +0000521 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000522 * clock of every thread -- these segments can no longer be involved in a
523 * data race.
524 */
525static void thread_discard_ordered_segments(void)
526{
bart3772a982008-03-15 08:11:03 +0000527 unsigned i;
528 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000529
bart3772a982008-03-15 08:11:03 +0000530 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000531
bart3772a982008-03-15 08:11:03 +0000532 vc_init(&thread_vc_min, 0, 0);
533 thread_compute_minimum_vc(&thread_vc_min);
534 if (sg_get_trace())
535 {
536 char msg[256];
537 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000538
bart3772a982008-03-15 08:11:03 +0000539 vc_init(&thread_vc_max, 0, 0);
540 thread_compute_maximum_vc(&thread_vc_max);
541 VG_(snprintf)(msg, sizeof(msg),
542 "Discarding ordered segments -- min vc is ");
543 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
544 &thread_vc_min);
545 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
546 ", max vc is ");
547 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
548 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000549 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000550 vc_cleanup(&thread_vc_max);
551 }
sewardjaf44c822007-11-25 14:01:38 +0000552
bart3772a982008-03-15 08:11:03 +0000553 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
554 {
555 Segment* sg;
556 Segment* sg_next;
557 for (sg = s_threadinfo[i].first;
558 sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
559 sg = sg_next)
560 {
561 thread_discard_segment(i, sg);
562 }
563 }
564 vc_cleanup(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000565}
566
barta9c37392008-03-22 09:38:48 +0000567/** Merge all segments that may be merged without triggering false positives
568 * or discarding real data races. For the theoretical background of segment
569 * merging, see also the following paper:
570 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
571 * Bounding the number of segment histories during data race detection.
572 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
573 * September 2002.
574 */
575static void thread_merge_segments(void)
576{
577 unsigned i;
578
579 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
580 {
581 Segment* sg;
582
bart23d3a4e2008-04-05 12:53:00 +0000583 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000584
585 for (sg = s_threadinfo[i].first; sg; sg = sg->next)
586 {
587 if (sg_get_refcnt(sg) == 1
588 && sg->next
589 && sg_get_refcnt(sg->next) == 1
590 && sg->next->next)
591 {
592 /* Merge sg and sg->next into sg. */
593 sg_merge(sg, sg->next);
594 thread_discard_segment(i, sg->next);
595 }
596 }
597
bart23d3a4e2008-04-05 12:53:00 +0000598 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000599 }
600}
601
barta2b6e1b2008-03-17 18:32:39 +0000602/** Create a new segment for the specified thread, and discard any segments
603 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000604 */
605void thread_new_segment(const DrdThreadId tid)
606{
barta2b6e1b2008-03-17 18:32:39 +0000607 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000608
barta2b6e1b2008-03-17 18:32:39 +0000609 thread_append_segment(tid, sg_new(tid, tid));
sewardjaf44c822007-11-25 14:01:38 +0000610
bart3772a982008-03-15 08:11:03 +0000611 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000612
barta9c37392008-03-22 09:38:48 +0000613 if (s_segment_merging)
614 thread_merge_segments();
615
bart3772a982008-03-15 08:11:03 +0000616 if (tid == s_drd_running_tid)
617 {
618 /* Every change in the vector clock of the current thread may cause */
619 /* segments that were previously ordered to this thread to become */
620 /* unordered. Hence, recalculate the danger set if the vector clock */
621 /* of the current thread is updated. */
622 thread_update_danger_set(tid);
623 }
sewardjaf44c822007-11-25 14:01:38 +0000624}
625
bart26f73e12008-02-24 18:37:08 +0000626/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000627void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
628{
bart3772a982008-03-15 08:11:03 +0000629 tl_assert(joiner != joinee);
630 tl_assert(0 <= joiner && joiner < DRD_N_THREADS
631 && joiner != DRD_INVALID_THREADID);
632 tl_assert(0 <= joinee && joinee < DRD_N_THREADS
633 && joinee != DRD_INVALID_THREADID);
634 tl_assert(s_threadinfo[joiner].last);
635 tl_assert(s_threadinfo[joinee].last);
636 vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
637 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000638
bart3772a982008-03-15 08:11:03 +0000639 if (joiner == s_drd_running_tid)
640 {
641 thread_update_danger_set(joiner);
642 }
sewardjaf44c822007-11-25 14:01:38 +0000643}
644
bart26f73e12008-02-24 18:37:08 +0000645/** Call this function after thread 'tid' had to wait because of thread
646 * synchronization until the memory accesses in the segment with vector clock
647 * 'vc' finished.
648 */
sewardjaf44c822007-11-25 14:01:38 +0000649void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
650{
bart3772a982008-03-15 08:11:03 +0000651 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
652 tl_assert(s_threadinfo[tid].last);
653 tl_assert(vc);
654 vc_combine(&s_threadinfo[tid].last->vc, vc);
655 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000656}
657
bart26f73e12008-02-24 18:37:08 +0000658/** Call this function whenever a thread is no longer using the memory
659 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
660 * increase.
661 */
sewardjaf44c822007-11-25 14:01:38 +0000662void thread_stop_using_mem(const Addr a1, const Addr a2)
663{
bartd43f8d32008-03-16 17:29:20 +0000664 DrdThreadId other_user;
665 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000666
bart3772a982008-03-15 08:11:03 +0000667 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000668 other_user = DRD_INVALID_THREADID;
bart3772a982008-03-15 08:11:03 +0000669 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
670 {
671 Segment* p;
672 for (p = s_threadinfo[i].first; p; p = p->next)
673 {
674 if (other_user == DRD_INVALID_THREADID
bart8bf2f8b2008-03-30 17:56:43 +0000675 && i != s_drd_running_tid)
sewardjaf44c822007-11-25 14:01:38 +0000676 {
bart8bf2f8b2008-03-30 17:56:43 +0000677 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
678 {
679 other_user = i;
680 }
681 continue;
sewardjaf44c822007-11-25 14:01:38 +0000682 }
bart3772a982008-03-15 08:11:03 +0000683 bm_clear(p->bm, a1, a2);
684 }
685 }
sewardjaf44c822007-11-25 14:01:38 +0000686
bart3772a982008-03-15 08:11:03 +0000687 /* If any other thread had accessed memory in [ a1, a2 [, update the */
688 /* danger set. */
689 if (other_user != DRD_INVALID_THREADID
690 && bm_has_any_access(s_danger_set, a1, a2))
691 {
692 thread_update_danger_set(thread_get_running_tid());
693 }
sewardjaf44c822007-11-25 14:01:38 +0000694}
695
bart0268dfa2008-03-11 20:10:21 +0000696void thread_start_recording(const DrdThreadId tid)
697{
bart3772a982008-03-15 08:11:03 +0000698 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
699 tl_assert(! s_threadinfo[tid].is_recording);
700 s_threadinfo[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000701}
702
703void thread_stop_recording(const DrdThreadId tid)
704{
bart3772a982008-03-15 08:11:03 +0000705 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
706 tl_assert(s_threadinfo[tid].is_recording);
707 s_threadinfo[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000708}
709
sewardjaf44c822007-11-25 14:01:38 +0000710void thread_print_all(void)
711{
bart3772a982008-03-15 08:11:03 +0000712 unsigned i;
713 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000714
bart3772a982008-03-15 08:11:03 +0000715 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
716 {
717 if (s_threadinfo[i].first)
718 {
719 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000720 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000721 "**************\n",
722 i,
723 s_threadinfo[i].vg_thread_exists,
724 s_threadinfo[i].vg_threadid,
725 s_threadinfo[i].posix_thread_exists,
726 s_threadinfo[i].pt_threadid,
bart354009c2008-03-16 10:42:33 +0000727 s_threadinfo[i].detached_posix_thread);
bart3772a982008-03-15 08:11:03 +0000728 for (p = s_threadinfo[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000729 {
bart3772a982008-03-15 08:11:03 +0000730 sg_print(p);
sewardjaf44c822007-11-25 14:01:38 +0000731 }
bart3772a982008-03-15 08:11:03 +0000732 }
733 }
sewardjaf44c822007-11-25 14:01:38 +0000734}
735
736static void show_call_stack(const DrdThreadId tid,
737 const Char* const msg,
738 ExeContext* const callstack)
739{
bart3772a982008-03-15 08:11:03 +0000740 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000741
bartaa97a542008-03-16 17:57:01 +0000742 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000743
bart3772a982008-03-15 08:11:03 +0000744 if (vg_tid != VG_INVALID_THREADID)
745 {
746 if (callstack)
747 {
748 VG_(pp_ExeContext)(callstack);
749 }
750 else
751 {
752 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
753 }
754 }
755 else
756 {
757 VG_(message)(Vg_UserMsg,
758 " (thread finished, call stack no longer available)");
759 }
sewardjaf44c822007-11-25 14:01:38 +0000760}
761
sewardjaf44c822007-11-25 14:01:38 +0000762static void
763thread_report_conflicting_segments_segment(const DrdThreadId tid,
764 const Addr addr,
765 const SizeT size,
766 const BmAccessTypeT access_type,
767 const Segment* const p)
768{
bart3772a982008-03-15 08:11:03 +0000769 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000770
bart3772a982008-03-15 08:11:03 +0000771 tl_assert(0 <= tid && tid < DRD_N_THREADS
772 && tid != DRD_INVALID_THREADID);
773 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000774
bart3772a982008-03-15 08:11:03 +0000775 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
776 {
777 if (i != tid)
778 {
779 Segment* q;
780 for (q = s_threadinfo[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000781 {
bart3772a982008-03-15 08:11:03 +0000782 // Since q iterates over the segments of thread i in order of
783 // decreasing vector clocks, if q->vc <= p->vc, then
784 // q->next->vc <= p->vc will also hold. Hence, break out of the
785 // loop once this condition is met.
786 if (vc_lte(&q->vc, &p->vc))
787 break;
788 if (! vc_lte(&p->vc, &q->vc))
789 {
790 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
791 {
792 tl_assert(q->stacktrace);
793 show_call_stack(i, "Other segment start",
794 q->stacktrace);
795 show_call_stack(i, "Other segment end",
796 q->next ? q->next->stacktrace : 0);
797 }
798 }
sewardjaf44c822007-11-25 14:01:38 +0000799 }
bart3772a982008-03-15 08:11:03 +0000800 }
801 }
sewardjaf44c822007-11-25 14:01:38 +0000802}
803
804void thread_report_conflicting_segments(const DrdThreadId tid,
805 const Addr addr,
806 const SizeT size,
807 const BmAccessTypeT access_type)
808{
bart3772a982008-03-15 08:11:03 +0000809 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000810
bart3772a982008-03-15 08:11:03 +0000811 tl_assert(0 <= tid && tid < DRD_N_THREADS
812 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000813
bart3772a982008-03-15 08:11:03 +0000814 for (p = s_threadinfo[tid].first; p; p = p->next)
815 {
816 if (bm_has(p->bm, addr, addr + size, access_type))
817 {
818 thread_report_conflicting_segments_segment(tid, addr, size,
819 access_type, p);
820 }
821 }
sewardjaf44c822007-11-25 14:01:38 +0000822}
sewardjaf44c822007-11-25 14:01:38 +0000823
bart26f73e12008-02-24 18:37:08 +0000824/** Compute a bitmap that represents the union of all memory accesses of all
825 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +0000826 */
827static void thread_update_danger_set(const DrdThreadId tid)
828{
bart3772a982008-03-15 08:11:03 +0000829 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000830
bart3772a982008-03-15 08:11:03 +0000831 tl_assert(0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID);
832 tl_assert(tid == s_drd_running_tid);
sewardjaf44c822007-11-25 14:01:38 +0000833
bart3772a982008-03-15 08:11:03 +0000834 s_update_danger_set_count++;
835 s_danger_set_bitmap_creation_count -= bm_get_bitmap_creation_count();
836 s_danger_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000837
bart3772a982008-03-15 08:11:03 +0000838 if (s_danger_set)
839 {
bart1ea5fff2008-03-16 08:36:23 +0000840 bm_delete(s_danger_set);
bart3772a982008-03-15 08:11:03 +0000841 }
bart1ea5fff2008-03-16 08:36:23 +0000842 s_danger_set = bm_new();
bart26f73e12008-02-24 18:37:08 +0000843
bart3772a982008-03-15 08:11:03 +0000844 if (s_trace_danger_set)
845 {
846 char msg[256];
847
848 VG_(snprintf)(msg, sizeof(msg),
bartaa97a542008-03-16 17:57:01 +0000849 "computing danger set for thread %d/%d with vc ",
850 DrdThreadIdToVgThreadId(tid), tid);
bart3772a982008-03-15 08:11:03 +0000851 vc_snprint(msg + VG_(strlen)(msg),
852 sizeof(msg) - VG_(strlen)(msg),
853 &s_threadinfo[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +0000854 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000855 }
856
857 p = s_threadinfo[tid].last;
858 {
859 unsigned j;
860
861 if (s_trace_danger_set)
862 {
bart26f73e12008-02-24 18:37:08 +0000863 char msg[256];
864
865 VG_(snprintf)(msg, sizeof(msg),
bart3772a982008-03-15 08:11:03 +0000866 "danger set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +0000867 tid);
868 vc_snprint(msg + VG_(strlen)(msg),
869 sizeof(msg) - VG_(strlen)(msg),
bart3772a982008-03-15 08:11:03 +0000870 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +0000871 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000872 }
sewardjaf44c822007-11-25 14:01:38 +0000873
bart3772a982008-03-15 08:11:03 +0000874 for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++)
875 {
876 if (IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +0000877 {
bart3772a982008-03-15 08:11:03 +0000878 const Segment* q;
879 for (q = s_threadinfo[j].last; q; q = q->prev)
880 if (j != tid && q != 0
881 && ! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc))
882 {
883 if (s_trace_danger_set)
884 {
885 char msg[256];
886 VG_(snprintf)(msg, sizeof(msg),
887 "danger set: [%d] merging segment ", j);
888 vc_snprint(msg + VG_(strlen)(msg),
889 sizeof(msg) - VG_(strlen)(msg),
890 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000891 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000892 }
893 bm_merge2(s_danger_set, q->bm);
894 }
895 else
896 {
897 if (s_trace_danger_set)
898 {
899 char msg[256];
900 VG_(snprintf)(msg, sizeof(msg),
901 "danger set: [%d] ignoring segment ", j);
902 vc_snprint(msg + VG_(strlen)(msg),
903 sizeof(msg) - VG_(strlen)(msg),
904 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000905 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000906 }
907 }
bart26f73e12008-02-24 18:37:08 +0000908 }
bart3772a982008-03-15 08:11:03 +0000909 }
bart3772a982008-03-15 08:11:03 +0000910 }
sewardjaf44c822007-11-25 14:01:38 +0000911
bart3772a982008-03-15 08:11:03 +0000912 s_danger_set_bitmap_creation_count += bm_get_bitmap_creation_count();
913 s_danger_set_bitmap2_creation_count += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000914
bart3772a982008-03-15 08:11:03 +0000915 if (0 && s_trace_danger_set)
916 {
barta2b6e1b2008-03-17 18:32:39 +0000917 VG_(message)(Vg_UserMsg, "[%d] new danger set:", tid);
bart3772a982008-03-15 08:11:03 +0000918 bm_print(s_danger_set);
barta2b6e1b2008-03-17 18:32:39 +0000919 VG_(message)(Vg_UserMsg, "[%d] end of new danger set.", tid);
bart3772a982008-03-15 08:11:03 +0000920 }
sewardjaf44c822007-11-25 14:01:38 +0000921}
922
sewardjaf44c822007-11-25 14:01:38 +0000923ULong thread_get_context_switch_count(void)
924{
bart3772a982008-03-15 08:11:03 +0000925 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +0000926}
927
sewardjaf44c822007-11-25 14:01:38 +0000928ULong thread_get_discard_ordered_segments_count(void)
929{
bart3772a982008-03-15 08:11:03 +0000930 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +0000931}
932
933ULong thread_get_update_danger_set_count(void)
934{
bart3772a982008-03-15 08:11:03 +0000935 return s_update_danger_set_count;
sewardjaf44c822007-11-25 14:01:38 +0000936}
937
938ULong thread_get_danger_set_bitmap_creation_count(void)
939{
bart3772a982008-03-15 08:11:03 +0000940 return s_danger_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000941}
942
943ULong thread_get_danger_set_bitmap2_creation_count(void)
944{
bart3772a982008-03-15 08:11:03 +0000945 return s_danger_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000946}