blob: 5a8b130d2c6c8b5c0f3b56605ecde6d877b4410c [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
bart86562bd2009-02-16 19:43:56 +00002 This file is part of drd, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00003
bart86562bd2009-02-16 19:43:56 +00004 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
sewardjaf44c822007-11-25 14:01:38 +00005
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307, USA.
20
21 The GNU General Public License is contained in the file COPYING.
22*/
23
24
25#include "drd_error.h"
bart09dc13f2009-02-14 15:13:31 +000026#include "drd_barrier.h"
bartd2c5eae2009-02-21 15:27:04 +000027#include "drd_clientobj.h"
bart09dc13f2009-02-14 15:13:31 +000028#include "drd_cond.h"
29#include "drd_mutex.h"
sewardjaf44c822007-11-25 14:01:38 +000030#include "drd_segment.h"
bart09dc13f2009-02-14 15:13:31 +000031#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000032#include "drd_suppression.h"
33#include "drd_thread.h"
bart82195c12008-04-13 17:35:08 +000034#include "pub_tool_vki.h"
sewardjaf44c822007-11-25 14:01:38 +000035#include "pub_tool_basics.h" // Addr, SizeT
36#include "pub_tool_errormgr.h" // VG_(unique_error)()
37#include "pub_tool_libcassert.h" // tl_assert()
38#include "pub_tool_libcbase.h" // VG_(strlen)()
39#include "pub_tool_libcprint.h" // VG_(printf)()
bart82195c12008-04-13 17:35:08 +000040#include "pub_tool_libcproc.h" // VG_(getenv)()
sewardjaf44c822007-11-25 14:01:38 +000041#include "pub_tool_machine.h"
42#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
sewardj85642922008-01-14 11:54:56 +000043#include "pub_tool_options.h" // VG_(clo_backtrace_size)
sewardjaf44c822007-11-25 14:01:38 +000044#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
45
bart32ba2082008-06-05 08:53:42 +000046
sewardjaf44c822007-11-25 14:01:38 +000047
bart324a23b2009-02-15 12:14:52 +000048/* Local functions. */
sewardjaf44c822007-11-25 14:01:38 +000049
bart62a784c2009-02-15 13:11:14 +000050static void DRD_(thread_append_segment)(const DrdThreadId tid,
51 Segment* const sg);
52static void DRD_(thread_discard_segment)(const DrdThreadId tid,
53 Segment* const sg);
54static Bool DRD_(thread_conflict_set_up_to_date)(const DrdThreadId tid);
55static void DRD_(thread_compute_conflict_set)(struct bitmap** conflict_set,
56 const DrdThreadId tid);
sewardjaf44c822007-11-25 14:01:38 +000057
58
bart324a23b2009-02-15 12:14:52 +000059/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000060
bart324a23b2009-02-15 12:14:52 +000061static ULong DRD_(s_context_switch_count);
62static ULong DRD_(s_discard_ordered_segments_count);
63static ULong DRD_(s_update_conflict_set_count);
64static ULong DRD_(s_conflict_set_new_segment_count);
65static ULong DRD_(s_conflict_set_combine_vc_count);
66static ULong DRD_(s_conflict_set_bitmap_creation_count);
67static ULong DRD_(s_conflict_set_bitmap2_creation_count);
68static ThreadId DRD_(s_vg_running_tid) = VG_INVALID_THREADID;
69DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
70ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
71struct bitmap* DRD_(g_conflict_set);
72static Bool DRD_(s_trace_context_switches) = False;
73static Bool DRD_(s_trace_conflict_set) = False;
74static Bool DRD_(s_trace_fork_join) = False;
75static Bool DRD_(s_segment_merging) = True;
sewardjaf44c822007-11-25 14:01:38 +000076
77
bart324a23b2009-02-15 12:14:52 +000078/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000079
bart62a784c2009-02-15 13:11:14 +000080void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000081{
bart09dc13f2009-02-14 15:13:31 +000082 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +000083 DRD_(s_trace_context_switches) = t;
bart26f73e12008-02-24 18:37:08 +000084}
85
bart62a784c2009-02-15 13:11:14 +000086void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000087{
bart09dc13f2009-02-14 15:13:31 +000088 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +000089 DRD_(s_trace_conflict_set) = t;
bart26f73e12008-02-24 18:37:08 +000090}
91
bart09dc13f2009-02-14 15:13:31 +000092Bool DRD_(thread_get_trace_fork_join)(void)
93{
bart324a23b2009-02-15 12:14:52 +000094 return DRD_(s_trace_fork_join);
bart09dc13f2009-02-14 15:13:31 +000095}
96
97void DRD_(thread_set_trace_fork_join)(const Bool t)
98{
99 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +0000100 DRD_(s_trace_fork_join) = t;
bart09dc13f2009-02-14 15:13:31 +0000101}
102
bart62a784c2009-02-15 13:11:14 +0000103void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000104{
bart09dc13f2009-02-14 15:13:31 +0000105 tl_assert(m == False || m == True);
bart324a23b2009-02-15 12:14:52 +0000106 DRD_(s_segment_merging) = m;
barta9c37392008-03-22 09:38:48 +0000107}
108
sewardjaf44c822007-11-25 14:01:38 +0000109/**
110 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
111 * Valgrind's ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000112 */
bart62a784c2009-02-15 13:11:14 +0000113DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000114{
bart3772a982008-03-15 08:11:03 +0000115 int i;
sewardjaf44c822007-11-25 14:01:38 +0000116
bart3772a982008-03-15 08:11:03 +0000117 if (tid == VG_INVALID_THREADID)
118 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000119
bart3772a982008-03-15 08:11:03 +0000120 for (i = 1; i < DRD_N_THREADS; i++)
121 {
bart324a23b2009-02-15 12:14:52 +0000122 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
123 && DRD_(g_threadinfo)[i].vg_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000124 {
125 return i;
126 }
127 }
sewardjaf44c822007-11-25 14:01:38 +0000128
bart3772a982008-03-15 08:11:03 +0000129 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000130}
131
bart62a784c2009-02-15 13:11:14 +0000132static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000133{
bart3772a982008-03-15 08:11:03 +0000134 int i;
sewardjaf44c822007-11-25 14:01:38 +0000135
bart62a784c2009-02-15 13:11:14 +0000136 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000137
bart3772a982008-03-15 08:11:03 +0000138 for (i = 1; i < DRD_N_THREADS; i++)
139 {
bart324a23b2009-02-15 12:14:52 +0000140 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
141 && DRD_(g_threadinfo)[i].posix_thread_exists == False
142 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
bart3772a982008-03-15 08:11:03 +0000143 {
bart324a23b2009-02-15 12:14:52 +0000144 DRD_(g_threadinfo)[i].vg_thread_exists = True;
145 DRD_(g_threadinfo)[i].vg_threadid = tid;
146 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
147 DRD_(g_threadinfo)[i].stack_min = 0;
148 DRD_(g_threadinfo)[i].stack_min_min = 0;
149 DRD_(g_threadinfo)[i].stack_startup = 0;
150 DRD_(g_threadinfo)[i].stack_max = 0;
151 DRD_(g_threadinfo)[i].is_recording = True;
152 DRD_(g_threadinfo)[i].synchr_nesting = 0;
153 if (DRD_(g_threadinfo)[i].first != 0)
bart3772a982008-03-15 08:11:03 +0000154 VG_(printf)("drd thread id = %d\n", i);
bart324a23b2009-02-15 12:14:52 +0000155 tl_assert(DRD_(g_threadinfo)[i].first == 0);
156 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart3772a982008-03-15 08:11:03 +0000157 return i;
158 }
159 }
sewardjaf44c822007-11-25 14:01:38 +0000160
bart3772a982008-03-15 08:11:03 +0000161 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000162
bart3772a982008-03-15 08:11:03 +0000163 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000164}
165
bart62a784c2009-02-15 13:11:14 +0000166DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000167{
bart3772a982008-03-15 08:11:03 +0000168 int i;
sewardjaf44c822007-11-25 14:01:38 +0000169
bart3772a982008-03-15 08:11:03 +0000170 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000171
bart3772a982008-03-15 08:11:03 +0000172 for (i = 1; i < DRD_N_THREADS; i++)
173 {
bart324a23b2009-02-15 12:14:52 +0000174 if (DRD_(g_threadinfo)[i].posix_thread_exists
175 && DRD_(g_threadinfo)[i].pt_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000176 {
177 return i;
178 }
179 }
180 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000181}
182
bart62a784c2009-02-15 13:11:14 +0000183ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000184{
bart74a5f212008-05-11 06:43:07 +0000185 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
186 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000187 return (DRD_(g_threadinfo)[tid].vg_thread_exists
188 ? DRD_(g_threadinfo)[tid].vg_threadid
bart3772a982008-03-15 08:11:03 +0000189 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000190}
191
bart23d3a4e2008-04-05 12:53:00 +0000192#if 0
bart324a23b2009-02-15 12:14:52 +0000193/**
194 * Sanity check of the doubly linked list of segments referenced by a
195 * ThreadInfo struct.
196 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000197 */
bart62a784c2009-02-15 13:11:14 +0000198static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000199{
bart3772a982008-03-15 08:11:03 +0000200 Segment* p;
201 for (p = ti->first; p; p = p->next) {
202 if (p->next && p->next->prev != p)
203 return False;
204 if (p->next == 0 && p != ti->last)
205 return False;
206 }
207 for (p = ti->last; p; p = p->prev) {
208 if (p->prev && p->prev->next != p)
209 return False;
210 if (p->prev == 0 && p != ti->first)
211 return False;
212 }
213 return True;
sewardjaf44c822007-11-25 14:01:38 +0000214}
bart23d3a4e2008-04-05 12:53:00 +0000215#endif
sewardjaf44c822007-11-25 14:01:38 +0000216
bart439c55f2009-02-15 10:38:37 +0000217/**
218 * Create the first segment for a newly started thread.
219 *
220 * This function is called from the handler installed via
221 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
222 * from the context of the creator thread, before the new thread has been
223 * created.
224 */
bart62a784c2009-02-15 13:11:14 +0000225DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
226 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000227{
bart3772a982008-03-15 08:11:03 +0000228 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000229
bart62a784c2009-02-15 13:11:14 +0000230 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
231 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
bart74a5f212008-05-11 06:43:07 +0000232 tl_assert(0 <= (int)created && created < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000233 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000234
bart324a23b2009-02-15 12:14:52 +0000235 tl_assert(DRD_(g_threadinfo)[created].first == 0);
236 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart62a784c2009-02-15 13:11:14 +0000237 DRD_(thread_append_segment)(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000238
bart3772a982008-03-15 08:11:03 +0000239 return created;
sewardjaf44c822007-11-25 14:01:38 +0000240}
241
bart439c55f2009-02-15 10:38:37 +0000242/**
bart324a23b2009-02-15 12:14:52 +0000243 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called after
bart439c55f2009-02-15 10:38:37 +0000244 * the thread has been created and before any client instructioins are run
245 * on the newly created thread, e.g. from the handler installed via
246 * VG_(track_pre_thread_first_insn)().
247 */
bart62a784c2009-02-15 13:11:14 +0000248DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000249{
bart62a784c2009-02-15 13:11:14 +0000250 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000251
252 tl_assert(0 <= (int)created && created < DRD_N_THREADS
253 && created != DRD_INVALID_THREADID);
254
bart324a23b2009-02-15 12:14:52 +0000255 DRD_(g_threadinfo)[created].stack_max = VG_(thread_get_stack_max)(vg_created);
256 DRD_(g_threadinfo)[created].stack_startup = DRD_(g_threadinfo)[created].stack_max;
257 DRD_(g_threadinfo)[created].stack_min = DRD_(g_threadinfo)[created].stack_max;
258 DRD_(g_threadinfo)[created].stack_min_min = DRD_(g_threadinfo)[created].stack_max;
259 DRD_(g_threadinfo)[created].stack_size = VG_(thread_get_stack_size)(vg_created);
260 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000261
262 return created;
263}
bart09dc13f2009-02-14 15:13:31 +0000264
bart324a23b2009-02-15 12:14:52 +0000265/**
266 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
267 * after thread drd_joiner joined thread drd_joinee.
268 */
bart09dc13f2009-02-14 15:13:31 +0000269void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
270{
bart62a784c2009-02-15 13:11:14 +0000271 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
272 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
273 DRD_(thread_new_segment)(drd_joinee);
274 DRD_(thread_combine_vc)(drd_joiner, drd_joinee);
275 DRD_(thread_new_segment)(drd_joiner);
bart09dc13f2009-02-14 15:13:31 +0000276
bart324a23b2009-02-15 12:14:52 +0000277 if (DRD_(s_trace_fork_join))
bart09dc13f2009-02-14 15:13:31 +0000278 {
bart62a784c2009-02-15 13:11:14 +0000279 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
280 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000281 const unsigned msg_size = 256;
282 char* msg;
283
284 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
285 tl_assert(msg);
286 VG_(snprintf)(msg, msg_size,
287 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
288 joiner, drd_joiner, joinee, drd_joinee);
289 if (joiner)
290 {
291 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
292 ", new vc: ");
bart41b226c2009-02-14 16:55:19 +0000293 DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart62a784c2009-02-15 13:11:14 +0000294 DRD_(thread_get_vc)(drd_joiner));
bart09dc13f2009-02-14 15:13:31 +0000295 }
296 VG_(message)(Vg_DebugMsg, "%s", msg);
297 VG_(free)(msg);
298 }
299
300 if (! DRD_(get_check_stack_accesses)())
301 {
bart62a784c2009-02-15 13:11:14 +0000302 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
303 - DRD_(thread_get_stack_size)(drd_joinee),
304 DRD_(thread_get_stack_max)(drd_joinee));
bart09dc13f2009-02-14 15:13:31 +0000305 }
bartd2c5eae2009-02-21 15:27:04 +0000306 DRD_(clientobj_delete_thread)(drd_joinee);
bart62a784c2009-02-15 13:11:14 +0000307 DRD_(thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000308}
309
bart324a23b2009-02-15 12:14:52 +0000310/**
311 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
312 * and accesses this data structure from multiple threads without locking.
313 * Any conflicting accesses in the range stack_startup..stack_max will be
314 * ignored.
315 */
bart62a784c2009-02-15 13:11:14 +0000316void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
317 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000318{
bart74a5f212008-05-11 06:43:07 +0000319 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
320 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000321 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
322 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
323 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000324}
325
bart62a784c2009-02-15 13:11:14 +0000326Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000327{
bart74a5f212008-05-11 06:43:07 +0000328 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000329 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000330 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000331}
332
bart62a784c2009-02-15 13:11:14 +0000333Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000334{
bart74a5f212008-05-11 06:43:07 +0000335 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000336 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000337 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000338}
339
bart62a784c2009-02-15 13:11:14 +0000340Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000341{
bart74a5f212008-05-11 06:43:07 +0000342 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartd43f8d32008-03-16 17:29:20 +0000343 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000344 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000345}
346
bart62a784c2009-02-15 13:11:14 +0000347SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000348{
bart74a5f212008-05-11 06:43:07 +0000349 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000350 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000351 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000352}
353
bart09dc13f2009-02-14 15:13:31 +0000354/**
355 * Clean up thread-specific data structures. Call this just after
356 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000357 */
bart62a784c2009-02-15 13:11:14 +0000358void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000359{
bart3772a982008-03-15 08:11:03 +0000360 Segment* sg;
361 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000362
bart74a5f212008-05-11 06:43:07 +0000363 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000364 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000365 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
366 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
bart3772a982008-03-15 08:11:03 +0000367 {
368 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000369 sg->prev = 0;
370 sg->next = 0;
bart62ada3f2009-02-14 17:19:58 +0000371 DRD_(sg_put)(sg);
bart3772a982008-03-15 08:11:03 +0000372 }
bart324a23b2009-02-15 12:14:52 +0000373 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
374 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
375 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
376 DRD_(g_threadinfo)[tid].first = 0;
377 DRD_(g_threadinfo)[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000378}
379
bart324a23b2009-02-15 12:14:52 +0000380/**
381 * Called after a thread performed its last memory access and before
382 * thread_delete() is called. Note: thread_delete() is only called for
383 * joinable threads, not for detached threads.
384 */
bart62a784c2009-02-15 13:11:14 +0000385void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000386{
bart74a5f212008-05-11 06:43:07 +0000387 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000388 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000389
bart324a23b2009-02-15 12:14:52 +0000390 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000391
bart324a23b2009-02-15 12:14:52 +0000392 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
bart3772a982008-03-15 08:11:03 +0000393 {
394 /* Once a detached thread has finished, its stack is deallocated and */
barte73b0aa2008-06-28 07:19:56 +0000395 /* should no longer be taken into account when computing the conflict set*/
bart324a23b2009-02-15 12:14:52 +0000396 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000397
bart3772a982008-03-15 08:11:03 +0000398 /* For a detached thread, calling pthread_exit() invalidates the */
399 /* POSIX thread ID associated with the detached thread. For joinable */
400 /* POSIX threads however, the POSIX thread ID remains live after the */
401 /* pthread_exit() call until pthread_join() is called. */
bart324a23b2009-02-15 12:14:52 +0000402 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
bart3772a982008-03-15 08:11:03 +0000403 }
sewardjaf44c822007-11-25 14:01:38 +0000404}
405
bart9b2974a2008-09-27 12:35:31 +0000406/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000407void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000408{
409 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
410 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000411 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000412
bart324a23b2009-02-15 12:14:52 +0000413 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000414}
415
bart62a784c2009-02-15 13:11:14 +0000416void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000417{
bart74a5f212008-05-11 06:43:07 +0000418 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000419 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000420 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID);
bart3772a982008-03-15 08:11:03 +0000421 tl_assert(ptid != INVALID_POSIX_THREADID);
bart324a23b2009-02-15 12:14:52 +0000422 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
423 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000424}
425
bart62a784c2009-02-15 13:11:14 +0000426Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
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);
bart324a23b2009-02-15 12:14:52 +0000430 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000431}
432
bart62a784c2009-02-15 13:11:14 +0000433void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000434{
bart74a5f212008-05-11 06:43:07 +0000435 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000436 && tid != DRD_INVALID_THREADID);
437 tl_assert(!! joinable == joinable);
bart324a23b2009-02-15 12:14:52 +0000438 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000439#if 0
bart3772a982008-03-15 08:11:03 +0000440 VG_(message)(Vg_DebugMsg,
441 "thread_set_joinable(%d/%d, %s)",
442 tid,
bart324a23b2009-02-15 12:14:52 +0000443 DRD_(g_threadinfo)[tid].vg_threadid,
bart3772a982008-03-15 08:11:03 +0000444 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000445#endif
bart324a23b2009-02-15 12:14:52 +0000446 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000447}
448
bart62a784c2009-02-15 13:11:14 +0000449void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000450{
bart3772a982008-03-15 08:11:03 +0000451 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000452
bart324a23b2009-02-15 12:14:52 +0000453 if (vg_tid != DRD_(s_vg_running_tid))
bart3772a982008-03-15 08:11:03 +0000454 {
bart62a784c2009-02-15 13:11:14 +0000455 DRD_(thread_set_running_tid)(vg_tid,
456 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
bart3772a982008-03-15 08:11:03 +0000457 }
sewardj8b09d4f2007-12-04 21:27:18 +0000458
bart324a23b2009-02-15 12:14:52 +0000459 tl_assert(DRD_(s_vg_running_tid) != VG_INVALID_THREADID);
460 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000461}
462
bart62a784c2009-02-15 13:11:14 +0000463void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
464 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000465{
bart3772a982008-03-15 08:11:03 +0000466 tl_assert(vg_tid != VG_INVALID_THREADID);
467 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000468
bart324a23b2009-02-15 12:14:52 +0000469 if (vg_tid != DRD_(s_vg_running_tid))
bart3772a982008-03-15 08:11:03 +0000470 {
bart324a23b2009-02-15 12:14:52 +0000471 if (DRD_(s_trace_context_switches)
472 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
bart3772a982008-03-15 08:11:03 +0000473 {
474 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000475 "Context switch from thread %d/%d to thread %d/%d;"
476 " segments: %llu",
bart324a23b2009-02-15 12:14:52 +0000477 DRD_(s_vg_running_tid), DRD_(g_drd_running_tid),
bart62a784c2009-02-15 13:11:14 +0000478 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
bart62ada3f2009-02-14 17:19:58 +0000479 DRD_(sg_get_segments_alive_count)());
bart3772a982008-03-15 08:11:03 +0000480 }
bart324a23b2009-02-15 12:14:52 +0000481 DRD_(s_vg_running_tid) = vg_tid;
482 DRD_(g_drd_running_tid) = drd_tid;
bart62a784c2009-02-15 13:11:14 +0000483 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set), drd_tid);
bart324a23b2009-02-15 12:14:52 +0000484 DRD_(s_context_switch_count)++;
bart3772a982008-03-15 08:11:03 +0000485 }
sewardj8b09d4f2007-12-04 21:27:18 +0000486
bart324a23b2009-02-15 12:14:52 +0000487 tl_assert(DRD_(s_vg_running_tid) != VG_INVALID_THREADID);
488 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000489}
490
bart62a784c2009-02-15 13:11:14 +0000491int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000492{
bart62a784c2009-02-15 13:11:14 +0000493 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000494 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000495}
496
bart62a784c2009-02-15 13:11:14 +0000497int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000498{
bart62a784c2009-02-15 13:11:14 +0000499 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000500 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
501 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000502}
503
bart62a784c2009-02-15 13:11:14 +0000504int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000505{
bart62a784c2009-02-15 13:11:14 +0000506 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000507 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000508}
509
bart1a473c72008-03-13 19:03:38 +0000510/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000511static
512void DRD_(thread_append_segment)(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000513{
bart74a5f212008-05-11 06:43:07 +0000514 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000515 && tid != DRD_INVALID_THREADID);
bart62a784c2009-02-15 13:11:14 +0000516 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart324a23b2009-02-15 12:14:52 +0000517 sg->prev = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +0000518 sg->next = 0;
bart324a23b2009-02-15 12:14:52 +0000519 if (DRD_(g_threadinfo)[tid].last)
520 DRD_(g_threadinfo)[tid].last->next = sg;
521 DRD_(g_threadinfo)[tid].last = sg;
522 if (DRD_(g_threadinfo)[tid].first == 0)
523 DRD_(g_threadinfo)[tid].first = sg;
bart62a784c2009-02-15 13:11:14 +0000524 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000525}
526
bart324a23b2009-02-15 12:14:52 +0000527/**
528 * Remove a segment from the segment list of thread threadid, and free the
529 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000530 */
bart62a784c2009-02-15 13:11:14 +0000531static
532void DRD_(thread_discard_segment)(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000533{
bart74a5f212008-05-11 06:43:07 +0000534 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000535 && tid != DRD_INVALID_THREADID);
bart62a784c2009-02-15 13:11:14 +0000536 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart26f73e12008-02-24 18:37:08 +0000537
bart3772a982008-03-15 08:11:03 +0000538 if (sg->prev)
539 sg->prev->next = sg->next;
540 if (sg->next)
541 sg->next->prev = sg->prev;
bart324a23b2009-02-15 12:14:52 +0000542 if (sg == DRD_(g_threadinfo)[tid].first)
543 DRD_(g_threadinfo)[tid].first = sg->next;
544 if (sg == DRD_(g_threadinfo)[tid].last)
545 DRD_(g_threadinfo)[tid].last = sg->prev;
bart62ada3f2009-02-14 17:19:58 +0000546 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000547
bart62a784c2009-02-15 13:11:14 +0000548 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000549}
550
bart62a784c2009-02-15 13:11:14 +0000551VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000552{
bart74a5f212008-05-11 06:43:07 +0000553 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
554 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000555 tl_assert(DRD_(g_threadinfo)[tid].last);
556 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000557}
558
bart324a23b2009-02-15 12:14:52 +0000559/**
560 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000561 */
bart62a784c2009-02-15 13:11:14 +0000562void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000563{
564 tl_assert(sg);
bart74a5f212008-05-11 06:43:07 +0000565 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
566 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000567 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000568
bart62ada3f2009-02-14 17:19:58 +0000569 DRD_(sg_put)(*sg);
bart324a23b2009-02-15 12:14:52 +0000570 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000571}
572
sewardjaf44c822007-11-25 14:01:38 +0000573/**
574 * Compute the minimum of all latest vector clocks of all threads
575 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
576 * @param vc pointer to a vectorclock, holds result upon return.
577 */
bart62a784c2009-02-15 13:11:14 +0000578static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000579{
bart3772a982008-03-15 08:11:03 +0000580 unsigned i;
581 Bool first;
582 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000583
bart3772a982008-03-15 08:11:03 +0000584 first = True;
bart62a784c2009-02-15 13:11:14 +0000585 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
586 i++)
bart3772a982008-03-15 08:11:03 +0000587 {
bart324a23b2009-02-15 12:14:52 +0000588 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000589 if (latest_sg)
590 {
591 if (first)
bart41b226c2009-02-14 16:55:19 +0000592 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000593 else
bart41b226c2009-02-14 16:55:19 +0000594 DRD_(vc_min)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000595 first = False;
596 }
597 }
sewardjaf44c822007-11-25 14:01:38 +0000598}
599
bart62a784c2009-02-15 13:11:14 +0000600static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000601{
bart3772a982008-03-15 08:11:03 +0000602 unsigned i;
603 Bool first;
604 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000605
bart3772a982008-03-15 08:11:03 +0000606 first = True;
bart62a784c2009-02-15 13:11:14 +0000607 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
608 i++)
bart3772a982008-03-15 08:11:03 +0000609 {
bart324a23b2009-02-15 12:14:52 +0000610 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000611 if (latest_sg)
612 {
613 if (first)
bart41b226c2009-02-14 16:55:19 +0000614 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000615 else
bart41b226c2009-02-14 16:55:19 +0000616 DRD_(vc_combine)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000617 first = False;
618 }
619 }
sewardjaf44c822007-11-25 14:01:38 +0000620}
621
622/**
bart5bd9f2d2008-03-03 20:31:58 +0000623 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000624 * clock of every thread -- these segments can no longer be involved in a
625 * data race.
626 */
bart62a784c2009-02-15 13:11:14 +0000627static void DRD_(thread_discard_ordered_segments)(void)
sewardjaf44c822007-11-25 14:01:38 +0000628{
bart3772a982008-03-15 08:11:03 +0000629 unsigned i;
630 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000631
bart324a23b2009-02-15 12:14:52 +0000632 DRD_(s_discard_ordered_segments_count)++;
sewardjaf44c822007-11-25 14:01:38 +0000633
bart41b226c2009-02-14 16:55:19 +0000634 DRD_(vc_init)(&thread_vc_min, 0, 0);
bart62a784c2009-02-15 13:11:14 +0000635 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
bart62ada3f2009-02-14 17:19:58 +0000636 if (DRD_(sg_get_trace)())
bart3772a982008-03-15 08:11:03 +0000637 {
638 char msg[256];
639 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000640
bart41b226c2009-02-14 16:55:19 +0000641 DRD_(vc_init)(&thread_vc_max, 0, 0);
bart62a784c2009-02-15 13:11:14 +0000642 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart3772a982008-03-15 08:11:03 +0000643 VG_(snprintf)(msg, sizeof(msg),
644 "Discarding ordered segments -- min vc is ");
bart41b226c2009-02-14 16:55:19 +0000645 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
646 &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000647 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
648 ", max vc is ");
bart41b226c2009-02-14 16:55:19 +0000649 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
650 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000651 VG_(message)(Vg_UserMsg, "%s", msg);
bart41b226c2009-02-14 16:55:19 +0000652 DRD_(vc_cleanup)(&thread_vc_max);
bart3772a982008-03-15 08:11:03 +0000653 }
sewardjaf44c822007-11-25 14:01:38 +0000654
bart62a784c2009-02-15 13:11:14 +0000655 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
656 i++)
bart3772a982008-03-15 08:11:03 +0000657 {
658 Segment* sg;
659 Segment* sg_next;
bart324a23b2009-02-15 12:14:52 +0000660 for (sg = DRD_(g_threadinfo)[i].first;
bart41b226c2009-02-14 16:55:19 +0000661 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000662 sg = sg_next)
663 {
bart62a784c2009-02-15 13:11:14 +0000664 DRD_(thread_discard_segment)(i, sg);
bart3772a982008-03-15 08:11:03 +0000665 }
666 }
bart41b226c2009-02-14 16:55:19 +0000667 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000668}
669
bart324a23b2009-02-15 12:14:52 +0000670/**
671 * Merge all segments that may be merged without triggering false positives
672 * or discarding real data races. For the theoretical background of segment
673 * merging, see also the following paper:
674 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
675 * Bounding the number of segment histories during data race detection.
676 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
677 * September 2002.
barta9c37392008-03-22 09:38:48 +0000678 */
679static void thread_merge_segments(void)
680{
681 unsigned i;
682
bart62a784c2009-02-15 13:11:14 +0000683 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
684 i++)
barta9c37392008-03-22 09:38:48 +0000685 {
686 Segment* sg;
687
bart62a784c2009-02-15 13:11:14 +0000688 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000689
bart324a23b2009-02-15 12:14:52 +0000690 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000691 {
bart62ada3f2009-02-14 17:19:58 +0000692 if (DRD_(sg_get_refcnt)(sg) == 1
barta9c37392008-03-22 09:38:48 +0000693 && sg->next
bart62ada3f2009-02-14 17:19:58 +0000694 && DRD_(sg_get_refcnt)(sg->next) == 1
barta9c37392008-03-22 09:38:48 +0000695 && sg->next->next)
696 {
697 /* Merge sg and sg->next into sg. */
bart62ada3f2009-02-14 17:19:58 +0000698 DRD_(sg_merge)(sg, sg->next);
bart62a784c2009-02-15 13:11:14 +0000699 DRD_(thread_discard_segment)(i, sg->next);
barta9c37392008-03-22 09:38:48 +0000700 }
701 }
702
bart62a784c2009-02-15 13:11:14 +0000703 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000704 }
705}
706
bart324a23b2009-02-15 12:14:52 +0000707/**
708 * Every change in the vector clock of a thread may cause segments that
709 * were previously ordered to this thread to become unordered. Hence,
710 * it may be necessary to recalculate the conflict set if the vector clock
711 * of the current thread is updated. This function check whether such a
712 * recalculation is necessary.
bartd66e3a82008-04-06 15:02:17 +0000713 *
bart324a23b2009-02-15 12:14:52 +0000714 * @param tid Thread ID of the thread to which a new segment has been
715 * appended.
716 * @param new_sg Pointer to the most recent segment of thread tid.
bartd66e3a82008-04-06 15:02:17 +0000717 */
barte73b0aa2008-06-28 07:19:56 +0000718static Bool conflict_set_update_needed(const DrdThreadId tid,
bart41b226c2009-02-14 16:55:19 +0000719 const Segment* const new_sg)
bartd66e3a82008-04-06 15:02:17 +0000720{
bart5d421ba2008-04-19 15:15:12 +0000721#if 0
bartd66e3a82008-04-06 15:02:17 +0000722 unsigned i;
723 const Segment* old_sg;
724
725 tl_assert(new_sg);
726
727 /* If a new segment was added to another thread than the running thread, */
barte73b0aa2008-06-28 07:19:56 +0000728 /* just tell the caller to update the conflict set. */
bart324a23b2009-02-15 12:14:52 +0000729 if (tid != DRD_(g_drd_running_tid))
bartd66e3a82008-04-06 15:02:17 +0000730 return True;
731
barte73b0aa2008-06-28 07:19:56 +0000732 /* Always let the caller update the conflict set after creation of the */
bartd66e3a82008-04-06 15:02:17 +0000733 /* first segment. */
734 old_sg = new_sg->prev;
735 if (old_sg == 0)
736 return True;
737
bart62a784c2009-02-15 13:11:14 +0000738 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
739 i++)
bartd66e3a82008-04-06 15:02:17 +0000740 {
741 Segment* q;
742
bart324a23b2009-02-15 12:14:52 +0000743 if (i == DRD_(g_drd_running_tid))
bartd66e3a82008-04-06 15:02:17 +0000744 continue;
745
bart324a23b2009-02-15 12:14:52 +0000746 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000747 {
748 /* If the expression below evaluates to false, this expression will */
749 /* also evaluate to false for all subsequent iterations. So stop */
750 /* iterating. */
bart41b226c2009-02-14 16:55:19 +0000751 if (DRD_(vc_lte)(&q->vc, &old_sg->vc))
bartd66e3a82008-04-06 15:02:17 +0000752 break;
753 /* If the vector clock of the 2nd the last segment is not ordered */
754 /* to the vector clock of segment q, and the last segment is, ask */
barte73b0aa2008-06-28 07:19:56 +0000755 /* the caller to update the conflict set. */
bart41b226c2009-02-14 16:55:19 +0000756 if (! DRD_(vc_lte)(&old_sg->vc, &q->vc))
bartd66e3a82008-04-06 15:02:17 +0000757 {
758 return True;
759 }
760 /* If the vector clock of the last segment is not ordered to the */
barte73b0aa2008-06-28 07:19:56 +0000761 /* vector clock of segment q, ask the caller to update the conflict */
bartd66e3a82008-04-06 15:02:17 +0000762 /* set. */
bart41b226c2009-02-14 16:55:19 +0000763 if (! DRD_(vc_lte)(&q->vc, &new_sg->vc) && ! DRD_(vc_lte)(&new_sg->vc, &q->vc))
bartd66e3a82008-04-06 15:02:17 +0000764 {
765 return True;
766 }
767 }
768 }
769
770 return False;
bart5d421ba2008-04-19 15:15:12 +0000771#else
772 return True;
773#endif
bartd66e3a82008-04-06 15:02:17 +0000774}
775
bart324a23b2009-02-15 12:14:52 +0000776/**
777 * Create a new segment for the specified thread, and discard any segments
778 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000779 */
bart62a784c2009-02-15 13:11:14 +0000780void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000781{
bartd66e3a82008-04-06 15:02:17 +0000782 Segment* new_sg;
783
bart74a5f212008-05-11 06:43:07 +0000784 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
785 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000786
bart62ada3f2009-02-14 17:19:58 +0000787 new_sg = DRD_(sg_new)(tid, tid);
bart62a784c2009-02-15 13:11:14 +0000788 DRD_(thread_append_segment)(tid, new_sg);
bartd66e3a82008-04-06 15:02:17 +0000789
barte73b0aa2008-06-28 07:19:56 +0000790 if (conflict_set_update_needed(tid, new_sg))
bartd66e3a82008-04-06 15:02:17 +0000791 {
bart62a784c2009-02-15 13:11:14 +0000792 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set),
793 DRD_(g_drd_running_tid));
bart324a23b2009-02-15 12:14:52 +0000794 DRD_(s_conflict_set_new_segment_count)++;
bartd66e3a82008-04-06 15:02:17 +0000795 }
bart324a23b2009-02-15 12:14:52 +0000796 else if (tid == DRD_(g_drd_running_tid))
bart82195c12008-04-13 17:35:08 +0000797 {
bart62a784c2009-02-15 13:11:14 +0000798 tl_assert(DRD_(thread_conflict_set_up_to_date)(DRD_(g_drd_running_tid)));
bart82195c12008-04-13 17:35:08 +0000799 }
sewardjaf44c822007-11-25 14:01:38 +0000800
bart62a784c2009-02-15 13:11:14 +0000801 DRD_(thread_discard_ordered_segments)();
bart26f73e12008-02-24 18:37:08 +0000802
bart324a23b2009-02-15 12:14:52 +0000803 if (DRD_(s_segment_merging))
804 {
barta9c37392008-03-22 09:38:48 +0000805 thread_merge_segments();
bart324a23b2009-02-15 12:14:52 +0000806 }
sewardjaf44c822007-11-25 14:01:38 +0000807}
808
bart26f73e12008-02-24 18:37:08 +0000809/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart62a784c2009-02-15 13:11:14 +0000810void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000811{
bart3772a982008-03-15 08:11:03 +0000812 tl_assert(joiner != joinee);
bart74a5f212008-05-11 06:43:07 +0000813 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000814 && joiner != DRD_INVALID_THREADID);
bart74a5f212008-05-11 06:43:07 +0000815 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000816 && joinee != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000817 tl_assert(DRD_(g_threadinfo)[joiner].last);
818 tl_assert(DRD_(g_threadinfo)[joinee].last);
819 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
820 &DRD_(g_threadinfo)[joinee].last->vc);
bart62a784c2009-02-15 13:11:14 +0000821 DRD_(thread_discard_ordered_segments)();
sewardjaf44c822007-11-25 14:01:38 +0000822
bart324a23b2009-02-15 12:14:52 +0000823 if (joiner == DRD_(g_drd_running_tid))
bart3772a982008-03-15 08:11:03 +0000824 {
bart62a784c2009-02-15 13:11:14 +0000825 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set), joiner);
bart3772a982008-03-15 08:11:03 +0000826 }
sewardjaf44c822007-11-25 14:01:38 +0000827}
828
bart324a23b2009-02-15 12:14:52 +0000829/**
830 * Call this function after thread 'tid' had to wait because of thread
831 * synchronization until the memory accesses in the segment with vector clock
832 * 'vc' finished.
bart26f73e12008-02-24 18:37:08 +0000833 */
bart62a784c2009-02-15 13:11:14 +0000834void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc)
sewardjaf44c822007-11-25 14:01:38 +0000835{
bart74a5f212008-05-11 06:43:07 +0000836 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
837 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000838 tl_assert(DRD_(g_threadinfo)[tid].last);
bart3772a982008-03-15 08:11:03 +0000839 tl_assert(vc);
bart324a23b2009-02-15 12:14:52 +0000840 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
bart62a784c2009-02-15 13:11:14 +0000841 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set), tid);
842 DRD_(thread_discard_ordered_segments)();
bart324a23b2009-02-15 12:14:52 +0000843 DRD_(s_conflict_set_combine_vc_count)++;
sewardjaf44c822007-11-25 14:01:38 +0000844}
845
bart324a23b2009-02-15 12:14:52 +0000846/**
847 * Call this function whenever a thread is no longer using the memory
848 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
849 * increase.
bart26f73e12008-02-24 18:37:08 +0000850 */
bart62a784c2009-02-15 13:11:14 +0000851void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000852{
bartd43f8d32008-03-16 17:29:20 +0000853 DrdThreadId other_user;
854 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000855
bart3772a982008-03-15 08:11:03 +0000856 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000857 other_user = DRD_INVALID_THREADID;
bart62a784c2009-02-15 13:11:14 +0000858 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
859 i++)
bart3772a982008-03-15 08:11:03 +0000860 {
861 Segment* p;
bart324a23b2009-02-15 12:14:52 +0000862 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +0000863 {
864 if (other_user == DRD_INVALID_THREADID
bart324a23b2009-02-15 12:14:52 +0000865 && i != DRD_(g_drd_running_tid))
sewardjaf44c822007-11-25 14:01:38 +0000866 {
bart99edb292009-02-15 15:59:20 +0000867 if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2)))
bart8bf2f8b2008-03-30 17:56:43 +0000868 {
869 other_user = i;
870 }
871 continue;
sewardjaf44c822007-11-25 14:01:38 +0000872 }
bart99edb292009-02-15 15:59:20 +0000873 DRD_(bm_clear)(p->bm, a1, a2);
bart3772a982008-03-15 08:11:03 +0000874 }
875 }
sewardjaf44c822007-11-25 14:01:38 +0000876
bart324a23b2009-02-15 12:14:52 +0000877 /*
878 * If any other thread had accessed memory in [ a1, a2 [, update the
879 * conflict set.
880 */
bart3772a982008-03-15 08:11:03 +0000881 if (other_user != DRD_INVALID_THREADID
bart99edb292009-02-15 15:59:20 +0000882 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
bart3772a982008-03-15 08:11:03 +0000883 {
bart62a784c2009-02-15 13:11:14 +0000884 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set),
885 DRD_(thread_get_running_tid)());
bart3772a982008-03-15 08:11:03 +0000886 }
sewardjaf44c822007-11-25 14:01:38 +0000887}
888
bart62a784c2009-02-15 13:11:14 +0000889void DRD_(thread_start_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000890{
bart74a5f212008-05-11 06:43:07 +0000891 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
892 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000893 tl_assert(! DRD_(g_threadinfo)[tid].is_recording);
894 DRD_(g_threadinfo)[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000895}
896
bart62a784c2009-02-15 13:11:14 +0000897void DRD_(thread_stop_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000898{
bart74a5f212008-05-11 06:43:07 +0000899 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
900 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000901 tl_assert(DRD_(g_threadinfo)[tid].is_recording);
902 DRD_(g_threadinfo)[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000903}
904
bart62a784c2009-02-15 13:11:14 +0000905void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +0000906{
bart3772a982008-03-15 08:11:03 +0000907 unsigned i;
908 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000909
bart62a784c2009-02-15 13:11:14 +0000910 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
911 i++)
bart3772a982008-03-15 08:11:03 +0000912 {
bart324a23b2009-02-15 12:14:52 +0000913 if (DRD_(g_threadinfo)[i].first)
bart3772a982008-03-15 08:11:03 +0000914 {
915 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000916 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000917 "**************\n",
918 i,
bart324a23b2009-02-15 12:14:52 +0000919 DRD_(g_threadinfo)[i].vg_thread_exists,
920 DRD_(g_threadinfo)[i].vg_threadid,
921 DRD_(g_threadinfo)[i].posix_thread_exists,
922 DRD_(g_threadinfo)[i].pt_threadid,
923 DRD_(g_threadinfo)[i].detached_posix_thread);
924 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000925 {
bart62ada3f2009-02-14 17:19:58 +0000926 DRD_(sg_print)(p);
sewardjaf44c822007-11-25 14:01:38 +0000927 }
bart3772a982008-03-15 08:11:03 +0000928 }
929 }
sewardjaf44c822007-11-25 14:01:38 +0000930}
931
932static void show_call_stack(const DrdThreadId tid,
933 const Char* const msg,
934 ExeContext* const callstack)
935{
bart62a784c2009-02-15 13:11:14 +0000936 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +0000937
bartaa97a542008-03-16 17:57:01 +0000938 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000939
bart3772a982008-03-15 08:11:03 +0000940 if (vg_tid != VG_INVALID_THREADID)
941 {
942 if (callstack)
943 {
944 VG_(pp_ExeContext)(callstack);
945 }
946 else
947 {
948 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
949 }
950 }
951 else
952 {
953 VG_(message)(Vg_UserMsg,
954 " (thread finished, call stack no longer available)");
955 }
sewardjaf44c822007-11-25 14:01:38 +0000956}
957
sewardjaf44c822007-11-25 14:01:38 +0000958static void
959thread_report_conflicting_segments_segment(const DrdThreadId tid,
960 const Addr addr,
961 const SizeT size,
962 const BmAccessTypeT access_type,
963 const Segment* const p)
964{
bart3772a982008-03-15 08:11:03 +0000965 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000966
bart74a5f212008-05-11 06:43:07 +0000967 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000968 && tid != DRD_INVALID_THREADID);
969 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000970
bart62a784c2009-02-15 13:11:14 +0000971 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
972 i++)
bart3772a982008-03-15 08:11:03 +0000973 {
974 if (i != tid)
975 {
976 Segment* q;
bart324a23b2009-02-15 12:14:52 +0000977 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000978 {
bart324a23b2009-02-15 12:14:52 +0000979 /*
980 * Since q iterates over the segments of thread i in order of
981 * decreasing vector clocks, if q->vc <= p->vc, then
982 * q->next->vc <= p->vc will also hold. Hence, break out of the
983 * loop once this condition is met.
984 */
bart41b226c2009-02-14 16:55:19 +0000985 if (DRD_(vc_lte)(&q->vc, &p->vc))
bart3772a982008-03-15 08:11:03 +0000986 break;
bart41b226c2009-02-14 16:55:19 +0000987 if (! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000988 {
bart99edb292009-02-15 15:59:20 +0000989 if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size,
990 access_type))
bart3772a982008-03-15 08:11:03 +0000991 {
992 tl_assert(q->stacktrace);
993 show_call_stack(i, "Other segment start",
994 q->stacktrace);
995 show_call_stack(i, "Other segment end",
996 q->next ? q->next->stacktrace : 0);
997 }
998 }
sewardjaf44c822007-11-25 14:01:38 +0000999 }
bart3772a982008-03-15 08:11:03 +00001000 }
1001 }
sewardjaf44c822007-11-25 14:01:38 +00001002}
1003
bart62a784c2009-02-15 13:11:14 +00001004void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1005 const Addr addr,
1006 const SizeT size,
1007 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001008{
bart3772a982008-03-15 08:11:03 +00001009 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001010
bart74a5f212008-05-11 06:43:07 +00001011 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +00001012 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001013
bart324a23b2009-02-15 12:14:52 +00001014 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +00001015 {
bart99edb292009-02-15 15:59:20 +00001016 if (DRD_(bm_has)(p->bm, addr, addr + size, access_type))
bart3772a982008-03-15 08:11:03 +00001017 {
1018 thread_report_conflicting_segments_segment(tid, addr, size,
1019 access_type, p);
1020 }
1021 }
sewardjaf44c822007-11-25 14:01:38 +00001022}
sewardjaf44c822007-11-25 14:01:38 +00001023
bart324a23b2009-02-15 12:14:52 +00001024/**
1025 * Verify whether the conflict set for thread tid is up to date. Only perform
1026 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
bart82195c12008-04-13 17:35:08 +00001027 */
bart62a784c2009-02-15 13:11:14 +00001028static Bool DRD_(thread_conflict_set_up_to_date)(const DrdThreadId tid)
bart82195c12008-04-13 17:35:08 +00001029{
barte73b0aa2008-06-28 07:19:56 +00001030 static int do_verify_conflict_set = -1;
bart82195c12008-04-13 17:35:08 +00001031 Bool result;
barte73b0aa2008-06-28 07:19:56 +00001032 struct bitmap* computed_conflict_set = 0;
bart82195c12008-04-13 17:35:08 +00001033
barte73b0aa2008-06-28 07:19:56 +00001034 if (do_verify_conflict_set < 0)
bart82195c12008-04-13 17:35:08 +00001035 {
barte73b0aa2008-06-28 07:19:56 +00001036 //VG_(message)(Vg_DebugMsg, "%s", VG_(getenv)("DRD_VERIFY_CONFLICT_SET"));
1037 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
bart82195c12008-04-13 17:35:08 +00001038 }
barte73b0aa2008-06-28 07:19:56 +00001039 if (do_verify_conflict_set == 0)
bart82195c12008-04-13 17:35:08 +00001040 return True;
1041
bart62a784c2009-02-15 13:11:14 +00001042 DRD_(thread_compute_conflict_set)(&computed_conflict_set, tid);
bart99edb292009-02-15 15:59:20 +00001043 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1044 DRD_(bm_delete)(computed_conflict_set);
bart82195c12008-04-13 17:35:08 +00001045 return result;
1046}
1047
bart324a23b2009-02-15 12:14:52 +00001048/**
1049 * Compute a bitmap that represents the union of all memory accesses of all
1050 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001051 */
bart62a784c2009-02-15 13:11:14 +00001052static void DRD_(thread_compute_conflict_set)(struct bitmap** conflict_set,
1053 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001054{
bart3772a982008-03-15 08:11:03 +00001055 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001056
bart74a5f212008-05-11 06:43:07 +00001057 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1058 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +00001059 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001060
bart324a23b2009-02-15 12:14:52 +00001061 DRD_(s_update_conflict_set_count)++;
bart99edb292009-02-15 15:59:20 +00001062 DRD_(s_conflict_set_bitmap_creation_count) -= DRD_(bm_get_bitmap_creation_count)();
1063 DRD_(s_conflict_set_bitmap2_creation_count) -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001064
barte73b0aa2008-06-28 07:19:56 +00001065 if (*conflict_set)
bart3772a982008-03-15 08:11:03 +00001066 {
bart99edb292009-02-15 15:59:20 +00001067 DRD_(bm_delete)(*conflict_set);
bart3772a982008-03-15 08:11:03 +00001068 }
bart99edb292009-02-15 15:59:20 +00001069 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001070
bart324a23b2009-02-15 12:14:52 +00001071 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001072 {
1073 char msg[256];
1074
1075 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001076 "computing conflict set for thread %d/%d with vc ",
bart62a784c2009-02-15 13:11:14 +00001077 DRD_(DrdThreadIdToVgThreadId)(tid), tid);
bart41b226c2009-02-14 16:55:19 +00001078 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1079 sizeof(msg) - VG_(strlen)(msg),
bart324a23b2009-02-15 12:14:52 +00001080 &DRD_(g_threadinfo)[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +00001081 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001082 }
1083
bart324a23b2009-02-15 12:14:52 +00001084 p = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +00001085 {
1086 unsigned j;
1087
bart324a23b2009-02-15 12:14:52 +00001088 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001089 {
bart26f73e12008-02-24 18:37:08 +00001090 char msg[256];
1091
1092 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001093 "conflict set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +00001094 tid);
bart41b226c2009-02-14 16:55:19 +00001095 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1096 sizeof(msg) - VG_(strlen)(msg),
1097 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +00001098 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001099 }
sewardjaf44c822007-11-25 14:01:38 +00001100
bart324a23b2009-02-15 12:14:52 +00001101 for (j = 0; j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); j++)
bart3772a982008-03-15 08:11:03 +00001102 {
bart62a784c2009-02-15 13:11:14 +00001103 if (j != tid && DRD_(IsValidDrdThreadId)(j))
bart26f73e12008-02-24 18:37:08 +00001104 {
bart3772a982008-03-15 08:11:03 +00001105 const Segment* q;
bart324a23b2009-02-15 12:14:52 +00001106 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +00001107 {
bart41b226c2009-02-14 16:55:19 +00001108 if (! DRD_(vc_lte)(&q->vc, &p->vc) && ! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +00001109 {
bart324a23b2009-02-15 12:14:52 +00001110 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001111 {
1112 char msg[256];
1113 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001114 "conflict set: [%d] merging segment ", j);
bart41b226c2009-02-14 16:55:19 +00001115 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1116 sizeof(msg) - VG_(strlen)(msg),
1117 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001118 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001119 }
bart99edb292009-02-15 15:59:20 +00001120 DRD_(bm_merge2)(*conflict_set, q->bm);
bart3772a982008-03-15 08:11:03 +00001121 }
1122 else
1123 {
bart324a23b2009-02-15 12:14:52 +00001124 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001125 {
1126 char msg[256];
1127 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001128 "conflict set: [%d] ignoring segment ", j);
bart41b226c2009-02-14 16:55:19 +00001129 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1130 sizeof(msg) - VG_(strlen)(msg),
1131 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001132 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001133 }
1134 }
bartd66e3a82008-04-06 15:02:17 +00001135 }
bart26f73e12008-02-24 18:37:08 +00001136 }
bart3772a982008-03-15 08:11:03 +00001137 }
bart3772a982008-03-15 08:11:03 +00001138 }
sewardjaf44c822007-11-25 14:01:38 +00001139
bart99edb292009-02-15 15:59:20 +00001140 DRD_(s_conflict_set_bitmap_creation_count) += DRD_(bm_get_bitmap_creation_count)();
1141 DRD_(s_conflict_set_bitmap2_creation_count) += DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001142
bart324a23b2009-02-15 12:14:52 +00001143 if (0 && DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001144 {
barte73b0aa2008-06-28 07:19:56 +00001145 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
bart99edb292009-02-15 15:59:20 +00001146 DRD_(bm_print)(*conflict_set);
barte73b0aa2008-06-28 07:19:56 +00001147 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
bart3772a982008-03-15 08:11:03 +00001148 }
sewardjaf44c822007-11-25 14:01:38 +00001149}
1150
bart62a784c2009-02-15 13:11:14 +00001151ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001152{
bart324a23b2009-02-15 12:14:52 +00001153 return DRD_(s_context_switch_count);
sewardjaf44c822007-11-25 14:01:38 +00001154}
1155
bart62a784c2009-02-15 13:11:14 +00001156ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001157{
bart324a23b2009-02-15 12:14:52 +00001158 return DRD_(s_discard_ordered_segments_count);
sewardjaf44c822007-11-25 14:01:38 +00001159}
1160
bart62a784c2009-02-15 13:11:14 +00001161ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001162{
bartd66e3a82008-04-06 15:02:17 +00001163 tl_assert(dsnsc);
1164 tl_assert(dscvc);
bart324a23b2009-02-15 12:14:52 +00001165 *dsnsc = DRD_(s_conflict_set_new_segment_count);
1166 *dscvc = DRD_(s_conflict_set_combine_vc_count);
1167 return DRD_(s_update_conflict_set_count);
sewardjaf44c822007-11-25 14:01:38 +00001168}
1169
bart62a784c2009-02-15 13:11:14 +00001170ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001171{
bart324a23b2009-02-15 12:14:52 +00001172 return DRD_(s_conflict_set_bitmap_creation_count);
sewardjaf44c822007-11-25 14:01:38 +00001173}
1174
bart62a784c2009-02-15 13:11:14 +00001175ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001176{
bart324a23b2009-02-15 12:14:52 +00001177 return DRD_(s_conflict_set_bitmap2_creation_count);
sewardjaf44c822007-11-25 14:01:38 +00001178}