blob: b57140fb8518dd5a7af611839b0555291294646d [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
bart9b2974a2008-09-27 12:35:31 +0000324/** Called just before pthread_cancel(). */
bartaf0691b2008-09-27 12:26:50 +0000325void thread_pre_cancel(const DrdThreadId tid)
326{
327 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
328 && tid != DRD_INVALID_THREADID);
329 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
330
331 s_threadinfo[tid].synchr_nesting = 0;
332}
333
sewardjaf44c822007-11-25 14:01:38 +0000334void thread_set_pthreadid(const DrdThreadId tid, const PThreadId ptid)
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 tl_assert(s_threadinfo[tid].pt_threadid == INVALID_POSIX_THREADID);
339 tl_assert(ptid != INVALID_POSIX_THREADID);
340 s_threadinfo[tid].posix_thread_exists = True;
341 s_threadinfo[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000342}
343
344Bool thread_get_joinable(const DrdThreadId tid)
345{
bart74a5f212008-05-11 06:43:07 +0000346 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000347 && tid != DRD_INVALID_THREADID);
348 return ! s_threadinfo[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000349}
350
351void thread_set_joinable(const DrdThreadId tid, const Bool joinable)
352{
bart74a5f212008-05-11 06:43:07 +0000353 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000354 && tid != DRD_INVALID_THREADID);
355 tl_assert(!! joinable == joinable);
356 tl_assert(s_threadinfo[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000357#if 0
bart3772a982008-03-15 08:11:03 +0000358 VG_(message)(Vg_DebugMsg,
359 "thread_set_joinable(%d/%d, %s)",
360 tid,
361 s_threadinfo[tid].vg_threadid,
362 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000363#endif
bart3772a982008-03-15 08:11:03 +0000364 s_threadinfo[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000365}
366
sewardj8b09d4f2007-12-04 21:27:18 +0000367void thread_set_vg_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000368{
bart3772a982008-03-15 08:11:03 +0000369 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000370
bart3772a982008-03-15 08:11:03 +0000371 if (vg_tid != s_vg_running_tid)
372 {
373 thread_set_running_tid(vg_tid, VgThreadIdToDrdThreadId(vg_tid));
374 }
sewardj8b09d4f2007-12-04 21:27:18 +0000375
bart3772a982008-03-15 08:11:03 +0000376 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
377 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000378}
379
380void thread_set_running_tid(const ThreadId vg_tid, const DrdThreadId drd_tid)
381{
bart3772a982008-03-15 08:11:03 +0000382 tl_assert(vg_tid != VG_INVALID_THREADID);
383 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000384
bart3772a982008-03-15 08:11:03 +0000385 if (vg_tid != s_vg_running_tid)
386 {
387 if (s_trace_context_switches
388 && s_drd_running_tid != DRD_INVALID_THREADID)
389 {
390 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000391 "Context switch from thread %d/%d to thread %d/%d;"
392 " segments: %llu",
bartaa97a542008-03-16 17:57:01 +0000393 s_vg_running_tid, s_drd_running_tid,
barta2b6e1b2008-03-17 18:32:39 +0000394 DrdThreadIdToVgThreadId(drd_tid), drd_tid,
395 sg_get_alive_segments_count());
bart3772a982008-03-15 08:11:03 +0000396 }
397 s_vg_running_tid = vg_tid;
398 s_drd_running_tid = drd_tid;
barte73b0aa2008-06-28 07:19:56 +0000399 thread_compute_conflict_set(&s_conflict_set, drd_tid);
bart3772a982008-03-15 08:11:03 +0000400 s_context_switch_count++;
401 }
sewardj8b09d4f2007-12-04 21:27:18 +0000402
bart3772a982008-03-15 08:11:03 +0000403 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
404 tl_assert(s_drd_running_tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000405}
406
bart0268dfa2008-03-11 20:10:21 +0000407int thread_enter_synchr(const DrdThreadId tid)
408{
bart3772a982008-03-15 08:11:03 +0000409 tl_assert(IsValidDrdThreadId(tid));
410 return s_threadinfo[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000411}
412
413int thread_leave_synchr(const DrdThreadId tid)
414{
bart3772a982008-03-15 08:11:03 +0000415 tl_assert(IsValidDrdThreadId(tid));
416 tl_assert(s_threadinfo[tid].synchr_nesting >= 1);
417 return --s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000418}
419
420int thread_get_synchr_nesting_count(const DrdThreadId tid)
421{
bart3772a982008-03-15 08:11:03 +0000422 tl_assert(IsValidDrdThreadId(tid));
423 return s_threadinfo[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000424}
425
bart1a473c72008-03-13 19:03:38 +0000426/** Append a new segment at the end of the segment list. */
bart26f73e12008-02-24 18:37:08 +0000427static void thread_append_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000428{
bart74a5f212008-05-11 06:43:07 +0000429 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000430 && tid != DRD_INVALID_THREADID);
bart23d3a4e2008-04-05 12:53:00 +0000431 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart3772a982008-03-15 08:11:03 +0000432 sg->prev = s_threadinfo[tid].last;
433 sg->next = 0;
434 if (s_threadinfo[tid].last)
435 s_threadinfo[tid].last->next = sg;
436 s_threadinfo[tid].last = sg;
437 if (s_threadinfo[tid].first == 0)
438 s_threadinfo[tid].first = sg;
bart23d3a4e2008-04-05 12:53:00 +0000439 // tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000440}
441
bart26f73e12008-02-24 18:37:08 +0000442/** Remove a segment from the segment list of thread threadid, and free the
443 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000444 */
bart26f73e12008-02-24 18:37:08 +0000445static void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000446{
bart74a5f212008-05-11 06:43:07 +0000447 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000448 && tid != DRD_INVALID_THREADID);
bart3f749672008-03-22 09:49:40 +0000449 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
bart26f73e12008-02-24 18:37:08 +0000450
bart3772a982008-03-15 08:11:03 +0000451 if (sg->prev)
452 sg->prev->next = sg->next;
453 if (sg->next)
454 sg->next->prev = sg->prev;
455 if (sg == s_threadinfo[tid].first)
456 s_threadinfo[tid].first = sg->next;
457 if (sg == s_threadinfo[tid].last)
458 s_threadinfo[tid].last = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000459 sg_put(sg);
bart3f749672008-03-22 09:49:40 +0000460
461 //tl_assert(sane_ThreadInfo(&s_threadinfo[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000462}
463
464VectorClock* thread_get_vc(const DrdThreadId tid)
465{
bart74a5f212008-05-11 06:43:07 +0000466 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
467 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000468 tl_assert(s_threadinfo[tid].last);
469 return &s_threadinfo[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000470}
471
barta2b6e1b2008-03-17 18:32:39 +0000472/** Return the latest segment of thread 'tid' and increment its reference
473 * count.
474 */
475void thread_get_latest_segment(Segment** sg, const DrdThreadId tid)
476{
477 tl_assert(sg);
bart74a5f212008-05-11 06:43:07 +0000478 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
479 && tid != DRD_INVALID_THREADID);
barta2b6e1b2008-03-17 18:32:39 +0000480 tl_assert(s_threadinfo[tid].last);
481
482 sg_put(*sg);
483 *sg = sg_get(s_threadinfo[tid].last);
484}
485
sewardjaf44c822007-11-25 14:01:38 +0000486/**
487 * Compute the minimum of all latest vector clocks of all threads
488 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
489 * @param vc pointer to a vectorclock, holds result upon return.
490 */
491static void thread_compute_minimum_vc(VectorClock* vc)
492{
bart3772a982008-03-15 08:11:03 +0000493 unsigned i;
494 Bool first;
495 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000496
bart3772a982008-03-15 08:11:03 +0000497 first = True;
498 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
499 {
500 latest_sg = s_threadinfo[i].last;
501 if (latest_sg)
502 {
503 if (first)
504 vc_assign(vc, &latest_sg->vc);
505 else
506 vc_min(vc, &latest_sg->vc);
507 first = False;
508 }
509 }
sewardjaf44c822007-11-25 14:01:38 +0000510}
511
512static void thread_compute_maximum_vc(VectorClock* vc)
513{
bart3772a982008-03-15 08:11:03 +0000514 unsigned i;
515 Bool first;
516 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000517
bart3772a982008-03-15 08:11:03 +0000518 first = True;
519 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
520 {
521 latest_sg = s_threadinfo[i].last;
522 if (latest_sg)
523 {
524 if (first)
525 vc_assign(vc, &latest_sg->vc);
526 else
527 vc_combine(vc, &latest_sg->vc);
528 first = False;
529 }
530 }
sewardjaf44c822007-11-25 14:01:38 +0000531}
532
533/**
bart5bd9f2d2008-03-03 20:31:58 +0000534 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000535 * clock of every thread -- these segments can no longer be involved in a
536 * data race.
537 */
538static void thread_discard_ordered_segments(void)
539{
bart3772a982008-03-15 08:11:03 +0000540 unsigned i;
541 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000542
bart3772a982008-03-15 08:11:03 +0000543 s_discard_ordered_segments_count++;
sewardjaf44c822007-11-25 14:01:38 +0000544
bart3772a982008-03-15 08:11:03 +0000545 vc_init(&thread_vc_min, 0, 0);
546 thread_compute_minimum_vc(&thread_vc_min);
547 if (sg_get_trace())
548 {
549 char msg[256];
550 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000551
bart3772a982008-03-15 08:11:03 +0000552 vc_init(&thread_vc_max, 0, 0);
553 thread_compute_maximum_vc(&thread_vc_max);
554 VG_(snprintf)(msg, sizeof(msg),
555 "Discarding ordered segments -- min vc is ");
556 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
557 &thread_vc_min);
558 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
559 ", max vc is ");
560 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
561 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000562 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000563 vc_cleanup(&thread_vc_max);
564 }
sewardjaf44c822007-11-25 14:01:38 +0000565
bart3772a982008-03-15 08:11:03 +0000566 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
567 {
568 Segment* sg;
569 Segment* sg_next;
570 for (sg = s_threadinfo[i].first;
571 sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
572 sg = sg_next)
573 {
574 thread_discard_segment(i, sg);
575 }
576 }
577 vc_cleanup(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000578}
579
barta9c37392008-03-22 09:38:48 +0000580/** Merge all segments that may be merged without triggering false positives
581 * or discarding real data races. For the theoretical background of segment
582 * merging, see also the following paper:
583 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
584 * Bounding the number of segment histories during data race detection.
585 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
586 * September 2002.
587 */
588static void thread_merge_segments(void)
589{
590 unsigned i;
591
592 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
593 {
594 Segment* sg;
595
bart23d3a4e2008-04-05 12:53:00 +0000596 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000597
598 for (sg = s_threadinfo[i].first; sg; sg = sg->next)
599 {
600 if (sg_get_refcnt(sg) == 1
601 && sg->next
602 && sg_get_refcnt(sg->next) == 1
603 && sg->next->next)
604 {
605 /* Merge sg and sg->next into sg. */
606 sg_merge(sg, sg->next);
607 thread_discard_segment(i, sg->next);
608 }
609 }
610
bart23d3a4e2008-04-05 12:53:00 +0000611 // tl_assert(sane_ThreadInfo(&s_threadinfo[i]));
barta9c37392008-03-22 09:38:48 +0000612 }
613}
614
bartd66e3a82008-04-06 15:02:17 +0000615/** Every change in the vector clock of a thread may cause segments that
616 * were previously ordered to this thread to become unordered. Hence,
barte73b0aa2008-06-28 07:19:56 +0000617 * it may be necessary to recalculate the conflict set if the vector clock
bartd66e3a82008-04-06 15:02:17 +0000618 * of the current thread is updated. This function check whether such a
619 * recalculation is necessary.
620 *
621 * @param tid Thread ID of the thread to which a new segment has been
622 * appended.
623 * @param new_sg Pointer to the most recent segment of thread tid.
624 */
barte73b0aa2008-06-28 07:19:56 +0000625static Bool conflict_set_update_needed(const DrdThreadId tid,
bartd66e3a82008-04-06 15:02:17 +0000626 const Segment* const new_sg)
627{
bart5d421ba2008-04-19 15:15:12 +0000628#if 0
bartd66e3a82008-04-06 15:02:17 +0000629 unsigned i;
630 const Segment* old_sg;
631
632 tl_assert(new_sg);
633
634 /* If a new segment was added to another thread than the running thread, */
barte73b0aa2008-06-28 07:19:56 +0000635 /* just tell the caller to update the conflict set. */
bartd66e3a82008-04-06 15:02:17 +0000636 if (tid != s_drd_running_tid)
637 return True;
638
barte73b0aa2008-06-28 07:19:56 +0000639 /* Always let the caller update the conflict set after creation of the */
bartd66e3a82008-04-06 15:02:17 +0000640 /* first segment. */
641 old_sg = new_sg->prev;
642 if (old_sg == 0)
643 return True;
644
645 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
646 {
647 Segment* q;
648
649 if (i == s_drd_running_tid)
650 continue;
651
652 for (q = s_threadinfo[i].last; q; q = q->prev)
653 {
654 /* If the expression below evaluates to false, this expression will */
655 /* also evaluate to false for all subsequent iterations. So stop */
656 /* iterating. */
657 if (vc_lte(&q->vc, &old_sg->vc))
658 break;
659 /* If the vector clock of the 2nd the last segment is not ordered */
660 /* to the vector clock of segment q, and the last segment is, ask */
barte73b0aa2008-06-28 07:19:56 +0000661 /* the caller to update the conflict set. */
bartd66e3a82008-04-06 15:02:17 +0000662 if (! vc_lte(&old_sg->vc, &q->vc))
663 {
664 return True;
665 }
666 /* If the vector clock of the last segment is not ordered to the */
barte73b0aa2008-06-28 07:19:56 +0000667 /* vector clock of segment q, ask the caller to update the conflict */
bartd66e3a82008-04-06 15:02:17 +0000668 /* set. */
669 if (! vc_lte(&q->vc, &new_sg->vc) && ! vc_lte(&new_sg->vc, &q->vc))
670 {
671 return True;
672 }
673 }
674 }
675
676 return False;
bart5d421ba2008-04-19 15:15:12 +0000677#else
678 return True;
679#endif
bartd66e3a82008-04-06 15:02:17 +0000680}
681
barta2b6e1b2008-03-17 18:32:39 +0000682/** Create a new segment for the specified thread, and discard any segments
683 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000684 */
685void thread_new_segment(const DrdThreadId tid)
686{
bartd66e3a82008-04-06 15:02:17 +0000687 Segment* new_sg;
688
bart74a5f212008-05-11 06:43:07 +0000689 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
690 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000691
bartd66e3a82008-04-06 15:02:17 +0000692 new_sg = sg_new(tid, tid);
693 thread_append_segment(tid, new_sg);
694
barte73b0aa2008-06-28 07:19:56 +0000695 if (conflict_set_update_needed(tid, new_sg))
bartd66e3a82008-04-06 15:02:17 +0000696 {
barte73b0aa2008-06-28 07:19:56 +0000697 thread_compute_conflict_set(&s_conflict_set, s_drd_running_tid);
698 s_conflict_set_new_segment_count++;
bartd66e3a82008-04-06 15:02:17 +0000699 }
bart82195c12008-04-13 17:35:08 +0000700 else if (tid == s_drd_running_tid)
701 {
barte73b0aa2008-06-28 07:19:56 +0000702 tl_assert(thread_conflict_set_up_to_date(s_drd_running_tid));
bart82195c12008-04-13 17:35:08 +0000703 }
sewardjaf44c822007-11-25 14:01:38 +0000704
bart3772a982008-03-15 08:11:03 +0000705 thread_discard_ordered_segments();
bart26f73e12008-02-24 18:37:08 +0000706
barta9c37392008-03-22 09:38:48 +0000707 if (s_segment_merging)
708 thread_merge_segments();
sewardjaf44c822007-11-25 14:01:38 +0000709}
710
bart26f73e12008-02-24 18:37:08 +0000711/** Call this function after thread 'joiner' joined thread 'joinee'. */
sewardjaf44c822007-11-25 14:01:38 +0000712void thread_combine_vc(DrdThreadId joiner, DrdThreadId joinee)
713{
bart3772a982008-03-15 08:11:03 +0000714 tl_assert(joiner != joinee);
bart74a5f212008-05-11 06:43:07 +0000715 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000716 && joiner != DRD_INVALID_THREADID);
bart74a5f212008-05-11 06:43:07 +0000717 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000718 && joinee != DRD_INVALID_THREADID);
719 tl_assert(s_threadinfo[joiner].last);
720 tl_assert(s_threadinfo[joinee].last);
721 vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
722 thread_discard_ordered_segments();
sewardjaf44c822007-11-25 14:01:38 +0000723
bart3772a982008-03-15 08:11:03 +0000724 if (joiner == s_drd_running_tid)
725 {
barte73b0aa2008-06-28 07:19:56 +0000726 thread_compute_conflict_set(&s_conflict_set, joiner);
bart3772a982008-03-15 08:11:03 +0000727 }
sewardjaf44c822007-11-25 14:01:38 +0000728}
729
bart26f73e12008-02-24 18:37:08 +0000730/** Call this function after thread 'tid' had to wait because of thread
731 * synchronization until the memory accesses in the segment with vector clock
732 * 'vc' finished.
733 */
sewardjaf44c822007-11-25 14:01:38 +0000734void thread_combine_vc2(DrdThreadId tid, const VectorClock* const vc)
735{
bart74a5f212008-05-11 06:43:07 +0000736 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
737 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000738 tl_assert(s_threadinfo[tid].last);
739 tl_assert(vc);
740 vc_combine(&s_threadinfo[tid].last->vc, vc);
barte73b0aa2008-06-28 07:19:56 +0000741 thread_compute_conflict_set(&s_conflict_set, tid);
bart3772a982008-03-15 08:11:03 +0000742 thread_discard_ordered_segments();
barte73b0aa2008-06-28 07:19:56 +0000743 s_conflict_set_combine_vc_count++;
sewardjaf44c822007-11-25 14:01:38 +0000744}
745
bart26f73e12008-02-24 18:37:08 +0000746/** Call this function whenever a thread is no longer using the memory
747 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
748 * increase.
749 */
sewardjaf44c822007-11-25 14:01:38 +0000750void thread_stop_using_mem(const Addr a1, const Addr a2)
751{
bartd43f8d32008-03-16 17:29:20 +0000752 DrdThreadId other_user;
753 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000754
bart3772a982008-03-15 08:11:03 +0000755 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000756 other_user = DRD_INVALID_THREADID;
bart3772a982008-03-15 08:11:03 +0000757 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
758 {
759 Segment* p;
760 for (p = s_threadinfo[i].first; p; p = p->next)
761 {
762 if (other_user == DRD_INVALID_THREADID
bart8bf2f8b2008-03-30 17:56:43 +0000763 && i != s_drd_running_tid)
sewardjaf44c822007-11-25 14:01:38 +0000764 {
bart8bf2f8b2008-03-30 17:56:43 +0000765 if (UNLIKELY(bm_test_and_clear(p->bm, a1, a2)))
766 {
767 other_user = i;
768 }
769 continue;
sewardjaf44c822007-11-25 14:01:38 +0000770 }
bart3772a982008-03-15 08:11:03 +0000771 bm_clear(p->bm, a1, a2);
772 }
773 }
sewardjaf44c822007-11-25 14:01:38 +0000774
bart3772a982008-03-15 08:11:03 +0000775 /* If any other thread had accessed memory in [ a1, a2 [, update the */
barte73b0aa2008-06-28 07:19:56 +0000776 /* conflict set. */
bart3772a982008-03-15 08:11:03 +0000777 if (other_user != DRD_INVALID_THREADID
barte73b0aa2008-06-28 07:19:56 +0000778 && bm_has_any_access(s_conflict_set, a1, a2))
bart3772a982008-03-15 08:11:03 +0000779 {
barte73b0aa2008-06-28 07:19:56 +0000780 thread_compute_conflict_set(&s_conflict_set, thread_get_running_tid());
bart3772a982008-03-15 08:11:03 +0000781 }
sewardjaf44c822007-11-25 14:01:38 +0000782}
783
bart0268dfa2008-03-11 20:10:21 +0000784void thread_start_recording(const DrdThreadId tid)
785{
bart74a5f212008-05-11 06:43:07 +0000786 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
787 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000788 tl_assert(! s_threadinfo[tid].is_recording);
789 s_threadinfo[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000790}
791
792void thread_stop_recording(const DrdThreadId tid)
793{
bart74a5f212008-05-11 06:43:07 +0000794 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
795 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000796 tl_assert(s_threadinfo[tid].is_recording);
797 s_threadinfo[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000798}
799
sewardjaf44c822007-11-25 14:01:38 +0000800void thread_print_all(void)
801{
bart3772a982008-03-15 08:11:03 +0000802 unsigned i;
803 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000804
bart3772a982008-03-15 08:11:03 +0000805 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
806 {
807 if (s_threadinfo[i].first)
808 {
809 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000810 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000811 "**************\n",
812 i,
813 s_threadinfo[i].vg_thread_exists,
814 s_threadinfo[i].vg_threadid,
815 s_threadinfo[i].posix_thread_exists,
816 s_threadinfo[i].pt_threadid,
bart354009c2008-03-16 10:42:33 +0000817 s_threadinfo[i].detached_posix_thread);
bart3772a982008-03-15 08:11:03 +0000818 for (p = s_threadinfo[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000819 {
bart3772a982008-03-15 08:11:03 +0000820 sg_print(p);
sewardjaf44c822007-11-25 14:01:38 +0000821 }
bart3772a982008-03-15 08:11:03 +0000822 }
823 }
sewardjaf44c822007-11-25 14:01:38 +0000824}
825
826static void show_call_stack(const DrdThreadId tid,
827 const Char* const msg,
828 ExeContext* const callstack)
829{
bart3772a982008-03-15 08:11:03 +0000830 const ThreadId vg_tid = DrdThreadIdToVgThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000831
bartaa97a542008-03-16 17:57:01 +0000832 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000833
bart3772a982008-03-15 08:11:03 +0000834 if (vg_tid != VG_INVALID_THREADID)
835 {
836 if (callstack)
837 {
838 VG_(pp_ExeContext)(callstack);
839 }
840 else
841 {
842 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
843 }
844 }
845 else
846 {
847 VG_(message)(Vg_UserMsg,
848 " (thread finished, call stack no longer available)");
849 }
sewardjaf44c822007-11-25 14:01:38 +0000850}
851
sewardjaf44c822007-11-25 14:01:38 +0000852static void
853thread_report_conflicting_segments_segment(const DrdThreadId tid,
854 const Addr addr,
855 const SizeT size,
856 const BmAccessTypeT access_type,
857 const Segment* const p)
858{
bart3772a982008-03-15 08:11:03 +0000859 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000860
bart74a5f212008-05-11 06:43:07 +0000861 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000862 && tid != DRD_INVALID_THREADID);
863 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000864
bart3772a982008-03-15 08:11:03 +0000865 for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
866 {
867 if (i != tid)
868 {
869 Segment* q;
870 for (q = s_threadinfo[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000871 {
bart3772a982008-03-15 08:11:03 +0000872 // Since q iterates over the segments of thread i in order of
873 // decreasing vector clocks, if q->vc <= p->vc, then
874 // q->next->vc <= p->vc will also hold. Hence, break out of the
875 // loop once this condition is met.
876 if (vc_lte(&q->vc, &p->vc))
877 break;
878 if (! vc_lte(&p->vc, &q->vc))
879 {
880 if (bm_has_conflict_with(q->bm, addr, addr + size, access_type))
881 {
882 tl_assert(q->stacktrace);
883 show_call_stack(i, "Other segment start",
884 q->stacktrace);
885 show_call_stack(i, "Other segment end",
886 q->next ? q->next->stacktrace : 0);
887 }
888 }
sewardjaf44c822007-11-25 14:01:38 +0000889 }
bart3772a982008-03-15 08:11:03 +0000890 }
891 }
sewardjaf44c822007-11-25 14:01:38 +0000892}
893
894void thread_report_conflicting_segments(const DrdThreadId tid,
895 const Addr addr,
896 const SizeT size,
897 const BmAccessTypeT access_type)
898{
bart3772a982008-03-15 08:11:03 +0000899 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000900
bart74a5f212008-05-11 06:43:07 +0000901 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000902 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000903
bart3772a982008-03-15 08:11:03 +0000904 for (p = s_threadinfo[tid].first; p; p = p->next)
905 {
906 if (bm_has(p->bm, addr, addr + size, access_type))
907 {
908 thread_report_conflicting_segments_segment(tid, addr, size,
909 access_type, p);
910 }
911 }
sewardjaf44c822007-11-25 14:01:38 +0000912}
sewardjaf44c822007-11-25 14:01:38 +0000913
barte73b0aa2008-06-28 07:19:56 +0000914/** Verify whether the conflict set for thread tid is up to date. Only perform
915 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
bart82195c12008-04-13 17:35:08 +0000916 */
barte73b0aa2008-06-28 07:19:56 +0000917static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
bart82195c12008-04-13 17:35:08 +0000918{
barte73b0aa2008-06-28 07:19:56 +0000919 static int do_verify_conflict_set = -1;
bart82195c12008-04-13 17:35:08 +0000920 Bool result;
barte73b0aa2008-06-28 07:19:56 +0000921 struct bitmap* computed_conflict_set = 0;
bart82195c12008-04-13 17:35:08 +0000922
barte73b0aa2008-06-28 07:19:56 +0000923 if (do_verify_conflict_set < 0)
bart82195c12008-04-13 17:35:08 +0000924 {
barte73b0aa2008-06-28 07:19:56 +0000925 //VG_(message)(Vg_DebugMsg, "%s", VG_(getenv)("DRD_VERIFY_CONFLICT_SET"));
926 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
bart82195c12008-04-13 17:35:08 +0000927 }
barte73b0aa2008-06-28 07:19:56 +0000928 if (do_verify_conflict_set == 0)
bart82195c12008-04-13 17:35:08 +0000929 return True;
930
barte73b0aa2008-06-28 07:19:56 +0000931 thread_compute_conflict_set(&computed_conflict_set, tid);
932 result = bm_equal(s_conflict_set, computed_conflict_set);
933 bm_delete(computed_conflict_set);
bart82195c12008-04-13 17:35:08 +0000934 return result;
935}
936
bart26f73e12008-02-24 18:37:08 +0000937/** Compute a bitmap that represents the union of all memory accesses of all
938 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +0000939 */
barte73b0aa2008-06-28 07:19:56 +0000940static void thread_compute_conflict_set(struct bitmap** conflict_set,
941 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000942{
bart3772a982008-03-15 08:11:03 +0000943 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000944
bart74a5f212008-05-11 06:43:07 +0000945 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
946 && tid != DRD_INVALID_THREADID);
bart3772a982008-03-15 08:11:03 +0000947 tl_assert(tid == s_drd_running_tid);
sewardjaf44c822007-11-25 14:01:38 +0000948
barte73b0aa2008-06-28 07:19:56 +0000949 s_update_conflict_set_count++;
950 s_conflict_set_bitmap_creation_count -= bm_get_bitmap_creation_count();
951 s_conflict_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +0000952
barte73b0aa2008-06-28 07:19:56 +0000953 if (*conflict_set)
bart3772a982008-03-15 08:11:03 +0000954 {
barte73b0aa2008-06-28 07:19:56 +0000955 bm_delete(*conflict_set);
bart3772a982008-03-15 08:11:03 +0000956 }
barte73b0aa2008-06-28 07:19:56 +0000957 *conflict_set = bm_new();
bart26f73e12008-02-24 18:37:08 +0000958
barte73b0aa2008-06-28 07:19:56 +0000959 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000960 {
961 char msg[256];
962
963 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +0000964 "computing conflict set for thread %d/%d with vc ",
bartaa97a542008-03-16 17:57:01 +0000965 DrdThreadIdToVgThreadId(tid), tid);
bart3772a982008-03-15 08:11:03 +0000966 vc_snprint(msg + VG_(strlen)(msg),
967 sizeof(msg) - VG_(strlen)(msg),
968 &s_threadinfo[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +0000969 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000970 }
971
972 p = s_threadinfo[tid].last;
973 {
974 unsigned j;
975
barte73b0aa2008-06-28 07:19:56 +0000976 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000977 {
bart26f73e12008-02-24 18:37:08 +0000978 char msg[256];
979
980 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +0000981 "conflict set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +0000982 tid);
983 vc_snprint(msg + VG_(strlen)(msg),
984 sizeof(msg) - VG_(strlen)(msg),
bart3772a982008-03-15 08:11:03 +0000985 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +0000986 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +0000987 }
sewardjaf44c822007-11-25 14:01:38 +0000988
bart3772a982008-03-15 08:11:03 +0000989 for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++)
990 {
bartd66e3a82008-04-06 15:02:17 +0000991 if (j != tid && IsValidDrdThreadId(j))
bart26f73e12008-02-24 18:37:08 +0000992 {
bart3772a982008-03-15 08:11:03 +0000993 const Segment* q;
994 for (q = s_threadinfo[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000995 {
996 if (! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000997 {
barte73b0aa2008-06-28 07:19:56 +0000998 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +0000999 {
1000 char msg[256];
1001 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001002 "conflict set: [%d] merging segment ", j);
bart3772a982008-03-15 08:11:03 +00001003 vc_snprint(msg + VG_(strlen)(msg),
1004 sizeof(msg) - VG_(strlen)(msg),
1005 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001006 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001007 }
barte73b0aa2008-06-28 07:19:56 +00001008 bm_merge2(*conflict_set, q->bm);
bart3772a982008-03-15 08:11:03 +00001009 }
1010 else
1011 {
barte73b0aa2008-06-28 07:19:56 +00001012 if (s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001013 {
1014 char msg[256];
1015 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001016 "conflict set: [%d] ignoring segment ", j);
bart3772a982008-03-15 08:11:03 +00001017 vc_snprint(msg + VG_(strlen)(msg),
1018 sizeof(msg) - VG_(strlen)(msg),
1019 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001020 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001021 }
1022 }
bartd66e3a82008-04-06 15:02:17 +00001023 }
bart26f73e12008-02-24 18:37:08 +00001024 }
bart3772a982008-03-15 08:11:03 +00001025 }
bart3772a982008-03-15 08:11:03 +00001026 }
sewardjaf44c822007-11-25 14:01:38 +00001027
barte73b0aa2008-06-28 07:19:56 +00001028 s_conflict_set_bitmap_creation_count += bm_get_bitmap_creation_count();
1029 s_conflict_set_bitmap2_creation_count += bm_get_bitmap2_creation_count();
sewardjaf44c822007-11-25 14:01:38 +00001030
barte73b0aa2008-06-28 07:19:56 +00001031 if (0 && s_trace_conflict_set)
bart3772a982008-03-15 08:11:03 +00001032 {
barte73b0aa2008-06-28 07:19:56 +00001033 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
1034 bm_print(*conflict_set);
1035 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
bart3772a982008-03-15 08:11:03 +00001036 }
sewardjaf44c822007-11-25 14:01:38 +00001037}
1038
sewardjaf44c822007-11-25 14:01:38 +00001039ULong thread_get_context_switch_count(void)
1040{
bart3772a982008-03-15 08:11:03 +00001041 return s_context_switch_count;
sewardjaf44c822007-11-25 14:01:38 +00001042}
1043
sewardjaf44c822007-11-25 14:01:38 +00001044ULong thread_get_discard_ordered_segments_count(void)
1045{
bart3772a982008-03-15 08:11:03 +00001046 return s_discard_ordered_segments_count;
sewardjaf44c822007-11-25 14:01:38 +00001047}
1048
barte73b0aa2008-06-28 07:19:56 +00001049ULong thread_get_update_conflict_set_count(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001050{
bartd66e3a82008-04-06 15:02:17 +00001051 tl_assert(dsnsc);
1052 tl_assert(dscvc);
barte73b0aa2008-06-28 07:19:56 +00001053 *dsnsc = s_conflict_set_new_segment_count;
1054 *dscvc = s_conflict_set_combine_vc_count;
1055 return s_update_conflict_set_count;
sewardjaf44c822007-11-25 14:01:38 +00001056}
1057
barte73b0aa2008-06-28 07:19:56 +00001058ULong thread_get_conflict_set_bitmap_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001059{
barte73b0aa2008-06-28 07:19:56 +00001060 return s_conflict_set_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001061}
1062
barte73b0aa2008-06-28 07:19:56 +00001063ULong thread_get_conflict_set_bitmap2_creation_count(void)
sewardjaf44c822007-11-25 14:01:38 +00001064{
barte73b0aa2008-06-28 07:19:56 +00001065 return s_conflict_set_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +00001066}