blob: 82b4d86b6f736bf2152cd51e154c6c72d4963235 [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
bartaf0691b2008-09-27 12:26:50 +0000324void thread_pre_cancel(const DrdThreadId tid)
325{
326 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
327 && tid != DRD_INVALID_THREADID);
328 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
329
330 s_threadinfo[tid].synchr_nesting = 0;
331}
332
sewardjaf44c822007-11-25 14:01:38 +0000333void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
334{
bart74a5f212008-05-11 06:43:07 +0000335 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000336 && tid != DRD_INVALID_THREADID);
337 tl_assert(s_threadinfo[tid].pt_threadid == INVALID_POSIX_THREADID);
338 tl_assert(ptid != INVALID_POSIX_THREADID);
339 s_threadinfo[tid].posix_thread_exists = True;
340 s_threadinfo[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000341}
342
343Bool thread_get_joinable(const DrdThreadId tid)
344{
bart74a5f212008-05-11 06:43:07 +0000345 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000346 && tid != DRD_INVALID_THREADID);
347 return ! s_threadinfo[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000348}
349
350void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
351{
bart74a5f212008-05-11 06:43:07 +0000352 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000353 && tid != DRD_INVALID_THREADID);
354 tl_assert(!! joinable == joinable);
355 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000356#if 0
bart3772a982008-03-15 08:11:03 +0000357 VG_(message)(Vg_DebugMsg,
358 "thread_set_joinable(%d/%d, %s)",
359 tid,
360 s_threadinfo[tid].vg_threadid,
361 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000362#endif
bart3772a982008-03-15 08:11:03 +0000363 s_threadinfo[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000364}
365
sewardj8b09d4f2007-12-04 21:27:18 +0000366void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000367{
bart3772a982008-03-15 08:11:03 +0000368 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000369
bart3772a982008-03-15 08:11:03 +0000370 if (vg_tid != s_vg_running_tid)
371 {
372 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
373 }
sewardj8b09d4f2007-12-04 21:27:18 +0000374
bart3772a982008-03-15 08:11:03 +0000375 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
376 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000377}
378
379void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
380{
bart3772a982008-03-15 08:11:03 +0000381 tl_assert(vg_tid != VG_INVALID_THREADID);
382 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000383
bart3772a982008-03-15 08:11:03 +0000384 if (vg_tid != s_vg_running_tid)
385 {
386 if (s_trace_context_switches
387 && s_drd_running_tid != DRD_INVALID_THREADID)
388 {
389 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000390 "Context switch from thread %d/%d to thread %d/%d;"
391 " segments: %llu",
bartaa97a542008-03-16 17:57:01 +0000392 s_vg_running_tid, s_drd_running_tid,
barta2b6e1b2008-03-17 18:32:39 +0000393 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
394 sg_get_alive_segments_count());
bart3772a982008-03-15 08:11:03 +0000395 }
396 s_vg_running_tid = vg_tid;
397 s_drd_running_tid = drd_tid;
barte73b0aa2008-06-28 07:19:56 +0000398 thread_compute_conflict_set(&s_conflict_set, drd_tid);
bart3772a982008-03-15 08:11:03 +0000399 s_context_switch_count++;
400 }
sewardj8b09d4f2007-12-04 21:27:18 +0000401
bart3772a982008-03-15 08:11:03 +0000402 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
403 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000404}
405
bart0268dfa2008-03-11 20:10:21 +0000406int thread_enter_synchr(const DrdThreadId tid)
407{
bart3772a982008-03-15 08:11:03 +0000408 tl_assert(IsValidDrdThreadId(tid));
409 return s_threadinfo[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000410}
411
412int thread_leave_synchr(const DrdThreadId tid)
413{
bart3772a982008-03-15 08:11:03 +0000414 tl_assert(IsValidDrdThreadId(tid));
415 tl_assert(s_threadinfo[tid].synchr_nesting >= 1);
416 return --s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000417}
418
419int thread_get_synchr_nesting_count(const DrdThreadId tid)
420{
bart3772a982008-03-15 08:11:03 +0000421 tl_assert(IsValidDrdThreadId(tid));
422 return s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000423}
424
bart1a473c72008-03-13 19:03:38 +0000425/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000426static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000427{
bart74a5f212008-05-11 06:43:07 +0000428 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000429 && tid != DRD_INVALID_THREADID);
bart23d3a4e2008-04-05 12:53:00 +0000430 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart3772a982008-03-15 08:11:03 +0000431 sg->prev = s_threadinfo[tid].last;
432 sg->next = 0;
433 if (s_threadinfo[tid].last)
434 s_threadinfo[tid].last->next = sg;
435 s_threadinfo[tid].last = sg;
436 if (s_threadinfo[tid].first == 0)
437 s_threadinfo[tid].first = sg;
bart23d3a4e2008-04-05 12:53:00 +0000438 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000439}
440
bart26f73e12008-02-24 18:37:08 +0000441/** Remove a segment from the segment list of thread threadid, and free the
442 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000443 */
bart26f73e12008-02-24 18:37:08 +0000444static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000445{
bart74a5f212008-05-11 06:43:07 +0000446 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000447 && tid != DRD_INVALID_THREADID);
bart3f749672008-03-22 09:49:40 +0000448 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart26f73e12008-02-24 18:37:08 +0000449
bart3772a982008-03-15 08:11:03 +0000450 if (sg->prev)
451 sg->prev->next = sg->next;
452 if (sg->next)
453 sg->next->prev = sg->prev;
454 if (sg == s_threadinfo[tid].first)
455 s_threadinfo[tid].first = sg->next;
456 if (sg == s_threadinfo[tid].last)
457 s_threadinfo[tid].last = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000458 sg_put(sg);
bart3f749672008-03-22 09:49:40 +0000459
460 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000461}
462
463VectorClock* thread_get_vc(const DrdThreadId tid)
464{
bart74a5f212008-05-11 06:43:07 +0000465 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
466 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000467 tl_assert(s_threadinfo[tid].last);
468 return &s_threadinfo[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000469}
470
barta2b6e1b2008-03-17 18:32:39 +0000471/** Return the latest segment of thread 'tid' and increment its reference
472 * count.
473 */
474void thread_get_latest_segment(Segment** sg, const DrdThreadId tid)
475{
476 tl_assert(sg);
bart74a5f212008-05-11 06:43:07 +0000477 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
478 && tid != DRD_INVALID_THREADID);
barta2b6e1b2008-03-17 18:32:39 +0000479 tl_assert(s_threadinfo[tid].last);
480
481 sg_put(*sg);
482 *sg = sg_get(s_threadinfo[tid].last);
483}
484
sewardjaf44c822007-11-25 14:01:38 +0000485/**
486 * Compute the minimum of all latest vector clocks of all threads
487 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
488 * @param vc pointer to a vectorclock, holds result upon return.
489 */
490static void thread_compute_minimum_vc(VectorClock* vc)
491{
bart3772a982008-03-15 08:11:03 +0000492 unsigned i;
493 Bool first;
494 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000495
bart3772a982008-03-15 08:11:03 +0000496 first = True;
497 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
498 {
499 latest_sg = s_threadinfo[i].last;
500 if (latest_sg)
501 {
502 if (first)
503 vc_assign(vc, &latest_sg->vc);
504 else
505 vc_min(vc, &latest_sg->vc);
506 first = False;
507 }
508 }
sewardjaf44c822007-11-25 14:01:38 +0000509}
510
511static void thread_compute_maximum_vc(VectorClock* vc)
512{
bart3772a982008-03-15 08:11:03 +0000513 unsigned i;
514 Bool first;
515 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000516
bart3772a982008-03-15 08:11:03 +0000517 first = True;
518 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
519 {
520 latest_sg = s_threadinfo[i].last;
521 if (latest_sg)
522 {
523 if (first)
524 vc_assign(vc, &latest_sg->vc);
525 else
526 vc_combine(vc, &latest_sg->vc);
527 first = False;
528 }
529 }
sewardjaf44c822007-11-25 14:01:38 +0000530}
531
532/**
bart5bd9f2d2008-03-03 20:31:58 +0000533 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000534 * clock of every thread -- these segments can no longer be involved in a
535 * data race.
536 */
537static void thread_discard_ordered_segments(void)
538{
bart3772a982008-03-15 08:11:03 +0000539 unsigned i;
540 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000541
bart3772a982008-03-15 08:11:03 +0000542 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000543
bart3772a982008-03-15 08:11:03 +0000544 vc_init(&thread_vc_min, 0, 0);
545 thread_compute_minimum_vc(&thread_vc_min);
546 if (sg_get_trace())
547 {
548 char msg[256];
549 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000550
bart3772a982008-03-15 08:11:03 +0000551 vc_init(&thread_vc_max, 0, 0);
552 thread_compute_maximum_vc(&thread_vc_max);
553 VG_(snprintf)(msg, sizeof(msg),
554 "Discarding ordered segments -- min vc is ");
555 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
556 &thread_vc_min);
557 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
558 ", max vc is ");
559 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
560 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000561 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000562 vc_cleanup(&thread_vc_max);
563 }
sewardjaf44c822007-11-25 14:01:38 +0000564
bart3772a982008-03-15 08:11:03 +0000565 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
566 {
567 Segment* sg;
568 Segment* sg_next;
569 for (sg = s_threadinfo[i].first;
570 sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
571 sg = sg_next)
572 {
573 thread_discard_segment(i, sg);
574 }
575 }
576 vc_cleanup(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000577}
578
barta9c37392008-03-22 09:38:48 +0000579/** Merge all segments that may be merged without triggering false positives
580 * or discarding real data races. For the theoretical background of segment
581 * merging, see also the following paper:
582 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
583 * Bounding the number of segment histories during data race detection.
584 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
585 * September 2002.
586 */
587static void thread_merge_segments(void)
588{
589 unsigned i;
590
591 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
592 {
593 Segment* sg;
594
bart23d3a4e2008-04-05 12:53:00 +0000595 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000596
597 for (sg = s_threadinfo[i].first; sg; sg = sg->next)
598 {
599 if (sg_get_refcnt(sg) == 1
600 && sg->next
601 && sg_get_refcnt(sg->next) == 1
602 && sg->next->next)
603 {
604 /* Merge sg and sg->next into sg. */
605 sg_merge(sg, sg->next);
606 thread_discard_segment(i, sg->next);
607 }
608 }
609
bart23d3a4e2008-04-05 12:53:00 +0000610 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000611 }
612}
613
bartd66e3a82008-04-06 15:02:17 +0000614/** Every change in the vector clock of a thread may cause segments that
615 * were previously ordered to this thread to become unordered. Hence,
barte73b0aa2008-06-28 07:19:56 +0000616 * it may be necessary to recalculate the conflict set if the vector clock
bartd66e3a82008-04-06 15:02:17 +0000617 * of the current thread is updated. This function check whether such a
618 * recalculation is necessary.
619 *
620 * @param tid Thread ID of the thread to which a new segment has been
621 * appended.
622 * @param new_sg Pointer to the most recent segment of thread tid.
623 */
barte73b0aa2008-06-28 07:19:56 +0000624static Bool conflict_set_update_needed(const DrdThreadId tid,
bartd66e3a82008-04-06 15:02:17 +0000625 const Segment* const new_sg)
626{
bart5d421ba2008-04-19 15:15:12 +0000627#if 0
bartd66e3a82008-04-06 15:02:17 +0000628 unsigned i;
629 const Segment* old_sg;
630
631 tl_assert(new_sg);
632
633 /* If a new segment was added to another thread than the running thread, */
barte73b0aa2008-06-28 07:19:56 +0000634 /* just tell the caller to update the conflict set. */
bartd66e3a82008-04-06 15:02:17 +0000635 if (tid != s_drd_running_tid)
636 return True;
637
barte73b0aa2008-06-28 07:19:56 +0000638 /* Always let the caller update the conflict set after creation of the */
bartd66e3a82008-04-06 15:02:17 +0000639 /* first segment. */
640 old_sg = new_sg->prev;
641 if (old_sg == 0)
642 return True;
643
644 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
645 {
646 Segment* q;
647
648 if (i == s_drd_running_tid)
649 continue;
650
651 for (q = s_threadinfo[i].last; q; q = q->prev)
652 {
653 /* If the expression below evaluates to false, this expression will */
654 /* also evaluate to false for all subsequent iterations. So stop */
655 /* iterating. */
656 if (vc_lte(&q->vc, &old_sg->vc))
657 break;
658 /* If the vector clock of the 2nd the last segment is not ordered */
659 /* to the vector clock of segment q, and the last segment is, ask */
barte73b0aa2008-06-28 07:19:56 +0000660 /* the caller to update the conflict set. */
bartd66e3a82008-04-06 15:02:17 +0000661 if (! vc_lte(&old_sg->vc, &q->vc))
662 {
663 return True;
664 }
665 /* If the vector clock of the last segment is not ordered to the */
barte73b0aa2008-06-28 07:19:56 +0000666 /* vector clock of segment q, ask the caller to update the conflict */
bartd66e3a82008-04-06 15:02:17 +0000667 /* set. */
668 if (! vc_lte(&q->vc, &new_sg->vc) && ! vc_lte(&new_sg->vc, &q->vc))
669 {
670 return True;
671 }
672 }
673 }
674
675 return False;
bart5d421ba2008-04-19 15:15:12 +0000676#else
677 return True;
678#endif
bartd66e3a82008-04-06 15:02:17 +0000679}
680
barta2b6e1b2008-03-17 18:32:39 +0000681/** Create a new segment for the specified thread, and discard any segments
682 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000683 */
684void thread_new_segment(const DrdThreadId tid)
685{
bartd66e3a82008-04-06 15:02:17 +0000686 Segment* new_sg;
687
bart74a5f212008-05-11 06:43:07 +0000688 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
689 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000690
bartd66e3a82008-04-06 15:02:17 +0000691 new_sg = sg_new(tid, tid);
692 thread_append_segment(tid, new_sg);
693
barte73b0aa2008-06-28 07:19:56 +0000694 if (conflict_set_update_needed(tid, new_sg))
bartd66e3a82008-04-06 15:02:17 +0000695 {
barte73b0aa2008-06-28 07:19:56 +0000696 thread_compute_conflict_set(&s_conflict_set, s_drd_running_tid);
697 s_conflict_set_new_segment_count++;
bartd66e3a82008-04-06 15:02:17 +0000698 }
bart82195c12008-04-13 17:35:08 +0000699 else if (tid == s_drd_running_tid)
700 {
barte73b0aa2008-06-28 07:19:56 +0000701 tl_assert(thread_conflict_set_up_to_date(s_drd_running_tid));
bart82195c12008-04-13 17:35:08 +0000702 }
sewardjaf44c822007-11-25 14:01:38 +0000703
bart3772a982008-03-15 08:11:03 +0000704 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000705
barta9c37392008-03-22 09:38:48 +0000706 if (s_segment_merging)
707 thread_merge_segments();
sewardjaf44c822007-11-25 14:01:38 +0000708}
709
bart26f73e12008-02-24 18:37:08 +0000710/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000711void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
712{
bart3772a982008-03-15 08:11:03 +0000713 tl_assert(joiner != joinee);
bart74a5f212008-05-11 06:43:07 +0000714 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000715 && joiner != DRD_INVALID_THREADID);
bart74a5f212008-05-11 06:43:07 +0000716 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000717 && joinee != DRD_INVALID_THREADID);
718 tl_assert(s_threadinfo[joiner].last);
719 tl_assert(s_threadinfo[joinee].last);
720 vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
721 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000722
bart3772a982008-03-15 08:11:03 +0000723 if (joiner == s_drd_running_tid)
724 {
barte73b0aa2008-06-28 07:19:56 +0000725 thread_compute_conflict_set(&s_conflict_set, joiner);
bart3772a982008-03-15 08:11:03 +0000726 }
sewardjaf44c822007-11-25 14:01:38 +0000727}
728
bart26f73e12008-02-24 18:37:08 +0000729/** Call this function after thread 'tid' had to wait because of thread
730 * synchronization until the memory accesses in the segment with vector clock
731 * 'vc' finished.
732 */
sewardjaf44c822007-11-25 14:01:38 +0000733void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
734{
bart74a5f212008-05-11 06:43:07 +0000735 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
736 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000737 tl_assert(s_threadinfo[tid].last);
738 tl_assert(vc);
739 vc_combine(&s_threadinfo[tid].last->vc, vc);
barte73b0aa2008-06-28 07:19:56 +0000740 thread_compute_conflict_set(&s_conflict_set, tid);
bart3772a982008-03-15 08:11:03 +0000741 thread_discard_ordered_segments();
barte73b0aa2008-06-28 07:19:56 +0000742 s_conflict_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000743}
744
bart26f73e12008-02-24 18:37:08 +0000745/** Call this function whenever a thread is no longer using the memory
746 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
747 * increase.
748 */
sewardjaf44c822007-11-25 14:01:38 +0000749void thread_stop_using_mem(const Addr a1, const Addr a2)
750{
bartd43f8d32008-03-16 17:29:20 +0000751 DrdThreadId other_user;
752 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000753
bart3772a982008-03-15 08:11:03 +0000754 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000755 other_user = DRD_INVALID_THREADID;
bart3772a982008-03-15 08:11:03 +0000756 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
757 {
758 Segment* p;
759 for (p = s_threadinfo[i].first; p; p = p->next)
760 {
761 if (other_user == DRD_INVALID_THREADID
bart8bf2f8b2008-03-30 17:56:43 +0000762 && i != s_drd_running_tid)
sewardjaf44c822007-11-25 14:01:38 +0000763 {
bart8bf2f8b2008-03-30 17:56:43 +0000764 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
765 {
766 other_user = i;
767 }
768 continue;
sewardjaf44c822007-11-25 14:01:38 +0000769 }
bart3772a982008-03-15 08:11:03 +0000770 bm_clear(p->bm, a1, a2);
771 }
772 }
sewardjaf44c822007-11-25 14:01:38 +0000773
bart3772a982008-03-15 08:11:03 +0000774 /* If any other thread had accessed memory in [ a1, a2 [, update the */
barte73b0aa2008-06-28 07:19:56 +0000775 /* conflict set. */
bart3772a982008-03-15 08:11:03 +0000776 if (other_user != DRD_INVALID_THREADID
barte73b0aa2008-06-28 07:19:56 +0000777 && bm_has_any_access(s_conflict_set, a1, a2))
bart3772a982008-03-15 08:11:03 +0000778 {
barte73b0aa2008-06-28 07:19:56 +0000779 thread_compute_conflict_set(&s_conflict_set, thread_get_running_tid());
bart3772a982008-03-15 08:11:03 +0000780 }
sewardjaf44c822007-11-25 14:01:38 +0000781}
782
bart0268dfa2008-03-11 20:10:21 +0000783void thread_start_recording(const DrdThreadId tid)
784{
bart74a5f212008-05-11 06:43:07 +0000785 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
786 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000787 tl_assert(! s_threadinfo[tid].is_recording);
788 s_threadinfo[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000789}
790
791void thread_stop_recording(const DrdThreadId tid)
792{
bart74a5f212008-05-11 06:43:07 +0000793 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
794 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000795 tl_assert(s_threadinfo[tid].is_recording);
796 s_threadinfo[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000797}
798
sewardjaf44c822007-11-25 14:01:38 +0000799void thread_print_all(void)
800{
bart3772a982008-03-15 08:11:03 +0000801 unsigned i;
802 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000803
bart3772a982008-03-15 08:11:03 +0000804 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
805 {
806 if (s_threadinfo[i].first)
807 {
808 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000809 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000810 "**************\n",
811 i,
812 s_threadinfo[i].vg_thread_exists,
813 s_threadinfo[i].vg_threadid,
814 s_threadinfo[i].posix_thread_exists,
815 s_threadinfo[i].pt_threadid,
bart354009c2008-03-16 10:42:33 +0000816 s_threadinfo[i].detached_posix_thread);
bart3772a982008-03-15 08:11:03 +0000817 for (p = s_threadinfo[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000818 {
bart3772a982008-03-15 08:11:03 +0000819 sg_print(p);
sewardjaf44c822007-11-25 14:01:38 +0000820 }
bart3772a982008-03-15 08:11:03 +0000821 }
822 }
sewardjaf44c822007-11-25 14:01:38 +0000823}
824
825static void show_call_stack(const DrdThreadId tid,
826 const Char* const msg,
827 ExeContext* const callstack)
828{
bart3772a982008-03-15 08:11:03 +0000829 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000830
bartaa97a542008-03-16 17:57:01 +0000831 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000832
bart3772a982008-03-15 08:11:03 +0000833 if (vg_tid != VG_INVALID_THREADID)
834 {
835 if (callstack)
836 {
837 VG_(pp_ExeContext)(callstack);
838 }
839 else
840 {
841 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
842 }
843 }
844 else
845 {
846 VG_(message)(Vg_UserMsg,
847 " (thread finished, call stack no longer available)");
848 }
sewardjaf44c822007-11-25 14:01:38 +0000849}
850
sewardjaf44c822007-11-25 14:01:38 +0000851static void
852thread_report_conflicting_segments_segment(const DrdThreadId tid,
853 const Addr addr,
854 const SizeT size,
855 const BmAccessTypeT access_type,
856 const Segment* const p)
857{
bart3772a982008-03-15 08:11:03 +0000858 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000859
bart74a5f212008-05-11 06:43:07 +0000860 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000861 && tid != DRD_INVALID_THREADID);
862 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000863
bart3772a982008-03-15 08:11:03 +0000864 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
865 {
866 if (i != tid)
867 {
868 Segment* q;
869 for (q = s_threadinfo[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000870 {
bart3772a982008-03-15 08:11:03 +0000871 // Since q iterates over the segments of thread i in order of
872 // decreasing vector clocks, if q->vc <= p->vc, then
873 // q->next->vc <= p->vc will also hold. Hence, break out of the
874 // loop once this condition is met.
875 if (vc_lte(&q->vc, &p->vc))
876 break;
877 if (! vc_lte(&p->vc, &q->vc))
878 {
879 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
880 {
881 tl_assert(q->stacktrace);
882 show_call_stack(i, "Other segment start",
883 q->stacktrace);
884 show_call_stack(i, "Other segment end",
885 q->next ? q->next->stacktrace : 0);
886 }
887 }
sewardjaf44c822007-11-25 14:01:38 +0000888 }
bart3772a982008-03-15 08:11:03 +0000889 }
890 }
sewardjaf44c822007-11-25 14:01:38 +0000891}
892
893void thread_report_conflicting_segments(const DrdThreadId tid,
894 const Addr addr,
895 const SizeT size,
896 const BmAccessTypeT access_type)
897{
bart3772a982008-03-15 08:11:03 +0000898 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000899
bart74a5f212008-05-11 06:43:07 +0000900 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000901 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000902
bart3772a982008-03-15 08:11:03 +0000903 for (p = s_threadinfo[tid].first; p; p = p->next)
904 {
905 if (bm_has(p->bm, addr, addr + size, access_type))
906 {
907 thread_report_conflicting_segments_segment(tid, addr, size,
908 access_type, p);
909 }
910 }
sewardjaf44c822007-11-25 14:01:38 +0000911}
sewardjaf44c822007-11-25 14:01:38 +0000912
barte73b0aa2008-06-28 07:19:56 +0000913/** Verify whether the conflict set for thread tid is up to date. Only perform
914 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
bart82195c12008-04-13 17:35:08 +0000915 */
barte73b0aa2008-06-28 07:19:56 +0000916static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
bart82195c12008-04-13 17:35:08 +0000917{
barte73b0aa2008-06-28 07:19:56 +0000918 static int do_verify_conflict_set = -1;
bart82195c12008-04-13 17:35:08 +0000919 Bool result;
barte73b0aa2008-06-28 07:19:56 +0000920 struct bitmap* computed_conflict_set = 0;
bart82195c12008-04-13 17:35:08 +0000921
barte73b0aa2008-06-28 07:19:56 +0000922 if (do_verify_conflict_set < 0)
bart82195c12008-04-13 17:35:08 +0000923 {
barte73b0aa2008-06-28 07:19:56 +0000924 //VG_(message)(Vg_DebugMsg, "%s", VG_(getenv)("DRD_VERIFY_CONFLICT_SET"));
925 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
bart82195c12008-04-13 17:35:08 +0000926 }
barte73b0aa2008-06-28 07:19:56 +0000927 if (do_verify_conflict_set == 0)
bart82195c12008-04-13 17:35:08 +0000928 return True;
929
barte73b0aa2008-06-28 07:19:56 +0000930 thread_compute_conflict_set(&computed_conflict_set, tid);
931 result = bm_equal(s_conflict_set, computed_conflict_set);
932 bm_delete(computed_conflict_set);
bart82195c12008-04-13 17:35:08 +0000933 return result;
934}
935
bart26f73e12008-02-24 18:37:08 +0000936/** Compute a bitmap that represents the union of all memory accesses of all
937 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +0000938 */
barte73b0aa2008-06-28 07:19:56 +0000939static void thread_compute_conflict_set(struct bitmap** conflict_set,
940 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000941{
bart3772a982008-03-15 08:11:03 +0000942 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000943
bart74a5f212008-05-11 06:43:07 +0000944 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
945 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000946 tl_assert(tid == s_drd_running_tid);
sewardjaf44c822007-11-25 14:01:38 +0000947
barte73b0aa2008-06-28 07:19:56 +0000948 s_update_conflict_set_count++;
949 s_conflict_set_bitmap_creation_count -= bm_get_bitmap_creation_count();
950 s_conflict_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000951
barte73b0aa2008-06-28 07:19:56 +0000952 if (*conflict_set)
bart3772a982008-03-15 08:11:03 +0000953 {
barte73b0aa2008-06-28 07:19:56 +0000954 bm_delete(*conflict_set);
bart3772a982008-03-15 08:11:03 +0000955 }
barte73b0aa2008-06-28 07:19:56 +0000956 *conflict_set = bm_new();
bart26f73e12008-02-24 18:37:08 +0000957
barte73b0aa2008-06-28 07:19:56 +0000958 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000959 {
960 char msg[256];
961
962 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +0000963 "computing conflict set for thread %d/%d with vc ",
bartaa97a542008-03-16 17:57:01 +0000964 DrdThreadIdToVgThreadId(tid), tid);
bart3772a982008-03-15 08:11:03 +0000965 vc_snprint(msg + VG_(strlen)(msg),
966 sizeof(msg) - VG_(strlen)(msg),
967 &s_threadinfo[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +0000968 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000969 }
970
971 p = s_threadinfo[tid].last;
972 {
973 unsigned j;
974
barte73b0aa2008-06-28 07:19:56 +0000975 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000976 {
bart26f73e12008-02-24 18:37:08 +0000977 char msg[256];
978
979 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +0000980 "conflict set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +0000981 tid);
982 vc_snprint(msg + VG_(strlen)(msg),
983 sizeof(msg) - VG_(strlen)(msg),
bart3772a982008-03-15 08:11:03 +0000984 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +0000985 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000986 }
sewardjaf44c822007-11-25 14:01:38 +0000987
bart3772a982008-03-15 08:11:03 +0000988 for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++)
989 {
bartd66e3a82008-04-06 15:02:17 +0000990 if (j != tid && IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +0000991 {
bart3772a982008-03-15 08:11:03 +0000992 const Segment* q;
993 for (q = s_threadinfo[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000994 {
995 if (! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000996 {
barte73b0aa2008-06-28 07:19:56 +0000997 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000998 {
999 char msg[256];
1000 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001001 "conflict set: [%d] merging segment ", j);
bart3772a982008-03-15 08:11:03 +00001002 vc_snprint(msg + VG_(strlen)(msg),
1003 sizeof(msg) - VG_(strlen)(msg),
1004 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001005 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001006 }
barte73b0aa2008-06-28 07:19:56 +00001007 bm_merge2(*conflict_set, q->bm);
bart3772a982008-03-15 08:11:03 +00001008 }
1009 else
1010 {
barte73b0aa2008-06-28 07:19:56 +00001011 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001012 {
1013 char msg[256];
1014 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001015 "conflict set: [%d] ignoring segment ", j);
bart3772a982008-03-15 08:11:03 +00001016 vc_snprint(msg + VG_(strlen)(msg),
1017 sizeof(msg) - VG_(strlen)(msg),
1018 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001019 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001020 }
1021 }
bartd66e3a82008-04-06 15:02:17 +00001022 }
bart26f73e12008-02-24 18:37:08 +00001023 }
bart3772a982008-03-15 08:11:03 +00001024 }
bart3772a982008-03-15 08:11:03 +00001025 }
sewardjaf44c822007-11-25 14:01:38 +00001026
barte73b0aa2008-06-28 07:19:56 +00001027 s_conflict_set_bitmap_creation_count += bm_get_bitmap_creation_count();
1028 s_conflict_set_bitmap2_creation_count += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +00001029
barte73b0aa2008-06-28 07:19:56 +00001030 if (0 && s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001031 {
barte73b0aa2008-06-28 07:19:56 +00001032 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
1033 bm_print(*conflict_set);
1034 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
bart3772a982008-03-15 08:11:03 +00001035 }
sewardjaf44c822007-11-25 14:01:38 +00001036}
1037
sewardjaf44c822007-11-25 14:01:38 +00001038ULong thread_get_context_switch_count(void)
1039{
bart3772a982008-03-15 08:11:03 +00001040 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001041}
1042
sewardjaf44c822007-11-25 14:01:38 +00001043ULong thread_get_discard_ordered_segments_count(void)
1044{
bart3772a982008-03-15 08:11:03 +00001045 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001046}
1047
barte73b0aa2008-06-28 07:19:56 +00001048ULong thread_get_update_conflict_set_count(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001049{
bartd66e3a82008-04-06 15:02:17 +00001050 tl_assert(dsnsc);
1051 tl_assert(dscvc);
barte73b0aa2008-06-28 07:19:56 +00001052 *dsnsc = s_conflict_set_new_segment_count;
1053 *dscvc = s_conflict_set_combine_vc_count;
1054 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001055}
1056
barte73b0aa2008-06-28 07:19:56 +00001057ULong thread_get_conflict_set_bitmap_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001058{
barte73b0aa2008-06-28 07:19:56 +00001059 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001060}
1061
barte73b0aa2008-06-28 07:19:56 +00001062ULong thread_get_conflict_set_bitmap2_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001063{
barte73b0aa2008-06-28 07:19:56 +00001064 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001065}