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