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