1 /* -*- mode: C; c-basic-offset: 3; -*- */
2 /*
3 This file is part of drd, a thread error detector.
4
5 Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23 */
24
25
26 #include "drd_error.h"
27 #include "drd_barrier.h"
28 #include "drd_clientobj.h"
29 #include "drd_cond.h"
30 #include "drd_mutex.h"
31 #include "drd_segment.h"
32 #include "drd_semaphore.h"
33 #include "drd_suppression.h"
34 #include "drd_thread.h"
35 #include "pub_tool_vki.h"
36 #include "pub_tool_basics.h" // Addr, SizeT
37 #include "pub_tool_libcassert.h" // tl_assert()
38 #include "pub_tool_libcbase.h" // VG_(strlen)()
39 #include "pub_tool_libcprint.h" // VG_(printf)()
40 #include "pub_tool_libcproc.h" // VG_(getenv)()
41 #include "pub_tool_machine.h"
42 #include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)()
43 #include "pub_tool_options.h" // VG_(clo_backtrace_size)
44 #include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
45
46
47
48 /* Local functions. */
49
50 static void thread_append_segment(const DrdThreadId tid, Segment* const sg);
51 static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
52 static void thread_compute_conflict_set(struct bitmap** conflict_set,
53 const DrdThreadId tid);
54 static Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
55
56
57 /* Local variables. */
58
59 static ULong s_context_switch_count;
60 static ULong s_discard_ordered_segments_count;
61 static ULong s_compute_conflict_set_count;
62 static ULong s_update_conflict_set_count;
63 static ULong s_update_conflict_set_new_sg_count;
64 static ULong s_update_conflict_set_sync_count;
65 static ULong s_update_conflict_set_join_count;
66 static ULong s_conflict_set_bitmap_creation_count;
67 static ULong s_conflict_set_bitmap2_creation_count;
68 static ThreadId s_vg_running_tid = VG_INVALID_THREADID;
69 DrdThreadId DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
70 ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS];
71 struct bitmap* DRD_(g_conflict_set);
72 static Bool s_trace_context_switches = False;
73 static Bool s_trace_conflict_set = False;
74 static Bool s_trace_conflict_set_bm = False;
75 static Bool s_trace_fork_join = False;
76 static Bool s_segment_merging = True;
77 static Bool s_new_segments_since_last_merge;
78 static int s_segment_merge_interval = 10;
79
80
81 /* Function definitions. */
82
83 /** Enables/disables context switch tracing. */
DRD_(thread_trace_context_switches)84 void DRD_(thread_trace_context_switches)(const Bool t)
85 {
86 tl_assert(t == False || t == True);
87 s_trace_context_switches = t;
88 }
89
90 /** Enables/disables conflict set tracing. */
DRD_(thread_trace_conflict_set)91 void DRD_(thread_trace_conflict_set)(const Bool t)
92 {
93 tl_assert(t == False || t == True);
94 s_trace_conflict_set = t;
95 }
96
97 /** Enables/disables conflict set bitmap tracing. */
DRD_(thread_trace_conflict_set_bm)98 void DRD_(thread_trace_conflict_set_bm)(const Bool t)
99 {
100 tl_assert(t == False || t == True);
101 s_trace_conflict_set_bm = t;
102 }
103
104 /** Report whether fork/join tracing is enabled. */
DRD_(thread_get_trace_fork_join)105 Bool DRD_(thread_get_trace_fork_join)(void)
106 {
107 return s_trace_fork_join;
108 }
109
110 /** Enables/disables fork/join tracing. */
DRD_(thread_set_trace_fork_join)111 void DRD_(thread_set_trace_fork_join)(const Bool t)
112 {
113 tl_assert(t == False || t == True);
114 s_trace_fork_join = t;
115 }
116
117 /** Enables/disables segment merging. */
DRD_(thread_set_segment_merging)118 void DRD_(thread_set_segment_merging)(const Bool m)
119 {
120 tl_assert(m == False || m == True);
121 s_segment_merging = m;
122 }
123
124 /** Get the segment merging interval. */
DRD_(thread_get_segment_merge_interval)125 int DRD_(thread_get_segment_merge_interval)(void)
126 {
127 return s_segment_merge_interval;
128 }
129
130 /** Set the segment merging interval. */
DRD_(thread_set_segment_merge_interval)131 void DRD_(thread_set_segment_merge_interval)(const int i)
132 {
133 s_segment_merge_interval = i;
134 }
135
136 /**
137 * Convert Valgrind's ThreadId into a DrdThreadId.
138 *
139 * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
140 * Valgrind ThreadId does not yet exist.
141 */
DRD_(VgThreadIdToDrdThreadId)142 DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
143 {
144 int i;
145
146 if (tid == VG_INVALID_THREADID)
147 return DRD_INVALID_THREADID;
148
149 for (i = 1; i < DRD_N_THREADS; i++)
150 {
151 if (DRD_(g_threadinfo)[i].vg_thread_exists == True
152 && DRD_(g_threadinfo)[i].vg_threadid == tid)
153 {
154 return i;
155 }
156 }
157
158 return DRD_INVALID_THREADID;
159 }
160
161 /** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
DRD_(VgThreadIdToNewDrdThreadId)162 static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
163 {
164 int i;
165
166 tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
167
168 for (i = 1; i < DRD_N_THREADS; i++)
169 {
170 if (DRD_(g_threadinfo)[i].vg_thread_exists == False
171 && DRD_(g_threadinfo)[i].posix_thread_exists == False
172 && DRD_(g_threadinfo)[i].detached_posix_thread == False)
173 {
174 tl_assert(! DRD_(IsValidDrdThreadId)(i));
175
176 DRD_(g_threadinfo)[i].vg_thread_exists = True;
177 DRD_(g_threadinfo)[i].vg_threadid = tid;
178 DRD_(g_threadinfo)[i].pt_threadid = INVALID_POSIX_THREADID;
179 DRD_(g_threadinfo)[i].stack_min = 0;
180 DRD_(g_threadinfo)[i].stack_min_min = 0;
181 DRD_(g_threadinfo)[i].stack_startup = 0;
182 DRD_(g_threadinfo)[i].stack_max = 0;
183 DRD_(thread_set_name)(i, "");
184 DRD_(g_threadinfo)[i].on_alt_stack = False;
185 DRD_(g_threadinfo)[i].is_recording_loads = True;
186 DRD_(g_threadinfo)[i].is_recording_stores = True;
187 DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
188 DRD_(g_threadinfo)[i].synchr_nesting = 0;
189 tl_assert(DRD_(g_threadinfo)[i].first == 0);
190 tl_assert(DRD_(g_threadinfo)[i].last == 0);
191
192 tl_assert(DRD_(IsValidDrdThreadId)(i));
193
194 return i;
195 }
196 }
197
198 VG_(printf)(
199 "\nSorry, but the maximum number of threads supported by DRD has been exceeded."
200 "Aborting.\n");
201
202 tl_assert(False);
203
204 return DRD_INVALID_THREADID;
205 }
206
207 /** Convert a POSIX thread ID into a DRD thread ID. */
DRD_(PtThreadIdToDrdThreadId)208 DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
209 {
210 int i;
211
212 if (tid != INVALID_POSIX_THREADID)
213 {
214 for (i = 1; i < DRD_N_THREADS; i++)
215 {
216 if (DRD_(g_threadinfo)[i].posix_thread_exists
217 && DRD_(g_threadinfo)[i].pt_threadid == tid)
218 {
219 return i;
220 }
221 }
222 }
223 return DRD_INVALID_THREADID;
224 }
225
226 /** Convert a DRD thread ID into a Valgrind thread ID. */
DRD_(DrdThreadIdToVgThreadId)227 ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
228 {
229 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
230 && tid != DRD_INVALID_THREADID);
231
232 return (DRD_(g_threadinfo)[tid].vg_thread_exists
233 ? DRD_(g_threadinfo)[tid].vg_threadid
234 : VG_INVALID_THREADID);
235 }
236
237 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
238 /**
239 * Sanity check of the doubly linked list of segments referenced by a
240 * ThreadInfo struct.
241 * @return True if sane, False if not.
242 */
DRD_(sane_ThreadInfo)243 static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
244 {
245 Segment* p;
246
247 for (p = ti->first; p; p = p->next) {
248 if (p->next && p->next->prev != p)
249 return False;
250 if (p->next == 0 && p != ti->last)
251 return False;
252 }
253 for (p = ti->last; p; p = p->prev) {
254 if (p->prev && p->prev->next != p)
255 return False;
256 if (p->prev == 0 && p != ti->first)
257 return False;
258 }
259 return True;
260 }
261 #endif
262
263 /**
264 * Create the first segment for a newly started thread.
265 *
266 * This function is called from the handler installed via
267 * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
268 * from the context of the creator thread, before the new thread has been
269 * created.
270 *
271 * @param[in] creator DRD thread ID of the creator thread.
272 * @param[in] vg_created Valgrind thread ID of the created thread.
273 *
274 * @return DRD thread ID of the created thread.
275 */
DRD_(thread_pre_create)276 DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
277 const ThreadId vg_created)
278 {
279 DrdThreadId created;
280
281 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
282 created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
283 tl_assert(0 <= (int)created && created < DRD_N_THREADS
284 && created != DRD_INVALID_THREADID);
285
286 tl_assert(DRD_(g_threadinfo)[created].first == 0);
287 tl_assert(DRD_(g_threadinfo)[created].last == 0);
288 /* Create an initial segment for the newly created thread. */
289 thread_append_segment(created, DRD_(sg_new)(creator, created));
290
291 return created;
292 }
293
294 /**
295 * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
296 * after the thread has been created and before any client instructions are run
297 * on the newly created thread, e.g. from the handler installed via
298 * VG_(track_pre_thread_first_insn)().
299 *
300 * @param[in] vg_created Valgrind thread ID of the newly created thread.
301 *
302 * @return DRD thread ID for the new thread.
303 */
DRD_(thread_post_create)304 DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
305 {
306 const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
307
308 tl_assert(0 <= (int)created && created < DRD_N_THREADS
309 && created != DRD_INVALID_THREADID);
310
311 DRD_(g_threadinfo)[created].stack_max
312 = VG_(thread_get_stack_max)(vg_created);
313 DRD_(g_threadinfo)[created].stack_startup
314 = DRD_(g_threadinfo)[created].stack_max;
315 DRD_(g_threadinfo)[created].stack_min
316 = DRD_(g_threadinfo)[created].stack_max;
317 DRD_(g_threadinfo)[created].stack_min_min
318 = DRD_(g_threadinfo)[created].stack_max;
319 DRD_(g_threadinfo)[created].stack_size
320 = VG_(thread_get_stack_size)(vg_created);
321 tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
322
323 return created;
324 }
325
326 /**
327 * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
328 * after thread drd_joiner joined thread drd_joinee.
329 */
DRD_(thread_post_join)330 void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
331 {
332 tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
333 tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
334
335 DRD_(thread_new_segment)(drd_joiner);
336 DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
337 DRD_(thread_new_segment)(drd_joinee);
338
339 if (s_trace_fork_join)
340 {
341 const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
342 const unsigned msg_size = 256;
343 char* msg;
344
345 msg = VG_(malloc)("drd.main.dptj.1", msg_size);
346 tl_assert(msg);
347 VG_(snprintf)(msg, msg_size,
348 "drd_post_thread_join joiner = %d, joinee = %d",
349 drd_joiner, drd_joinee);
350 if (joiner)
351 {
352 char* vc;
353
354 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
355 VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
356 ", new vc: %s", vc);
357 VG_(free)(vc);
358 }
359 VG_(message)(Vg_DebugMsg, "%s\n", msg);
360 VG_(free)(msg);
361 }
362
363 if (! DRD_(get_check_stack_accesses)())
364 {
365 DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
366 - DRD_(thread_get_stack_size)(drd_joinee),
367 DRD_(thread_get_stack_max)(drd_joinee));
368 }
369 DRD_(clientobj_delete_thread)(drd_joinee);
370 DRD_(thread_delete)(drd_joinee, False);
371 }
372
373 /**
374 * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
375 * and accesses this data structure from multiple threads without locking.
376 * Any conflicting accesses in the range stack_startup..stack_max will be
377 * ignored.
378 */
DRD_(thread_set_stack_startup)379 void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
380 const Addr stack_startup)
381 {
382 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
383 && tid != DRD_INVALID_THREADID);
384 tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
385 tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
386 DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
387 }
388
389 /** Return the stack pointer for the specified thread. */
DRD_(thread_get_stack_min)390 Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
391 {
392 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
393 && tid != DRD_INVALID_THREADID);
394 return DRD_(g_threadinfo)[tid].stack_min;
395 }
396
397 /**
398 * Return the lowest value that was ever assigned to the stack pointer
399 * for the specified thread.
400 */
DRD_(thread_get_stack_min_min)401 Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
402 {
403 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
404 && tid != DRD_INVALID_THREADID);
405 return DRD_(g_threadinfo)[tid].stack_min_min;
406 }
407
408 /** Return the top address for the stack of the specified thread. */
DRD_(thread_get_stack_max)409 Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
410 {
411 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
412 && tid != DRD_INVALID_THREADID);
413 return DRD_(g_threadinfo)[tid].stack_max;
414 }
415
416 /** Return the maximum stack size for the specified thread. */
DRD_(thread_get_stack_size)417 SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
418 {
419 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
420 && tid != DRD_INVALID_THREADID);
421 return DRD_(g_threadinfo)[tid].stack_size;
422 }
423
DRD_(thread_get_on_alt_stack)424 Bool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid)
425 {
426 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
427 && tid != DRD_INVALID_THREADID);
428 return DRD_(g_threadinfo)[tid].on_alt_stack;
429 }
430
DRD_(thread_set_on_alt_stack)431 void DRD_(thread_set_on_alt_stack)(const DrdThreadId tid,
432 const Bool on_alt_stack)
433 {
434 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
435 && tid != DRD_INVALID_THREADID);
436 tl_assert(on_alt_stack == !!on_alt_stack);
437 DRD_(g_threadinfo)[tid].on_alt_stack = on_alt_stack;
438 }
439
DRD_(thread_get_threads_on_alt_stack)440 Int DRD_(thread_get_threads_on_alt_stack)(void)
441 {
442 int i, n = 0;
443
444 for (i = 1; i < DRD_N_THREADS; i++)
445 n += DRD_(g_threadinfo)[i].on_alt_stack;
446 return n;
447 }
448
449 /**
450 * Clean up thread-specific data structures. Call this just after
451 * pthread_join().
452 */
DRD_(thread_delete)453 void DRD_(thread_delete)(const DrdThreadId tid, const Bool detached)
454 {
455 Segment* sg;
456 Segment* sg_prev;
457
458 tl_assert(DRD_(IsValidDrdThreadId)(tid));
459
460 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
461 for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
462 {
463 sg_prev = sg->prev;
464 sg->prev = 0;
465 sg->next = 0;
466 DRD_(sg_put)(sg);
467 }
468 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
469 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
470 if (detached)
471 DRD_(g_threadinfo)[tid].detached_posix_thread = False;
472 else
473 tl_assert(!DRD_(g_threadinfo)[tid].detached_posix_thread);
474 DRD_(g_threadinfo)[tid].first = 0;
475 DRD_(g_threadinfo)[tid].last = 0;
476
477 tl_assert(! DRD_(IsValidDrdThreadId)(tid));
478 }
479
480 /**
481 * Called after a thread performed its last memory access and before
482 * thread_delete() is called. Note: thread_delete() is only called for
483 * joinable threads, not for detached threads.
484 */
DRD_(thread_finished)485 void DRD_(thread_finished)(const DrdThreadId tid)
486 {
487 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
488 && tid != DRD_INVALID_THREADID);
489
490 DRD_(g_threadinfo)[tid].vg_thread_exists = False;
491
492 if (DRD_(g_threadinfo)[tid].detached_posix_thread)
493 {
494 /*
495 * Once a detached thread has finished, its stack is deallocated and
496 * should no longer be taken into account when computing the conflict set.
497 */
498 DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
499
500 /*
501 * For a detached thread, calling pthread_exit() invalidates the
502 * POSIX thread ID associated with the detached thread. For joinable
503 * POSIX threads however, the POSIX thread ID remains live after the
504 * pthread_exit() call until pthread_join() is called.
505 */
506 DRD_(g_threadinfo)[tid].posix_thread_exists = False;
507 }
508 }
509
510 /** Called just after fork() in the child process. */
DRD_(drd_thread_atfork_child)511 void DRD_(drd_thread_atfork_child)(const DrdThreadId tid)
512 {
513 unsigned i;
514
515 for (i = 1; i < DRD_N_THREADS; i++)
516 {
517 if (i == tid)
518 continue;
519 if (DRD_(IsValidDrdThreadId(i)))
520 DRD_(thread_delete)(i, True);
521 tl_assert(!DRD_(IsValidDrdThreadId(i)));
522 }
523 }
524
525 /** Called just before pthread_cancel(). */
DRD_(thread_pre_cancel)526 void DRD_(thread_pre_cancel)(const DrdThreadId tid)
527 {
528 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
529 && tid != DRD_INVALID_THREADID);
530 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
531
532 DRD_(g_threadinfo)[tid].synchr_nesting = 0;
533 }
534
535 /**
536 * Store the POSIX thread ID for the specified thread.
537 *
538 * @note This function can be called two times for the same thread -- see also
539 * the comment block preceding the pthread_create() wrapper in
540 * drd_pthread_intercepts.c.
541 */
DRD_(thread_set_pthreadid)542 void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
543 {
544 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
545 && tid != DRD_INVALID_THREADID);
546 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
547 || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
548 tl_assert(ptid != INVALID_POSIX_THREADID);
549 DRD_(g_threadinfo)[tid].posix_thread_exists = True;
550 DRD_(g_threadinfo)[tid].pt_threadid = ptid;
551 }
552
553 /** Returns true for joinable threads and false for detached threads. */
DRD_(thread_get_joinable)554 Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
555 {
556 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
557 && tid != DRD_INVALID_THREADID);
558 return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
559 }
560
561 /** Store the thread mode: joinable or detached. */
DRD_(thread_set_joinable)562 void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
563 {
564 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
565 && tid != DRD_INVALID_THREADID);
566 tl_assert(!! joinable == joinable);
567 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
568
569 DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
570 }
571
572 /** Tells DRD that the calling thread is about to enter pthread_create(). */
DRD_(thread_entering_pthread_create)573 void DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
574 {
575 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
576 && tid != DRD_INVALID_THREADID);
577 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
578 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
579
580 DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
581 }
582
583 /** Tells DRD that the calling thread has left pthread_create(). */
DRD_(thread_left_pthread_create)584 void DRD_(thread_left_pthread_create)(const DrdThreadId tid)
585 {
586 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
587 && tid != DRD_INVALID_THREADID);
588 tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
589 tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
590
591 DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
592 }
593
594 /** Obtain the thread number and the user-assigned thread name. */
DRD_(thread_get_name)595 const char* DRD_(thread_get_name)(const DrdThreadId tid)
596 {
597 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
598 && tid != DRD_INVALID_THREADID);
599
600 return DRD_(g_threadinfo)[tid].name;
601 }
602
603 /** Set the name of the specified thread. */
DRD_(thread_set_name)604 void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
605 {
606 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
607 && tid != DRD_INVALID_THREADID);
608
609 if (name == NULL || name[0] == 0)
610 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
611 sizeof(DRD_(g_threadinfo)[tid].name),
612 "Thread %d",
613 tid);
614 else
615 VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
616 sizeof(DRD_(g_threadinfo)[tid].name),
617 "Thread %d (%s)",
618 tid, name);
619 DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
620 }
621
622 /**
623 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
624 * conflict set.
625 */
DRD_(thread_set_vg_running_tid)626 void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
627 {
628 tl_assert(vg_tid != VG_INVALID_THREADID);
629
630 if (vg_tid != s_vg_running_tid)
631 {
632 DRD_(thread_set_running_tid)(vg_tid,
633 DRD_(VgThreadIdToDrdThreadId)(vg_tid));
634 }
635
636 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
637 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
638 }
639
640 /**
641 * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
642 * conflict set.
643 */
DRD_(thread_set_running_tid)644 void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
645 const DrdThreadId drd_tid)
646 {
647 tl_assert(vg_tid != VG_INVALID_THREADID);
648 tl_assert(drd_tid != DRD_INVALID_THREADID);
649
650 if (vg_tid != s_vg_running_tid)
651 {
652 if (s_trace_context_switches
653 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
654 {
655 VG_(message)(Vg_DebugMsg,
656 "Context switch from thread %d to thread %d;"
657 " segments: %llu\n",
658 DRD_(g_drd_running_tid), drd_tid,
659 DRD_(sg_get_segments_alive_count)());
660 }
661 s_vg_running_tid = vg_tid;
662 DRD_(g_drd_running_tid) = drd_tid;
663 thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
664 s_context_switch_count++;
665 }
666
667 tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
668 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
669 }
670
671 /**
672 * Increase the synchronization nesting counter. Must be called before the
673 * client calls a synchronization function.
674 */
DRD_(thread_enter_synchr)675 int DRD_(thread_enter_synchr)(const DrdThreadId tid)
676 {
677 tl_assert(DRD_(IsValidDrdThreadId)(tid));
678 return DRD_(g_threadinfo)[tid].synchr_nesting++;
679 }
680
681 /**
682 * Decrease the synchronization nesting counter. Must be called after the
683 * client left a synchronization function.
684 */
DRD_(thread_leave_synchr)685 int DRD_(thread_leave_synchr)(const DrdThreadId tid)
686 {
687 tl_assert(DRD_(IsValidDrdThreadId)(tid));
688 tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
689 return --DRD_(g_threadinfo)[tid].synchr_nesting;
690 }
691
692 /** Returns the synchronization nesting counter. */
DRD_(thread_get_synchr_nesting_count)693 int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
694 {
695 tl_assert(DRD_(IsValidDrdThreadId)(tid));
696 return DRD_(g_threadinfo)[tid].synchr_nesting;
697 }
698
699 /** Append a new segment at the end of the segment list. */
700 static
thread_append_segment(const DrdThreadId tid,Segment * const sg)701 void thread_append_segment(const DrdThreadId tid, Segment* const sg)
702 {
703 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
704 && tid != DRD_INVALID_THREADID);
705
706 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
707 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
708 #endif
709
710 sg->prev = DRD_(g_threadinfo)[tid].last;
711 sg->next = 0;
712 if (DRD_(g_threadinfo)[tid].last)
713 DRD_(g_threadinfo)[tid].last->next = sg;
714 DRD_(g_threadinfo)[tid].last = sg;
715 if (DRD_(g_threadinfo)[tid].first == 0)
716 DRD_(g_threadinfo)[tid].first = sg;
717
718 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
719 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
720 #endif
721 }
722
723 /**
724 * Remove a segment from the segment list of thread threadid, and free the
725 * associated memory.
726 */
727 static
thread_discard_segment(const DrdThreadId tid,Segment * const sg)728 void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
729 {
730 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
731 && tid != DRD_INVALID_THREADID);
732
733 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
734 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
735 #endif
736
737 if (sg->prev)
738 sg->prev->next = sg->next;
739 if (sg->next)
740 sg->next->prev = sg->prev;
741 if (sg == DRD_(g_threadinfo)[tid].first)
742 DRD_(g_threadinfo)[tid].first = sg->next;
743 if (sg == DRD_(g_threadinfo)[tid].last)
744 DRD_(g_threadinfo)[tid].last = sg->prev;
745 DRD_(sg_put)(sg);
746
747 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
748 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
749 #endif
750 }
751
752 /**
753 * Returns a pointer to the vector clock of the most recent segment associated
754 * with thread 'tid'.
755 */
DRD_(thread_get_vc)756 VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
757 {
758 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
759 && tid != DRD_INVALID_THREADID);
760 tl_assert(DRD_(g_threadinfo)[tid].last);
761 return &DRD_(g_threadinfo)[tid].last->vc;
762 }
763
764 /**
765 * Return the latest segment of thread 'tid' and increment its reference count.
766 */
DRD_(thread_get_latest_segment)767 void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
768 {
769 tl_assert(sg);
770 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
771 && tid != DRD_INVALID_THREADID);
772 tl_assert(DRD_(g_threadinfo)[tid].last);
773
774 DRD_(sg_put)(*sg);
775 *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
776 }
777
778 /**
779 * Compute the minimum of all latest vector clocks of all threads
780 * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
781 *
782 * @param vc pointer to a vectorclock, holds result upon return.
783 */
DRD_(thread_compute_minimum_vc)784 static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
785 {
786 unsigned i;
787 Bool first;
788 Segment* latest_sg;
789
790 first = True;
791 for (i = 0; i < DRD_N_THREADS; i++)
792 {
793 latest_sg = DRD_(g_threadinfo)[i].last;
794 if (latest_sg)
795 {
796 if (first)
797 DRD_(vc_assign)(vc, &latest_sg->vc);
798 else
799 DRD_(vc_min)(vc, &latest_sg->vc);
800 first = False;
801 }
802 }
803 }
804
805 /**
806 * Compute the maximum of all latest vector clocks of all threads.
807 *
808 * @param vc pointer to a vectorclock, holds result upon return.
809 */
DRD_(thread_compute_maximum_vc)810 static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
811 {
812 unsigned i;
813 Bool first;
814 Segment* latest_sg;
815
816 first = True;
817 for (i = 0; i < DRD_N_THREADS; i++)
818 {
819 latest_sg = DRD_(g_threadinfo)[i].last;
820 if (latest_sg)
821 {
822 if (first)
823 DRD_(vc_assign)(vc, &latest_sg->vc);
824 else
825 DRD_(vc_combine)(vc, &latest_sg->vc);
826 first = False;
827 }
828 }
829 }
830
831 /**
832 * Discard all segments that have a defined order against the latest vector
833 * clock of all threads -- these segments can no longer be involved in a
834 * data race.
835 */
thread_discard_ordered_segments(void)836 static void thread_discard_ordered_segments(void)
837 {
838 unsigned i;
839 VectorClock thread_vc_min;
840
841 s_discard_ordered_segments_count++;
842
843 DRD_(vc_init)(&thread_vc_min, 0, 0);
844 DRD_(thread_compute_minimum_vc)(&thread_vc_min);
845 if (DRD_(sg_get_trace)())
846 {
847 char *vc_min, *vc_max;
848 VectorClock thread_vc_max;
849
850 DRD_(vc_init)(&thread_vc_max, 0, 0);
851 DRD_(thread_compute_maximum_vc)(&thread_vc_max);
852 vc_min = DRD_(vc_aprint)(&thread_vc_min);
853 vc_max = DRD_(vc_aprint)(&thread_vc_max);
854 VG_(message)(Vg_DebugMsg,
855 "Discarding ordered segments -- min vc is %s, max vc is %s\n",
856 vc_min, vc_max);
857 VG_(free)(vc_min);
858 VG_(free)(vc_max);
859 DRD_(vc_cleanup)(&thread_vc_max);
860 }
861
862 for (i = 0; i < DRD_N_THREADS; i++)
863 {
864 Segment* sg;
865 Segment* sg_next;
866 for (sg = DRD_(g_threadinfo)[i].first;
867 sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
868 sg = sg_next)
869 {
870 thread_discard_segment(i, sg);
871 }
872 }
873 DRD_(vc_cleanup)(&thread_vc_min);
874 }
875
876 /**
877 * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
878 * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
879 * all segments in the set CS are ordered consistently against both sg1 and
880 * sg2. The set CS is defined as the set of segments that can immediately
881 * precede future segments via inter-thread synchronization operations. In
882 * DRD the set CS consists of the latest segment of each thread combined with
883 * all segments for which the reference count is strictly greater than one.
884 * The code below is an optimized version of the following:
885 *
886 * for (i = 0; i < DRD_N_THREADS; i++)
887 * {
888 * Segment* sg;
889 *
890 * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
891 * {
892 * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
893 * {
894 * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
895 * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
896 * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
897 * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
898 * {
899 * return False;
900 * }
901 * }
902 * }
903 * }
904 */
thread_consistent_segment_ordering(const DrdThreadId tid,Segment * const sg1,Segment * const sg2)905 static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
906 Segment* const sg1,
907 Segment* const sg2)
908 {
909 unsigned i;
910
911 tl_assert(sg1->next);
912 tl_assert(sg2->next);
913 tl_assert(sg1->next == sg2);
914 tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
915
916 for (i = 0; i < DRD_N_THREADS; i++)
917 {
918 Segment* sg;
919
920 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
921 {
922 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
923 {
924 if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
925 break;
926 if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
927 return False;
928 }
929 }
930 for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
931 {
932 if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
933 {
934 if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
935 break;
936 if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
937 return False;
938 }
939 }
940 }
941 return True;
942 }
943
944 /**
945 * Merge all segments that may be merged without triggering false positives
946 * or discarding real data races. For the theoretical background of segment
947 * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
948 * and Koen De Bosschere. Bounding the number of segment histories during
949 * data race detection. Parallel Computing archive, Volume 28, Issue 9,
950 * pp 1221-1238, September 2002. This paper contains a proof that merging
951 * consecutive segments for which the property equiv(s1,s2) holds can be
952 * merged without reducing the accuracy of datarace detection. Furthermore
953 * it is also proven that the total number of all segments will never grow
954 * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
955 * every time a new segment is created. The property equiv(s1, s2) is defined
956 * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
957 * clocks of segments s and s1 are ordered in the same way as those of segments
958 * s and s2. The set CS is defined as the set of existing segments s that have
959 * the potential to conflict with not yet created segments, either because the
960 * segment s is the latest segment of a thread or because it can become the
961 * immediate predecessor of a new segment due to a synchronization operation.
962 */
thread_merge_segments(void)963 static void thread_merge_segments(void)
964 {
965 unsigned i;
966
967 s_new_segments_since_last_merge = 0;
968
969 for (i = 0; i < DRD_N_THREADS; i++)
970 {
971 Segment* sg;
972
973 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
974 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
975 #endif
976
977 for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
978 {
979 if (DRD_(sg_get_refcnt)(sg) == 1
980 && sg->next
981 && DRD_(sg_get_refcnt)(sg->next) == 1
982 && sg->next->next
983 && thread_consistent_segment_ordering(i, sg, sg->next))
984 {
985 /* Merge sg and sg->next into sg. */
986 DRD_(sg_merge)(sg, sg->next);
987 thread_discard_segment(i, sg->next);
988 }
989 }
990
991 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
992 tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
993 #endif
994 }
995 }
996
997 /**
998 * Create a new segment for the specified thread, and discard any segments
999 * that cannot cause races anymore.
1000 */
DRD_(thread_new_segment)1001 void DRD_(thread_new_segment)(const DrdThreadId tid)
1002 {
1003 Segment* last_sg;
1004 Segment* new_sg;
1005
1006 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1007 && tid != DRD_INVALID_THREADID);
1008 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1009
1010 last_sg = DRD_(g_threadinfo)[tid].last;
1011 new_sg = DRD_(sg_new)(tid, tid);
1012 thread_append_segment(tid, new_sg);
1013 if (tid == DRD_(g_drd_running_tid) && last_sg)
1014 {
1015 DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
1016 s_update_conflict_set_new_sg_count++;
1017 }
1018
1019 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1020
1021 if (s_segment_merging
1022 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1023 {
1024 thread_discard_ordered_segments();
1025 thread_merge_segments();
1026 }
1027 }
1028
1029 /** Call this function after thread 'joiner' joined thread 'joinee'. */
DRD_(thread_combine_vc_join)1030 void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
1031 {
1032 tl_assert(joiner != joinee);
1033 tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
1034 && joiner != DRD_INVALID_THREADID);
1035 tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
1036 && joinee != DRD_INVALID_THREADID);
1037 tl_assert(DRD_(g_threadinfo)[joiner].last);
1038 tl_assert(DRD_(g_threadinfo)[joinee].last);
1039
1040 if (DRD_(sg_get_trace)())
1041 {
1042 char *str1, *str2;
1043 str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
1044 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
1045 VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
1046 str1, str2);
1047 VG_(free)(str1);
1048 VG_(free)(str2);
1049 }
1050 if (joiner == DRD_(g_drd_running_tid))
1051 {
1052 VectorClock old_vc;
1053
1054 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[joiner].last->vc);
1055 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
1056 &DRD_(g_threadinfo)[joinee].last->vc);
1057 DRD_(thread_update_conflict_set)(joiner, &old_vc);
1058 s_update_conflict_set_join_count++;
1059 DRD_(vc_cleanup)(&old_vc);
1060 }
1061 else
1062 {
1063 DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
1064 &DRD_(g_threadinfo)[joinee].last->vc);
1065 }
1066
1067 thread_discard_ordered_segments();
1068
1069 if (DRD_(sg_get_trace)())
1070 {
1071 char* str;
1072 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
1073 VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
1074 VG_(free)(str);
1075 }
1076 }
1077
1078 /**
1079 * Update the vector clock of the last segment of thread tid with the
1080 * the vector clock of segment sg.
1081 */
thread_combine_vc_sync(DrdThreadId tid,const Segment * sg)1082 static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
1083 {
1084 const VectorClock* const vc = &sg->vc;
1085
1086 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1087 && tid != DRD_INVALID_THREADID);
1088 tl_assert(DRD_(g_threadinfo)[tid].last);
1089 tl_assert(sg);
1090 tl_assert(vc);
1091
1092 if (tid != sg->tid)
1093 {
1094 VectorClock old_vc;
1095
1096 DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
1097 DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
1098 if (DRD_(sg_get_trace)())
1099 {
1100 char *str1, *str2;
1101 str1 = DRD_(vc_aprint)(&old_vc);
1102 str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1103 VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
1104 VG_(free)(str1);
1105 VG_(free)(str2);
1106 }
1107
1108 thread_discard_ordered_segments();
1109
1110 DRD_(thread_update_conflict_set)(tid, &old_vc);
1111 s_update_conflict_set_sync_count++;
1112
1113 DRD_(vc_cleanup)(&old_vc);
1114 }
1115 else
1116 {
1117 tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
1118 }
1119 }
1120
1121 /**
1122 * Create a new segment for thread tid and update the vector clock of the last
1123 * segment of this thread with the the vector clock of segment sg. Call this
1124 * function after thread tid had to wait because of thread synchronization
1125 * until the memory accesses in the segment sg finished.
1126 */
DRD_(thread_new_segment_and_combine_vc)1127 void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
1128 {
1129 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1130 && tid != DRD_INVALID_THREADID);
1131 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1132 tl_assert(sg);
1133
1134 thread_append_segment(tid, DRD_(sg_new)(tid, tid));
1135
1136 thread_combine_vc_sync(tid, sg);
1137
1138 if (s_segment_merging
1139 && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1140 {
1141 thread_discard_ordered_segments();
1142 thread_merge_segments();
1143 }
1144 }
1145
1146 /**
1147 * Call this function whenever a thread is no longer using the memory
1148 * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1149 * increase.
1150 */
DRD_(thread_stop_using_mem)1151 void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2,
1152 const Bool dont_clear_access)
1153 {
1154 DrdThreadId other_user;
1155 unsigned i;
1156
1157 /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
1158 other_user = DRD_INVALID_THREADID;
1159 for (i = 0; i < DRD_N_THREADS; i++)
1160 {
1161 Segment* p;
1162 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1163 {
1164 if (other_user == DRD_INVALID_THREADID
1165 && i != DRD_(g_drd_running_tid))
1166 {
1167 if (UNLIKELY((!dont_clear_access
1168 && DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2))
1169 || (dont_clear_access
1170 && DRD_(bm_has_any_access)(DRD_(sg_bm)(p), a1, a2))
1171 ))
1172 {
1173 other_user = i;
1174 }
1175 continue;
1176 }
1177 if (!dont_clear_access)
1178 DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
1179 }
1180 }
1181
1182 /*
1183 * If any other thread had accessed memory in [ a1, a2 [, update the
1184 * conflict set.
1185 */
1186 if (other_user != DRD_INVALID_THREADID
1187 && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
1188 {
1189 thread_compute_conflict_set(&DRD_(g_conflict_set),
1190 DRD_(thread_get_running_tid)());
1191 }
1192 }
1193
1194 /** Specify whether memory loads should be recorded. */
DRD_(thread_set_record_loads)1195 void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
1196 {
1197 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1198 && tid != DRD_INVALID_THREADID);
1199 tl_assert(enabled == !! enabled);
1200
1201 DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
1202 }
1203
1204 /** Specify whether memory stores should be recorded. */
DRD_(thread_set_record_stores)1205 void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
1206 {
1207 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1208 && tid != DRD_INVALID_THREADID);
1209 tl_assert(enabled == !! enabled);
1210
1211 DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
1212 }
1213
1214 /**
1215 * Print the segment information for all threads.
1216 *
1217 * This function is only used for debugging purposes.
1218 */
DRD_(thread_print_all)1219 void DRD_(thread_print_all)(void)
1220 {
1221 unsigned i;
1222 Segment* p;
1223
1224 for (i = 0; i < DRD_N_THREADS; i++)
1225 {
1226 if (DRD_(g_threadinfo)[i].first)
1227 {
1228 VG_(printf)("**************\n"
1229 "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
1230 "**************\n",
1231 i,
1232 DRD_(g_threadinfo)[i].vg_thread_exists,
1233 DRD_(g_threadinfo)[i].vg_threadid,
1234 DRD_(g_threadinfo)[i].posix_thread_exists,
1235 DRD_(g_threadinfo)[i].pt_threadid,
1236 DRD_(g_threadinfo)[i].detached_posix_thread);
1237 for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
1238 {
1239 DRD_(sg_print)(p);
1240 }
1241 }
1242 }
1243 }
1244
1245 /** Show a call stack involved in a data race. */
show_call_stack(const DrdThreadId tid,const Char * const msg,ExeContext * const callstack)1246 static void show_call_stack(const DrdThreadId tid,
1247 const Char* const msg,
1248 ExeContext* const callstack)
1249 {
1250 const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
1251
1252 VG_(message)(Vg_UserMsg, "%s (thread %d)\n", msg, tid);
1253
1254 if (vg_tid != VG_INVALID_THREADID)
1255 {
1256 if (callstack)
1257 {
1258 VG_(pp_ExeContext)(callstack);
1259 }
1260 else
1261 {
1262 VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1263 }
1264 }
1265 else
1266 {
1267 VG_(message)(Vg_UserMsg,
1268 " (thread finished, call stack no longer available)\n");
1269 }
1270 }
1271
1272 /** Print information about the segments involved in a data race. */
1273 static void
thread_report_conflicting_segments_segment(const DrdThreadId tid,const Addr addr,const SizeT size,const BmAccessTypeT access_type,const Segment * const p)1274 thread_report_conflicting_segments_segment(const DrdThreadId tid,
1275 const Addr addr,
1276 const SizeT size,
1277 const BmAccessTypeT access_type,
1278 const Segment* const p)
1279 {
1280 unsigned i;
1281
1282 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1283 && tid != DRD_INVALID_THREADID);
1284 tl_assert(p);
1285
1286 for (i = 0; i < DRD_N_THREADS; i++)
1287 {
1288 if (i != tid)
1289 {
1290 Segment* q;
1291 for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
1292 {
1293 /*
1294 * Since q iterates over the segments of thread i in order of
1295 * decreasing vector clocks, if q->vc <= p->vc, then
1296 * q->next->vc <= p->vc will also hold. Hence, break out of the
1297 * loop once this condition is met.
1298 */
1299 if (DRD_(vc_lte)(&q->vc, &p->vc))
1300 break;
1301 if (! DRD_(vc_lte)(&p->vc, &q->vc))
1302 {
1303 if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
1304 access_type))
1305 {
1306 tl_assert(q->stacktrace);
1307 show_call_stack(i, "Other segment start",
1308 q->stacktrace);
1309 show_call_stack(i, "Other segment end",
1310 q->next ? q->next->stacktrace : 0);
1311 }
1312 }
1313 }
1314 }
1315 }
1316 }
1317
1318 /** Print information about all segments involved in a data race. */
DRD_(thread_report_conflicting_segments)1319 void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
1320 const Addr addr,
1321 const SizeT size,
1322 const BmAccessTypeT access_type)
1323 {
1324 Segment* p;
1325
1326 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1327 && tid != DRD_INVALID_THREADID);
1328
1329 for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
1330 {
1331 if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
1332 {
1333 thread_report_conflicting_segments_segment(tid, addr, size,
1334 access_type, p);
1335 }
1336 }
1337 }
1338
1339 /**
1340 * Verify whether the conflict set for thread tid is up to date. Only perform
1341 * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
1342 */
thread_conflict_set_up_to_date(const DrdThreadId tid)1343 static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
1344 {
1345 static int do_verify_conflict_set = -1;
1346 Bool result;
1347 struct bitmap* computed_conflict_set = 0;
1348
1349 if (do_verify_conflict_set < 0)
1350 do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
1351
1352 if (do_verify_conflict_set == 0)
1353 return True;
1354
1355 thread_compute_conflict_set(&computed_conflict_set, tid);
1356 result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
1357 if (! result)
1358 {
1359 VG_(printf)("actual conflict set:\n");
1360 DRD_(bm_print)(DRD_(g_conflict_set));
1361 VG_(printf)("\n");
1362 VG_(printf)("computed conflict set:\n");
1363 DRD_(bm_print)(computed_conflict_set);
1364 VG_(printf)("\n");
1365 }
1366 DRD_(bm_delete)(computed_conflict_set);
1367 return result;
1368 }
1369
1370 /**
1371 * Compute the conflict set: a bitmap that represents the union of all memory
1372 * accesses of all segments that are unordered to the current segment of the
1373 * thread tid.
1374 */
thread_compute_conflict_set(struct bitmap ** conflict_set,const DrdThreadId tid)1375 static void thread_compute_conflict_set(struct bitmap** conflict_set,
1376 const DrdThreadId tid)
1377 {
1378 Segment* p;
1379
1380 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1381 && tid != DRD_INVALID_THREADID);
1382 tl_assert(tid == DRD_(g_drd_running_tid));
1383
1384 s_compute_conflict_set_count++;
1385 s_conflict_set_bitmap_creation_count
1386 -= DRD_(bm_get_bitmap_creation_count)();
1387 s_conflict_set_bitmap2_creation_count
1388 -= DRD_(bm_get_bitmap2_creation_count)();
1389
1390 if (*conflict_set)
1391 {
1392 DRD_(bm_cleanup)(*conflict_set);
1393 DRD_(bm_init)(*conflict_set);
1394 }
1395 else
1396 {
1397 *conflict_set = DRD_(bm_new)();
1398 }
1399
1400 if (s_trace_conflict_set)
1401 {
1402 char* str;
1403
1404 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1405 VG_(message)(Vg_DebugMsg,
1406 "computing conflict set for thread %d with vc %s\n",
1407 tid, str);
1408 VG_(free)(str);
1409 }
1410
1411 p = DRD_(g_threadinfo)[tid].last;
1412 {
1413 unsigned j;
1414
1415 if (s_trace_conflict_set)
1416 {
1417 char* vc;
1418
1419 vc = DRD_(vc_aprint)(&p->vc);
1420 VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
1421 tid, vc);
1422 VG_(free)(vc);
1423 }
1424
1425 for (j = 0; j < DRD_N_THREADS; j++)
1426 {
1427 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1428 {
1429 Segment* q;
1430 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1431 {
1432 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1433 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1434 {
1435 if (s_trace_conflict_set)
1436 {
1437 char* str;
1438
1439 str = DRD_(vc_aprint)(&q->vc);
1440 VG_(message)(Vg_DebugMsg,
1441 "conflict set: [%d] merging segment %s\n",
1442 j, str);
1443 VG_(free)(str);
1444 }
1445 DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
1446 }
1447 else
1448 {
1449 if (s_trace_conflict_set)
1450 {
1451 char* str;
1452
1453 str = DRD_(vc_aprint)(&q->vc);
1454 VG_(message)(Vg_DebugMsg,
1455 "conflict set: [%d] ignoring segment %s\n",
1456 j, str);
1457 VG_(free)(str);
1458 }
1459 }
1460 }
1461 }
1462 }
1463 }
1464
1465 s_conflict_set_bitmap_creation_count
1466 += DRD_(bm_get_bitmap_creation_count)();
1467 s_conflict_set_bitmap2_creation_count
1468 += DRD_(bm_get_bitmap2_creation_count)();
1469
1470 if (s_trace_conflict_set_bm)
1471 {
1472 VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
1473 DRD_(bm_print)(*conflict_set);
1474 VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
1475 }
1476 }
1477
1478 /**
1479 * Update the conflict set after the vector clock of thread tid has been
1480 * updated from old_vc to its current value, either because a new segment has
1481 * been created or because of a synchronization operation.
1482 */
DRD_(thread_update_conflict_set)1483 void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
1484 const VectorClock* const old_vc)
1485 {
1486 const VectorClock* new_vc;
1487 Segment* p;
1488 unsigned j;
1489
1490 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1491 && tid != DRD_INVALID_THREADID);
1492 tl_assert(old_vc);
1493 tl_assert(tid == DRD_(g_drd_running_tid));
1494 tl_assert(DRD_(g_conflict_set));
1495
1496 if (s_trace_conflict_set)
1497 {
1498 char* str;
1499
1500 str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
1501 VG_(message)(Vg_DebugMsg,
1502 "updating conflict set for thread %d with vc %s\n",
1503 tid, str);
1504 VG_(free)(str);
1505 }
1506
1507 new_vc = &DRD_(g_threadinfo)[tid].last->vc;
1508
1509 DRD_(bm_unmark)(DRD_(g_conflict_set));
1510
1511 for (j = 0; j < DRD_N_THREADS; j++)
1512 {
1513 Segment* q;
1514
1515 if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
1516 continue;
1517
1518 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1519 {
1520 const int included_in_old_conflict_set
1521 = ! DRD_(vc_lte)(&q->vc, old_vc)
1522 && ! DRD_(vc_lte)(old_vc, &q->vc);
1523 const int included_in_new_conflict_set
1524 = ! DRD_(vc_lte)(&q->vc, new_vc)
1525 && ! DRD_(vc_lte)(new_vc, &q->vc);
1526 if (included_in_old_conflict_set != included_in_new_conflict_set)
1527 {
1528 if (s_trace_conflict_set)
1529 {
1530 char* str;
1531
1532 str = DRD_(vc_aprint)(&q->vc);
1533 VG_(message)(Vg_DebugMsg,
1534 "conflict set: [%d] merging segment %s\n", j, str);
1535 VG_(free)(str);
1536 }
1537 DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1538 }
1539 else
1540 {
1541 if (s_trace_conflict_set)
1542 {
1543 char* str;
1544
1545 str = DRD_(vc_aprint)(&q->vc);
1546 VG_(message)(Vg_DebugMsg,
1547 "conflict set: [%d] ignoring segment %s\n", j, str);
1548 VG_(free)(str);
1549 }
1550 }
1551 }
1552 }
1553
1554 DRD_(bm_clear_marked)(DRD_(g_conflict_set));
1555
1556 p = DRD_(g_threadinfo)[tid].last;
1557 {
1558 for (j = 0; j < DRD_N_THREADS; j++)
1559 {
1560 if (j != tid && DRD_(IsValidDrdThreadId)(j))
1561 {
1562 Segment* q;
1563 for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
1564 {
1565 if (! DRD_(vc_lte)(&q->vc, &p->vc)
1566 && ! DRD_(vc_lte)(&p->vc, &q->vc))
1567 {
1568 DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1569 }
1570 }
1571 }
1572 }
1573 }
1574
1575 DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
1576
1577 s_update_conflict_set_count++;
1578
1579 if (s_trace_conflict_set_bm)
1580 {
1581 VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
1582 DRD_(bm_print)(DRD_(g_conflict_set));
1583 VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
1584 }
1585
1586 tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1587 }
1588
1589 /** Report the number of context switches performed. */
DRD_(thread_get_context_switch_count)1590 ULong DRD_(thread_get_context_switch_count)(void)
1591 {
1592 return s_context_switch_count;
1593 }
1594
1595 /** Report the number of ordered segments that have been discarded. */
DRD_(thread_get_discard_ordered_segments_count)1596 ULong DRD_(thread_get_discard_ordered_segments_count)(void)
1597 {
1598 return s_discard_ordered_segments_count;
1599 }
1600
1601 /** Return how many times the conflict set has been updated entirely. */
DRD_(thread_get_compute_conflict_set_count)1602 ULong DRD_(thread_get_compute_conflict_set_count)()
1603 {
1604 return s_compute_conflict_set_count;
1605 }
1606
1607 /** Return how many times the conflict set has been updated partially. */
DRD_(thread_get_update_conflict_set_count)1608 ULong DRD_(thread_get_update_conflict_set_count)(void)
1609 {
1610 return s_update_conflict_set_count;
1611 }
1612
1613 /**
1614 * Return how many times the conflict set has been updated partially
1615 * because a new segment has been created.
1616 */
DRD_(thread_get_update_conflict_set_new_sg_count)1617 ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
1618 {
1619 return s_update_conflict_set_new_sg_count;
1620 }
1621
1622 /**
1623 * Return how many times the conflict set has been updated partially
1624 * because of combining vector clocks due to synchronization operations
1625 * other than reader/writer lock or barrier operations.
1626 */
DRD_(thread_get_update_conflict_set_sync_count)1627 ULong DRD_(thread_get_update_conflict_set_sync_count)(void)
1628 {
1629 return s_update_conflict_set_sync_count;
1630 }
1631
1632 /**
1633 * Return how many times the conflict set has been updated partially
1634 * because of thread joins.
1635 */
DRD_(thread_get_update_conflict_set_join_count)1636 ULong DRD_(thread_get_update_conflict_set_join_count)(void)
1637 {
1638 return s_update_conflict_set_join_count;
1639 }
1640
1641 /**
1642 * Return the number of first-level bitmaps that have been created during
1643 * conflict set updates.
1644 */
DRD_(thread_get_conflict_set_bitmap_creation_count)1645 ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
1646 {
1647 return s_conflict_set_bitmap_creation_count;
1648 }
1649
1650 /**
1651 * Return the number of second-level bitmaps that have been created during
1652 * conflict set updates.
1653 */
DRD_(thread_get_conflict_set_bitmap2_creation_count)1654 ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
1655 {
1656 return s_conflict_set_bitmap2_creation_count;
1657 }
1658