1 2 /*--------------------------------------------------------------------*/ 3 /*--- Helgrind: a Valgrind tool for detecting errors ---*/ 4 /*--- in threaded programs. hg_main.c ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of Helgrind, a Valgrind tool for detecting errors 9 in threaded programs. 10 11 Copyright (C) 2007-2010 OpenWorks LLP 12 info (at) open-works.co.uk 13 14 Copyright (C) 2007-2010 Apple, Inc. 15 16 This program is free software; you can redistribute it and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of the 19 License, or (at your option) any later version. 20 21 This program is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received a copy of the GNU General Public License 27 along with this program; if not, write to the Free Software 28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29 02111-1307, USA. 30 31 The GNU General Public License is contained in the file COPYING. 32 33 Neither the names of the U.S. Department of Energy nor the 34 University of California nor the names of its contributors may be 35 used to endorse or promote products derived from this software 36 without prior written permission. 37 */ 38 39 #include "pub_tool_basics.h" 40 #include "pub_tool_libcassert.h" 41 #include "pub_tool_libcbase.h" 42 #include "pub_tool_libcprint.h" 43 #include "pub_tool_threadstate.h" 44 #include "pub_tool_tooliface.h" 45 #include "pub_tool_hashtable.h" 46 #include "pub_tool_replacemalloc.h" 47 #include "pub_tool_machine.h" 48 #include "pub_tool_options.h" 49 #include "pub_tool_xarray.h" 50 #include "pub_tool_stacktrace.h" 51 #include "pub_tool_wordfm.h" 52 #include "pub_tool_debuginfo.h" // VG_(find_seginfo), VG_(seginfo_soname) 53 #include "pub_tool_redir.h" // sonames for the dynamic linkers 54 #include "pub_tool_vki.h" // VKI_PAGE_SIZE 55 #include "pub_tool_libcproc.h" // VG_(atfork) 56 #include "pub_tool_aspacemgr.h" // VG_(am_is_valid_for_client) 57 58 #include "hg_basics.h" 59 #include "hg_wordset.h" 60 #include "hg_lock_n_thread.h" 61 #include "hg_errors.h" 62 63 #include "libhb.h" 64 65 #include "helgrind.h" 66 67 68 // FIXME: new_mem_w_tid ignores the supplied tid. (wtf?!) 69 70 // FIXME: when client destroys a lock or a CV, remove these 71 // from our mappings, so that the associated SO can be freed up 72 73 /*----------------------------------------------------------------*/ 74 /*--- ---*/ 75 /*----------------------------------------------------------------*/ 76 77 /* Note this needs to be compiled with -fno-strict-aliasing, since it 78 contains a whole bunch of calls to lookupFM etc which cast between 79 Word and pointer types. gcc rightly complains this breaks ANSI C 80 strict aliasing rules, at -O2. No complaints at -O, but -O2 gives 81 worthwhile performance benefits over -O. 82 */ 83 84 // FIXME catch sync signals (SEGV, basically) and unlock BHL, 85 // if held. Otherwise a LOCK-prefixed insn which segfaults 86 // gets Helgrind into a total muddle as the BHL will not be 87 // released after the insn. 88 89 // FIXME what is supposed to happen to locks in memory which 90 // is relocated as a result of client realloc? 91 92 // FIXME put referencing ThreadId into Thread and get 93 // rid of the slow reverse mapping function. 94 95 // FIXME accesses to NoAccess areas: change state to Excl? 96 97 // FIXME report errors for accesses of NoAccess memory? 98 99 // FIXME pth_cond_wait/timedwait wrappers. Even if these fail, 100 // the thread still holds the lock. 101 102 /* ------------ Debug/trace options ------------ */ 103 104 // this is: 105 // shadow_mem_make_NoAccess: 29156 SMs, 1728 scanned 106 // happens_before_wrk: 1000 107 // ev__post_thread_join: 3360 SMs, 29 scanned, 252 re-Excls 108 #define SHOW_EXPENSIVE_STUFF 0 109 110 // 0 for silent, 1 for some stuff, 2 for lots of stuff 111 #define SHOW_EVENTS 0 112 113 114 static void all__sanity_check ( Char* who ); /* fwds */ 115 116 #define HG_CLI__MALLOC_REDZONE_SZB 16 /* let's say */ 117 118 // 0 for none, 1 for dump at end of run 119 #define SHOW_DATA_STRUCTURES 0 120 121 122 /* ------------ Misc comments ------------ */ 123 124 // FIXME: don't hardwire initial entries for root thread. 125 // Instead, let the pre_thread_ll_create handler do this. 126 127 128 /*----------------------------------------------------------------*/ 129 /*--- Primary data structures ---*/ 130 /*----------------------------------------------------------------*/ 131 132 /* Admin linked list of Threads */ 133 static Thread* admin_threads = NULL; 134 135 /* Admin linked list of Locks */ 136 static Lock* admin_locks = NULL; 137 138 /* Mapping table for core ThreadIds to Thread* */ 139 static Thread** map_threads = NULL; /* Array[VG_N_THREADS] of Thread* */ 140 141 /* Mapping table for lock guest addresses to Lock* */ 142 static WordFM* map_locks = NULL; /* WordFM LockAddr Lock* */ 143 144 /* The word-set universes for thread sets and lock sets. */ 145 static WordSetU* univ_tsets = NULL; /* sets of Thread* */ 146 static WordSetU* univ_lsets = NULL; /* sets of Lock* */ 147 static WordSetU* univ_laog = NULL; /* sets of Lock*, for LAOG */ 148 149 /* never changed; we only care about its address. Is treated as if it 150 was a standard userspace lock. Also we have a Lock* describing it 151 so it can participate in lock sets in the usual way. */ 152 static Int __bus_lock = 0; 153 static Lock* __bus_lock_Lock = NULL; 154 155 156 /*----------------------------------------------------------------*/ 157 /*--- Simple helpers for the data structures ---*/ 158 /*----------------------------------------------------------------*/ 159 160 static UWord stats__lockN_acquires = 0; 161 static UWord stats__lockN_releases = 0; 162 163 static 164 ThreadId map_threads_maybe_reverse_lookup_SLOW ( Thread* thr ); /*fwds*/ 165 166 /* --------- Constructors --------- */ 167 168 static Thread* mk_Thread ( Thr* hbthr ) { 169 static Int indx = 1; 170 Thread* thread = HG_(zalloc)( "hg.mk_Thread.1", sizeof(Thread) ); 171 thread->locksetA = HG_(emptyWS)( univ_lsets ); 172 thread->locksetW = HG_(emptyWS)( univ_lsets ); 173 thread->magic = Thread_MAGIC; 174 thread->hbthr = hbthr; 175 thread->coretid = VG_INVALID_THREADID; 176 thread->created_at = NULL; 177 thread->announced = False; 178 thread->errmsg_index = indx++; 179 thread->admin = admin_threads; 180 admin_threads = thread; 181 return thread; 182 } 183 184 // Make a new lock which is unlocked (hence ownerless) 185 static Lock* mk_LockN ( LockKind kind, Addr guestaddr ) { 186 static ULong unique = 0; 187 Lock* lock = HG_(zalloc)( "hg.mk_Lock.1", sizeof(Lock) ); 188 lock->admin = admin_locks; 189 lock->unique = unique++; 190 lock->magic = LockN_MAGIC; 191 lock->appeared_at = NULL; 192 lock->acquired_at = NULL; 193 lock->hbso = libhb_so_alloc(); 194 lock->guestaddr = guestaddr; 195 lock->kind = kind; 196 lock->heldW = False; 197 lock->heldBy = NULL; 198 tl_assert(HG_(is_sane_LockN)(lock)); 199 admin_locks = lock; 200 return lock; 201 } 202 203 /* Release storage for a Lock. Also release storage in .heldBy, if 204 any. */ 205 static void del_LockN ( Lock* lk ) 206 { 207 tl_assert(HG_(is_sane_LockN)(lk)); 208 tl_assert(lk->hbso); 209 libhb_so_dealloc(lk->hbso); 210 if (lk->heldBy) 211 VG_(deleteBag)( lk->heldBy ); 212 VG_(memset)(lk, 0xAA, sizeof(*lk)); 213 HG_(free)(lk); 214 } 215 216 /* Update 'lk' to reflect that 'thr' now has a write-acquisition of 217 it. This is done strictly: only combinations resulting from 218 correct program and libpthread behaviour are allowed. */ 219 static void lockN_acquire_writer ( Lock* lk, Thread* thr ) 220 { 221 tl_assert(HG_(is_sane_LockN)(lk)); 222 tl_assert(HG_(is_sane_Thread)(thr)); 223 224 stats__lockN_acquires++; 225 226 /* EXPOSITION only */ 227 /* We need to keep recording snapshots of where the lock was 228 acquired, so as to produce better lock-order error messages. */ 229 if (lk->acquired_at == NULL) { 230 ThreadId tid; 231 tl_assert(lk->heldBy == NULL); 232 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 233 lk->acquired_at 234 = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 235 } else { 236 tl_assert(lk->heldBy != NULL); 237 } 238 /* end EXPOSITION only */ 239 240 switch (lk->kind) { 241 case LK_nonRec: 242 case_LK_nonRec: 243 tl_assert(lk->heldBy == NULL); /* can't w-lock recursively */ 244 tl_assert(!lk->heldW); 245 lk->heldW = True; 246 lk->heldBy = VG_(newBag)( HG_(zalloc), "hg.lNaw.1", HG_(free) ); 247 VG_(addToBag)( lk->heldBy, (Word)thr ); 248 break; 249 case LK_mbRec: 250 if (lk->heldBy == NULL) 251 goto case_LK_nonRec; 252 /* 2nd and subsequent locking of a lock by its owner */ 253 tl_assert(lk->heldW); 254 /* assert: lk is only held by one thread .. */ 255 tl_assert(VG_(sizeUniqueBag(lk->heldBy)) == 1); 256 /* assert: .. and that thread is 'thr'. */ 257 tl_assert(VG_(elemBag)(lk->heldBy, (Word)thr) 258 == VG_(sizeTotalBag)(lk->heldBy)); 259 VG_(addToBag)(lk->heldBy, (Word)thr); 260 break; 261 case LK_rdwr: 262 tl_assert(lk->heldBy == NULL && !lk->heldW); /* must be unheld */ 263 goto case_LK_nonRec; 264 default: 265 tl_assert(0); 266 } 267 tl_assert(HG_(is_sane_LockN)(lk)); 268 } 269 270 static void lockN_acquire_reader ( Lock* lk, Thread* thr ) 271 { 272 tl_assert(HG_(is_sane_LockN)(lk)); 273 tl_assert(HG_(is_sane_Thread)(thr)); 274 /* can only add reader to a reader-writer lock. */ 275 tl_assert(lk->kind == LK_rdwr); 276 /* lk must be free or already r-held. */ 277 tl_assert(lk->heldBy == NULL 278 || (lk->heldBy != NULL && !lk->heldW)); 279 280 stats__lockN_acquires++; 281 282 /* EXPOSITION only */ 283 /* We need to keep recording snapshots of where the lock was 284 acquired, so as to produce better lock-order error messages. */ 285 if (lk->acquired_at == NULL) { 286 ThreadId tid; 287 tl_assert(lk->heldBy == NULL); 288 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 289 lk->acquired_at 290 = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 291 } else { 292 tl_assert(lk->heldBy != NULL); 293 } 294 /* end EXPOSITION only */ 295 296 if (lk->heldBy) { 297 VG_(addToBag)(lk->heldBy, (Word)thr); 298 } else { 299 lk->heldW = False; 300 lk->heldBy = VG_(newBag)( HG_(zalloc), "hg.lNar.1", HG_(free) ); 301 VG_(addToBag)( lk->heldBy, (Word)thr ); 302 } 303 tl_assert(!lk->heldW); 304 tl_assert(HG_(is_sane_LockN)(lk)); 305 } 306 307 /* Update 'lk' to reflect a release of it by 'thr'. This is done 308 strictly: only combinations resulting from correct program and 309 libpthread behaviour are allowed. */ 310 311 static void lockN_release ( Lock* lk, Thread* thr ) 312 { 313 Bool b; 314 tl_assert(HG_(is_sane_LockN)(lk)); 315 tl_assert(HG_(is_sane_Thread)(thr)); 316 /* lock must be held by someone */ 317 tl_assert(lk->heldBy); 318 stats__lockN_releases++; 319 /* Remove it from the holder set */ 320 b = VG_(delFromBag)(lk->heldBy, (Word)thr); 321 /* thr must actually have been a holder of lk */ 322 tl_assert(b); 323 /* normalise */ 324 tl_assert(lk->acquired_at); 325 if (VG_(isEmptyBag)(lk->heldBy)) { 326 VG_(deleteBag)(lk->heldBy); 327 lk->heldBy = NULL; 328 lk->heldW = False; 329 lk->acquired_at = NULL; 330 } 331 tl_assert(HG_(is_sane_LockN)(lk)); 332 } 333 334 static void remove_Lock_from_locksets_of_all_owning_Threads( Lock* lk ) 335 { 336 Thread* thr; 337 if (!lk->heldBy) { 338 tl_assert(!lk->heldW); 339 return; 340 } 341 /* for each thread that holds this lock do ... */ 342 VG_(initIterBag)( lk->heldBy ); 343 while (VG_(nextIterBag)( lk->heldBy, (Word*)&thr, NULL )) { 344 tl_assert(HG_(is_sane_Thread)(thr)); 345 tl_assert(HG_(elemWS)( univ_lsets, 346 thr->locksetA, (Word)lk )); 347 thr->locksetA 348 = HG_(delFromWS)( univ_lsets, thr->locksetA, (Word)lk ); 349 350 if (lk->heldW) { 351 tl_assert(HG_(elemWS)( univ_lsets, 352 thr->locksetW, (Word)lk )); 353 thr->locksetW 354 = HG_(delFromWS)( univ_lsets, thr->locksetW, (Word)lk ); 355 } 356 } 357 VG_(doneIterBag)( lk->heldBy ); 358 } 359 360 361 /*----------------------------------------------------------------*/ 362 /*--- Print out the primary data structures ---*/ 363 /*----------------------------------------------------------------*/ 364 365 //static WordSetID del_BHL ( WordSetID lockset ); /* fwds */ 366 367 #define PP_THREADS (1<<1) 368 #define PP_LOCKS (1<<2) 369 #define PP_ALL (PP_THREADS | PP_LOCKS) 370 371 372 static const Int sHOW_ADMIN = 0; 373 374 static void space ( Int n ) 375 { 376 Int i; 377 Char spaces[128+1]; 378 tl_assert(n >= 0 && n < 128); 379 if (n == 0) 380 return; 381 for (i = 0; i < n; i++) 382 spaces[i] = ' '; 383 spaces[i] = 0; 384 tl_assert(i < 128+1); 385 VG_(printf)("%s", spaces); 386 } 387 388 static void pp_Thread ( Int d, Thread* t ) 389 { 390 space(d+0); VG_(printf)("Thread %p {\n", t); 391 if (sHOW_ADMIN) { 392 space(d+3); VG_(printf)("admin %p\n", t->admin); 393 space(d+3); VG_(printf)("magic 0x%x\n", (UInt)t->magic); 394 } 395 space(d+3); VG_(printf)("locksetA %d\n", (Int)t->locksetA); 396 space(d+3); VG_(printf)("locksetW %d\n", (Int)t->locksetW); 397 space(d+0); VG_(printf)("}\n"); 398 } 399 400 static void pp_admin_threads ( Int d ) 401 { 402 Int i, n; 403 Thread* t; 404 for (n = 0, t = admin_threads; t; n++, t = t->admin) { 405 /* nothing */ 406 } 407 space(d); VG_(printf)("admin_threads (%d records) {\n", n); 408 for (i = 0, t = admin_threads; t; i++, t = t->admin) { 409 if (0) { 410 space(n); 411 VG_(printf)("admin_threads record %d of %d:\n", i, n); 412 } 413 pp_Thread(d+3, t); 414 } 415 space(d); VG_(printf)("}\n"); 416 } 417 418 static void pp_map_threads ( Int d ) 419 { 420 Int i, n = 0; 421 space(d); VG_(printf)("map_threads "); 422 for (i = 0; i < VG_N_THREADS; i++) { 423 if (map_threads[i] != NULL) 424 n++; 425 } 426 VG_(printf)("(%d entries) {\n", n); 427 for (i = 0; i < VG_N_THREADS; i++) { 428 if (map_threads[i] == NULL) 429 continue; 430 space(d+3); 431 VG_(printf)("coretid %d -> Thread %p\n", i, map_threads[i]); 432 } 433 space(d); VG_(printf)("}\n"); 434 } 435 436 static const HChar* show_LockKind ( LockKind lkk ) { 437 switch (lkk) { 438 case LK_mbRec: return "mbRec"; 439 case LK_nonRec: return "nonRec"; 440 case LK_rdwr: return "rdwr"; 441 default: tl_assert(0); 442 } 443 } 444 445 static void pp_Lock ( Int d, Lock* lk ) 446 { 447 space(d+0); VG_(printf)("Lock %p (ga %#lx) {\n", lk, lk->guestaddr); 448 if (sHOW_ADMIN) { 449 space(d+3); VG_(printf)("admin %p\n", lk->admin); 450 space(d+3); VG_(printf)("magic 0x%x\n", (UInt)lk->magic); 451 } 452 space(d+3); VG_(printf)("unique %llu\n", lk->unique); 453 space(d+3); VG_(printf)("kind %s\n", show_LockKind(lk->kind)); 454 space(d+3); VG_(printf)("heldW %s\n", lk->heldW ? "yes" : "no"); 455 space(d+3); VG_(printf)("heldBy %p", lk->heldBy); 456 if (lk->heldBy) { 457 Thread* thr; 458 Word count; 459 VG_(printf)(" { "); 460 VG_(initIterBag)( lk->heldBy ); 461 while (VG_(nextIterBag)( lk->heldBy, (Word*)&thr, &count )) 462 VG_(printf)("%lu:%p ", count, thr); 463 VG_(doneIterBag)( lk->heldBy ); 464 VG_(printf)("}"); 465 } 466 VG_(printf)("\n"); 467 space(d+0); VG_(printf)("}\n"); 468 } 469 470 static void pp_admin_locks ( Int d ) 471 { 472 Int i, n; 473 Lock* lk; 474 for (n = 0, lk = admin_locks; lk; n++, lk = lk->admin) { 475 /* nothing */ 476 } 477 space(d); VG_(printf)("admin_locks (%d records) {\n", n); 478 for (i = 0, lk = admin_locks; lk; i++, lk = lk->admin) { 479 if (0) { 480 space(n); 481 VG_(printf)("admin_locks record %d of %d:\n", i, n); 482 } 483 pp_Lock(d+3, lk); 484 } 485 space(d); VG_(printf)("}\n"); 486 } 487 488 static void pp_map_locks ( Int d ) 489 { 490 void* gla; 491 Lock* lk; 492 space(d); VG_(printf)("map_locks (%d entries) {\n", 493 (Int)VG_(sizeFM)( map_locks )); 494 VG_(initIterFM)( map_locks ); 495 while (VG_(nextIterFM)( map_locks, (Word*)&gla, 496 (Word*)&lk )) { 497 space(d+3); 498 VG_(printf)("guest %p -> Lock %p\n", gla, lk); 499 } 500 VG_(doneIterFM)( map_locks ); 501 space(d); VG_(printf)("}\n"); 502 } 503 504 static void pp_everything ( Int flags, Char* caller ) 505 { 506 Int d = 0; 507 VG_(printf)("\n"); 508 VG_(printf)("All_Data_Structures (caller = \"%s\") {\n", caller); 509 if (flags & PP_THREADS) { 510 VG_(printf)("\n"); 511 pp_admin_threads(d+3); 512 VG_(printf)("\n"); 513 pp_map_threads(d+3); 514 } 515 if (flags & PP_LOCKS) { 516 VG_(printf)("\n"); 517 pp_admin_locks(d+3); 518 VG_(printf)("\n"); 519 pp_map_locks(d+3); 520 } 521 522 VG_(printf)("\n"); 523 VG_(printf)("}\n"); 524 VG_(printf)("\n"); 525 } 526 527 #undef SHOW_ADMIN 528 529 530 /*----------------------------------------------------------------*/ 531 /*--- Initialise the primary data structures ---*/ 532 /*----------------------------------------------------------------*/ 533 534 static void initialise_data_structures ( Thr* hbthr_root ) 535 { 536 Thread* thr; 537 538 /* Get everything initialised and zeroed. */ 539 tl_assert(admin_threads == NULL); 540 tl_assert(admin_locks == NULL); 541 542 tl_assert(sizeof(Addr) == sizeof(Word)); 543 544 tl_assert(map_threads == NULL); 545 map_threads = HG_(zalloc)( "hg.ids.1", VG_N_THREADS * sizeof(Thread*) ); 546 tl_assert(map_threads != NULL); 547 548 tl_assert(sizeof(Addr) == sizeof(Word)); 549 tl_assert(map_locks == NULL); 550 map_locks = VG_(newFM)( HG_(zalloc), "hg.ids.2", HG_(free), 551 NULL/*unboxed Word cmp*/); 552 tl_assert(map_locks != NULL); 553 554 __bus_lock_Lock = mk_LockN( LK_nonRec, (Addr)&__bus_lock ); 555 tl_assert(HG_(is_sane_LockN)(__bus_lock_Lock)); 556 VG_(addToFM)( map_locks, (Word)&__bus_lock, (Word)__bus_lock_Lock ); 557 558 tl_assert(univ_tsets == NULL); 559 univ_tsets = HG_(newWordSetU)( HG_(zalloc), "hg.ids.3", HG_(free), 560 8/*cacheSize*/ ); 561 tl_assert(univ_tsets != NULL); 562 563 tl_assert(univ_lsets == NULL); 564 univ_lsets = HG_(newWordSetU)( HG_(zalloc), "hg.ids.4", HG_(free), 565 8/*cacheSize*/ ); 566 tl_assert(univ_lsets != NULL); 567 568 tl_assert(univ_laog == NULL); 569 univ_laog = HG_(newWordSetU)( HG_(zalloc), "hg.ids.5 (univ_laog)", 570 HG_(free), 24/*cacheSize*/ ); 571 tl_assert(univ_laog != NULL); 572 573 /* Set up entries for the root thread */ 574 // FIXME: this assumes that the first real ThreadId is 1 575 576 /* a Thread for the new thread ... */ 577 thr = mk_Thread(hbthr_root); 578 thr->coretid = 1; /* FIXME: hardwires an assumption about the 579 identity of the root thread. */ 580 tl_assert( libhb_get_Thr_opaque(hbthr_root) == NULL ); 581 libhb_set_Thr_opaque(hbthr_root, thr); 582 583 /* and bind it in the thread-map table. */ 584 tl_assert(HG_(is_sane_ThreadId)(thr->coretid)); 585 tl_assert(thr->coretid != VG_INVALID_THREADID); 586 587 map_threads[thr->coretid] = thr; 588 589 tl_assert(VG_INVALID_THREADID == 0); 590 591 /* Mark the new bus lock correctly (to stop the sanity checks 592 complaining) */ 593 tl_assert( sizeof(__bus_lock) == 4 ); 594 595 all__sanity_check("initialise_data_structures"); 596 } 597 598 599 /*----------------------------------------------------------------*/ 600 /*--- map_threads :: array[core-ThreadId] of Thread* ---*/ 601 /*----------------------------------------------------------------*/ 602 603 /* Doesn't assert if the relevant map_threads entry is NULL. */ 604 static Thread* map_threads_maybe_lookup ( ThreadId coretid ) 605 { 606 Thread* thr; 607 tl_assert( HG_(is_sane_ThreadId)(coretid) ); 608 thr = map_threads[coretid]; 609 return thr; 610 } 611 612 /* Asserts if the relevant map_threads entry is NULL. */ 613 static inline Thread* map_threads_lookup ( ThreadId coretid ) 614 { 615 Thread* thr; 616 tl_assert( HG_(is_sane_ThreadId)(coretid) ); 617 thr = map_threads[coretid]; 618 tl_assert(thr); 619 return thr; 620 } 621 622 /* Do a reverse lookup. Does not assert if 'thr' is not found in 623 map_threads. */ 624 static ThreadId map_threads_maybe_reverse_lookup_SLOW ( Thread* thr ) 625 { 626 ThreadId tid; 627 tl_assert(HG_(is_sane_Thread)(thr)); 628 /* Check nobody used the invalid-threadid slot */ 629 tl_assert(VG_INVALID_THREADID >= 0 && VG_INVALID_THREADID < VG_N_THREADS); 630 tl_assert(map_threads[VG_INVALID_THREADID] == NULL); 631 tid = thr->coretid; 632 tl_assert(HG_(is_sane_ThreadId)(tid)); 633 return tid; 634 } 635 636 /* Do a reverse lookup. Warning: POTENTIALLY SLOW. Asserts if 'thr' 637 is not found in map_threads. */ 638 static ThreadId map_threads_reverse_lookup_SLOW ( Thread* thr ) 639 { 640 ThreadId tid = map_threads_maybe_reverse_lookup_SLOW( thr ); 641 tl_assert(tid != VG_INVALID_THREADID); 642 tl_assert(map_threads[tid]); 643 tl_assert(map_threads[tid]->coretid == tid); 644 return tid; 645 } 646 647 static void map_threads_delete ( ThreadId coretid ) 648 { 649 Thread* thr; 650 tl_assert(coretid != 0); 651 tl_assert( HG_(is_sane_ThreadId)(coretid) ); 652 thr = map_threads[coretid]; 653 tl_assert(thr); 654 map_threads[coretid] = NULL; 655 } 656 657 658 /*----------------------------------------------------------------*/ 659 /*--- map_locks :: WordFM guest-Addr-of-lock Lock* ---*/ 660 /*----------------------------------------------------------------*/ 661 662 /* Make sure there is a lock table entry for the given (lock) guest 663 address. If not, create one of the stated 'kind' in unheld state. 664 In any case, return the address of the existing or new Lock. */ 665 static 666 Lock* map_locks_lookup_or_create ( LockKind lkk, Addr ga, ThreadId tid ) 667 { 668 Bool found; 669 Lock* oldlock = NULL; 670 tl_assert(HG_(is_sane_ThreadId)(tid)); 671 found = VG_(lookupFM)( map_locks, 672 NULL, (Word*)&oldlock, (Word)ga ); 673 if (!found) { 674 Lock* lock = mk_LockN(lkk, ga); 675 lock->appeared_at = VG_(record_ExeContext)( tid, 0 ); 676 tl_assert(HG_(is_sane_LockN)(lock)); 677 VG_(addToFM)( map_locks, (Word)ga, (Word)lock ); 678 tl_assert(oldlock == NULL); 679 return lock; 680 } else { 681 tl_assert(oldlock != NULL); 682 tl_assert(HG_(is_sane_LockN)(oldlock)); 683 tl_assert(oldlock->guestaddr == ga); 684 return oldlock; 685 } 686 } 687 688 static Lock* map_locks_maybe_lookup ( Addr ga ) 689 { 690 Bool found; 691 Lock* lk = NULL; 692 found = VG_(lookupFM)( map_locks, NULL, (Word*)&lk, (Word)ga ); 693 tl_assert(found ? lk != NULL : lk == NULL); 694 return lk; 695 } 696 697 static void map_locks_delete ( Addr ga ) 698 { 699 Addr ga2 = 0; 700 Lock* lk = NULL; 701 VG_(delFromFM)( map_locks, 702 (Word*)&ga2, (Word*)&lk, (Word)ga ); 703 /* delFromFM produces the val which is being deleted, if it is 704 found. So assert it is non-null; that in effect asserts that we 705 are deleting a (ga, Lock) pair which actually exists. */ 706 tl_assert(lk != NULL); 707 tl_assert(ga2 == ga); 708 } 709 710 711 712 /*----------------------------------------------------------------*/ 713 /*--- Sanity checking the data structures ---*/ 714 /*----------------------------------------------------------------*/ 715 716 static UWord stats__sanity_checks = 0; 717 718 static void laog__sanity_check ( Char* who ); /* fwds */ 719 720 /* REQUIRED INVARIANTS: 721 722 Thread vs Segment/Lock/SecMaps 723 724 for each t in Threads { 725 726 // Thread.lockset: each element is really a valid Lock 727 728 // Thread.lockset: each Lock in set is actually held by that thread 729 for lk in Thread.lockset 730 lk == LockedBy(t) 731 732 // Thread.csegid is a valid SegmentID 733 // and the associated Segment has .thr == t 734 735 } 736 737 all thread Locksets are pairwise empty under intersection 738 (that is, no lock is claimed to be held by more than one thread) 739 -- this is guaranteed if all locks in locksets point back to their 740 owner threads 741 742 Lock vs Thread/Segment/SecMaps 743 744 for each entry (gla, la) in map_locks 745 gla == la->guest_addr 746 747 for each lk in Locks { 748 749 lk->tag is valid 750 lk->guest_addr does not have shadow state NoAccess 751 if lk == LockedBy(t), then t->lockset contains lk 752 if lk == UnlockedBy(segid) then segid is valid SegmentID 753 and can be mapped to a valid Segment(seg) 754 and seg->thr->lockset does not contain lk 755 if lk == UnlockedNew then (no lockset contains lk) 756 757 secmaps for lk has .mbHasLocks == True 758 759 } 760 761 Segment vs Thread/Lock/SecMaps 762 763 the Segment graph is a dag (no cycles) 764 all of the Segment graph must be reachable from the segids 765 mentioned in the Threads 766 767 for seg in Segments { 768 769 seg->thr is a sane Thread 770 771 } 772 773 SecMaps vs Segment/Thread/Lock 774 775 for sm in SecMaps { 776 777 sm properly aligned 778 if any shadow word is ShR or ShM then .mbHasShared == True 779 780 for each Excl(segid) state 781 map_segments_lookup maps to a sane Segment(seg) 782 for each ShM/ShR(tsetid,lsetid) state 783 each lk in lset is a valid Lock 784 each thr in tset is a valid thread, which is non-dead 785 786 } 787 */ 788 789 790 /* Return True iff 'thr' holds 'lk' in some mode. */ 791 static Bool thread_is_a_holder_of_Lock ( Thread* thr, Lock* lk ) 792 { 793 if (lk->heldBy) 794 return VG_(elemBag)( lk->heldBy, (Word)thr ) > 0; 795 else 796 return False; 797 } 798 799 /* Sanity check Threads, as far as possible */ 800 __attribute__((noinline)) 801 static void threads__sanity_check ( Char* who ) 802 { 803 #define BAD(_str) do { how = (_str); goto bad; } while (0) 804 Char* how = "no error"; 805 Thread* thr; 806 WordSetID wsA, wsW; 807 UWord* ls_words; 808 Word ls_size, i; 809 Lock* lk; 810 for (thr = admin_threads; thr; thr = thr->admin) { 811 if (!HG_(is_sane_Thread)(thr)) BAD("1"); 812 wsA = thr->locksetA; 813 wsW = thr->locksetW; 814 // locks held in W mode are a subset of all locks held 815 if (!HG_(isSubsetOf)( univ_lsets, wsW, wsA )) BAD("7"); 816 HG_(getPayloadWS)( &ls_words, &ls_size, univ_lsets, wsA ); 817 for (i = 0; i < ls_size; i++) { 818 lk = (Lock*)ls_words[i]; 819 // Thread.lockset: each element is really a valid Lock 820 if (!HG_(is_sane_LockN)(lk)) BAD("2"); 821 // Thread.lockset: each Lock in set is actually held by that 822 // thread 823 if (!thread_is_a_holder_of_Lock(thr,lk)) BAD("3"); 824 } 825 } 826 return; 827 bad: 828 VG_(printf)("threads__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how); 829 tl_assert(0); 830 #undef BAD 831 } 832 833 834 /* Sanity check Locks, as far as possible */ 835 __attribute__((noinline)) 836 static void locks__sanity_check ( Char* who ) 837 { 838 #define BAD(_str) do { how = (_str); goto bad; } while (0) 839 Char* how = "no error"; 840 Addr gla; 841 Lock* lk; 842 Int i; 843 // # entries in admin_locks == # entries in map_locks 844 for (i = 0, lk = admin_locks; lk; i++, lk = lk->admin) 845 ; 846 if (i != VG_(sizeFM)(map_locks)) BAD("1"); 847 // for each entry (gla, lk) in map_locks 848 // gla == lk->guest_addr 849 VG_(initIterFM)( map_locks ); 850 while (VG_(nextIterFM)( map_locks, 851 (Word*)&gla, (Word*)&lk )) { 852 if (lk->guestaddr != gla) BAD("2"); 853 } 854 VG_(doneIterFM)( map_locks ); 855 // scan through admin_locks ... 856 for (lk = admin_locks; lk; lk = lk->admin) { 857 // lock is sane. Quite comprehensive, also checks that 858 // referenced (holder) threads are sane. 859 if (!HG_(is_sane_LockN)(lk)) BAD("3"); 860 // map_locks binds guest address back to this lock 861 if (lk != map_locks_maybe_lookup(lk->guestaddr)) BAD("4"); 862 // look at all threads mentioned as holders of this lock. Ensure 863 // this lock is mentioned in their locksets. 864 if (lk->heldBy) { 865 Thread* thr; 866 Word count; 867 VG_(initIterBag)( lk->heldBy ); 868 while (VG_(nextIterBag)( lk->heldBy, 869 (Word*)&thr, &count )) { 870 // HG_(is_sane_LockN) above ensures these 871 tl_assert(count >= 1); 872 tl_assert(HG_(is_sane_Thread)(thr)); 873 if (!HG_(elemWS)(univ_lsets, thr->locksetA, (Word)lk)) 874 BAD("6"); 875 // also check the w-only lockset 876 if (lk->heldW 877 && !HG_(elemWS)(univ_lsets, thr->locksetW, (Word)lk)) 878 BAD("7"); 879 if ((!lk->heldW) 880 && HG_(elemWS)(univ_lsets, thr->locksetW, (Word)lk)) 881 BAD("8"); 882 } 883 VG_(doneIterBag)( lk->heldBy ); 884 } else { 885 /* lock not held by anybody */ 886 if (lk->heldW) BAD("9"); /* should be False if !heldBy */ 887 // since lk is unheld, then (no lockset contains lk) 888 // hmm, this is really too expensive to check. Hmm. 889 } 890 } 891 892 return; 893 bad: 894 VG_(printf)("locks__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how); 895 tl_assert(0); 896 #undef BAD 897 } 898 899 900 static void all_except_Locks__sanity_check ( Char* who ) { 901 stats__sanity_checks++; 902 if (0) VG_(printf)("all_except_Locks__sanity_check(%s)\n", who); 903 threads__sanity_check(who); 904 laog__sanity_check(who); 905 } 906 static void all__sanity_check ( Char* who ) { 907 all_except_Locks__sanity_check(who); 908 locks__sanity_check(who); 909 } 910 911 912 /*----------------------------------------------------------------*/ 913 /*--- the core memory state machine (msm__* functions) ---*/ 914 /*----------------------------------------------------------------*/ 915 916 //static WordSetID add_BHL ( WordSetID lockset ) { 917 // return HG_(addToWS)( univ_lsets, lockset, (Word)__bus_lock_Lock ); 918 //} 919 //static WordSetID del_BHL ( WordSetID lockset ) { 920 // return HG_(delFromWS)( univ_lsets, lockset, (Word)__bus_lock_Lock ); 921 //} 922 923 924 ///* Last-lock-lossage records. This mechanism exists to help explain 925 // to programmers why we are complaining about a race. The idea is to 926 // monitor all lockset transitions. When a previously nonempty 927 // lockset becomes empty, the lock(s) that just disappeared (the 928 // "lossage") are the locks that have consistently protected the 929 // location (ga_of_access) in question for the longest time. Most of 930 // the time the lossage-set is a single lock. Because the 931 // lossage-lock is the one that has survived longest, there is there 932 // is a good chance that it is indeed the lock that the programmer 933 // intended to use to protect the location. 934 // 935 // Note that we cannot in general just look at the lossage set when we 936 // see a transition to ShM(...,empty-set), because a transition to an 937 // empty lockset can happen arbitrarily far before the point where we 938 // want to report an error. This is in the case where there are many 939 // transitions ShR -> ShR, all with an empty lockset, and only later 940 // is there a transition to ShM. So what we want to do is note the 941 // lossage lock at the point where a ShR -> ShR transition empties out 942 // the lockset, so we can present it later if there should be a 943 // transition to ShM. 944 // 945 // So this function finds such transitions. For each, it associates 946 // in ga_to_lastlock, the guest address and the lossage lock. In fact 947 // we do not record the Lock* directly as that may disappear later, 948 // but instead the ExeContext inside the Lock which says where it was 949 // initialised or first locked. ExeContexts are permanent so keeping 950 // them indefinitely is safe. 951 // 952 // A boring detail: the hardware bus lock is not interesting in this 953 // respect, so we first remove that from the pre/post locksets. 954 //*/ 955 // 956 //static UWord stats__ga_LL_adds = 0; 957 // 958 //static WordFM* ga_to_lastlock = NULL; /* GuestAddr -> ExeContext* */ 959 // 960 //static 961 //void record_last_lock_lossage ( Addr ga_of_access, 962 // WordSetID lset_old, WordSetID lset_new ) 963 //{ 964 // Lock* lk; 965 // Int card_old, card_new; 966 // 967 // tl_assert(lset_old != lset_new); 968 // 969 // if (0) VG_(printf)("XX1: %d (card %ld) -> %d (card %ld) %#lx\n", 970 // (Int)lset_old, 971 // HG_(cardinalityWS)(univ_lsets,lset_old), 972 // (Int)lset_new, 973 // HG_(cardinalityWS)(univ_lsets,lset_new), 974 // ga_of_access ); 975 // 976 // /* This is slow, but at least it's simple. The bus hardware lock 977 // just confuses the logic, so remove it from the locksets we're 978 // considering before doing anything else. */ 979 // lset_new = del_BHL( lset_new ); 980 // 981 // if (!HG_(isEmptyWS)( univ_lsets, lset_new )) { 982 // /* The post-transition lock set is not empty. So we are not 983 // interested. We're only interested in spotting transitions 984 // that make locksets become empty. */ 985 // return; 986 // } 987 // 988 // /* lset_new is now empty */ 989 // card_new = HG_(cardinalityWS)( univ_lsets, lset_new ); 990 // tl_assert(card_new == 0); 991 // 992 // lset_old = del_BHL( lset_old ); 993 // card_old = HG_(cardinalityWS)( univ_lsets, lset_old ); 994 // 995 // if (0) VG_(printf)(" X2: %d (card %d) -> %d (card %d)\n", 996 // (Int)lset_old, card_old, (Int)lset_new, card_new ); 997 // 998 // if (card_old == 0) { 999 // /* The old lockset was also empty. Not interesting. */ 1000 // return; 1001 // } 1002 // 1003 // tl_assert(card_old > 0); 1004 // tl_assert(!HG_(isEmptyWS)( univ_lsets, lset_old )); 1005 // 1006 // /* Now we know we've got a transition from a nonempty lockset to an 1007 // empty one. So lset_old must be the set of locks lost. Record 1008 // some details. If there is more than one element in the lossage 1009 // set, just choose one arbitrarily -- not the best, but at least 1010 // it's simple. */ 1011 // 1012 // lk = (Lock*)HG_(anyElementOfWS)( univ_lsets, lset_old ); 1013 // if (0) VG_(printf)("lossage %ld %p\n", 1014 // HG_(cardinalityWS)( univ_lsets, lset_old), lk ); 1015 // if (lk->appeared_at) { 1016 // if (ga_to_lastlock == NULL) 1017 // ga_to_lastlock = VG_(newFM)( HG_(zalloc), "hg.rlll.1", HG_(free), NULL ); 1018 // VG_(addToFM)( ga_to_lastlock, ga_of_access, (Word)lk->appeared_at ); 1019 // stats__ga_LL_adds++; 1020 // } 1021 //} 1022 // 1023 ///* This queries the table (ga_to_lastlock) made by 1024 // record_last_lock_lossage, when constructing error messages. It 1025 // attempts to find the ExeContext of the allocation or initialisation 1026 // point for the lossage lock associated with 'ga'. */ 1027 // 1028 //static ExeContext* maybe_get_lastlock_initpoint ( Addr ga ) 1029 //{ 1030 // ExeContext* ec_hint = NULL; 1031 // if (ga_to_lastlock != NULL 1032 // && VG_(lookupFM)(ga_to_lastlock, 1033 // NULL, (Word*)&ec_hint, ga)) { 1034 // tl_assert(ec_hint != NULL); 1035 // return ec_hint; 1036 // } else { 1037 // return NULL; 1038 // } 1039 //} 1040 1041 1042 /*----------------------------------------------------------------*/ 1043 /*--- Shadow value and address range handlers ---*/ 1044 /*----------------------------------------------------------------*/ 1045 1046 static void laog__pre_thread_acquires_lock ( Thread*, Lock* ); /* fwds */ 1047 //static void laog__handle_lock_deletions ( WordSetID ); /* fwds */ 1048 static inline Thread* get_current_Thread ( void ); /* fwds */ 1049 __attribute__((noinline)) 1050 static void laog__handle_one_lock_deletion ( Lock* lk ); /* fwds */ 1051 1052 1053 /* Block-copy states (needed for implementing realloc()). */ 1054 /* FIXME this copies shadow memory; it doesn't apply the MSM to it. 1055 Is that a problem? (hence 'scopy' rather than 'ccopy') */ 1056 static void shadow_mem_scopy_range ( Thread* thr, 1057 Addr src, Addr dst, SizeT len ) 1058 { 1059 Thr* hbthr = thr->hbthr; 1060 tl_assert(hbthr); 1061 libhb_copy_shadow_state( hbthr, src, dst, len ); 1062 } 1063 1064 static void shadow_mem_cread_range ( Thread* thr, Addr a, SizeT len ) 1065 { 1066 Thr* hbthr = thr->hbthr; 1067 tl_assert(hbthr); 1068 LIBHB_CREAD_N(hbthr, a, len); 1069 } 1070 1071 static void shadow_mem_cwrite_range ( Thread* thr, Addr a, SizeT len ) { 1072 Thr* hbthr = thr->hbthr; 1073 tl_assert(hbthr); 1074 LIBHB_CWRITE_N(hbthr, a, len); 1075 } 1076 1077 static void shadow_mem_make_New ( Thread* thr, Addr a, SizeT len ) 1078 { 1079 libhb_srange_new( thr->hbthr, a, len ); 1080 } 1081 1082 static void shadow_mem_make_NoAccess ( Thread* thr, Addr aIN, SizeT len ) 1083 { 1084 if (0 && len > 500) 1085 VG_(printf)("make NoAccess ( %#lx, %ld )\n", aIN, len ); 1086 libhb_srange_noaccess( thr->hbthr, aIN, len ); 1087 } 1088 1089 static void shadow_mem_make_Untracked ( Thread* thr, Addr aIN, SizeT len ) 1090 { 1091 if (0 && len > 500) 1092 VG_(printf)("make Untracked ( %#lx, %ld )\n", aIN, len ); 1093 libhb_srange_untrack( thr->hbthr, aIN, len ); 1094 } 1095 1096 1097 /*----------------------------------------------------------------*/ 1098 /*--- Event handlers (evh__* functions) ---*/ 1099 /*--- plus helpers (evhH__* functions) ---*/ 1100 /*----------------------------------------------------------------*/ 1101 1102 /*--------- Event handler helpers (evhH__* functions) ---------*/ 1103 1104 /* Create a new segment for 'thr', making it depend (.prev) on its 1105 existing segment, bind together the SegmentID and Segment, and 1106 return both of them. Also update 'thr' so it references the new 1107 Segment. */ 1108 //zz static 1109 //zz void evhH__start_new_segment_for_thread ( /*OUT*/SegmentID* new_segidP, 1110 //zz /*OUT*/Segment** new_segP, 1111 //zz Thread* thr ) 1112 //zz { 1113 //zz Segment* cur_seg; 1114 //zz tl_assert(new_segP); 1115 //zz tl_assert(new_segidP); 1116 //zz tl_assert(HG_(is_sane_Thread)(thr)); 1117 //zz cur_seg = map_segments_lookup( thr->csegid ); 1118 //zz tl_assert(cur_seg); 1119 //zz tl_assert(cur_seg->thr == thr); /* all sane segs should point back 1120 //zz at their owner thread. */ 1121 //zz *new_segP = mk_Segment( thr, cur_seg, NULL/*other*/ ); 1122 //zz *new_segidP = alloc_SegmentID(); 1123 //zz map_segments_add( *new_segidP, *new_segP ); 1124 //zz thr->csegid = *new_segidP; 1125 //zz } 1126 1127 1128 /* The lock at 'lock_ga' has acquired a writer. Make all necessary 1129 updates, and also do all possible error checks. */ 1130 static 1131 void evhH__post_thread_w_acquires_lock ( Thread* thr, 1132 LockKind lkk, Addr lock_ga ) 1133 { 1134 Lock* lk; 1135 1136 /* Basically what we need to do is call lockN_acquire_writer. 1137 However, that will barf if any 'invalid' lock states would 1138 result. Therefore check before calling. Side effect is that 1139 'HG_(is_sane_LockN)(lk)' is both a pre- and post-condition of this 1140 routine. 1141 1142 Because this routine is only called after successful lock 1143 acquisition, we should not be asked to move the lock into any 1144 invalid states. Requests to do so are bugs in libpthread, since 1145 that should have rejected any such requests. */ 1146 1147 tl_assert(HG_(is_sane_Thread)(thr)); 1148 /* Try to find the lock. If we can't, then create a new one with 1149 kind 'lkk'. */ 1150 lk = map_locks_lookup_or_create( 1151 lkk, lock_ga, map_threads_reverse_lookup_SLOW(thr) ); 1152 tl_assert( HG_(is_sane_LockN)(lk) ); 1153 1154 /* check libhb level entities exist */ 1155 tl_assert(thr->hbthr); 1156 tl_assert(lk->hbso); 1157 1158 if (lk->heldBy == NULL) { 1159 /* the lock isn't held. Simple. */ 1160 tl_assert(!lk->heldW); 1161 lockN_acquire_writer( lk, thr ); 1162 /* acquire a dependency from the lock's VCs */ 1163 libhb_so_recv( thr->hbthr, lk->hbso, True/*strong_recv*/ ); 1164 goto noerror; 1165 } 1166 1167 /* So the lock is already held. If held as a r-lock then 1168 libpthread must be buggy. */ 1169 tl_assert(lk->heldBy); 1170 if (!lk->heldW) { 1171 HG_(record_error_Misc)( 1172 thr, "Bug in libpthread: write lock " 1173 "granted on rwlock which is currently rd-held"); 1174 goto error; 1175 } 1176 1177 /* So the lock is held in w-mode. If it's held by some other 1178 thread, then libpthread must be buggy. */ 1179 tl_assert(VG_(sizeUniqueBag)(lk->heldBy) == 1); /* from precondition */ 1180 1181 if (thr != (Thread*)VG_(anyElementOfBag)(lk->heldBy)) { 1182 HG_(record_error_Misc)( 1183 thr, "Bug in libpthread: write lock " 1184 "granted on mutex/rwlock which is currently " 1185 "wr-held by a different thread"); 1186 goto error; 1187 } 1188 1189 /* So the lock is already held in w-mode by 'thr'. That means this 1190 is an attempt to lock it recursively, which is only allowable 1191 for LK_mbRec kinded locks. Since this routine is called only 1192 once the lock has been acquired, this must also be a libpthread 1193 bug. */ 1194 if (lk->kind != LK_mbRec) { 1195 HG_(record_error_Misc)( 1196 thr, "Bug in libpthread: recursive write lock " 1197 "granted on mutex/wrlock which does not " 1198 "support recursion"); 1199 goto error; 1200 } 1201 1202 /* So we are recursively re-locking a lock we already w-hold. */ 1203 lockN_acquire_writer( lk, thr ); 1204 /* acquire a dependency from the lock's VC. Probably pointless, 1205 but also harmless. */ 1206 libhb_so_recv( thr->hbthr, lk->hbso, True/*strong_recv*/ ); 1207 goto noerror; 1208 1209 noerror: 1210 /* check lock order acquisition graph, and update. This has to 1211 happen before the lock is added to the thread's locksetA/W. */ 1212 laog__pre_thread_acquires_lock( thr, lk ); 1213 /* update the thread's held-locks set */ 1214 thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (Word)lk ); 1215 thr->locksetW = HG_(addToWS)( univ_lsets, thr->locksetW, (Word)lk ); 1216 /* fall through */ 1217 1218 error: 1219 tl_assert(HG_(is_sane_LockN)(lk)); 1220 } 1221 1222 1223 /* The lock at 'lock_ga' has acquired a reader. Make all necessary 1224 updates, and also do all possible error checks. */ 1225 static 1226 void evhH__post_thread_r_acquires_lock ( Thread* thr, 1227 LockKind lkk, Addr lock_ga ) 1228 { 1229 Lock* lk; 1230 1231 /* Basically what we need to do is call lockN_acquire_reader. 1232 However, that will barf if any 'invalid' lock states would 1233 result. Therefore check before calling. Side effect is that 1234 'HG_(is_sane_LockN)(lk)' is both a pre- and post-condition of this 1235 routine. 1236 1237 Because this routine is only called after successful lock 1238 acquisition, we should not be asked to move the lock into any 1239 invalid states. Requests to do so are bugs in libpthread, since 1240 that should have rejected any such requests. */ 1241 1242 tl_assert(HG_(is_sane_Thread)(thr)); 1243 /* Try to find the lock. If we can't, then create a new one with 1244 kind 'lkk'. Only a reader-writer lock can be read-locked, 1245 hence the first assertion. */ 1246 tl_assert(lkk == LK_rdwr); 1247 lk = map_locks_lookup_or_create( 1248 lkk, lock_ga, map_threads_reverse_lookup_SLOW(thr) ); 1249 tl_assert( HG_(is_sane_LockN)(lk) ); 1250 1251 /* check libhb level entities exist */ 1252 tl_assert(thr->hbthr); 1253 tl_assert(lk->hbso); 1254 1255 if (lk->heldBy == NULL) { 1256 /* the lock isn't held. Simple. */ 1257 tl_assert(!lk->heldW); 1258 lockN_acquire_reader( lk, thr ); 1259 /* acquire a dependency from the lock's VC */ 1260 libhb_so_recv( thr->hbthr, lk->hbso, False/*!strong_recv*/ ); 1261 goto noerror; 1262 } 1263 1264 /* So the lock is already held. If held as a w-lock then 1265 libpthread must be buggy. */ 1266 tl_assert(lk->heldBy); 1267 if (lk->heldW) { 1268 HG_(record_error_Misc)( thr, "Bug in libpthread: read lock " 1269 "granted on rwlock which is " 1270 "currently wr-held"); 1271 goto error; 1272 } 1273 1274 /* Easy enough. In short anybody can get a read-lock on a rwlock 1275 provided it is either unlocked or already in rd-held. */ 1276 lockN_acquire_reader( lk, thr ); 1277 /* acquire a dependency from the lock's VC. Probably pointless, 1278 but also harmless. */ 1279 libhb_so_recv( thr->hbthr, lk->hbso, False/*!strong_recv*/ ); 1280 goto noerror; 1281 1282 noerror: 1283 /* check lock order acquisition graph, and update. This has to 1284 happen before the lock is added to the thread's locksetA/W. */ 1285 laog__pre_thread_acquires_lock( thr, lk ); 1286 /* update the thread's held-locks set */ 1287 thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (Word)lk ); 1288 /* but don't update thr->locksetW, since lk is only rd-held */ 1289 /* fall through */ 1290 1291 error: 1292 tl_assert(HG_(is_sane_LockN)(lk)); 1293 } 1294 1295 1296 /* The lock at 'lock_ga' is just about to be unlocked. Make all 1297 necessary updates, and also do all possible error checks. */ 1298 static 1299 void evhH__pre_thread_releases_lock ( Thread* thr, 1300 Addr lock_ga, Bool isRDWR ) 1301 { 1302 Lock* lock; 1303 Word n; 1304 Bool was_heldW; 1305 1306 /* This routine is called prior to a lock release, before 1307 libpthread has had a chance to validate the call. Hence we need 1308 to detect and reject any attempts to move the lock into an 1309 invalid state. Such attempts are bugs in the client. 1310 1311 isRDWR is True if we know from the wrapper context that lock_ga 1312 should refer to a reader-writer lock, and is False if [ditto] 1313 lock_ga should refer to a standard mutex. */ 1314 1315 tl_assert(HG_(is_sane_Thread)(thr)); 1316 lock = map_locks_maybe_lookup( lock_ga ); 1317 1318 if (!lock) { 1319 /* We know nothing about a lock at 'lock_ga'. Nevertheless 1320 the client is trying to unlock it. So complain, then ignore 1321 the attempt. */ 1322 HG_(record_error_UnlockBogus)( thr, lock_ga ); 1323 return; 1324 } 1325 1326 tl_assert(lock->guestaddr == lock_ga); 1327 tl_assert(HG_(is_sane_LockN)(lock)); 1328 1329 if (isRDWR && lock->kind != LK_rdwr) { 1330 HG_(record_error_Misc)( thr, "pthread_rwlock_unlock with a " 1331 "pthread_mutex_t* argument " ); 1332 } 1333 if ((!isRDWR) && lock->kind == LK_rdwr) { 1334 HG_(record_error_Misc)( thr, "pthread_mutex_unlock with a " 1335 "pthread_rwlock_t* argument " ); 1336 } 1337 1338 if (!lock->heldBy) { 1339 /* The lock is not held. This indicates a serious bug in the 1340 client. */ 1341 tl_assert(!lock->heldW); 1342 HG_(record_error_UnlockUnlocked)( thr, lock ); 1343 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lock )); 1344 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock )); 1345 goto error; 1346 } 1347 1348 /* test just above dominates */ 1349 tl_assert(lock->heldBy); 1350 was_heldW = lock->heldW; 1351 1352 /* The lock is held. Is this thread one of the holders? If not, 1353 report a bug in the client. */ 1354 n = VG_(elemBag)( lock->heldBy, (Word)thr ); 1355 tl_assert(n >= 0); 1356 if (n == 0) { 1357 /* We are not a current holder of the lock. This is a bug in 1358 the guest, and (per POSIX pthread rules) the unlock 1359 attempt will fail. So just complain and do nothing 1360 else. */ 1361 Thread* realOwner = (Thread*)VG_(anyElementOfBag)( lock->heldBy ); 1362 tl_assert(HG_(is_sane_Thread)(realOwner)); 1363 tl_assert(realOwner != thr); 1364 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lock )); 1365 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock )); 1366 HG_(record_error_UnlockForeign)( thr, realOwner, lock ); 1367 goto error; 1368 } 1369 1370 /* Ok, we hold the lock 'n' times. */ 1371 tl_assert(n >= 1); 1372 1373 lockN_release( lock, thr ); 1374 1375 n--; 1376 tl_assert(n >= 0); 1377 1378 if (n > 0) { 1379 tl_assert(lock->heldBy); 1380 tl_assert(n == VG_(elemBag)( lock->heldBy, (Word)thr )); 1381 /* We still hold the lock. So either it's a recursive lock 1382 or a rwlock which is currently r-held. */ 1383 tl_assert(lock->kind == LK_mbRec 1384 || (lock->kind == LK_rdwr && !lock->heldW)); 1385 tl_assert(HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lock )); 1386 if (lock->heldW) 1387 tl_assert(HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock )); 1388 else 1389 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock )); 1390 } else { 1391 /* n is zero. This means we don't hold the lock any more. But 1392 if it's a rwlock held in r-mode, someone else could still 1393 hold it. Just do whatever sanity checks we can. */ 1394 if (lock->kind == LK_rdwr && lock->heldBy) { 1395 /* It's a rwlock. We no longer hold it but we used to; 1396 nevertheless it still appears to be held by someone else. 1397 The implication is that, prior to this release, it must 1398 have been shared by us and and whoever else is holding it; 1399 which in turn implies it must be r-held, since a lock 1400 can't be w-held by more than one thread. */ 1401 /* The lock is now R-held by somebody else: */ 1402 tl_assert(lock->heldW == False); 1403 } else { 1404 /* Normal case. It's either not a rwlock, or it's a rwlock 1405 that we used to hold in w-mode (which is pretty much the 1406 same thing as a non-rwlock.) Since this transaction is 1407 atomic (V does not allow multiple threads to run 1408 simultaneously), it must mean the lock is now not held by 1409 anybody. Hence assert for it. */ 1410 /* The lock is now not held by anybody: */ 1411 tl_assert(!lock->heldBy); 1412 tl_assert(lock->heldW == False); 1413 } 1414 //if (lock->heldBy) { 1415 // tl_assert(0 == VG_(elemBag)( lock->heldBy, (Word)thr )); 1416 //} 1417 /* update this thread's lockset accordingly. */ 1418 thr->locksetA 1419 = HG_(delFromWS)( univ_lsets, thr->locksetA, (Word)lock ); 1420 thr->locksetW 1421 = HG_(delFromWS)( univ_lsets, thr->locksetW, (Word)lock ); 1422 /* push our VC into the lock */ 1423 tl_assert(thr->hbthr); 1424 tl_assert(lock->hbso); 1425 /* If the lock was previously W-held, then we want to do a 1426 strong send, and if previously R-held, then a weak send. */ 1427 libhb_so_send( thr->hbthr, lock->hbso, was_heldW ); 1428 } 1429 /* fall through */ 1430 1431 error: 1432 tl_assert(HG_(is_sane_LockN)(lock)); 1433 } 1434 1435 1436 /* ---------------------------------------------------------- */ 1437 /* -------- Event handlers proper (evh__* functions) -------- */ 1438 /* ---------------------------------------------------------- */ 1439 1440 /* What is the Thread* for the currently running thread? This is 1441 absolutely performance critical. We receive notifications from the 1442 core for client code starts/stops, and cache the looked-up result 1443 in 'current_Thread'. Hence, for the vast majority of requests, 1444 finding the current thread reduces to a read of a global variable, 1445 provided get_current_Thread_in_C_C is inlined. 1446 1447 Outside of client code, current_Thread is NULL, and presumably 1448 any uses of it will cause a segfault. Hence: 1449 1450 - for uses definitely within client code, use 1451 get_current_Thread_in_C_C. 1452 1453 - for all other uses, use get_current_Thread. 1454 */ 1455 1456 static Thread *current_Thread = NULL, 1457 *current_Thread_prev = NULL; 1458 1459 static void evh__start_client_code ( ThreadId tid, ULong nDisp ) { 1460 if (0) VG_(printf)("start %d %llu\n", (Int)tid, nDisp); 1461 tl_assert(current_Thread == NULL); 1462 current_Thread = map_threads_lookup( tid ); 1463 tl_assert(current_Thread != NULL); 1464 if (current_Thread != current_Thread_prev) { 1465 libhb_Thr_resumes( current_Thread->hbthr ); 1466 current_Thread_prev = current_Thread; 1467 } 1468 } 1469 static void evh__stop_client_code ( ThreadId tid, ULong nDisp ) { 1470 if (0) VG_(printf)(" stop %d %llu\n", (Int)tid, nDisp); 1471 tl_assert(current_Thread != NULL); 1472 current_Thread = NULL; 1473 libhb_maybe_GC(); 1474 } 1475 static inline Thread* get_current_Thread_in_C_C ( void ) { 1476 return current_Thread; 1477 } 1478 static inline Thread* get_current_Thread ( void ) { 1479 ThreadId coretid; 1480 Thread* thr; 1481 thr = get_current_Thread_in_C_C(); 1482 if (LIKELY(thr)) 1483 return thr; 1484 /* evidently not in client code. Do it the slow way. */ 1485 coretid = VG_(get_running_tid)(); 1486 /* FIXME: get rid of the following kludge. It exists because 1487 evh__new_mem is called during initialisation (as notification 1488 of initial memory layout) and VG_(get_running_tid)() returns 1489 VG_INVALID_THREADID at that point. */ 1490 if (coretid == VG_INVALID_THREADID) 1491 coretid = 1; /* KLUDGE */ 1492 thr = map_threads_lookup( coretid ); 1493 return thr; 1494 } 1495 1496 static 1497 void evh__new_mem ( Addr a, SizeT len ) { 1498 if (SHOW_EVENTS >= 2) 1499 VG_(printf)("evh__new_mem(%p, %lu)\n", (void*)a, len ); 1500 shadow_mem_make_New( get_current_Thread(), a, len ); 1501 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1502 all__sanity_check("evh__new_mem-post"); 1503 } 1504 1505 static 1506 void evh__new_mem_stack ( Addr a, SizeT len ) { 1507 if (SHOW_EVENTS >= 2) 1508 VG_(printf)("evh__new_mem_stack(%p, %lu)\n", (void*)a, len ); 1509 shadow_mem_make_New( get_current_Thread(), 1510 -VG_STACK_REDZONE_SZB + a, len ); 1511 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1512 all__sanity_check("evh__new_mem_stack-post"); 1513 } 1514 1515 static 1516 void evh__new_mem_w_tid ( Addr a, SizeT len, ThreadId tid ) { 1517 if (SHOW_EVENTS >= 2) 1518 VG_(printf)("evh__new_mem_w_tid(%p, %lu)\n", (void*)a, len ); 1519 shadow_mem_make_New( get_current_Thread(), a, len ); 1520 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1521 all__sanity_check("evh__new_mem_w_tid-post"); 1522 } 1523 1524 static 1525 void evh__new_mem_w_perms ( Addr a, SizeT len, 1526 Bool rr, Bool ww, Bool xx, ULong di_handle ) { 1527 if (SHOW_EVENTS >= 1) 1528 VG_(printf)("evh__new_mem_w_perms(%p, %lu, %d,%d,%d)\n", 1529 (void*)a, len, (Int)rr, (Int)ww, (Int)xx ); 1530 if (rr || ww || xx) 1531 shadow_mem_make_New( get_current_Thread(), a, len ); 1532 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1533 all__sanity_check("evh__new_mem_w_perms-post"); 1534 } 1535 1536 static 1537 void evh__set_perms ( Addr a, SizeT len, 1538 Bool rr, Bool ww, Bool xx ) { 1539 if (SHOW_EVENTS >= 1) 1540 VG_(printf)("evh__set_perms(%p, %lu, %d,%d,%d)\n", 1541 (void*)a, len, (Int)rr, (Int)ww, (Int)xx ); 1542 /* Hmm. What should we do here, that actually makes any sense? 1543 Let's say: if neither readable nor writable, then declare it 1544 NoAccess, else leave it alone. */ 1545 if (!(rr || ww)) 1546 shadow_mem_make_NoAccess( get_current_Thread(), a, len ); 1547 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1548 all__sanity_check("evh__set_perms-post"); 1549 } 1550 1551 static 1552 void evh__die_mem ( Addr a, SizeT len ) { 1553 // urr, libhb ignores this. 1554 if (SHOW_EVENTS >= 2) 1555 VG_(printf)("evh__die_mem(%p, %lu)\n", (void*)a, len ); 1556 shadow_mem_make_NoAccess( get_current_Thread(), a, len ); 1557 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1558 all__sanity_check("evh__die_mem-post"); 1559 } 1560 1561 static 1562 void evh__untrack_mem ( Addr a, SizeT len ) { 1563 // whereas it doesn't ignore this 1564 if (SHOW_EVENTS >= 2) 1565 VG_(printf)("evh__untrack_mem(%p, %lu)\n", (void*)a, len ); 1566 shadow_mem_make_Untracked( get_current_Thread(), a, len ); 1567 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1568 all__sanity_check("evh__untrack_mem-post"); 1569 } 1570 1571 static 1572 void evh__copy_mem ( Addr src, Addr dst, SizeT len ) { 1573 if (SHOW_EVENTS >= 2) 1574 VG_(printf)("evh__copy_mem(%p, %p, %lu)\n", (void*)src, (void*)dst, len ); 1575 shadow_mem_scopy_range( get_current_Thread(), src, dst, len ); 1576 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1577 all__sanity_check("evh__copy_mem-post"); 1578 } 1579 1580 static 1581 void evh__pre_thread_ll_create ( ThreadId parent, ThreadId child ) 1582 { 1583 if (SHOW_EVENTS >= 1) 1584 VG_(printf)("evh__pre_thread_ll_create(p=%d, c=%d)\n", 1585 (Int)parent, (Int)child ); 1586 1587 if (parent != VG_INVALID_THREADID) { 1588 Thread* thr_p; 1589 Thread* thr_c; 1590 Thr* hbthr_p; 1591 Thr* hbthr_c; 1592 1593 tl_assert(HG_(is_sane_ThreadId)(parent)); 1594 tl_assert(HG_(is_sane_ThreadId)(child)); 1595 tl_assert(parent != child); 1596 1597 thr_p = map_threads_maybe_lookup( parent ); 1598 thr_c = map_threads_maybe_lookup( child ); 1599 1600 tl_assert(thr_p != NULL); 1601 tl_assert(thr_c == NULL); 1602 1603 hbthr_p = thr_p->hbthr; 1604 tl_assert(hbthr_p != NULL); 1605 tl_assert( libhb_get_Thr_opaque(hbthr_p) == thr_p ); 1606 1607 hbthr_c = libhb_create ( hbthr_p ); 1608 1609 /* Create a new thread record for the child. */ 1610 /* a Thread for the new thread ... */ 1611 thr_c = mk_Thread( hbthr_c ); 1612 tl_assert( libhb_get_Thr_opaque(hbthr_c) == NULL ); 1613 libhb_set_Thr_opaque(hbthr_c, thr_c); 1614 1615 /* and bind it in the thread-map table */ 1616 map_threads[child] = thr_c; 1617 tl_assert(thr_c->coretid == VG_INVALID_THREADID); 1618 thr_c->coretid = child; 1619 1620 /* Record where the parent is so we can later refer to this in 1621 error messages. 1622 1623 On amd64-linux, this entails a nasty glibc-2.5 specific hack. 1624 The stack snapshot is taken immediately after the parent has 1625 returned from its sys_clone call. Unfortunately there is no 1626 unwind info for the insn following "syscall" - reading the 1627 glibc sources confirms this. So we ask for a snapshot to be 1628 taken as if RIP was 3 bytes earlier, in a place where there 1629 is unwind info. Sigh. 1630 */ 1631 { Word first_ip_delta = 0; 1632 # if defined(VGP_amd64_linux) 1633 first_ip_delta = -3; 1634 # endif 1635 thr_c->created_at = VG_(record_ExeContext)(parent, first_ip_delta); 1636 } 1637 } 1638 1639 if (HG_(clo_sanity_flags) & SCE_THREADS) 1640 all__sanity_check("evh__pre_thread_create-post"); 1641 } 1642 1643 static 1644 void evh__pre_thread_ll_exit ( ThreadId quit_tid ) 1645 { 1646 Int nHeld; 1647 Thread* thr_q; 1648 if (SHOW_EVENTS >= 1) 1649 VG_(printf)("evh__pre_thread_ll_exit(thr=%d)\n", 1650 (Int)quit_tid ); 1651 1652 /* quit_tid has disappeared without joining to any other thread. 1653 Therefore there is no synchronisation event associated with its 1654 exit and so we have to pretty much treat it as if it was still 1655 alive but mysteriously making no progress. That is because, if 1656 we don't know when it really exited, then we can never say there 1657 is a point in time when we're sure the thread really has 1658 finished, and so we need to consider the possibility that it 1659 lingers indefinitely and continues to interact with other 1660 threads. */ 1661 /* However, it might have rendezvous'd with a thread that called 1662 pthread_join with this one as arg, prior to this point (that's 1663 how NPTL works). In which case there has already been a prior 1664 sync event. So in any case, just let the thread exit. On NPTL, 1665 all thread exits go through here. */ 1666 tl_assert(HG_(is_sane_ThreadId)(quit_tid)); 1667 thr_q = map_threads_maybe_lookup( quit_tid ); 1668 tl_assert(thr_q != NULL); 1669 1670 /* Complain if this thread holds any locks. */ 1671 nHeld = HG_(cardinalityWS)( univ_lsets, thr_q->locksetA ); 1672 tl_assert(nHeld >= 0); 1673 if (nHeld > 0) { 1674 HChar buf[80]; 1675 VG_(sprintf)(buf, "Exiting thread still holds %d lock%s", 1676 nHeld, nHeld > 1 ? "s" : ""); 1677 HG_(record_error_Misc)( thr_q, buf ); 1678 } 1679 1680 /* Not much to do here: 1681 - tell libhb the thread is gone 1682 - clear the map_threads entry, in order that the Valgrind core 1683 can re-use it. */ 1684 /* Cleanup actions (next 5 lines) copied in evh__atfork_child; keep 1685 in sync. */ 1686 tl_assert(thr_q->hbthr); 1687 libhb_async_exit(thr_q->hbthr); 1688 tl_assert(thr_q->coretid == quit_tid); 1689 thr_q->coretid = VG_INVALID_THREADID; 1690 map_threads_delete( quit_tid ); 1691 1692 if (HG_(clo_sanity_flags) & SCE_THREADS) 1693 all__sanity_check("evh__pre_thread_ll_exit-post"); 1694 } 1695 1696 /* This is called immediately after fork, for the child only. 'tid' 1697 is the only surviving thread (as per POSIX rules on fork() in 1698 threaded programs), so we have to clean up map_threads to remove 1699 entries for any other threads. */ 1700 static 1701 void evh__atfork_child ( ThreadId tid ) 1702 { 1703 UInt i; 1704 Thread* thr; 1705 /* Slot 0 should never be used. */ 1706 thr = map_threads_maybe_lookup( 0/*INVALID*/ ); 1707 tl_assert(!thr); 1708 /* Clean up all other slots except 'tid'. */ 1709 for (i = 1; i < VG_N_THREADS; i++) { 1710 if (i == tid) 1711 continue; 1712 thr = map_threads_maybe_lookup(i); 1713 if (!thr) 1714 continue; 1715 /* Cleanup actions (next 5 lines) copied from end of 1716 evh__pre_thread_ll_exit; keep in sync. */ 1717 tl_assert(thr->hbthr); 1718 libhb_async_exit(thr->hbthr); 1719 tl_assert(thr->coretid == i); 1720 thr->coretid = VG_INVALID_THREADID; 1721 map_threads_delete(i); 1722 } 1723 } 1724 1725 1726 static 1727 void evh__HG_PTHREAD_JOIN_POST ( ThreadId stay_tid, Thread* quit_thr ) 1728 { 1729 Thread* thr_s; 1730 Thread* thr_q; 1731 Thr* hbthr_s; 1732 Thr* hbthr_q; 1733 SO* so; 1734 1735 if (SHOW_EVENTS >= 1) 1736 VG_(printf)("evh__post_thread_join(stayer=%d, quitter=%p)\n", 1737 (Int)stay_tid, quit_thr ); 1738 1739 tl_assert(HG_(is_sane_ThreadId)(stay_tid)); 1740 1741 thr_s = map_threads_maybe_lookup( stay_tid ); 1742 thr_q = quit_thr; 1743 tl_assert(thr_s != NULL); 1744 tl_assert(thr_q != NULL); 1745 tl_assert(thr_s != thr_q); 1746 1747 hbthr_s = thr_s->hbthr; 1748 hbthr_q = thr_q->hbthr; 1749 tl_assert(hbthr_s != hbthr_q); 1750 tl_assert( libhb_get_Thr_opaque(hbthr_s) == thr_s ); 1751 tl_assert( libhb_get_Thr_opaque(hbthr_q) == thr_q ); 1752 1753 /* Allocate a temporary synchronisation object and use it to send 1754 an imaginary message from the quitter to the stayer, the purpose 1755 being to generate a dependence from the quitter to the 1756 stayer. */ 1757 so = libhb_so_alloc(); 1758 tl_assert(so); 1759 /* Send last arg of _so_send as False, since the sending thread 1760 doesn't actually exist any more, so we don't want _so_send to 1761 try taking stack snapshots of it. */ 1762 libhb_so_send(hbthr_q, so, True/*strong_send*/); 1763 libhb_so_recv(hbthr_s, so, True/*strong_recv*/); 1764 libhb_so_dealloc(so); 1765 1766 /* evh__pre_thread_ll_exit issues an error message if the exiting 1767 thread holds any locks. No need to check here. */ 1768 1769 /* This holds because, at least when using NPTL as the thread 1770 library, we should be notified the low level thread exit before 1771 we hear of any join event on it. The low level exit 1772 notification feeds through into evh__pre_thread_ll_exit, 1773 which should clear the map_threads entry for it. Hence we 1774 expect there to be no map_threads entry at this point. */ 1775 tl_assert( map_threads_maybe_reverse_lookup_SLOW(thr_q) 1776 == VG_INVALID_THREADID); 1777 1778 if (HG_(clo_sanity_flags) & SCE_THREADS) 1779 all__sanity_check("evh__post_thread_join-post"); 1780 } 1781 1782 static 1783 void evh__pre_mem_read ( CorePart part, ThreadId tid, Char* s, 1784 Addr a, SizeT size) { 1785 if (SHOW_EVENTS >= 2 1786 || (SHOW_EVENTS >= 1 && size != 1)) 1787 VG_(printf)("evh__pre_mem_read(ctid=%d, \"%s\", %p, %lu)\n", 1788 (Int)tid, s, (void*)a, size ); 1789 shadow_mem_cread_range( map_threads_lookup(tid), a, size); 1790 if (size >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1791 all__sanity_check("evh__pre_mem_read-post"); 1792 } 1793 1794 static 1795 void evh__pre_mem_read_asciiz ( CorePart part, ThreadId tid, 1796 Char* s, Addr a ) { 1797 Int len; 1798 if (SHOW_EVENTS >= 1) 1799 VG_(printf)("evh__pre_mem_asciiz(ctid=%d, \"%s\", %p)\n", 1800 (Int)tid, s, (void*)a ); 1801 // Don't segfault if the string starts in an obviously stupid 1802 // place. Actually we should check the whole string, not just 1803 // the start address, but that's too much trouble. At least 1804 // checking the first byte is better than nothing. See #255009. 1805 if (!VG_(am_is_valid_for_client) (a, 1, VKI_PROT_READ)) 1806 return; 1807 len = VG_(strlen)( (Char*) a ); 1808 shadow_mem_cread_range( map_threads_lookup(tid), a, len+1 ); 1809 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1810 all__sanity_check("evh__pre_mem_read_asciiz-post"); 1811 } 1812 1813 static 1814 void evh__pre_mem_write ( CorePart part, ThreadId tid, Char* s, 1815 Addr a, SizeT size ) { 1816 if (SHOW_EVENTS >= 1) 1817 VG_(printf)("evh__pre_mem_write(ctid=%d, \"%s\", %p, %lu)\n", 1818 (Int)tid, s, (void*)a, size ); 1819 shadow_mem_cwrite_range( map_threads_lookup(tid), a, size); 1820 if (size >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1821 all__sanity_check("evh__pre_mem_write-post"); 1822 } 1823 1824 static 1825 void evh__new_mem_heap ( Addr a, SizeT len, Bool is_inited ) { 1826 if (SHOW_EVENTS >= 1) 1827 VG_(printf)("evh__new_mem_heap(%p, %lu, inited=%d)\n", 1828 (void*)a, len, (Int)is_inited ); 1829 // FIXME: this is kinda stupid 1830 if (is_inited) { 1831 shadow_mem_make_New(get_current_Thread(), a, len); 1832 } else { 1833 shadow_mem_make_New(get_current_Thread(), a, len); 1834 } 1835 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1836 all__sanity_check("evh__pre_mem_read-post"); 1837 } 1838 1839 static 1840 void evh__die_mem_heap ( Addr a, SizeT len ) { 1841 if (SHOW_EVENTS >= 1) 1842 VG_(printf)("evh__die_mem_heap(%p, %lu)\n", (void*)a, len ); 1843 shadow_mem_make_NoAccess( get_current_Thread(), a, len ); 1844 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1845 all__sanity_check("evh__pre_mem_read-post"); 1846 } 1847 1848 /* --- Event handlers called from generated code --- */ 1849 1850 static VG_REGPARM(1) 1851 void evh__mem_help_cread_1(Addr a) { 1852 Thread* thr = get_current_Thread_in_C_C(); 1853 Thr* hbthr = thr->hbthr; 1854 LIBHB_CREAD_1(hbthr, a); 1855 } 1856 1857 static VG_REGPARM(1) 1858 void evh__mem_help_cread_2(Addr a) { 1859 Thread* thr = get_current_Thread_in_C_C(); 1860 Thr* hbthr = thr->hbthr; 1861 LIBHB_CREAD_2(hbthr, a); 1862 } 1863 1864 static VG_REGPARM(1) 1865 void evh__mem_help_cread_4(Addr a) { 1866 Thread* thr = get_current_Thread_in_C_C(); 1867 Thr* hbthr = thr->hbthr; 1868 LIBHB_CREAD_4(hbthr, a); 1869 } 1870 1871 static VG_REGPARM(1) 1872 void evh__mem_help_cread_8(Addr a) { 1873 Thread* thr = get_current_Thread_in_C_C(); 1874 Thr* hbthr = thr->hbthr; 1875 LIBHB_CREAD_8(hbthr, a); 1876 } 1877 1878 static VG_REGPARM(2) 1879 void evh__mem_help_cread_N(Addr a, SizeT size) { 1880 Thread* thr = get_current_Thread_in_C_C(); 1881 Thr* hbthr = thr->hbthr; 1882 LIBHB_CREAD_N(hbthr, a, size); 1883 } 1884 1885 static VG_REGPARM(1) 1886 void evh__mem_help_cwrite_1(Addr a) { 1887 Thread* thr = get_current_Thread_in_C_C(); 1888 Thr* hbthr = thr->hbthr; 1889 LIBHB_CWRITE_1(hbthr, a); 1890 } 1891 1892 static VG_REGPARM(1) 1893 void evh__mem_help_cwrite_2(Addr a) { 1894 Thread* thr = get_current_Thread_in_C_C(); 1895 Thr* hbthr = thr->hbthr; 1896 LIBHB_CWRITE_2(hbthr, a); 1897 } 1898 1899 static VG_REGPARM(1) 1900 void evh__mem_help_cwrite_4(Addr a) { 1901 Thread* thr = get_current_Thread_in_C_C(); 1902 Thr* hbthr = thr->hbthr; 1903 LIBHB_CWRITE_4(hbthr, a); 1904 } 1905 1906 static VG_REGPARM(1) 1907 void evh__mem_help_cwrite_8(Addr a) { 1908 Thread* thr = get_current_Thread_in_C_C(); 1909 Thr* hbthr = thr->hbthr; 1910 LIBHB_CWRITE_8(hbthr, a); 1911 } 1912 1913 static VG_REGPARM(2) 1914 void evh__mem_help_cwrite_N(Addr a, SizeT size) { 1915 Thread* thr = get_current_Thread_in_C_C(); 1916 Thr* hbthr = thr->hbthr; 1917 LIBHB_CWRITE_N(hbthr, a, size); 1918 } 1919 1920 1921 /* ------------------------------------------------------- */ 1922 /* -------------- events to do with mutexes -------------- */ 1923 /* ------------------------------------------------------- */ 1924 1925 /* EXPOSITION only: by intercepting lock init events we can show the 1926 user where the lock was initialised, rather than only being able to 1927 show where it was first locked. Intercepting lock initialisations 1928 is not necessary for the basic operation of the race checker. */ 1929 static 1930 void evh__HG_PTHREAD_MUTEX_INIT_POST( ThreadId tid, 1931 void* mutex, Word mbRec ) 1932 { 1933 if (SHOW_EVENTS >= 1) 1934 VG_(printf)("evh__hg_PTHREAD_MUTEX_INIT_POST(ctid=%d, mbRec=%ld, %p)\n", 1935 (Int)tid, mbRec, (void*)mutex ); 1936 tl_assert(mbRec == 0 || mbRec == 1); 1937 map_locks_lookup_or_create( mbRec ? LK_mbRec : LK_nonRec, 1938 (Addr)mutex, tid ); 1939 if (HG_(clo_sanity_flags) & SCE_LOCKS) 1940 all__sanity_check("evh__hg_PTHREAD_MUTEX_INIT_POST"); 1941 } 1942 1943 static 1944 void evh__HG_PTHREAD_MUTEX_DESTROY_PRE( ThreadId tid, void* mutex ) 1945 { 1946 Thread* thr; 1947 Lock* lk; 1948 if (SHOW_EVENTS >= 1) 1949 VG_(printf)("evh__hg_PTHREAD_MUTEX_DESTROY_PRE(ctid=%d, %p)\n", 1950 (Int)tid, (void*)mutex ); 1951 1952 thr = map_threads_maybe_lookup( tid ); 1953 /* cannot fail - Thread* must already exist */ 1954 tl_assert( HG_(is_sane_Thread)(thr) ); 1955 1956 lk = map_locks_maybe_lookup( (Addr)mutex ); 1957 1958 if (lk == NULL || (lk->kind != LK_nonRec && lk->kind != LK_mbRec)) { 1959 HG_(record_error_Misc)( 1960 thr, "pthread_mutex_destroy with invalid argument" ); 1961 } 1962 1963 if (lk) { 1964 tl_assert( HG_(is_sane_LockN)(lk) ); 1965 tl_assert( lk->guestaddr == (Addr)mutex ); 1966 if (lk->heldBy) { 1967 /* Basically act like we unlocked the lock */ 1968 HG_(record_error_Misc)( 1969 thr, "pthread_mutex_destroy of a locked mutex" ); 1970 /* remove lock from locksets of all owning threads */ 1971 remove_Lock_from_locksets_of_all_owning_Threads( lk ); 1972 VG_(deleteBag)( lk->heldBy ); 1973 lk->heldBy = NULL; 1974 lk->heldW = False; 1975 lk->acquired_at = NULL; 1976 } 1977 tl_assert( !lk->heldBy ); 1978 tl_assert( HG_(is_sane_LockN)(lk) ); 1979 1980 laog__handle_one_lock_deletion(lk); 1981 map_locks_delete( lk->guestaddr ); 1982 del_LockN( lk ); 1983 } 1984 1985 if (HG_(clo_sanity_flags) & SCE_LOCKS) 1986 all__sanity_check("evh__hg_PTHREAD_MUTEX_DESTROY_PRE"); 1987 } 1988 1989 static void evh__HG_PTHREAD_MUTEX_LOCK_PRE ( ThreadId tid, 1990 void* mutex, Word isTryLock ) 1991 { 1992 /* Just check the mutex is sane; nothing else to do. */ 1993 // 'mutex' may be invalid - not checked by wrapper 1994 Thread* thr; 1995 Lock* lk; 1996 if (SHOW_EVENTS >= 1) 1997 VG_(printf)("evh__hg_PTHREAD_MUTEX_LOCK_PRE(ctid=%d, mutex=%p)\n", 1998 (Int)tid, (void*)mutex ); 1999 2000 tl_assert(isTryLock == 0 || isTryLock == 1); 2001 thr = map_threads_maybe_lookup( tid ); 2002 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2003 2004 lk = map_locks_maybe_lookup( (Addr)mutex ); 2005 2006 if (lk && (lk->kind == LK_rdwr)) { 2007 HG_(record_error_Misc)( thr, "pthread_mutex_lock with a " 2008 "pthread_rwlock_t* argument " ); 2009 } 2010 2011 if ( lk 2012 && isTryLock == 0 2013 && (lk->kind == LK_nonRec || lk->kind == LK_rdwr) 2014 && lk->heldBy 2015 && lk->heldW 2016 && VG_(elemBag)( lk->heldBy, (Word)thr ) > 0 ) { 2017 /* uh, it's a non-recursive lock and we already w-hold it, and 2018 this is a real lock operation (not a speculative "tryLock" 2019 kind of thing). Duh. Deadlock coming up; but at least 2020 produce an error message. */ 2021 HChar* errstr = "Attempt to re-lock a " 2022 "non-recursive lock I already hold"; 2023 HChar* auxstr = "Lock was previously acquired"; 2024 if (lk->acquired_at) { 2025 HG_(record_error_Misc_w_aux)( thr, errstr, auxstr, lk->acquired_at ); 2026 } else { 2027 HG_(record_error_Misc)( thr, errstr ); 2028 } 2029 } 2030 } 2031 2032 static void evh__HG_PTHREAD_MUTEX_LOCK_POST ( ThreadId tid, void* mutex ) 2033 { 2034 // only called if the real library call succeeded - so mutex is sane 2035 Thread* thr; 2036 if (SHOW_EVENTS >= 1) 2037 VG_(printf)("evh__HG_PTHREAD_MUTEX_LOCK_POST(ctid=%d, mutex=%p)\n", 2038 (Int)tid, (void*)mutex ); 2039 2040 thr = map_threads_maybe_lookup( tid ); 2041 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2042 2043 evhH__post_thread_w_acquires_lock( 2044 thr, 2045 LK_mbRec, /* if not known, create new lock with this LockKind */ 2046 (Addr)mutex 2047 ); 2048 } 2049 2050 static void evh__HG_PTHREAD_MUTEX_UNLOCK_PRE ( ThreadId tid, void* mutex ) 2051 { 2052 // 'mutex' may be invalid - not checked by wrapper 2053 Thread* thr; 2054 if (SHOW_EVENTS >= 1) 2055 VG_(printf)("evh__HG_PTHREAD_MUTEX_UNLOCK_PRE(ctid=%d, mutex=%p)\n", 2056 (Int)tid, (void*)mutex ); 2057 2058 thr = map_threads_maybe_lookup( tid ); 2059 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2060 2061 evhH__pre_thread_releases_lock( thr, (Addr)mutex, False/*!isRDWR*/ ); 2062 } 2063 2064 static void evh__HG_PTHREAD_MUTEX_UNLOCK_POST ( ThreadId tid, void* mutex ) 2065 { 2066 // only called if the real library call succeeded - so mutex is sane 2067 Thread* thr; 2068 if (SHOW_EVENTS >= 1) 2069 VG_(printf)("evh__hg_PTHREAD_MUTEX_UNLOCK_POST(ctid=%d, mutex=%p)\n", 2070 (Int)tid, (void*)mutex ); 2071 thr = map_threads_maybe_lookup( tid ); 2072 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2073 2074 // anything we should do here? 2075 } 2076 2077 2078 /* ------------------------------------------------------- */ 2079 /* -------------- events to do with spinlocks ------------ */ 2080 /* ------------------------------------------------------- */ 2081 2082 /* All a bit of a kludge. Pretend we're really dealing with ordinary 2083 pthread_mutex_t's instead, for the most part. */ 2084 2085 static void evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE( ThreadId tid, 2086 void* slock ) 2087 { 2088 Thread* thr; 2089 Lock* lk; 2090 /* In glibc's kludgey world, we're either initialising or unlocking 2091 it. Since this is the pre-routine, if it is locked, unlock it 2092 and take a dependence edge. Otherwise, do nothing. */ 2093 2094 if (SHOW_EVENTS >= 1) 2095 VG_(printf)("evh__hg_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE" 2096 "(ctid=%d, slock=%p)\n", 2097 (Int)tid, (void*)slock ); 2098 2099 thr = map_threads_maybe_lookup( tid ); 2100 /* cannot fail - Thread* must already exist */; 2101 tl_assert( HG_(is_sane_Thread)(thr) ); 2102 2103 lk = map_locks_maybe_lookup( (Addr)slock ); 2104 if (lk && lk->heldBy) { 2105 /* it's held. So do the normal pre-unlock actions, as copied 2106 from evh__HG_PTHREAD_MUTEX_UNLOCK_PRE. This stupidly 2107 duplicates the map_locks_maybe_lookup. */ 2108 evhH__pre_thread_releases_lock( thr, (Addr)slock, 2109 False/*!isRDWR*/ ); 2110 } 2111 } 2112 2113 static void evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST( ThreadId tid, 2114 void* slock ) 2115 { 2116 Lock* lk; 2117 /* More kludgery. If the lock has never been seen before, do 2118 actions as per evh__HG_PTHREAD_MUTEX_INIT_POST. Else do 2119 nothing. */ 2120 2121 if (SHOW_EVENTS >= 1) 2122 VG_(printf)("evh__hg_PTHREAD_SPIN_INIT_OR_UNLOCK_POST" 2123 "(ctid=%d, slock=%p)\n", 2124 (Int)tid, (void*)slock ); 2125 2126 lk = map_locks_maybe_lookup( (Addr)slock ); 2127 if (!lk) { 2128 map_locks_lookup_or_create( LK_nonRec, (Addr)slock, tid ); 2129 } 2130 } 2131 2132 static void evh__HG_PTHREAD_SPIN_LOCK_PRE( ThreadId tid, 2133 void* slock, Word isTryLock ) 2134 { 2135 evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, slock, isTryLock ); 2136 } 2137 2138 static void evh__HG_PTHREAD_SPIN_LOCK_POST( ThreadId tid, 2139 void* slock ) 2140 { 2141 evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, slock ); 2142 } 2143 2144 static void evh__HG_PTHREAD_SPIN_DESTROY_PRE( ThreadId tid, 2145 void* slock ) 2146 { 2147 evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, slock ); 2148 } 2149 2150 2151 /* ----------------------------------------------------- */ 2152 /* --------------- events to do with CVs --------------- */ 2153 /* ----------------------------------------------------- */ 2154 2155 /* A mapping from CV to (the SO associated with it, plus some 2156 auxiliary data for error checking). When the CV is 2157 signalled/broadcasted upon, we do a 'send' into the SO, and when a 2158 wait on it completes, we do a 'recv' from the SO. This is believed 2159 to give the correct happens-before events arising from CV 2160 signallings/broadcasts. 2161 */ 2162 2163 /* .so is the SO for this CV. 2164 .mx_ga is the associated mutex, when .nWaiters > 0 2165 2166 POSIX says effectively that the first pthread_cond_{timed}wait call 2167 causes a dynamic binding between the CV and the mutex, and that 2168 lasts until such time as the waiter count falls to zero. Hence 2169 need to keep track of the number of waiters in order to do 2170 consistency tracking. */ 2171 typedef 2172 struct { 2173 SO* so; /* libhb-allocated SO */ 2174 void* mx_ga; /* addr of associated mutex, if any */ 2175 UWord nWaiters; /* # threads waiting on the CV */ 2176 } 2177 CVInfo; 2178 2179 2180 /* pthread_cond_t* -> CVInfo* */ 2181 static WordFM* map_cond_to_CVInfo = NULL; 2182 2183 static void map_cond_to_CVInfo_INIT ( void ) { 2184 if (UNLIKELY(map_cond_to_CVInfo == NULL)) { 2185 map_cond_to_CVInfo = VG_(newFM)( HG_(zalloc), 2186 "hg.mctCI.1", HG_(free), NULL ); 2187 tl_assert(map_cond_to_CVInfo != NULL); 2188 } 2189 } 2190 2191 static CVInfo* map_cond_to_CVInfo_lookup_or_alloc ( void* cond ) { 2192 UWord key, val; 2193 map_cond_to_CVInfo_INIT(); 2194 if (VG_(lookupFM)( map_cond_to_CVInfo, &key, &val, (UWord)cond )) { 2195 tl_assert(key == (UWord)cond); 2196 return (CVInfo*)val; 2197 } else { 2198 SO* so = libhb_so_alloc(); 2199 CVInfo* cvi = HG_(zalloc)("hg.mctCloa.1", sizeof(CVInfo)); 2200 cvi->so = so; 2201 cvi->mx_ga = 0; 2202 VG_(addToFM)( map_cond_to_CVInfo, (UWord)cond, (UWord)cvi ); 2203 return cvi; 2204 } 2205 } 2206 2207 static void map_cond_to_CVInfo_delete ( void* cond ) { 2208 UWord keyW, valW; 2209 map_cond_to_CVInfo_INIT(); 2210 if (VG_(delFromFM)( map_cond_to_CVInfo, &keyW, &valW, (UWord)cond )) { 2211 CVInfo* cvi = (CVInfo*)valW; 2212 tl_assert(keyW == (UWord)cond); 2213 tl_assert(cvi); 2214 tl_assert(cvi->so); 2215 libhb_so_dealloc(cvi->so); 2216 cvi->mx_ga = 0; 2217 HG_(free)(cvi); 2218 } 2219 } 2220 2221 static void evh__HG_PTHREAD_COND_SIGNAL_PRE ( ThreadId tid, void* cond ) 2222 { 2223 /* 'tid' has signalled on 'cond'. As per the comment above, bind 2224 cond to a SO if it is not already so bound, and 'send' on the 2225 SO. This is later used by other thread(s) which successfully 2226 exit from a pthread_cond_wait on the same cv; then they 'recv' 2227 from the SO, thereby acquiring a dependency on this signalling 2228 event. */ 2229 Thread* thr; 2230 CVInfo* cvi; 2231 //Lock* lk; 2232 2233 if (SHOW_EVENTS >= 1) 2234 VG_(printf)("evh__HG_PTHREAD_COND_SIGNAL_PRE(ctid=%d, cond=%p)\n", 2235 (Int)tid, (void*)cond ); 2236 2237 thr = map_threads_maybe_lookup( tid ); 2238 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2239 2240 cvi = map_cond_to_CVInfo_lookup_or_alloc( cond ); 2241 tl_assert(cvi); 2242 tl_assert(cvi->so); 2243 2244 // error-if: mutex is bogus 2245 // error-if: mutex is not locked 2246 // Hmm. POSIX doesn't actually say that it's an error to call 2247 // pthread_cond_signal with the associated mutex being unlocked. 2248 // Although it does say that it should be "if consistent scheduling 2249 // is desired." 2250 // 2251 // For the moment, disable these checks. 2252 //lk = map_locks_maybe_lookup(cvi->mx_ga); 2253 //if (lk == NULL || cvi->mx_ga == 0) { 2254 // HG_(record_error_Misc)( thr, 2255 // "pthread_cond_{signal,broadcast}: " 2256 // "no or invalid mutex associated with cond"); 2257 //} 2258 ///* note: lk could be NULL. Be careful. */ 2259 //if (lk) { 2260 // if (lk->kind == LK_rdwr) { 2261 // HG_(record_error_Misc)(thr, 2262 // "pthread_cond_{signal,broadcast}: associated lock is a rwlock"); 2263 // } 2264 // if (lk->heldBy == NULL) { 2265 // HG_(record_error_Misc)(thr, 2266 // "pthread_cond_{signal,broadcast}: " 2267 // "associated lock is not held by any thread"); 2268 // } 2269 // if (lk->heldBy != NULL && 0 == VG_(elemBag)(lk->heldBy, (Word)thr)) { 2270 // HG_(record_error_Misc)(thr, 2271 // "pthread_cond_{signal,broadcast}: " 2272 // "associated lock is not held by calling thread"); 2273 // } 2274 //} 2275 2276 libhb_so_send( thr->hbthr, cvi->so, True/*strong_send*/ ); 2277 } 2278 2279 /* returns True if it reckons 'mutex' is valid and held by this 2280 thread, else False */ 2281 static Bool evh__HG_PTHREAD_COND_WAIT_PRE ( ThreadId tid, 2282 void* cond, void* mutex ) 2283 { 2284 Thread* thr; 2285 Lock* lk; 2286 Bool lk_valid = True; 2287 CVInfo* cvi; 2288 2289 if (SHOW_EVENTS >= 1) 2290 VG_(printf)("evh__hg_PTHREAD_COND_WAIT_PRE" 2291 "(ctid=%d, cond=%p, mutex=%p)\n", 2292 (Int)tid, (void*)cond, (void*)mutex ); 2293 2294 thr = map_threads_maybe_lookup( tid ); 2295 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2296 2297 lk = map_locks_maybe_lookup( (Addr)mutex ); 2298 2299 /* Check for stupid mutex arguments. There are various ways to be 2300 a bozo. Only complain once, though, even if more than one thing 2301 is wrong. */ 2302 if (lk == NULL) { 2303 lk_valid = False; 2304 HG_(record_error_Misc)( 2305 thr, 2306 "pthread_cond_{timed}wait called with invalid mutex" ); 2307 } else { 2308 tl_assert( HG_(is_sane_LockN)(lk) ); 2309 if (lk->kind == LK_rdwr) { 2310 lk_valid = False; 2311 HG_(record_error_Misc)( 2312 thr, "pthread_cond_{timed}wait called with mutex " 2313 "of type pthread_rwlock_t*" ); 2314 } else 2315 if (lk->heldBy == NULL) { 2316 lk_valid = False; 2317 HG_(record_error_Misc)( 2318 thr, "pthread_cond_{timed}wait called with un-held mutex"); 2319 } else 2320 if (lk->heldBy != NULL 2321 && VG_(elemBag)( lk->heldBy, (Word)thr ) == 0) { 2322 lk_valid = False; 2323 HG_(record_error_Misc)( 2324 thr, "pthread_cond_{timed}wait called with mutex " 2325 "held by a different thread" ); 2326 } 2327 } 2328 2329 // error-if: cond is also associated with a different mutex 2330 cvi = map_cond_to_CVInfo_lookup_or_alloc(cond); 2331 tl_assert(cvi); 2332 tl_assert(cvi->so); 2333 if (cvi->nWaiters == 0) { 2334 /* form initial (CV,MX) binding */ 2335 cvi->mx_ga = mutex; 2336 } 2337 else /* check existing (CV,MX) binding */ 2338 if (cvi->mx_ga != mutex) { 2339 HG_(record_error_Misc)( 2340 thr, "pthread_cond_{timed}wait: cond is associated " 2341 "with a different mutex"); 2342 } 2343 cvi->nWaiters++; 2344 2345 return lk_valid; 2346 } 2347 2348 static void evh__HG_PTHREAD_COND_WAIT_POST ( ThreadId tid, 2349 void* cond, void* mutex ) 2350 { 2351 /* A pthread_cond_wait(cond, mutex) completed successfully. Find 2352 the SO for this cond, and 'recv' from it so as to acquire a 2353 dependency edge back to the signaller/broadcaster. */ 2354 Thread* thr; 2355 CVInfo* cvi; 2356 2357 if (SHOW_EVENTS >= 1) 2358 VG_(printf)("evh__HG_PTHREAD_COND_WAIT_POST" 2359 "(ctid=%d, cond=%p, mutex=%p)\n", 2360 (Int)tid, (void*)cond, (void*)mutex ); 2361 2362 thr = map_threads_maybe_lookup( tid ); 2363 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2364 2365 // error-if: cond is also associated with a different mutex 2366 2367 cvi = map_cond_to_CVInfo_lookup_or_alloc( cond ); 2368 tl_assert(cvi); 2369 tl_assert(cvi->so); 2370 tl_assert(cvi->nWaiters > 0); 2371 2372 if (!libhb_so_everSent(cvi->so)) { 2373 /* Hmm. How can a wait on 'cond' succeed if nobody signalled 2374 it? If this happened it would surely be a bug in the threads 2375 library. Or one of those fabled "spurious wakeups". */ 2376 HG_(record_error_Misc)( thr, "Bug in libpthread: pthread_cond_wait " 2377 "succeeded on" 2378 " without prior pthread_cond_post"); 2379 } 2380 2381 /* anyway, acquire a dependency on it. */ 2382 libhb_so_recv( thr->hbthr, cvi->so, True/*strong_recv*/ ); 2383 2384 cvi->nWaiters--; 2385 } 2386 2387 static void evh__HG_PTHREAD_COND_DESTROY_PRE ( ThreadId tid, 2388 void* cond ) 2389 { 2390 /* Deal with destroy events. The only purpose is to free storage 2391 associated with the CV, so as to avoid any possible resource 2392 leaks. */ 2393 if (SHOW_EVENTS >= 1) 2394 VG_(printf)("evh__HG_PTHREAD_COND_DESTROY_PRE" 2395 "(ctid=%d, cond=%p)\n", 2396 (Int)tid, (void*)cond ); 2397 2398 map_cond_to_CVInfo_delete( cond ); 2399 } 2400 2401 2402 /* ------------------------------------------------------- */ 2403 /* -------------- events to do with rwlocks -------------- */ 2404 /* ------------------------------------------------------- */ 2405 2406 /* EXPOSITION only */ 2407 static 2408 void evh__HG_PTHREAD_RWLOCK_INIT_POST( ThreadId tid, void* rwl ) 2409 { 2410 if (SHOW_EVENTS >= 1) 2411 VG_(printf)("evh__hg_PTHREAD_RWLOCK_INIT_POST(ctid=%d, %p)\n", 2412 (Int)tid, (void*)rwl ); 2413 map_locks_lookup_or_create( LK_rdwr, (Addr)rwl, tid ); 2414 if (HG_(clo_sanity_flags) & SCE_LOCKS) 2415 all__sanity_check("evh__hg_PTHREAD_RWLOCK_INIT_POST"); 2416 } 2417 2418 static 2419 void evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( ThreadId tid, void* rwl ) 2420 { 2421 Thread* thr; 2422 Lock* lk; 2423 if (SHOW_EVENTS >= 1) 2424 VG_(printf)("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE(ctid=%d, %p)\n", 2425 (Int)tid, (void*)rwl ); 2426 2427 thr = map_threads_maybe_lookup( tid ); 2428 /* cannot fail - Thread* must already exist */ 2429 tl_assert( HG_(is_sane_Thread)(thr) ); 2430 2431 lk = map_locks_maybe_lookup( (Addr)rwl ); 2432 2433 if (lk == NULL || lk->kind != LK_rdwr) { 2434 HG_(record_error_Misc)( 2435 thr, "pthread_rwlock_destroy with invalid argument" ); 2436 } 2437 2438 if (lk) { 2439 tl_assert( HG_(is_sane_LockN)(lk) ); 2440 tl_assert( lk->guestaddr == (Addr)rwl ); 2441 if (lk->heldBy) { 2442 /* Basically act like we unlocked the lock */ 2443 HG_(record_error_Misc)( 2444 thr, "pthread_rwlock_destroy of a locked mutex" ); 2445 /* remove lock from locksets of all owning threads */ 2446 remove_Lock_from_locksets_of_all_owning_Threads( lk ); 2447 VG_(deleteBag)( lk->heldBy ); 2448 lk->heldBy = NULL; 2449 lk->heldW = False; 2450 lk->acquired_at = NULL; 2451 } 2452 tl_assert( !lk->heldBy ); 2453 tl_assert( HG_(is_sane_LockN)(lk) ); 2454 2455 laog__handle_one_lock_deletion(lk); 2456 map_locks_delete( lk->guestaddr ); 2457 del_LockN( lk ); 2458 } 2459 2460 if (HG_(clo_sanity_flags) & SCE_LOCKS) 2461 all__sanity_check("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE"); 2462 } 2463 2464 static 2465 void evh__HG_PTHREAD_RWLOCK_LOCK_PRE ( ThreadId tid, 2466 void* rwl, 2467 Word isW, Word isTryLock ) 2468 { 2469 /* Just check the rwl is sane; nothing else to do. */ 2470 // 'rwl' may be invalid - not checked by wrapper 2471 Thread* thr; 2472 Lock* lk; 2473 if (SHOW_EVENTS >= 1) 2474 VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_PRE(ctid=%d, isW=%d, %p)\n", 2475 (Int)tid, (Int)isW, (void*)rwl ); 2476 2477 tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */ 2478 tl_assert(isTryLock == 0 || isTryLock == 1); /* assured us by wrapper */ 2479 thr = map_threads_maybe_lookup( tid ); 2480 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2481 2482 lk = map_locks_maybe_lookup( (Addr)rwl ); 2483 if ( lk 2484 && (lk->kind == LK_nonRec || lk->kind == LK_mbRec) ) { 2485 /* Wrong kind of lock. Duh. */ 2486 HG_(record_error_Misc)( 2487 thr, "pthread_rwlock_{rd,rw}lock with a " 2488 "pthread_mutex_t* argument " ); 2489 } 2490 } 2491 2492 static 2493 void evh__HG_PTHREAD_RWLOCK_LOCK_POST ( ThreadId tid, void* rwl, Word isW ) 2494 { 2495 // only called if the real library call succeeded - so mutex is sane 2496 Thread* thr; 2497 if (SHOW_EVENTS >= 1) 2498 VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_POST(ctid=%d, isW=%d, %p)\n", 2499 (Int)tid, (Int)isW, (void*)rwl ); 2500 2501 tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */ 2502 thr = map_threads_maybe_lookup( tid ); 2503 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2504 2505 (isW ? evhH__post_thread_w_acquires_lock 2506 : evhH__post_thread_r_acquires_lock)( 2507 thr, 2508 LK_rdwr, /* if not known, create new lock with this LockKind */ 2509 (Addr)rwl 2510 ); 2511 } 2512 2513 static void evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE ( ThreadId tid, void* rwl ) 2514 { 2515 // 'rwl' may be invalid - not checked by wrapper 2516 Thread* thr; 2517 if (SHOW_EVENTS >= 1) 2518 VG_(printf)("evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE(ctid=%d, rwl=%p)\n", 2519 (Int)tid, (void*)rwl ); 2520 2521 thr = map_threads_maybe_lookup( tid ); 2522 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2523 2524 evhH__pre_thread_releases_lock( thr, (Addr)rwl, True/*isRDWR*/ ); 2525 } 2526 2527 static void evh__HG_PTHREAD_RWLOCK_UNLOCK_POST ( ThreadId tid, void* rwl ) 2528 { 2529 // only called if the real library call succeeded - so mutex is sane 2530 Thread* thr; 2531 if (SHOW_EVENTS >= 1) 2532 VG_(printf)("evh__hg_PTHREAD_RWLOCK_UNLOCK_POST(ctid=%d, rwl=%p)\n", 2533 (Int)tid, (void*)rwl ); 2534 thr = map_threads_maybe_lookup( tid ); 2535 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2536 2537 // anything we should do here? 2538 } 2539 2540 2541 /* ---------------------------------------------------------- */ 2542 /* -------------- events to do with semaphores -------------- */ 2543 /* ---------------------------------------------------------- */ 2544 2545 /* This is similar to but not identical to the handling for condition 2546 variables. */ 2547 2548 /* For each semaphore, we maintain a stack of SOs. When a 'post' 2549 operation is done on a semaphore (unlocking, essentially), a new SO 2550 is created for the posting thread, the posting thread does a strong 2551 send to it (which merely installs the posting thread's VC in the 2552 SO), and the SO is pushed on the semaphore's stack. 2553 2554 Later, when a (probably different) thread completes 'wait' on the 2555 semaphore, we pop a SO off the semaphore's stack (which should be 2556 nonempty), and do a strong recv from it. This mechanism creates 2557 dependencies between posters and waiters of the semaphore. 2558 2559 It may not be necessary to use a stack - perhaps a bag of SOs would 2560 do. But we do need to keep track of how many unused-up posts have 2561 happened for the semaphore. 2562 2563 Imagine T1 and T2 both post once on a semaphore S, and T3 waits 2564 twice on S. T3 cannot complete its waits without both T1 and T2 2565 posting. The above mechanism will ensure that T3 acquires 2566 dependencies on both T1 and T2. 2567 2568 When a semaphore is initialised with value N, we do as if we'd 2569 posted N times on the semaphore: basically create N SOs and do a 2570 strong send to all of then. This allows up to N waits on the 2571 semaphore to acquire a dependency on the initialisation point, 2572 which AFAICS is the correct behaviour. 2573 2574 We don't emit an error for DESTROY_PRE on a semaphore we don't know 2575 about. We should. 2576 */ 2577 2578 /* sem_t* -> XArray* SO* */ 2579 static WordFM* map_sem_to_SO_stack = NULL; 2580 2581 static void map_sem_to_SO_stack_INIT ( void ) { 2582 if (map_sem_to_SO_stack == NULL) { 2583 map_sem_to_SO_stack = VG_(newFM)( HG_(zalloc), "hg.mstSs.1", 2584 HG_(free), NULL ); 2585 tl_assert(map_sem_to_SO_stack != NULL); 2586 } 2587 } 2588 2589 static void push_SO_for_sem ( void* sem, SO* so ) { 2590 UWord keyW; 2591 XArray* xa; 2592 tl_assert(so); 2593 map_sem_to_SO_stack_INIT(); 2594 if (VG_(lookupFM)( map_sem_to_SO_stack, 2595 &keyW, (UWord*)&xa, (UWord)sem )) { 2596 tl_assert(keyW == (UWord)sem); 2597 tl_assert(xa); 2598 VG_(addToXA)( xa, &so ); 2599 } else { 2600 xa = VG_(newXA)( HG_(zalloc), "hg.pSfs.1", HG_(free), sizeof(SO*) ); 2601 VG_(addToXA)( xa, &so ); 2602 VG_(addToFM)( map_sem_to_SO_stack, (Word)sem, (Word)xa ); 2603 } 2604 } 2605 2606 static SO* mb_pop_SO_for_sem ( void* sem ) { 2607 UWord keyW; 2608 XArray* xa; 2609 SO* so; 2610 map_sem_to_SO_stack_INIT(); 2611 if (VG_(lookupFM)( map_sem_to_SO_stack, 2612 &keyW, (UWord*)&xa, (UWord)sem )) { 2613 /* xa is the stack for this semaphore. */ 2614 Word sz; 2615 tl_assert(keyW == (UWord)sem); 2616 sz = VG_(sizeXA)( xa ); 2617 tl_assert(sz >= 0); 2618 if (sz == 0) 2619 return NULL; /* odd, the stack is empty */ 2620 so = *(SO**)VG_(indexXA)( xa, sz-1 ); 2621 tl_assert(so); 2622 VG_(dropTailXA)( xa, 1 ); 2623 return so; 2624 } else { 2625 /* hmm, that's odd. No stack for this semaphore. */ 2626 return NULL; 2627 } 2628 } 2629 2630 static void evh__HG_POSIX_SEM_DESTROY_PRE ( ThreadId tid, void* sem ) 2631 { 2632 UWord keyW, valW; 2633 SO* so; 2634 2635 if (SHOW_EVENTS >= 1) 2636 VG_(printf)("evh__HG_POSIX_SEM_DESTROY_PRE(ctid=%d, sem=%p)\n", 2637 (Int)tid, (void*)sem ); 2638 2639 map_sem_to_SO_stack_INIT(); 2640 2641 /* Empty out the semaphore's SO stack. This way of doing it is 2642 stupid, but at least it's easy. */ 2643 while (1) { 2644 so = mb_pop_SO_for_sem( sem ); 2645 if (!so) break; 2646 libhb_so_dealloc(so); 2647 } 2648 2649 if (VG_(delFromFM)( map_sem_to_SO_stack, &keyW, &valW, (UWord)sem )) { 2650 XArray* xa = (XArray*)valW; 2651 tl_assert(keyW == (UWord)sem); 2652 tl_assert(xa); 2653 tl_assert(VG_(sizeXA)(xa) == 0); /* preceding loop just emptied it */ 2654 VG_(deleteXA)(xa); 2655 } 2656 } 2657 2658 static 2659 void evh__HG_POSIX_SEM_INIT_POST ( ThreadId tid, void* sem, UWord value ) 2660 { 2661 SO* so; 2662 Thread* thr; 2663 2664 if (SHOW_EVENTS >= 1) 2665 VG_(printf)("evh__HG_POSIX_SEM_INIT_POST(ctid=%d, sem=%p, value=%lu)\n", 2666 (Int)tid, (void*)sem, value ); 2667 2668 thr = map_threads_maybe_lookup( tid ); 2669 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2670 2671 /* Empty out the semaphore's SO stack. This way of doing it is 2672 stupid, but at least it's easy. */ 2673 while (1) { 2674 so = mb_pop_SO_for_sem( sem ); 2675 if (!so) break; 2676 libhb_so_dealloc(so); 2677 } 2678 2679 /* If we don't do this check, the following while loop runs us out 2680 of memory for stupid initial values of 'value'. */ 2681 if (value > 10000) { 2682 HG_(record_error_Misc)( 2683 thr, "sem_init: initial value exceeds 10000; using 10000" ); 2684 value = 10000; 2685 } 2686 2687 /* Now create 'valid' new SOs for the thread, do a strong send to 2688 each of them, and push them all on the stack. */ 2689 for (; value > 0; value--) { 2690 Thr* hbthr = thr->hbthr; 2691 tl_assert(hbthr); 2692 2693 so = libhb_so_alloc(); 2694 libhb_so_send( hbthr, so, True/*strong send*/ ); 2695 push_SO_for_sem( sem, so ); 2696 } 2697 } 2698 2699 static void evh__HG_POSIX_SEM_POST_PRE ( ThreadId tid, void* sem ) 2700 { 2701 /* 'tid' has posted on 'sem'. Create a new SO, do a strong send to 2702 it (iow, write our VC into it, then tick ours), and push the SO 2703 on on a stack of SOs associated with 'sem'. This is later used 2704 by other thread(s) which successfully exit from a sem_wait on 2705 the same sem; by doing a strong recv from SOs popped of the 2706 stack, they acquire dependencies on the posting thread 2707 segment(s). */ 2708 2709 Thread* thr; 2710 SO* so; 2711 Thr* hbthr; 2712 2713 if (SHOW_EVENTS >= 1) 2714 VG_(printf)("evh__HG_POSIX_SEM_POST_PRE(ctid=%d, sem=%p)\n", 2715 (Int)tid, (void*)sem ); 2716 2717 thr = map_threads_maybe_lookup( tid ); 2718 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2719 2720 // error-if: sem is bogus 2721 2722 hbthr = thr->hbthr; 2723 tl_assert(hbthr); 2724 2725 so = libhb_so_alloc(); 2726 libhb_so_send( hbthr, so, True/*strong send*/ ); 2727 push_SO_for_sem( sem, so ); 2728 } 2729 2730 static void evh__HG_POSIX_SEM_WAIT_POST ( ThreadId tid, void* sem ) 2731 { 2732 /* A sem_wait(sem) completed successfully. Pop the posting-SO for 2733 the 'sem' from this semaphore's SO-stack, and do a strong recv 2734 from it. This creates a dependency back to one of the post-ers 2735 for the semaphore. */ 2736 2737 Thread* thr; 2738 SO* so; 2739 Thr* hbthr; 2740 2741 if (SHOW_EVENTS >= 1) 2742 VG_(printf)("evh__HG_POSIX_SEM_WAIT_POST(ctid=%d, sem=%p)\n", 2743 (Int)tid, (void*)sem ); 2744 2745 thr = map_threads_maybe_lookup( tid ); 2746 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2747 2748 // error-if: sem is bogus 2749 2750 so = mb_pop_SO_for_sem( sem ); 2751 2752 if (so) { 2753 hbthr = thr->hbthr; 2754 tl_assert(hbthr); 2755 2756 libhb_so_recv( hbthr, so, True/*strong recv*/ ); 2757 libhb_so_dealloc(so); 2758 } else { 2759 /* Hmm. How can a wait on 'sem' succeed if nobody posted to it? 2760 If this happened it would surely be a bug in the threads 2761 library. */ 2762 HG_(record_error_Misc)( 2763 thr, "Bug in libpthread: sem_wait succeeded on" 2764 " semaphore without prior sem_post"); 2765 } 2766 } 2767 2768 2769 /* -------------------------------------------------------- */ 2770 /* -------------- events to do with barriers -------------- */ 2771 /* -------------------------------------------------------- */ 2772 2773 typedef 2774 struct { 2775 Bool initted; /* has it yet been initted by guest? */ 2776 Bool resizable; /* is resizing allowed? */ 2777 UWord size; /* declared size */ 2778 XArray* waiting; /* XA of Thread*. # present is 0 .. .size */ 2779 } 2780 Bar; 2781 2782 static Bar* new_Bar ( void ) { 2783 Bar* bar = HG_(zalloc)( "hg.nB.1 (new_Bar)", sizeof(Bar) ); 2784 tl_assert(bar); 2785 /* all fields are zero */ 2786 tl_assert(bar->initted == False); 2787 return bar; 2788 } 2789 2790 static void delete_Bar ( Bar* bar ) { 2791 tl_assert(bar); 2792 if (bar->waiting) 2793 VG_(deleteXA)(bar->waiting); 2794 HG_(free)(bar); 2795 } 2796 2797 /* A mapping which stores auxiliary data for barriers. */ 2798 2799 /* pthread_barrier_t* -> Bar* */ 2800 static WordFM* map_barrier_to_Bar = NULL; 2801 2802 static void map_barrier_to_Bar_INIT ( void ) { 2803 if (UNLIKELY(map_barrier_to_Bar == NULL)) { 2804 map_barrier_to_Bar = VG_(newFM)( HG_(zalloc), 2805 "hg.mbtBI.1", HG_(free), NULL ); 2806 tl_assert(map_barrier_to_Bar != NULL); 2807 } 2808 } 2809 2810 static Bar* map_barrier_to_Bar_lookup_or_alloc ( void* barrier ) { 2811 UWord key, val; 2812 map_barrier_to_Bar_INIT(); 2813 if (VG_(lookupFM)( map_barrier_to_Bar, &key, &val, (UWord)barrier )) { 2814 tl_assert(key == (UWord)barrier); 2815 return (Bar*)val; 2816 } else { 2817 Bar* bar = new_Bar(); 2818 VG_(addToFM)( map_barrier_to_Bar, (UWord)barrier, (UWord)bar ); 2819 return bar; 2820 } 2821 } 2822 2823 static void map_barrier_to_Bar_delete ( void* barrier ) { 2824 UWord keyW, valW; 2825 map_barrier_to_Bar_INIT(); 2826 if (VG_(delFromFM)( map_barrier_to_Bar, &keyW, &valW, (UWord)barrier )) { 2827 Bar* bar = (Bar*)valW; 2828 tl_assert(keyW == (UWord)barrier); 2829 delete_Bar(bar); 2830 } 2831 } 2832 2833 2834 static void evh__HG_PTHREAD_BARRIER_INIT_PRE ( ThreadId tid, 2835 void* barrier, 2836 UWord count, 2837 UWord resizable ) 2838 { 2839 Thread* thr; 2840 Bar* bar; 2841 2842 if (SHOW_EVENTS >= 1) 2843 VG_(printf)("evh__HG_PTHREAD_BARRIER_INIT_PRE" 2844 "(tid=%d, barrier=%p, count=%lu, resizable=%lu)\n", 2845 (Int)tid, (void*)barrier, count, resizable ); 2846 2847 thr = map_threads_maybe_lookup( tid ); 2848 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2849 2850 if (count == 0) { 2851 HG_(record_error_Misc)( 2852 thr, "pthread_barrier_init: 'count' argument is zero" 2853 ); 2854 } 2855 2856 if (resizable != 0 && resizable != 1) { 2857 HG_(record_error_Misc)( 2858 thr, "pthread_barrier_init: invalid 'resizable' argument" 2859 ); 2860 } 2861 2862 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 2863 tl_assert(bar); 2864 2865 if (bar->initted) { 2866 HG_(record_error_Misc)( 2867 thr, "pthread_barrier_init: barrier is already initialised" 2868 ); 2869 } 2870 2871 if (bar->waiting && VG_(sizeXA)(bar->waiting) > 0) { 2872 tl_assert(bar->initted); 2873 HG_(record_error_Misc)( 2874 thr, "pthread_barrier_init: threads are waiting at barrier" 2875 ); 2876 VG_(dropTailXA)(bar->waiting, VG_(sizeXA)(bar->waiting)); 2877 } 2878 if (!bar->waiting) { 2879 bar->waiting = VG_(newXA)( HG_(zalloc), "hg.eHPBIP.1", HG_(free), 2880 sizeof(Thread*) ); 2881 } 2882 2883 tl_assert(bar->waiting); 2884 tl_assert(VG_(sizeXA)(bar->waiting) == 0); 2885 bar->initted = True; 2886 bar->resizable = resizable == 1 ? True : False; 2887 bar->size = count; 2888 } 2889 2890 2891 static void evh__HG_PTHREAD_BARRIER_DESTROY_PRE ( ThreadId tid, 2892 void* barrier ) 2893 { 2894 Thread* thr; 2895 Bar* bar; 2896 2897 /* Deal with destroy events. The only purpose is to free storage 2898 associated with the barrier, so as to avoid any possible 2899 resource leaks. */ 2900 if (SHOW_EVENTS >= 1) 2901 VG_(printf)("evh__HG_PTHREAD_BARRIER_DESTROY_PRE" 2902 "(tid=%d, barrier=%p)\n", 2903 (Int)tid, (void*)barrier ); 2904 2905 thr = map_threads_maybe_lookup( tid ); 2906 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2907 2908 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 2909 tl_assert(bar); 2910 2911 if (!bar->initted) { 2912 HG_(record_error_Misc)( 2913 thr, "pthread_barrier_destroy: barrier was never initialised" 2914 ); 2915 } 2916 2917 if (bar->initted && bar->waiting && VG_(sizeXA)(bar->waiting) > 0) { 2918 HG_(record_error_Misc)( 2919 thr, "pthread_barrier_destroy: threads are waiting at barrier" 2920 ); 2921 } 2922 2923 /* Maybe we shouldn't do this; just let it persist, so that when it 2924 is reinitialised we don't need to do any dynamic memory 2925 allocation? The downside is a potentially unlimited space leak, 2926 if the client creates (in turn) a large number of barriers all 2927 at different locations. Note that if we do later move to the 2928 don't-delete-it scheme, we need to mark the barrier as 2929 uninitialised again since otherwise a later _init call will 2930 elicit a duplicate-init error. */ 2931 map_barrier_to_Bar_delete( barrier ); 2932 } 2933 2934 2935 /* All the threads have arrived. Now do the Interesting Bit. Get a 2936 new synchronisation object and do a weak send to it from all the 2937 participating threads. This makes its vector clocks be the join of 2938 all the individual threads' vector clocks. Then do a strong 2939 receive from it back to all threads, so that their VCs are a copy 2940 of it (hence are all equal to the join of their original VCs.) */ 2941 static void do_barrier_cross_sync_and_empty ( Bar* bar ) 2942 { 2943 /* XXX check bar->waiting has no duplicates */ 2944 UWord i; 2945 SO* so = libhb_so_alloc(); 2946 2947 tl_assert(bar->waiting); 2948 tl_assert(VG_(sizeXA)(bar->waiting) == bar->size); 2949 2950 /* compute the join ... */ 2951 for (i = 0; i < bar->size; i++) { 2952 Thread* t = *(Thread**)VG_(indexXA)(bar->waiting, i); 2953 Thr* hbthr = t->hbthr; 2954 libhb_so_send( hbthr, so, False/*weak send*/ ); 2955 } 2956 /* ... and distribute to all threads */ 2957 for (i = 0; i < bar->size; i++) { 2958 Thread* t = *(Thread**)VG_(indexXA)(bar->waiting, i); 2959 Thr* hbthr = t->hbthr; 2960 libhb_so_recv( hbthr, so, True/*strong recv*/ ); 2961 } 2962 2963 /* finally, we must empty out the waiting vector */ 2964 VG_(dropTailXA)(bar->waiting, VG_(sizeXA)(bar->waiting)); 2965 2966 /* and we don't need this any more. Perhaps a stack-allocated 2967 SO would be better? */ 2968 libhb_so_dealloc(so); 2969 } 2970 2971 2972 static void evh__HG_PTHREAD_BARRIER_WAIT_PRE ( ThreadId tid, 2973 void* barrier ) 2974 { 2975 /* This function gets called after a client thread calls 2976 pthread_barrier_wait but before it arrives at the real 2977 pthread_barrier_wait. 2978 2979 Why is the following correct? It's a bit subtle. 2980 2981 If this is not the last thread arriving at the barrier, we simply 2982 note its presence and return. Because valgrind (at least as of 2983 Nov 08) is single threaded, we are guaranteed safe from any race 2984 conditions when in this function -- no other client threads are 2985 running. 2986 2987 If this is the last thread, then we are again the only running 2988 thread. All the other threads will have either arrived at the 2989 real pthread_barrier_wait or are on their way to it, but in any 2990 case are guaranteed not to be able to move past it, because this 2991 thread is currently in this function and so has not yet arrived 2992 at the real pthread_barrier_wait. That means that: 2993 2994 1. While we are in this function, none of the other threads 2995 waiting at the barrier can move past it. 2996 2997 2. When this function returns (and simulated execution resumes), 2998 this thread and all other waiting threads will be able to move 2999 past the real barrier. 3000 3001 Because of this, it is now safe to update the vector clocks of 3002 all threads, to represent the fact that they all arrived at the 3003 barrier and have all moved on. There is no danger of any 3004 complications to do with some threads leaving the barrier and 3005 racing back round to the front, whilst others are still leaving 3006 (which is the primary source of complication in correct handling/ 3007 implementation of barriers). That can't happen because we update 3008 here our data structures so as to indicate that the threads have 3009 passed the barrier, even though, as per (2) above, they are 3010 guaranteed not to pass the barrier until we return. 3011 3012 This relies crucially on Valgrind being single threaded. If that 3013 changes, this will need to be reconsidered. 3014 */ 3015 Thread* thr; 3016 Bar* bar; 3017 UWord present; 3018 3019 if (SHOW_EVENTS >= 1) 3020 VG_(printf)("evh__HG_PTHREAD_BARRIER_WAIT_PRE" 3021 "(tid=%d, barrier=%p)\n", 3022 (Int)tid, (void*)barrier ); 3023 3024 thr = map_threads_maybe_lookup( tid ); 3025 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3026 3027 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 3028 tl_assert(bar); 3029 3030 if (!bar->initted) { 3031 HG_(record_error_Misc)( 3032 thr, "pthread_barrier_wait: barrier is uninitialised" 3033 ); 3034 return; /* client is broken .. avoid assertions below */ 3035 } 3036 3037 /* guaranteed by _INIT_PRE above */ 3038 tl_assert(bar->size > 0); 3039 tl_assert(bar->waiting); 3040 3041 VG_(addToXA)( bar->waiting, &thr ); 3042 3043 /* guaranteed by this function */ 3044 present = VG_(sizeXA)(bar->waiting); 3045 tl_assert(present > 0 && present <= bar->size); 3046 3047 if (present < bar->size) 3048 return; 3049 3050 do_barrier_cross_sync_and_empty(bar); 3051 } 3052 3053 3054 static void evh__HG_PTHREAD_BARRIER_RESIZE_PRE ( ThreadId tid, 3055 void* barrier, 3056 UWord newcount ) 3057 { 3058 Thread* thr; 3059 Bar* bar; 3060 UWord present; 3061 3062 if (SHOW_EVENTS >= 1) 3063 VG_(printf)("evh__HG_PTHREAD_BARRIER_RESIZE_PRE" 3064 "(tid=%d, barrier=%p, newcount=%lu)\n", 3065 (Int)tid, (void*)barrier, newcount ); 3066 3067 thr = map_threads_maybe_lookup( tid ); 3068 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3069 3070 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 3071 tl_assert(bar); 3072 3073 if (!bar->initted) { 3074 HG_(record_error_Misc)( 3075 thr, "pthread_barrier_resize: barrier is uninitialised" 3076 ); 3077 return; /* client is broken .. avoid assertions below */ 3078 } 3079 3080 if (!bar->resizable) { 3081 HG_(record_error_Misc)( 3082 thr, "pthread_barrier_resize: barrier is may not be resized" 3083 ); 3084 return; /* client is broken .. avoid assertions below */ 3085 } 3086 3087 if (newcount == 0) { 3088 HG_(record_error_Misc)( 3089 thr, "pthread_barrier_resize: 'newcount' argument is zero" 3090 ); 3091 return; /* client is broken .. avoid assertions below */ 3092 } 3093 3094 /* guaranteed by _INIT_PRE above */ 3095 tl_assert(bar->size > 0); 3096 tl_assert(bar->waiting); 3097 /* Guaranteed by this fn */ 3098 tl_assert(newcount > 0); 3099 3100 if (newcount >= bar->size) { 3101 /* Increasing the capacity. There's no possibility of threads 3102 moving on from the barrier in this situation, so just note 3103 the fact and do nothing more. */ 3104 bar->size = newcount; 3105 } else { 3106 /* Decreasing the capacity. If we decrease it to be equal or 3107 below the number of waiting threads, they will now move past 3108 the barrier, so need to mess with dep edges in the same way 3109 as if the barrier had filled up normally. */ 3110 present = VG_(sizeXA)(bar->waiting); 3111 tl_assert(present >= 0 && present <= bar->size); 3112 if (newcount <= present) { 3113 bar->size = present; /* keep the cross_sync call happy */ 3114 do_barrier_cross_sync_and_empty(bar); 3115 } 3116 bar->size = newcount; 3117 } 3118 } 3119 3120 3121 /* ----------------------------------------------------- */ 3122 /* ----- events to do with user-specified HB edges ----- */ 3123 /* ----------------------------------------------------- */ 3124 3125 /* A mapping from arbitrary UWord tag to the SO associated with it. 3126 The UWord tags are meaningless to us, interpreted only by the 3127 user. */ 3128 3129 3130 3131 /* UWord -> SO* */ 3132 static WordFM* map_usertag_to_SO = NULL; 3133 3134 static void map_usertag_to_SO_INIT ( void ) { 3135 if (UNLIKELY(map_usertag_to_SO == NULL)) { 3136 map_usertag_to_SO = VG_(newFM)( HG_(zalloc), 3137 "hg.mutS.1", HG_(free), NULL ); 3138 tl_assert(map_usertag_to_SO != NULL); 3139 } 3140 } 3141 3142 static SO* map_usertag_to_SO_lookup_or_alloc ( UWord usertag ) { 3143 UWord key, val; 3144 map_usertag_to_SO_INIT(); 3145 if (VG_(lookupFM)( map_usertag_to_SO, &key, &val, usertag )) { 3146 tl_assert(key == (UWord)usertag); 3147 return (SO*)val; 3148 } else { 3149 SO* so = libhb_so_alloc(); 3150 VG_(addToFM)( map_usertag_to_SO, usertag, (UWord)so ); 3151 return so; 3152 } 3153 } 3154 3155 // If it's ever needed (XXX check before use) 3156 //static void map_usertag_to_SO_delete ( UWord usertag ) { 3157 // UWord keyW, valW; 3158 // map_usertag_to_SO_INIT(); 3159 // if (VG_(delFromFM)( map_usertag_to_SO, &keyW, &valW, usertag )) { 3160 // SO* so = (SO*)valW; 3161 // tl_assert(keyW == usertag); 3162 // tl_assert(so); 3163 // libhb_so_dealloc(so); 3164 // } 3165 //} 3166 3167 3168 static 3169 void evh__HG_USERSO_SEND_PRE ( ThreadId tid, UWord usertag ) 3170 { 3171 /* TID is just about to notionally sent a message on a notional 3172 abstract synchronisation object whose identity is given by 3173 USERTAG. Bind USERTAG to a real SO if it is not already so 3174 bound, and do a 'strong send' on the SO. This is later used by 3175 other thread(s) which successfully 'receive' from the SO, 3176 thereby acquiring a dependency on this signalling event. */ 3177 Thread* thr; 3178 SO* so; 3179 3180 if (SHOW_EVENTS >= 1) 3181 VG_(printf)("evh__HG_USERSO_SEND_PRE(ctid=%d, usertag=%#lx)\n", 3182 (Int)tid, usertag ); 3183 3184 thr = map_threads_maybe_lookup( tid ); 3185 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3186 3187 so = map_usertag_to_SO_lookup_or_alloc( usertag ); 3188 tl_assert(so); 3189 3190 libhb_so_send( thr->hbthr, so, True/*strong_send*/ ); 3191 } 3192 3193 static 3194 void evh__HG_USERSO_RECV_POST ( ThreadId tid, UWord usertag ) 3195 { 3196 /* TID has just notionally received a message from a notional 3197 abstract synchronisation object whose identity is given by 3198 USERTAG. Bind USERTAG to a real SO if it is not already so 3199 bound. If the SO has at some point in the past been 'sent' on, 3200 to a 'strong receive' on it, thereby acquiring a dependency on 3201 the sender. */ 3202 Thread* thr; 3203 SO* so; 3204 3205 if (SHOW_EVENTS >= 1) 3206 VG_(printf)("evh__HG_USERSO_RECV_POST(ctid=%d, usertag=%#lx)\n", 3207 (Int)tid, usertag ); 3208 3209 thr = map_threads_maybe_lookup( tid ); 3210 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3211 3212 so = map_usertag_to_SO_lookup_or_alloc( usertag ); 3213 tl_assert(so); 3214 3215 /* Acquire a dependency on it. If the SO has never so far been 3216 sent on, then libhb_so_recv will do nothing. So we're safe 3217 regardless of SO's history. */ 3218 libhb_so_recv( thr->hbthr, so, True/*strong_recv*/ ); 3219 } 3220 3221 3222 /*--------------------------------------------------------------*/ 3223 /*--- Lock acquisition order monitoring ---*/ 3224 /*--------------------------------------------------------------*/ 3225 3226 /* FIXME: here are some optimisations still to do in 3227 laog__pre_thread_acquires_lock. 3228 3229 The graph is structured so that if L1 --*--> L2 then L1 must be 3230 acquired before L2. 3231 3232 The common case is that some thread T holds (eg) L1 L2 and L3 and 3233 is repeatedly acquiring and releasing Ln, and there is no ordering 3234 error in what it is doing. Hence it repeatly: 3235 3236 (1) searches laog to see if Ln --*--> {L1,L2,L3}, which always 3237 produces the answer No (because there is no error). 3238 3239 (2) adds edges {L1,L2,L3} --> Ln to laog, which are already present 3240 (because they already got added the first time T acquired Ln). 3241 3242 Hence cache these two events: 3243 3244 (1) Cache result of the query from last time. Invalidate the cache 3245 any time any edges are added to or deleted from laog. 3246 3247 (2) Cache these add-edge requests and ignore them if said edges 3248 have already been added to laog. Invalidate the cache any time 3249 any edges are deleted from laog. 3250 */ 3251 3252 typedef 3253 struct { 3254 WordSetID inns; /* in univ_laog */ 3255 WordSetID outs; /* in univ_laog */ 3256 } 3257 LAOGLinks; 3258 3259 /* lock order acquisition graph */ 3260 static WordFM* laog = NULL; /* WordFM Lock* LAOGLinks* */ 3261 3262 /* EXPOSITION ONLY: for each edge in 'laog', record the two places 3263 where that edge was created, so that we can show the user later if 3264 we need to. */ 3265 typedef 3266 struct { 3267 Addr src_ga; /* Lock guest addresses for */ 3268 Addr dst_ga; /* src/dst of the edge */ 3269 ExeContext* src_ec; /* And corresponding places where that */ 3270 ExeContext* dst_ec; /* ordering was established */ 3271 } 3272 LAOGLinkExposition; 3273 3274 static Word cmp_LAOGLinkExposition ( UWord llx1W, UWord llx2W ) { 3275 /* Compare LAOGLinkExposition*s by (src_ga,dst_ga) field pair. */ 3276 LAOGLinkExposition* llx1 = (LAOGLinkExposition*)llx1W; 3277 LAOGLinkExposition* llx2 = (LAOGLinkExposition*)llx2W; 3278 if (llx1->src_ga < llx2->src_ga) return -1; 3279 if (llx1->src_ga > llx2->src_ga) return 1; 3280 if (llx1->dst_ga < llx2->dst_ga) return -1; 3281 if (llx1->dst_ga > llx2->dst_ga) return 1; 3282 return 0; 3283 } 3284 3285 static WordFM* laog_exposition = NULL; /* WordFM LAOGLinkExposition* NULL */ 3286 /* end EXPOSITION ONLY */ 3287 3288 3289 __attribute__((noinline)) 3290 static void laog__init ( void ) 3291 { 3292 tl_assert(!laog); 3293 tl_assert(!laog_exposition); 3294 3295 laog = VG_(newFM)( HG_(zalloc), "hg.laog__init.1", 3296 HG_(free), NULL/*unboxedcmp*/ ); 3297 3298 laog_exposition = VG_(newFM)( HG_(zalloc), "hg.laog__init.2", HG_(free), 3299 cmp_LAOGLinkExposition ); 3300 tl_assert(laog); 3301 tl_assert(laog_exposition); 3302 } 3303 3304 static void laog__show ( Char* who ) { 3305 Word i, ws_size; 3306 UWord* ws_words; 3307 Lock* me; 3308 LAOGLinks* links; 3309 VG_(printf)("laog (requested by %s) {\n", who); 3310 VG_(initIterFM)( laog ); 3311 me = NULL; 3312 links = NULL; 3313 while (VG_(nextIterFM)( laog, (Word*)&me, 3314 (Word*)&links )) { 3315 tl_assert(me); 3316 tl_assert(links); 3317 VG_(printf)(" node %p:\n", me); 3318 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns ); 3319 for (i = 0; i < ws_size; i++) 3320 VG_(printf)(" inn %#lx\n", ws_words[i] ); 3321 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs ); 3322 for (i = 0; i < ws_size; i++) 3323 VG_(printf)(" out %#lx\n", ws_words[i] ); 3324 me = NULL; 3325 links = NULL; 3326 } 3327 VG_(doneIterFM)( laog ); 3328 VG_(printf)("}\n"); 3329 } 3330 3331 __attribute__((noinline)) 3332 static void laog__add_edge ( Lock* src, Lock* dst ) { 3333 Word keyW; 3334 LAOGLinks* links; 3335 Bool presentF, presentR; 3336 if (0) VG_(printf)("laog__add_edge %p %p\n", src, dst); 3337 3338 /* Take the opportunity to sanity check the graph. Record in 3339 presentF if there is already a src->dst mapping in this node's 3340 forwards links, and presentR if there is already a src->dst 3341 mapping in this node's backwards links. They should agree! 3342 Also, we need to know whether the edge was already present so as 3343 to decide whether or not to update the link details mapping. We 3344 can compute presentF and presentR essentially for free, so may 3345 as well do this always. */ 3346 presentF = presentR = False; 3347 3348 /* Update the out edges for src */ 3349 keyW = 0; 3350 links = NULL; 3351 if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) { 3352 WordSetID outs_new; 3353 tl_assert(links); 3354 tl_assert(keyW == (Word)src); 3355 outs_new = HG_(addToWS)( univ_laog, links->outs, (Word)dst ); 3356 presentF = outs_new == links->outs; 3357 links->outs = outs_new; 3358 } else { 3359 links = HG_(zalloc)("hg.lae.1", sizeof(LAOGLinks)); 3360 links->inns = HG_(emptyWS)( univ_laog ); 3361 links->outs = HG_(singletonWS)( univ_laog, (Word)dst ); 3362 VG_(addToFM)( laog, (Word)src, (Word)links ); 3363 } 3364 /* Update the in edges for dst */ 3365 keyW = 0; 3366 links = NULL; 3367 if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) { 3368 WordSetID inns_new; 3369 tl_assert(links); 3370 tl_assert(keyW == (Word)dst); 3371 inns_new = HG_(addToWS)( univ_laog, links->inns, (Word)src ); 3372 presentR = inns_new == links->inns; 3373 links->inns = inns_new; 3374 } else { 3375 links = HG_(zalloc)("hg.lae.2", sizeof(LAOGLinks)); 3376 links->inns = HG_(singletonWS)( univ_laog, (Word)src ); 3377 links->outs = HG_(emptyWS)( univ_laog ); 3378 VG_(addToFM)( laog, (Word)dst, (Word)links ); 3379 } 3380 3381 tl_assert( (presentF && presentR) || (!presentF && !presentR) ); 3382 3383 if (!presentF && src->acquired_at && dst->acquired_at) { 3384 LAOGLinkExposition expo; 3385 /* If this edge is entering the graph, and we have acquired_at 3386 information for both src and dst, record those acquisition 3387 points. Hence, if there is later a violation of this 3388 ordering, we can show the user the two places in which the 3389 required src-dst ordering was previously established. */ 3390 if (0) VG_(printf)("acquire edge %#lx %#lx\n", 3391 src->guestaddr, dst->guestaddr); 3392 expo.src_ga = src->guestaddr; 3393 expo.dst_ga = dst->guestaddr; 3394 expo.src_ec = NULL; 3395 expo.dst_ec = NULL; 3396 tl_assert(laog_exposition); 3397 if (VG_(lookupFM)( laog_exposition, NULL, NULL, (Word)&expo )) { 3398 /* we already have it; do nothing */ 3399 } else { 3400 LAOGLinkExposition* expo2 = HG_(zalloc)("hg.lae.3", 3401 sizeof(LAOGLinkExposition)); 3402 expo2->src_ga = src->guestaddr; 3403 expo2->dst_ga = dst->guestaddr; 3404 expo2->src_ec = src->acquired_at; 3405 expo2->dst_ec = dst->acquired_at; 3406 VG_(addToFM)( laog_exposition, (Word)expo2, (Word)NULL ); 3407 } 3408 } 3409 } 3410 3411 __attribute__((noinline)) 3412 static void laog__del_edge ( Lock* src, Lock* dst ) { 3413 Word keyW; 3414 LAOGLinks* links; 3415 if (0) VG_(printf)("laog__del_edge %p %p\n", src, dst); 3416 /* Update the out edges for src */ 3417 keyW = 0; 3418 links = NULL; 3419 if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) { 3420 tl_assert(links); 3421 tl_assert(keyW == (Word)src); 3422 links->outs = HG_(delFromWS)( univ_laog, links->outs, (Word)dst ); 3423 } 3424 /* Update the in edges for dst */ 3425 keyW = 0; 3426 links = NULL; 3427 if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) { 3428 tl_assert(links); 3429 tl_assert(keyW == (Word)dst); 3430 links->inns = HG_(delFromWS)( univ_laog, links->inns, (Word)src ); 3431 } 3432 } 3433 3434 __attribute__((noinline)) 3435 static WordSetID /* in univ_laog */ laog__succs ( Lock* lk ) { 3436 Word keyW; 3437 LAOGLinks* links; 3438 keyW = 0; 3439 links = NULL; 3440 if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) { 3441 tl_assert(links); 3442 tl_assert(keyW == (Word)lk); 3443 return links->outs; 3444 } else { 3445 return HG_(emptyWS)( univ_laog ); 3446 } 3447 } 3448 3449 __attribute__((noinline)) 3450 static WordSetID /* in univ_laog */ laog__preds ( Lock* lk ) { 3451 Word keyW; 3452 LAOGLinks* links; 3453 keyW = 0; 3454 links = NULL; 3455 if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) { 3456 tl_assert(links); 3457 tl_assert(keyW == (Word)lk); 3458 return links->inns; 3459 } else { 3460 return HG_(emptyWS)( univ_laog ); 3461 } 3462 } 3463 3464 __attribute__((noinline)) 3465 static void laog__sanity_check ( Char* who ) { 3466 Word i, ws_size; 3467 UWord* ws_words; 3468 Lock* me; 3469 LAOGLinks* links; 3470 if (UNLIKELY(!laog || !laog_exposition)) 3471 laog__init(); 3472 VG_(initIterFM)( laog ); 3473 me = NULL; 3474 links = NULL; 3475 if (0) VG_(printf)("laog sanity check\n"); 3476 while (VG_(nextIterFM)( laog, (Word*)&me, 3477 (Word*)&links )) { 3478 tl_assert(me); 3479 tl_assert(links); 3480 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns ); 3481 for (i = 0; i < ws_size; i++) { 3482 if ( ! HG_(elemWS)( univ_laog, 3483 laog__succs( (Lock*)ws_words[i] ), 3484 (Word)me )) 3485 goto bad; 3486 } 3487 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs ); 3488 for (i = 0; i < ws_size; i++) { 3489 if ( ! HG_(elemWS)( univ_laog, 3490 laog__preds( (Lock*)ws_words[i] ), 3491 (Word)me )) 3492 goto bad; 3493 } 3494 me = NULL; 3495 links = NULL; 3496 } 3497 VG_(doneIterFM)( laog ); 3498 return; 3499 3500 bad: 3501 VG_(printf)("laog__sanity_check(%s) FAILED\n", who); 3502 laog__show(who); 3503 tl_assert(0); 3504 } 3505 3506 /* If there is a path in laog from 'src' to any of the elements in 3507 'dst', return an arbitrarily chosen element of 'dst' reachable from 3508 'src'. If no path exist from 'src' to any element in 'dst', return 3509 NULL. */ 3510 __attribute__((noinline)) 3511 static 3512 Lock* laog__do_dfs_from_to ( Lock* src, WordSetID dsts /* univ_lsets */ ) 3513 { 3514 Lock* ret; 3515 Word i, ssz; 3516 XArray* stack; /* of Lock* */ 3517 WordFM* visited; /* Lock* -> void, iow, Set(Lock*) */ 3518 Lock* here; 3519 WordSetID succs; 3520 Word succs_size; 3521 UWord* succs_words; 3522 //laog__sanity_check(); 3523 3524 /* If the destination set is empty, we can never get there from 3525 'src' :-), so don't bother to try */ 3526 if (HG_(isEmptyWS)( univ_lsets, dsts )) 3527 return NULL; 3528 3529 ret = NULL; 3530 stack = VG_(newXA)( HG_(zalloc), "hg.lddft.1", HG_(free), sizeof(Lock*) ); 3531 visited = VG_(newFM)( HG_(zalloc), "hg.lddft.2", HG_(free), NULL/*unboxedcmp*/ ); 3532 3533 (void) VG_(addToXA)( stack, &src ); 3534 3535 while (True) { 3536 3537 ssz = VG_(sizeXA)( stack ); 3538 3539 if (ssz == 0) { ret = NULL; break; } 3540 3541 here = *(Lock**) VG_(indexXA)( stack, ssz-1 ); 3542 VG_(dropTailXA)( stack, 1 ); 3543 3544 if (HG_(elemWS)( univ_lsets, dsts, (Word)here )) { ret = here; break; } 3545 3546 if (VG_(lookupFM)( visited, NULL, NULL, (Word)here )) 3547 continue; 3548 3549 VG_(addToFM)( visited, (Word)here, 0 ); 3550 3551 succs = laog__succs( here ); 3552 HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs ); 3553 for (i = 0; i < succs_size; i++) 3554 (void) VG_(addToXA)( stack, &succs_words[i] ); 3555 } 3556 3557 VG_(deleteFM)( visited, NULL, NULL ); 3558 VG_(deleteXA)( stack ); 3559 return ret; 3560 } 3561 3562 3563 /* Thread 'thr' is acquiring 'lk'. Check for inconsistent ordering 3564 between 'lk' and the locks already held by 'thr' and issue a 3565 complaint if so. Also, update the ordering graph appropriately. 3566 */ 3567 __attribute__((noinline)) 3568 static void laog__pre_thread_acquires_lock ( 3569 Thread* thr, /* NB: BEFORE lock is added */ 3570 Lock* lk 3571 ) 3572 { 3573 UWord* ls_words; 3574 Word ls_size, i; 3575 Lock* other; 3576 3577 /* It may be that 'thr' already holds 'lk' and is recursively 3578 relocking in. In this case we just ignore the call. */ 3579 /* NB: univ_lsets really is correct here */ 3580 if (HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lk )) 3581 return; 3582 3583 if (UNLIKELY(!laog || !laog_exposition)) 3584 laog__init(); 3585 3586 /* First, the check. Complain if there is any path in laog from lk 3587 to any of the locks already held by thr, since if any such path 3588 existed, it would mean that previously lk was acquired before 3589 (rather than after, as we are doing here) at least one of those 3590 locks. 3591 */ 3592 other = laog__do_dfs_from_to(lk, thr->locksetA); 3593 if (other) { 3594 LAOGLinkExposition key, *found; 3595 /* So we managed to find a path lk --*--> other in the graph, 3596 which implies that 'lk' should have been acquired before 3597 'other' but is in fact being acquired afterwards. We present 3598 the lk/other arguments to record_error_LockOrder in the order 3599 in which they should have been acquired. */ 3600 /* Go look in the laog_exposition mapping, to find the allocation 3601 points for this edge, so we can show the user. */ 3602 key.src_ga = lk->guestaddr; 3603 key.dst_ga = other->guestaddr; 3604 key.src_ec = NULL; 3605 key.dst_ec = NULL; 3606 found = NULL; 3607 if (VG_(lookupFM)( laog_exposition, 3608 (Word*)&found, NULL, (Word)&key )) { 3609 tl_assert(found != &key); 3610 tl_assert(found->src_ga == key.src_ga); 3611 tl_assert(found->dst_ga == key.dst_ga); 3612 tl_assert(found->src_ec); 3613 tl_assert(found->dst_ec); 3614 HG_(record_error_LockOrder)( 3615 thr, lk->guestaddr, other->guestaddr, 3616 found->src_ec, found->dst_ec ); 3617 } else { 3618 /* Hmm. This can't happen (can it?) */ 3619 HG_(record_error_LockOrder)( 3620 thr, lk->guestaddr, other->guestaddr, 3621 NULL, NULL ); 3622 } 3623 } 3624 3625 /* Second, add to laog the pairs 3626 (old, lk) | old <- locks already held by thr 3627 Since both old and lk are currently held by thr, their acquired_at 3628 fields must be non-NULL. 3629 */ 3630 tl_assert(lk->acquired_at); 3631 HG_(getPayloadWS)( &ls_words, &ls_size, univ_lsets, thr->locksetA ); 3632 for (i = 0; i < ls_size; i++) { 3633 Lock* old = (Lock*)ls_words[i]; 3634 tl_assert(old->acquired_at); 3635 laog__add_edge( old, lk ); 3636 } 3637 3638 /* Why "except_Locks" ? We're here because a lock is being 3639 acquired by a thread, and we're in an inconsistent state here. 3640 See the call points in evhH__post_thread_{r,w}_acquires_lock. 3641 When called in this inconsistent state, locks__sanity_check duly 3642 barfs. */ 3643 if (HG_(clo_sanity_flags) & SCE_LAOG) 3644 all_except_Locks__sanity_check("laog__pre_thread_acquires_lock-post"); 3645 } 3646 3647 3648 /* Delete from 'laog' any pair mentioning a lock in locksToDelete */ 3649 3650 __attribute__((noinline)) 3651 static void laog__handle_one_lock_deletion ( Lock* lk ) 3652 { 3653 WordSetID preds, succs; 3654 Word preds_size, succs_size, i, j; 3655 UWord *preds_words, *succs_words; 3656 3657 if (UNLIKELY(!laog || !laog_exposition)) 3658 laog__init(); 3659 3660 preds = laog__preds( lk ); 3661 succs = laog__succs( lk ); 3662 3663 HG_(getPayloadWS)( &preds_words, &preds_size, univ_laog, preds ); 3664 for (i = 0; i < preds_size; i++) 3665 laog__del_edge( (Lock*)preds_words[i], lk ); 3666 3667 HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs ); 3668 for (j = 0; j < succs_size; j++) 3669 laog__del_edge( lk, (Lock*)succs_words[j] ); 3670 3671 for (i = 0; i < preds_size; i++) { 3672 for (j = 0; j < succs_size; j++) { 3673 if (preds_words[i] != succs_words[j]) { 3674 /* This can pass unlocked locks to laog__add_edge, since 3675 we're deleting stuff. So their acquired_at fields may 3676 be NULL. */ 3677 laog__add_edge( (Lock*)preds_words[i], (Lock*)succs_words[j] ); 3678 } 3679 } 3680 } 3681 } 3682 3683 //__attribute__((noinline)) 3684 //static void laog__handle_lock_deletions ( 3685 // WordSetID /* in univ_laog */ locksToDelete 3686 // ) 3687 //{ 3688 // Word i, ws_size; 3689 // UWord* ws_words; 3690 // 3691 // if (UNLIKELY(!laog || !laog_exposition)) 3692 // laog__init(); 3693 // 3694 // HG_(getPayloadWS)( &ws_words, &ws_size, univ_lsets, locksToDelete ); 3695 // for (i = 0; i < ws_size; i++) 3696 // laog__handle_one_lock_deletion( (Lock*)ws_words[i] ); 3697 // 3698 // if (HG_(clo_sanity_flags) & SCE_LAOG) 3699 // all__sanity_check("laog__handle_lock_deletions-post"); 3700 //} 3701 3702 3703 /*--------------------------------------------------------------*/ 3704 /*--- Malloc/free replacements ---*/ 3705 /*--------------------------------------------------------------*/ 3706 3707 typedef 3708 struct { 3709 void* next; /* required by m_hashtable */ 3710 Addr payload; /* ptr to actual block */ 3711 SizeT szB; /* size requested */ 3712 ExeContext* where; /* where it was allocated */ 3713 Thread* thr; /* allocating thread */ 3714 } 3715 MallocMeta; 3716 3717 /* A hash table of MallocMetas, used to track malloc'd blocks 3718 (obviously). */ 3719 static VgHashTable hg_mallocmeta_table = NULL; 3720 3721 3722 static MallocMeta* new_MallocMeta ( void ) { 3723 MallocMeta* md = HG_(zalloc)( "hg.new_MallocMeta.1", sizeof(MallocMeta) ); 3724 tl_assert(md); 3725 return md; 3726 } 3727 static void delete_MallocMeta ( MallocMeta* md ) { 3728 HG_(free)(md); 3729 } 3730 3731 3732 /* Allocate a client block and set up the metadata for it. */ 3733 3734 static 3735 void* handle_alloc ( ThreadId tid, 3736 SizeT szB, SizeT alignB, Bool is_zeroed ) 3737 { 3738 Addr p; 3739 MallocMeta* md; 3740 3741 tl_assert( ((SSizeT)szB) >= 0 ); 3742 p = (Addr)VG_(cli_malloc)(alignB, szB); 3743 if (!p) { 3744 return NULL; 3745 } 3746 if (is_zeroed) 3747 VG_(memset)((void*)p, 0, szB); 3748 3749 /* Note that map_threads_lookup must succeed (cannot assert), since 3750 memory can only be allocated by currently alive threads, hence 3751 they must have an entry in map_threads. */ 3752 md = new_MallocMeta(); 3753 md->payload = p; 3754 md->szB = szB; 3755 md->where = VG_(record_ExeContext)( tid, 0 ); 3756 md->thr = map_threads_lookup( tid ); 3757 3758 VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md ); 3759 3760 /* Tell the lower level memory wranglers. */ 3761 evh__new_mem_heap( p, szB, is_zeroed ); 3762 3763 return (void*)p; 3764 } 3765 3766 /* Re the checks for less-than-zero (also in hg_cli__realloc below): 3767 Cast to a signed type to catch any unexpectedly negative args. 3768 We're assuming here that the size asked for is not greater than 3769 2^31 bytes (for 32-bit platforms) or 2^63 bytes (for 64-bit 3770 platforms). */ 3771 static void* hg_cli__malloc ( ThreadId tid, SizeT n ) { 3772 if (((SSizeT)n) < 0) return NULL; 3773 return handle_alloc ( tid, n, VG_(clo_alignment), 3774 /*is_zeroed*/False ); 3775 } 3776 static void* hg_cli____builtin_new ( ThreadId tid, SizeT n ) { 3777 if (((SSizeT)n) < 0) return NULL; 3778 return handle_alloc ( tid, n, VG_(clo_alignment), 3779 /*is_zeroed*/False ); 3780 } 3781 static void* hg_cli____builtin_vec_new ( ThreadId tid, SizeT n ) { 3782 if (((SSizeT)n) < 0) return NULL; 3783 return handle_alloc ( tid, n, VG_(clo_alignment), 3784 /*is_zeroed*/False ); 3785 } 3786 static void* hg_cli__memalign ( ThreadId tid, SizeT align, SizeT n ) { 3787 if (((SSizeT)n) < 0) return NULL; 3788 return handle_alloc ( tid, n, align, 3789 /*is_zeroed*/False ); 3790 } 3791 static void* hg_cli__calloc ( ThreadId tid, SizeT nmemb, SizeT size1 ) { 3792 if ( ((SSizeT)nmemb) < 0 || ((SSizeT)size1) < 0 ) return NULL; 3793 return handle_alloc ( tid, nmemb*size1, VG_(clo_alignment), 3794 /*is_zeroed*/True ); 3795 } 3796 3797 3798 /* Free a client block, including getting rid of the relevant 3799 metadata. */ 3800 3801 static void handle_free ( ThreadId tid, void* p ) 3802 { 3803 MallocMeta *md, *old_md; 3804 SizeT szB; 3805 3806 /* First see if we can find the metadata for 'p'. */ 3807 md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p ); 3808 if (!md) 3809 return; /* apparently freeing a bogus address. Oh well. */ 3810 3811 tl_assert(md->payload == (Addr)p); 3812 szB = md->szB; 3813 3814 /* Nuke the metadata block */ 3815 old_md = (MallocMeta*) 3816 VG_(HT_remove)( hg_mallocmeta_table, (UWord)p ); 3817 tl_assert(old_md); /* it must be present - we just found it */ 3818 tl_assert(old_md == md); 3819 tl_assert(old_md->payload == (Addr)p); 3820 3821 VG_(cli_free)((void*)old_md->payload); 3822 delete_MallocMeta(old_md); 3823 3824 /* Tell the lower level memory wranglers. */ 3825 evh__die_mem_heap( (Addr)p, szB ); 3826 } 3827 3828 static void hg_cli__free ( ThreadId tid, void* p ) { 3829 handle_free(tid, p); 3830 } 3831 static void hg_cli____builtin_delete ( ThreadId tid, void* p ) { 3832 handle_free(tid, p); 3833 } 3834 static void hg_cli____builtin_vec_delete ( ThreadId tid, void* p ) { 3835 handle_free(tid, p); 3836 } 3837 3838 3839 static void* hg_cli__realloc ( ThreadId tid, void* payloadV, SizeT new_size ) 3840 { 3841 MallocMeta *md, *md_new, *md_tmp; 3842 SizeT i; 3843 3844 Addr payload = (Addr)payloadV; 3845 3846 if (((SSizeT)new_size) < 0) return NULL; 3847 3848 md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)payload ); 3849 if (!md) 3850 return NULL; /* apparently realloc-ing a bogus address. Oh well. */ 3851 3852 tl_assert(md->payload == payload); 3853 3854 if (md->szB == new_size) { 3855 /* size unchanged */ 3856 md->where = VG_(record_ExeContext)(tid, 0); 3857 return payloadV; 3858 } 3859 3860 if (md->szB > new_size) { 3861 /* new size is smaller */ 3862 md->szB = new_size; 3863 md->where = VG_(record_ExeContext)(tid, 0); 3864 evh__die_mem_heap( md->payload + new_size, md->szB - new_size ); 3865 return payloadV; 3866 } 3867 3868 /* else */ { 3869 /* new size is bigger */ 3870 Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size); 3871 3872 /* First half kept and copied, second half new */ 3873 // FIXME: shouldn't we use a copier which implements the 3874 // memory state machine? 3875 evh__copy_mem( payload, p_new, md->szB ); 3876 evh__new_mem_heap ( p_new + md->szB, new_size - md->szB, 3877 /*inited*/False ); 3878 /* FIXME: can anything funny happen here? specifically, if the 3879 old range contained a lock, then die_mem_heap will complain. 3880 Is that the correct behaviour? Not sure. */ 3881 evh__die_mem_heap( payload, md->szB ); 3882 3883 /* Copy from old to new */ 3884 for (i = 0; i < md->szB; i++) 3885 ((UChar*)p_new)[i] = ((UChar*)payload)[i]; 3886 3887 /* Because the metadata hash table is index by payload address, 3888 we have to get rid of the old hash table entry and make a new 3889 one. We can't just modify the existing metadata in place, 3890 because then it would (almost certainly) be in the wrong hash 3891 chain. */ 3892 md_new = new_MallocMeta(); 3893 *md_new = *md; 3894 3895 md_tmp = VG_(HT_remove)( hg_mallocmeta_table, payload ); 3896 tl_assert(md_tmp); 3897 tl_assert(md_tmp == md); 3898 3899 VG_(cli_free)((void*)md->payload); 3900 delete_MallocMeta(md); 3901 3902 /* Update fields */ 3903 md_new->where = VG_(record_ExeContext)( tid, 0 ); 3904 md_new->szB = new_size; 3905 md_new->payload = p_new; 3906 md_new->thr = map_threads_lookup( tid ); 3907 3908 /* and add */ 3909 VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md_new ); 3910 3911 return (void*)p_new; 3912 } 3913 } 3914 3915 static SizeT hg_cli_malloc_usable_size ( ThreadId tid, void* p ) 3916 { 3917 MallocMeta *md = VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p ); 3918 3919 // There may be slop, but pretend there isn't because only the asked-for 3920 // area will have been shadowed properly. 3921 return ( md ? md->szB : 0 ); 3922 } 3923 3924 3925 /* For error creation: map 'data_addr' to a malloc'd chunk, if any. 3926 Slow linear search. With a bit of hash table help if 'data_addr' 3927 is either the start of a block or up to 15 word-sized steps along 3928 from the start of a block. */ 3929 3930 static inline Bool addr_is_in_MM_Chunk( MallocMeta* mm, Addr a ) 3931 { 3932 /* Accept 'a' as within 'mm' if 'mm's size is zero and 'a' points 3933 right at it. */ 3934 if (UNLIKELY(mm->szB == 0 && a == mm->payload)) 3935 return True; 3936 /* else normal interval rules apply */ 3937 if (LIKELY(a < mm->payload)) return False; 3938 if (LIKELY(a >= mm->payload + mm->szB)) return False; 3939 return True; 3940 } 3941 3942 Bool HG_(mm_find_containing_block)( /*OUT*/ExeContext** where, 3943 /*OUT*/Addr* payload, 3944 /*OUT*/SizeT* szB, 3945 Addr data_addr ) 3946 { 3947 MallocMeta* mm; 3948 Int i; 3949 const Int n_fast_check_words = 16; 3950 3951 /* First, do a few fast searches on the basis that data_addr might 3952 be exactly the start of a block or up to 15 words inside. This 3953 can happen commonly via the creq 3954 _VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK. */ 3955 for (i = 0; i < n_fast_check_words; i++) { 3956 mm = VG_(HT_lookup)( hg_mallocmeta_table, 3957 data_addr - (UWord)(UInt)i * sizeof(UWord) ); 3958 if (UNLIKELY(mm && addr_is_in_MM_Chunk(mm, data_addr))) 3959 goto found; 3960 } 3961 3962 /* Well, this totally sucks. But without using an interval tree or 3963 some such, it's hard to see how to do better. We have to check 3964 every block in the entire table. */ 3965 VG_(HT_ResetIter)(hg_mallocmeta_table); 3966 while ( (mm = VG_(HT_Next)(hg_mallocmeta_table)) ) { 3967 if (UNLIKELY(addr_is_in_MM_Chunk(mm, data_addr))) 3968 goto found; 3969 } 3970 3971 /* Not found. Bah. */ 3972 return False; 3973 /*NOTREACHED*/ 3974 3975 found: 3976 tl_assert(mm); 3977 tl_assert(addr_is_in_MM_Chunk(mm, data_addr)); 3978 if (where) *where = mm->where; 3979 if (payload) *payload = mm->payload; 3980 if (szB) *szB = mm->szB; 3981 return True; 3982 } 3983 3984 3985 /*--------------------------------------------------------------*/ 3986 /*--- Instrumentation ---*/ 3987 /*--------------------------------------------------------------*/ 3988 3989 static void instrument_mem_access ( IRSB* bbOut, 3990 IRExpr* addr, 3991 Int szB, 3992 Bool isStore, 3993 Int hWordTy_szB ) 3994 { 3995 IRType tyAddr = Ity_INVALID; 3996 HChar* hName = NULL; 3997 void* hAddr = NULL; 3998 Int regparms = 0; 3999 IRExpr** argv = NULL; 4000 IRDirty* di = NULL; 4001 4002 tl_assert(isIRAtom(addr)); 4003 tl_assert(hWordTy_szB == 4 || hWordTy_szB == 8); 4004 4005 tyAddr = typeOfIRExpr( bbOut->tyenv, addr ); 4006 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64); 4007 4008 /* So the effective address is in 'addr' now. */ 4009 regparms = 1; // unless stated otherwise 4010 if (isStore) { 4011 switch (szB) { 4012 case 1: 4013 hName = "evh__mem_help_cwrite_1"; 4014 hAddr = &evh__mem_help_cwrite_1; 4015 argv = mkIRExprVec_1( addr ); 4016 break; 4017 case 2: 4018 hName = "evh__mem_help_cwrite_2"; 4019 hAddr = &evh__mem_help_cwrite_2; 4020 argv = mkIRExprVec_1( addr ); 4021 break; 4022 case 4: 4023 hName = "evh__mem_help_cwrite_4"; 4024 hAddr = &evh__mem_help_cwrite_4; 4025 argv = mkIRExprVec_1( addr ); 4026 break; 4027 case 8: 4028 hName = "evh__mem_help_cwrite_8"; 4029 hAddr = &evh__mem_help_cwrite_8; 4030 argv = mkIRExprVec_1( addr ); 4031 break; 4032 default: 4033 tl_assert(szB > 8 && szB <= 512); /* stay sane */ 4034 regparms = 2; 4035 hName = "evh__mem_help_cwrite_N"; 4036 hAddr = &evh__mem_help_cwrite_N; 4037 argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB )); 4038 break; 4039 } 4040 } else { 4041 switch (szB) { 4042 case 1: 4043 hName = "evh__mem_help_cread_1"; 4044 hAddr = &evh__mem_help_cread_1; 4045 argv = mkIRExprVec_1( addr ); 4046 break; 4047 case 2: 4048 hName = "evh__mem_help_cread_2"; 4049 hAddr = &evh__mem_help_cread_2; 4050 argv = mkIRExprVec_1( addr ); 4051 break; 4052 case 4: 4053 hName = "evh__mem_help_cread_4"; 4054 hAddr = &evh__mem_help_cread_4; 4055 argv = mkIRExprVec_1( addr ); 4056 break; 4057 case 8: 4058 hName = "evh__mem_help_cread_8"; 4059 hAddr = &evh__mem_help_cread_8; 4060 argv = mkIRExprVec_1( addr ); 4061 break; 4062 default: 4063 tl_assert(szB > 8 && szB <= 512); /* stay sane */ 4064 regparms = 2; 4065 hName = "evh__mem_help_cread_N"; 4066 hAddr = &evh__mem_help_cread_N; 4067 argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB )); 4068 break; 4069 } 4070 } 4071 4072 /* Add the helper. */ 4073 tl_assert(hName); 4074 tl_assert(hAddr); 4075 tl_assert(argv); 4076 di = unsafeIRDirty_0_N( regparms, 4077 hName, VG_(fnptr_to_fnentry)( hAddr ), 4078 argv ); 4079 addStmtToIRSB( bbOut, IRStmt_Dirty(di) ); 4080 } 4081 4082 4083 /* Figure out if GA is a guest code address in the dynamic linker, and 4084 if so return True. Otherwise (and in case of any doubt) return 4085 False. (sidedly safe w/ False as the safe value) */ 4086 static Bool is_in_dynamic_linker_shared_object( Addr64 ga ) 4087 { 4088 DebugInfo* dinfo; 4089 const UChar* soname; 4090 if (0) return False; 4091 4092 dinfo = VG_(find_DebugInfo)( (Addr)ga ); 4093 if (!dinfo) return False; 4094 4095 soname = VG_(DebugInfo_get_soname)(dinfo); 4096 tl_assert(soname); 4097 if (0) VG_(printf)("%s\n", soname); 4098 4099 # if defined(VGO_linux) 4100 if (VG_STREQ(soname, VG_U_LD_LINUX_SO_3)) return True; 4101 if (VG_STREQ(soname, VG_U_LD_LINUX_SO_2)) return True; 4102 if (VG_STREQ(soname, VG_U_LD_LINUX_X86_64_SO_2)) return True; 4103 if (VG_STREQ(soname, VG_U_LD64_SO_1)) return True; 4104 if (VG_STREQ(soname, VG_U_LD_SO_1)) return True; 4105 # elif defined(VGO_darwin) 4106 if (VG_STREQ(soname, VG_U_DYLD)) return True; 4107 # else 4108 # error "Unsupported OS" 4109 # endif 4110 return False; 4111 } 4112 4113 static 4114 IRSB* hg_instrument ( VgCallbackClosure* closure, 4115 IRSB* bbIn, 4116 VexGuestLayout* layout, 4117 VexGuestExtents* vge, 4118 IRType gWordTy, IRType hWordTy ) 4119 { 4120 Int i; 4121 IRSB* bbOut; 4122 Addr64 cia; /* address of current insn */ 4123 IRStmt* st; 4124 Bool inLDSO = False; 4125 Addr64 inLDSOmask4K = 1; /* mismatches on first check */ 4126 4127 if (gWordTy != hWordTy) { 4128 /* We don't currently support this case. */ 4129 VG_(tool_panic)("host/guest word size mismatch"); 4130 } 4131 4132 if (VKI_PAGE_SIZE < 4096 || VG_(log2)(VKI_PAGE_SIZE) == -1) { 4133 VG_(tool_panic)("implausible or too-small VKI_PAGE_SIZE"); 4134 } 4135 4136 /* Set up BB */ 4137 bbOut = emptyIRSB(); 4138 bbOut->tyenv = deepCopyIRTypeEnv(bbIn->tyenv); 4139 bbOut->next = deepCopyIRExpr(bbIn->next); 4140 bbOut->jumpkind = bbIn->jumpkind; 4141 4142 // Copy verbatim any IR preamble preceding the first IMark 4143 i = 0; 4144 while (i < bbIn->stmts_used && bbIn->stmts[i]->tag != Ist_IMark) { 4145 addStmtToIRSB( bbOut, bbIn->stmts[i] ); 4146 i++; 4147 } 4148 4149 // Get the first statement, and initial cia from it 4150 tl_assert(bbIn->stmts_used > 0); 4151 tl_assert(i < bbIn->stmts_used); 4152 st = bbIn->stmts[i]; 4153 tl_assert(Ist_IMark == st->tag); 4154 cia = st->Ist.IMark.addr; 4155 st = NULL; 4156 4157 for (/*use current i*/; i < bbIn->stmts_used; i++) { 4158 st = bbIn->stmts[i]; 4159 tl_assert(st); 4160 tl_assert(isFlatIRStmt(st)); 4161 switch (st->tag) { 4162 case Ist_NoOp: 4163 case Ist_AbiHint: 4164 case Ist_Put: 4165 case Ist_PutI: 4166 case Ist_Exit: 4167 /* None of these can contain any memory references. */ 4168 break; 4169 4170 case Ist_IMark: 4171 /* no mem refs, but note the insn address. */ 4172 cia = st->Ist.IMark.addr; 4173 /* Don't instrument the dynamic linker. It generates a 4174 lot of races which we just expensively suppress, so 4175 it's pointless. 4176 4177 Avoid flooding is_in_dynamic_linker_shared_object with 4178 requests by only checking at transitions between 4K 4179 pages. */ 4180 if ((cia & ~(Addr64)0xFFF) != inLDSOmask4K) { 4181 if (0) VG_(printf)("NEW %#lx\n", (Addr)cia); 4182 inLDSOmask4K = cia & ~(Addr64)0xFFF; 4183 inLDSO = is_in_dynamic_linker_shared_object(cia); 4184 } else { 4185 if (0) VG_(printf)("old %#lx\n", (Addr)cia); 4186 } 4187 break; 4188 4189 case Ist_MBE: 4190 switch (st->Ist.MBE.event) { 4191 case Imbe_Fence: 4192 break; /* not interesting */ 4193 default: 4194 goto unhandled; 4195 } 4196 break; 4197 4198 case Ist_CAS: { 4199 /* Atomic read-modify-write cycle. Just pretend it's a 4200 read. */ 4201 IRCAS* cas = st->Ist.CAS.details; 4202 Bool isDCAS = cas->oldHi != IRTemp_INVALID; 4203 if (isDCAS) { 4204 tl_assert(cas->expdHi); 4205 tl_assert(cas->dataHi); 4206 } else { 4207 tl_assert(!cas->expdHi); 4208 tl_assert(!cas->dataHi); 4209 } 4210 /* Just be boring about it. */ 4211 if (!inLDSO) { 4212 instrument_mem_access( 4213 bbOut, 4214 cas->addr, 4215 (isDCAS ? 2 : 1) 4216 * sizeofIRType(typeOfIRExpr(bbIn->tyenv, cas->dataLo)), 4217 False/*!isStore*/, 4218 sizeofIRType(hWordTy) 4219 ); 4220 } 4221 break; 4222 } 4223 4224 case Ist_LLSC: { 4225 /* We pretend store-conditionals don't exist, viz, ignore 4226 them. Whereas load-linked's are treated the same as 4227 normal loads. */ 4228 IRType dataTy; 4229 if (st->Ist.LLSC.storedata == NULL) { 4230 /* LL */ 4231 dataTy = typeOfIRTemp(bbIn->tyenv, st->Ist.LLSC.result); 4232 if (!inLDSO) { 4233 instrument_mem_access( 4234 bbOut, 4235 st->Ist.LLSC.addr, 4236 sizeofIRType(dataTy), 4237 False/*!isStore*/, 4238 sizeofIRType(hWordTy) 4239 ); 4240 } 4241 } else { 4242 /* SC */ 4243 /*ignore */ 4244 } 4245 break; 4246 } 4247 4248 case Ist_Store: 4249 /* It seems we pretend that store-conditionals don't 4250 exist, viz, just ignore them ... */ 4251 if (!inLDSO) { 4252 instrument_mem_access( 4253 bbOut, 4254 st->Ist.Store.addr, 4255 sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)), 4256 True/*isStore*/, 4257 sizeofIRType(hWordTy) 4258 ); 4259 } 4260 break; 4261 4262 case Ist_WrTmp: { 4263 /* ... whereas here we don't care whether a load is a 4264 vanilla one or a load-linked. */ 4265 IRExpr* data = st->Ist.WrTmp.data; 4266 if (data->tag == Iex_Load) { 4267 if (!inLDSO) { 4268 instrument_mem_access( 4269 bbOut, 4270 data->Iex.Load.addr, 4271 sizeofIRType(data->Iex.Load.ty), 4272 False/*!isStore*/, 4273 sizeofIRType(hWordTy) 4274 ); 4275 } 4276 } 4277 break; 4278 } 4279 4280 case Ist_Dirty: { 4281 Int dataSize; 4282 IRDirty* d = st->Ist.Dirty.details; 4283 if (d->mFx != Ifx_None) { 4284 /* This dirty helper accesses memory. Collect the 4285 details. */ 4286 tl_assert(d->mAddr != NULL); 4287 tl_assert(d->mSize != 0); 4288 dataSize = d->mSize; 4289 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) { 4290 if (!inLDSO) { 4291 instrument_mem_access( 4292 bbOut, d->mAddr, dataSize, False/*!isStore*/, 4293 sizeofIRType(hWordTy) 4294 ); 4295 } 4296 } 4297 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) { 4298 if (!inLDSO) { 4299 instrument_mem_access( 4300 bbOut, d->mAddr, dataSize, True/*isStore*/, 4301 sizeofIRType(hWordTy) 4302 ); 4303 } 4304 } 4305 } else { 4306 tl_assert(d->mAddr == NULL); 4307 tl_assert(d->mSize == 0); 4308 } 4309 break; 4310 } 4311 4312 default: 4313 unhandled: 4314 ppIRStmt(st); 4315 tl_assert(0); 4316 4317 } /* switch (st->tag) */ 4318 4319 addStmtToIRSB( bbOut, st ); 4320 } /* iterate over bbIn->stmts */ 4321 4322 return bbOut; 4323 } 4324 4325 4326 /*----------------------------------------------------------------*/ 4327 /*--- Client requests ---*/ 4328 /*----------------------------------------------------------------*/ 4329 4330 /* Sheesh. Yet another goddam finite map. */ 4331 static WordFM* map_pthread_t_to_Thread = NULL; /* pthread_t -> Thread* */ 4332 4333 static void map_pthread_t_to_Thread_INIT ( void ) { 4334 if (UNLIKELY(map_pthread_t_to_Thread == NULL)) { 4335 map_pthread_t_to_Thread = VG_(newFM)( HG_(zalloc), "hg.mpttT.1", 4336 HG_(free), NULL ); 4337 tl_assert(map_pthread_t_to_Thread != NULL); 4338 } 4339 } 4340 4341 4342 static 4343 Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret) 4344 { 4345 if (!VG_IS_TOOL_USERREQ('H','G',args[0])) 4346 return False; 4347 4348 /* Anything that gets past the above check is one of ours, so we 4349 should be able to handle it. */ 4350 4351 /* default, meaningless return value, unless otherwise set */ 4352 *ret = 0; 4353 4354 switch (args[0]) { 4355 4356 /* --- --- User-visible client requests --- --- */ 4357 4358 case VG_USERREQ__HG_CLEAN_MEMORY: 4359 if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY(%#lx,%ld)\n", 4360 args[1], args[2]); 4361 /* Call die_mem to (expensively) tidy up properly, if there 4362 are any held locks etc in the area. Calling evh__die_mem 4363 and then evh__new_mem is a bit inefficient; probably just 4364 the latter would do. */ 4365 if (args[2] > 0) { /* length */ 4366 evh__die_mem(args[1], args[2]); 4367 /* and then set it to New */ 4368 evh__new_mem(args[1], args[2]); 4369 } 4370 break; 4371 4372 case _VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK: { 4373 Addr payload = 0; 4374 SizeT pszB = 0; 4375 if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK(%#lx)\n", 4376 args[1]); 4377 if (HG_(mm_find_containing_block)(NULL, &payload, &pszB, args[1])) { 4378 if (pszB > 0) { 4379 evh__die_mem(payload, pszB); 4380 evh__new_mem(payload, pszB); 4381 } 4382 *ret = pszB; 4383 } else { 4384 *ret = (UWord)-1; 4385 } 4386 break; 4387 } 4388 4389 case _VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED: 4390 if (0) VG_(printf)("HG_ARANGE_MAKE_UNTRACKED(%#lx,%ld)\n", 4391 args[1], args[2]); 4392 if (args[2] > 0) { /* length */ 4393 evh__untrack_mem(args[1], args[2]); 4394 } 4395 break; 4396 4397 case _VG_USERREQ__HG_ARANGE_MAKE_TRACKED: 4398 if (0) VG_(printf)("HG_ARANGE_MAKE_TRACKED(%#lx,%ld)\n", 4399 args[1], args[2]); 4400 if (args[2] > 0) { /* length */ 4401 evh__new_mem(args[1], args[2]); 4402 } 4403 break; 4404 4405 /* --- --- Client requests for Helgrind's use only --- --- */ 4406 4407 /* Some thread is telling us its pthread_t value. Record the 4408 binding between that and the associated Thread*, so we can 4409 later find the Thread* again when notified of a join by the 4410 thread. */ 4411 case _VG_USERREQ__HG_SET_MY_PTHREAD_T: { 4412 Thread* my_thr = NULL; 4413 if (0) 4414 VG_(printf)("SET_MY_PTHREAD_T (tid %d): pthread_t = %p\n", (Int)tid, 4415 (void*)args[1]); 4416 map_pthread_t_to_Thread_INIT(); 4417 my_thr = map_threads_maybe_lookup( tid ); 4418 /* This assertion should hold because the map_threads (tid to 4419 Thread*) binding should have been made at the point of 4420 low-level creation of this thread, which should have 4421 happened prior to us getting this client request for it. 4422 That's because this client request is sent from 4423 client-world from the 'thread_wrapper' function, which 4424 only runs once the thread has been low-level created. */ 4425 tl_assert(my_thr != NULL); 4426 /* So now we know that (pthread_t)args[1] is associated with 4427 (Thread*)my_thr. Note that down. */ 4428 if (0) 4429 VG_(printf)("XXXX: bind pthread_t %p to Thread* %p\n", 4430 (void*)args[1], (void*)my_thr ); 4431 VG_(addToFM)( map_pthread_t_to_Thread, (Word)args[1], (Word)my_thr ); 4432 break; 4433 } 4434 4435 case _VG_USERREQ__HG_PTH_API_ERROR: { 4436 Thread* my_thr = NULL; 4437 map_pthread_t_to_Thread_INIT(); 4438 my_thr = map_threads_maybe_lookup( tid ); 4439 tl_assert(my_thr); /* See justification above in SET_MY_PTHREAD_T */ 4440 HG_(record_error_PthAPIerror)( 4441 my_thr, (HChar*)args[1], (Word)args[2], (HChar*)args[3] ); 4442 break; 4443 } 4444 4445 /* This thread (tid) has completed a join with the quitting 4446 thread whose pthread_t is in args[1]. */ 4447 case _VG_USERREQ__HG_PTHREAD_JOIN_POST: { 4448 Thread* thr_q = NULL; /* quitter Thread* */ 4449 Bool found = False; 4450 if (0) 4451 VG_(printf)("NOTIFY_JOIN_COMPLETE (tid %d): quitter = %p\n", (Int)tid, 4452 (void*)args[1]); 4453 map_pthread_t_to_Thread_INIT(); 4454 found = VG_(lookupFM)( map_pthread_t_to_Thread, 4455 NULL, (Word*)&thr_q, (Word)args[1] ); 4456 /* Can this fail? It would mean that our pthread_join 4457 wrapper observed a successful join on args[1] yet that 4458 thread never existed (or at least, it never lodged an 4459 entry in the mapping (via SET_MY_PTHREAD_T)). Which 4460 sounds like a bug in the threads library. */ 4461 // FIXME: get rid of this assertion; handle properly 4462 tl_assert(found); 4463 if (found) { 4464 if (0) 4465 VG_(printf)(".................... quitter Thread* = %p\n", 4466 thr_q); 4467 evh__HG_PTHREAD_JOIN_POST( tid, thr_q ); 4468 } 4469 break; 4470 } 4471 4472 /* EXPOSITION only: by intercepting lock init events we can show 4473 the user where the lock was initialised, rather than only 4474 being able to show where it was first locked. Intercepting 4475 lock initialisations is not necessary for the basic operation 4476 of the race checker. */ 4477 case _VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST: 4478 evh__HG_PTHREAD_MUTEX_INIT_POST( tid, (void*)args[1], args[2] ); 4479 break; 4480 4481 case _VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE: 4482 evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, (void*)args[1] ); 4483 break; 4484 4485 case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE: // pth_mx_t* 4486 evh__HG_PTHREAD_MUTEX_UNLOCK_PRE( tid, (void*)args[1] ); 4487 break; 4488 4489 case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST: // pth_mx_t* 4490 evh__HG_PTHREAD_MUTEX_UNLOCK_POST( tid, (void*)args[1] ); 4491 break; 4492 4493 case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE: // pth_mx_t*, Word 4494 evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, (void*)args[1], args[2] ); 4495 break; 4496 4497 case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST: // pth_mx_t* 4498 evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, (void*)args[1] ); 4499 break; 4500 4501 /* This thread is about to do pthread_cond_signal on the 4502 pthread_cond_t* in arg[1]. Ditto pthread_cond_broadcast. */ 4503 case _VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE: 4504 case _VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE: 4505 evh__HG_PTHREAD_COND_SIGNAL_PRE( tid, (void*)args[1] ); 4506 break; 4507 4508 /* Entry into pthread_cond_wait, cond=arg[1], mutex=arg[2]. 4509 Returns a flag indicating whether or not the mutex is believed to be 4510 valid for this operation. */ 4511 case _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE: { 4512 Bool mutex_is_valid 4513 = evh__HG_PTHREAD_COND_WAIT_PRE( tid, (void*)args[1], 4514 (void*)args[2] ); 4515 *ret = mutex_is_valid ? 1 : 0; 4516 break; 4517 } 4518 4519 /* cond=arg[1] */ 4520 case _VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE: 4521 evh__HG_PTHREAD_COND_DESTROY_PRE( tid, (void*)args[1] ); 4522 break; 4523 4524 /* Thread successfully completed pthread_cond_wait, cond=arg[1], 4525 mutex=arg[2] */ 4526 case _VG_USERREQ__HG_PTHREAD_COND_WAIT_POST: 4527 evh__HG_PTHREAD_COND_WAIT_POST( tid, 4528 (void*)args[1], (void*)args[2] ); 4529 break; 4530 4531 case _VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST: 4532 evh__HG_PTHREAD_RWLOCK_INIT_POST( tid, (void*)args[1] ); 4533 break; 4534 4535 case _VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE: 4536 evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( tid, (void*)args[1] ); 4537 break; 4538 4539 /* rwlock=arg[1], isW=arg[2], isTryLock=arg[3] */ 4540 case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE: 4541 evh__HG_PTHREAD_RWLOCK_LOCK_PRE( tid, (void*)args[1], 4542 args[2], args[3] ); 4543 break; 4544 4545 /* rwlock=arg[1], isW=arg[2] */ 4546 case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST: 4547 evh__HG_PTHREAD_RWLOCK_LOCK_POST( tid, (void*)args[1], args[2] ); 4548 break; 4549 4550 case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE: 4551 evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE( tid, (void*)args[1] ); 4552 break; 4553 4554 case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST: 4555 evh__HG_PTHREAD_RWLOCK_UNLOCK_POST( tid, (void*)args[1] ); 4556 break; 4557 4558 case _VG_USERREQ__HG_POSIX_SEM_INIT_POST: /* sem_t*, unsigned long */ 4559 evh__HG_POSIX_SEM_INIT_POST( tid, (void*)args[1], args[2] ); 4560 break; 4561 4562 case _VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE: /* sem_t* */ 4563 evh__HG_POSIX_SEM_DESTROY_PRE( tid, (void*)args[1] ); 4564 break; 4565 4566 case _VG_USERREQ__HG_POSIX_SEM_POST_PRE: /* sem_t* */ 4567 evh__HG_POSIX_SEM_POST_PRE( tid, (void*)args[1] ); 4568 break; 4569 4570 case _VG_USERREQ__HG_POSIX_SEM_WAIT_POST: /* sem_t* */ 4571 evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] ); 4572 break; 4573 4574 case _VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE: 4575 /* pth_bar_t*, ulong count, ulong resizable */ 4576 evh__HG_PTHREAD_BARRIER_INIT_PRE( tid, (void*)args[1], 4577 args[2], args[3] ); 4578 break; 4579 4580 case _VG_USERREQ__HG_PTHREAD_BARRIER_RESIZE_PRE: 4581 /* pth_bar_t*, ulong newcount */ 4582 evh__HG_PTHREAD_BARRIER_RESIZE_PRE ( tid, (void*)args[1], 4583 args[2] ); 4584 break; 4585 4586 case _VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE: 4587 /* pth_bar_t* */ 4588 evh__HG_PTHREAD_BARRIER_WAIT_PRE( tid, (void*)args[1] ); 4589 break; 4590 4591 case _VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE: 4592 /* pth_bar_t* */ 4593 evh__HG_PTHREAD_BARRIER_DESTROY_PRE( tid, (void*)args[1] ); 4594 break; 4595 4596 case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE: 4597 /* pth_spinlock_t* */ 4598 evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE( tid, (void*)args[1] ); 4599 break; 4600 4601 case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST: 4602 /* pth_spinlock_t* */ 4603 evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST( tid, (void*)args[1] ); 4604 break; 4605 4606 case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE: 4607 /* pth_spinlock_t*, Word */ 4608 evh__HG_PTHREAD_SPIN_LOCK_PRE( tid, (void*)args[1], args[2] ); 4609 break; 4610 4611 case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST: 4612 /* pth_spinlock_t* */ 4613 evh__HG_PTHREAD_SPIN_LOCK_POST( tid, (void*)args[1] ); 4614 break; 4615 4616 case _VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE: 4617 /* pth_spinlock_t* */ 4618 evh__HG_PTHREAD_SPIN_DESTROY_PRE( tid, (void*)args[1] ); 4619 break; 4620 4621 case _VG_USERREQ__HG_CLIENTREQ_UNIMP: { 4622 /* char* who */ 4623 HChar* who = (HChar*)args[1]; 4624 HChar buf[50 + 50]; 4625 Thread* thr = map_threads_maybe_lookup( tid ); 4626 tl_assert( thr ); /* I must be mapped */ 4627 tl_assert( who ); 4628 tl_assert( VG_(strlen)(who) <= 50 ); 4629 VG_(sprintf)(buf, "Unimplemented client request macro \"%s\"", who ); 4630 /* record_error_Misc strdup's buf, so this is safe: */ 4631 HG_(record_error_Misc)( thr, buf ); 4632 break; 4633 } 4634 4635 case _VG_USERREQ__HG_USERSO_SEND_PRE: 4636 /* UWord arbitrary-SO-tag */ 4637 evh__HG_USERSO_SEND_PRE( tid, args[1] ); 4638 break; 4639 4640 case _VG_USERREQ__HG_USERSO_RECV_POST: 4641 /* UWord arbitrary-SO-tag */ 4642 evh__HG_USERSO_RECV_POST( tid, args[1] ); 4643 break; 4644 4645 default: 4646 /* Unhandled Helgrind client request! */ 4647 tl_assert2(0, "unhandled Helgrind client request 0x%lx", 4648 args[0]); 4649 } 4650 4651 return True; 4652 } 4653 4654 4655 /*----------------------------------------------------------------*/ 4656 /*--- Setup ---*/ 4657 /*----------------------------------------------------------------*/ 4658 4659 static Bool hg_process_cmd_line_option ( Char* arg ) 4660 { 4661 Char* tmp_str; 4662 4663 if VG_BOOL_CLO(arg, "--track-lockorders", 4664 HG_(clo_track_lockorders)) {} 4665 else if VG_BOOL_CLO(arg, "--cmp-race-err-addrs", 4666 HG_(clo_cmp_race_err_addrs)) {} 4667 4668 else if VG_XACT_CLO(arg, "--history-level=none", 4669 HG_(clo_history_level), 0); 4670 else if VG_XACT_CLO(arg, "--history-level=approx", 4671 HG_(clo_history_level), 1); 4672 else if VG_XACT_CLO(arg, "--history-level=full", 4673 HG_(clo_history_level), 2); 4674 4675 /* If you change the 10k/30mill limits, remember to also change 4676 them in assertions at the top of event_map_maybe_GC. */ 4677 else if VG_BINT_CLO(arg, "--conflict-cache-size", 4678 HG_(clo_conflict_cache_size), 10*1000, 30*1000*1000) {} 4679 4680 /* "stuvwx" --> stuvwx (binary) */ 4681 else if VG_STR_CLO(arg, "--hg-sanity-flags", tmp_str) { 4682 Int j; 4683 4684 if (6 != VG_(strlen)(tmp_str)) { 4685 VG_(message)(Vg_UserMsg, 4686 "--hg-sanity-flags argument must have 6 digits\n"); 4687 return False; 4688 } 4689 for (j = 0; j < 6; j++) { 4690 if ('0' == tmp_str[j]) { /* do nothing */ } 4691 else if ('1' == tmp_str[j]) HG_(clo_sanity_flags) |= (1 << (6-1-j)); 4692 else { 4693 VG_(message)(Vg_UserMsg, "--hg-sanity-flags argument can " 4694 "only contain 0s and 1s\n"); 4695 return False; 4696 } 4697 } 4698 if (0) VG_(printf)("XXX sanity flags: 0x%lx\n", HG_(clo_sanity_flags)); 4699 } 4700 4701 else 4702 return VG_(replacement_malloc_process_cmd_line_option)(arg); 4703 4704 return True; 4705 } 4706 4707 static void hg_print_usage ( void ) 4708 { 4709 VG_(printf)( 4710 " --track-lockorders=no|yes show lock ordering errors? [yes]\n" 4711 " --history-level=none|approx|full [full]\n" 4712 " full: show both stack traces for a data race (can be very slow)\n" 4713 " approx: full trace for one thread, approx for the other (faster)\n" 4714 " none: only show trace for one thread in a race (fastest)\n" 4715 " --conflict-cache-size=N size of 'full' history cache [1000000]\n" 4716 ); 4717 } 4718 4719 static void hg_print_debug_usage ( void ) 4720 { 4721 VG_(printf)(" --cmp-race-err-addrs=no|yes are data addresses in " 4722 "race errors significant? [no]\n"); 4723 VG_(printf)(" --hg-sanity-flags=<XXXXXX> sanity check " 4724 " at events (X = 0|1) [000000]\n"); 4725 VG_(printf)(" --hg-sanity-flags values:\n"); 4726 VG_(printf)(" 010000 after changes to " 4727 "lock-order-acquisition-graph\n"); 4728 VG_(printf)(" 001000 at memory accesses (NB: not currently used)\n"); 4729 VG_(printf)(" 000100 at mem permission setting for " 4730 "ranges >= %d bytes\n", SCE_BIGRANGE_T); 4731 VG_(printf)(" 000010 at lock/unlock events\n"); 4732 VG_(printf)(" 000001 at thread create/join events\n"); 4733 } 4734 4735 static void hg_post_clo_init ( void ) 4736 { 4737 } 4738 4739 static void hg_fini ( Int exitcode ) 4740 { 4741 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) { 4742 VG_(message)(Vg_UserMsg, 4743 "For counts of detected and suppressed errors, " 4744 "rerun with: -v\n"); 4745 } 4746 4747 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml) 4748 && HG_(clo_history_level) >= 2) { 4749 VG_(umsg)( 4750 "Use --history-level=approx or =none to gain increased speed, at\n" ); 4751 VG_(umsg)( 4752 "the cost of reduced accuracy of conflicting-access information\n"); 4753 } 4754 4755 if (SHOW_DATA_STRUCTURES) 4756 pp_everything( PP_ALL, "SK_(fini)" ); 4757 if (HG_(clo_sanity_flags)) 4758 all__sanity_check("SK_(fini)"); 4759 4760 if (VG_(clo_stats)) { 4761 4762 if (1) { 4763 VG_(printf)("\n"); 4764 HG_(ppWSUstats)( univ_tsets, "univ_tsets" ); 4765 VG_(printf)("\n"); 4766 HG_(ppWSUstats)( univ_lsets, "univ_lsets" ); 4767 VG_(printf)("\n"); 4768 HG_(ppWSUstats)( univ_laog, "univ_laog" ); 4769 } 4770 4771 //zz VG_(printf)("\n"); 4772 //zz VG_(printf)(" hbefore: %'10lu queries\n", stats__hbefore_queries); 4773 //zz VG_(printf)(" hbefore: %'10lu cache 0 hits\n", stats__hbefore_cache0s); 4774 //zz VG_(printf)(" hbefore: %'10lu cache > 0 hits\n", stats__hbefore_cacheNs); 4775 //zz VG_(printf)(" hbefore: %'10lu graph searches\n", stats__hbefore_gsearches); 4776 //zz VG_(printf)(" hbefore: %'10lu of which slow\n", 4777 //zz stats__hbefore_gsearches - stats__hbefore_gsearchFs); 4778 //zz VG_(printf)(" hbefore: %'10lu stack high water mark\n", 4779 //zz stats__hbefore_stk_hwm); 4780 //zz VG_(printf)(" hbefore: %'10lu cache invals\n", stats__hbefore_invals); 4781 //zz VG_(printf)(" hbefore: %'10lu probes\n", stats__hbefore_probes); 4782 4783 VG_(printf)("\n"); 4784 VG_(printf)(" locksets: %'8d unique lock sets\n", 4785 (Int)HG_(cardinalityWSU)( univ_lsets )); 4786 VG_(printf)(" threadsets: %'8d unique thread sets\n", 4787 (Int)HG_(cardinalityWSU)( univ_tsets )); 4788 VG_(printf)(" univ_laog: %'8d unique lock sets\n", 4789 (Int)HG_(cardinalityWSU)( univ_laog )); 4790 4791 //VG_(printf)("L(ast)L(ock) map: %'8lu inserts (%d map size)\n", 4792 // stats__ga_LL_adds, 4793 // (Int)(ga_to_lastlock ? VG_(sizeFM)( ga_to_lastlock ) : 0) ); 4794 4795 VG_(printf)(" LockN-to-P map: %'8llu queries (%llu map size)\n", 4796 HG_(stats__LockN_to_P_queries), 4797 HG_(stats__LockN_to_P_get_map_size)() ); 4798 4799 VG_(printf)("string table map: %'8llu queries (%llu map size)\n", 4800 HG_(stats__string_table_queries), 4801 HG_(stats__string_table_get_map_size)() ); 4802 VG_(printf)(" LAOG: %'8d map size\n", 4803 (Int)(laog ? VG_(sizeFM)( laog ) : 0)); 4804 VG_(printf)(" LAOG exposition: %'8d map size\n", 4805 (Int)(laog_exposition ? VG_(sizeFM)( laog_exposition ) : 0)); 4806 VG_(printf)(" locks: %'8lu acquires, " 4807 "%'lu releases\n", 4808 stats__lockN_acquires, 4809 stats__lockN_releases 4810 ); 4811 VG_(printf)(" sanity checks: %'8lu\n", stats__sanity_checks); 4812 4813 VG_(printf)("\n"); 4814 libhb_shutdown(True); 4815 } 4816 } 4817 4818 /* FIXME: move these somewhere sane */ 4819 4820 static 4821 void for_libhb__get_stacktrace ( Thr* hbt, Addr* frames, UWord nRequest ) 4822 { 4823 Thread* thr; 4824 ThreadId tid; 4825 UWord nActual; 4826 tl_assert(hbt); 4827 thr = libhb_get_Thr_opaque( hbt ); 4828 tl_assert(thr); 4829 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 4830 nActual = (UWord)VG_(get_StackTrace)( tid, frames, (UInt)nRequest, 4831 NULL, NULL, 0 ); 4832 tl_assert(nActual <= nRequest); 4833 for (; nActual < nRequest; nActual++) 4834 frames[nActual] = 0; 4835 } 4836 4837 static 4838 ExeContext* for_libhb__get_EC ( Thr* hbt ) 4839 { 4840 Thread* thr; 4841 ThreadId tid; 4842 ExeContext* ec; 4843 tl_assert(hbt); 4844 thr = libhb_get_Thr_opaque( hbt ); 4845 tl_assert(thr); 4846 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 4847 /* this will assert if tid is invalid */ 4848 ec = VG_(record_ExeContext)( tid, 0 ); 4849 return ec; 4850 } 4851 4852 4853 static void hg_pre_clo_init ( void ) 4854 { 4855 Thr* hbthr_root; 4856 4857 VG_(details_name) ("Helgrind"); 4858 VG_(details_version) (NULL); 4859 VG_(details_description) ("a thread error detector"); 4860 VG_(details_copyright_author)( 4861 "Copyright (C) 2007-2010, and GNU GPL'd, by OpenWorks LLP et al."); 4862 VG_(details_bug_reports_to) (VG_BUGS_TO); 4863 VG_(details_avg_translation_sizeB) ( 200 ); 4864 4865 VG_(basic_tool_funcs) (hg_post_clo_init, 4866 hg_instrument, 4867 hg_fini); 4868 4869 VG_(needs_core_errors) (); 4870 VG_(needs_tool_errors) (HG_(eq_Error), 4871 HG_(before_pp_Error), 4872 HG_(pp_Error), 4873 False,/*show TIDs for errors*/ 4874 HG_(update_extra), 4875 HG_(recognised_suppression), 4876 HG_(read_extra_suppression_info), 4877 HG_(error_matches_suppression), 4878 HG_(get_error_name), 4879 HG_(get_extra_suppression_info)); 4880 4881 VG_(needs_xml_output) (); 4882 4883 VG_(needs_command_line_options)(hg_process_cmd_line_option, 4884 hg_print_usage, 4885 hg_print_debug_usage); 4886 VG_(needs_client_requests) (hg_handle_client_request); 4887 4888 // FIXME? 4889 //VG_(needs_sanity_checks) (hg_cheap_sanity_check, 4890 // hg_expensive_sanity_check); 4891 4892 VG_(needs_malloc_replacement) (hg_cli__malloc, 4893 hg_cli____builtin_new, 4894 hg_cli____builtin_vec_new, 4895 hg_cli__memalign, 4896 hg_cli__calloc, 4897 hg_cli__free, 4898 hg_cli____builtin_delete, 4899 hg_cli____builtin_vec_delete, 4900 hg_cli__realloc, 4901 hg_cli_malloc_usable_size, 4902 HG_CLI__MALLOC_REDZONE_SZB ); 4903 4904 /* 21 Dec 08: disabled this; it mostly causes H to start more 4905 slowly and use significantly more memory, without very often 4906 providing useful results. The user can request to load this 4907 information manually with --read-var-info=yes. */ 4908 if (0) VG_(needs_var_info)(); /* optional */ 4909 4910 VG_(track_new_mem_startup) ( evh__new_mem_w_perms ); 4911 VG_(track_new_mem_stack_signal)( evh__new_mem_w_tid ); 4912 VG_(track_new_mem_brk) ( evh__new_mem_w_tid ); 4913 VG_(track_new_mem_mmap) ( evh__new_mem_w_perms ); 4914 VG_(track_new_mem_stack) ( evh__new_mem_stack ); 4915 4916 // FIXME: surely this isn't thread-aware 4917 VG_(track_copy_mem_remap) ( evh__copy_mem ); 4918 4919 VG_(track_change_mem_mprotect) ( evh__set_perms ); 4920 4921 VG_(track_die_mem_stack_signal)( evh__die_mem ); 4922 VG_(track_die_mem_brk) ( evh__die_mem ); 4923 VG_(track_die_mem_munmap) ( evh__die_mem ); 4924 VG_(track_die_mem_stack) ( evh__die_mem ); 4925 4926 // FIXME: what is this for? 4927 VG_(track_ban_mem_stack) (NULL); 4928 4929 VG_(track_pre_mem_read) ( evh__pre_mem_read ); 4930 VG_(track_pre_mem_read_asciiz) ( evh__pre_mem_read_asciiz ); 4931 VG_(track_pre_mem_write) ( evh__pre_mem_write ); 4932 VG_(track_post_mem_write) (NULL); 4933 4934 ///////////////// 4935 4936 VG_(track_pre_thread_ll_create)( evh__pre_thread_ll_create ); 4937 VG_(track_pre_thread_ll_exit) ( evh__pre_thread_ll_exit ); 4938 4939 VG_(track_start_client_code)( evh__start_client_code ); 4940 VG_(track_stop_client_code)( evh__stop_client_code ); 4941 4942 ///////////////////////////////////////////// 4943 hbthr_root = libhb_init( for_libhb__get_stacktrace, 4944 for_libhb__get_EC ); 4945 ///////////////////////////////////////////// 4946 4947 initialise_data_structures(hbthr_root); 4948 4949 /* Ensure that requirements for "dodgy C-as-C++ style inheritance" 4950 as described in comments at the top of pub_tool_hashtable.h, are 4951 met. Blargh. */ 4952 tl_assert( sizeof(void*) == sizeof(struct _MallocMeta*) ); 4953 tl_assert( sizeof(UWord) == sizeof(Addr) ); 4954 hg_mallocmeta_table 4955 = VG_(HT_construct)( "hg_malloc_metadata_table" ); 4956 4957 // add a callback to clean up on (threaded) fork. 4958 VG_(atfork)(NULL/*pre*/, NULL/*parent*/, evh__atfork_child/*child*/); 4959 } 4960 4961 VG_DETERMINE_INTERFACE_VERSION(hg_pre_clo_init) 4962 4963 /*--------------------------------------------------------------------*/ 4964 /*--- end hg_main.c ---*/ 4965 /*--------------------------------------------------------------------*/ 4966