• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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;
get_admin_threads(void)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. */
HG_(get_univ_lsets)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. */
HG_(get_admin_locks)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 
mk_Thread(Thr * hbthr)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.
mk_LockN(LockKind kind,Addr guestaddr)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. */
del_LockN(Lock * lk)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. */
lockN_acquire_writer(Lock * lk,Thread * thr)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 
lockN_acquire_reader(Lock * lk,Thread * thr)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 
lockN_release(Lock * lk,Thread * thr)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 
remove_Lock_from_locksets_of_all_owning_Threads(Lock * lk)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 
space(Int n)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 
pp_Thread(Int d,Thread * t)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 
pp_admin_threads(Int d)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 
pp_map_threads(Int d)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 
show_LockKind(LockKind lkk)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. */
pp_Lock(Int d,Lock * lk,Bool show_lock_addrdescr,Bool show_internal_data)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 
pp_admin_locks(Int d)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 
pp_map_locks(Int d)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 
pp_everything(Int flags,const HChar * caller)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 
initialise_data_structures(Thr * hbthr_root)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. */
map_threads_maybe_lookup(ThreadId coretid)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. */
map_threads_lookup(ThreadId coretid)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. */
map_threads_maybe_reverse_lookup_SLOW(Thread * thr)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. */
map_threads_reverse_lookup_SLOW(Thread * thr)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 
map_threads_delete(ThreadId coretid)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
map_locks_lookup_or_create(LockKind lkk,Addr ga,ThreadId tid)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 
map_locks_maybe_lookup(Addr ga)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 
map_locks_delete(Addr ga)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. */
thread_is_a_holder_of_Lock(Thread * thr,Lock * lk)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))
threads__sanity_check(const HChar * who)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))
locks__sanity_check(const HChar * who)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 
all_except_Locks__sanity_check(const HChar * who)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 }
all__sanity_check(const HChar * who)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') */
shadow_mem_scopy_range(Thread * thr,Addr src,Addr dst,SizeT len)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 
shadow_mem_cread_range(Thread * thr,Addr a,SizeT len)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 
shadow_mem_cwrite_range(Thread * thr,Addr a,SizeT len)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 
shadow_mem_make_New(Thread * thr,Addr a,SizeT len)994 static void shadow_mem_make_New ( Thread* thr, Addr a, SizeT len )
995 {
996    libhb_srange_new( thr->hbthr, a, len );
997 }
998 
shadow_mem_make_NoAccess_NoFX(Thread * thr,Addr aIN,SizeT len)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 
shadow_mem_make_NoAccess_AHAE(Thread * thr,Addr aIN,SizeT len)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 
shadow_mem_make_Untracked(Thread * thr,Addr aIN,SizeT len)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
evhH__post_thread_w_acquires_lock(Thread * thr,LockKind lkk,Addr lock_ga)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
evhH__post_thread_r_acquires_lock(Thread * thr,LockKind lkk,Addr lock_ga)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
evhH__pre_thread_releases_lock(Thread * thr,Addr lock_ga,Bool isRDWR)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 
evh__start_client_code(ThreadId tid,ULong nDisp)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 }
evh__stop_client_code(ThreadId tid,ULong nDisp)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 }
get_current_Thread_in_C_C(void)1405 static inline Thread* get_current_Thread_in_C_C ( void ) {
1406    return current_Thread;
1407 }
get_current_Thread(void)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
evh__new_mem(Addr a,SizeT len)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
evh__new_mem_stack(Addr a,SizeT len)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
evh__new_mem_w_tid(Addr a,SizeT len,ThreadId tid)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
evh__new_mem_w_perms(Addr a,SizeT len,Bool rr,Bool ww,Bool xx,ULong di_handle)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
evh__set_perms(Addr a,SizeT len,Bool rr,Bool ww,Bool xx)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
evh__die_mem(Addr a,SizeT len)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
evh__die_mem_munmap(Addr a,SizeT len)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
evh__untrack_mem(Addr a,SizeT len)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
evh__copy_mem(Addr src,Addr dst,SizeT len)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
evh__pre_thread_ll_create(ThreadId parent,ThreadId child)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
evh__pre_thread_ll_exit(ThreadId quit_tid)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
evh__atfork_child(ThreadId tid)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
evh__HG_PTHREAD_JOIN_POST(ThreadId stay_tid,Thread * quit_thr)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
evh__pre_mem_read(CorePart part,ThreadId tid,const HChar * s,Addr a,SizeT size)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
evh__pre_mem_read_asciiz(CorePart part,ThreadId tid,const HChar * s,Addr a)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
evh__pre_mem_write(CorePart part,ThreadId tid,const HChar * s,Addr a,SizeT size)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
evh__new_mem_heap(Addr a,SizeT len,Bool is_inited)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
evh__die_mem_heap(Addr a,SizeT len)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)
evh__mem_help_cread_1(Addr a)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)
evh__mem_help_cread_2(Addr a)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)
evh__mem_help_cread_4(Addr a)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)
evh__mem_help_cread_8(Addr a)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)
evh__mem_help_cread_N(Addr a,SizeT size)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)
evh__mem_help_cwrite_1(Addr a)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)
evh__mem_help_cwrite_2(Addr a)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)
evh__mem_help_cwrite_4(Addr a)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)
evh__mem_help_cwrite_8(Addr a)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)
evh__mem_help_cwrite_N(Addr a,SizeT size)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
evh__HG_PTHREAD_MUTEX_INIT_POST(ThreadId tid,void * mutex,Word mbRec)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
evh__HG_PTHREAD_MUTEX_DESTROY_PRE(ThreadId tid,void * mutex,Bool mutex_is_init)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 
evh__HG_PTHREAD_MUTEX_LOCK_PRE(ThreadId tid,void * mutex,Word isTryLock)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 
evh__HG_PTHREAD_MUTEX_LOCK_POST(ThreadId tid,void * mutex)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 
evh__HG_PTHREAD_MUTEX_UNLOCK_PRE(ThreadId tid,void * mutex)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 
evh__HG_PTHREAD_MUTEX_UNLOCK_POST(ThreadId tid,void * mutex)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 
evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE(ThreadId tid,void * slock)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 
evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST(ThreadId tid,void * slock)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 
evh__HG_PTHREAD_SPIN_LOCK_PRE(ThreadId tid,void * slock,Word isTryLock)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 
evh__HG_PTHREAD_SPIN_LOCK_POST(ThreadId tid,void * slock)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 
evh__HG_PTHREAD_SPIN_DESTROY_PRE(ThreadId tid,void * slock)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 
map_cond_to_CVInfo_INIT(void)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 
map_cond_to_CVInfo_lookup_or_alloc(void * cond)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 
map_cond_to_CVInfo_lookup_NO_alloc(void * cond)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 
map_cond_to_CVInfo_delete(ThreadId tid,void * cond,Bool cond_is_init)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 
evh__HG_PTHREAD_COND_SIGNAL_PRE(ThreadId tid,void * cond)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 */
evh__HG_PTHREAD_COND_WAIT_PRE(ThreadId tid,void * cond,void * mutex)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 
evh__HG_PTHREAD_COND_WAIT_POST(ThreadId tid,void * cond,void * mutex,Bool timeout)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 
evh__HG_PTHREAD_COND_INIT_POST(ThreadId tid,void * cond,void * cond_attr)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 
evh__HG_PTHREAD_COND_DESTROY_PRE(ThreadId tid,void * cond,Bool cond_is_init)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
evh__HG_PTHREAD_RWLOCK_INIT_POST(ThreadId tid,void * rwl)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
evh__HG_PTHREAD_RWLOCK_DESTROY_PRE(ThreadId tid,void * rwl)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
evh__HG_PTHREAD_RWLOCK_LOCK_PRE(ThreadId tid,void * rwl,Word isW,Word isTryLock)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
evh__HG_PTHREAD_RWLOCK_LOCK_POST(ThreadId tid,void * rwl,Word isW)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 
evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE(ThreadId tid,void * rwl)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 
evh__HG_PTHREAD_RWLOCK_UNLOCK_POST(ThreadId tid,void * rwl)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 
map_sem_to_SO_stack_INIT(void)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 
push_SO_for_sem(void * sem,SO * so)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 
mb_pop_SO_for_sem(void * sem)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 
evh__HG_POSIX_SEM_DESTROY_PRE(ThreadId tid,void * sem)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
evh__HG_POSIX_SEM_INIT_POST(ThreadId tid,void * sem,UWord value)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 
evh__HG_POSIX_SEM_POST_PRE(ThreadId tid,void * sem)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 
evh__HG_POSIX_SEM_WAIT_POST(ThreadId tid,void * sem)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 
new_Bar(void)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 
delete_Bar(Bar * bar)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 
map_barrier_to_Bar_INIT(void)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 
map_barrier_to_Bar_lookup_or_alloc(void * barrier)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 
map_barrier_to_Bar_delete(void * barrier)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 
evh__HG_PTHREAD_BARRIER_INIT_PRE(ThreadId tid,void * barrier,UWord count,UWord resizable)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 
evh__HG_PTHREAD_BARRIER_DESTROY_PRE(ThreadId tid,void * barrier)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.) */
do_barrier_cross_sync_and_empty(Bar * bar)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 
evh__HG_PTHREAD_BARRIER_WAIT_PRE(ThreadId tid,void * barrier)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 
evh__HG_PTHREAD_BARRIER_RESIZE_PRE(ThreadId tid,void * barrier,UWord newcount)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 
map_usertag_to_SO_INIT(void)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 
map_usertag_to_SO_lookup_or_alloc(UWord usertag)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 
map_usertag_to_SO_delete(UWord usertag)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
evh__HG_USERSO_SEND_PRE(ThreadId tid,UWord usertag)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
evh__HG_USERSO_RECV_POST(ThreadId tid,UWord usertag)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
evh__HG_USERSO_FORGET_ALL(ThreadId tid,UWord usertag)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 
cmp_LAOGLinkExposition(UWord llx1W,UWord llx2W)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))
laog__init(void)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 
laog__show(const HChar * who)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 
univ_laog_do_GC(void)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))
laog__add_edge(Lock * src,Lock * dst)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))
laog__del_edge(Lock * src,Lock * dst)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))
laog__succs(Lock * lk)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))
laog__preds(Lock * lk)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))
laog__sanity_check(const HChar * who)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
laog__do_dfs_from_to(Lock * src,WordSetID dsts)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))
laog__pre_thread_acquires_lock(Thread * thr,Lock * lk)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. */
UWordV_dup(UWord * words,Word words_size)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))
laog__handle_one_lock_deletion(Lock * lk)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 
new_MallocMeta(void)3988 static MallocMeta* new_MallocMeta ( void ) {
3989    MallocMeta* md = VG_(allocEltPA) (MallocMeta_poolalloc);
3990    VG_(memset)(md, 0, sizeof(MallocMeta));
3991    return md;
3992 }
delete_MallocMeta(MallocMeta * md)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
handle_alloc(ThreadId tid,SizeT szB,SizeT alignB,Bool is_zeroed)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). */
hg_cli__malloc(ThreadId tid,SizeT n)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 }
hg_cli____builtin_new(ThreadId tid,SizeT n)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 }
hg_cli____builtin_vec_new(ThreadId tid,SizeT n)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 }
hg_cli__memalign(ThreadId tid,SizeT align,SizeT n)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 }
hg_cli__calloc(ThreadId tid,SizeT nmemb,SizeT size1)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 
handle_free(ThreadId tid,void * p)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 
hg_cli__free(ThreadId tid,void * p)4094 static void hg_cli__free ( ThreadId tid, void* p ) {
4095    handle_free(tid, p);
4096 }
hg_cli____builtin_delete(ThreadId tid,void * p)4097 static void hg_cli____builtin_delete ( ThreadId tid, void* p ) {
4098    handle_free(tid, p);
4099 }
hg_cli____builtin_vec_delete(ThreadId tid,void * p)4100 static void hg_cli____builtin_vec_delete ( ThreadId tid, void* p ) {
4101    handle_free(tid, p);
4102 }
4103 
4104 
hg_cli__realloc(ThreadId tid,void * payloadV,SizeT new_size)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 
hg_cli_malloc_usable_size(ThreadId tid,void * p)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 
addr_is_in_MM_Chunk(MallocMeta * mm,Addr a)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 
HG_(mm_find_containing_block)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. */
mk_And1(IRSB * sbOut,IRExpr * arg1,IRExpr * arg2)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 
instrument_mem_access(IRSB * sbOut,IRExpr * addr,Int szB,Bool isStore,Int hWordTy_szB,Int goff_sp,IRExpr * guard)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) */
is_in_dynamic_linker_shared_object(Addr64 ga)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
hg_instrument(VgCallbackClosure * closure,IRSB * bbIn,VexGuestLayout * layout,VexGuestExtents * vge,VexArchInfo * archinfo_host,IRType gWordTy,IRType hWordTy)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 
map_pthread_t_to_Thread_INIT(void)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 
print_monitor_help(void)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 */
handle_gdb_monitor_command(ThreadId tid,HChar * req)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
hg_handle_client_request(ThreadId tid,UWord * args,UWord * ret)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 
hg_process_cmd_line_option(const HChar * arg)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 
hg_print_usage(void)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 
hg_print_debug_usage(void)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 
hg_print_stats(void)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 
hg_fini(Int exitcode)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
for_libhb__get_stacktrace(Thr * hbt,Addr * frames,UWord nRequest)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
for_libhb__get_EC(Thr * hbt)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 
hg_post_clo_init(void)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 
hg_info_location(Addr a)5384 static void hg_info_location (Addr a)
5385 {
5386    (void) HG_(get_and_pp_addrdescr) (a);
5387 }
5388 
hg_pre_clo_init(void)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