blob: b1d443c58922c3f4741afefbda30db9109199b2a [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
26#include "drd_error.h"
27#include "drd_segment.h"
28#include "drd_suppression.h"
29#include "drd_thread.h"
bart82195c12008-04-13 17:35:08 +000030#include "pub_tool_vki.h"
sewardjaf44c822007-11-25 14:01:38 +000031#include "pub_tool_basics.h" // Addr, SizeT
32#include "pub_tool_errormgr.h" // VG_(unique_error)()
33#include "pub_tool_libcassert.h" // tl_assert()
34#include "pub_tool_libcbase.h" // VG_(strlen)()
35#include "pub_tool_libcprint.h" // VG_(printf)()
bart82195c12008-04-13 17:35:08 +000036#include "pub_tool_libcproc.h" // VG_(getenv)()
sewardjaf44c822007-11-25 14:01:38 +000037#include "pub_tool_machine.h"
38#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
sewardj85642922008-01-14 11:54:56 +000039#include "pub_tool_options.h" // VG_(clo_backtrace_size)
sewardjaf44c822007-11-25 14:01:38 +000040#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
41
bart32ba2082008-06-05 08:53:42 +000042
sewardjaf44c822007-11-25 14:01:38 +000043
sewardjaf44c822007-11-25 14:01:38 +000044// Local functions.
45
46static void thread_append_segment(const DrdThreadId tid,
47 Segment* const sg);
barta2b6e1b2008-03-17 18:32:39 +000048static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
barte73b0aa2008-06-28 07:19:56 +000049static Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
50static void thread_compute_conflict_set(struct bitmap** conflict_set,
51 const DrdThreadId tid);
sewardjaf44c822007-11-25 14:01:38 +000052
53
54// Local variables.
55
56static ULong s_context_switch_count;
57static ULong s_discard_ordered_segments_count;
barte73b0aa2008-06-28 07:19:56 +000058static ULong s_update_conflict_set_count;
59static ULong s_conflict_set_new_segment_count;
60static ULong s_conflict_set_combine_vc_count;
61static ULong s_conflict_set_bitmap_creation_count;
62static ULong s_conflict_set_bitmap2_creation_count;
sewardj8b09d4f2007-12-04 21:27:18 +000063static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
bartf00a85b2008-03-13 18:49:23 +000064DrdThreadId s_drd_running_tid = DRD_INVALID_THREADID;
65ThreadInfo s_threadinfo[DRD_N_THREADS];
barte73b0aa2008-06-28 07:19:56 +000066struct bitmap* s_conflict_set;
bart26f73e12008-02-24 18:37:08 +000067static Bool s_trace_context_switches = False;
barte73b0aa2008-06-28 07:19:56 +000068static Bool s_trace_conflict_set = False;
barta9c37392008-03-22 09:38:48 +000069static Bool s_segment_merging = True;
sewardjaf44c822007-11-25 14:01:38 +000070
71
72// Function definitions.
73
bart26f73e12008-02-24 18:37:08 +000074void thread_trace_context_switches(const Bool t)
75{
bart3772a982008-03-15 08:11:03 +000076 s_trace_context_switches = t;
bart26f73e12008-02-24 18:37:08 +000077}
78
barte73b0aa2008-06-28 07:19:56 +000079void thread_trace_conflict_set(const Bool t)
bart26f73e12008-02-24 18:37:08 +000080{
barte73b0aa2008-06-28 07:19:56 +000081 s_trace_conflict_set = t;
bart26f73e12008-02-24 18:37:08 +000082}
83
barta9c37392008-03-22 09:38:48 +000084void thread_set_segment_merging(const Bool m)
85{
86 s_segment_merging = m;
87}
88
sewardjaf44c822007-11-25 14:01:38 +000089/**
90 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
91 * Valgrind's ThreadId does not yet exist.
92 **/
93DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid)
94{
bart3772a982008-03-15 08:11:03 +000095 int i;
sewardjaf44c822007-11-25 14:01:38 +000096
bart3772a982008-03-15 08:11:03 +000097 if (tid == VG_INVALID_THREADID)
98 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +000099
bart3772a982008-03-15 08:11:03 +0000100 for (i = 1; i < DRD_N_THREADS; i++)
101 {
102 if (s_threadinfo[i].vg_thread_exists == True
103 && s_threadinfo[i].vg_threadid == tid)
104 {
105 return i;
106 }
107 }
sewardjaf44c822007-11-25 14:01:38 +0000108
bart3772a982008-03-15 08:11:03 +0000109 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000110}
111
112static
113DrdThreadId VgThreadIdToNewDrdThreadId(const ThreadId tid)
114{
bart3772a982008-03-15 08:11:03 +0000115 int i;
sewardjaf44c822007-11-25 14:01:38 +0000116
bart3772a982008-03-15 08:11:03 +0000117 tl_assert(VgThreadIdToDrdThreadId(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000118
bart3772a982008-03-15 08:11:03 +0000119 for (i = 1; i < DRD_N_THREADS; i++)
120 {
121 if (s_threadinfo[i].vg_thread_exists == False
122 && s_threadinfo[i].posix_thread_exists == False
123 && s_threadinfo[i].detached_posix_thread == False)
124 {
125 s_threadinfo[i].vg_thread_exists = True;
126 s_threadinfo[i].vg_threadid = tid;
127 s_threadinfo[i].pt_threadid = INVALID_POSIX_THREADID;
bart3772a982008-03-15 08:11:03 +0000128 s_threadinfo[i].stack_min = 0;
bartcac53462008-03-29 09:27:08 +0000129 s_threadinfo[i].stack_min_min = 0;
bart3772a982008-03-15 08:11:03 +0000130 s_threadinfo[i].stack_startup = 0;
131 s_threadinfo[i].stack_max = 0;
bart3772a982008-03-15 08:11:03 +0000132 s_threadinfo[i].is_recording = True;
133 s_threadinfo[i].synchr_nesting = 0;
134 if (s_threadinfo[i].first != 0)
135 VG_(printf)("drd thread id = %d\n", i);
136 tl_assert(s_threadinfo[i].first == 0);
137 tl_assert(s_threadinfo[i].last == 0);
138 return i;
139 }
140 }
sewardjaf44c822007-11-25 14:01:38 +0000141
bart3772a982008-03-15 08:11:03 +0000142 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000143
bart3772a982008-03-15 08:11:03 +0000144 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000145}
146
147DrdThreadId PtThreadIdToDrdThreadId(const PThreadId tid)
148{
bart3772a982008-03-15 08:11:03 +0000149 int i;
sewardjaf44c822007-11-25 14:01:38 +0000150
bart3772a982008-03-15 08:11:03 +0000151 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000152
bart3772a982008-03-15 08:11:03 +0000153 for (i = 1; i < DRD_N_THREADS; i++)
154 {
155 if (s_threadinfo[i].posix_thread_exists
156 && s_threadinfo[i].pt_threadid == tid)
157 {
158 return i;
159 }
160 }
161 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000162}
163
164ThreadId DrdThreadIdToVgThreadId(const DrdThreadId tid)
165{
bart74a5f212008-05-11 06:43:07 +0000166 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
167 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000168 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);
bart74a5f212008-05-11 06:43:07 +0000204 tl_assert(0 <= (int)created && created < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000205 && 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
bart74a5f212008-05-11 06:43:07 +0000221 tl_assert(0 <= (int)created && created < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000222 && 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{
bart74a5f212008-05-11 06:43:07 +0000240 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
241 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000242 tl_assert(s_threadinfo[tid].stack_min <= stack_startup);
243 tl_assert(stack_startup <= s_threadinfo[tid].stack_max);
244 s_threadinfo[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000245}
246
247Addr thread_get_stack_min(const DrdThreadId tid)
248{
bart74a5f212008-05-11 06:43:07 +0000249 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000250 && tid != DRD_INVALID_THREADID);
251 return s_threadinfo[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000252}
253
bartcac53462008-03-29 09:27:08 +0000254Addr thread_get_stack_min_min(const DrdThreadId tid)
255{
bart74a5f212008-05-11 06:43:07 +0000256 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000257 && tid != DRD_INVALID_THREADID);
258 return s_threadinfo[tid].stack_min_min;
259}
260
bartd43f8d32008-03-16 17:29:20 +0000261Addr thread_get_stack_max(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000262{
bart74a5f212008-05-11 06:43:07 +0000263 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartd43f8d32008-03-16 17:29:20 +0000264 && tid != DRD_INVALID_THREADID);
265 return s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000266}
267
bartcac53462008-03-29 09:27:08 +0000268SizeT thread_get_stack_size(const DrdThreadId tid)
269{
bart74a5f212008-05-11 06:43:07 +0000270 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000271 && tid != DRD_INVALID_THREADID);
272 return s_threadinfo[tid].stack_size;
273}
274
barta2b6e1b2008-03-17 18:32:39 +0000275/** Clean up thread-specific data structures. Call this just after
276 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000277 */
278void thread_delete(const DrdThreadId tid)
279{
bart3772a982008-03-15 08:11:03 +0000280 Segment* sg;
281 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000282
bart74a5f212008-05-11 06:43:07 +0000283 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000284 && tid != DRD_INVALID_THREADID);
285 tl_assert(s_threadinfo[tid].synchr_nesting == 0);
286 for (sg = s_threadinfo[tid].last; sg; sg = sg_prev)
287 {
288 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000289 sg->prev = 0;
290 sg->next = 0;
291 sg_put(sg);
bart3772a982008-03-15 08:11:03 +0000292 }
293 s_threadinfo[tid].vg_thread_exists = False;
294 s_threadinfo[tid].posix_thread_exists = False;
295 tl_assert(s_threadinfo[tid].detached_posix_thread == False);
296 s_threadinfo[tid].first = 0;
297 s_threadinfo[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000298}
299
300/* Called after a thread performed its last memory access and before */
301/* thread_delete() is called. Note: thread_delete() is only called for */
302/* joinable threads, not for detached threads. */
303void thread_finished(const DrdThreadId tid)
304{
bart74a5f212008-05-11 06:43:07 +0000305 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000306 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000307
bart3772a982008-03-15 08:11:03 +0000308 s_threadinfo[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000309
bart3772a982008-03-15 08:11:03 +0000310 if (s_threadinfo[tid].detached_posix_thread)
311 {
312 /* Once a detached thread has finished, its stack is deallocated and */
barte73b0aa2008-06-28 07:19:56 +0000313 /* should no longer be taken into account when computing the conflict set*/
bart3772a982008-03-15 08:11:03 +0000314 s_threadinfo[tid].stack_min = s_threadinfo[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000315
bart3772a982008-03-15 08:11:03 +0000316 /* For a detached thread, calling pthread_exit() invalidates the */
317 /* POSIX thread ID associated with the detached thread. For joinable */
318 /* POSIX threads however, the POSIX thread ID remains live after the */
319 /* pthread_exit() call until pthread_join() is called. */
320 s_threadinfo[tid].posix_thread_exists = False;
321 }
sewardjaf44c822007-11-25 14:01:38 +0000322}
323
324void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
325{
bart74a5f212008-05-11 06:43:07 +0000326 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000327 && tid != DRD_INVALID_THREADID);
328 tl_assert(s_threadinfo[tid].pt_threadid == INVALID_POSIX_THREADID);
329 tl_assert(ptid != INVALID_POSIX_THREADID);
330 s_threadinfo[tid].posix_thread_exists = True;
331 s_threadinfo[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000332}
333
334Bool thread_get_joinable(const DrdThreadId tid)
335{
bart74a5f212008-05-11 06:43:07 +0000336 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000337 && tid != DRD_INVALID_THREADID);
338 return ! s_threadinfo[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000339}
340
341void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
342{
bart74a5f212008-05-11 06:43:07 +0000343 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000344 && tid != DRD_INVALID_THREADID);
345 tl_assert(!! joinable == joinable);
346 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000347#if 0
bart3772a982008-03-15 08:11:03 +0000348 VG_(message)(Vg_DebugMsg,
349 "thread_set_joinable(%d/%d, %s)",
350 tid,
351 s_threadinfo[tid].vg_threadid,
352 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000353#endif
bart3772a982008-03-15 08:11:03 +0000354 s_threadinfo[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000355}
356
sewardj8b09d4f2007-12-04 21:27:18 +0000357void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000358{
bart3772a982008-03-15 08:11:03 +0000359 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000360
bart3772a982008-03-15 08:11:03 +0000361 if (vg_tid != s_vg_running_tid)
362 {
363 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
364 }
sewardj8b09d4f2007-12-04 21:27:18 +0000365
bart3772a982008-03-15 08:11:03 +0000366 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
367 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000368}
369
370void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
371{
bart3772a982008-03-15 08:11:03 +0000372 tl_assert(vg_tid != VG_INVALID_THREADID);
373 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000374
bart3772a982008-03-15 08:11:03 +0000375 if (vg_tid != s_vg_running_tid)
376 {
377 if (s_trace_context_switches
378 && s_drd_running_tid != DRD_INVALID_THREADID)
379 {
380 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000381 "Context switch from thread %d/%d to thread %d/%d;"
382 " segments: %llu",
bartaa97a542008-03-16 17:57:01 +0000383 s_vg_running_tid, s_drd_running_tid,
barta2b6e1b2008-03-17 18:32:39 +0000384 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
385 sg_get_alive_segments_count());
bart3772a982008-03-15 08:11:03 +0000386 }
387 s_vg_running_tid = vg_tid;
388 s_drd_running_tid = drd_tid;
barte73b0aa2008-06-28 07:19:56 +0000389 thread_compute_conflict_set(&s_conflict_set, drd_tid);
bart3772a982008-03-15 08:11:03 +0000390 s_context_switch_count++;
391 }
sewardj8b09d4f2007-12-04 21:27:18 +0000392
bart3772a982008-03-15 08:11:03 +0000393 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
394 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000395}
396
bart0268dfa2008-03-11 20:10:21 +0000397int thread_enter_synchr(const DrdThreadId tid)
398{
bart3772a982008-03-15 08:11:03 +0000399 tl_assert(IsValidDrdThreadId(tid));
400 return s_threadinfo[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000401}
402
403int thread_leave_synchr(const DrdThreadId tid)
404{
bart3772a982008-03-15 08:11:03 +0000405 tl_assert(IsValidDrdThreadId(tid));
406 tl_assert(s_threadinfo[tid].synchr_nesting >= 1);
407 return --s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000408}
409
410int thread_get_synchr_nesting_count(const DrdThreadId tid)
411{
bart3772a982008-03-15 08:11:03 +0000412 tl_assert(IsValidDrdThreadId(tid));
413 return s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000414}
415
bart1a473c72008-03-13 19:03:38 +0000416/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000417static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000418{
bart74a5f212008-05-11 06:43:07 +0000419 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000420 && tid != DRD_INVALID_THREADID);
bart23d3a4e2008-04-05 12:53:00 +0000421 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart3772a982008-03-15 08:11:03 +0000422 sg->prev = s_threadinfo[tid].last;
423 sg->next = 0;
424 if (s_threadinfo[tid].last)
425 s_threadinfo[tid].last->next = sg;
426 s_threadinfo[tid].last = sg;
427 if (s_threadinfo[tid].first == 0)
428 s_threadinfo[tid].first = sg;
bart23d3a4e2008-04-05 12:53:00 +0000429 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000430}
431
bart26f73e12008-02-24 18:37:08 +0000432/** Remove a segment from the segment list of thread threadid, and free the
433 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000434 */
bart26f73e12008-02-24 18:37:08 +0000435static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000436{
bart74a5f212008-05-11 06:43:07 +0000437 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000438 && tid != DRD_INVALID_THREADID);
bart3f749672008-03-22 09:49:40 +0000439 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart26f73e12008-02-24 18:37:08 +0000440
bart3772a982008-03-15 08:11:03 +0000441 if (sg->prev)
442 sg->prev->next = sg->next;
443 if (sg->next)
444 sg->next->prev = sg->prev;
445 if (sg == s_threadinfo[tid].first)
446 s_threadinfo[tid].first = sg->next;
447 if (sg == s_threadinfo[tid].last)
448 s_threadinfo[tid].last = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000449 sg_put(sg);
bart3f749672008-03-22 09:49:40 +0000450
451 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000452}
453
454VectorClock* thread_get_vc(const DrdThreadId tid)
455{
bart74a5f212008-05-11 06:43:07 +0000456 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
457 && 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);
bart74a5f212008-05-11 06:43:07 +0000468 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
469 && tid != DRD_INVALID_THREADID);
barta2b6e1b2008-03-17 18:32:39 +0000470 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,
barte73b0aa2008-06-28 07:19:56 +0000607 * it may be necessary to recalculate the conflict set if the vector clock
bartd66e3a82008-04-06 15:02:17 +0000608 * 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 */
barte73b0aa2008-06-28 07:19:56 +0000615static Bool conflict_set_update_needed(const DrdThreadId tid,
bartd66e3a82008-04-06 15:02:17 +0000616 const Segment* const new_sg)
617{
bart5d421ba2008-04-19 15:15:12 +0000618#if 0
bartd66e3a82008-04-06 15:02:17 +0000619 unsigned i;
620 const Segment* old_sg;
621
622 tl_assert(new_sg);
623
624 /* If a new segment was added to another thread than the running thread, */
barte73b0aa2008-06-28 07:19:56 +0000625 /* just tell the caller to update the conflict set. */
bartd66e3a82008-04-06 15:02:17 +0000626 if (tid != s_drd_running_tid)
627 return True;
628
barte73b0aa2008-06-28 07:19:56 +0000629 /* Always let the caller update the conflict set after creation of the */
bartd66e3a82008-04-06 15:02:17 +0000630 /* first segment. */
631 old_sg = new_sg->prev;
632 if (old_sg == 0)
633 return True;
634
635 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
636 {
637 Segment* q;
638
639 if (i == s_drd_running_tid)
640 continue;
641
642 for (q = s_threadinfo[i].last; q; q = q->prev)
643 {
644 /* If the expression below evaluates to false, this expression will */
645 /* also evaluate to false for all subsequent iterations. So stop */
646 /* iterating. */
647 if (vc_lte(&q->vc, &old_sg->vc))
648 break;
649 /* If the vector clock of the 2nd the last segment is not ordered */
650 /* to the vector clock of segment q, and the last segment is, ask */
barte73b0aa2008-06-28 07:19:56 +0000651 /* the caller to update the conflict set. */
bartd66e3a82008-04-06 15:02:17 +0000652 if (! vc_lte(&old_sg->vc, &q->vc))
653 {
654 return True;
655 }
656 /* If the vector clock of the last segment is not ordered to the */
barte73b0aa2008-06-28 07:19:56 +0000657 /* vector clock of segment q, ask the caller to update the conflict */
bartd66e3a82008-04-06 15:02:17 +0000658 /* set. */
659 if (! vc_lte(&q->vc, &new_sg->vc) && ! vc_lte(&new_sg->vc, &q->vc))
660 {
661 return True;
662 }
663 }
664 }
665
666 return False;
bart5d421ba2008-04-19 15:15:12 +0000667#else
668 return True;
669#endif
bartd66e3a82008-04-06 15:02:17 +0000670}
671
barta2b6e1b2008-03-17 18:32:39 +0000672/** Create a new segment for the specified thread, and discard any segments
673 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000674 */
675void thread_new_segment(const DrdThreadId tid)
676{
bartd66e3a82008-04-06 15:02:17 +0000677 Segment* new_sg;
678
bart74a5f212008-05-11 06:43:07 +0000679 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
680 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000681
bartd66e3a82008-04-06 15:02:17 +0000682 new_sg = sg_new(tid, tid);
683 thread_append_segment(tid, new_sg);
684
barte73b0aa2008-06-28 07:19:56 +0000685 if (conflict_set_update_needed(tid, new_sg))
bartd66e3a82008-04-06 15:02:17 +0000686 {
barte73b0aa2008-06-28 07:19:56 +0000687 thread_compute_conflict_set(&s_conflict_set, s_drd_running_tid);
688 s_conflict_set_new_segment_count++;
bartd66e3a82008-04-06 15:02:17 +0000689 }
bart82195c12008-04-13 17:35:08 +0000690 else if (tid == s_drd_running_tid)
691 {
barte73b0aa2008-06-28 07:19:56 +0000692 tl_assert(thread_conflict_set_up_to_date(s_drd_running_tid));
bart82195c12008-04-13 17:35:08 +0000693 }
sewardjaf44c822007-11-25 14:01:38 +0000694
bart3772a982008-03-15 08:11:03 +0000695 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000696
barta9c37392008-03-22 09:38:48 +0000697 if (s_segment_merging)
698 thread_merge_segments();
sewardjaf44c822007-11-25 14:01:38 +0000699}
700
bart26f73e12008-02-24 18:37:08 +0000701/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000702void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
703{
bart3772a982008-03-15 08:11:03 +0000704 tl_assert(joiner != joinee);
bart74a5f212008-05-11 06:43:07 +0000705 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000706 && joiner != DRD_INVALID_THREADID);
bart74a5f212008-05-11 06:43:07 +0000707 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000708 && joinee != DRD_INVALID_THREADID);
709 tl_assert(s_threadinfo[joiner].last);
710 tl_assert(s_threadinfo[joinee].last);
711 vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
712 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000713
bart3772a982008-03-15 08:11:03 +0000714 if (joiner == s_drd_running_tid)
715 {
barte73b0aa2008-06-28 07:19:56 +0000716 thread_compute_conflict_set(&s_conflict_set, joiner);
bart3772a982008-03-15 08:11:03 +0000717 }
sewardjaf44c822007-11-25 14:01:38 +0000718}
719
bart26f73e12008-02-24 18:37:08 +0000720/** Call this function after thread 'tid' had to wait because of thread
721 * synchronization until the memory accesses in the segment with vector clock
722 * 'vc' finished.
723 */
sewardjaf44c822007-11-25 14:01:38 +0000724void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
725{
bart74a5f212008-05-11 06:43:07 +0000726 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
727 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000728 tl_assert(s_threadinfo[tid].last);
729 tl_assert(vc);
730 vc_combine(&s_threadinfo[tid].last->vc, vc);
barte73b0aa2008-06-28 07:19:56 +0000731 thread_compute_conflict_set(&s_conflict_set, tid);
bart3772a982008-03-15 08:11:03 +0000732 thread_discard_ordered_segments();
barte73b0aa2008-06-28 07:19:56 +0000733 s_conflict_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000734}
735
bart26f73e12008-02-24 18:37:08 +0000736/** Call this function whenever a thread is no longer using the memory
737 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
738 * increase.
739 */
sewardjaf44c822007-11-25 14:01:38 +0000740void thread_stop_using_mem(const Addr a1, const Addr a2)
741{
bartd43f8d32008-03-16 17:29:20 +0000742 DrdThreadId other_user;
743 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000744
bart3772a982008-03-15 08:11:03 +0000745 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000746 other_user = DRD_INVALID_THREADID;
bart3772a982008-03-15 08:11:03 +0000747 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
748 {
749 Segment* p;
750 for (p = s_threadinfo[i].first; p; p = p->next)
751 {
752 if (other_user == DRD_INVALID_THREADID
bart8bf2f8b2008-03-30 17:56:43 +0000753 && i != s_drd_running_tid)
sewardjaf44c822007-11-25 14:01:38 +0000754 {
bart8bf2f8b2008-03-30 17:56:43 +0000755 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
756 {
757 other_user = i;
758 }
759 continue;
sewardjaf44c822007-11-25 14:01:38 +0000760 }
bart3772a982008-03-15 08:11:03 +0000761 bm_clear(p->bm, a1, a2);
762 }
763 }
sewardjaf44c822007-11-25 14:01:38 +0000764
bart3772a982008-03-15 08:11:03 +0000765 /* If any other thread had accessed memory in [ a1, a2 [, update the */
barte73b0aa2008-06-28 07:19:56 +0000766 /* conflict set. */
bart3772a982008-03-15 08:11:03 +0000767 if (other_user != DRD_INVALID_THREADID
barte73b0aa2008-06-28 07:19:56 +0000768 && bm_has_any_access(s_conflict_set, a1, a2))
bart3772a982008-03-15 08:11:03 +0000769 {
barte73b0aa2008-06-28 07:19:56 +0000770 thread_compute_conflict_set(&s_conflict_set, thread_get_running_tid());
bart3772a982008-03-15 08:11:03 +0000771 }
sewardjaf44c822007-11-25 14:01:38 +0000772}
773
bart0268dfa2008-03-11 20:10:21 +0000774void thread_start_recording(const DrdThreadId tid)
775{
bart74a5f212008-05-11 06:43:07 +0000776 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
777 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000778 tl_assert(! s_threadinfo[tid].is_recording);
779 s_threadinfo[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000780}
781
782void thread_stop_recording(const DrdThreadId tid)
783{
bart74a5f212008-05-11 06:43:07 +0000784 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
785 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000786 tl_assert(s_threadinfo[tid].is_recording);
787 s_threadinfo[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000788}
789
sewardjaf44c822007-11-25 14:01:38 +0000790void thread_print_all(void)
791{
bart3772a982008-03-15 08:11:03 +0000792 unsigned i;
793 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000794
bart3772a982008-03-15 08:11:03 +0000795 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
796 {
797 if (s_threadinfo[i].first)
798 {
799 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000800 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000801 "**************\n",
802 i,
803 s_threadinfo[i].vg_thread_exists,
804 s_threadinfo[i].vg_threadid,
805 s_threadinfo[i].posix_thread_exists,
806 s_threadinfo[i].pt_threadid,
bart354009c2008-03-16 10:42:33 +0000807 s_threadinfo[i].detached_posix_thread);
bart3772a982008-03-15 08:11:03 +0000808 for (p = s_threadinfo[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000809 {
bart3772a982008-03-15 08:11:03 +0000810 sg_print(p);
sewardjaf44c822007-11-25 14:01:38 +0000811 }
bart3772a982008-03-15 08:11:03 +0000812 }
813 }
sewardjaf44c822007-11-25 14:01:38 +0000814}
815
816static void show_call_stack(const DrdThreadId tid,
817 const Char* const msg,
818 ExeContext* const callstack)
819{
bart3772a982008-03-15 08:11:03 +0000820 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000821
bartaa97a542008-03-16 17:57:01 +0000822 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000823
bart3772a982008-03-15 08:11:03 +0000824 if (vg_tid != VG_INVALID_THREADID)
825 {
826 if (callstack)
827 {
828 VG_(pp_ExeContext)(callstack);
829 }
830 else
831 {
832 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
833 }
834 }
835 else
836 {
837 VG_(message)(Vg_UserMsg,
838 " (thread finished, call stack no longer available)");
839 }
sewardjaf44c822007-11-25 14:01:38 +0000840}
841
sewardjaf44c822007-11-25 14:01:38 +0000842static void
843thread_report_conflicting_segments_segment(const DrdThreadId tid,
844 const Addr addr,
845 const SizeT size,
846 const BmAccessTypeT access_type,
847 const Segment* const p)
848{
bart3772a982008-03-15 08:11:03 +0000849 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000850
bart74a5f212008-05-11 06:43:07 +0000851 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000852 && tid != DRD_INVALID_THREADID);
853 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000854
bart3772a982008-03-15 08:11:03 +0000855 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
856 {
857 if (i != tid)
858 {
859 Segment* q;
860 for (q = s_threadinfo[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000861 {
bart3772a982008-03-15 08:11:03 +0000862 // Since q iterates over the segments of thread i in order of
863 // decreasing vector clocks, if q->vc <= p->vc, then
864 // q->next->vc <= p->vc will also hold. Hence, break out of the
865 // loop once this condition is met.
866 if (vc_lte(&q->vc, &p->vc))
867 break;
868 if (! vc_lte(&p->vc, &q->vc))
869 {
870 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
871 {
872 tl_assert(q->stacktrace);
873 show_call_stack(i, "Other segment start",
874 q->stacktrace);
875 show_call_stack(i, "Other segment end",
876 q->next ? q->next->stacktrace : 0);
877 }
878 }
sewardjaf44c822007-11-25 14:01:38 +0000879 }
bart3772a982008-03-15 08:11:03 +0000880 }
881 }
sewardjaf44c822007-11-25 14:01:38 +0000882}
883
884void thread_report_conflicting_segments(const DrdThreadId tid,
885 const Addr addr,
886 const SizeT size,
887 const BmAccessTypeT access_type)
888{
bart3772a982008-03-15 08:11:03 +0000889 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000890
bart74a5f212008-05-11 06:43:07 +0000891 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000892 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000893
bart3772a982008-03-15 08:11:03 +0000894 for (p = s_threadinfo[tid].first; p; p = p->next)
895 {
896 if (bm_has(p->bm, addr, addr + size, access_type))
897 {
898 thread_report_conflicting_segments_segment(tid, addr, size,
899 access_type, p);
900 }
901 }
sewardjaf44c822007-11-25 14:01:38 +0000902}
sewardjaf44c822007-11-25 14:01:38 +0000903
barte73b0aa2008-06-28 07:19:56 +0000904/** Verify whether the conflict set for thread tid is up to date. Only perform
905 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
bart82195c12008-04-13 17:35:08 +0000906 */
barte73b0aa2008-06-28 07:19:56 +0000907static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
bart82195c12008-04-13 17:35:08 +0000908{
barte73b0aa2008-06-28 07:19:56 +0000909 static int do_verify_conflict_set = -1;
bart82195c12008-04-13 17:35:08 +0000910 Bool result;
barte73b0aa2008-06-28 07:19:56 +0000911 struct bitmap* computed_conflict_set = 0;
bart82195c12008-04-13 17:35:08 +0000912
barte73b0aa2008-06-28 07:19:56 +0000913 if (do_verify_conflict_set < 0)
bart82195c12008-04-13 17:35:08 +0000914 {
barte73b0aa2008-06-28 07:19:56 +0000915 //VG_(message)(Vg_DebugMsg, "%s", VG_(getenv)("DRD_VERIFY_CONFLICT_SET"));
916 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
bart82195c12008-04-13 17:35:08 +0000917 }
barte73b0aa2008-06-28 07:19:56 +0000918 if (do_verify_conflict_set == 0)
bart82195c12008-04-13 17:35:08 +0000919 return True;
920
barte73b0aa2008-06-28 07:19:56 +0000921 thread_compute_conflict_set(&computed_conflict_set, tid);
922 result = bm_equal(s_conflict_set, computed_conflict_set);
923 bm_delete(computed_conflict_set);
bart82195c12008-04-13 17:35:08 +0000924 return result;
925}
926
bart26f73e12008-02-24 18:37:08 +0000927/** Compute a bitmap that represents the union of all memory accesses of all
928 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +0000929 */
barte73b0aa2008-06-28 07:19:56 +0000930static void thread_compute_conflict_set(struct bitmap** conflict_set,
931 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000932{
bart3772a982008-03-15 08:11:03 +0000933 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000934
bart74a5f212008-05-11 06:43:07 +0000935 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
936 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000937 tl_assert(tid == s_drd_running_tid);
sewardjaf44c822007-11-25 14:01:38 +0000938
barte73b0aa2008-06-28 07:19:56 +0000939 s_update_conflict_set_count++;
940 s_conflict_set_bitmap_creation_count -= bm_get_bitmap_creation_count();
941 s_conflict_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000942
barte73b0aa2008-06-28 07:19:56 +0000943 if (*conflict_set)
bart3772a982008-03-15 08:11:03 +0000944 {
barte73b0aa2008-06-28 07:19:56 +0000945 bm_delete(*conflict_set);
bart3772a982008-03-15 08:11:03 +0000946 }
barte73b0aa2008-06-28 07:19:56 +0000947 *conflict_set = bm_new();
bart26f73e12008-02-24 18:37:08 +0000948
barte73b0aa2008-06-28 07:19:56 +0000949 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000950 {
951 char msg[256];
952
953 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +0000954 "computing conflict set for thread %d/%d with vc ",
bartaa97a542008-03-16 17:57:01 +0000955 DrdThreadIdToVgThreadId(tid), tid);
bart3772a982008-03-15 08:11:03 +0000956 vc_snprint(msg + VG_(strlen)(msg),
957 sizeof(msg) - VG_(strlen)(msg),
958 &s_threadinfo[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +0000959 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000960 }
961
962 p = s_threadinfo[tid].last;
963 {
964 unsigned j;
965
barte73b0aa2008-06-28 07:19:56 +0000966 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000967 {
bart26f73e12008-02-24 18:37:08 +0000968 char msg[256];
969
970 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +0000971 "conflict set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +0000972 tid);
973 vc_snprint(msg + VG_(strlen)(msg),
974 sizeof(msg) - VG_(strlen)(msg),
bart3772a982008-03-15 08:11:03 +0000975 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +0000976 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000977 }
sewardjaf44c822007-11-25 14:01:38 +0000978
bart3772a982008-03-15 08:11:03 +0000979 for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++)
980 {
bartd66e3a82008-04-06 15:02:17 +0000981 if (j != tid && IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +0000982 {
bart3772a982008-03-15 08:11:03 +0000983 const Segment* q;
984 for (q = s_threadinfo[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000985 {
986 if (! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000987 {
barte73b0aa2008-06-28 07:19:56 +0000988 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000989 {
990 char msg[256];
991 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +0000992 "conflict set: [%d] merging segment ", j);
bart3772a982008-03-15 08:11:03 +0000993 vc_snprint(msg + VG_(strlen)(msg),
994 sizeof(msg) - VG_(strlen)(msg),
995 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +0000996 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000997 }
barte73b0aa2008-06-28 07:19:56 +0000998 bm_merge2(*conflict_set, q->bm);
bart3772a982008-03-15 08:11:03 +0000999 }
1000 else
1001 {
barte73b0aa2008-06-28 07:19:56 +00001002 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001003 {
1004 char msg[256];
1005 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001006 "conflict set: [%d] ignoring segment ", j);
bart3772a982008-03-15 08:11:03 +00001007 vc_snprint(msg + VG_(strlen)(msg),
1008 sizeof(msg) - VG_(strlen)(msg),
1009 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001010 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001011 }
1012 }
bartd66e3a82008-04-06 15:02:17 +00001013 }
bart26f73e12008-02-24 18:37:08 +00001014 }
bart3772a982008-03-15 08:11:03 +00001015 }
bart3772a982008-03-15 08:11:03 +00001016 }
sewardjaf44c822007-11-25 14:01:38 +00001017
barte73b0aa2008-06-28 07:19:56 +00001018 s_conflict_set_bitmap_creation_count += bm_get_bitmap_creation_count();
1019 s_conflict_set_bitmap2_creation_count += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +00001020
barte73b0aa2008-06-28 07:19:56 +00001021 if (0 && s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001022 {
barte73b0aa2008-06-28 07:19:56 +00001023 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
1024 bm_print(*conflict_set);
1025 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
bart3772a982008-03-15 08:11:03 +00001026 }
sewardjaf44c822007-11-25 14:01:38 +00001027}
1028
sewardjaf44c822007-11-25 14:01:38 +00001029ULong thread_get_context_switch_count(void)
1030{
bart3772a982008-03-15 08:11:03 +00001031 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001032}
1033
sewardjaf44c822007-11-25 14:01:38 +00001034ULong thread_get_discard_ordered_segments_count(void)
1035{
bart3772a982008-03-15 08:11:03 +00001036 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001037}
1038
barte73b0aa2008-06-28 07:19:56 +00001039ULong thread_get_update_conflict_set_count(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001040{
bartd66e3a82008-04-06 15:02:17 +00001041 tl_assert(dsnsc);
1042 tl_assert(dscvc);
barte73b0aa2008-06-28 07:19:56 +00001043 *dsnsc = s_conflict_set_new_segment_count;
1044 *dscvc = s_conflict_set_combine_vc_count;
1045 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001046}
1047
barte73b0aa2008-06-28 07:19:56 +00001048ULong thread_get_conflict_set_bitmap_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001049{
barte73b0aa2008-06-28 07:19:56 +00001050 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001051}
1052
barte73b0aa2008-06-28 07:19:56 +00001053ULong thread_get_conflict_set_bitmap2_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001054{
barte73b0aa2008-06-28 07:19:56 +00001055 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001056}