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