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