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