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