blob: aeacbfa620f406e0dae541ebc966f5e10719b35e [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"
27#include "drd_cond.h"
28#include "drd_mutex.h"
sewardjaf44c822007-11-25 14:01:38 +000029#include "drd_segment.h"
bart09dc13f2009-02-14 15:13:31 +000030#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000031#include "drd_suppression.h"
32#include "drd_thread.h"
bart82195c12008-04-13 17:35:08 +000033#include "pub_tool_vki.h"
sewardjaf44c822007-11-25 14:01:38 +000034#include "pub_tool_basics.h" // Addr, SizeT
35#include "pub_tool_errormgr.h" // VG_(unique_error)()
36#include "pub_tool_libcassert.h" // tl_assert()
37#include "pub_tool_libcbase.h" // VG_(strlen)()
38#include "pub_tool_libcprint.h" // VG_(printf)()
bart82195c12008-04-13 17:35:08 +000039#include "pub_tool_libcproc.h" // VG_(getenv)()
sewardjaf44c822007-11-25 14:01:38 +000040#include "pub_tool_machine.h"
41#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
sewardj85642922008-01-14 11:54:56 +000042#include "pub_tool_options.h" // VG_(clo_backtrace_size)
sewardjaf44c822007-11-25 14:01:38 +000043#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
44
bart32ba2082008-06-05 08:53:42 +000045
sewardjaf44c822007-11-25 14:01:38 +000046
bart324a23b2009-02-15 12:14:52 +000047/* Local functions. */
sewardjaf44c822007-11-25 14:01:38 +000048
bart62a784c2009-02-15 13:11:14 +000049static void DRD_(thread_append_segment)(const DrdThreadId tid,
50 Segment* const sg);
51static void DRD_(thread_discard_segment)(const DrdThreadId tid,
52 Segment* const sg);
53static Bool DRD_(thread_conflict_set_up_to_date)(const DrdThreadId tid);
54static void DRD_(thread_compute_conflict_set)(struct bitmap** conflict_set,
55 const DrdThreadId tid);
sewardjaf44c822007-11-25 14:01:38 +000056
57
bart324a23b2009-02-15 12:14:52 +000058/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000059
bart324a23b2009-02-15 12:14:52 +000060static ULong DRD_(s_context_switch_count);
61static ULong DRD_(s_discard_ordered_segments_count);
62static ULong DRD_(s_update_conflict_set_count);
63static ULong DRD_(s_conflict_set_new_segment_count);
64static ULong DRD_(s_conflict_set_combine_vc_count);
65static ULong DRD_(s_conflict_set_bitmap_creation_count);
66static ULong DRD_(s_conflict_set_bitmap2_creation_count);
67static ThreadId DRD_(s_vg_running_tid) = VG_INVALID_THREADID;
68DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
69ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
70struct bitmap* DRD_(g_conflict_set);
71static Bool DRD_(s_trace_context_switches) = False;
72static Bool DRD_(s_trace_conflict_set) = False;
73static Bool DRD_(s_trace_fork_join) = False;
74static Bool DRD_(s_segment_merging) = True;
sewardjaf44c822007-11-25 14:01:38 +000075
76
bart324a23b2009-02-15 12:14:52 +000077/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000078
bart62a784c2009-02-15 13:11:14 +000079void DRD_(thread_trace_context_switches)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000080{
bart09dc13f2009-02-14 15:13:31 +000081 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +000082 DRD_(s_trace_context_switches) = t;
bart26f73e12008-02-24 18:37:08 +000083}
84
bart62a784c2009-02-15 13:11:14 +000085void DRD_(thread_trace_conflict_set)(const Bool t)
bart26f73e12008-02-24 18:37:08 +000086{
bart09dc13f2009-02-14 15:13:31 +000087 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +000088 DRD_(s_trace_conflict_set) = t;
bart26f73e12008-02-24 18:37:08 +000089}
90
bart09dc13f2009-02-14 15:13:31 +000091Bool DRD_(thread_get_trace_fork_join)(void)
92{
bart324a23b2009-02-15 12:14:52 +000093 return DRD_(s_trace_fork_join);
bart09dc13f2009-02-14 15:13:31 +000094}
95
96void DRD_(thread_set_trace_fork_join)(const Bool t)
97{
98 tl_assert(t == False || t == True);
bart324a23b2009-02-15 12:14:52 +000099 DRD_(s_trace_fork_join) = t;
bart09dc13f2009-02-14 15:13:31 +0000100}
101
bart62a784c2009-02-15 13:11:14 +0000102void DRD_(thread_set_segment_merging)(const Bool m)
barta9c37392008-03-22 09:38:48 +0000103{
bart09dc13f2009-02-14 15:13:31 +0000104 tl_assert(m == False || m == True);
bart324a23b2009-02-15 12:14:52 +0000105 DRD_(s_segment_merging) = m;
barta9c37392008-03-22 09:38:48 +0000106}
107
sewardjaf44c822007-11-25 14:01:38 +0000108/**
109 * Convert Valgrind's ThreadId into a DrdThreadId. Report failure if
110 * Valgrind's ThreadId does not yet exist.
bart324a23b2009-02-15 12:14:52 +0000111 */
bart62a784c2009-02-15 13:11:14 +0000112DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000113{
bart3772a982008-03-15 08:11:03 +0000114 int i;
sewardjaf44c822007-11-25 14:01:38 +0000115
bart3772a982008-03-15 08:11:03 +0000116 if (tid == VG_INVALID_THREADID)
117 return 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 {
bart324a23b2009-02-15 12:14:52 +0000121 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
122 && DRD_(g_threadinfo)[i].vg_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000123 {
124 return i;
125 }
126 }
sewardjaf44c822007-11-25 14:01:38 +0000127
bart3772a982008-03-15 08:11:03 +0000128 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000129}
130
bart62a784c2009-02-15 13:11:14 +0000131static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000132{
bart3772a982008-03-15 08:11:03 +0000133 int i;
sewardjaf44c822007-11-25 14:01:38 +0000134
bart62a784c2009-02-15 13:11:14 +0000135 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000136
bart3772a982008-03-15 08:11:03 +0000137 for (i = 1; i < DRD_N_THREADS; i++)
138 {
bart324a23b2009-02-15 12:14:52 +0000139 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
140 && DRD_(g_threadinfo)[i].posix_thread_exists == False
141 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
bart3772a982008-03-15 08:11:03 +0000142 {
bart324a23b2009-02-15 12:14:52 +0000143 DRD_(g_threadinfo)[i].vg_thread_exists = True;
144 DRD_(g_threadinfo)[i].vg_threadid = tid;
145 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
146 DRD_(g_threadinfo)[i].stack_min = 0;
147 DRD_(g_threadinfo)[i].stack_min_min = 0;
148 DRD_(g_threadinfo)[i].stack_startup = 0;
149 DRD_(g_threadinfo)[i].stack_max = 0;
150 DRD_(g_threadinfo)[i].is_recording = True;
151 DRD_(g_threadinfo)[i].synchr_nesting = 0;
152 if (DRD_(g_threadinfo)[i].first != 0)
bart3772a982008-03-15 08:11:03 +0000153 VG_(printf)("drd thread id = %d\n", i);
bart324a23b2009-02-15 12:14:52 +0000154 tl_assert(DRD_(g_threadinfo)[i].first == 0);
155 tl_assert(DRD_(g_threadinfo)[i].last == 0);
bart3772a982008-03-15 08:11:03 +0000156 return i;
157 }
158 }
sewardjaf44c822007-11-25 14:01:38 +0000159
bart3772a982008-03-15 08:11:03 +0000160 tl_assert(False);
sewardjaf44c822007-11-25 14:01:38 +0000161
bart3772a982008-03-15 08:11:03 +0000162 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000163}
164
bart62a784c2009-02-15 13:11:14 +0000165DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000166{
bart3772a982008-03-15 08:11:03 +0000167 int i;
sewardjaf44c822007-11-25 14:01:38 +0000168
bart3772a982008-03-15 08:11:03 +0000169 tl_assert(tid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000170
bart3772a982008-03-15 08:11:03 +0000171 for (i = 1; i < DRD_N_THREADS; i++)
172 {
bart324a23b2009-02-15 12:14:52 +0000173 if (DRD_(g_threadinfo)[i].posix_thread_exists
174 && DRD_(g_threadinfo)[i].pt_threadid == tid)
bart3772a982008-03-15 08:11:03 +0000175 {
176 return i;
177 }
178 }
179 return DRD_INVALID_THREADID;
sewardjaf44c822007-11-25 14:01:38 +0000180}
181
bart62a784c2009-02-15 13:11:14 +0000182ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000183{
bart74a5f212008-05-11 06:43:07 +0000184 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
185 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000186 return (DRD_(g_threadinfo)[tid].vg_thread_exists
187 ? DRD_(g_threadinfo)[tid].vg_threadid
bart3772a982008-03-15 08:11:03 +0000188 : VG_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000189}
190
bart23d3a4e2008-04-05 12:53:00 +0000191#if 0
bart324a23b2009-02-15 12:14:52 +0000192/**
193 * Sanity check of the doubly linked list of segments referenced by a
194 * ThreadInfo struct.
195 * @return True if sane, False if not.
sewardjaf44c822007-11-25 14:01:38 +0000196 */
bart62a784c2009-02-15 13:11:14 +0000197static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
sewardjaf44c822007-11-25 14:01:38 +0000198{
bart3772a982008-03-15 08:11:03 +0000199 Segment* p;
200 for (p = ti->first; p; p = p->next) {
201 if (p->next && p->next->prev != p)
202 return False;
203 if (p->next == 0 && p != ti->last)
204 return False;
205 }
206 for (p = ti->last; p; p = p->prev) {
207 if (p->prev && p->prev->next != p)
208 return False;
209 if (p->prev == 0 && p != ti->first)
210 return False;
211 }
212 return True;
sewardjaf44c822007-11-25 14:01:38 +0000213}
bart23d3a4e2008-04-05 12:53:00 +0000214#endif
sewardjaf44c822007-11-25 14:01:38 +0000215
bart439c55f2009-02-15 10:38:37 +0000216/**
217 * Create the first segment for a newly started thread.
218 *
219 * This function is called from the handler installed via
220 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
221 * from the context of the creator thread, before the new thread has been
222 * created.
223 */
bart62a784c2009-02-15 13:11:14 +0000224DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
225 const ThreadId vg_created)
sewardjaf44c822007-11-25 14:01:38 +0000226{
bart3772a982008-03-15 08:11:03 +0000227 DrdThreadId created;
sewardjaf44c822007-11-25 14:01:38 +0000228
bart62a784c2009-02-15 13:11:14 +0000229 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
230 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
bart74a5f212008-05-11 06:43:07 +0000231 tl_assert(0 <= (int)created && created < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000232 && created != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000233
bart324a23b2009-02-15 12:14:52 +0000234 tl_assert(DRD_(g_threadinfo)[created].first == 0);
235 tl_assert(DRD_(g_threadinfo)[created].last == 0);
bart62a784c2009-02-15 13:11:14 +0000236 DRD_(thread_append_segment)(created, DRD_(sg_new)(creator, created));
sewardjaf44c822007-11-25 14:01:38 +0000237
bart3772a982008-03-15 08:11:03 +0000238 return created;
sewardjaf44c822007-11-25 14:01:38 +0000239}
240
bart439c55f2009-02-15 10:38:37 +0000241/**
bart324a23b2009-02-15 12:14:52 +0000242 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called after
bart439c55f2009-02-15 10:38:37 +0000243 * the thread has been created and before any client instructioins are run
244 * on the newly created thread, e.g. from the handler installed via
245 * VG_(track_pre_thread_first_insn)().
246 */
bart62a784c2009-02-15 13:11:14 +0000247DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
bart439c55f2009-02-15 10:38:37 +0000248{
bart62a784c2009-02-15 13:11:14 +0000249 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
bart439c55f2009-02-15 10:38:37 +0000250
251 tl_assert(0 <= (int)created && created < DRD_N_THREADS
252 && created != DRD_INVALID_THREADID);
253
bart324a23b2009-02-15 12:14:52 +0000254 DRD_(g_threadinfo)[created].stack_max = VG_(thread_get_stack_max)(vg_created);
255 DRD_(g_threadinfo)[created].stack_startup = DRD_(g_threadinfo)[created].stack_max;
256 DRD_(g_threadinfo)[created].stack_min = DRD_(g_threadinfo)[created].stack_max;
257 DRD_(g_threadinfo)[created].stack_min_min = DRD_(g_threadinfo)[created].stack_max;
258 DRD_(g_threadinfo)[created].stack_size = VG_(thread_get_stack_size)(vg_created);
259 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
bart439c55f2009-02-15 10:38:37 +0000260
261 return created;
262}
bart09dc13f2009-02-14 15:13:31 +0000263
bart324a23b2009-02-15 12:14:52 +0000264/**
265 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
266 * after thread drd_joiner joined thread drd_joinee.
267 */
bart09dc13f2009-02-14 15:13:31 +0000268void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
269{
bart62a784c2009-02-15 13:11:14 +0000270 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
271 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
272 DRD_(thread_new_segment)(drd_joinee);
273 DRD_(thread_combine_vc)(drd_joiner, drd_joinee);
274 DRD_(thread_new_segment)(drd_joiner);
bart09dc13f2009-02-14 15:13:31 +0000275
bart324a23b2009-02-15 12:14:52 +0000276 if (DRD_(s_trace_fork_join))
bart09dc13f2009-02-14 15:13:31 +0000277 {
bart62a784c2009-02-15 13:11:14 +0000278 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
279 const ThreadId joinee = DRD_(DrdThreadIdToVgThreadId)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000280 const unsigned msg_size = 256;
281 char* msg;
282
283 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
284 tl_assert(msg);
285 VG_(snprintf)(msg, msg_size,
286 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
287 joiner, drd_joiner, joinee, drd_joinee);
288 if (joiner)
289 {
290 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
291 ", new vc: ");
bart41b226c2009-02-14 16:55:19 +0000292 DRD_(vc_snprint)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
bart62a784c2009-02-15 13:11:14 +0000293 DRD_(thread_get_vc)(drd_joiner));
bart09dc13f2009-02-14 15:13:31 +0000294 }
295 VG_(message)(Vg_DebugMsg, "%s", msg);
296 VG_(free)(msg);
297 }
298
299 if (! DRD_(get_check_stack_accesses)())
300 {
bart62a784c2009-02-15 13:11:14 +0000301 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
302 - DRD_(thread_get_stack_size)(drd_joinee),
303 DRD_(thread_get_stack_max)(drd_joinee));
bart09dc13f2009-02-14 15:13:31 +0000304 }
bart62a784c2009-02-15 13:11:14 +0000305 DRD_(thread_delete)(drd_joinee);
bartdc1ef032009-02-15 14:18:02 +0000306 DRD_(mutex_thread_delete)(drd_joinee);
307 DRD_(cond_thread_delete)(drd_joinee);
308 DRD_(semaphore_thread_delete)(drd_joinee);
barta8cf7652009-02-15 11:00:29 +0000309 DRD_(barrier_thread_delete)(drd_joinee);
bart09dc13f2009-02-14 15:13:31 +0000310}
311
bart324a23b2009-02-15 12:14:52 +0000312/**
313 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
314 * and accesses this data structure from multiple threads without locking.
315 * Any conflicting accesses in the range stack_startup..stack_max will be
316 * ignored.
317 */
bart62a784c2009-02-15 13:11:14 +0000318void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
319 const Addr stack_startup)
sewardjaf44c822007-11-25 14:01:38 +0000320{
bart74a5f212008-05-11 06:43:07 +0000321 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
322 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000323 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
324 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
325 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
sewardjaf44c822007-11-25 14:01:38 +0000326}
327
bart62a784c2009-02-15 13:11:14 +0000328Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000329{
bart74a5f212008-05-11 06:43:07 +0000330 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000331 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000332 return DRD_(g_threadinfo)[tid].stack_min;
sewardjaf44c822007-11-25 14:01:38 +0000333}
334
bart62a784c2009-02-15 13:11:14 +0000335Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000336{
bart74a5f212008-05-11 06:43:07 +0000337 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000338 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000339 return DRD_(g_threadinfo)[tid].stack_min_min;
bartcac53462008-03-29 09:27:08 +0000340}
341
bart62a784c2009-02-15 13:11:14 +0000342Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000343{
bart74a5f212008-05-11 06:43:07 +0000344 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartd43f8d32008-03-16 17:29:20 +0000345 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000346 return DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000347}
348
bart62a784c2009-02-15 13:11:14 +0000349SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
bartcac53462008-03-29 09:27:08 +0000350{
bart74a5f212008-05-11 06:43:07 +0000351 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bartcac53462008-03-29 09:27:08 +0000352 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000353 return DRD_(g_threadinfo)[tid].stack_size;
bartcac53462008-03-29 09:27:08 +0000354}
355
bart09dc13f2009-02-14 15:13:31 +0000356/**
357 * Clean up thread-specific data structures. Call this just after
358 * pthread_join().
sewardjaf44c822007-11-25 14:01:38 +0000359 */
bart62a784c2009-02-15 13:11:14 +0000360void DRD_(thread_delete)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000361{
bart3772a982008-03-15 08:11:03 +0000362 Segment* sg;
363 Segment* sg_prev;
sewardjaf44c822007-11-25 14:01:38 +0000364
bart74a5f212008-05-11 06:43:07 +0000365 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000366 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000367 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
368 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
bart3772a982008-03-15 08:11:03 +0000369 {
370 sg_prev = sg->prev;
barta2b6e1b2008-03-17 18:32:39 +0000371 sg->prev = 0;
372 sg->next = 0;
bart62ada3f2009-02-14 17:19:58 +0000373 DRD_(sg_put)(sg);
bart3772a982008-03-15 08:11:03 +0000374 }
bart324a23b2009-02-15 12:14:52 +0000375 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
376 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
377 tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
378 DRD_(g_threadinfo)[tid].first = 0;
379 DRD_(g_threadinfo)[tid].last = 0;
sewardjaf44c822007-11-25 14:01:38 +0000380}
381
bart324a23b2009-02-15 12:14:52 +0000382/**
383 * Called after a thread performed its last memory access and before
384 * thread_delete() is called. Note: thread_delete() is only called for
385 * joinable threads, not for detached threads.
386 */
bart62a784c2009-02-15 13:11:14 +0000387void DRD_(thread_finished)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000388{
bart74a5f212008-05-11 06:43:07 +0000389 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000390 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000391
bart324a23b2009-02-15 12:14:52 +0000392 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
sewardjaf44c822007-11-25 14:01:38 +0000393
bart324a23b2009-02-15 12:14:52 +0000394 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
bart3772a982008-03-15 08:11:03 +0000395 {
396 /* Once a detached thread has finished, its stack is deallocated and */
barte73b0aa2008-06-28 07:19:56 +0000397 /* should no longer be taken into account when computing the conflict set*/
bart324a23b2009-02-15 12:14:52 +0000398 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
sewardjaf44c822007-11-25 14:01:38 +0000399
bart3772a982008-03-15 08:11:03 +0000400 /* For a detached thread, calling pthread_exit() invalidates the */
401 /* POSIX thread ID associated with the detached thread. For joinable */
402 /* POSIX threads however, the POSIX thread ID remains live after the */
403 /* pthread_exit() call until pthread_join() is called. */
bart324a23b2009-02-15 12:14:52 +0000404 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
bart3772a982008-03-15 08:11:03 +0000405 }
sewardjaf44c822007-11-25 14:01:38 +0000406}
407
bart9b2974a2008-09-27 12:35:31 +0000408/** Called just before pthread_cancel(). */
bart62a784c2009-02-15 13:11:14 +0000409void DRD_(thread_pre_cancel)(const DrdThreadId tid)
bartaf0691b2008-09-27 12:26:50 +0000410{
411 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
412 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000413 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
bartaf0691b2008-09-27 12:26:50 +0000414
bart324a23b2009-02-15 12:14:52 +0000415 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
bartaf0691b2008-09-27 12:26:50 +0000416}
417
bart62a784c2009-02-15 13:11:14 +0000418void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
sewardjaf44c822007-11-25 14:01:38 +0000419{
bart74a5f212008-05-11 06:43:07 +0000420 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000421 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000422 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID);
bart3772a982008-03-15 08:11:03 +0000423 tl_assert(ptid != INVALID_POSIX_THREADID);
bart324a23b2009-02-15 12:14:52 +0000424 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
425 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
sewardjaf44c822007-11-25 14:01:38 +0000426}
427
bart62a784c2009-02-15 13:11:14 +0000428Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000429{
bart74a5f212008-05-11 06:43:07 +0000430 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000431 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000432 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
sewardjaf44c822007-11-25 14:01:38 +0000433}
434
bart62a784c2009-02-15 13:11:14 +0000435void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
sewardjaf44c822007-11-25 14:01:38 +0000436{
bart74a5f212008-05-11 06:43:07 +0000437 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000438 && tid != DRD_INVALID_THREADID);
439 tl_assert(!! joinable == joinable);
bart324a23b2009-02-15 12:14:52 +0000440 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000441#if 0
bart3772a982008-03-15 08:11:03 +0000442 VG_(message)(Vg_DebugMsg,
443 "thread_set_joinable(%d/%d, %s)",
444 tid,
bart324a23b2009-02-15 12:14:52 +0000445 DRD_(g_threadinfo)[tid].vg_threadid,
bart3772a982008-03-15 08:11:03 +0000446 joinable ? "joinable" : "detached");
sewardjaf44c822007-11-25 14:01:38 +0000447#endif
bart324a23b2009-02-15 12:14:52 +0000448 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
sewardjaf44c822007-11-25 14:01:38 +0000449}
450
bart62a784c2009-02-15 13:11:14 +0000451void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000452{
bart3772a982008-03-15 08:11:03 +0000453 tl_assert(vg_tid != VG_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000454
bart324a23b2009-02-15 12:14:52 +0000455 if (vg_tid != DRD_(s_vg_running_tid))
bart3772a982008-03-15 08:11:03 +0000456 {
bart62a784c2009-02-15 13:11:14 +0000457 DRD_(thread_set_running_tid)(vg_tid,
458 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
bart3772a982008-03-15 08:11:03 +0000459 }
sewardj8b09d4f2007-12-04 21:27:18 +0000460
bart324a23b2009-02-15 12:14:52 +0000461 tl_assert(DRD_(s_vg_running_tid) != VG_INVALID_THREADID);
462 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000463}
464
bart62a784c2009-02-15 13:11:14 +0000465void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
466 const DrdThreadId drd_tid)
sewardj8b09d4f2007-12-04 21:27:18 +0000467{
bart3772a982008-03-15 08:11:03 +0000468 tl_assert(vg_tid != VG_INVALID_THREADID);
469 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000470
bart324a23b2009-02-15 12:14:52 +0000471 if (vg_tid != DRD_(s_vg_running_tid))
bart3772a982008-03-15 08:11:03 +0000472 {
bart324a23b2009-02-15 12:14:52 +0000473 if (DRD_(s_trace_context_switches)
474 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
bart3772a982008-03-15 08:11:03 +0000475 {
476 VG_(message)(Vg_DebugMsg,
barta2b6e1b2008-03-17 18:32:39 +0000477 "Context switch from thread %d/%d to thread %d/%d;"
478 " segments: %llu",
bart324a23b2009-02-15 12:14:52 +0000479 DRD_(s_vg_running_tid), DRD_(g_drd_running_tid),
bart62a784c2009-02-15 13:11:14 +0000480 DRD_(DrdThreadIdToVgThreadId)(drd_tid), drd_tid,
bart62ada3f2009-02-14 17:19:58 +0000481 DRD_(sg_get_segments_alive_count)());
bart3772a982008-03-15 08:11:03 +0000482 }
bart324a23b2009-02-15 12:14:52 +0000483 DRD_(s_vg_running_tid) = vg_tid;
484 DRD_(g_drd_running_tid) = drd_tid;
bart62a784c2009-02-15 13:11:14 +0000485 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set), drd_tid);
bart324a23b2009-02-15 12:14:52 +0000486 DRD_(s_context_switch_count)++;
bart3772a982008-03-15 08:11:03 +0000487 }
sewardj8b09d4f2007-12-04 21:27:18 +0000488
bart324a23b2009-02-15 12:14:52 +0000489 tl_assert(DRD_(s_vg_running_tid) != VG_INVALID_THREADID);
490 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000491}
492
bart62a784c2009-02-15 13:11:14 +0000493int DRD_(thread_enter_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000494{
bart62a784c2009-02-15 13:11:14 +0000495 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000496 return DRD_(g_threadinfo)[tid].synchr_nesting++;
bart0268dfa2008-03-11 20:10:21 +0000497}
498
bart62a784c2009-02-15 13:11:14 +0000499int DRD_(thread_leave_synchr)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000500{
bart62a784c2009-02-15 13:11:14 +0000501 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000502 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
503 return --DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000504}
505
bart62a784c2009-02-15 13:11:14 +0000506int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000507{
bart62a784c2009-02-15 13:11:14 +0000508 tl_assert(DRD_(IsValidDrdThreadId)(tid));
bart324a23b2009-02-15 12:14:52 +0000509 return DRD_(g_threadinfo)[tid].synchr_nesting;
bart0268dfa2008-03-11 20:10:21 +0000510}
511
bart1a473c72008-03-13 19:03:38 +0000512/** Append a new segment at the end of the segment list. */
bart62a784c2009-02-15 13:11:14 +0000513static
514void DRD_(thread_append_segment)(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000515{
bart74a5f212008-05-11 06:43:07 +0000516 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000517 && tid != DRD_INVALID_THREADID);
bart62a784c2009-02-15 13:11:14 +0000518 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart324a23b2009-02-15 12:14:52 +0000519 sg->prev = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +0000520 sg->next = 0;
bart324a23b2009-02-15 12:14:52 +0000521 if (DRD_(g_threadinfo)[tid].last)
522 DRD_(g_threadinfo)[tid].last->next = sg;
523 DRD_(g_threadinfo)[tid].last = sg;
524 if (DRD_(g_threadinfo)[tid].first == 0)
525 DRD_(g_threadinfo)[tid].first = sg;
bart62a784c2009-02-15 13:11:14 +0000526 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000527}
528
bart324a23b2009-02-15 12:14:52 +0000529/**
530 * Remove a segment from the segment list of thread threadid, and free the
531 * associated memory.
sewardjaf44c822007-11-25 14:01:38 +0000532 */
bart62a784c2009-02-15 13:11:14 +0000533static
534void DRD_(thread_discard_segment)(const DrdThreadId tid, Segment* const sg)
sewardjaf44c822007-11-25 14:01:38 +0000535{
bart74a5f212008-05-11 06:43:07 +0000536 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000537 && tid != DRD_INVALID_THREADID);
bart62a784c2009-02-15 13:11:14 +0000538 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
bart26f73e12008-02-24 18:37:08 +0000539
bart3772a982008-03-15 08:11:03 +0000540 if (sg->prev)
541 sg->prev->next = sg->next;
542 if (sg->next)
543 sg->next->prev = sg->prev;
bart324a23b2009-02-15 12:14:52 +0000544 if (sg == DRD_(g_threadinfo)[tid].first)
545 DRD_(g_threadinfo)[tid].first = sg->next;
546 if (sg == DRD_(g_threadinfo)[tid].last)
547 DRD_(g_threadinfo)[tid].last = sg->prev;
bart62ada3f2009-02-14 17:19:58 +0000548 DRD_(sg_put)(sg);
bart3f749672008-03-22 09:49:40 +0000549
bart62a784c2009-02-15 13:11:14 +0000550 //tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
sewardjaf44c822007-11-25 14:01:38 +0000551}
552
bart62a784c2009-02-15 13:11:14 +0000553VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000554{
bart74a5f212008-05-11 06:43:07 +0000555 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
556 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000557 tl_assert(DRD_(g_threadinfo)[tid].last);
558 return &DRD_(g_threadinfo)[tid].last->vc;
sewardjaf44c822007-11-25 14:01:38 +0000559}
560
bart324a23b2009-02-15 12:14:52 +0000561/**
562 * Return the latest segment of thread 'tid' and increment its reference count.
barta2b6e1b2008-03-17 18:32:39 +0000563 */
bart62a784c2009-02-15 13:11:14 +0000564void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
barta2b6e1b2008-03-17 18:32:39 +0000565{
566 tl_assert(sg);
bart74a5f212008-05-11 06:43:07 +0000567 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
568 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000569 tl_assert(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000570
bart62ada3f2009-02-14 17:19:58 +0000571 DRD_(sg_put)(*sg);
bart324a23b2009-02-15 12:14:52 +0000572 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
barta2b6e1b2008-03-17 18:32:39 +0000573}
574
sewardjaf44c822007-11-25 14:01:38 +0000575/**
576 * Compute the minimum of all latest vector clocks of all threads
577 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
578 * @param vc pointer to a vectorclock, holds result upon return.
579 */
bart62a784c2009-02-15 13:11:14 +0000580static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000581{
bart3772a982008-03-15 08:11:03 +0000582 unsigned i;
583 Bool first;
584 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000585
bart3772a982008-03-15 08:11:03 +0000586 first = True;
bart62a784c2009-02-15 13:11:14 +0000587 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
588 i++)
bart3772a982008-03-15 08:11:03 +0000589 {
bart324a23b2009-02-15 12:14:52 +0000590 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000591 if (latest_sg)
592 {
593 if (first)
bart41b226c2009-02-14 16:55:19 +0000594 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000595 else
bart41b226c2009-02-14 16:55:19 +0000596 DRD_(vc_min)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000597 first = False;
598 }
599 }
sewardjaf44c822007-11-25 14:01:38 +0000600}
601
bart62a784c2009-02-15 13:11:14 +0000602static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
sewardjaf44c822007-11-25 14:01:38 +0000603{
bart3772a982008-03-15 08:11:03 +0000604 unsigned i;
605 Bool first;
606 Segment* latest_sg;
sewardjaf44c822007-11-25 14:01:38 +0000607
bart3772a982008-03-15 08:11:03 +0000608 first = True;
bart62a784c2009-02-15 13:11:14 +0000609 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
610 i++)
bart3772a982008-03-15 08:11:03 +0000611 {
bart324a23b2009-02-15 12:14:52 +0000612 latest_sg = DRD_(g_threadinfo)[i].last;
bart3772a982008-03-15 08:11:03 +0000613 if (latest_sg)
614 {
615 if (first)
bart41b226c2009-02-14 16:55:19 +0000616 DRD_(vc_assign)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000617 else
bart41b226c2009-02-14 16:55:19 +0000618 DRD_(vc_combine)(vc, &latest_sg->vc);
bart3772a982008-03-15 08:11:03 +0000619 first = False;
620 }
621 }
sewardjaf44c822007-11-25 14:01:38 +0000622}
623
624/**
bart5bd9f2d2008-03-03 20:31:58 +0000625 * Discard all segments that have a defined order against the latest vector
sewardjaf44c822007-11-25 14:01:38 +0000626 * clock of every thread -- these segments can no longer be involved in a
627 * data race.
628 */
bart62a784c2009-02-15 13:11:14 +0000629static void DRD_(thread_discard_ordered_segments)(void)
sewardjaf44c822007-11-25 14:01:38 +0000630{
bart3772a982008-03-15 08:11:03 +0000631 unsigned i;
632 VectorClock thread_vc_min;
sewardjaf44c822007-11-25 14:01:38 +0000633
bart324a23b2009-02-15 12:14:52 +0000634 DRD_(s_discard_ordered_segments_count)++;
sewardjaf44c822007-11-25 14:01:38 +0000635
bart41b226c2009-02-14 16:55:19 +0000636 DRD_(vc_init)(&thread_vc_min, 0, 0);
bart62a784c2009-02-15 13:11:14 +0000637 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
bart62ada3f2009-02-14 17:19:58 +0000638 if (DRD_(sg_get_trace)())
bart3772a982008-03-15 08:11:03 +0000639 {
640 char msg[256];
641 VectorClock thread_vc_max;
sewardjaf44c822007-11-25 14:01:38 +0000642
bart41b226c2009-02-14 16:55:19 +0000643 DRD_(vc_init)(&thread_vc_max, 0, 0);
bart62a784c2009-02-15 13:11:14 +0000644 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
bart3772a982008-03-15 08:11:03 +0000645 VG_(snprintf)(msg, sizeof(msg),
646 "Discarding ordered segments -- min vc is ");
bart41b226c2009-02-14 16:55:19 +0000647 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
648 &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000649 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
650 ", max vc is ");
bart41b226c2009-02-14 16:55:19 +0000651 DRD_(vc_snprint)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
652 &thread_vc_max);
barta2b6e1b2008-03-17 18:32:39 +0000653 VG_(message)(Vg_UserMsg, "%s", msg);
bart41b226c2009-02-14 16:55:19 +0000654 DRD_(vc_cleanup)(&thread_vc_max);
bart3772a982008-03-15 08:11:03 +0000655 }
sewardjaf44c822007-11-25 14:01:38 +0000656
bart62a784c2009-02-15 13:11:14 +0000657 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
658 i++)
bart3772a982008-03-15 08:11:03 +0000659 {
660 Segment* sg;
661 Segment* sg_next;
bart324a23b2009-02-15 12:14:52 +0000662 for (sg = DRD_(g_threadinfo)[i].first;
bart41b226c2009-02-14 16:55:19 +0000663 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
bart3772a982008-03-15 08:11:03 +0000664 sg = sg_next)
665 {
bart62a784c2009-02-15 13:11:14 +0000666 DRD_(thread_discard_segment)(i, sg);
bart3772a982008-03-15 08:11:03 +0000667 }
668 }
bart41b226c2009-02-14 16:55:19 +0000669 DRD_(vc_cleanup)(&thread_vc_min);
sewardjaf44c822007-11-25 14:01:38 +0000670}
671
bart324a23b2009-02-15 12:14:52 +0000672/**
673 * Merge all segments that may be merged without triggering false positives
674 * or discarding real data races. For the theoretical background of segment
675 * merging, see also the following paper:
676 * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
677 * Bounding the number of segment histories during data race detection.
678 * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
679 * September 2002.
barta9c37392008-03-22 09:38:48 +0000680 */
681static void thread_merge_segments(void)
682{
683 unsigned i;
684
bart62a784c2009-02-15 13:11:14 +0000685 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
686 i++)
barta9c37392008-03-22 09:38:48 +0000687 {
688 Segment* sg;
689
bart62a784c2009-02-15 13:11:14 +0000690 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000691
bart324a23b2009-02-15 12:14:52 +0000692 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
barta9c37392008-03-22 09:38:48 +0000693 {
bart62ada3f2009-02-14 17:19:58 +0000694 if (DRD_(sg_get_refcnt)(sg) == 1
barta9c37392008-03-22 09:38:48 +0000695 && sg->next
bart62ada3f2009-02-14 17:19:58 +0000696 && DRD_(sg_get_refcnt)(sg->next) == 1
barta9c37392008-03-22 09:38:48 +0000697 && sg->next->next)
698 {
699 /* Merge sg and sg->next into sg. */
bart62ada3f2009-02-14 17:19:58 +0000700 DRD_(sg_merge)(sg, sg->next);
bart62a784c2009-02-15 13:11:14 +0000701 DRD_(thread_discard_segment)(i, sg->next);
barta9c37392008-03-22 09:38:48 +0000702 }
703 }
704
bart62a784c2009-02-15 13:11:14 +0000705 // tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
barta9c37392008-03-22 09:38:48 +0000706 }
707}
708
bart324a23b2009-02-15 12:14:52 +0000709/**
710 * Every change in the vector clock of a thread may cause segments that
711 * were previously ordered to this thread to become unordered. Hence,
712 * it may be necessary to recalculate the conflict set if the vector clock
713 * of the current thread is updated. This function check whether such a
714 * recalculation is necessary.
bartd66e3a82008-04-06 15:02:17 +0000715 *
bart324a23b2009-02-15 12:14:52 +0000716 * @param tid Thread ID of the thread to which a new segment has been
717 * appended.
718 * @param new_sg Pointer to the most recent segment of thread tid.
bartd66e3a82008-04-06 15:02:17 +0000719 */
barte73b0aa2008-06-28 07:19:56 +0000720static Bool conflict_set_update_needed(const DrdThreadId tid,
bart41b226c2009-02-14 16:55:19 +0000721 const Segment* const new_sg)
bartd66e3a82008-04-06 15:02:17 +0000722{
bart5d421ba2008-04-19 15:15:12 +0000723#if 0
bartd66e3a82008-04-06 15:02:17 +0000724 unsigned i;
725 const Segment* old_sg;
726
727 tl_assert(new_sg);
728
729 /* If a new segment was added to another thread than the running thread, */
barte73b0aa2008-06-28 07:19:56 +0000730 /* just tell the caller to update the conflict set. */
bart324a23b2009-02-15 12:14:52 +0000731 if (tid != DRD_(g_drd_running_tid))
bartd66e3a82008-04-06 15:02:17 +0000732 return True;
733
barte73b0aa2008-06-28 07:19:56 +0000734 /* Always let the caller update the conflict set after creation of the */
bartd66e3a82008-04-06 15:02:17 +0000735 /* first segment. */
736 old_sg = new_sg->prev;
737 if (old_sg == 0)
738 return True;
739
bart62a784c2009-02-15 13:11:14 +0000740 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
741 i++)
bartd66e3a82008-04-06 15:02:17 +0000742 {
743 Segment* q;
744
bart324a23b2009-02-15 12:14:52 +0000745 if (i == DRD_(g_drd_running_tid))
bartd66e3a82008-04-06 15:02:17 +0000746 continue;
747
bart324a23b2009-02-15 12:14:52 +0000748 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +0000749 {
750 /* If the expression below evaluates to false, this expression will */
751 /* also evaluate to false for all subsequent iterations. So stop */
752 /* iterating. */
bart41b226c2009-02-14 16:55:19 +0000753 if (DRD_(vc_lte)(&q->vc, &old_sg->vc))
bartd66e3a82008-04-06 15:02:17 +0000754 break;
755 /* If the vector clock of the 2nd the last segment is not ordered */
756 /* to the vector clock of segment q, and the last segment is, ask */
barte73b0aa2008-06-28 07:19:56 +0000757 /* the caller to update the conflict set. */
bart41b226c2009-02-14 16:55:19 +0000758 if (! DRD_(vc_lte)(&old_sg->vc, &q->vc))
bartd66e3a82008-04-06 15:02:17 +0000759 {
760 return True;
761 }
762 /* If the vector clock of the last segment is not ordered to the */
barte73b0aa2008-06-28 07:19:56 +0000763 /* vector clock of segment q, ask the caller to update the conflict */
bartd66e3a82008-04-06 15:02:17 +0000764 /* set. */
bart41b226c2009-02-14 16:55:19 +0000765 if (! DRD_(vc_lte)(&q->vc, &new_sg->vc) && ! DRD_(vc_lte)(&new_sg->vc, &q->vc))
bartd66e3a82008-04-06 15:02:17 +0000766 {
767 return True;
768 }
769 }
770 }
771
772 return False;
bart5d421ba2008-04-19 15:15:12 +0000773#else
774 return True;
775#endif
bartd66e3a82008-04-06 15:02:17 +0000776}
777
bart324a23b2009-02-15 12:14:52 +0000778/**
779 * Create a new segment for the specified thread, and discard any segments
780 * that cannot cause races anymore.
sewardjaf44c822007-11-25 14:01:38 +0000781 */
bart62a784c2009-02-15 13:11:14 +0000782void DRD_(thread_new_segment)(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000783{
bartd66e3a82008-04-06 15:02:17 +0000784 Segment* new_sg;
785
bart74a5f212008-05-11 06:43:07 +0000786 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
787 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +0000788
bart62ada3f2009-02-14 17:19:58 +0000789 new_sg = DRD_(sg_new)(tid, tid);
bart62a784c2009-02-15 13:11:14 +0000790 DRD_(thread_append_segment)(tid, new_sg);
bartd66e3a82008-04-06 15:02:17 +0000791
barte73b0aa2008-06-28 07:19:56 +0000792 if (conflict_set_update_needed(tid, new_sg))
bartd66e3a82008-04-06 15:02:17 +0000793 {
bart62a784c2009-02-15 13:11:14 +0000794 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set),
795 DRD_(g_drd_running_tid));
bart324a23b2009-02-15 12:14:52 +0000796 DRD_(s_conflict_set_new_segment_count)++;
bartd66e3a82008-04-06 15:02:17 +0000797 }
bart324a23b2009-02-15 12:14:52 +0000798 else if (tid == DRD_(g_drd_running_tid))
bart82195c12008-04-13 17:35:08 +0000799 {
bart62a784c2009-02-15 13:11:14 +0000800 tl_assert(DRD_(thread_conflict_set_up_to_date)(DRD_(g_drd_running_tid)));
bart82195c12008-04-13 17:35:08 +0000801 }
sewardjaf44c822007-11-25 14:01:38 +0000802
bart62a784c2009-02-15 13:11:14 +0000803 DRD_(thread_discard_ordered_segments)();
bart26f73e12008-02-24 18:37:08 +0000804
bart324a23b2009-02-15 12:14:52 +0000805 if (DRD_(s_segment_merging))
806 {
barta9c37392008-03-22 09:38:48 +0000807 thread_merge_segments();
bart324a23b2009-02-15 12:14:52 +0000808 }
sewardjaf44c822007-11-25 14:01:38 +0000809}
810
bart26f73e12008-02-24 18:37:08 +0000811/** Call this function after thread 'joiner' joined thread 'joinee'. */
bart62a784c2009-02-15 13:11:14 +0000812void DRD_(thread_combine_vc)(DrdThreadId joiner, DrdThreadId joinee)
sewardjaf44c822007-11-25 14:01:38 +0000813{
bart3772a982008-03-15 08:11:03 +0000814 tl_assert(joiner != joinee);
bart74a5f212008-05-11 06:43:07 +0000815 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000816 && joiner != DRD_INVALID_THREADID);
bart74a5f212008-05-11 06:43:07 +0000817 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000818 && joinee != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000819 tl_assert(DRD_(g_threadinfo)[joiner].last);
820 tl_assert(DRD_(g_threadinfo)[joinee].last);
821 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
822 &DRD_(g_threadinfo)[joinee].last->vc);
bart62a784c2009-02-15 13:11:14 +0000823 DRD_(thread_discard_ordered_segments)();
sewardjaf44c822007-11-25 14:01:38 +0000824
bart324a23b2009-02-15 12:14:52 +0000825 if (joiner == DRD_(g_drd_running_tid))
bart3772a982008-03-15 08:11:03 +0000826 {
bart62a784c2009-02-15 13:11:14 +0000827 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set), joiner);
bart3772a982008-03-15 08:11:03 +0000828 }
sewardjaf44c822007-11-25 14:01:38 +0000829}
830
bart324a23b2009-02-15 12:14:52 +0000831/**
832 * Call this function after thread 'tid' had to wait because of thread
833 * synchronization until the memory accesses in the segment with vector clock
834 * 'vc' finished.
bart26f73e12008-02-24 18:37:08 +0000835 */
bart62a784c2009-02-15 13:11:14 +0000836void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc)
sewardjaf44c822007-11-25 14:01:38 +0000837{
bart74a5f212008-05-11 06:43:07 +0000838 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
839 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000840 tl_assert(DRD_(g_threadinfo)[tid].last);
bart3772a982008-03-15 08:11:03 +0000841 tl_assert(vc);
bart324a23b2009-02-15 12:14:52 +0000842 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
bart62a784c2009-02-15 13:11:14 +0000843 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set), tid);
844 DRD_(thread_discard_ordered_segments)();
bart324a23b2009-02-15 12:14:52 +0000845 DRD_(s_conflict_set_combine_vc_count)++;
sewardjaf44c822007-11-25 14:01:38 +0000846}
847
bart324a23b2009-02-15 12:14:52 +0000848/**
849 * Call this function whenever a thread is no longer using the memory
850 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
851 * increase.
bart26f73e12008-02-24 18:37:08 +0000852 */
bart62a784c2009-02-15 13:11:14 +0000853void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000854{
bartd43f8d32008-03-16 17:29:20 +0000855 DrdThreadId other_user;
856 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000857
bart3772a982008-03-15 08:11:03 +0000858 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
bartd43f8d32008-03-16 17:29:20 +0000859 other_user = DRD_INVALID_THREADID;
bart62a784c2009-02-15 13:11:14 +0000860 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
861 i++)
bart3772a982008-03-15 08:11:03 +0000862 {
863 Segment* p;
bart324a23b2009-02-15 12:14:52 +0000864 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +0000865 {
866 if (other_user == DRD_INVALID_THREADID
bart324a23b2009-02-15 12:14:52 +0000867 && i != DRD_(g_drd_running_tid))
sewardjaf44c822007-11-25 14:01:38 +0000868 {
bart99edb292009-02-15 15:59:20 +0000869 if (UNLIKELY(DRD_(bm_test_and_clear)(p->bm, a1, a2)))
bart8bf2f8b2008-03-30 17:56:43 +0000870 {
871 other_user = i;
872 }
873 continue;
sewardjaf44c822007-11-25 14:01:38 +0000874 }
bart99edb292009-02-15 15:59:20 +0000875 DRD_(bm_clear)(p->bm, a1, a2);
bart3772a982008-03-15 08:11:03 +0000876 }
877 }
sewardjaf44c822007-11-25 14:01:38 +0000878
bart324a23b2009-02-15 12:14:52 +0000879 /*
880 * If any other thread had accessed memory in [ a1, a2 [, update the
881 * conflict set.
882 */
bart3772a982008-03-15 08:11:03 +0000883 if (other_user != DRD_INVALID_THREADID
bart99edb292009-02-15 15:59:20 +0000884 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
bart3772a982008-03-15 08:11:03 +0000885 {
bart62a784c2009-02-15 13:11:14 +0000886 DRD_(thread_compute_conflict_set)(&DRD_(g_conflict_set),
887 DRD_(thread_get_running_tid)());
bart3772a982008-03-15 08:11:03 +0000888 }
sewardjaf44c822007-11-25 14:01:38 +0000889}
890
bart62a784c2009-02-15 13:11:14 +0000891void DRD_(thread_start_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000892{
bart74a5f212008-05-11 06:43:07 +0000893 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
894 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000895 tl_assert(! DRD_(g_threadinfo)[tid].is_recording);
896 DRD_(g_threadinfo)[tid].is_recording = True;
bart0268dfa2008-03-11 20:10:21 +0000897}
898
bart62a784c2009-02-15 13:11:14 +0000899void DRD_(thread_stop_recording)(const DrdThreadId tid)
bart0268dfa2008-03-11 20:10:21 +0000900{
bart74a5f212008-05-11 06:43:07 +0000901 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
902 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +0000903 tl_assert(DRD_(g_threadinfo)[tid].is_recording);
904 DRD_(g_threadinfo)[tid].is_recording = False;
bart0268dfa2008-03-11 20:10:21 +0000905}
906
bart62a784c2009-02-15 13:11:14 +0000907void DRD_(thread_print_all)(void)
sewardjaf44c822007-11-25 14:01:38 +0000908{
bart3772a982008-03-15 08:11:03 +0000909 unsigned i;
910 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +0000911
bart62a784c2009-02-15 13:11:14 +0000912 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
913 i++)
bart3772a982008-03-15 08:11:03 +0000914 {
bart324a23b2009-02-15 12:14:52 +0000915 if (DRD_(g_threadinfo)[i].first)
bart3772a982008-03-15 08:11:03 +0000916 {
917 VG_(printf)("**************\n"
barta2b6e1b2008-03-17 18:32:39 +0000918 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
bart3772a982008-03-15 08:11:03 +0000919 "**************\n",
920 i,
bart324a23b2009-02-15 12:14:52 +0000921 DRD_(g_threadinfo)[i].vg_thread_exists,
922 DRD_(g_threadinfo)[i].vg_threadid,
923 DRD_(g_threadinfo)[i].posix_thread_exists,
924 DRD_(g_threadinfo)[i].pt_threadid,
925 DRD_(g_threadinfo)[i].detached_posix_thread);
926 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
sewardjaf44c822007-11-25 14:01:38 +0000927 {
bart62ada3f2009-02-14 17:19:58 +0000928 DRD_(sg_print)(p);
sewardjaf44c822007-11-25 14:01:38 +0000929 }
bart3772a982008-03-15 08:11:03 +0000930 }
931 }
sewardjaf44c822007-11-25 14:01:38 +0000932}
933
934static void show_call_stack(const DrdThreadId tid,
935 const Char* const msg,
936 ExeContext* const callstack)
937{
bart62a784c2009-02-15 13:11:14 +0000938 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
sewardjaf44c822007-11-25 14:01:38 +0000939
bartaa97a542008-03-16 17:57:01 +0000940 VG_(message)(Vg_UserMsg, "%s (thread %d/%d)", msg, vg_tid, tid);
sewardjaf44c822007-11-25 14:01:38 +0000941
bart3772a982008-03-15 08:11:03 +0000942 if (vg_tid != VG_INVALID_THREADID)
943 {
944 if (callstack)
945 {
946 VG_(pp_ExeContext)(callstack);
947 }
948 else
949 {
950 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
951 }
952 }
953 else
954 {
955 VG_(message)(Vg_UserMsg,
956 " (thread finished, call stack no longer available)");
957 }
sewardjaf44c822007-11-25 14:01:38 +0000958}
959
sewardjaf44c822007-11-25 14:01:38 +0000960static void
961thread_report_conflicting_segments_segment(const DrdThreadId tid,
962 const Addr addr,
963 const SizeT size,
964 const BmAccessTypeT access_type,
965 const Segment* const p)
966{
bart3772a982008-03-15 08:11:03 +0000967 unsigned i;
sewardjaf44c822007-11-25 14:01:38 +0000968
bart74a5f212008-05-11 06:43:07 +0000969 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +0000970 && tid != DRD_INVALID_THREADID);
971 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000972
bart62a784c2009-02-15 13:11:14 +0000973 for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
974 i++)
bart3772a982008-03-15 08:11:03 +0000975 {
976 if (i != tid)
977 {
978 Segment* q;
bart324a23b2009-02-15 12:14:52 +0000979 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
sewardjaf44c822007-11-25 14:01:38 +0000980 {
bart324a23b2009-02-15 12:14:52 +0000981 /*
982 * Since q iterates over the segments of thread i in order of
983 * decreasing vector clocks, if q->vc <= p->vc, then
984 * q->next->vc <= p->vc will also hold. Hence, break out of the
985 * loop once this condition is met.
986 */
bart41b226c2009-02-14 16:55:19 +0000987 if (DRD_(vc_lte)(&q->vc, &p->vc))
bart3772a982008-03-15 08:11:03 +0000988 break;
bart41b226c2009-02-14 16:55:19 +0000989 if (! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +0000990 {
bart99edb292009-02-15 15:59:20 +0000991 if (DRD_(bm_has_conflict_with)(q->bm, addr, addr + size,
992 access_type))
bart3772a982008-03-15 08:11:03 +0000993 {
994 tl_assert(q->stacktrace);
995 show_call_stack(i, "Other segment start",
996 q->stacktrace);
997 show_call_stack(i, "Other segment end",
998 q->next ? q->next->stacktrace : 0);
999 }
1000 }
sewardjaf44c822007-11-25 14:01:38 +00001001 }
bart3772a982008-03-15 08:11:03 +00001002 }
1003 }
sewardjaf44c822007-11-25 14:01:38 +00001004}
1005
bart62a784c2009-02-15 13:11:14 +00001006void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1007 const Addr addr,
1008 const SizeT size,
1009 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +00001010{
bart3772a982008-03-15 08:11:03 +00001011 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001012
bart74a5f212008-05-11 06:43:07 +00001013 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
bart3772a982008-03-15 08:11:03 +00001014 && tid != DRD_INVALID_THREADID);
sewardjaf44c822007-11-25 14:01:38 +00001015
bart324a23b2009-02-15 12:14:52 +00001016 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
bart3772a982008-03-15 08:11:03 +00001017 {
bart99edb292009-02-15 15:59:20 +00001018 if (DRD_(bm_has)(p->bm, addr, addr + size, access_type))
bart3772a982008-03-15 08:11:03 +00001019 {
1020 thread_report_conflicting_segments_segment(tid, addr, size,
1021 access_type, p);
1022 }
1023 }
sewardjaf44c822007-11-25 14:01:38 +00001024}
sewardjaf44c822007-11-25 14:01:38 +00001025
bart324a23b2009-02-15 12:14:52 +00001026/**
1027 * Verify whether the conflict set for thread tid is up to date. Only perform
1028 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
bart82195c12008-04-13 17:35:08 +00001029 */
bart62a784c2009-02-15 13:11:14 +00001030static Bool DRD_(thread_conflict_set_up_to_date)(const DrdThreadId tid)
bart82195c12008-04-13 17:35:08 +00001031{
barte73b0aa2008-06-28 07:19:56 +00001032 static int do_verify_conflict_set = -1;
bart82195c12008-04-13 17:35:08 +00001033 Bool result;
barte73b0aa2008-06-28 07:19:56 +00001034 struct bitmap* computed_conflict_set = 0;
bart82195c12008-04-13 17:35:08 +00001035
barte73b0aa2008-06-28 07:19:56 +00001036 if (do_verify_conflict_set < 0)
bart82195c12008-04-13 17:35:08 +00001037 {
barte73b0aa2008-06-28 07:19:56 +00001038 //VG_(message)(Vg_DebugMsg, "%s", VG_(getenv)("DRD_VERIFY_CONFLICT_SET"));
1039 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
bart82195c12008-04-13 17:35:08 +00001040 }
barte73b0aa2008-06-28 07:19:56 +00001041 if (do_verify_conflict_set == 0)
bart82195c12008-04-13 17:35:08 +00001042 return True;
1043
bart62a784c2009-02-15 13:11:14 +00001044 DRD_(thread_compute_conflict_set)(&computed_conflict_set, tid);
bart99edb292009-02-15 15:59:20 +00001045 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1046 DRD_(bm_delete)(computed_conflict_set);
bart82195c12008-04-13 17:35:08 +00001047 return result;
1048}
1049
bart324a23b2009-02-15 12:14:52 +00001050/**
1051 * Compute a bitmap that represents the union of all memory accesses of all
1052 * segments that are unordered to the current segment of the thread tid.
sewardjaf44c822007-11-25 14:01:38 +00001053 */
bart62a784c2009-02-15 13:11:14 +00001054static void DRD_(thread_compute_conflict_set)(struct bitmap** conflict_set,
1055 const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +00001056{
bart3772a982008-03-15 08:11:03 +00001057 Segment* p;
sewardjaf44c822007-11-25 14:01:38 +00001058
bart74a5f212008-05-11 06:43:07 +00001059 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1060 && tid != DRD_INVALID_THREADID);
bart324a23b2009-02-15 12:14:52 +00001061 tl_assert(tid == DRD_(g_drd_running_tid));
sewardjaf44c822007-11-25 14:01:38 +00001062
bart324a23b2009-02-15 12:14:52 +00001063 DRD_(s_update_conflict_set_count)++;
bart99edb292009-02-15 15:59:20 +00001064 DRD_(s_conflict_set_bitmap_creation_count) -= DRD_(bm_get_bitmap_creation_count)();
1065 DRD_(s_conflict_set_bitmap2_creation_count) -= DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001066
barte73b0aa2008-06-28 07:19:56 +00001067 if (*conflict_set)
bart3772a982008-03-15 08:11:03 +00001068 {
bart99edb292009-02-15 15:59:20 +00001069 DRD_(bm_delete)(*conflict_set);
bart3772a982008-03-15 08:11:03 +00001070 }
bart99edb292009-02-15 15:59:20 +00001071 *conflict_set = DRD_(bm_new)();
bart26f73e12008-02-24 18:37:08 +00001072
bart324a23b2009-02-15 12:14:52 +00001073 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001074 {
1075 char msg[256];
1076
1077 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001078 "computing conflict set for thread %d/%d with vc ",
bart62a784c2009-02-15 13:11:14 +00001079 DRD_(DrdThreadIdToVgThreadId)(tid), tid);
bart41b226c2009-02-14 16:55:19 +00001080 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1081 sizeof(msg) - VG_(strlen)(msg),
bart324a23b2009-02-15 12:14:52 +00001082 &DRD_(g_threadinfo)[tid].last->vc);
barta2b6e1b2008-03-17 18:32:39 +00001083 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001084 }
1085
bart324a23b2009-02-15 12:14:52 +00001086 p = DRD_(g_threadinfo)[tid].last;
bart3772a982008-03-15 08:11:03 +00001087 {
1088 unsigned j;
1089
bart324a23b2009-02-15 12:14:52 +00001090 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001091 {
bart26f73e12008-02-24 18:37:08 +00001092 char msg[256];
1093
1094 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001095 "conflict set: thread [%d] at vc ",
bart26f73e12008-02-24 18:37:08 +00001096 tid);
bart41b226c2009-02-14 16:55:19 +00001097 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1098 sizeof(msg) - VG_(strlen)(msg),
1099 &p->vc);
barta2b6e1b2008-03-17 18:32:39 +00001100 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001101 }
sewardjaf44c822007-11-25 14:01:38 +00001102
bart324a23b2009-02-15 12:14:52 +00001103 for (j = 0; j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]); j++)
bart3772a982008-03-15 08:11:03 +00001104 {
bart62a784c2009-02-15 13:11:14 +00001105 if (j != tid && DRD_(IsValidDrdThreadId)(j))
bart26f73e12008-02-24 18:37:08 +00001106 {
bart3772a982008-03-15 08:11:03 +00001107 const Segment* q;
bart324a23b2009-02-15 12:14:52 +00001108 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
bartd66e3a82008-04-06 15:02:17 +00001109 {
bart41b226c2009-02-14 16:55:19 +00001110 if (! DRD_(vc_lte)(&q->vc, &p->vc) && ! DRD_(vc_lte)(&p->vc, &q->vc))
bart3772a982008-03-15 08:11:03 +00001111 {
bart324a23b2009-02-15 12:14:52 +00001112 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001113 {
1114 char msg[256];
1115 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001116 "conflict set: [%d] merging segment ", j);
bart41b226c2009-02-14 16:55:19 +00001117 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1118 sizeof(msg) - VG_(strlen)(msg),
1119 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001120 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001121 }
bart99edb292009-02-15 15:59:20 +00001122 DRD_(bm_merge2)(*conflict_set, q->bm);
bart3772a982008-03-15 08:11:03 +00001123 }
1124 else
1125 {
bart324a23b2009-02-15 12:14:52 +00001126 if (DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001127 {
1128 char msg[256];
1129 VG_(snprintf)(msg, sizeof(msg),
barte73b0aa2008-06-28 07:19:56 +00001130 "conflict set: [%d] ignoring segment ", j);
bart41b226c2009-02-14 16:55:19 +00001131 DRD_(vc_snprint)(msg + VG_(strlen)(msg),
1132 sizeof(msg) - VG_(strlen)(msg),
1133 &q->vc);
barta2b6e1b2008-03-17 18:32:39 +00001134 VG_(message)(Vg_UserMsg, "%s", msg);
bart3772a982008-03-15 08:11:03 +00001135 }
1136 }
bartd66e3a82008-04-06 15:02:17 +00001137 }
bart26f73e12008-02-24 18:37:08 +00001138 }
bart3772a982008-03-15 08:11:03 +00001139 }
bart3772a982008-03-15 08:11:03 +00001140 }
sewardjaf44c822007-11-25 14:01:38 +00001141
bart99edb292009-02-15 15:59:20 +00001142 DRD_(s_conflict_set_bitmap_creation_count) += DRD_(bm_get_bitmap_creation_count)();
1143 DRD_(s_conflict_set_bitmap2_creation_count) += DRD_(bm_get_bitmap2_creation_count)();
sewardjaf44c822007-11-25 14:01:38 +00001144
bart324a23b2009-02-15 12:14:52 +00001145 if (0 && DRD_(s_trace_conflict_set))
bart3772a982008-03-15 08:11:03 +00001146 {
barte73b0aa2008-06-28 07:19:56 +00001147 VG_(message)(Vg_UserMsg, "[%d] new conflict set:", tid);
bart99edb292009-02-15 15:59:20 +00001148 DRD_(bm_print)(*conflict_set);
barte73b0aa2008-06-28 07:19:56 +00001149 VG_(message)(Vg_UserMsg, "[%d] end of new conflict set.", tid);
bart3772a982008-03-15 08:11:03 +00001150 }
sewardjaf44c822007-11-25 14:01:38 +00001151}
1152
bart62a784c2009-02-15 13:11:14 +00001153ULong DRD_(thread_get_context_switch_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001154{
bart324a23b2009-02-15 12:14:52 +00001155 return DRD_(s_context_switch_count);
sewardjaf44c822007-11-25 14:01:38 +00001156}
1157
bart62a784c2009-02-15 13:11:14 +00001158ULong DRD_(thread_get_discard_ordered_segments_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001159{
bart324a23b2009-02-15 12:14:52 +00001160 return DRD_(s_discard_ordered_segments_count);
sewardjaf44c822007-11-25 14:01:38 +00001161}
1162
bart62a784c2009-02-15 13:11:14 +00001163ULong DRD_(thread_get_update_conflict_set_count)(ULong* dsnsc, ULong* dscvc)
sewardjaf44c822007-11-25 14:01:38 +00001164{
bartd66e3a82008-04-06 15:02:17 +00001165 tl_assert(dsnsc);
1166 tl_assert(dscvc);
bart324a23b2009-02-15 12:14:52 +00001167 *dsnsc = DRD_(s_conflict_set_new_segment_count);
1168 *dscvc = DRD_(s_conflict_set_combine_vc_count);
1169 return DRD_(s_update_conflict_set_count);
sewardjaf44c822007-11-25 14:01:38 +00001170}
1171
bart62a784c2009-02-15 13:11:14 +00001172ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001173{
bart324a23b2009-02-15 12:14:52 +00001174 return DRD_(s_conflict_set_bitmap_creation_count);
sewardjaf44c822007-11-25 14:01:38 +00001175}
1176
bart62a784c2009-02-15 13:11:14 +00001177ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +00001178{
bart324a23b2009-02-15 12:14:52 +00001179 return DRD_(s_conflict_set_bitmap2_creation_count);
sewardjaf44c822007-11-25 14:01:38 +00001180}