29
29
The GNU General Public License is contained in the file COPYING.
31
Neither the names of the U.S. Department of Energy nor the
32
University of California nor the names of its contributors may be
33
used to endorse or promote products derived from this software
34
without prior written permission.
33
// Helgrind is not 64-bit clean.
35
// For anyone wanting to understand race conditions better, this paper might
38
// S. Carr, J. Mayo and C.-K. Shene. Race Conditions: A Case Study, The
39
// Journal of Computing in Small Colleges 17(1), September 2001.
40
// http://www.cs.mtu.edu/~carr/papers/jcsc02.pdf
42
// It nicely describes several example race conditions, emphasising the
43
// fundamentals in each case.
45
37
#include "pub_tool_basics.h"
46
#include "pub_tool_threadstate.h"
47
38
#include "pub_tool_aspacemgr.h"
48
#include "pub_tool_debuginfo.h"
49
#include "pub_tool_hashtable.h"
39
#include "pub_tool_libcassert.h"
50
40
#include "pub_tool_libcbase.h"
51
#include "pub_tool_libcassert.h"
52
41
#include "pub_tool_libcprint.h"
53
#include "pub_tool_libcproc.h"
42
#include "pub_tool_mallocfree.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"
54
47
#include "pub_tool_machine.h"
55
#include "pub_tool_mallocfree.h"
56
48
#include "pub_tool_options.h"
57
#include "pub_tool_replacemalloc.h"
58
#include "pub_tool_tooliface.h"
49
#include "pub_tool_xarray.h"
50
#include "pub_tool_stacktrace.h"
60
52
#include "helgrind.h"
62
static UInt n_hg_warnings = 0;
63
static UInt n_lockorder_warnings = 0;
65
/*------------------------------------------------------------*/
66
/*--- Debug guff ---*/
67
/*------------------------------------------------------------*/
69
#define DEBUG_LOCK_TABLE 0 /* Print lock table at end */
71
#define DEBUG_MAKE_ACCESSES 0 /* Print make_access() calls */
72
#define DEBUG_LOCKS 0 /* Print lock()/unlock() calls and locksets */
73
#define DEBUG_NEW_LOCKSETS 0 /* Print new locksets when created */
74
#define DEBUG_ACCESSES 0 /* Print reads, writes */
75
#define DEBUG_MEM_LOCKSET_CHANGES 0
76
/* Print when an address's lockset
77
changes; only useful with
79
#define SLOW_ASSERTS 0 /* do expensive asserts */
80
#define DEBUG_VIRGIN_READS 0 /* Dump around address on VIRGIN reads */
83
#define TL_ASSERT(x) tl_assert(x)
88
/* heavyweight LockSet sanity checking:
90
1 == after important ops
91
2 == As 1 and also after pthread_mutex_* ops (excessively slow)
93
#define LOCKSET_SANITY 0
95
/* Rotate an unsigned quantity left */
96
#define ROTL(x, n) (((x) << (n)) | ((x) >> ((sizeof(x)*8)-(n))))
98
/*------------------------------------------------------------*/
99
/*--- Command line options ---*/
100
/*------------------------------------------------------------*/
106
} clo_execontext = EC_None;
108
static Bool clo_priv_stacks = False;
110
/*------------------------------------------------------------*/
111
/*--- Crude profiling machinery. ---*/
112
/*------------------------------------------------------------*/
114
// PPP: work out if I want this
116
#define PROF_EVENT(x)
118
#ifdef VG_PROFILE_MEMORY
120
#define N_PROF_EVENTS 150
122
static UInt event_ctr[N_PROF_EVENTS];
124
void VGE_(done_prof_mem) ( void )
54
#define HG_(str) VGAPPEND(vgHelgrind_,str)
55
#include "hg_wordfm.h"
56
#include "hg_wordset.h"
58
/*----------------------------------------------------------------*/
60
/*----------------------------------------------------------------*/
62
/* Note this needs to be compiled with -fno-strict-aliasing, since it
63
contains a whole bunch of calls to lookupFM etc which cast between
64
Word and pointer types. gcc rightly complains this breaks ANSI C
65
strict aliasing rules, at -O2. No complaints at -O, but -O2 gives
66
worthwhile performance benefits over -O.
69
// FIXME catch sync signals (SEGV, basically) and unlock BHL,
70
// if held. Otherwise a LOCK-prefixed insn which segfaults
71
// gets Helgrind into a total muddle as the BHL will not be
72
// released after the insn.
74
// FIXME what is supposed to happen to locks in memory which
75
// is relocated as a result of client realloc?
77
// FIXME put referencing ThreadId into Thread and get
78
// rid of the slow reverse mapping function.
80
// FIXME accesses to NoAccess areas: change state to Excl?
82
// FIXME report errors for accesses of NoAccess memory?
84
// FIXME pth_cond_wait/timedwait wrappers. Even if these fail,
85
// the thread still holds the lock.
87
/* ------------ Debug/trace options ------------ */
90
// shadow_mem_make_NoAccess: 29156 SMs, 1728 scanned
91
// happens_before_wrk: 1000
92
// ev__post_thread_join: 3360 SMs, 29 scanned, 252 re-Excls
93
#define SHOW_EXPENSIVE_STUFF 0
95
// 0 for silent, 1 for some stuff, 2 for lots of stuff
98
// Flags for controlling for which events sanity checking is done
99
#define SCE_THREADS (1<<0) // Sanity check at thread create/join
100
#define SCE_LOCKS (1<<1) // Sanity check at lock events
101
#define SCE_BIGRANGE (1<<2) // Sanity check at big mem range events
102
#define SCE_ACCESS (1<<3) // Sanity check at mem accesses
103
#define SCE_LAOG (1<<4) // Sanity check at significant LAOG events
104
#define SCE_HBEFORE (1<<5) // Crosscheck VTS vs Explicit h-before-graph
106
#define SCE_BIGRANGE_T 256 // big mem range minimum size
109
/* For the shadow mem cache stuff we may want more intrusive
110
checks. Unfortunately there's no almost-zero-cost way to make them
111
selectable at run time. Hence set the #if 0 to #if 1 and
112
rebuild if you want them. */
114
# define SCE_CACHELINE 1 /* do sanity-check CacheLine stuff */
115
# define inline __attribute__((noinline))
116
/* probably want to ditch -fomit-frame-pointer too */
118
# define SCE_CACHELINE 0 /* don't sanity-check CacheLine stuff */
121
static void all__sanity_check ( Char* who ); /* fwds */
123
#define HG_CLI__MALLOC_REDZONE_SZB 16 /* let's say */
125
// 0 for none, 1 for dump at end of run
126
#define SHOW_DATA_STRUCTURES 0
129
/* ------------ Command line options ------------ */
131
// 0 = no segments at all
132
// 1 = segments at thread create/join
133
// 2 = as 1 + segments at condition variable signal/broadcast/wait
134
// + segments at sem_wait/sem_post
135
static Int clo_happens_before = 2; /* default setting */
137
/* Generate .vcg output of the happens-before graph?
138
0: no 1: yes, without VTSs 2: yes, with VTSs */
139
static Int clo_gen_vcg = 0;
141
/* When comparing race errors for equality, should the race address be
142
taken into account? For users, no, but for verification purposes
143
(regtesting) this is sometimes important. */
144
static Bool clo_cmp_race_err_addrs = False;
146
/* Tracing memory accesses, so we can see what's going on.
147
clo_trace_addr is the address to monitor. clo_trace_level = 0 for
148
no tracing, 1 for summary, 2 for detailed. */
149
static Addr clo_trace_addr = 0;
150
static Int clo_trace_level = 0;
152
/* Sanity check level. This is an or-ing of
153
SCE_{THREADS,LOCKS,BIGRANGE,ACCESS,LAOG}. */
154
static Int clo_sanity_flags = 0;
156
/* This has to do with printing error messages. See comments on
157
announce_threadset() and summarise_threadset(). Perhaps it
158
should be a command line option. */
159
#define N_THREADS_TO_ANNOUNCE 5
162
/* ------------ Misc comments ------------ */
164
// FIXME: don't hardwire initial entries for root thread.
165
// Instead, let the pre_thread_ll_create handler do this.
167
// FIXME: when a SecMap is completely set via and address range
168
// setting operation to a non-ShR/M state, clear its .mbHasShared
171
/* FIXME: figure out what the real rules are for Excl->ShR/M
172
transitions w.r.t locksets.
174
Muelenfeld thesis Sec 2.2.1 p 8/9 says that
176
When another thread accesses the memory location, the lock-set
177
is initialized with all active locks and the algorithm reports
178
the next access that results in an empty lock-set.
180
What does "all active locks" mean? All locks held by the accessing
181
thread, or all locks held by the system as a whole?
183
However: Muelenfeld's enhanced Helgrind (eraser_mem_read_word)
184
seems to use simply the set of locks held by the thread causing the
185
transition into a shared state at the time of the transition:
187
*sword = SW(Vge_Shar, packLockSet(thread_locks_rd[tid]));
189
Original Eraser paper also says "all active locks".
192
// Major stuff to fix:
193
// - reader-writer locks
195
/* Thread async exit:
197
remove the map_threads entry
198
leave the Thread object in place
199
complain if holds any locks
201
unlike with Join, do not change any memory states
203
I _think_ this is correctly handled now.
206
/*----------------------------------------------------------------*/
207
/*--- Some very basic stuff ---*/
208
/*----------------------------------------------------------------*/
210
static void* hg_zalloc ( SizeT n ) {
213
p = VG_(malloc)( n );
215
VG_(memset)(p, 0, n);
218
static void hg_free ( void* p ) {
223
/* Round a up to the next multiple of N. N must be a power of 2 */
224
#define ROUNDUP(a, N) ((a + N - 1) & ~(N-1))
225
/* Round a down to the next multiple of N. N must be a power of 2 */
226
#define ROUNDDN(a, N) ((a) & ~(N-1))
228
#ifdef HAVE_BUILTIN_EXPECT
229
#define LIKELY(cond) __builtin_expect(!!(cond),1)
230
#define UNLIKELY(cond) __builtin_expect(!!(cond),0)
232
#define LIKELY(cond) (cond)
233
#define UNLIKELY(cond) (cond)
237
/*----------------------------------------------------------------*/
238
/*--- Primary data definitions ---*/
239
/*----------------------------------------------------------------*/
245
/* These are handles for thread segments. CONSTRAINTS: Must be small
246
ints numbered from zero, since 30-bit versions of them must are
247
used to represent Exclusive shadow states. Are used as keys in
248
WordFMs so must be castable to Words at the appropriate points. */
249
typedef UInt SegmentID;
252
/* These are handles for Word sets. CONSTRAINTS: must be (very) small
253
ints numbered from zero, since < 30-bit versions of them are used to
254
encode thread-sets and lock-sets in 32-bit shadow words. */
255
typedef WordSet WordSetID;
258
/* Stores information about a thread. Addresses of these also serve
259
as unique thread identifiers and so are never freed, so they should
260
be as small as possible. */
264
struct _Thread* admin;
267
WordSetID locksetA; /* WordSet of Lock* currently held by thread */
268
WordSetID locksetW; /* subset of locksetA held in w-mode */
269
SegmentID csegid; /* current thread segment for thread */
271
/* Place where parent was when this thread was created. */
272
ExeContext* created_at;
274
/* Index for generating references in error messages. */
280
/* Stores information about a lock's current state. These are
281
allocated and later freed (when the containing memory becomes
282
NoAccess). This gives a problem for the XError type, which
283
contains Lock*s. Solution is to copy any Lock which is to be
284
incorporated into an XErrors, so as to make it independent from the
285
'normal' collection of Locks, which can come and go. When the lock
286
is copied, its .magic is changed from LockN_Magic to
292
LK_mbRec=1001, /* normal mutex, possibly recursive */
293
LK_nonRec, /* normal mutex, definitely non recursive */
294
LK_rdwr /* reader-writer lock */
302
ULong unique; /* used for persistence-hashing */
303
UInt magic; /* LockN_MAGIC or LockP_MAGIC */
305
/* Place where lock first came to the attention of Helgrind. */
306
ExeContext* appeared_at;
307
/* If the lock is held, place where the lock most recently made
308
an unlocked->locked transition. Must be sync'd with .heldBy:
309
either both NULL or both non-NULL. */
310
ExeContext* acquired_at;
312
Addr guestaddr; /* Guest address of lock */
313
LockKind kind; /* what kind of lock this is */
316
WordBag* heldBy; /* bag of threads that hold this lock */
317
/* .heldBy is NULL: lock is unheld, and .heldW is meaningless
318
but arbitrarily set to False
320
.heldW is True: lock is w-held by threads in heldBy
321
.heldW is False: lock is r-held by threads in heldBy
322
Either way, heldBy may not validly be an empty Bag.
324
for LK_nonRec, r-holdings are not allowed, and w-holdings may
325
only have sizeTotal(heldBy) == 1
327
for LK_mbRec, r-holdings are not allowed, and w-holdings may
328
only have sizeUnique(heldBy) == 1
330
for LK_rdwr, w-holdings may only have sizeTotal(heldBy) == 1 */
335
/* Stores information about thread segments. .prev can be NULL only
336
when this is the first segment for the thread. .other is NULL
337
unless this segment depends on a message (create, join, signal)
338
from some other thread. Segments are never freed (!) */
342
struct _Segment* admin;
345
UInt dfsver; /* Version # for depth-first searches */
346
Thread* thr; /* The thread that I am part of */
347
struct _Segment* prev; /* The previous segment in this thread */
348
struct _Segment* other; /* Possibly a segment from some other
349
thread, which happened-before me */
350
XArray* vts; /* XArray of ScalarTS */
351
/* DEBUGGING ONLY: what does 'other' arise from?
352
c=thread creation, j=join, s=cvsignal, S=semaphore */
358
/* ------ CacheLine ------ */
360
#define N_LINE_BITS 5 /* must be >= 3 */
361
#define N_LINE_ARANGE (1 << N_LINE_BITS)
362
#define N_LINE_TREES (N_LINE_ARANGE >> 3)
366
UShort descrs[N_LINE_TREES];
367
SVal svals[N_LINE_ARANGE]; // == N_LINE_TREES * 8
371
#define TREE_DESCR_16_0 (1<<0)
372
#define TREE_DESCR_32_0 (1<<1)
373
#define TREE_DESCR_16_1 (1<<2)
374
#define TREE_DESCR_64 (1<<3)
375
#define TREE_DESCR_16_2 (1<<4)
376
#define TREE_DESCR_32_1 (1<<5)
377
#define TREE_DESCR_16_3 (1<<6)
378
#define TREE_DESCR_8_0 (1<<7)
379
#define TREE_DESCR_8_1 (1<<8)
380
#define TREE_DESCR_8_2 (1<<9)
381
#define TREE_DESCR_8_3 (1<<10)
382
#define TREE_DESCR_8_4 (1<<11)
383
#define TREE_DESCR_8_5 (1<<12)
384
#define TREE_DESCR_8_6 (1<<13)
385
#define TREE_DESCR_8_7 (1<<14)
386
#define TREE_DESCR_DTY (1<<15)
390
SVal dict[4]; /* can represent up to 4 diff values in the line */
391
UChar ix2s[N_LINE_ARANGE/4]; /* array of N_LINE_ARANGE 2-bit
393
/* if dict[0] == 0 then dict[1] is the index of the CacheLineF
396
CacheLineZ; /* compressed rep for a cache line */
401
SVal w32s[N_LINE_ARANGE];
403
CacheLineF; /* full rep for a cache line */
407
Primary map is a WordFM Addr SecMap*.
408
SecMaps cover some page-size-ish section of address space and hold
409
a compressed representation.
410
CacheLine-sized chunks of SecMaps are copied into a Cache, being
411
decompressed when moved into the cache and recompressed on the
412
way out. Because of this, the cache must operate as a writeback
413
cache, not a writethrough one.
415
/* See comments below on shadow_mem_make_NoAccess re performance
416
effects of N_SECMAP_BITS settings. On a 2.4GHz Core2,
417
starting/quitting OOo (32-bit), I have these rough numbers:
418
N_SECMAP_BITS = 11 2m23
419
N_SECMAP_BITS = 12 1m58
420
N_SECMAP_BITS = 13 1m53
422
Each SecMap must hold a power-of-2 number of CacheLines. Hence
423
N_SECMAP_BITS must >= N_LINE_BITS.
425
#define N_SECMAP_BITS 13
426
#define N_SECMAP_ARANGE (1 << N_SECMAP_BITS)
428
// # CacheLines held by a SecMap
429
#define N_SECMAP_ZLINES (N_SECMAP_ARANGE / N_LINE_ARANGE)
433
Bool mbHasLocks; /* hint: any locks in range? safe: True */
434
Bool mbHasShared; /* hint: any ShM/ShR states in range? safe: True */
435
CacheLineZ linesZ[N_SECMAP_ZLINES];
443
Int line_no; /* which Z-line are we in? */
444
Int word_no; /* inside the line, which word is current? */
448
static void initSecMapIter ( SecMapIter* itr ) {
453
/* Get the current val, and move to the next position. This is called
454
a huge amount in some programs (eg OpenOffice). Hence the
456
static UWord stats__secmap_iterator_steppings; /* fwds */
459
static Bool stepSecMapIter ( /*OUT*/SVal** pVal,
460
/*MOD*/SecMapIter* itr, SecMap* sm )
462
CacheLineZ* lineZ = NULL;
463
CacheLineF* lineF = NULL;
464
/* Either it points to a valid place, or to (-1,-1) */
465
stats__secmap_iterator_steppings++;
466
if (UNLIKELY(itr->line_no == -1)) {
467
tl_assert(itr->word_no == -1);
470
/* so now it must be a valid place in the SecMap. */
471
if (0) VG_(printf)("%p %d %d\n", sm, (Int)itr->line_no, (Int)itr->word_no);
472
tl_assert(itr->line_no >= 0 && itr->line_no < N_SECMAP_ZLINES);
473
lineZ = &sm->linesZ[itr->line_no];
474
if (UNLIKELY(lineZ->dict[0] == 0)) {
475
tl_assert(sm->linesF);
476
tl_assert(sm->linesF_size > 0);
477
tl_assert(lineZ->dict[1] >= 0);
478
tl_assert(lineZ->dict[1] < sm->linesF_size);
479
lineF = &sm->linesF[ lineZ->dict[1] ];
480
tl_assert(lineF->inUse);
481
tl_assert(itr->word_no >= 0 && itr->word_no < N_LINE_ARANGE);
482
*pVal = &lineF->w32s[itr->word_no];
484
if (itr->word_no == N_LINE_ARANGE)
487
tl_assert(itr->word_no >= 0 && itr->word_no <= 3);
488
tl_assert(lineZ->dict[itr->word_no] != 0);
489
*pVal = &lineZ->dict[itr->word_no];
491
if (itr->word_no == 4 || lineZ->dict[itr->word_no] == 0)
495
if (itr->word_no == 0) {
497
if (itr->line_no == N_SECMAP_ZLINES) {
506
/* ------ Cache ------ */
508
#define N_WAY_BITS 16
509
#define N_WAY_NENT (1 << N_WAY_BITS)
511
/* Each tag is the address of the associated CacheLine, rounded down
512
to a CacheLine address boundary. A CacheLine size must be a power
513
of 2 and must be 8 or more. Hence an easy way to initialise the
514
cache so it is empty is to set all the tag values to any value % 8
515
!= 0, eg 1. This means all queries in the cache initially miss.
516
It does however require us to detect and not writeback, any line
520
CacheLine lyns0[N_WAY_NENT];
521
Addr tags0[N_WAY_NENT];
526
/* --------- Primary data structures --------- */
528
/* Admin linked list of Threads */
529
static Thread* admin_threads = NULL;
531
/* Admin linked list of Locks */
532
static Lock* admin_locks = NULL;
534
/* Admin linked list of Segments */
535
static Segment* admin_segments = NULL;
537
/* Shadow memory primary map */
538
static WordFM* map_shmem = NULL; /* WordFM Addr SecMap* */
539
static Cache cache_shmem;
541
/* Mapping table for core ThreadIds to Thread* */
542
static Thread** map_threads = NULL; /* Array[VG_N_THREADS] of Thread* */
544
/* Mapping table for thread segments IDs to Segment* */
545
static WordFM* map_segments = NULL; /* WordFM SegmentID Segment* */
547
/* Mapping table for lock guest addresses to Lock* */
548
static WordFM* map_locks = NULL; /* WordFM LockAddr Lock* */
550
/* The word-set universes for thread sets and lock sets. */
551
static WordSetU* univ_tsets = NULL; /* sets of Thread* */
552
static WordSetU* univ_lsets = NULL; /* sets of Lock* */
553
static WordSetU* univ_laog = NULL; /* sets of Lock*, for LAOG */
555
/* never changed; we only care about its address. Is treated as if it
556
was a standard userspace lock. Also we have a Lock* describing it
557
so it can participate in lock sets in the usual way. */
558
static Int __bus_lock = 0;
559
static Lock* __bus_lock_Lock = NULL;
562
/*----------------------------------------------------------------*/
563
/*--- Simple helpers for the data structures ---*/
564
/*----------------------------------------------------------------*/
566
static UWord stats__lockN_acquires = 0;
567
static UWord stats__lockN_releases = 0;
569
static ThreadId map_threads_maybe_reverse_lookup_SLOW ( Thread* ); /*fwds*/
571
#define Thread_MAGIC 0x504fc5e5
572
#define LockN_MAGIC 0x6545b557 /* normal nonpersistent locks */
573
#define LockP_MAGIC 0x755b5456 /* persistent (copied) locks */
574
#define Segment_MAGIC 0x49e94d81
575
#define SecMap_MAGIC 0x571e58cb
577
static UWord stats__mk_Segment = 0;
579
/* --------- Constructors --------- */
581
static inline Bool is_sane_LockN ( Lock* lock ); /* fwds */
583
static Thread* mk_Thread ( SegmentID csegid ) {
585
Thread* thread = hg_zalloc( sizeof(Thread) );
586
thread->locksetA = HG_(emptyWS)( univ_lsets );
587
thread->locksetW = HG_(emptyWS)( univ_lsets );
588
thread->csegid = csegid;
589
thread->magic = Thread_MAGIC;
590
thread->created_at = NULL;
591
thread->announced = False;
592
thread->errmsg_index = indx++;
593
thread->admin = admin_threads;
594
admin_threads = thread;
597
// Make a new lock which is unlocked (hence ownerless)
598
static Lock* mk_LockN ( LockKind kind, Addr guestaddr ) {
599
static ULong unique = 0;
600
Lock* lock = hg_zalloc( sizeof(Lock) );
601
lock->admin = admin_locks;
602
lock->unique = unique++;
603
lock->magic = LockN_MAGIC;
604
lock->appeared_at = NULL;
605
lock->acquired_at = NULL;
606
lock->guestaddr = guestaddr;
610
tl_assert(is_sane_LockN(lock));
614
static Segment* mk_Segment ( Thread* thr, Segment* prev, Segment* other ) {
615
Segment* seg = hg_zalloc( sizeof(Segment) );
621
seg->other_hint = ' ';
622
seg->magic = Segment_MAGIC;
623
seg->admin = admin_segments;
624
admin_segments = seg;
629
static inline Bool is_sane_Segment ( Segment* seg ) {
630
return seg != NULL && seg->magic == Segment_MAGIC;
632
static inline Bool is_sane_Thread ( Thread* thr ) {
633
return thr != NULL && thr->magic == Thread_MAGIC;
636
static Bool is_sane_Bag_of_Threads ( WordBag* bag )
640
HG_(initIterBag)( bag );
641
while (HG_(nextIterBag)( bag, (Word*)&thr, &count )) {
642
if (count < 1) return False;
643
if (!is_sane_Thread(thr)) return False;
645
HG_(doneIterBag)( bag );
648
static Bool is_sane_Lock_BASE ( Lock* lock )
651
|| (lock->magic != LockN_MAGIC && lock->magic != LockP_MAGIC))
653
switch (lock->kind) {
654
case LK_mbRec: case LK_nonRec: case LK_rdwr: break;
655
default: return False;
657
if (lock->heldBy == NULL) {
658
if (lock->acquired_at != NULL) return False;
659
/* Unheld. We arbitrarily require heldW to be False. */
662
if (lock->acquired_at == NULL) return False;
665
/* If heldBy is non-NULL, we require it to contain at least one
667
if (HG_(isEmptyBag)(lock->heldBy))
670
/* Lock is either r- or w-held. */
671
if (!is_sane_Bag_of_Threads(lock->heldBy))
674
/* Held in write-mode */
675
if ((lock->kind == LK_nonRec || lock->kind == LK_rdwr)
676
&& !HG_(isSingletonTotalBag)(lock->heldBy))
679
/* Held in read-mode */
680
if (lock->kind != LK_rdwr) return False;
684
static inline Bool is_sane_LockP ( Lock* lock ) {
686
&& lock->magic == LockP_MAGIC
687
&& is_sane_Lock_BASE(lock);
689
static inline Bool is_sane_LockN ( Lock* lock ) {
691
&& lock->magic == LockN_MAGIC
692
&& is_sane_Lock_BASE(lock);
694
static inline Bool is_sane_LockNorP ( Lock* lock ) {
695
return is_sane_Lock_BASE(lock);
698
/* Release storage for a Lock. Also release storage in .heldBy, if
700
static void del_LockN ( Lock* lk )
702
tl_assert(is_sane_LockN(lk));
704
HG_(deleteBag)( lk->heldBy );
705
VG_(memset)(lk, 0xAA, sizeof(*lk));
709
/* Update 'lk' to reflect that 'thr' now has a write-acquisition of
710
it. This is done strictly: only combinations resulting from
711
correct program and libpthread behaviour are allowed. */
712
static void lockN_acquire_writer ( Lock* lk, Thread* thr )
714
tl_assert(is_sane_LockN(lk));
715
tl_assert(is_sane_Thread(thr));
717
stats__lockN_acquires++;
719
/* EXPOSITION only */
720
/* We need to keep recording snapshots of where the lock was
721
acquired, so as to produce better lock-order error messages. */
722
if (lk->acquired_at == NULL) {
724
tl_assert(lk->heldBy == NULL);
725
tid = map_threads_maybe_reverse_lookup_SLOW(thr);
727
= VG_(record_ExeContext(tid, 0/*first_ip_delta*/));
729
tl_assert(lk->heldBy != NULL);
731
/* end EXPOSITION only */
736
tl_assert(lk->heldBy == NULL); /* can't w-lock recursively */
737
tl_assert(!lk->heldW);
739
lk->heldBy = HG_(newBag)( hg_zalloc, hg_free );
740
HG_(addToBag)( lk->heldBy, (Word)thr );
743
if (lk->heldBy == NULL)
745
/* 2nd and subsequent locking of a lock by its owner */
746
tl_assert(lk->heldW);
747
/* assert: lk is only held by one thread .. */
748
tl_assert(HG_(sizeUniqueBag(lk->heldBy)) == 1);
749
/* assert: .. and that thread is 'thr'. */
750
tl_assert(HG_(elemBag)(lk->heldBy, (Word)thr)
751
== HG_(sizeTotalBag)(lk->heldBy));
752
HG_(addToBag)(lk->heldBy, (Word)thr);
755
tl_assert(lk->heldBy == NULL && !lk->heldW); /* must be unheld */
760
tl_assert(is_sane_LockN(lk));
763
static void lockN_acquire_reader ( Lock* lk, Thread* thr )
765
tl_assert(is_sane_LockN(lk));
766
tl_assert(is_sane_Thread(thr));
767
/* can only add reader to a reader-writer lock. */
768
tl_assert(lk->kind == LK_rdwr);
769
/* lk must be free or already r-held. */
770
tl_assert(lk->heldBy == NULL
771
|| (lk->heldBy != NULL && !lk->heldW));
773
stats__lockN_acquires++;
775
/* EXPOSITION only */
776
/* We need to keep recording snapshots of where the lock was
777
acquired, so as to produce better lock-order error messages. */
778
if (lk->acquired_at == NULL) {
780
tl_assert(lk->heldBy == NULL);
781
tid = map_threads_maybe_reverse_lookup_SLOW(thr);
783
= VG_(record_ExeContext(tid, 0/*first_ip_delta*/));
785
tl_assert(lk->heldBy != NULL);
787
/* end EXPOSITION only */
790
HG_(addToBag)(lk->heldBy, (Word)thr);
793
lk->heldBy = HG_(newBag)( hg_zalloc, hg_free );
794
HG_(addToBag)( lk->heldBy, (Word)thr );
796
tl_assert(!lk->heldW);
797
tl_assert(is_sane_LockN(lk));
800
/* Update 'lk' to reflect a release of it by 'thr'. This is done
801
strictly: only combinations resulting from correct program and
802
libpthread behaviour are allowed. */
804
static void lockN_release ( Lock* lk, Thread* thr )
807
tl_assert(is_sane_LockN(lk));
808
tl_assert(is_sane_Thread(thr));
809
/* lock must be held by someone */
810
tl_assert(lk->heldBy);
811
stats__lockN_releases++;
812
/* Remove it from the holder set */
813
b = HG_(delFromBag)(lk->heldBy, (Word)thr);
814
/* thr must actually have been a holder of lk */
817
tl_assert(lk->acquired_at);
818
if (HG_(isEmptyBag)(lk->heldBy)) {
819
HG_(deleteBag)(lk->heldBy);
822
lk->acquired_at = NULL;
824
tl_assert(is_sane_LockN(lk));
827
static void remove_Lock_from_locksets_of_all_owning_Threads( Lock* lk )
831
tl_assert(!lk->heldW);
834
/* for each thread that holds this lock do ... */
835
HG_(initIterBag)( lk->heldBy );
836
while (HG_(nextIterBag)( lk->heldBy, (Word*)&thr, NULL )) {
837
tl_assert(is_sane_Thread(thr));
838
tl_assert(HG_(elemWS)( univ_lsets,
839
thr->locksetA, (Word)lk ));
841
= HG_(delFromWS)( univ_lsets, thr->locksetA, (Word)lk );
844
tl_assert(HG_(elemWS)( univ_lsets,
845
thr->locksetW, (Word)lk ));
847
= HG_(delFromWS)( univ_lsets, thr->locksetW, (Word)lk );
850
HG_(doneIterBag)( lk->heldBy );
853
/* --------- xxxID functions --------- */
855
/* Proposal (for debugging sanity):
857
SegmentIDs from 0x1000000 .. 0x1FFFFFF (16777216)
859
All other xxxID handles are invalid.
861
static inline Bool is_sane_SegmentID ( SegmentID tseg ) {
862
return tseg >= 0x1000000 && tseg <= 0x1FFFFFF;
864
static inline Bool is_sane_ThreadId ( ThreadId coretid ) {
865
return coretid >= 0 && coretid < VG_N_THREADS;
867
static SegmentID alloc_SegmentID ( void ) {
868
static SegmentID next = 0x1000000;
869
tl_assert(is_sane_SegmentID(next));
873
/* --------- Shadow memory --------- */
875
static inline Bool is_valid_scache_tag ( Addr tag ) {
876
/* a valid tag should be naturally aligned to the start of
878
return 0 == (tag & (N_LINE_ARANGE - 1));
881
static inline Bool is_sane_SecMap ( SecMap* sm ) {
882
return sm != NULL && sm->magic == SecMap_MAGIC;
885
/* Shadow value encodings:
887
11 WordSetID:TSID_BITS WordSetID:LSID_BITS ShM thread-set lock-set
888
10 WordSetID:TSID_BITS WordSetID:LSID_BITS ShR thread-set lock-set
889
01 TSegmentID:30 Excl thread-segment
890
00 0--(20)--0 10 0000 0000 New
891
00 0--(20)--0 01 0000 0000 NoAccess
892
00 0--(20)--0 00 0000 0000 Invalid
894
TSID_BITS + LSID_BITS must equal 30.
895
The elements in thread sets are Thread*, casted to Word.
896
The elements in lock sets are Lock*, casted to Word.
899
#define N_LSID_BITS 17
900
#define N_LSID_MASK ((1 << (N_LSID_BITS)) - 1)
901
#define N_LSID_SHIFT 0
903
#define N_TSID_BITS (30 - (N_LSID_BITS))
904
#define N_TSID_MASK ((1 << (N_TSID_BITS)) - 1)
905
#define N_TSID_SHIFT (N_LSID_BITS)
907
static inline Bool is_sane_WordSetID_LSet ( WordSetID wset ) {
908
return wset >= 0 && wset <= N_LSID_MASK;
910
static inline Bool is_sane_WordSetID_TSet ( WordSetID wset ) {
911
return wset >= 0 && wset <= N_TSID_MASK;
915
__attribute__((noinline))
916
__attribute__((noreturn))
917
static void mk_SHVAL_fail ( WordSetID tset, WordSetID lset, HChar* who ) {
919
VG_(printf)("Helgrind: Fatal internal error -- cannot continue.\n");
920
VG_(printf)("Helgrind: mk_SHVAL_ShR(tset=%d,lset=%d): FAILED\n",
921
(Int)tset, (Int)lset);
922
VG_(printf)("Helgrind: max allowed tset=%d, lset=%d\n",
923
(Int)N_TSID_MASK, (Int)N_LSID_MASK);
924
VG_(printf)("Helgrind: program has too many thread "
925
"sets or lock sets to track.\n");
929
static inline SVal mk_SHVAL_ShM ( WordSetID tset, WordSetID lset ) {
930
if (LIKELY(is_sane_WordSetID_TSet(tset)
931
&& is_sane_WordSetID_LSet(lset))) {
932
return (SVal)( (3<<30) | (tset << N_TSID_SHIFT)
933
| (lset << N_LSID_SHIFT));
935
mk_SHVAL_fail(tset, lset, "mk_SHVAL_ShM");
938
static inline SVal mk_SHVAL_ShR ( WordSetID tset, WordSetID lset ) {
939
if (LIKELY(is_sane_WordSetID_TSet(tset)
940
&& is_sane_WordSetID_LSet(lset))) {
941
return (SVal)( (2<<30) | (tset << N_TSID_SHIFT)
942
| (lset << N_LSID_SHIFT) );
944
mk_SHVAL_fail(tset, lset, "mk_SHVAL_ShR");
947
static inline SVal mk_SHVAL_Excl ( SegmentID tseg ) {
948
tl_assert(is_sane_SegmentID(tseg));
949
return (SVal)( (1<<30) | tseg );
951
#define SHVAL_New ((SVal)(2<<8))
952
#define SHVAL_NoAccess ((SVal)(1<<8))
953
#define SHVAL_Invalid ((SVal)(0<<8))
955
static inline Bool is_SHVAL_ShM ( SVal w32 ) {
956
return (w32 >> 30) == 3;
958
static inline Bool is_SHVAL_ShR ( SVal w32 ) {
959
return (w32 >> 30) == 2;
961
static inline Bool is_SHVAL_Sh ( SVal w32 ) {
962
return (w32 >> 31) == 1;
964
static inline Bool is_SHVAL_Excl ( SVal w32 ) {
965
return (w32 >> 30) == 1;
967
static inline Bool is_SHVAL_New ( SVal w32 ) {
968
return w32 == SHVAL_New;
970
static inline Bool is_SHVAL_NoAccess ( SVal w32 ) {
971
return w32 == SHVAL_NoAccess;
973
static inline Bool is_SHVAL_valid ( SVal w32 ) {
974
return is_SHVAL_Excl(w32) || is_SHVAL_NoAccess(w32)
975
|| is_SHVAL_Sh(w32) || is_SHVAL_New(w32);
978
static inline SegmentID un_SHVAL_Excl ( SVal w32 ) {
979
tl_assert(is_SHVAL_Excl(w32));
980
return w32 & ~(3<<30);
982
static inline WordSetID un_SHVAL_ShR_tset ( SVal w32 ) {
983
tl_assert(is_SHVAL_ShR(w32));
984
return (w32 >> N_TSID_SHIFT) & N_TSID_MASK;
986
static inline WordSetID un_SHVAL_ShR_lset ( SVal w32 ) {
987
tl_assert(is_SHVAL_ShR(w32));
988
return (w32 >> N_LSID_SHIFT) & N_LSID_MASK;
990
static inline WordSetID un_SHVAL_ShM_tset ( SVal w32 ) {
991
tl_assert(is_SHVAL_ShM(w32));
992
return (w32 >> N_TSID_SHIFT) & N_TSID_MASK;
994
static inline WordSetID un_SHVAL_ShM_lset ( SVal w32 ) {
995
tl_assert(is_SHVAL_ShM(w32));
996
return (w32 >> N_LSID_SHIFT) & N_LSID_MASK;
998
static inline WordSetID un_SHVAL_Sh_tset ( SVal w32 ) {
999
tl_assert(is_SHVAL_Sh(w32));
1000
return (w32 >> N_TSID_SHIFT) & N_TSID_MASK;
1002
static inline WordSetID un_SHVAL_Sh_lset ( SVal w32 ) {
1003
tl_assert(is_SHVAL_Sh(w32));
1004
return (w32 >> N_LSID_SHIFT) & N_LSID_MASK;
1008
/*----------------------------------------------------------------*/
1009
/*--- Print out the primary data structures ---*/
1010
/*----------------------------------------------------------------*/
1012
static WordSetID del_BHL ( WordSetID lockset ); /* fwds */
1014
void get_ZF_by_index ( /*OUT*/CacheLineZ** zp, /*OUT*/CacheLineF** fp,
1015
SecMap* sm, Int zix ); /* fwds */
1017
Segment* map_segments_maybe_lookup ( SegmentID segid ); /* fwds */
1019
#define PP_THREADS (1<<1)
1020
#define PP_LOCKS (1<<2)
1021
#define PP_SEGMENTS (1<<3)
1022
#define PP_SHMEM_SHARED (1<<4)
1023
#define PP_ALL (PP_THREADS | PP_LOCKS | PP_SEGMENTS | PP_SHMEM_SHARED)
1026
static const Int sHOW_ADMIN = 0;
1028
static void space ( Int n )
1032
tl_assert(n >= 0 && n < 128);
1035
for (i = 0; i < n; i++)
1038
tl_assert(i < 128+1);
1039
VG_(printf)("%s", spaces);
1042
static void pp_Thread ( Int d, Thread* t )
1044
space(d+0); VG_(printf)("Thread %p {\n", t);
1046
space(d+3); VG_(printf)("admin %p\n", t->admin);
1047
space(d+3); VG_(printf)("magic 0x%x\n", (UInt)t->magic);
1049
space(d+3); VG_(printf)("locksetA %d\n", (Int)t->locksetA);
1050
space(d+3); VG_(printf)("locksetW %d\n", (Int)t->locksetW);
1051
space(d+3); VG_(printf)("csegid 0x%x\n", (UInt)t->csegid);
1052
space(d+0); VG_(printf)("}\n");
1055
static void pp_admin_threads ( Int d )
1059
for (n = 0, t = admin_threads; t; n++, t = t->admin) {
1062
space(d); VG_(printf)("admin_threads (%d records) {\n", n);
1063
for (i = 0, t = admin_threads; t; i++, t = t->admin) {
1066
VG_(printf)("admin_threads record %d of %d:\n", i, n);
1070
space(d); VG_(printf)("}\n", n);
1073
static void pp_map_threads ( Int d )
1077
space(d); VG_(printf)("map_threads ");
1079
for (i = 0; i < VG_N_THREADS; i++) {
1080
if (map_threads[i] != NULL)
1083
VG_(printf)("(%d entries) {\n", n);
1084
for (i = 0; i < VG_N_THREADS; i++) {
1085
if (map_threads[i] == NULL)
1088
VG_(printf)("coretid %d -> Thread %p\n", i, map_threads[i]);
1090
space(d); VG_(printf)("}\n");
1093
static const HChar* show_LockKind ( LockKind lkk ) {
1095
case LK_mbRec: return "mbRec";
1096
case LK_nonRec: return "nonRec";
1097
case LK_rdwr: return "rdwr";
1098
default: tl_assert(0);
1102
static void pp_Lock ( Int d, Lock* lk )
1104
space(d+0); VG_(printf)("Lock %p (ga %p) {\n", lk, lk->guestaddr);
1106
space(d+3); VG_(printf)("admin %p\n", lk->admin);
1107
space(d+3); VG_(printf)("magic 0x%x\n", (UInt)lk->magic);
1109
space(d+3); VG_(printf)("unique %llu\n", lk->unique);
1110
space(d+3); VG_(printf)("kind %s\n", show_LockKind(lk->kind));
1111
space(d+3); VG_(printf)("heldW %s\n", lk->heldW ? "yes" : "no");
1112
space(d+3); VG_(printf)("heldBy %p", lk->heldBy);
1117
HG_(initIterBag)( lk->heldBy );
1118
while (HG_(nextIterBag)( lk->heldBy, (Word*)&thr, &count ))
1119
VG_(printf)("%lu:%p ", count, thr);
1120
HG_(doneIterBag)( lk->heldBy );
1124
space(d+0); VG_(printf)("}\n");
1127
static void pp_admin_locks ( Int d )
1131
for (n = 0, lk = admin_locks; lk; n++, lk = lk->admin) {
1134
space(d); VG_(printf)("admin_locks (%d records) {\n", n);
1135
for (i = 0, lk = admin_locks; lk; i++, lk = lk->admin) {
1138
VG_(printf)("admin_locks record %d of %d:\n", i, n);
1142
space(d); VG_(printf)("}\n", n);
1145
static void pp_map_locks ( Int d )
1149
space(d); VG_(printf)("map_locks (%d entries) {\n",
1150
(Int)HG_(sizeFM)( map_locks ));
1151
HG_(initIterFM)( map_locks );
1152
while (HG_(nextIterFM)( map_locks, (Word*)&gla,
1155
VG_(printf)("guest %p -> Lock %p\n", gla, lk);
1157
HG_(doneIterFM)( map_locks );
1158
space(d); VG_(printf)("}\n");
1161
static void pp_Segment ( Int d, Segment* s )
1163
space(d+0); VG_(printf)("Segment %p {\n", s);
1165
space(d+3); VG_(printf)("admin %p\n", s->admin);
1166
space(d+3); VG_(printf)("magic 0x%x\n", (UInt)s->magic);
1168
space(d+3); VG_(printf)("dfsver %u\n", s->dfsver);
1169
space(d+3); VG_(printf)("thr %p\n", s->thr);
1170
space(d+3); VG_(printf)("prev %p\n", s->prev);
1171
space(d+3); VG_(printf)("other[%c] %p\n", s->other_hint, s->other);
1172
space(d+0); VG_(printf)("}\n");
1175
static void pp_admin_segments ( Int d )
1179
for (n = 0, s = admin_segments; s; n++, s = s->admin) {
1182
space(d); VG_(printf)("admin_segments (%d records) {\n", n);
1183
for (i = 0, s = admin_segments; s; i++, s = s->admin) {
1186
VG_(printf)("admin_segments record %d of %d:\n", i, n);
1190
space(d); VG_(printf)("}\n", n);
1193
static void pp_map_segments ( Int d )
1197
space(d); VG_(printf)("map_segments (%d entries) {\n",
1198
(Int)HG_(sizeFM)( map_segments ));
1199
HG_(initIterFM)( map_segments );
1200
while (HG_(nextIterFM)( map_segments, (Word*)&segid,
1203
VG_(printf)("segid 0x%x -> Segment %p\n", (UInt)segid, seg);
1205
HG_(doneIterFM)( map_segments );
1206
space(d); VG_(printf)("}\n");
1209
static void show_shadow_w32 ( /*OUT*/Char* buf, Int nBuf, SVal w32 )
1211
tl_assert(nBuf-1 >= 99);
1212
VG_(memset)(buf, 0, nBuf);
1213
if (is_SHVAL_ShM(w32)) {
1214
VG_(sprintf)(buf, "ShM(%u,%u)",
1215
un_SHVAL_ShM_tset(w32), un_SHVAL_ShM_lset(w32));
1218
if (is_SHVAL_ShR(w32)) {
1219
VG_(sprintf)(buf, "ShR(%u,%u)",
1220
un_SHVAL_ShR_tset(w32), un_SHVAL_ShR_lset(w32));
1223
if (is_SHVAL_Excl(w32)) {
1224
VG_(sprintf)(buf, "Excl(%u)", un_SHVAL_Excl(w32));
1227
if (is_SHVAL_New(w32)) {
1228
VG_(sprintf)(buf, "%s", "New");
1231
if (is_SHVAL_NoAccess(w32)) {
1232
VG_(sprintf)(buf, "%s", "NoAccess");
1235
VG_(sprintf)(buf, "Invalid-shadow-word(%u)", w32);
1240
void show_shadow_w32_for_user ( /*OUT*/Char* buf, Int nBuf, SVal w32 )
1242
tl_assert(nBuf-1 >= 99);
1243
VG_(memset)(buf, 0, nBuf);
1244
if (is_SHVAL_ShM(w32)) {
1245
WordSetID tset = un_SHVAL_ShM_tset(w32);
1246
WordSetID lset = del_BHL( un_SHVAL_ShM_lset(w32) );
1247
VG_(sprintf)(buf, "ShMod(#Tset=%d,#Lset=%d)",
1248
HG_(cardinalityWS)(univ_tsets, tset),
1249
HG_(cardinalityWS)(univ_lsets, lset));
1252
if (is_SHVAL_ShR(w32)) {
1253
WordSetID tset = un_SHVAL_ShR_tset(w32);
1254
WordSetID lset = del_BHL( un_SHVAL_ShR_lset(w32) );
1255
VG_(sprintf)(buf, "ShRO(#Tset=%d,#Lset=%d)",
1256
HG_(cardinalityWS)(univ_tsets, tset),
1257
HG_(cardinalityWS)(univ_lsets, lset));
1260
if (is_SHVAL_Excl(w32)) {
1261
SegmentID segid = un_SHVAL_Excl(w32);
1262
Segment* mb_seg = map_segments_maybe_lookup(segid);
1263
if (mb_seg && mb_seg->thr && is_sane_Thread(mb_seg->thr)) {
1264
VG_(sprintf)(buf, "Exclusive(thr#%d)", mb_seg->thr->errmsg_index);
1266
VG_(sprintf)(buf, "Exclusive(segid=%u)", un_SHVAL_Excl(w32));
1270
if (is_SHVAL_New(w32)) {
1271
VG_(sprintf)(buf, "%s", "New");
1274
if (is_SHVAL_NoAccess(w32)) {
1275
VG_(sprintf)(buf, "%s", "NoAccess");
1278
VG_(sprintf)(buf, "Invalid-shadow-word(%u)", w32);
1282
static void pp_SecMap_shared ( Int d, SecMap* sm, Addr ga )
1292
space(d+0); VG_(printf)("SecMap %p (ga %p) {\n", sm, (void*)ga);
1294
for (i = 0; i < N_SECMAP_ZLINES; i++) {
1295
get_ZF_by_index( &lineZ, &lineF, sm, i );
1296
space(d+3); VG_(printf)("// pp_SecMap_shared: not implemented\n");
1300
for (i = 0; i < N_SECMAP_ARANGE; i++) {
1303
if (! (is_SHVAL_ShM(w32) || is_SHVAL_ShR(w32)))
1305
space(d+3); VG_(printf)("%p -> 0x%08x ", (void*)a, w32);
1306
show_shadow_w32(buf, sizeof(buf), w32);
1307
VG_(printf)("%s\n", buf);
1311
space(d+0); VG_(printf)("}\n");
1314
static void pp_map_shmem_shared ( Int d )
1318
space(d); VG_(printf)("map_shmem_ShR_and_ShM_only {\n");
1319
HG_(initIterFM)( map_shmem );
1320
while (HG_(nextIterFM)( map_shmem, (Word*)&ga,
1322
pp_SecMap_shared( d+3, sm, ga );
1324
HG_(doneIterFM) ( map_shmem );
1325
space(d); VG_(printf)("}\n");
1328
static void pp_everything ( Int flags, Char* caller )
1332
VG_(printf)("All_Data_Structures (caller = \"%s\") {\n", caller);
1333
if (flags & PP_THREADS) {
1335
pp_admin_threads(d+3);
1337
pp_map_threads(d+3);
1339
if (flags & PP_LOCKS) {
1341
pp_admin_locks(d+3);
1345
if (flags & PP_SEGMENTS) {
1347
pp_admin_segments(d+3);
1349
pp_map_segments(d+3);
1351
if (flags & PP_SHMEM_SHARED) {
1353
pp_map_shmem_shared( d+3 );
1364
/*----------------------------------------------------------------*/
1365
/*--- Initialise the primary data structures ---*/
1366
/*----------------------------------------------------------------*/
1369
static void map_segments_add ( SegmentID segid, Segment* seg );
1370
static void shmem__invalidate_scache ( void );
1371
static void hbefore__invalidate_cache ( void );
1372
static void shmem__set_mbHasLocks ( Addr a, Bool b );
1373
static Bool shmem__get_mbHasLocks ( Addr a );
1374
static void shadow_mem_set8 ( Thread* uu_thr_acc, Addr a, SVal svNew );
1375
static XArray* singleton_VTS ( Thread* thr, UWord tym );
1377
static void initialise_data_structures ( void )
1383
/* Get everything initialised and zeroed. */
1384
tl_assert(admin_threads == NULL);
1385
tl_assert(admin_locks == NULL);
1386
tl_assert(admin_segments == NULL);
1388
tl_assert(sizeof(Addr) == sizeof(Word));
1389
tl_assert(map_shmem == NULL);
1390
map_shmem = HG_(newFM)( hg_zalloc, hg_free, NULL/*unboxed Word cmp*/);
1391
tl_assert(map_shmem != NULL);
1392
shmem__invalidate_scache();
1394
tl_assert(map_threads == NULL);
1395
map_threads = hg_zalloc( VG_N_THREADS * sizeof(Thread*) );
1396
tl_assert(map_threads != NULL);
1398
/* re <=: < on 64-bit platforms, == on 32-bit ones */
1399
tl_assert(sizeof(SegmentID) <= sizeof(Word));
1400
tl_assert(sizeof(Segment*) == sizeof(Word));
1401
tl_assert(map_segments == NULL);
1402
map_segments = HG_(newFM)( hg_zalloc, hg_free, NULL/*unboxed Word cmp*/);
1403
tl_assert(map_segments != NULL);
1404
hbefore__invalidate_cache();
1406
tl_assert(sizeof(Addr) == sizeof(Word));
1407
tl_assert(map_locks == NULL);
1408
map_locks = HG_(newFM)( hg_zalloc, hg_free, NULL/*unboxed Word cmp*/);
1409
tl_assert(map_locks != NULL);
1411
__bus_lock_Lock = mk_LockN( LK_nonRec, (Addr)&__bus_lock );
1412
tl_assert(is_sane_LockN(__bus_lock_Lock));
1413
HG_(addToFM)( map_locks, (Word)&__bus_lock, (Word)__bus_lock_Lock );
1415
tl_assert(univ_tsets == NULL);
1416
univ_tsets = HG_(newWordSetU)( hg_zalloc, hg_free, 8/*cacheSize*/ );
1417
tl_assert(univ_tsets != NULL);
1419
tl_assert(univ_lsets == NULL);
1420
univ_lsets = HG_(newWordSetU)( hg_zalloc, hg_free, 8/*cacheSize*/ );
1421
tl_assert(univ_lsets != NULL);
1423
tl_assert(univ_laog == NULL);
1424
univ_laog = HG_(newWordSetU)( hg_zalloc, hg_free, 24/*cacheSize*/ );
1425
tl_assert(univ_laog != NULL);
1427
/* Set up entries for the root thread */
1428
// FIXME: this assumes that the first real ThreadId is 1
1430
/* a segment for the new thread ... */
1431
// FIXME: code duplication in ev__post_thread_create
1432
segid = alloc_SegmentID();
1433
seg = mk_Segment( NULL, NULL, NULL );
1434
map_segments_add( segid, seg );
1436
/* a Thread for the new thread ... */
1437
thr = mk_Thread( segid );
1440
/* Give the thread a starting-off vector timestamp. */
1441
seg->vts = singleton_VTS( seg->thr, 1 );
1443
/* and bind it in the thread-map table.
1444
FIXME: assumes root ThreadId == 1. */
1445
map_threads[1] = thr;
1447
tl_assert(VG_INVALID_THREADID == 0);
1449
/* Mark the new bus lock correctly (to stop the sanity checks
1451
tl_assert( sizeof(__bus_lock) == 4 );
1452
shadow_mem_set8( NULL/*unused*/, __bus_lock_Lock->guestaddr,
1453
mk_SHVAL_Excl(segid) );
1454
shmem__set_mbHasLocks( __bus_lock_Lock->guestaddr, True );
1456
all__sanity_check("initialise_data_structures");
1460
/*----------------------------------------------------------------*/
1461
/*--- map_threads :: WordFM core-ThreadId Thread* ---*/
1462
/*----------------------------------------------------------------*/
1464
/* Doesn't assert if the relevant map_threads entry is NULL. */
1465
static Thread* map_threads_maybe_lookup ( ThreadId coretid )
1468
tl_assert( is_sane_ThreadId(coretid) );
1469
thr = map_threads[coretid];
1473
/* Asserts if the relevant map_threads entry is NULL. */
1474
static inline Thread* map_threads_lookup ( ThreadId coretid )
1477
tl_assert( is_sane_ThreadId(coretid) );
1478
thr = map_threads[coretid];
1483
/* Do a reverse lookup. Warning: POTENTIALLY SLOW. Does not assert
1484
if 'thr' is not found in map_threads. */
1485
static ThreadId map_threads_maybe_reverse_lookup_SLOW ( Thread* thr )
127
for (i = 0; i < N_PROF_EVENTS; i++) {
130
if (event_ctr[i] > 0)
131
VG_(printf)( "prof mem event %2d: %d\n", i, event_ctr[i] );
136
#define PROF_EVENT(ev) \
137
do { tl_assert((ev) >= 0 && (ev) < N_PROF_EVENTS); \
143
//static void init_prof_mem ( void ) { }
144
// void VG_(done_prof_mem) ( void ) { }
146
#define PROF_EVENT(ev) /* */
148
#endif /* VG_PROFILE_MEMORY */
150
/* Event index. If just the name of the fn is given, this means the
151
number of calls to the fn. Otherwise it is the specified event.
153
[PPP: snip event numbers...]
158
/*------------------------------------------------------------*/
159
/*--- Data defns. ---*/
160
/*------------------------------------------------------------*/
164
struct _HG_Chunk* next;
165
Addr data; /* ptr to actual block */
166
SizeT size; /* size requested */
167
ExeContext* where; /* where it was allocated */
168
ThreadId tid; /* allocating thread */
173
{ Vge_VirginInit, Vge_NonVirginInit, Vge_SegmentInit, Vge_Error }
177
// XXX: not 64-bit clean!
178
/* Should add up to 32 to fit in one word */
179
#define OTHER_BITS 30
182
#define ESEC_MAP_WORDS 16384 /* Words per secondary map */
184
/* This is for indicating that a memory block has been initialised but not
185
* really directly by a particular thread... (eg. text/data initialised
186
* automatically at startup).
187
* Must be different to virgin_word.other */
188
#define TID_INDICATING_NONVIRGIN 1
190
/* Magic packed TLS used for error suppression; if word state is Excl
191
and tid is this, then it means all access are OK without changing
192
state and without raising any more errors */
193
#define TLSP_INDICATING_ALL ((1 << OTHER_BITS) - 1)
195
/* Number of entries must fit in STATE_BITS bits */
196
typedef enum { Vge_Virgin, Vge_Excl, Vge_Shar, Vge_SharMod } pth_state;
198
static inline const Char *pp_state(pth_state st)
203
case Vge_Virgin: ret = "virgin"; break;
204
case Vge_Excl: ret = "exclusive"; break;
205
case Vge_Shar: ret = "shared RO"; break;
206
case Vge_SharMod: ret = "shared RW"; break;
207
default: ret = "???";
214
/* gcc arranges this bitfield with state in the 2LSB and other
215
in the 30MSB, which is what we want */
216
UInt state:STATE_BITS;
217
UInt other:OTHER_BITS;
220
#define SW(st, other) ((shadow_word) { st, other })
224
shadow_word swords[ESEC_MAP_WORDS];
228
static ESecMap* primary_map[ 65536 ];
229
static ESecMap distinguished_secondary_map;
231
static const shadow_word virgin_sword = SW(Vge_Virgin, 0);
232
static const shadow_word error_sword = SW(Vge_Excl, TLSP_INDICATING_ALL);
234
#define VGE_IS_DISTINGUISHED_SM(smap) \
235
((smap) == &distinguished_secondary_map)
237
#define ENSURE_MAPPABLE(addr,caller) \
239
if (VGE_IS_DISTINGUISHED_SM(primary_map[(addr) >> 16])) { \
240
primary_map[(addr) >> 16] = alloc_secondary_map(caller); \
241
/*VG_(printf)("new 2map because of %p\n", addr);*/ \
246
/* Parallel map which contains execution contexts when words last
247
changed state (if required) */
249
typedef struct EC_IP {
254
UInt state:STATE_BITS;
255
UInt tls:OTHER_BITS; /* packed TLS */
258
#define NULL_EC_IP ((EC_IP){ { 0 }, 0, 0})
260
#define IP(ip, prev, tls) ((EC_IP) { (union u_ec_ip)(ip), (prev).state, packTLS(tls) })
261
#define EC(ec, prev, tls) ((EC_IP) { (union u_ec_ip)(ec), (prev).state, packTLS(tls) })
263
static inline UInt packEC(ExeContext *ec)
265
TL_ASSERT(((UWord)ec & ((1 << STATE_BITS)-1)) == 0);
266
return ((UWord)ec) >> STATE_BITS;
269
/* Lose 2 LSB of IP */
270
static inline UInt packIP(Addr ip)
272
return ip >> STATE_BITS;
275
static inline Addr unpackIP(UInt i)
277
return (Addr)(i << STATE_BITS);
281
EC_IP execontext[ESEC_MAP_WORDS];
284
static ExeContextMap** execontext_map;
286
static inline void setExeContext(Addr a, EC_IP ec)
288
UInt idx = (a >> 16) & 0xffff;
289
UInt off = (a >> 2) & 0x3fff;
291
if (execontext_map[idx] == NULL) {
292
execontext_map[idx] = VG_(malloc)(sizeof(ExeContextMap));
293
VG_(memset)(execontext_map[idx], 0, sizeof(ExeContextMap));
296
execontext_map[idx]->execontext[off] = ec;
299
static inline EC_IP getExeContext(Addr a)
301
UInt idx = (a >> 16) & 0xffff;
302
UInt off = (a >> 2) & 0x3fff;
303
EC_IP ec = NULL_EC_IP;
305
if (execontext_map[idx] != NULL)
306
ec = execontext_map[idx]->execontext[off];
311
/*------------------------------------------------------------*/
312
/*--- Thread lifetime segments ---*/
313
/*------------------------------------------------------------*/
316
* This mechanism deals with the common case of a parent thread
317
* creating a structure for a child thread, and then passing ownership
318
* of the structure to that thread. It similarly copes with a child
319
* thread passing information back to another thread waiting to join
322
* Each thread's lifetime can be partitioned into segments. Those
323
* segments are arranged to form an interference graph which indicates
324
* whether two thread lifetime segments can possibly be concurrent.
325
* If not, then memory with is exclusively accessed by one TLS can be
326
* passed on to another TLS without an error occurring, and without
327
* moving it from Excl state.
329
* At present this only considers thread creation and join as
330
* synchronisation events for creating new lifetime segments, but
331
* others may be possible (like mutex operations).
334
typedef struct _ThreadLifeSeg ThreadLifeSeg;
336
struct _ThreadLifeSeg {
338
ThreadLifeSeg *prior[2]; /* Previous lifetime segments */
339
UInt refcount; /* Number of memory locations pointing here */
340
UInt mark; /* mark used for graph traversal */
341
ThreadLifeSeg *next; /* list of all TLS */
344
static ThreadLifeSeg *all_tls;
345
static UInt tls_since_gc;
346
#define TLS_SINCE_GC 10000
348
/* current mark used for TLS graph traversal */
351
static ThreadLifeSeg *thread_seg[VG_N_THREADS];
354
static void tls_gc(void)
356
/* XXX later. Walk through all TLSs and look for ones with 0
357
refcount and remove them from the structure and free them.
358
Could probably get rid of ThreadLifeSeg.refcount and simply use
359
mark-sweep from the shadow table. */
360
VG_(printf)("WRITEME: TLS GC\n");
363
static void newTLS(ThreadId tid)
365
static const Bool debug = False;
369
if (thread_seg[tid] == NULL) {
370
tls = VG_(malloc)(sizeof(*tls));
372
tls->prior[0] = tls->prior[1] = NULL;
374
tls->mark = tlsmark-1;
380
thread_seg[tid] = tls;
384
/* Previous TLS was unused, so just recycle */
385
if (thread_seg[tid]->refcount == 0) {
387
VG_(printf)("newTLS; recycling TLS %p for tid %u\n",
388
thread_seg[tid], tid);
392
/* Use existing TLS for this tid as a prior for new TLS */
393
tls = VG_(malloc)(sizeof(*tls));
395
tls->prior[0] = thread_seg[tid];
396
tls->prior[1] = NULL;
398
tls->mark = tlsmark-1;
402
if (++tls_since_gc > TLS_SINCE_GC) {
408
VG_(printf)("newTLS: made new TLS %p for tid %u (prior %p(%u))\n",
409
tls, tid, tls->prior[0], tls->prior[0]->tid);
411
thread_seg[tid] = tls;
414
/* clear out a TLS for a thread that's died */
415
static void clearTLS(ThreadId tid)
419
thread_seg[tid]->prior[0] = NULL;
420
thread_seg[tid]->prior[1] = NULL;
423
static void addPriorTLS(ThreadId tid, ThreadId prior)
425
static const Bool debug = False;
426
ThreadLifeSeg *tls = thread_seg[tid];
429
VG_(printf)("making TLS %p(%u) prior to TLS %p(%u)\n",
430
thread_seg[prior], prior, tls, tid);
432
tl_assert(thread_seg[tid] != NULL);
433
tl_assert(thread_seg[prior] != NULL);
435
if (tls->prior[0] == NULL)
436
tls->prior[0] = thread_seg[prior];
438
tl_assert(tls->prior[1] == NULL);
439
tls->prior[1] = thread_seg[prior];
443
static Bool isPrior(const ThreadLifeSeg *t, const ThreadLifeSeg *prior)
445
if (t == NULL || t->mark == tlsmark)
451
((ThreadLifeSeg *)t)->mark = tlsmark;
453
return isPrior(t->prior[0], prior) || isPrior(t->prior[1], prior);
456
/* Return True if prior is definitely not concurrent with tls */
457
static Bool tlsIsDisjoint(const ThreadLifeSeg *tls,
458
const ThreadLifeSeg *prior)
460
tlsmark++; /* new traversal mark */
462
return isPrior(tls, prior);
465
static inline UInt packTLS(ThreadLifeSeg *tls)
467
TL_ASSERT(((UWord)tls & ((1 << STATE_BITS)-1)) == 0);
468
return ((UWord)tls) >> STATE_BITS;
471
static inline ThreadLifeSeg *unpackTLS(UInt i)
473
/* HACK ALERT -- DUBIOUS CAST */
474
return (ThreadLifeSeg *)ULong_to_Ptr(i << STATE_BITS);
477
/*------------------------------------------------------------*/
478
/*--- Low-level support for memory tracking. ---*/
479
/*------------------------------------------------------------*/
482
All reads and writes are recorded in the memory map, which
483
records the state of all memory in the process. The memory map is
484
organised like that for normal Valgrind, except each that everything
485
is done at word-level instead of byte-level, and each word has only
486
one word of shadow (instead of 36 bits).
488
As for normal Valgrind there is a distinguished secondary map. But we're
489
working at word-granularity, so it has 16k word entries instead of 64k byte
490
entries. Lookup is done as follows:
492
bits 31..16: primary map lookup
493
bits 15.. 2: secondary map lookup
498
/*------------------------------------------------------------*/
499
/*--- Basic bitmap management, reading and writing. ---*/
500
/*------------------------------------------------------------*/
502
/* Allocate and initialise a secondary map, marking all words as virgin. */
504
/* Just a value that isn't a real pointer */
505
#define SEC_MAP_ACCESS (shadow_word*)0x99
509
ESecMap* alloc_secondary_map ( __attribute__ ((unused)) Char* caller )
513
//PROF_EVENT(10); PPP
515
// Mark all words as virgin.
516
map = (ESecMap *)VG_(am_shadow_alloc)(sizeof(ESecMap));
518
VG_(out_of_memory_NORETURN)( "helgrind:allocate new ESecMap",
520
for (i = 0; i < ESEC_MAP_WORDS; i++)
521
map->swords[i] = virgin_sword;
527
/* Set a word. The byte give by 'a' could be anywhere in the word -- the whole
529
static /* __inline__ */
530
void set_sword ( Addr a, shadow_word sword )
535
//PROF_EVENT(23); PPP
536
ENSURE_MAPPABLE(a, "VGE_(set_sword)");
538
/* Use bits 31..16 for primary, 15..2 for secondary lookup */
539
sm = primary_map[a >> 16];
540
tl_assert(sm != &distinguished_secondary_map);
541
oldsw = &sm->swords[(a & 0xFFFC) >> 2];
542
if (oldsw->state == Vge_Excl && oldsw->other != TLSP_INDICATING_ALL) {
543
ThreadLifeSeg *tls = unpackTLS(oldsw->other);
547
if (sword.state == Vge_Excl && sword.other != TLSP_INDICATING_ALL) {
548
ThreadLifeSeg *tls = unpackTLS(sword.other);
552
sm->swords[(a & 0xFFFC) >> 2] = sword;
554
if (VGE_IS_DISTINGUISHED_SM(sm)) {
555
VG_(printf)("wrote to distinguished 2ndary map! 0x%x\n", a);
556
// XXX: may be legit, but I want to know when it happens --njn
557
VG_(tool_panic)("wrote to distinguished 2ndary map!");
563
shadow_word* get_sword_addr ( Addr a )
565
/* Use bits 31..16 for primary, 15..2 for secondary lookup */
566
ESecMap* sm = primary_map[a >> 16];
567
UInt sm_off = (a & 0xFFFC) >> 2;
569
if (VGE_IS_DISTINGUISHED_SM(sm)) {
570
VG_(printf)("accessed distinguished 2ndary map! 0x%x\n", a);
571
// XXX: may be legit, but I want to know when it happens --njn
572
//VG_(tool_panic)("accessed distinguished 2ndary map!");
573
return SEC_MAP_ACCESS;
576
//PROF_EVENT(21); PPP
577
return & (sm->swords[sm_off]);
581
// SSS: rename these so they're not so similar to memcheck, unless it's
582
// appropriate of course
585
void init_virgin_sword(Addr a)
587
if (clo_execontext != EC_None)
588
setExeContext(a, NULL_EC_IP);
589
set_sword(a, virgin_sword);
593
void init_error_sword(Addr a)
595
set_sword(a, error_sword);
599
void init_nonvirgin_sword(Addr a)
605
// The tid must be passed in here now; this requires more events to be
606
// given the tid in the first place.
608
//tid = VG_(get_current_or_recent_tid)();
609
VG_(message)(Vg_DebugMsg, "tid needs to be passed in here");
1488
tl_assert(is_sane_Thread(thr));
1489
/* Check nobody used the invalid-threadid slot */
1490
tl_assert(VG_INVALID_THREADID >= 0 && VG_INVALID_THREADID < VG_N_THREADS);
1491
tl_assert(map_threads[VG_INVALID_THREADID] == NULL);
1492
for (i = 0; i < VG_N_THREADS; i++) {
1493
if (i != VG_INVALID_THREADID && map_threads[i] == thr)
1496
return VG_INVALID_THREADID;
1499
/* Do a reverse lookup. Warning: POTENTIALLY SLOW. Asserts if 'thr'
1500
is not found in map_threads. */
1501
static ThreadId map_threads_reverse_lookup_SLOW ( Thread* thr )
1503
ThreadId tid = map_threads_maybe_reverse_lookup_SLOW( thr );
612
1504
tl_assert(tid != VG_INVALID_THREADID);
613
tls = thread_seg[tid];
615
sword = SW(Vge_Excl, packTLS(tls));
620
/* In this case, we treat it for Helgrind's sake like virgin (it hasn't
621
* been inited by a particular thread, it's just done automatically upon
622
* startup), but we mark its .state specially so it doesn't look like an
625
void init_magically_inited_sword(Addr a)
629
sword = SW(Vge_Virgin, TID_INDICATING_NONVIRGIN);
631
set_sword(a, virgin_sword);
635
/*------------------------------------------------------------*/
636
/*--- Implementation of lock sets. ---*/
637
/*------------------------------------------------------------*/
639
typedef struct _Mutex Mutex; /* forward decl */
640
typedef struct _LockSet LockSet;
642
typedef enum MutexState {
643
MxUnknown, /* don't know */
644
MxUnlocked, /* unlocked */
645
MxLocked, /* locked */
646
MxDead /* destroyed */
653
MutexState state; /* mutex state */
654
ThreadId tid; /* owner */
655
ExeContext *location; /* where the last change happened */
657
const LockSet *lockdep; /* set of locks we depend on */
658
UInt mark; /* mark for graph traversal */
661
static inline Int mutex_cmp(const Mutex *a, const Mutex *b)
663
return a->mutexp - b->mutexp;
667
Int setsize; /* number of members */
668
UInt hash; /* hash code */
669
LockSet *next; /* next in hash chain */
670
const Mutex *mutex[0]; /* locks */
673
static const LockSet *emptyset;
675
/* Each one is an index into the lockset table. */
676
static const LockSet *thread_locks[VG_N_THREADS];
678
#define LOCKSET_HASH_SZ 1021
680
static LockSet *lockset_hash[LOCKSET_HASH_SZ];
682
/* Pack and unpack a LockSet pointer into shadow_word.other */
683
static inline UInt packLockSet(const LockSet *p)
687
TL_ASSERT(((UWord)p & ((1 << STATE_BITS)-1)) == 0);
688
id = ((UWord)p) >> STATE_BITS;
693
static inline const LockSet *unpackLockSet(UInt id)
695
/* HACK ALERT -- DUBIOUS CAST */
696
return (LockSet *)ULong_to_Ptr(id << STATE_BITS);
1508
static void map_threads_delete ( ThreadId coretid )
1511
tl_assert(coretid != 0);
1512
tl_assert( is_sane_ThreadId(coretid) );
1513
thr = map_threads[coretid];
1515
map_threads[coretid] = NULL;
1519
/*----------------------------------------------------------------*/
1520
/*--- map_locks :: WordFM guest-Addr-of-lock Lock* ---*/
1521
/*----------------------------------------------------------------*/
1523
/* Make sure there is a lock table entry for the given (lock) guest
1524
address. If not, create one of the stated 'kind' in unheld state.
1525
In any case, return the address of the existing or new Lock. */
700
void pp_LockSet(const LockSet* p)
704
for(i = 0; i < p->setsize; i++) {
705
const Mutex *mx = p->mutex[i];
707
VG_(printf)("%p%(y ", mx->mutexp, mx->mutexp);
713
static void print_LockSet(const Char *s, const LockSet *ls)
715
VG_(printf)("%s: ", s);
719
/* Compute the hash of a LockSet */
720
static UInt hash_LockSet_w_wo(const LockSet *ls,
722
const Mutex *without)
725
UInt hash = ls->setsize + (with != NULL) - (without != NULL);
727
tl_assert(with == NULL || with != without);
729
for(i = 0; with != NULL || i < ls->setsize; i++) {
730
const Mutex *mx = i >= ls->setsize ? NULL : ls->mutex[i];
732
if (without && mutex_cmp(without, mx) == 0)
735
if (with && (mx == NULL || mutex_cmp(with, mx) < 0)) {
1527
Lock* map_locks_lookup_or_create ( LockKind lkk, Addr ga, ThreadId tid )
1530
Lock* oldlock = NULL;
1531
tl_assert(is_sane_ThreadId(tid));
1532
found = HG_(lookupFM)( map_locks,
1533
NULL, (Word*)&oldlock, (Word)ga );
1535
Lock* lock = mk_LockN(lkk, ga);
1536
lock->appeared_at = VG_(record_ExeContext)( tid, 0 );
1537
tl_assert(is_sane_LockN(lock));
1538
HG_(addToFM)( map_locks, (Word)ga, (Word)lock );
1539
tl_assert(oldlock == NULL);
1540
// mark the relevant secondary map has .mbHasLocks
1541
shmem__set_mbHasLocks( ga, True );
1544
tl_assert(oldlock != NULL);
1545
tl_assert(is_sane_LockN(oldlock));
1546
tl_assert(oldlock->guestaddr == ga);
1547
// check the relevant secondary map has .mbHasLocks?
1548
tl_assert(shmem__get_mbHasLocks(ga) == True);
1553
static Lock* map_locks_maybe_lookup ( Addr ga )
1557
found = HG_(lookupFM)( map_locks, NULL, (Word*)&lk, (Word)ga );
1558
tl_assert(found ? lk != NULL : lk == NULL);
1560
// check the relevant secondary map has .mbHasLocks?
1561
tl_assert(shmem__get_mbHasLocks(ga) == True);
1566
static void map_locks_delete ( Addr ga )
1570
HG_(delFromFM)( map_locks,
1571
(Word*)&ga2, (Word*)&lk, (Word)ga );
1572
/* delFromFM produces the val which is being deleted, if it is
1573
found. So assert it is non-null; that in effect asserts that we
1574
are deleting a (ga, Lock) pair which actually exists. */
1575
tl_assert(lk != NULL);
1576
tl_assert(ga2 == ga);
1580
/*----------------------------------------------------------------*/
1581
/*--- map_segments :: WordFM SegmentID Segment* ---*/
1582
/*--- the DAG of thread segments ---*/
1583
/*----------------------------------------------------------------*/
1585
static void segments__generate_vcg ( void ); /* fwds */
1587
/*--------------- SegmentID to Segment* maps ---------------*/
1589
static Segment* map_segments_lookup ( SegmentID segid )
1592
Segment* seg = NULL;
1593
tl_assert( is_sane_SegmentID(segid) );
1594
found = HG_(lookupFM)( map_segments,
1595
NULL, (Word*)&seg, (Word)segid );
1597
tl_assert(seg != NULL);
1601
static Segment* map_segments_maybe_lookup ( SegmentID segid )
1604
Segment* seg = NULL;
1605
tl_assert( is_sane_SegmentID(segid) );
1606
found = HG_(lookupFM)( map_segments,
1607
NULL, (Word*)&seg, (Word)segid );
1608
if (!found) tl_assert(seg == NULL);
1612
static void map_segments_add ( SegmentID segid, Segment* seg )
1614
/* This is a bit inefficient. Oh well. */
1615
tl_assert( !HG_(lookupFM)( map_segments, NULL, NULL, segid ));
1616
HG_(addToFM)( map_segments, (Word)segid, (Word)seg );
1619
/*--------------- to do with Vector Timestamps ---------------*/
1621
/* Scalar Timestamp */
1629
/* Vector Timestamp = XArray* ScalarTS */
1631
static Bool is_sane_VTS ( XArray* vts )
1634
ScalarTS *st1, *st2;
1635
n = VG_(sizeXA)( vts );
1637
for (i = 0; i < n-1; i++) {
1638
st1 = VG_(indexXA)( vts, i );
1639
st2 = VG_(indexXA)( vts, i+1 );
1640
if (st1->thr >= st2->thr)
1642
if (st1->tym == 0 || st2->tym == 0)
741
hash = ROTL(hash, 17);
745
return hash % LOCKSET_HASH_SZ;
748
static inline UInt hash_LockSet_with(const LockSet *ls, const Mutex *with)
750
UInt hash = hash_LockSet_w_wo(ls, with, NULL);
753
VG_(printf)("hash_with %p+%p -> %d\n", ls, with->mutexp, hash);
758
static inline UInt hash_LockSet_without(const LockSet *ls, const Mutex *without)
760
UInt hash = hash_LockSet_w_wo(ls, NULL, without);
763
VG_(printf)("hash_with %p-%p -> %d\n", ls, without->mutexp, hash);
768
static inline UInt hash_LockSet(const LockSet *ls)
770
UInt hash = hash_LockSet_w_wo(ls, NULL, NULL);
773
VG_(printf)("hash %p -> %d\n", ls, hash);
779
Bool structural_eq_LockSet(const LockSet* a, const LockSet* b)
785
if (a->setsize != b->setsize)
788
for(i = 0; i < a->setsize; i++) {
789
if (mutex_cmp(a->mutex[i], b->mutex[i]) != 0)
797
/* Tricky: equivalent to (compare(insert(missing_elem, a), b)), but
798
* doesn't do the insertion. Returns True if they match.
801
weird_LockSet_equals(const LockSet* a, const LockSet* b,
802
const Mutex *missing_mutex)
804
static const Bool debug = False;
807
/* Idea is to try and match each element of b against either an
808
element of a, or missing_mutex. */
811
print_LockSet("weird_LockSet_equals a", a);
812
print_LockSet(" b", b);
813
VG_(printf)( " missing: %p%(y\n",
814
missing_mutex->mutexp, missing_mutex->mutexp);
817
if ((a->setsize + 1) != b->setsize) {
819
VG_(printf)(" fastpath length mismatch -> 0\n");
823
/* There are three phases to this compare:
824
1 the section from the start of a up to missing_mutex
825
2 missing mutex itself
826
3 the section after missing_mutex to the end of a
832
/* 1: up to missing_mutex */
833
for(; ia < a->setsize && mutex_cmp(a->mutex[ia], missing_mutex) < 0; ia++, ib++) {
835
print_LockSet(" 1:a", a);
836
print_LockSet(" 1:b", b);
838
if (ib == b->setsize || mutex_cmp(a->mutex[ia], b->mutex[ib]) != 0)
842
/* 2: missing_mutex itself */
844
VG_(printf)( " 2:missing: %p%(y\n",
845
missing_mutex->mutexp, missing_mutex->mutexp);
846
print_LockSet(" 2: b", b);
849
tl_assert(ia == a->setsize || mutex_cmp(a->mutex[ia], missing_mutex) >= 0);
851
if (ib == b->setsize || mutex_cmp(missing_mutex, b->mutex[ib]) != 0)
856
/* 3: after missing_mutex to end */
858
for(; ia < a->setsize && ib < b->setsize; ia++, ib++) {
860
print_LockSet(" 3:a", a);
861
print_LockSet(" 3:b", b);
863
if (mutex_cmp(a->mutex[ia], b->mutex[ib]) != 0)
868
VG_(printf)(" ia=%d ib=%d --> %d\n", ia, ib, ia == a->setsize && ib == b->setsize);
870
return ia == a->setsize && ib == b->setsize;
875
static const LockSet *lookup_LockSet(const LockSet *set)
877
UInt bucket = set->hash;
880
for(ret = lockset_hash[bucket]; ret != NULL; ret = ret->next)
881
if (set == ret || structural_eq_LockSet(set, ret))
887
static const LockSet *lookup_LockSet_with(const LockSet *set, Mutex *mutex)
889
UInt bucket = hash_LockSet_with(set, mutex);
892
for(ret = lockset_hash[bucket]; ret != NULL; ret = ret->next)
893
if (weird_LockSet_equals(set, ret, mutex))
899
static const LockSet *lookup_LockSet_without(const LockSet *set, Mutex *mutex)
901
UInt bucket = hash_LockSet_without(set, mutex);
904
for(ret = lockset_hash[bucket]; ret != NULL; ret = ret->next)
905
if (weird_LockSet_equals(ret, set, mutex))
911
static void insert_LockSet(LockSet *set)
913
UInt hash = hash_LockSet(set);
917
tl_assert(lookup_LockSet(set) == NULL);
919
set->next = lockset_hash[hash];
920
lockset_hash[hash] = set;
924
LockSet *alloc_LockSet(UInt setsize)
926
LockSet *ret = VG_(malloc)(sizeof(*ret) + sizeof(Mutex *) * setsize);
927
ret->setsize = setsize;
932
void free_LockSet(LockSet *p)
934
/* assert: not present in hash */
939
void pp_all_LockSets ( void )
945
for (i = 0; i < LOCKSET_HASH_SZ; i++) {
946
const LockSet *ls = lockset_hash[i];
949
for(; ls != NULL; ls = ls->next) {
952
VG_(printf)("[%4d] = ", i);
962
VG_(printf)("%d distinct LockSets in %d buckets\n", sets, buckets);
965
static inline Bool isempty(const LockSet *ls)
967
return ls == NULL || ls->setsize == 0;
970
static Bool ismember(const LockSet *ls, const Mutex *mx)
974
/* XXX use binary search */
975
for(i = 0; i < ls->setsize; i++)
976
if (mutex_cmp(mx, ls->mutex[i]) == 0)
983
- all locksets are unique
984
- each set is an array in strictly increasing order of mutex addr
987
void sanity_check_locksets ( const Char* caller )
993
for(i = 0; i < LOCKSET_HASH_SZ; i++) {
995
for(ls = lockset_hash[i]; ls != NULL; ls = ls->next) {
999
if (hash_LockSet(ls) != ls->hash) {
1000
badness = "mismatched hash";
1003
if (ls->hash != (UInt)i) {
1004
badness = "wrong bucket";
1007
if (lookup_LockSet(ls) != ls) {
1008
badness = "non-unique set";
1012
prev = ls->mutex[0];
1013
for(j = 1; j < ls->setsize; j++) {
1014
if (mutex_cmp(prev, ls->mutex[j]) >= 0) {
1015
badness = "mutexes out of order";
1024
VG_(printf)("sanity_check_locksets: "
1025
"i = %d, ls=%p badness = %s, caller = %s\n",
1026
i, ls, badness, caller);
1028
VG_(tool_panic)("sanity_check_locksets");
1032
LockSet *add_LockSet(const LockSet *ls, const Mutex *mx)
1034
static const Bool debug = False;
1035
LockSet *ret = NULL;
1038
if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1039
VG_(printf)("add-IN mutex %p%(y\n", mx->mutexp, mx->mutexp);
1040
print_LockSet("add-IN", ls);
1043
if (debug || LOCKSET_SANITY)
1044
sanity_check_locksets("add-IN");
1046
tl_assert(!ismember(ls, mx));
1048
ret = alloc_LockSet(ls->setsize+1);
1050
for(i = j = 0; i < ls->setsize; i++) {
1052
VG_(printf)("i=%d j=%d ls->mutex[i]=%p mx=%p\n",
1053
i, j, ls->mutex[i]->mutexp, mx ? mx->mutexp : 0);
1054
if (mx && mutex_cmp(mx, ls->mutex[i]) < 0) {
1055
ret->mutex[j++] = mx;
1058
ret->mutex[j++] = ls->mutex[i];
1061
/* not added in loop - must be after */
1063
ret->mutex[j++] = mx;
1065
tl_assert(j == ret->setsize);
1067
if (debug || LOCKSET_SANITY) {
1068
print_LockSet("add-OUT", ret);
1069
sanity_check_locksets("add-OUT");
1074
/* Builds ls with mx removed. mx should actually be in ls!
1075
(a checked assertion). Resulting set should not already
1076
exist in the table (unchecked).
1079
LockSet *remove_LockSet ( const LockSet *ls, const Mutex *mx )
1081
static const Bool debug = False;
1082
LockSet *ret = NULL;
1085
if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1086
print_LockSet("remove-IN", ls);
1089
if (debug || LOCKSET_SANITY)
1090
sanity_check_locksets("remove-IN");
1092
tl_assert(ismember(ls, mx));
1094
ret = alloc_LockSet(ls->setsize-1);
1096
for(i = j = 0; i < ls->setsize; i++) {
1097
if (mutex_cmp(ls->mutex[i], mx) == 0)
1099
ret->mutex[j++] = ls->mutex[i];
1102
tl_assert(j == ret->setsize);
1104
if (debug || LOCKSET_SANITY) {
1105
print_LockSet("remove-OUT", ret);
1106
sanity_check_locksets("remove-OUT");
1112
/* Builds the intersection, and then unbuilds it if it's already in the table.
1114
static const LockSet *_intersect(const LockSet *a, const LockSet *b)
1116
static const Bool debug = False;
1121
const LockSet *found;
1123
if (debug || LOCKSET_SANITY)
1124
sanity_check_locksets("intersect-IN");
1126
if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1127
print_LockSet("intersect a", a);
1128
print_LockSet("intersect b", b);
1131
/* count the size of the new set */
1649
static XArray* new_VTS ( void ) {
1650
return VG_(newXA)( hg_zalloc, hg_free, sizeof(ScalarTS) );
1652
static XArray* singleton_VTS ( Thread* thr, UWord tym ) {
1656
tl_assert(tym >= 1);
1661
VG_(addToXA)( vts, &st );
1666
static Bool cmpGEQ_VTS ( XArray* a, XArray* b )
1668
Word ia, ib, useda, usedb;
1671
ScalarTS *tmpa, *tmpb;
1673
Bool all_leq = True;
1674
Bool all_geq = True;
1678
useda = VG_(sizeXA)( a );
1679
usedb = VG_(sizeXA)( b );
1134
for(size = ia = ib = 0; ia < a->setsize && ib < b->setsize; ) {
1135
if (mutex_cmp(a->mutex[ia], b->mutex[ib]) == 0) {
1139
} else if (mutex_cmp(a->mutex[ia], b->mutex[ib]) < 0) {
1142
tl_assert(mutex_cmp(a->mutex[ia], b->mutex[ib]) > 0);
1147
/* Build the intersection of the two sets */
1148
ret = alloc_LockSet(size);
1149
for (iret = ia = ib = 0; ia < a->setsize && ib < b->setsize; ) {
1150
if (mutex_cmp(a->mutex[ia], b->mutex[ib]) == 0) {
1151
tl_assert(iret < ret->setsize);
1152
ret->mutex[iret++] = a->mutex[ia];
1155
} else if (mutex_cmp(a->mutex[ia], b->mutex[ib]) < 0) {
1158
tl_assert(mutex_cmp(a->mutex[ia], b->mutex[ib]) > 0);
1163
ret->hash = hash_LockSet(ret);
1165
/* Now search for it in the table, adding it if not seen before */
1166
found = lookup_LockSet(ret);
1168
if (found != NULL) {
1171
insert_LockSet(ret);
1175
if (debug || LOCKSET_SANITY) {
1176
print_LockSet("intersect-OUT", found);
1177
sanity_check_locksets("intersect-OUT");
1183
/* inline the fastpath */
1184
static inline const LockSet *intersect(const LockSet *a, const LockSet *b)
1186
static const Bool debug = False;
1188
/* Fast case -- when the two are the same */
1190
if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1191
print_LockSet("intersect-same fastpath", a);
1196
if (isempty(a) || isempty(b)) {
1198
VG_(printf)("intersect empty fastpath\n");
1202
return _intersect(a, b);
1206
static const LockSet *ls_union(const LockSet *a, const LockSet *b)
1208
static const Bool debug = False;
1213
const LockSet *found;
1215
if (debug || LOCKSET_SANITY)
1216
sanity_check_locksets("union-IN");
1218
/* Fast case -- when the two are the same */
1220
if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1221
print_LockSet("union-same fastpath", a);
1228
print_LockSet("union a=empty b", b);
1233
print_LockSet("union b=empty a", a);
1237
if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1238
print_LockSet("union a", a);
1239
print_LockSet("union b", b);
1242
/* count the size of the new set */
1243
for(size = ia = ib = 0; (ia < a->setsize) || (ib < b->setsize); ) {
1246
if ((ia < a->setsize) && (ib < b->setsize))
1247
cmp = mutex_cmp(a->mutex[ia], b->mutex[ib]);
1248
else if (ia == a->setsize)
1257
} else if (cmp < 0) {
1267
/* Build the intersection of the two sets */
1268
ret = alloc_LockSet(size);
1269
for (iret = ia = ib = 0; (ia < a->setsize) || (ib < b->setsize); ) {
1271
tl_assert(iret < ret->setsize);
1273
if ((ia < a->setsize) && (ib < b->setsize))
1274
cmp = mutex_cmp(a->mutex[ia], b->mutex[ib]);
1275
else if (ia == a->setsize)
1281
ret->mutex[iret++] = a->mutex[ia];
1284
} else if (cmp < 0) {
1285
ret->mutex[iret++] = a->mutex[ia];
1289
ret->mutex[iret++] = b->mutex[ib];
1294
tl_assert(iret == ret->setsize);
1296
ret->hash = hash_LockSet(ret);
1298
/* Now search for it in the table, adding it if not seen before */
1299
found = lookup_LockSet(ret);
1301
if (found != NULL) {
1303
print_LockSet("union found existing set", found);
1307
print_LockSet("union inserting new set", ret);
1308
insert_LockSet(ret);
1312
if (debug || LOCKSET_SANITY) {
1313
print_LockSet("union-OUT", found);
1314
sanity_check_locksets("union-OUT");
1320
/*------------------------------------------------------------*/
1321
/*--- Implementation of mutex structure. ---*/
1322
/*------------------------------------------------------------*/
1324
static UInt graph_mark; /* current mark we're using for graph traversal */
1326
static void record_mutex_error(ThreadId tid, Mutex *mutex,
1327
Char *str, ExeContext *ec);
1328
static void record_lockgraph_error(ThreadId tid, Mutex *mutex,
1329
const LockSet *lockset_holding,
1330
const LockSet *lockset_prev);
1332
static void set_mutex_state(Mutex *mutex, MutexState state, ThreadId tid);
1334
#define M_MUTEX_HASHSZ 1021
1336
static Mutex *mutex_hash[M_MUTEX_HASHSZ];
1337
static UInt total_mutexes;
1339
static const Char *pp_MutexState(MutexState st)
1342
case MxLocked: return "Locked";
1343
case MxUnlocked: return "Unlocked";
1344
case MxDead: return "Dead";
1345
case MxUnknown: return "Unknown";
1350
static void pp_all_mutexes(void)
1355
locks = buckets = 0;
1356
for(i = 0; i < M_MUTEX_HASHSZ; i++) {
1360
for(mx = mutex_hash[i]; mx != NULL; mx = mx->next) {
1363
VG_(printf)("[%4d] = ", i);
1368
VG_(printf)("%p [%8s] -> %p%(y\n",
1369
mx, pp_MutexState(mx->state), mx->mutexp, mx->mutexp);
1373
VG_(printf)("%d locks in %d buckets (%d allocated)\n",
1374
locks, buckets, total_mutexes);
1377
/* find or create a Mutex for a program's mutex use */
1378
static Mutex *get_mutex(Addr mutexp)
1380
UInt bucket = mutexp % M_MUTEX_HASHSZ;
1383
for(mp = mutex_hash[bucket]; mp != NULL; mp = mp->next)
1384
if (mp->mutexp == mutexp)
1389
mp = VG_(malloc)(sizeof(*mp));
1390
mp->mutexp = mutexp;
1391
mp->next = mutex_hash[bucket];
1392
mutex_hash[bucket] = mp;
1394
mp->state = MxUnknown;
1395
mp->tid = VG_INVALID_THREADID;
1396
mp->location = NULL;
1398
mp->lockdep = emptyset;
1399
mp->mark = graph_mark - 1;
1404
/* Find all mutexes in a range of memory, and call the callback.
1405
Remove the mutex from the hash if the callback returns True (mutex
1406
structure itself is not freed, because it may be pointed to by a
1408
static void find_mutex_range(Addr start, Addr end, Bool (*action)(Mutex *))
1410
UInt first = start % M_MUTEX_HASHSZ;
1411
UInt last = (end+1) % M_MUTEX_HASHSZ;
1414
/* Single pass over the hash table, looking for likely hashes */
1415
for(i = first; i != last; ) {
1417
Mutex **prev = &mutex_hash[i];
1419
for(mx = mutex_hash[i]; mx != NULL; prev = &mx->next, mx = mx->next) {
1420
if (mx->mutexp >= start && mx->mutexp < end && (*action)(mx))
1424
if (++i == M_MUTEX_HASHSZ)
1429
#define MARK_LOOP (graph_mark+0)
1430
#define MARK_DONE (graph_mark+1)
1432
static Bool check_cycle_inner(const Mutex *mutex, const LockSet *ls)
1434
static const Bool debug = False;
1437
if (mutex->mark == MARK_LOOP)
1438
return True; /* found cycle */
1439
if (mutex->mark == MARK_DONE)
1440
return False; /* been here before, its OK */
1442
((Mutex*)mutex)->mark = MARK_LOOP;
1445
VG_(printf)("mark=%d visiting %p%(y mutex->lockset=%d\n",
1446
graph_mark, mutex->mutexp, mutex->mutexp, mutex->lockdep);
1447
for(i = 0; i < ls->setsize; i++) {
1448
const Mutex *mx = ls->mutex[i];
1451
VG_(printf)(" %y ls=%p (ls->mutex=%p%(y)\n",
1453
mx->mutexp, mx->mutexp);
1454
if (check_cycle_inner(mx, mx->lockdep))
1457
((Mutex*)mutex)->mark = MARK_DONE;
1685
/* This logic is to enumerate triples (thr, tyma, tymb) drawn
1686
from a and b in order, where thr is the next Thread*
1687
occurring in either a or b, and tyma/b are the relevant
1688
scalar timestamps, taking into account implicit zeroes. */
1689
tl_assert(ia >= 0 && ia <= useda);
1690
tl_assert(ib >= 0 && ib <= usedb);
1693
if (ia == useda && ib == usedb) {
1694
/* both empty - done */
1698
if (ia == useda && ib != usedb) {
1699
/* a empty, use up b */
1700
tmpb = VG_(indexXA)( b, ib );
1707
if (ia != useda && ib == usedb) {
1708
/* b empty, use up a */
1709
tmpa = VG_(indexXA)( a, ia );
1716
/* both not empty; extract lowest-Thread*'d triple */
1717
tmpa = VG_(indexXA)( a, ia );
1718
tmpb = VG_(indexXA)( b, ib );
1719
if (tmpa->thr < tmpb->thr) {
1720
/* a has the lowest unconsidered Thread* */
1727
if (tmpa->thr > tmpb->thr) {
1728
/* b has the lowest unconsidered Thread* */
1734
/* they both next mention the same Thread* */
1735
tl_assert(tmpa->thr == tmpb->thr);
1736
thr = tmpa->thr; /* == tmpb->thr */
1744
/* having laboriously determined (thr, tyma, tymb), do something
1752
if (all_leq && all_geq)
1753
return True; /* PordEQ */
1754
/* now we know they aren't equal, so either all_leq or all_geq or
1757
return False; /* PordLT */
1759
return True; /* PordGT */
1760
/* hmm, neither all_geq or all_leq. This means unordered. */
1761
return False; /* PordUN */
1765
/* Compute max((tick(thra,a),b) into a new XArray. a and b are
1766
unchanged. If neither a nor b supply a value for 'thra',
1769
XArray* tickL_and_joinR_VTS ( Thread* thra, XArray* a, XArray* b )
1771
Word ia, ib, useda, usedb, ticks_found;
1772
UWord tyma, tymb, tymMax;
1775
ScalarTS *tmpa, *tmpb;
1780
useda = VG_(sizeXA)( a );
1781
usedb = VG_(sizeXA)( b );
1784
ia = ib = ticks_found = 0;
1788
/* This logic is to enumerate triples (thr, tyma, tymb) drawn
1789
from a and b in order, where thr is the next Thread*
1790
occurring in either a or b, and tyma/b are the relevant
1791
scalar timestamps, taking into account implicit zeroes. */
1792
tl_assert(ia >= 0 && ia <= useda);
1793
tl_assert(ib >= 0 && ib <= usedb);
1796
if (ia == useda && ib == usedb) {
1797
/* both empty - done */
1801
if (ia == useda && ib != usedb) {
1802
/* a empty, use up b */
1803
tmpb = VG_(indexXA)( b, ib );
1810
if (ia != useda && ib == usedb) {
1811
/* b empty, use up a */
1812
tmpa = VG_(indexXA)( a, ia );
1819
/* both not empty; extract lowest-Thread*'d triple */
1820
tmpa = VG_(indexXA)( a, ia );
1821
tmpb = VG_(indexXA)( b, ib );
1822
if (tmpa->thr < tmpb->thr) {
1823
/* a has the lowest unconsidered Thread* */
1830
if (tmpa->thr > tmpb->thr) {
1831
/* b has the lowest unconsidered Thread* */
1837
/* they both next mention the same Thread* */
1838
tl_assert(tmpa->thr == tmpb->thr);
1839
thr = tmpa->thr; /* == tmpb->thr */
1847
/* having laboriously determined (thr, tyma, tymb), do something
1851
/* VTS 'a' actually supplied this value; it is not a
1852
default zero. Do the required 'tick' action. */
1856
/* 'a' didn't supply this value, so 'b' must have. */
1857
tl_assert(tymb > 0);
1860
tymMax = tyma > tymb ? tyma : tymb;
1865
VG_(addToXA)( res, &st );
1870
tl_assert(is_sane_VTS( res ));
1873
tl_assert(ticks_found == 1);
1875
tl_assert(ticks_found == 0);
1882
/* Do 'vts[me]++', so to speak. If 'me' does not have an entry in
1883
'vts', set it to 1 in the returned VTS. */
1885
static XArray* tick_VTS ( Thread* me, XArray* vts ) {
1886
ScalarTS* here = NULL;
1891
tl_assert(is_sane_VTS(vts));
1892
if (0) VG_(printf)("tick vts thrno %ld szin %d\n",
1893
(Word)me->errmsg_index, (Int)VG_(sizeXA)(vts) );
1895
n = VG_(sizeXA)( vts );
1896
for (i = 0; i < n; i++) {
1897
here = VG_(indexXA)( vts, i );
1898
if (me < here->thr) {
1899
/* We just went past 'me', without seeing it. */
1902
VG_(addToXA)( res, &tmp );
1904
VG_(addToXA)( res, &tmp );
1908
else if (me == here->thr) {
1911
VG_(addToXA)( res, &tmp );
1915
else /* me > here->thr */ {
1917
VG_(addToXA)( res, &tmp );
1920
tl_assert(i >= 0 && i <= n);
1921
if (i == n && here && here->thr < me) {
1924
VG_(addToXA)( res, &tmp );
1926
for (/*keepgoing*/; i < n; i++) {
1927
here = VG_(indexXA)( vts, i );
1929
VG_(addToXA)( res, &tmp );
1932
tl_assert(is_sane_VTS(res));
1933
if (0) VG_(printf)("tick vts thrno %ld szou %d\n",
1934
(Word)me->errmsg_index, (Int)VG_(sizeXA)(res) );
1938
static void show_VTS ( HChar* buf, Int nBuf, XArray* vts ) {
1943
tl_assert(avail > 16);
1946
n = VG_(sizeXA)( vts );
1947
for (i = 0; i < n; i++) {
1948
tl_assert(avail >= 10);
1949
st = VG_(indexXA)( vts, i );
1950
VG_(memset)(unit, 0, sizeof(unit));
1951
VG_(sprintf)(unit, i < n-1 ? "%ld:%ld " : "%ld:%ld",
1952
(Word)st->thr->errmsg_index, st->tym);
1953
if (avail < VG_(strlen)(unit) + 10/*let's say*/) {
1954
VG_(strcat)(buf, " ...]");
1957
VG_(strcat)(buf, unit);
1958
avail -= VG_(strlen)(unit);
1960
VG_(strcat)(buf, "]");
1964
/*------------ searching the happens-before graph ------------*/
1966
static UWord stats__hbefore_queries = 0; // total # queries
1967
static UWord stats__hbefore_cache0s = 0; // hits at cache[0]
1968
static UWord stats__hbefore_cacheNs = 0; // hits at cache[> 0]
1969
static UWord stats__hbefore_probes = 0; // # checks in cache
1970
static UWord stats__hbefore_gsearches = 0; // # searches in graph
1971
static UWord stats__hbefore_gsearchFs = 0; // # fast searches in graph
1972
static UWord stats__hbefore_invals = 0; // # cache invals
1973
static UWord stats__hbefore_stk_hwm = 0; // stack high water mark
1975
/* Running marker for depth-first searches */
1976
/* NOTE: global variable */
1977
static UInt dfsver_current = 0;
1979
/* A stack of possibly-unexplored nodes used in the depth first search */
1980
/* NOTE: global variable */
1981
static XArray* dfsver_stack = NULL;
1983
// FIXME: check this - is it really correct?
1984
__attribute__((noinline))
1985
static Bool happens_before_do_dfs_from_to ( Segment* src, Segment* dst )
1990
/* begin SPEEDUP HACK -- the following can safely be omitted */
1991
/* fast track common case, without favouring either the
1992
->prev or ->other links */
1995
if ((src->prev && src->prev == dst)
1996
|| (src->other && src->other == dst)) {
1997
stats__hbefore_gsearchFs++;
2000
/* end SPEEDUP HACK */
2002
/* empty out the stack */
2003
tl_assert(dfsver_stack);
2004
VG_(dropTailXA)( dfsver_stack, VG_(sizeXA)( dfsver_stack ));
2005
tl_assert(VG_(sizeXA)( dfsver_stack ) == 0);
2007
/* push starting point */
2008
(void) VG_(addToXA)( dfsver_stack, &src );
2011
/* While the stack is not empty, pop the next node off it and
2013
ssz = VG_(sizeXA)( dfsver_stack );
2014
tl_assert(ssz >= 0);
2016
return False; /* stack empty ==> no path from src to dst */
2018
if (UNLIKELY( ((UWord)ssz) > stats__hbefore_stk_hwm ))
2019
stats__hbefore_stk_hwm = (UWord)ssz;
2021
/* here = pop(stack) */
2022
here = *(Segment**) VG_(indexXA)( dfsver_stack, ssz-1 );
2023
VG_(dropTailXA)( dfsver_stack, 1 );
2026
/* consider the node 'here' */
2028
return True; /* found a path from src and dst */
2030
/* have we been to 'here' before? */
2031
tl_assert(here->dfsver <= dfsver_current);
2032
if (here->dfsver == dfsver_current)
2033
continue; /* We've been 'here' before - node is not interesting*/
2035
/* Mark that we've been here */
2036
here->dfsver = dfsver_current;
2038
/* Now push both children on the stack */
2040
/* begin SPEEDUP hack -- the following can safely be omitted */
2041
/* idea is, if there is exactly one child, avoid the overhead of
2042
pushing it on the stack and immediately popping it off again.
2043
Kinda like doing a tail-call. */
2044
if (here->prev && !here->other) {
2048
if (here->other && !here->prev) {
2052
/* end of SPEEDUP HACK */
2054
/* Push all available children on stack. From some quick
2055
experimentation it seems like exploring ->other first leads
2056
to lower maximum stack use, although getting repeatable
2057
results is difficult. */
2059
(void) VG_(addToXA)( dfsver_stack, &(here->prev) );
2061
(void) VG_(addToXA)( dfsver_stack, &(here->other) );
2065
__attribute__((noinline))
2066
static Bool happens_before_wrk ( Segment* seg1, Segment* seg2 )
2070
{ static Int nnn = 0;
2071
if (SHOW_EXPENSIVE_STUFF && (nnn++ % 1000) == 0)
2072
VG_(printf)("happens_before_wrk: %d\n", nnn);
2075
/* Now the question is, is there a chain of pointers through the
2076
.prev and .other fields, that leads from seg2 back to seg1 ? */
2077
tl_assert(dfsver_current < 0xFFFFFFFF);
2080
if (dfsver_stack == NULL) {
2081
dfsver_stack = VG_(newXA)( hg_zalloc, hg_free, sizeof(Segment*) );
2082
tl_assert(dfsver_stack);
2085
reachable = happens_before_do_dfs_from_to( seg2, seg1 );
2090
/*--------------- the happens_before cache ---------------*/
2092
#define HBEFORE__N_CACHE 64
2094
struct { SegmentID segid1; SegmentID segid2; Bool result; }
2097
static HBeforeCacheEnt hbefore__cache[HBEFORE__N_CACHE];
2099
static void hbefore__invalidate_cache ( void )
2102
SegmentID bogus = 0;
2103
tl_assert(!is_sane_SegmentID(bogus));
2104
stats__hbefore_invals++;
2105
for (i = 0; i < HBEFORE__N_CACHE; i++) {
2106
hbefore__cache[i].segid1 = bogus;
2107
hbefore__cache[i].segid2 = bogus;
2108
hbefore__cache[i].result = False;
2112
static Bool happens_before ( SegmentID segid1, SegmentID segid2 )
2115
Int i, j, iNSERT_POINT;
2116
Segment *seg1, *seg2;
2117
tl_assert(is_sane_SegmentID(segid1));
2118
tl_assert(is_sane_SegmentID(segid2));
2119
tl_assert(segid1 != segid2);
2120
stats__hbefore_queries++;
2121
stats__hbefore_probes++;
2122
if (segid1 == hbefore__cache[0].segid1
2123
&& segid2 == hbefore__cache[0].segid2) {
2124
stats__hbefore_cache0s++;
2125
return hbefore__cache[0].result;
2127
for (i = 1; i < HBEFORE__N_CACHE; i++) {
2128
stats__hbefore_probes++;
2129
if (segid1 == hbefore__cache[i].segid1
2130
&& segid2 == hbefore__cache[i].segid2) {
2131
/* Found it. Move it 1 step closer to the front. */
2132
HBeforeCacheEnt tmp = hbefore__cache[i];
2133
hbefore__cache[i] = hbefore__cache[i-1];
2134
hbefore__cache[i-1] = tmp;
2135
stats__hbefore_cacheNs++;
2139
/* Not found. Search the graph and add an entry to the cache. */
2140
stats__hbefore_gsearches++;
2142
seg1 = map_segments_lookup(segid1);
2143
seg2 = map_segments_lookup(segid2);
2144
tl_assert(is_sane_Segment(seg1));
2145
tl_assert(is_sane_Segment(seg2));
2146
tl_assert(seg1 != seg2);
2147
tl_assert(seg1->vts);
2148
tl_assert(seg2->vts);
2150
hbV = cmpGEQ_VTS( seg2->vts, seg1->vts );
2151
if (clo_sanity_flags & SCE_HBEFORE) {
2152
/* Crosscheck the vector-timestamp comparison result against that
2153
obtained from the explicit graph approach. Can be very
2155
hbG = happens_before_wrk( seg1, seg2 );
2157
/* Assume the vector-timestamp comparison result is correct, and
2163
VG_(printf)("seg1 %p seg2 %p hbV %d hbG %d\n",
2164
seg1,seg2,(Int)hbV,(Int)hbG);
2165
segments__generate_vcg();
2167
tl_assert(hbV == hbG);
2169
iNSERT_POINT = (1*HBEFORE__N_CACHE)/4 - 1;
2170
/* if (iNSERT_POINT > 4) iNSERT_POINT = 4; */
2172
for (j = HBEFORE__N_CACHE-1; j > iNSERT_POINT; j--) {
2173
hbefore__cache[j] = hbefore__cache[j-1];
2175
hbefore__cache[iNSERT_POINT].segid1 = segid1;
2176
hbefore__cache[iNSERT_POINT].segid2 = segid2;
2177
hbefore__cache[iNSERT_POINT].result = hbG;
2180
VG_(printf)("hb %d %d\n", (Int)segid1-(1<<24), (Int)segid2-(1<<24));
2184
/*--------------- generating .vcg output ---------------*/
2186
static void segments__generate_vcg ( void )
2188
#define PFX "xxxxxx"
2190
Black -- the chain of .prev links
2191
Green -- thread creation, link to parent
2192
Red -- thread exit, link to exiting thread
2193
Yellow -- signal edge
2194
Pink -- semaphore-up edge
2198
VG_(printf)(PFX "graph: { title: \"Segments\"\n");
2199
VG_(printf)(PFX "orientation: top_to_bottom\n");
2200
VG_(printf)(PFX "height: 900\n");
2201
VG_(printf)(PFX "width: 500\n");
2202
VG_(printf)(PFX "x: 20\n");
2203
VG_(printf)(PFX "y: 20\n");
2204
VG_(printf)(PFX "color: lightgrey\n");
2205
for (seg = admin_segments; seg; seg=seg->admin) {
2207
VG_(printf)(PFX "node: { title: \"%p\" color: lightcyan "
2208
"textcolor: darkgreen label: \"Seg %p\\n",
2210
if (seg->thr->errmsg_index == 1) {
2211
VG_(printf)("ROOT_THREAD");
2213
VG_(printf)("Thr# %d", seg->thr->errmsg_index);
2216
if (clo_gen_vcg >= 2) {
2217
show_VTS( vtsstr, sizeof(vtsstr)-1, seg->vts );
2218
vtsstr[sizeof(vtsstr)-1] = 0;
2219
VG_(printf)("\\n%s", vtsstr);
2222
VG_(printf)("\" }\n", vtsstr);
2225
VG_(printf)(PFX "edge: { sourcename: \"%p\" targetname: \"%p\""
2226
"color: black }\n", seg->prev, seg );
2228
HChar* colour = "orange";
2229
switch (seg->other_hint) {
2230
case 'c': colour = "darkgreen"; break; /* creation */
2231
case 'j': colour = "red"; break; /* join (exit) */
2232
case 's': colour = "orange"; break; /* signal */
2233
case 'S': colour = "pink"; break; /* sem_post->wait */
2234
case 'u': colour = "cyan"; break; /* unlock */
2235
default: tl_assert(0);
2237
VG_(printf)(PFX "edge: { sourcename: \"%p\" targetname: \"%p\""
2238
" color: %s }\n", seg->other, seg, colour );
2241
VG_(printf)(PFX "}\n");
2246
/*----------------------------------------------------------------*/
2247
/*--- map_shmem :: WordFM Addr SecMap ---*/
2248
/*--- shadow memory (low level handlers) (shmem__* fns) ---*/
2249
/*----------------------------------------------------------------*/
2252
static UWord stats__secmaps_allocd = 0; // # SecMaps issued
2253
static UWord stats__secmap_ga_space_covered = 0; // # ga bytes covered
2254
static UWord stats__secmap_linesZ_allocd = 0; // # CacheLineZ's issued
2255
static UWord stats__secmap_linesZ_bytes = 0; // .. using this much storage
2256
static UWord stats__secmap_linesF_allocd = 0; // # CacheLineF's issued
2257
static UWord stats__secmap_linesF_bytes = 0; // .. using this much storage
2258
static UWord stats__secmap_iterator_steppings = 0; // # calls to stepSMIter
2259
static UWord stats__cache_Z_fetches = 0; // # Z lines fetched
2260
static UWord stats__cache_Z_wbacks = 0; // # Z lines written back
2261
static UWord stats__cache_F_fetches = 0; // # F lines fetched
2262
static UWord stats__cache_F_wbacks = 0; // # F lines written back
2263
static UWord stats__cache_invals = 0; // # cache invals
2264
static UWord stats__cache_flushes = 0; // # cache flushes
2265
static UWord stats__cache_totrefs = 0; // # total accesses
2266
static UWord stats__cache_totmisses = 0; // # misses
2267
static UWord stats__cline_normalises = 0; // # calls to cacheline_normalise
2268
static UWord stats__cline_read64s = 0; // # calls to s_m_read64
2269
static UWord stats__cline_read32s = 0; // # calls to s_m_read32
2270
static UWord stats__cline_read16s = 0; // # calls to s_m_read16
2271
static UWord stats__cline_read8s = 0; // # calls to s_m_read8
2272
static UWord stats__cline_write64s = 0; // # calls to s_m_write64
2273
static UWord stats__cline_write32s = 0; // # calls to s_m_write32
2274
static UWord stats__cline_write16s = 0; // # calls to s_m_write16
2275
static UWord stats__cline_write8s = 0; // # calls to s_m_write8
2276
static UWord stats__cline_set64s = 0; // # calls to s_m_set64
2277
static UWord stats__cline_set32s = 0; // # calls to s_m_set32
2278
static UWord stats__cline_set16s = 0; // # calls to s_m_set16
2279
static UWord stats__cline_set8s = 0; // # calls to s_m_set8
2280
static UWord stats__cline_get8s = 0; // # calls to s_m_get8
2281
static UWord stats__cline_copy8s = 0; // # calls to s_m_copy8
2282
static UWord stats__cline_64to32splits = 0; // # 64-bit accesses split
2283
static UWord stats__cline_32to16splits = 0; // # 32-bit accesses split
2284
static UWord stats__cline_16to8splits = 0; // # 16-bit accesses split
2285
static UWord stats__cline_64to32pulldown = 0; // # calls to pulldown_to_32
2286
static UWord stats__cline_32to16pulldown = 0; // # calls to pulldown_to_16
2287
static UWord stats__cline_16to8pulldown = 0; // # calls to pulldown_to_8
2290
static SVal shadow_mem_get8 ( Addr a ); /* fwds */
2292
static inline Addr shmem__round_to_SecMap_base ( Addr a ) {
2293
return a & ~(N_SECMAP_ARANGE - 1);
2295
static inline UWord shmem__get_SecMap_offset ( Addr a ) {
2296
return a & (N_SECMAP_ARANGE - 1);
2299
/*--------------- SecMap allocation --------------- */
2301
static HChar* shmem__bigchunk_next = NULL;
2302
static HChar* shmem__bigchunk_end1 = NULL;
2304
static void* shmem__bigchunk_alloc ( SizeT n )
2306
const SizeT sHMEM__BIGCHUNK_SIZE = 4096 * 256;
2309
tl_assert(shmem__bigchunk_next <= shmem__bigchunk_end1);
2310
tl_assert(shmem__bigchunk_end1 - shmem__bigchunk_next
2311
<= (SSizeT)sHMEM__BIGCHUNK_SIZE);
2312
if (shmem__bigchunk_next + n > shmem__bigchunk_end1) {
2314
VG_(printf)("XXXXX bigchunk: abandoning %d bytes\n",
2315
(Int)(shmem__bigchunk_end1 - shmem__bigchunk_next));
2316
shmem__bigchunk_next = VG_(am_shadow_alloc)( sHMEM__BIGCHUNK_SIZE );
2317
shmem__bigchunk_end1 = shmem__bigchunk_next + sHMEM__BIGCHUNK_SIZE;
2319
tl_assert(shmem__bigchunk_next);
2320
tl_assert( 0 == (((Addr)shmem__bigchunk_next) & (16-1)) );
2321
tl_assert(shmem__bigchunk_next + n <= shmem__bigchunk_end1);
2322
shmem__bigchunk_next += n;
2323
return shmem__bigchunk_next - n;
2326
static SecMap* shmem__alloc_SecMap ( void )
2329
SecMap* sm = shmem__bigchunk_alloc( sizeof(SecMap) );
2330
if (0) VG_(printf)("alloc_SecMap %p\n",sm);
2332
sm->magic = SecMap_MAGIC;
2333
sm->mbHasLocks = False; /* dangerous */
2334
sm->mbHasShared = False; /* dangerous */
2335
for (i = 0; i < N_SECMAP_ZLINES; i++) {
2336
sm->linesZ[i].dict[0] = SHVAL_NoAccess;
2337
sm->linesZ[i].dict[1] = 0; /* completely invalid SHVAL */
2338
sm->linesZ[i].dict[2] = 0;
2339
sm->linesZ[i].dict[3] = 0;
2340
for (j = 0; j < N_LINE_ARANGE/4; j++)
2341
sm->linesZ[i].ix2s[j] = 0; /* all reference dict[0] */
2344
sm->linesF_size = 0;
2345
stats__secmaps_allocd++;
2346
stats__secmap_ga_space_covered += N_SECMAP_ARANGE;
2347
stats__secmap_linesZ_allocd += N_SECMAP_ZLINES;
2348
stats__secmap_linesZ_bytes += N_SECMAP_ZLINES * sizeof(CacheLineZ);
2352
static SecMap* shmem__find_or_alloc_SecMap ( Addr ga )
2355
Addr gaKey = shmem__round_to_SecMap_base(ga);
2356
if (HG_(lookupFM)( map_shmem,
2357
NULL/*keyP*/, (Word*)&sm, (Word)gaKey )) {
2358
/* Found; address of SecMap is in sm */
2361
/* create a new one */
2362
sm = shmem__alloc_SecMap();
2364
HG_(addToFM)( map_shmem, (Word)gaKey, (Word)sm );
2370
/*--------------- cache management/lookup --------------- */
2372
/*--------------- misc --------------- */
2374
static Bool shmem__get_mbHasLocks ( Addr a )
2377
Addr aKey = shmem__round_to_SecMap_base(a);
2378
if (HG_(lookupFM)( map_shmem,
2379
NULL/*keyP*/, (Word*)&sm, (Word)aKey )) {
2381
return sm->mbHasLocks;
2387
static void shmem__set_mbHasLocks ( Addr a, Bool b )
2390
Addr aKey = shmem__round_to_SecMap_base(a);
2391
tl_assert(b == False || b == True);
2392
if (HG_(lookupFM)( map_shmem,
2393
NULL/*keyP*/, (Word*)&sm, (Word)aKey )) {
2394
/* Found; address of SecMap is in sm */
2396
/* create a new one */
2397
sm = shmem__alloc_SecMap();
2399
HG_(addToFM)( map_shmem, (Word)aKey, (Word)sm );
2404
static void shmem__set_mbHasShared ( Addr a, Bool b )
2407
Addr aKey = shmem__round_to_SecMap_base(a);
2408
tl_assert(b == False || b == True);
2409
if (HG_(lookupFM)( map_shmem,
2410
NULL/*keyP*/, (Word*)&sm, (Word)aKey )) {
2411
/* Found; address of SecMap is in sm */
2413
/* create a new one */
2414
sm = shmem__alloc_SecMap();
2416
HG_(addToFM)( map_shmem, (Word)aKey, (Word)sm );
2418
sm->mbHasShared = b;
2422
/*----------------------------------------------------------------*/
2423
/*--- Sanity checking the data structures ---*/
2424
/*----------------------------------------------------------------*/
2426
static UWord stats__sanity_checks = 0;
2428
static Bool is_sane_CacheLine ( CacheLine* cl ); /* fwds */
2429
static Bool cmpGEQ_VTS ( XArray* a, XArray* b ); /* fwds */
2430
static void laog__sanity_check ( Char* who ); /* fwds */
2432
/* REQUIRED INVARIANTS:
2434
Thread vs Segment/Lock/SecMaps
2436
for each t in Threads {
2438
// Thread.lockset: each element is really a valid Lock
2440
// Thread.lockset: each Lock in set is actually held by that thread
2441
for lk in Thread.lockset
2444
// Thread.csegid is a valid SegmentID
2445
// and the associated Segment has .thr == t
2449
all thread Locksets are pairwise empty under intersection
2450
(that is, no lock is claimed to be held by more than one thread)
2451
-- this is guaranteed if all locks in locksets point back to their
2454
Lock vs Thread/Segment/SecMaps
2456
for each entry (gla, la) in map_locks
2457
gla == la->guest_addr
2459
for each lk in Locks {
2462
lk->guest_addr does not have shadow state NoAccess
2463
if lk == LockedBy(t), then t->lockset contains lk
2464
if lk == UnlockedBy(segid) then segid is valid SegmentID
2465
and can be mapped to a valid Segment(seg)
2466
and seg->thr->lockset does not contain lk
2467
if lk == UnlockedNew then (no lockset contains lk)
2469
secmaps for lk has .mbHasLocks == True
2473
Segment vs Thread/Lock/SecMaps
2475
the Segment graph is a dag (no cycles)
2476
all of the Segment graph must be reachable from the segids
2477
mentioned in the Threads
2479
for seg in Segments {
2481
seg->thr is a sane Thread
2485
SecMaps vs Segment/Thread/Lock
2490
if any shadow word is ShR or ShM then .mbHasShared == True
2492
for each Excl(segid) state
2493
map_segments_lookup maps to a sane Segment(seg)
2494
for each ShM/ShR(tsetid,lsetid) state
2495
each lk in lset is a valid Lock
2496
each thr in tset is a valid thread, which is non-dead
2502
/* Return True iff 'thr' holds 'lk' in some mode. */
2503
static Bool thread_is_a_holder_of_Lock ( Thread* thr, Lock* lk )
2506
return HG_(elemBag)( lk->heldBy, (Word)thr ) > 0;
2511
/* Sanity check Threads, as far as possible */
2512
__attribute__((noinline))
2513
static void threads__sanity_check ( Char* who )
2515
#define BAD(_str) do { how = (_str); goto bad; } while (0)
2516
Char* how = "no error";
2523
for (thr = admin_threads; thr; thr = thr->admin) {
2524
if (!is_sane_Thread(thr)) BAD("1");
2525
wsA = thr->locksetA;
2526
wsW = thr->locksetW;
2527
// locks held in W mode are a subset of all locks held
2528
if (!HG_(isSubsetOf)( univ_lsets, wsW, wsA )) BAD("7");
2529
HG_(getPayloadWS)( &ls_words, &ls_size, univ_lsets, wsA );
2530
for (i = 0; i < ls_size; i++) {
2531
lk = (Lock*)ls_words[i];
2532
// Thread.lockset: each element is really a valid Lock
2533
if (!is_sane_LockN(lk)) BAD("2");
2534
// Thread.lockset: each Lock in set is actually held by that
2536
if (!thread_is_a_holder_of_Lock(thr,lk)) BAD("3");
2537
// Thread.csegid is a valid SegmentID
2538
if (!is_sane_SegmentID(thr->csegid)) BAD("4");
2539
// and the associated Segment has .thr == t
2540
seg = map_segments_maybe_lookup(thr->csegid);
2541
if (!is_sane_Segment(seg)) BAD("5");
2542
if (seg->thr != thr) BAD("6");
2547
VG_(printf)("threads__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how);
2553
/* Sanity check Locks, as far as possible */
2554
__attribute__((noinline))
2555
static void locks__sanity_check ( Char* who )
2557
#define BAD(_str) do { how = (_str); goto bad; } while (0)
2558
Char* how = "no error";
2562
// # entries in admin_locks == # entries in map_locks
2563
for (i = 0, lk = admin_locks; lk; i++, lk = lk->admin)
2565
if (i != HG_(sizeFM)(map_locks)) BAD("1");
2566
// for each entry (gla, lk) in map_locks
2567
// gla == lk->guest_addr
2568
HG_(initIterFM)( map_locks );
2569
while (HG_(nextIterFM)( map_locks,
2570
(Word*)&gla, (Word*)&lk )) {
2571
if (lk->guestaddr != gla) BAD("2");
2573
HG_(doneIterFM)( map_locks );
2574
// scan through admin_locks ...
2575
for (lk = admin_locks; lk; lk = lk->admin) {
2576
// lock is sane. Quite comprehensive, also checks that
2577
// referenced (holder) threads are sane.
2578
if (!is_sane_LockN(lk)) BAD("3");
2579
// map_locks binds guest address back to this lock
2580
if (lk != map_locks_maybe_lookup(lk->guestaddr)) BAD("4");
2581
// lk->guest_addr does not have shadow state NoAccess
2582
// FIXME: this could legitimately arise from a buggy guest
2583
// that attempts to lock in (eg) freed memory. Detect this
2584
// and warn about it in the pre/post-mutex-lock event handler.
2585
if (is_SHVAL_NoAccess(shadow_mem_get8(lk->guestaddr))) BAD("5");
2586
// look at all threads mentioned as holders of this lock. Ensure
2587
// this lock is mentioned in their locksets.
2591
HG_(initIterBag)( lk->heldBy );
2592
while (HG_(nextIterBag)( lk->heldBy,
2593
(Word*)&thr, &count )) {
2594
// is_sane_LockN above ensures these
2595
tl_assert(count >= 1);
2596
tl_assert(is_sane_Thread(thr));
2597
if (!HG_(elemWS)(univ_lsets, thr->locksetA, (Word)lk))
2599
// also check the w-only lockset
2601
&& !HG_(elemWS)(univ_lsets, thr->locksetW, (Word)lk))
2604
&& HG_(elemWS)(univ_lsets, thr->locksetW, (Word)lk))
2607
HG_(doneIterBag)( lk->heldBy );
2609
/* lock not held by anybody */
2610
if (lk->heldW) BAD("9"); /* should be False if !heldBy */
2611
// since lk is unheld, then (no lockset contains lk)
2612
// hmm, this is really too expensive to check. Hmm.
2614
// secmaps for lk has .mbHasLocks == True
2615
if (!shmem__get_mbHasLocks(lk->guestaddr)) BAD("10");
2620
VG_(printf)("locks__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how);
2626
/* Sanity check Segments, as far as possible */
2627
__attribute__((noinline))
2628
static void segments__sanity_check ( Char* who )
2630
#define BAD(_str) do { how = (_str); goto bad; } while (0)
2631
Char* how = "no error";
2635
// the Segment graph is a dag (no cycles)
2636
// all of the Segment graph must be reachable from the segids
2637
// mentioned in the Threads
2638
// # entries in admin_segments == # entries in map_segments
2639
for (i = 0, seg = admin_segments; seg; i++, seg = seg->admin)
2641
if (i != HG_(sizeFM)(map_segments)) BAD("1");
2642
// for seg in Segments {
2643
for (seg = admin_segments; seg; seg = seg->admin) {
2644
if (!is_sane_Segment(seg)) BAD("2");
2645
if (!is_sane_Thread(seg->thr)) BAD("3");
2646
if (!seg->vts) BAD("4");
2647
if (seg->prev && seg->prev->vts
2648
&& !cmpGEQ_VTS(seg->vts, seg->prev->vts))
2650
if (seg->other && seg->other->vts
2651
&& !cmpGEQ_VTS(seg->vts, seg->other->vts))
2656
VG_(printf)("segments__sanity_check: who=\"%s\", bad=\"%s\"\n",
2663
/* Sanity check shadow memory, as far as possible */
2664
static Int cmp_Addr_for_ssort ( void* p1, void* p2 ) {
2665
Addr a1 = *(Addr*)p1;
2666
Addr a2 = *(Addr*)p2;
2667
if (a1 < a2) return -1;
2668
if (a1 > a2) return 1;
2671
__attribute__((noinline))
2672
static void shmem__sanity_check ( Char* who )
2674
#define BAD(_str) do { how = (_str); goto bad; } while (0)
2675
Char* how = "no error";
2678
Word i, j, ws_size, n_valid_tags;
2681
HG_(initIterFM)( map_shmem );
2682
// for sm in SecMaps {
2683
while (HG_(nextIterFM)( map_shmem,
2684
(Word*)&smga, (Word*)&sm )) {
2687
Bool mbHasShared = False;
2688
Bool allNoAccess = True;
2689
if (!is_sane_SecMap(sm)) BAD("1");
2690
// sm properly aligned
2691
if (smga != shmem__round_to_SecMap_base(smga)) BAD("2");
2692
// if any shadow word is ShR or ShM then .mbHasShared == True
2693
initSecMapIter( &itr );
2694
while (stepSecMapIter( &w32p, &itr, sm )) {
2696
if (is_SHVAL_Sh(w32))
2698
if (!is_SHVAL_NoAccess(w32))
2699
allNoAccess = False;
2700
if (is_SHVAL_Excl(w32)) {
2701
// for each Excl(segid) state
2702
// map_segments_lookup maps to a sane Segment(seg)
2704
SegmentID segid = un_SHVAL_Excl(w32);
2705
if (!is_sane_SegmentID(segid)) BAD("3");
2706
seg = map_segments_maybe_lookup(segid);
2707
if (!is_sane_Segment(seg)) BAD("4");
2709
else if (is_SHVAL_Sh(w32)) {
2710
WordSetID tset = un_SHVAL_Sh_tset(w32);
2711
WordSetID lset = un_SHVAL_Sh_lset(w32);
2712
if (!HG_(plausibleWS)( univ_tsets, tset )) BAD("5");
2713
if (!HG_(saneWS_SLOW)( univ_tsets, tset )) BAD("6");
2714
if (HG_(cardinalityWS)( univ_tsets, tset ) < 2) BAD("7");
2715
if (!HG_(plausibleWS)( univ_lsets, lset )) BAD("8");
2716
if (!HG_(saneWS_SLOW)( univ_lsets, lset )) BAD("9");
2717
HG_(getPayloadWS)( &ws_words, &ws_size, univ_lsets, lset );
2718
for (j = 0; j < ws_size; j++) {
2719
Lock* lk = (Lock*)ws_words[j];
2720
// for each ShM/ShR(tsetid,lsetid) state
2721
// each lk in lset is a valid Lock
2722
if (!is_sane_LockN(lk)) BAD("10");
2724
HG_(getPayloadWS)( &ws_words, &ws_size, univ_tsets, tset );
2725
for (j = 0; j < ws_size; j++) {
2726
Thread* thr = (Thread*)ws_words[j];
2727
//for each ShM/ShR(tsetid,lsetid) state
2728
// each thr in tset is a valid thread, which is non-dead
2729
if (!is_sane_Thread(thr)) BAD("11");
2732
else if (is_SHVAL_NoAccess(w32) || is_SHVAL_New(w32)) {
2733
/* nothing to check */
2736
/* bogus shadow mem value */
2739
} /* iterating over a SecMap */
2740
// Check essential safety property
2741
if (mbHasShared && !sm->mbHasShared) BAD("13");
2742
// This is optional - check that destroyed memory has its hint
2743
// bits cleared. NB won't work properly unless full, eager
2744
// GCing of SecMaps is implemented
2745
//if (allNoAccess && sm->mbHasLocks) BAD("13a");
2747
HG_(doneIterFM)( map_shmem );
2750
valid_tags = hg_zalloc(N_WAY_NENT * sizeof(Addr));
2752
tl_assert(valid_tags);
2753
for (i = 0; i < N_WAY_NENT; i++) {
2757
cl = &cache_shmem.lyns0[i];
2758
tag = cache_shmem.tags0[i];
2760
if (!is_valid_scache_tag(tag)) BAD("14-0");
2761
if (!is_sane_CacheLine(cl)) BAD("15-0");
2762
/* A valid tag should be of the form
2763
X---X line_number:N_WAY_BITS 0:N_LINE_BITS */
2764
if (tag & (N_LINE_ARANGE-1)) BAD("16-0");
2765
if ( i != ((tag >> N_LINE_BITS) & (N_WAY_NENT-1)) ) BAD("16-1");
2766
valid_tags[n_valid_tags++] = tag;
2769
tl_assert(n_valid_tags <= N_WAY_NENT);
2770
if (n_valid_tags > 1) {
2771
/* Check that the valid tags are unique */
2772
VG_(ssort)( valid_tags, n_valid_tags, sizeof(Addr), cmp_Addr_for_ssort );
2773
for (i = 0; i < n_valid_tags-1; i++) {
2774
if (valid_tags[i] >= valid_tags[i+1])
2778
hg_free(valid_tags);
2781
VG_(printf)("shmem__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how);
2786
static void all_except_Locks__sanity_check ( Char* who ) {
2787
stats__sanity_checks++;
2788
if (0) VG_(printf)("all_except_Locks__sanity_check(%s)\n", who);
2789
threads__sanity_check(who);
2790
segments__sanity_check(who);
2791
shmem__sanity_check(who);
2792
laog__sanity_check(who);
2794
static void all__sanity_check ( Char* who ) {
2795
all_except_Locks__sanity_check(who);
2796
locks__sanity_check(who);
2800
/*----------------------------------------------------------------*/
2801
/*--- the core memory state machine (msm__* functions) ---*/
2802
/*----------------------------------------------------------------*/
2804
static UWord stats__msm_read_Excl_nochange = 0;
2805
static UWord stats__msm_read_Excl_transfer = 0;
2806
static UWord stats__msm_read_Excl_to_ShR = 0;
2807
static UWord stats__msm_read_ShR_to_ShR = 0;
2808
static UWord stats__msm_read_ShM_to_ShM = 0;
2809
static UWord stats__msm_read_New_to_Excl = 0;
2810
static UWord stats__msm_read_NoAccess = 0;
2812
static UWord stats__msm_write_Excl_nochange = 0;
2813
static UWord stats__msm_write_Excl_transfer = 0;
2814
static UWord stats__msm_write_Excl_to_ShM = 0;
2815
static UWord stats__msm_write_ShR_to_ShM = 0;
2816
static UWord stats__msm_write_ShM_to_ShM = 0;
2817
static UWord stats__msm_write_New_to_Excl = 0;
2818
static UWord stats__msm_write_NoAccess = 0;
2821
static void record_error_Race ( Thread* thr,
2822
Addr data_addr, Bool isWrite, Int szB,
2823
SVal old_sv, SVal new_sv,
2824
ExeContext* mb_lastlock );
2826
static void record_error_FreeMemLock ( Thread* thr, Lock* lk );
2828
static void record_error_UnlockUnlocked ( Thread*, Lock* );
2829
static void record_error_UnlockForeign ( Thread*, Thread*, Lock* );
2830
static void record_error_UnlockBogus ( Thread*, Addr );
2831
static void record_error_PthAPIerror ( Thread*, HChar*, Word, HChar* );
2832
static void record_error_LockOrder ( Thread*, Addr, Addr,
2833
ExeContext*, ExeContext* );
2835
static void record_error_Misc ( Thread*, HChar* );
2836
static void announce_one_thread ( Thread* thr ); /* fwds */
2838
static WordSetID add_BHL ( WordSetID lockset ) {
2839
return HG_(addToWS)( univ_lsets, lockset, (Word)__bus_lock_Lock );
2841
static WordSetID del_BHL ( WordSetID lockset ) {
2842
return HG_(delFromWS)( univ_lsets, lockset, (Word)__bus_lock_Lock );
2846
/* Last-lock-lossage records. This mechanism exists to help explain
2847
to programmers why we are complaining about a race. The idea is to
2848
monitor all lockset transitions. When a previously nonempty
2849
lockset becomes empty, the lock(s) that just disappeared (the
2850
"lossage") are the locks that have consistently protected the
2851
location (ga_of_access) in question for the longest time. Most of
2852
the time the lossage-set is a single lock. Because the
2853
lossage-lock is the one that has survived longest, there is there
2854
is a good chance that it is indeed the lock that the programmer
2855
intended to use to protect the location.
2857
Note that we cannot in general just look at the lossage set when we
2858
see a transition to ShM(...,empty-set), because a transition to an
2859
empty lockset can happen arbitrarily far before the point where we
2860
want to report an error. This is in the case where there are many
2861
transitions ShR -> ShR, all with an empty lockset, and only later
2862
is there a transition to ShM. So what we want to do is note the
2863
lossage lock at the point where a ShR -> ShR transition empties out
2864
the lockset, so we can present it later if there should be a
2867
So this function finds such transitions. For each, it associates
2868
in ga_to_lastlock, the guest address and the lossage lock. In fact
2869
we do not record the Lock* directly as that may disappear later,
2870
but instead the ExeContext inside the Lock which says where it was
2871
initialised or first locked. ExeContexts are permanent so keeping
2872
them indefinitely is safe.
2874
A boring detail: the hardware bus lock is not interesting in this
2875
respect, so we first remove that from the pre/post locksets.
2878
static UWord stats__ga_LL_adds = 0;
2880
static WordFM* ga_to_lastlock = NULL; /* GuestAddr -> ExeContext* */
2883
void record_last_lock_lossage ( Addr ga_of_access,
2884
WordSetID lset_old, WordSetID lset_new )
2887
Int card_old, card_new;
2889
tl_assert(lset_old != lset_new);
2891
if (0) VG_(printf)("XX1: %d (card %d) -> %d (card %d) %p\n",
2893
HG_(cardinalityWS)(univ_lsets,lset_old),
2895
HG_(cardinalityWS)(univ_lsets,lset_new),
2898
/* This is slow, but at least it's simple. The bus hardware lock
2899
just confuses the logic, so remove it from the locksets we're
2900
considering before doing anything else. */
2901
lset_new = del_BHL( lset_new );
2903
if (!HG_(isEmptyWS)( univ_lsets, lset_new )) {
2904
/* The post-transition lock set is not empty. So we are not
2905
interested. We're only interested in spotting transitions
2906
that make locksets become empty. */
2910
/* lset_new is now empty */
2911
card_new = HG_(cardinalityWS)( univ_lsets, lset_new );
2912
tl_assert(card_new == 0);
2914
lset_old = del_BHL( lset_old );
2915
card_old = HG_(cardinalityWS)( univ_lsets, lset_old );
2917
if (0) VG_(printf)(" X2: %d (card %d) -> %d (card %d)\n",
2918
(Int)lset_old, card_old, (Int)lset_new, card_new );
2920
if (card_old == 0) {
2921
/* The old lockset was also empty. Not interesting. */
2925
tl_assert(card_old > 0);
2926
tl_assert(!HG_(isEmptyWS)( univ_lsets, lset_old ));
2928
/* Now we know we've got a transition from a nonempty lockset to an
2929
empty one. So lset_old must be the set of locks lost. Record
2930
some details. If there is more than one element in the lossage
2931
set, just choose one arbitrarily -- not the best, but at least
2934
lk = (Lock*)HG_(anyElementOfWS)( univ_lsets, lset_old );
2935
if (0) VG_(printf)("lossage %d %p\n",
2936
HG_(cardinalityWS)( univ_lsets, lset_old), lk );
2937
if (lk->appeared_at) {
2938
if (ga_to_lastlock == NULL)
2939
ga_to_lastlock = HG_(newFM)( hg_zalloc, hg_free, NULL );
2940
HG_(addToFM)( ga_to_lastlock, ga_of_access, (Word)lk->appeared_at );
2941
stats__ga_LL_adds++;
2945
/* This queries the table (ga_to_lastlock) made by
2946
record_last_lock_lossage, when constructing error messages. It
2947
attempts to find the ExeContext of the allocation or initialisation
2948
point for the lossage lock associated with 'ga'. */
2950
static ExeContext* maybe_get_lastlock_initpoint ( Addr ga )
2952
ExeContext* ec_hint = NULL;
2953
if (ga_to_lastlock != NULL
2954
&& HG_(lookupFM)(ga_to_lastlock,
2955
NULL, (Word*)&ec_hint, ga)) {
2956
tl_assert(ec_hint != NULL);
2964
static void msm__show_state_change ( Thread* thr_acc, Addr a, Int szB,
2966
SVal sv_old, SVal sv_new )
2969
UChar txt_old[100], txt_new[100];
2971
tl_assert(is_sane_Thread(thr_acc));
2972
tl_assert(clo_trace_level == 1 || clo_trace_level == 2);
2974
case 'r': how = "rd"; break;
2975
case 'w': how = "wr"; break;
2976
case 'p': how = "pa"; break;
2977
default: tl_assert(0);
2979
show_shadow_w32_for_user(txt_old, sizeof(txt_old), sv_old);
2980
show_shadow_w32_for_user(txt_new, sizeof(txt_new), sv_new);
2981
txt_old[sizeof(txt_old)-1] = 0;
2982
txt_new[sizeof(txt_new)-1] = 0;
2983
if (clo_trace_level == 2) {
2984
/* show everything */
2985
VG_(message)(Vg_UserMsg, "");
2986
announce_one_thread( thr_acc );
2987
VG_(message)(Vg_UserMsg,
2988
"TRACE: %p %s %d thr#%d :: %s --> %s",
2989
a, how, szB, thr_acc->errmsg_index, txt_old, txt_new );
2990
tid = map_threads_maybe_reverse_lookup_SLOW(thr_acc);
2991
if (tid != VG_INVALID_THREADID) {
2992
VG_(get_and_pp_StackTrace)( tid, 8 );
2995
/* Just print one line */
2996
VG_(message)(Vg_UserMsg,
2997
"TRACE: %p %s %d thr#%d :: %22s --> %22s",
2998
a, how, szB, thr_acc->errmsg_index, txt_old, txt_new );
3003
/* Here are some MSM stats from startup/shutdown of OpenOffice.
3005
msm: 489,734,723 80,278,862 rd/wr_Excl_nochange
3006
msm: 3,171,542 93,738 rd/wr_Excl_transfer
3007
msm: 45,036 167 rd/wr_Excl_to_ShR/ShM
3008
msm: 13,352,594 285 rd/wr_ShR_to_ShR/ShM
3009
msm: 1,125,879 815,779 rd/wr_ShM_to_ShM
3010
msm: 7,561,842 250,629,935 rd/wr_New_to_Excl
3011
msm: 17,778 0 rd/wr_NoAccess
3013
This says how the clauses should be ordered for greatest speed:
3015
* the vast majority of memory reads (490 million out of a total of
3016
515 million) are of memory in an exclusive state, and the state
3017
is unchanged. All other read accesses are insignificant by
3020
* 75% (251 million out of a total of 332 million) writes are 'first
3021
time' writes, which take New memory into exclusive ownership.
3022
Almost all the rest (80 million) are accesses to exclusive state,
3023
which remains unchanged. All other write accesses are
3026
/* The core MSM. If 'wold' is the old 32-bit shadow word for a
3027
location, return the new shadow word that would result for a read
3028
of the location, and report any errors necessary on the way. This
3029
does not update shadow memory - it merely produces new shadow words
3030
from old. 'thr_acc' and 'a' are supplied only so it can produce
3031
coherent error messages if necessary. */
3033
SVal msm__handle_read ( Thread* thr_acc, Addr a, SVal wold, Int szB )
3035
SVal wnew = SHVAL_Invalid;
3037
tl_assert(is_sane_Thread(thr_acc));
3039
if (0) VG_(printf)("read thr=%p %p\n", thr_acc, a);
3042
if (LIKELY(is_SHVAL_Excl(wold))) {
3044
| segid_old == segid-of-thread
3046
| segid_old `happens_before` segid-of-this-thread
3047
-> Excl(segid-of-this-thread)
3051
SegmentID segid_old = un_SHVAL_Excl(wold);
3052
tl_assert(is_sane_SegmentID(segid_old));
3053
if (LIKELY(segid_old == thr_acc->csegid)) {
3055
stats__msm_read_Excl_nochange++;
3056
/*NOCHANGE*/return wold;
3058
if (happens_before(segid_old, thr_acc->csegid)) {
3059
/* -> Excl(segid-of-this-thread) */
3060
wnew = mk_SHVAL_Excl(thr_acc->csegid);
3061
stats__msm_read_Excl_transfer++;
3065
/* Enter the shared-readonly (ShR) state. */
3066
WordSetID tset, lset;
3067
/* This location has been accessed by precisely two threads.
3068
Make an appropriate tset. */
3069
// FIXME: performance: duplicate map_segments_lookup(segid_old)
3070
// since must also be done in happens_before()
3071
Segment* seg_old = map_segments_lookup( segid_old );
3072
Thread* thr_old = seg_old->thr;
3073
tset = HG_(doubletonWS)( univ_tsets, (Word)thr_old, (Word)thr_acc );
3074
lset = add_BHL( thr_acc->locksetA ); /* read ==> use all locks */
3075
wnew = mk_SHVAL_ShR( tset, lset );
3076
stats__msm_read_Excl_to_ShR++;
3082
/* Shared-Readonly */
3083
if (is_SHVAL_ShR(wold)) {
3084
/* read Shared-Readonly(threadset, lockset)
3085
We remain in ShR state, but add this thread to the
3086
threadset and refine the lockset accordingly. Do not
3087
complain if the lockset becomes empty -- that's ok. */
3088
WordSetID tset_old = un_SHVAL_ShR_tset(wold);
3089
WordSetID lset_old = un_SHVAL_ShR_lset(wold);
3090
WordSetID tset_new = HG_(addToWS)( univ_tsets,
3091
tset_old, (Word)thr_acc );
3092
WordSetID lset_new = HG_(intersectWS)( univ_lsets,
3094
add_BHL(thr_acc->locksetA)
3095
/* read ==> use all locks */ );
3096
/*SVal*/ wnew = mk_SHVAL_ShR( tset_new, lset_new );
3097
if (lset_old != lset_new)
3098
record_last_lock_lossage(a,lset_old,lset_new);
3099
stats__msm_read_ShR_to_ShR++;
3103
/* Shared-Modified */
3104
if (is_SHVAL_ShM(wold)) {
3105
/* read Shared-Modified(threadset, lockset)
3106
We remain in ShM state, but add this thread to the
3107
threadset and refine the lockset accordingly.
3108
If the lockset becomes empty, complain. */
3109
WordSetID tset_old = un_SHVAL_ShM_tset(wold);
3110
WordSetID lset_old = un_SHVAL_ShM_lset(wold);
3111
WordSetID tset_new = HG_(addToWS)( univ_tsets,
3112
tset_old, (Word)thr_acc );
3113
WordSetID lset_new = HG_(intersectWS)( univ_lsets,
3115
add_BHL(thr_acc->locksetA)
3116
/* read ==> use all locks */ );
3117
/*SVal*/ wnew = mk_SHVAL_ShM( tset_new, lset_new );
3118
if (lset_old != lset_new)
3119
record_last_lock_lossage(a,lset_old,lset_new);
3120
if (HG_(isEmptyWS)(univ_lsets, lset_new)
3121
&& !HG_(isEmptyWS)(univ_lsets, lset_old)) {
3122
record_error_Race( thr_acc, a,
3123
False/*isWrite*/, szB, wold, wnew,
3124
maybe_get_lastlock_initpoint(a) );
3126
stats__msm_read_ShM_to_ShM++;
3131
if (is_SHVAL_New(wold)) {
3132
/* read New -> Excl(segid) */
3133
wnew = mk_SHVAL_Excl( thr_acc->csegid );
3134
stats__msm_read_New_to_Excl++;
3139
if (is_SHVAL_NoAccess(wold)) {
3140
// FIXME: complain if accessing here
3141
// FIXME: transition to Excl?
3144
"msm__handle_read_aligned_32(thr=%p, addr=%p): NoAccess\n",
3145
thr_acc, (void*)a );
3146
stats__msm_read_NoAccess++;
3147
/*NOCHANGE*/return wold; /* no change */
3150
/* hmm, bogus state */
3154
if (UNLIKELY(clo_trace_level > 0)) {
3155
if (a <= clo_trace_addr && clo_trace_addr < a+szB
3157
msm__show_state_change( thr_acc, a, szB, 'r', wold, wnew );
3163
/* Similar to msm__handle_read, compute a new 32-bit shadow word
3164
resulting from a write to a location, and report any errors
3165
necessary on the way. */
3167
SVal msm__handle_write ( Thread* thr_acc, Addr a, SVal wold, Int szB )
3169
SVal wnew = SHVAL_Invalid;
3171
tl_assert(is_sane_Thread(thr_acc));
3173
if (0) VG_(printf)("write32 thr=%p %p\n", thr_acc, a);
3176
if (LIKELY(is_SHVAL_New(wold))) {
3177
/* write New -> Excl(segid) */
3178
wnew = mk_SHVAL_Excl( thr_acc->csegid );
3179
stats__msm_write_New_to_Excl++;
3184
if (is_SHVAL_Excl(wold)) {
3185
// I believe is identical to case for read Excl
3186
// apart from enters ShM rather than ShR
3188
| segid_old == segid-of-thread
3190
| segid_old `happens_before` segid-of-this-thread
3191
-> Excl(segid-of-this-thread)
3195
SegmentID segid_old = un_SHVAL_Excl(wold);
3196
tl_assert(is_sane_SegmentID(segid_old));
3197
if (segid_old == thr_acc->csegid) {
3199
stats__msm_write_Excl_nochange++;
3200
/*NOCHANGE*/return wold;
3202
if (happens_before(segid_old, thr_acc->csegid)) {
3203
/* -> Excl(segid-of-this-thread) */
3204
wnew = mk_SHVAL_Excl(thr_acc->csegid);
3205
stats__msm_write_Excl_transfer++;
3209
/* Enter the shared-modified (ShM) state. */
3210
WordSetID tset, lset;
3211
/* This location has been accessed by precisely two threads.
3212
Make an appropriate tset. */
3213
// FIXME: performance: duplicate map_segments_lookup(segid_old)
3214
// since must also be done in happens_before()
3215
Segment* seg_old = map_segments_lookup( segid_old );
3216
Thread* thr_old = seg_old->thr;
3217
tset = HG_(doubletonWS)( univ_tsets, (Word)thr_old, (Word)thr_acc );
3218
lset = thr_acc->locksetW; /* write ==> use only w-held locks */
3219
wnew = mk_SHVAL_ShM( tset, lset );
3220
if (HG_(isEmptyWS)(univ_lsets, lset)) {
3221
record_error_Race( thr_acc,
3222
a, True/*isWrite*/, szB, wold, wnew,
3223
maybe_get_lastlock_initpoint(a) );
3225
stats__msm_write_Excl_to_ShM++;
3231
/* Shared-Readonly */
3232
if (is_SHVAL_ShR(wold)) {
3233
/* write Shared-Readonly(threadset, lockset)
3234
We move to ShM state, add this thread to the
3235
threadset and refine the lockset accordingly.
3236
If the lockset becomes empty, complain. */
3237
WordSetID tset_old = un_SHVAL_ShR_tset(wold);
3238
WordSetID lset_old = un_SHVAL_ShR_lset(wold);
3239
WordSetID tset_new = HG_(addToWS)( univ_tsets,
3240
tset_old, (Word)thr_acc );
3241
WordSetID lset_new = HG_(intersectWS)(
3245
/* write ==> use only w-held locks */
3247
/*SVal*/ wnew = mk_SHVAL_ShM( tset_new, lset_new );
3248
if (lset_old != lset_new)
3249
record_last_lock_lossage(a,lset_old,lset_new);
3250
if (HG_(isEmptyWS)(univ_lsets, lset_new)) {
3251
record_error_Race( thr_acc, a,
3252
True/*isWrite*/, szB, wold, wnew,
3253
maybe_get_lastlock_initpoint(a) );
3255
stats__msm_write_ShR_to_ShM++;
3259
/* Shared-Modified */
3260
else if (is_SHVAL_ShM(wold)) {
3261
/* write Shared-Modified(threadset, lockset)
3262
We remain in ShM state, but add this thread to the
3263
threadset and refine the lockset accordingly.
3264
If the lockset becomes empty, complain. */
3265
WordSetID tset_old = un_SHVAL_ShM_tset(wold);
3266
WordSetID lset_old = un_SHVAL_ShM_lset(wold);
3267
WordSetID tset_new = HG_(addToWS)( univ_tsets,
3268
tset_old, (Word)thr_acc );
3269
WordSetID lset_new = HG_(intersectWS)(
3273
/* write ==> use only w-held locks */
3275
/*SVal*/ wnew = mk_SHVAL_ShM( tset_new, lset_new );
3276
if (lset_old != lset_new)
3277
record_last_lock_lossage(a,lset_old,lset_new);
3278
if (HG_(isEmptyWS)(univ_lsets, lset_new)
3279
&& !HG_(isEmptyWS)(univ_lsets, lset_old)) {
3280
record_error_Race( thr_acc, a,
3281
True/*isWrite*/, szB, wold, wnew,
3282
maybe_get_lastlock_initpoint(a) );
3284
stats__msm_write_ShM_to_ShM++;
3289
if (is_SHVAL_NoAccess(wold)) {
3290
// FIXME: complain if accessing here
3291
// FIXME: transition to Excl?
3294
"msm__handle_write_aligned_32(thr=%p, addr=%p): NoAccess\n",
3295
thr_acc, (void*)a );
3296
stats__msm_write_NoAccess++;
3297
/*NOCHANGE*/return wold;
3300
/* hmm, bogus state */
3301
VG_(printf)("msm__handle_write_aligned_32: bogus old state 0x%x\n",
3306
if (UNLIKELY(clo_trace_level > 0)) {
3307
if (a <= clo_trace_addr && clo_trace_addr < a+szB
3309
msm__show_state_change( thr_acc, a, szB, 'w', wold, wnew );
3316
/*----------------------------------------------------------------*/
3317
/*--- Shadow value and address range handlers ---*/
3318
/*----------------------------------------------------------------*/
3320
static void laog__pre_thread_acquires_lock ( Thread*, Lock* ); /* fwds */
3321
static void laog__handle_lock_deletions ( WordSetID ); /* fwds */
3322
static inline Thread* get_current_Thread ( void ); /* fwds */
3324
/* ------------ CacheLineF and CacheLineZ related ------------ */
3326
static void write_twobit_array ( UChar* arr, UWord ix, UWord b2 ) {
3327
Word bix, shft, mask, prep;
3328
tl_assert((b2 & ~3) == 0);
3331
shft = 2 * (ix & 3); /* 0, 2, 4 or 6 */
3334
arr[bix] = (arr[bix] & ~mask) | prep;
3337
static UWord read_twobit_array ( UChar* arr, UWord ix ) {
3341
shft = 2 * (ix & 3); /* 0, 2, 4 or 6 */
3342
return (arr[bix] >> shft) & 3;
3345
/* Given a lineZ index and a SecMap, return the CacheLineZ* and CacheLineF*
3347
static void get_ZF_by_index ( /*OUT*/CacheLineZ** zp,
3348
/*OUT*/CacheLineF** fp,
3349
SecMap* sm, Int zix ) {
3353
tl_assert(zix >= 0 && zix < N_SECMAP_ZLINES);
3354
tl_assert(is_sane_SecMap(sm));
3355
lineZ = &sm->linesZ[zix];
3356
if (lineZ->dict[0] == 0) {
3357
Int fix = lineZ->dict[1];
3358
tl_assert(sm->linesF);
3359
tl_assert(sm->linesF_size > 0);
3360
tl_assert(fix >= 0 && fix < sm->linesF_size);
3362
*fp = &sm->linesF[fix];
3363
tl_assert(sm->linesF[fix].inUse);
3370
static void find_ZF_for_reading ( /*OUT*/CacheLineZ** zp,
3371
/*OUT*/CacheLineF** fp, Addr tag ) {
3375
SecMap* sm = shmem__find_or_alloc_SecMap(tag);
3376
UWord smoff = shmem__get_SecMap_offset(tag);
3377
/* since smoff is derived from a valid tag, it should be
3378
cacheline-aligned. */
3379
tl_assert(0 == (smoff & (N_LINE_ARANGE - 1)));
3380
zix = smoff >> N_LINE_BITS;
3381
tl_assert(zix < N_SECMAP_ZLINES);
3382
lineZ = &sm->linesZ[zix];
3384
if (lineZ->dict[0] == 0) {
3385
Word fix = lineZ->dict[1];
3386
tl_assert(sm->linesF);
3387
tl_assert(sm->linesF_size > 0);
3388
tl_assert(fix >= 0 && fix < sm->linesF_size);
3389
lineF = &sm->linesF[fix];
3390
tl_assert(lineF->inUse);
3397
static void find_Z_for_writing ( /*OUT*/SecMap** smp,
3403
SecMap* sm = shmem__find_or_alloc_SecMap(tag);
3404
UWord smoff = shmem__get_SecMap_offset(tag);
3405
/* since smoff is derived from a valid tag, it should be
3406
cacheline-aligned. */
3407
tl_assert(0 == (smoff & (N_LINE_ARANGE - 1)));
3408
zix = smoff >> N_LINE_BITS;
3409
tl_assert(zix < N_SECMAP_ZLINES);
3410
lineZ = &sm->linesZ[zix];
3412
/* If lineZ has an associated lineF, free it up. */
3413
if (lineZ->dict[0] == 0) {
3414
Word fix = lineZ->dict[1];
3415
tl_assert(sm->linesF);
3416
tl_assert(sm->linesF_size > 0);
3417
tl_assert(fix >= 0 && fix < sm->linesF_size);
3418
lineF = &sm->linesF[fix];
3419
tl_assert(lineF->inUse);
3420
lineF->inUse = False;
3427
void alloc_F_for_writing ( /*MOD*/SecMap* sm, /*OUT*/Word* fixp ) {
3432
tl_assert(sm->linesF_size > 0);
3434
tl_assert(sm->linesF_size == 0);
3438
for (i = 0; i < sm->linesF_size; i++) {
3439
if (!sm->linesF[i].inUse) {
3446
/* No free F line found. Expand existing array and try again. */
3447
new_size = sm->linesF_size==0 ? 1 : 2 * sm->linesF_size;
3448
nyu = hg_zalloc( new_size * sizeof(CacheLineF) );
3451
stats__secmap_linesF_allocd += (new_size - sm->linesF_size);
3452
stats__secmap_linesF_bytes += (new_size - sm->linesF_size)
3453
* sizeof(CacheLineF);
3456
VG_(printf)("SM %p: expand F array from %d to %d\n",
3457
sm, (Int)sm->linesF_size, new_size);
3459
for (i = 0; i < new_size; i++)
3460
nyu[i].inUse = False;
3463
for (i = 0; i < sm->linesF_size; i++) {
3464
tl_assert(sm->linesF[i].inUse);
3465
nyu[i] = sm->linesF[i];
3467
VG_(memset)(sm->linesF, 0, sm->linesF_size * sizeof(CacheLineF) );
3468
hg_free(sm->linesF);
3472
sm->linesF_size = new_size;
3474
for (i = 0; i < sm->linesF_size; i++) {
3475
if (!sm->linesF[i].inUse) {
3486
/* ------------ CacheLine and implicit-tree related ------------ */
3488
__attribute__((unused))
3489
static void pp_CacheLine ( CacheLine* cl ) {
3492
VG_(printf)("pp_CacheLine(NULL)\n");
3495
for (i = 0; i < N_LINE_TREES; i++)
3496
VG_(printf)(" descr: %04lx\n", (UWord)cl->descrs[i]);
3497
for (i = 0; i < N_LINE_ARANGE; i++)
3498
VG_(printf)(" sval: %08lx\n", (UWord)cl->svals[i]);
3501
static UChar descr_to_validbits ( UShort descr )
3503
/* a.k.a Party Time for gcc's constant folder */
3504
# define DESCR(b8_7, b8_6, b8_5, b8_4, b8_3, b8_2, b8_1, b8_0, \
3505
b16_3, b32_1, b16_2, b64, b16_1, b32_0, b16_0) \
3506
( (UShort) ( ( (b8_7) << 14) | ( (b8_6) << 13) | \
3507
( (b8_5) << 12) | ( (b8_4) << 11) | \
3508
( (b8_3) << 10) | ( (b8_2) << 9) | \
3509
( (b8_1) << 8) | ( (b8_0) << 7) | \
3510
( (b16_3) << 6) | ( (b32_1) << 5) | \
3511
( (b16_2) << 4) | ( (b64) << 3) | \
3512
( (b16_1) << 2) | ( (b32_0) << 1) | \
3515
# define BYTE(bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0) \
3516
( (UChar) ( ( (bit7) << 7) | ( (bit6) << 6) | \
3517
( (bit5) << 5) | ( (bit4) << 4) | \
3518
( (bit3) << 3) | ( (bit2) << 2) | \
3519
( (bit1) << 1) | ( (bit0) << 0) ) )
3521
/* these should all get folded out at compile time */
3522
tl_assert(DESCR(1,0,0,0,0,0,0,0, 0,0,0, 0, 0,0,0) == TREE_DESCR_8_7);
3523
tl_assert(DESCR(0,0,0,0,0,0,0,1, 0,0,0, 0, 0,0,0) == TREE_DESCR_8_0);
3524
tl_assert(DESCR(0,0,0,0,0,0,0,0, 1,0,0, 0, 0,0,0) == TREE_DESCR_16_3);
3525
tl_assert(DESCR(0,0,0,0,0,0,0,0, 0,1,0, 0, 0,0,0) == TREE_DESCR_32_1);
3526
tl_assert(DESCR(0,0,0,0,0,0,0,0, 0,0,1, 0, 0,0,0) == TREE_DESCR_16_2);
3527
tl_assert(DESCR(0,0,0,0,0,0,0,0, 0,0,0, 1, 0,0,0) == TREE_DESCR_64);
3528
tl_assert(DESCR(0,0,0,0,0,0,0,0, 0,0,0, 0, 1,0,0) == TREE_DESCR_16_1);
3529
tl_assert(DESCR(0,0,0,0,0,0,0,0, 0,0,0, 0, 0,1,0) == TREE_DESCR_32_0);
3530
tl_assert(DESCR(0,0,0,0,0,0,0,0, 0,0,0, 0, 0,0,1) == TREE_DESCR_16_0);
3534
+--------------------------------- TREE_DESCR_8_7
3535
| +------------------- TREE_DESCR_8_0
3536
| | +---------------- TREE_DESCR_16_3
3537
| | | +-------------- TREE_DESCR_32_1
3538
| | | | +------------ TREE_DESCR_16_2
3539
| | | | | +--------- TREE_DESCR_64
3540
| | | | | | +------ TREE_DESCR_16_1
3541
| | | | | | | +---- TREE_DESCR_32_0
3542
| | | | | | | | +-- TREE_DESCR_16_0
3544
| | | | | | | | | GRANULARITY, 7 -> 0 */
3545
case DESCR(1,1,1,1,1,1,1,1, 0,0,0, 0, 0,0,0): /* 8 8 8 8 8 8 8 8 */
3546
return BYTE(1,1,1,1,1,1,1,1);
3547
case DESCR(1,1,0,0,1,1,1,1, 0,0,1, 0, 0,0,0): /* 8 8 16 8 8 8 8 */
3548
return BYTE(1,1,0,1,1,1,1,1);
3549
case DESCR(0,0,1,1,1,1,1,1, 1,0,0, 0, 0,0,0): /* 16 8 8 8 8 8 8 */
3550
return BYTE(0,1,1,1,1,1,1,1);
3551
case DESCR(0,0,0,0,1,1,1,1, 1,0,1, 0, 0,0,0): /* 16 16 8 8 8 8 */
3552
return BYTE(0,1,0,1,1,1,1,1);
3554
case DESCR(1,1,1,1,1,1,0,0, 0,0,0, 0, 0,0,1): /* 8 8 8 8 8 8 16 */
3555
return BYTE(1,1,1,1,1,1,0,1);
3556
case DESCR(1,1,0,0,1,1,0,0, 0,0,1, 0, 0,0,1): /* 8 8 16 8 8 16 */
3557
return BYTE(1,1,0,1,1,1,0,1);
3558
case DESCR(0,0,1,1,1,1,0,0, 1,0,0, 0, 0,0,1): /* 16 8 8 8 8 16 */
3559
return BYTE(0,1,1,1,1,1,0,1);
3560
case DESCR(0,0,0,0,1,1,0,0, 1,0,1, 0, 0,0,1): /* 16 16 8 8 16 */
3561
return BYTE(0,1,0,1,1,1,0,1);
3563
case DESCR(1,1,1,1,0,0,1,1, 0,0,0, 0, 1,0,0): /* 8 8 8 8 16 8 8 */
3564
return BYTE(1,1,1,1,0,1,1,1);
3565
case DESCR(1,1,0,0,0,0,1,1, 0,0,1, 0, 1,0,0): /* 8 8 16 16 8 8 */
3566
return BYTE(1,1,0,1,0,1,1,1);
3567
case DESCR(0,0,1,1,0,0,1,1, 1,0,0, 0, 1,0,0): /* 16 8 8 16 8 8 */
3568
return BYTE(0,1,1,1,0,1,1,1);
3569
case DESCR(0,0,0,0,0,0,1,1, 1,0,1, 0, 1,0,0): /* 16 16 16 8 8 */
3570
return BYTE(0,1,0,1,0,1,1,1);
3572
case DESCR(1,1,1,1,0,0,0,0, 0,0,0, 0, 1,0,1): /* 8 8 8 8 16 16 */
3573
return BYTE(1,1,1,1,0,1,0,1);
3574
case DESCR(1,1,0,0,0,0,0,0, 0,0,1, 0, 1,0,1): /* 8 8 16 16 16 */
3575
return BYTE(1,1,0,1,0,1,0,1);
3576
case DESCR(0,0,1,1,0,0,0,0, 1,0,0, 0, 1,0,1): /* 16 8 8 16 16 */
3577
return BYTE(0,1,1,1,0,1,0,1);
3578
case DESCR(0,0,0,0,0,0,0,0, 1,0,1, 0, 1,0,1): /* 16 16 16 16 */
3579
return BYTE(0,1,0,1,0,1,0,1);
3581
case DESCR(0,0,0,0,1,1,1,1, 0,1,0, 0, 0,0,0): /* 32 8 8 8 8 */
3582
return BYTE(0,0,0,1,1,1,1,1);
3583
case DESCR(0,0,0,0,1,1,0,0, 0,1,0, 0, 0,0,1): /* 32 8 8 16 */
3584
return BYTE(0,0,0,1,1,1,0,1);
3585
case DESCR(0,0,0,0,0,0,1,1, 0,1,0, 0, 1,0,0): /* 32 16 8 8 */
3586
return BYTE(0,0,0,1,0,1,1,1);
3587
case DESCR(0,0,0,0,0,0,0,0, 0,1,0, 0, 1,0,1): /* 32 16 16 */
3588
return BYTE(0,0,0,1,0,1,0,1);
3590
case DESCR(1,1,1,1,0,0,0,0, 0,0,0, 0, 0,1,0): /* 8 8 8 8 32 */
3591
return BYTE(1,1,1,1,0,0,0,1);
3592
case DESCR(1,1,0,0,0,0,0,0, 0,0,1, 0, 0,1,0): /* 8 8 16 32 */
3593
return BYTE(1,1,0,1,0,0,0,1);
3594
case DESCR(0,0,1,1,0,0,0,0, 1,0,0, 0, 0,1,0): /* 16 8 8 32 */
3595
return BYTE(0,1,1,1,0,0,0,1);
3596
case DESCR(0,0,0,0,0,0,0,0, 1,0,1, 0, 0,1,0): /* 16 16 32 */
3597
return BYTE(0,1,0,1,0,0,0,1);
3599
case DESCR(0,0,0,0,0,0,0,0, 0,1,0, 0, 0,1,0): /* 32 32 */
3600
return BYTE(0,0,0,1,0,0,0,1);
3602
case DESCR(0,0,0,0,0,0,0,0, 0,0,0, 1, 0,0,0): /* 64 */
3603
return BYTE(0,0,0,0,0,0,0,1);
3605
default: return BYTE(0,0,0,0,0,0,0,0);
3606
/* INVALID - any valid descr produces at least one
3607
valid bit in tree[0..7]*/
3616
__attribute__((unused))
3617
static Bool is_sane_Descr ( UShort descr ) {
3618
return descr_to_validbits(descr) != 0;
3621
static void sprintf_Descr ( /*OUT*/UChar* dst, UShort descr ) {
3623
"%d%d%d%d%d%d%d%d %d%d%d %d %d%d%d",
3624
(Int)((descr & TREE_DESCR_8_7) ? 1 : 0),
3625
(Int)((descr & TREE_DESCR_8_6) ? 1 : 0),
3626
(Int)((descr & TREE_DESCR_8_5) ? 1 : 0),
3627
(Int)((descr & TREE_DESCR_8_4) ? 1 : 0),
3628
(Int)((descr & TREE_DESCR_8_3) ? 1 : 0),
3629
(Int)((descr & TREE_DESCR_8_2) ? 1 : 0),
3630
(Int)((descr & TREE_DESCR_8_1) ? 1 : 0),
3631
(Int)((descr & TREE_DESCR_8_0) ? 1 : 0),
3632
(Int)((descr & TREE_DESCR_16_3) ? 1 : 0),
3633
(Int)((descr & TREE_DESCR_32_1) ? 1 : 0),
3634
(Int)((descr & TREE_DESCR_16_2) ? 1 : 0),
3635
(Int)((descr & TREE_DESCR_64) ? 1 : 0),
3636
(Int)((descr & TREE_DESCR_16_1) ? 1 : 0),
3637
(Int)((descr & TREE_DESCR_32_0) ? 1 : 0),
3638
(Int)((descr & TREE_DESCR_16_0) ? 1 : 0)
3641
static void sprintf_Byte ( /*OUT*/UChar* dst, UChar byte ) {
3642
VG_(sprintf)(dst, "%d%d%d%d%d%d%d%d",
3643
(Int)((byte & 128) ? 1 : 0),
3644
(Int)((byte & 64) ? 1 : 0),
3645
(Int)((byte & 32) ? 1 : 0),
3646
(Int)((byte & 16) ? 1 : 0),
3647
(Int)((byte & 8) ? 1 : 0),
3648
(Int)((byte & 4) ? 1 : 0),
3649
(Int)((byte & 2) ? 1 : 0),
3650
(Int)((byte & 1) ? 1 : 0)
3654
static Bool is_sane_Descr_and_Tree ( UShort descr, SVal* tree ) {
3656
UChar validbits = descr_to_validbits(descr);
3657
UChar buf[128], buf2[128];
3660
for (i = 0; i < 8; i++) {
3661
if (validbits & (1<<i)) {
3662
if (!is_SHVAL_valid(tree[i]))
3671
sprintf_Descr( buf, descr );
3672
sprintf_Byte( buf2, validbits );
3673
VG_(printf)("is_sane_Descr_and_Tree: bad tree {\n");
3674
VG_(printf)(" validbits 0x%02lx %s\n", (UWord)validbits, buf2);
3675
VG_(printf)(" descr 0x%04lx %s\n", (UWord)descr, buf);
3676
for (i = 0; i < 8; i++)
3677
VG_(printf)(" [%ld] 0x%08x\n", i, tree[i]);
3683
static Bool is_sane_CacheLine ( CacheLine* cl )
3689
for (tno = 0, cloff = 0; tno < N_LINE_TREES; tno++, cloff += 8) {
3690
UShort descr = cl->descrs[tno];
3691
SVal* tree = &cl->svals[cloff];
3692
if (!is_sane_Descr_and_Tree(descr, tree))
3695
tl_assert(cloff == N_LINE_ARANGE);
1462
static Bool check_cycle(const Mutex *start, const LockSet* lockset)
1465
graph_mark += 2; /* clear all marks */
1467
return check_cycle_inner(start, lockset);
1470
/* test to see if a mutex state change would be problematic; this
1471
makes no changes to the mutex state. This should be called before
1472
the locking thread has actually blocked. */
1473
static void test_mutex_state(Mutex *mutex, MutexState state, ThreadId tid)
1475
static const Bool debug = False;
1477
if (mutex->state == MxDead) {
1481
case MxLocked: str = "lock dead mutex"; break;
1482
case MxUnlocked: str = "unlock dead mutex"; break;
1483
default: str = "operate on dead mutex"; break;
1486
/* can't do anything legal to a destroyed mutex */
1487
record_mutex_error(tid, mutex, str, mutex->location);
1493
tl_assert(!check_cycle(mutex, mutex->lockdep));
1496
print_LockSet("thread holding", thread_locks[tid]);
1498
if (check_cycle(mutex, thread_locks[tid]))
1499
record_lockgraph_error(tid, mutex, thread_locks[tid], mutex->lockdep);
1501
mutex->lockdep = ls_union(mutex->lockdep, thread_locks[tid]);
1504
VG_(printf)("giving mutex %p%(y lockdep = %p ",
1505
mutex->mutexp, mutex->mutexp, mutex->lockdep);
1506
print_LockSet("lockdep", mutex->lockdep);
1513
print_LockSet("thread holding", thread_locks[tid]);
1515
if (mutex->state != MxLocked) {
1516
record_mutex_error(tid, mutex,
1517
"unlock non-locked mutex", mutex->location);
1519
if (mutex->tid != tid) {
1520
record_mutex_error(tid, mutex,
1521
"unlock someone else's mutex", mutex->location);
1533
/* Update a mutex state. Expects most error testing and reporting to
1534
have happened in test_mutex_state(). The assumption is that no
1535
client code is run by thread tid between test and set, either
1536
because it is blocked or test and set are called together
1539
Setting state to MxDead is the exception, since that can happen as
1540
a result of any thread freeing memory; in this case set_mutex_state
1541
does all the error reporting as well.
1543
static void set_mutex_state(Mutex *mutex, MutexState state, ThreadId tid)
1545
static const Bool debug = False;
1548
VG_(printf)("\ntid %d changing mutex (%p)->%p%(y state %s -> %s\n",
1549
tid, mutex, mutex->mutexp, mutex->mutexp,
1550
pp_MutexState(mutex->state), pp_MutexState(state));
1552
if (mutex->state == MxDead) {
1553
/* can't do anything legal to a destroyed mutex */
1559
if (mutex->state == MxLocked) {
1560
if (mutex->tid != tid)
1561
record_mutex_error(tid, mutex, "take lock held by someone else",
1564
record_mutex_error(tid, mutex, "take lock we already hold",
1567
VG_(tool_panic)("core should have checked this\n");
1571
tl_assert(!check_cycle(mutex, mutex->lockdep));
1578
print_LockSet("thread holding", thread_locks[tid]);
1580
if (mutex->state != MxLocked || mutex->tid != tid)
1583
mutex->tid = VG_INVALID_THREADID;
1587
if (mutex->state == MxLocked) {
1588
/* forcably remove offending lock from thread's lockset */
1589
tl_assert(ismember(thread_locks[mutex->tid], mutex));
1590
thread_locks[mutex->tid] = remove_LockSet(thread_locks[mutex->tid], mutex);
1591
mutex->tid = VG_INVALID_THREADID;
1593
record_mutex_error(tid, mutex,
1594
"free locked mutex", mutex->location);
1602
mutex->location = VG_(record_ExeContext)(tid);
1603
mutex->state = state;
1606
/*------------------------------------------------------------*/
1607
/*--- Setting and checking permissions. ---*/
1608
/*------------------------------------------------------------*/
1610
/* only clean up dead mutexes */
1612
Bool cleanmx(Mutex *mx) {
1613
return mx->state == MxDead;
1617
void set_address_range_state ( Addr a, SizeT len /* in bytes */,
1618
VgeInitStatus status )
1622
# if DEBUG_MAKE_ACCESSES
1623
VG_(printf)("make_access: 0x%x, %u, status=%u\n", a, len, status);
1625
//PROF_EVENT(30); PPP
3703
static UShort normalise_tree ( /*MOD*/SVal* tree ) {
3706
/* pre: incoming tree[0..7] does not have any invalid shvals, in
3707
particular no zeroes. */
3708
for (i = 0; i < 8; i++)
3709
tl_assert(tree[i] != 0);
3711
descr = TREE_DESCR_8_7 | TREE_DESCR_8_6 | TREE_DESCR_8_5
3712
| TREE_DESCR_8_4 | TREE_DESCR_8_3 | TREE_DESCR_8_2
3713
| TREE_DESCR_8_1 | TREE_DESCR_8_0;
3714
/* build 16-bit layer */
3715
if (tree[1] == tree[0]) {
3716
tree[1] = 0/*INVALID*/;
3717
descr &= ~(TREE_DESCR_8_1 | TREE_DESCR_8_0);
3718
descr |= TREE_DESCR_16_0;
3720
if (tree[3] == tree[2]) {
3721
tree[3] = 0/*INVALID*/;
3722
descr &= ~(TREE_DESCR_8_3 | TREE_DESCR_8_2);
3723
descr |= TREE_DESCR_16_1;
3725
if (tree[5] == tree[4]) {
3726
tree[5] = 0/*INVALID*/;
3727
descr &= ~(TREE_DESCR_8_5 | TREE_DESCR_8_4);
3728
descr |= TREE_DESCR_16_2;
3730
if (tree[7] == tree[6]) {
3731
tree[7] = 0/*INVALID*/;
3732
descr &= ~(TREE_DESCR_8_7 | TREE_DESCR_8_6);
3733
descr |= TREE_DESCR_16_3;
3735
/* build 32-bit layer */
3736
if (tree[2] == tree[0]
3737
&& (descr & TREE_DESCR_16_1) && (descr & TREE_DESCR_16_0)) {
3738
tree[2] = 0; /* [3,1] must already be 0 */
3739
descr &= ~(TREE_DESCR_16_1 | TREE_DESCR_16_0);
3740
descr |= TREE_DESCR_32_0;
3742
if (tree[6] == tree[4]
3743
&& (descr & TREE_DESCR_16_3) && (descr & TREE_DESCR_16_2)) {
3744
tree[6] = 0; /* [7,5] must already be 0 */
3745
descr &= ~(TREE_DESCR_16_3 | TREE_DESCR_16_2);
3746
descr |= TREE_DESCR_32_1;
3748
/* build 64-bit layer */
3749
if (tree[4] == tree[0]
3750
&& (descr & TREE_DESCR_32_1) && (descr & TREE_DESCR_32_0)) {
3751
tree[4] = 0; /* [7,6,5,3,2,1] must already be 0 */
3752
descr &= ~(TREE_DESCR_32_1 | TREE_DESCR_32_0);
3753
descr |= TREE_DESCR_64;
3758
/* This takes a cacheline where all the data is at the leaves
3759
(w8[..]) and builds a correctly normalised tree. */
3760
static void normalise_CacheLine ( /*MOD*/CacheLine* cl )
3763
for (tno = 0, cloff = 0; tno < N_LINE_TREES; tno++, cloff += 8) {
3764
SVal* tree = &cl->svals[cloff];
3765
cl->descrs[tno] = normalise_tree( tree );
3767
tl_assert(cloff == N_LINE_ARANGE);
3769
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
3770
stats__cline_normalises++;
3775
SVal* sequentialise_tree ( /*MOD*/SVal* dst, /*OUT*/Bool* anyShared,
3776
UShort descr, SVal* tree ) {
3780
# define PUT(_n,_v) \
3782
if (is_SHVAL_Sh(_v)) \
3783
*anyShared = True; \
3784
for (i = 0; i < (_n); i++) \
3789
if (descr & TREE_DESCR_64) PUT(8, tree[0]); else
3790
if (descr & TREE_DESCR_32_0) PUT(4, tree[0]); else
3791
if (descr & TREE_DESCR_16_0) PUT(2, tree[0]); else
3792
if (descr & TREE_DESCR_8_0) PUT(1, tree[0]);
3794
if (descr & TREE_DESCR_8_1) PUT(1, tree[1]);
3796
if (descr & TREE_DESCR_16_1) PUT(2, tree[2]); else
3797
if (descr & TREE_DESCR_8_2) PUT(1, tree[2]);
3799
if (descr & TREE_DESCR_8_3) PUT(1, tree[3]);
3801
if (descr & TREE_DESCR_32_1) PUT(4, tree[4]); else
3802
if (descr & TREE_DESCR_16_2) PUT(2, tree[4]); else
3803
if (descr & TREE_DESCR_8_4) PUT(1, tree[4]);
3805
if (descr & TREE_DESCR_8_5) PUT(1, tree[5]);
3807
if (descr & TREE_DESCR_16_3) PUT(2, tree[6]); else
3808
if (descr & TREE_DESCR_8_6) PUT(1, tree[6]);
3810
if (descr & TREE_DESCR_8_7) PUT(1, tree[7]);
3814
tl_assert( (((Char*)dst) - ((Char*)dst0)) == 8 * sizeof(SVal) );
3818
/* Write the cacheline 'wix' to backing store. Where it ends up
3819
is determined by its tag field. */
3821
Bool sequentialise_CacheLine ( /*OUT*/SVal* dst, Word nDst, CacheLine* src )
3824
Bool anyShared = False;
3827
for (tno = 0, cloff = 0; tno < N_LINE_TREES; tno++, cloff += 8) {
3828
UShort descr = src->descrs[tno];
3829
SVal* tree = &src->svals[cloff];
3831
dst = sequentialise_tree ( dst, &bTmp, descr, tree );
3834
tl_assert(cloff == N_LINE_ARANGE);
3836
/* Assert we wrote N_LINE_ARANGE shadow values. */
3837
tl_assert( ((HChar*)dst) - ((HChar*)dst0)
3838
== nDst * sizeof(SVal) );
3844
static __attribute__((noinline)) void cacheline_wback ( UWord wix )
3847
Bool anyShared = False;
3854
SVal shvals[N_LINE_ARANGE];
3858
VG_(printf)("scache wback line %d\n", (Int)wix);
3860
tl_assert(wix >= 0 && wix < N_WAY_NENT);
3862
tag = cache_shmem.tags0[wix];
3863
cl = &cache_shmem.lyns0[wix];
3865
/* The cache line may have been invalidated; if so, ignore it. */
3866
if (!is_valid_scache_tag(tag))
3869
/* Where are we going to put it? */
3875
find_Z_for_writing( &sm, &zix, tag );
3877
tl_assert(zix >= 0 && zix < N_SECMAP_ZLINES);
3878
lineZ = &sm->linesZ[zix];
3880
/* Generate the data to be stored */
3882
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
3883
anyShared = sequentialise_CacheLine( shvals, N_LINE_ARANGE, cl );
3885
lineZ->dict[0] = lineZ->dict[1]
3886
= lineZ->dict[2] = lineZ->dict[3] = 0;
3888
for (i = 0; i < N_LINE_ARANGE; i++) {
3891
for (j = 0; j < 4; j++) {
3892
if (sv == lineZ->dict[j])
3895
for (j = 0; j < 4; j++) {
3896
if (lineZ->dict[j] == 0)
3899
tl_assert(j >= 0 && j <= 4);
3900
if (j == 4) break; /* we'll have to use the f rep */
3901
tl_assert(is_SHVAL_valid(sv));
3902
lineZ->dict[j] = sv;
3904
write_twobit_array( lineZ->ix2s, i, j );
3908
tl_assert(i >= 0 && i <= N_LINE_ARANGE);
3910
if (i < N_LINE_ARANGE) {
3911
/* cannot use the compressed rep. Use f rep instead. */
3912
alloc_F_for_writing( sm, &fix );
3913
tl_assert(sm->linesF);
3914
tl_assert(sm->linesF_size > 0);
3915
tl_assert(fix >= 0 && fix < sm->linesF_size);
3916
lineF = &sm->linesF[fix];
3917
tl_assert(!lineF->inUse);
3918
lineZ->dict[0] = lineZ->dict[2] = lineZ->dict[3] = 0;
3919
lineZ->dict[1] = (SVal)fix;
3920
lineF->inUse = True;
3921
for (i = 0; i < N_LINE_ARANGE; i++) {
3923
tl_assert(is_SHVAL_valid(sv));
3924
lineF->w32s[i] = sv;
3926
stats__cache_F_wbacks++;
3928
stats__cache_Z_wbacks++;
3932
sm->mbHasShared = True;
3934
/* mb_tidy_one_cacheline(); */
3937
/* Fetch the cacheline 'wix' from the backing store. The tag
3938
associated with 'wix' is assumed to have already been filled in;
3939
hence that is used to determine where in the backing store to read
3941
static __attribute__((noinline)) void cacheline_fetch ( UWord wix )
3950
VG_(printf)("scache fetch line %d\n", (Int)wix);
3952
tl_assert(wix >= 0 && wix < N_WAY_NENT);
3954
tag = cache_shmem.tags0[wix];
3955
cl = &cache_shmem.lyns0[wix];
3957
/* reject nonsense requests */
3958
tl_assert(is_valid_scache_tag(tag));
3962
find_ZF_for_reading( &lineZ, &lineF, tag );
3963
tl_assert( (lineZ && !lineF) || (!lineZ && lineF) );
3965
/* expand the data into the bottom layer of the tree, then get
3966
cacheline_normalise to build the descriptor array. */
3968
tl_assert(lineF->inUse);
3969
for (i = 0; i < N_LINE_ARANGE; i++) {
3970
cl->svals[i] = lineF->w32s[i];
3972
stats__cache_F_fetches++;
3974
for (i = 0; i < N_LINE_ARANGE; i++) {
3976
UWord ix = read_twobit_array( lineZ->ix2s, i );
3977
tl_assert(ix >= 0 && ix <= 3);
3978
sv = lineZ->dict[ix];
3982
stats__cache_Z_fetches++;
3984
normalise_CacheLine( cl );
3987
static void shmem__invalidate_scache ( void ) {
3989
if (0) VG_(printf)("scache inval\n");
3990
tl_assert(!is_valid_scache_tag(1));
3991
for (wix = 0; wix < N_WAY_NENT; wix++) {
3992
cache_shmem.tags0[wix] = 1/*INVALID*/;
3994
stats__cache_invals++;
3997
static void shmem__flush_and_invalidate_scache ( void ) {
4000
if (0) VG_(printf)("scache flush and invalidate\n");
4001
tl_assert(!is_valid_scache_tag(1));
4002
for (wix = 0; wix < N_WAY_NENT; wix++) {
4003
tag = cache_shmem.tags0[wix];
4004
if (tag == 1/*INVALID*/) {
4005
/* already invalid; nothing to do */
4007
tl_assert(is_valid_scache_tag(tag));
4008
cacheline_wback( wix );
4010
cache_shmem.tags0[wix] = 1/*INVALID*/;
4012
stats__cache_flushes++;
4013
stats__cache_invals++;
4017
/* ------------ Basic shadow memory read/write ops ------------ */
4019
static inline Bool aligned16 ( Addr a ) {
4020
return 0 == (a & 1);
4022
static inline Bool aligned32 ( Addr a ) {
4023
return 0 == (a & 3);
4025
static inline Bool aligned64 ( Addr a ) {
4026
return 0 == (a & 7);
4028
static inline UWord get_cacheline_offset ( Addr a ) {
4029
return (UWord)(a & (N_LINE_ARANGE - 1));
4031
static inline UWord get_treeno ( Addr a ) {
4032
return get_cacheline_offset(a) >> 3;
4034
static inline UWord get_tree_offset ( Addr a ) {
4038
static __attribute__((noinline))
4039
CacheLine* get_cacheline_MISS ( Addr a ); /* fwds */
4040
static inline CacheLine* get_cacheline ( Addr a )
4042
/* tag is 'a' with the in-line offset masked out,
4043
eg a[31]..a[4] 0000 */
4044
Addr tag = a & ~(N_LINE_ARANGE - 1);
4045
UWord wix = (a >> N_LINE_BITS) & (N_WAY_NENT - 1);
4046
stats__cache_totrefs++;
4047
if (LIKELY(tag == cache_shmem.tags0[wix])) {
4048
return &cache_shmem.lyns0[wix];
4050
return get_cacheline_MISS( a );
4054
static __attribute__((noinline))
4055
CacheLine* get_cacheline_MISS ( Addr a )
4057
/* tag is 'a' with the in-line offset masked out,
4058
eg a[31]..a[4] 0000 */
4062
Addr tag = a & ~(N_LINE_ARANGE - 1);
4063
UWord wix = (a >> N_LINE_BITS) & (N_WAY_NENT - 1);
4065
tl_assert(tag != cache_shmem.tags0[wix]);
4067
/* Dump the old line into the backing store. */
4068
stats__cache_totmisses++;
4070
cl = &cache_shmem.lyns0[wix];
4071
tag_old_p = &cache_shmem.tags0[wix];
4073
if (is_valid_scache_tag( *tag_old_p )) {
4074
/* EXPENSIVE and REDUNDANT: callee does it */
4076
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4077
cacheline_wback( wix );
4079
/* and reload the new one */
4081
cacheline_fetch( wix );
4083
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4087
static UShort pulldown_to_32 ( /*MOD*/SVal* tree, UWord toff, UShort descr ) {
4088
stats__cline_64to32pulldown++;
4091
tl_assert(descr & TREE_DESCR_64);
4093
descr &= ~TREE_DESCR_64;
4094
descr |= (TREE_DESCR_32_1 | TREE_DESCR_32_0);
4102
static UShort pulldown_to_16 ( /*MOD*/SVal* tree, UWord toff, UShort descr ) {
4103
stats__cline_32to16pulldown++;
4106
if (!(descr & TREE_DESCR_32_0)) {
4107
descr = pulldown_to_32(tree, 0, descr);
4109
tl_assert(descr & TREE_DESCR_32_0);
4111
descr &= ~TREE_DESCR_32_0;
4112
descr |= (TREE_DESCR_16_1 | TREE_DESCR_16_0);
4115
if (!(descr & TREE_DESCR_32_1)) {
4116
descr = pulldown_to_32(tree, 4, descr);
4118
tl_assert(descr & TREE_DESCR_32_1);
4120
descr &= ~TREE_DESCR_32_1;
4121
descr |= (TREE_DESCR_16_3 | TREE_DESCR_16_2);
4129
static UShort pulldown_to_8 ( /*MOD*/SVal* tree, UWord toff, UShort descr ) {
4130
stats__cline_16to8pulldown++;
4133
if (!(descr & TREE_DESCR_16_0)) {
4134
descr = pulldown_to_16(tree, 0, descr);
4136
tl_assert(descr & TREE_DESCR_16_0);
4138
descr &= ~TREE_DESCR_16_0;
4139
descr |= (TREE_DESCR_8_1 | TREE_DESCR_8_0);
4142
if (!(descr & TREE_DESCR_16_1)) {
4143
descr = pulldown_to_16(tree, 2, descr);
4145
tl_assert(descr & TREE_DESCR_16_1);
4147
descr &= ~TREE_DESCR_16_1;
4148
descr |= (TREE_DESCR_8_3 | TREE_DESCR_8_2);
4151
if (!(descr & TREE_DESCR_16_2)) {
4152
descr = pulldown_to_16(tree, 4, descr);
4154
tl_assert(descr & TREE_DESCR_16_2);
4156
descr &= ~TREE_DESCR_16_2;
4157
descr |= (TREE_DESCR_8_5 | TREE_DESCR_8_4);
4160
if (!(descr & TREE_DESCR_16_3)) {
4161
descr = pulldown_to_16(tree, 6, descr);
4163
tl_assert(descr & TREE_DESCR_16_3);
4165
descr &= ~TREE_DESCR_16_3;
4166
descr |= (TREE_DESCR_8_7 | TREE_DESCR_8_6);
4175
static UShort pullup_descr_to_16 ( UShort descr, UWord toff ) {
4179
mask = TREE_DESCR_8_1 | TREE_DESCR_8_0;
4180
tl_assert( (descr & mask) == mask );
4182
descr |= TREE_DESCR_16_0;
4185
mask = TREE_DESCR_8_3 | TREE_DESCR_8_2;
4186
tl_assert( (descr & mask) == mask );
4188
descr |= TREE_DESCR_16_1;
4191
mask = TREE_DESCR_8_5 | TREE_DESCR_8_4;
4192
tl_assert( (descr & mask) == mask );
4194
descr |= TREE_DESCR_16_2;
4197
mask = TREE_DESCR_8_7 | TREE_DESCR_8_6;
4198
tl_assert( (descr & mask) == mask );
4200
descr |= TREE_DESCR_16_3;
4208
static UShort pullup_descr_to_32 ( UShort descr, UWord toff ) {
4212
if (!(descr & TREE_DESCR_16_0))
4213
descr = pullup_descr_to_16(descr, 0);
4214
if (!(descr & TREE_DESCR_16_1))
4215
descr = pullup_descr_to_16(descr, 2);
4216
mask = TREE_DESCR_16_1 | TREE_DESCR_16_0;
4217
tl_assert( (descr & mask) == mask );
4219
descr |= TREE_DESCR_32_0;
4222
if (!(descr & TREE_DESCR_16_2))
4223
descr = pullup_descr_to_16(descr, 4);
4224
if (!(descr & TREE_DESCR_16_3))
4225
descr = pullup_descr_to_16(descr, 6);
4226
mask = TREE_DESCR_16_3 | TREE_DESCR_16_2;
4227
tl_assert( (descr & mask) == mask );
4229
descr |= TREE_DESCR_32_1;
4237
static Bool valid_value_is_above_me_32 ( UShort descr, UWord toff ) {
4240
return 0 != (descr & TREE_DESCR_64);
4246
static Bool valid_value_is_below_me_16 ( UShort descr, UWord toff ) {
4249
return 0 != (descr & (TREE_DESCR_8_1 | TREE_DESCR_8_0));
4251
return 0 != (descr & (TREE_DESCR_8_3 | TREE_DESCR_8_2));
4253
return 0 != (descr & (TREE_DESCR_8_5 | TREE_DESCR_8_4));
4255
return 0 != (descr & (TREE_DESCR_8_7 | TREE_DESCR_8_6));
4261
static void shadow_mem_read8 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4263
UWord cloff, tno, toff;
4266
stats__cline_read8s++;
4267
cl = get_cacheline(a);
4268
cloff = get_cacheline_offset(a);
4269
tno = get_treeno(a);
4270
toff = get_tree_offset(a); /* == 0 .. 7 */
4271
descr = cl->descrs[tno];
4272
if (UNLIKELY( !(descr & (TREE_DESCR_8_0 << toff)) )) {
4273
SVal* tree = &cl->svals[tno << 3];
4274
cl->descrs[tno] = pulldown_to_8(tree, toff, descr);
4276
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4278
svOld = cl->svals[cloff];
4279
svNew = msm__handle_read( thr_acc, a, svOld, 1 );
4280
cl->svals[cloff] = svNew;
4282
static void shadow_mem_read16 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4284
UWord cloff, tno, toff;
4287
stats__cline_read16s++;
4288
if (UNLIKELY(!aligned16(a))) goto slowcase;
4289
cl = get_cacheline(a);
4290
cloff = get_cacheline_offset(a);
4291
tno = get_treeno(a);
4292
toff = get_tree_offset(a); /* == 0, 2, 4 or 6 */
4293
descr = cl->descrs[tno];
4294
if (UNLIKELY( !(descr & (TREE_DESCR_16_0 << toff)) )) {
4295
if (valid_value_is_below_me_16(descr, toff)) {
4298
SVal* tree = &cl->svals[tno << 3];
4299
cl->descrs[tno] = pulldown_to_16(tree, toff, descr);
4302
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4304
svOld = cl->svals[cloff];
4305
svNew = msm__handle_read( thr_acc, a, svOld, 2 );
4306
cl->svals[cloff] = svNew;
4308
slowcase: /* misaligned, or must go further down the tree */
4309
stats__cline_16to8splits++;
4310
shadow_mem_read8( thr_acc, a + 0, 0/*unused*/ );
4311
shadow_mem_read8( thr_acc, a + 1, 0/*unused*/ );
4314
__attribute__((noinline))
4315
static void shadow_mem_read32_SLOW ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4317
UWord cloff, tno, toff;
4320
if (UNLIKELY(!aligned32(a))) goto slowcase;
4321
cl = get_cacheline(a);
4322
cloff = get_cacheline_offset(a);
4323
tno = get_treeno(a);
4324
toff = get_tree_offset(a); /* == 0 or 4 */
4325
descr = cl->descrs[tno];
4326
if (UNLIKELY( !(descr & (TREE_DESCR_32_0 << toff)) )) {
4327
if (valid_value_is_above_me_32(descr, toff)) {
4328
SVal* tree = &cl->svals[tno << 3];
4329
cl->descrs[tno] = pulldown_to_32(tree, toff, descr);
4334
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4336
svOld = cl->svals[cloff];
4337
svNew = msm__handle_read( thr_acc, a, svOld, 4 );
4338
cl->svals[cloff] = svNew;
4340
slowcase: /* misaligned, or must go further down the tree */
4341
stats__cline_32to16splits++;
4342
shadow_mem_read16( thr_acc, a + 0, 0/*unused*/ );
4343
shadow_mem_read16( thr_acc, a + 2, 0/*unused*/ );
4346
static void shadow_mem_read32 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4348
UWord cloff, tno, toff;
4350
stats__cline_read32s++;
4351
if (UNLIKELY(!aligned32(a))) goto slowcase;
4352
cl = get_cacheline(a);
4353
cloff = get_cacheline_offset(a);
4354
tno = get_treeno(a);
4355
toff = get_tree_offset(a); /* == 0 or 4 */
4356
descr = cl->descrs[tno];
4357
if (UNLIKELY( !(descr & (TREE_DESCR_32_0 << toff)) )) goto slowcase;
4358
{ SVal* p = &cl->svals[cloff];
4359
*p = msm__handle_read( thr_acc, a, *p, 4 );
4362
slowcase: /* misaligned, or not at this level in the tree */
4363
shadow_mem_read32_SLOW( thr_acc, a, uuOpaque );
4367
static void shadow_mem_read64 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4369
UWord cloff, tno, toff;
4372
stats__cline_read64s++;
4373
if (UNLIKELY(!aligned64(a))) goto slowcase;
4374
cl = get_cacheline(a);
4375
cloff = get_cacheline_offset(a);
4376
tno = get_treeno(a);
4377
toff = get_tree_offset(a); /* == 0, unused */
4378
descr = cl->descrs[tno];
4379
if (UNLIKELY( !(descr & TREE_DESCR_64) )) {
4382
svOld = cl->svals[cloff];
4383
svNew = msm__handle_read( thr_acc, a, svOld, 8 );
4384
cl->svals[cloff] = svNew;
4386
slowcase: /* misaligned, or must go further down the tree */
4387
stats__cline_64to32splits++;
4388
shadow_mem_read32( thr_acc, a + 0, 0/*unused*/ );
4389
shadow_mem_read32( thr_acc, a + 4, 0/*unused*/ );
4392
static void shadow_mem_write8 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4394
UWord cloff, tno, toff;
4397
stats__cline_write8s++;
4398
cl = get_cacheline(a);
4399
cloff = get_cacheline_offset(a);
4400
tno = get_treeno(a);
4401
toff = get_tree_offset(a); /* == 0 .. 7 */
4402
descr = cl->descrs[tno];
4403
if (UNLIKELY( !(descr & (TREE_DESCR_8_0 << toff)) )) {
4404
SVal* tree = &cl->svals[tno << 3];
4405
cl->descrs[tno] = pulldown_to_8(tree, toff, descr);
4407
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4409
svOld = cl->svals[cloff];
4410
svNew = msm__handle_write( thr_acc, a, svOld, 1 );
4411
cl->svals[cloff] = svNew;
4413
static void shadow_mem_write16 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4415
UWord cloff, tno, toff;
4418
stats__cline_write16s++;
4419
if (UNLIKELY(!aligned16(a))) goto slowcase;
4420
cl = get_cacheline(a);
4421
cloff = get_cacheline_offset(a);
4422
tno = get_treeno(a);
4423
toff = get_tree_offset(a); /* == 0, 2, 4 or 6 */
4424
descr = cl->descrs[tno];
4425
if (UNLIKELY( !(descr & (TREE_DESCR_16_0 << toff)) )) {
4426
if (valid_value_is_below_me_16(descr, toff)) {
4429
SVal* tree = &cl->svals[tno << 3];
4430
cl->descrs[tno] = pulldown_to_16(tree, toff, descr);
4433
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4435
svOld = cl->svals[cloff];
4436
svNew = msm__handle_write( thr_acc, a, svOld, 2 );
4437
cl->svals[cloff] = svNew;
4439
slowcase: /* misaligned, or must go further down the tree */
4440
stats__cline_16to8splits++;
4441
shadow_mem_write8( thr_acc, a + 0, 0/*unused*/ );
4442
shadow_mem_write8( thr_acc, a + 1, 0/*unused*/ );
4445
__attribute__((noinline))
4446
static void shadow_mem_write32_SLOW ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4448
UWord cloff, tno, toff;
4451
if (UNLIKELY(!aligned32(a))) goto slowcase;
4452
cl = get_cacheline(a);
4453
cloff = get_cacheline_offset(a);
4454
tno = get_treeno(a);
4455
toff = get_tree_offset(a); /* == 0 or 4 */
4456
descr = cl->descrs[tno];
4457
if (UNLIKELY( !(descr & (TREE_DESCR_32_0 << toff)) )) {
4458
if (valid_value_is_above_me_32(descr, toff)) {
4459
SVal* tree = &cl->svals[tno << 3];
4460
cl->descrs[tno] = pulldown_to_32(tree, toff, descr);
4465
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4467
svOld = cl->svals[cloff];
4468
svNew = msm__handle_write( thr_acc, a, svOld, 4 );
4469
cl->svals[cloff] = svNew;
4471
slowcase: /* misaligned, or must go further down the tree */
4472
stats__cline_32to16splits++;
4473
shadow_mem_write16( thr_acc, a + 0, 0/*unused*/ );
4474
shadow_mem_write16( thr_acc, a + 2, 0/*unused*/ );
4477
static void shadow_mem_write32 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4479
UWord cloff, tno, toff;
4481
stats__cline_write32s++;
4482
if (UNLIKELY(!aligned32(a))) goto slowcase;
4483
cl = get_cacheline(a);
4484
cloff = get_cacheline_offset(a);
4485
tno = get_treeno(a);
4486
toff = get_tree_offset(a); /* == 0 or 4 */
4487
descr = cl->descrs[tno];
4488
if (UNLIKELY( !(descr & (TREE_DESCR_32_0 << toff)) )) goto slowcase;
4489
{ SVal* p = &cl->svals[cloff];
4490
*p = msm__handle_write( thr_acc, a, *p, 4 );
4493
slowcase: /* misaligned, or must go further down the tree */
4494
shadow_mem_write32_SLOW( thr_acc, a, uuOpaque );
4498
static void shadow_mem_write64 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
4500
UWord cloff, tno, toff;
4503
stats__cline_write64s++;
4504
if (UNLIKELY(!aligned64(a))) goto slowcase;
4505
cl = get_cacheline(a);
4506
cloff = get_cacheline_offset(a);
4507
tno = get_treeno(a);
4508
toff = get_tree_offset(a); /* == 0, unused */
4509
descr = cl->descrs[tno];
4510
if (UNLIKELY( !(descr & TREE_DESCR_64) )) {
4513
svOld = cl->svals[cloff];
4514
svNew = msm__handle_write( thr_acc, a, svOld, 8 );
4515
cl->svals[cloff] = svNew;
4517
slowcase: /* misaligned, or must go further down the tree */
4518
stats__cline_64to32splits++;
4519
shadow_mem_write32( thr_acc, a + 0, 0/*unused*/ );
4520
shadow_mem_write32( thr_acc, a + 4, 0/*unused*/ );
4523
static void shadow_mem_set8 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
4525
UWord cloff, tno, toff;
4527
stats__cline_set8s++;
4528
cl = get_cacheline(a);
4529
cloff = get_cacheline_offset(a);
4530
tno = get_treeno(a);
4531
toff = get_tree_offset(a); /* == 0 .. 7 */
4532
descr = cl->descrs[tno];
4533
if (UNLIKELY( !(descr & (TREE_DESCR_8_0 << toff)) )) {
4534
SVal* tree = &cl->svals[tno << 3];
4535
cl->descrs[tno] = pulldown_to_8(tree, toff, descr);
4537
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4539
cl->svals[cloff] = svNew;
4541
static void shadow_mem_set16 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
4543
UWord cloff, tno, toff;
4545
stats__cline_set16s++;
4546
if (UNLIKELY(!aligned16(a))) goto slowcase;
4547
cl = get_cacheline(a);
4548
cloff = get_cacheline_offset(a);
4549
tno = get_treeno(a);
4550
toff = get_tree_offset(a); /* == 0, 2, 4 or 6 */
4551
descr = cl->descrs[tno];
4552
if (UNLIKELY( !(descr & (TREE_DESCR_16_0 << toff)) )) {
4553
if (valid_value_is_below_me_16(descr, toff)) {
4554
/* Writing at this level. Need to fix up 'descr'. */
4555
cl->descrs[tno] = pullup_descr_to_16(descr, toff);
4556
/* At this point, the tree does not match cl->descr[tno] any
4557
more. The assignments below will fix it up. */
4559
/* We can't indiscriminately write on the w16 node as in the
4560
w64 case, as that might make the node inconsistent with
4561
its parent. So first, pull down to this level. */
4562
SVal* tree = &cl->svals[tno << 3];
4563
cl->descrs[tno] = pulldown_to_16(tree, toff, descr);
4565
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4568
cl->svals[cloff + 0] = svNew;
4569
cl->svals[cloff + 1] = 0;
4571
slowcase: /* misaligned */
4572
stats__cline_16to8splits++;
4573
shadow_mem_set8( uu_thr_acc, a + 0, svNew );
4574
shadow_mem_set8( uu_thr_acc, a + 1, svNew );
4576
static void shadow_mem_set32 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
4578
UWord cloff, tno, toff;
4580
stats__cline_set32s++;
4581
if (UNLIKELY(!aligned32(a))) goto slowcase;
4582
cl = get_cacheline(a);
4583
cloff = get_cacheline_offset(a);
4584
tno = get_treeno(a);
4585
toff = get_tree_offset(a); /* == 0 or 4 */
4586
descr = cl->descrs[tno];
4587
if (UNLIKELY( !(descr & (TREE_DESCR_32_0 << toff)) )) {
4588
if (valid_value_is_above_me_32(descr, toff)) {
4589
/* We can't indiscriminately write on the w32 node as in the
4590
w64 case, as that might make the node inconsistent with
4591
its parent. So first, pull down to this level. */
4592
SVal* tree = &cl->svals[tno << 3];
4593
cl->descrs[tno] = pulldown_to_32(tree, toff, descr);
4595
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
4597
/* Writing at this level. Need to fix up 'descr'. */
4598
cl->descrs[tno] = pullup_descr_to_32(descr, toff);
4599
/* At this point, the tree does not match cl->descr[tno] any
4600
more. The assignments below will fix it up. */
4603
cl->svals[cloff + 0] = svNew;
4604
cl->svals[cloff + 1] = 0;
4605
cl->svals[cloff + 2] = 0;
4606
cl->svals[cloff + 3] = 0;
4608
slowcase: /* misaligned */
4609
stats__cline_32to16splits++;
4610
shadow_mem_set16( uu_thr_acc, a + 0, svNew );
4611
shadow_mem_set16( uu_thr_acc, a + 2, svNew );
4614
static void shadow_mem_set64 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
4616
UWord cloff, tno, toff;
4617
stats__cline_set64s++;
4618
if (UNLIKELY(!aligned64(a))) goto slowcase;
4619
cl = get_cacheline(a);
4620
cloff = get_cacheline_offset(a);
4621
tno = get_treeno(a);
4622
toff = get_tree_offset(a); /* == 0 */
4623
cl->descrs[tno] = TREE_DESCR_64;
4624
cl->svals[cloff + 0] = svNew;
4625
cl->svals[cloff + 1] = 0;
4626
cl->svals[cloff + 2] = 0;
4627
cl->svals[cloff + 3] = 0;
4628
cl->svals[cloff + 4] = 0;
4629
cl->svals[cloff + 5] = 0;
4630
cl->svals[cloff + 6] = 0;
4631
cl->svals[cloff + 7] = 0;
4633
slowcase: /* misaligned */
4634
stats__cline_64to32splits++;
4635
shadow_mem_set32( uu_thr_acc, a + 0, svNew );
4636
shadow_mem_set32( uu_thr_acc, a + 4, svNew );
4639
static SVal shadow_mem_get8 ( Addr a ) {
4641
UWord cloff, tno, toff;
4643
stats__cline_get8s++;
4644
cl = get_cacheline(a);
4645
cloff = get_cacheline_offset(a);
4646
tno = get_treeno(a);
4647
toff = get_tree_offset(a); /* == 0 .. 7 */
4648
descr = cl->descrs[tno];
4649
if (UNLIKELY( !(descr & (TREE_DESCR_8_0 << toff)) )) {
4650
SVal* tree = &cl->svals[tno << 3];
4651
cl->descrs[tno] = pulldown_to_8(tree, toff, descr);
4653
return cl->svals[cloff];
4656
static void shadow_mem_copy8 ( Addr src, Addr dst, Bool normalise ) {
4658
stats__cline_copy8s++;
4659
sv = shadow_mem_get8( src );
4661
if (UNLIKELY(clo_trace_level > 0)) {
4662
if (dst == clo_trace_addr) {
4663
Thread* thr = get_current_Thread();
4664
SVal sv_old = shadow_mem_get8( dst );
4665
msm__show_state_change( thr, dst, 1, 'w', sv_old, sv );
4669
shadow_mem_set8( NULL/*unused*/, dst, sv );
4673
/* ------------ Shadow memory range setting ops ------------ */
4675
static void shadow_mem_modify_range(
4679
void (*fn8) (Thread*,Addr,SVal),
4680
void (*fn16)(Thread*,Addr,SVal),
4681
void (*fn32)(Thread*,Addr,SVal),
4682
void (*fn64)(Thread*,Addr,SVal),
4686
/* fast track a couple of common cases */
4687
if (len == 4 && aligned32(a)) {
4688
fn32( thr, a, opaque );
4691
if (len == 8 && aligned64(a)) {
4692
fn64( thr, a, opaque );
4696
/* be completely general (but as efficient as possible) */
4697
if (len == 0) return;
4699
if (!aligned16(a) && len >= 1) {
4700
fn8( thr, a, opaque );
4703
tl_assert(aligned16(a));
4705
if (len == 0) return;
4707
if (!aligned32(a) && len >= 2) {
4708
fn16( thr, a, opaque );
4711
tl_assert(aligned32(a));
4713
if (len == 0) return;
4715
if (!aligned64(a) && len >= 4) {
4716
fn32( thr, a, opaque );
4719
tl_assert(aligned64(a));
4721
if (len == 0) return;
4724
tl_assert(aligned64(a));
4726
fn64( thr, a, opaque );
4730
tl_assert(aligned64(a));
4732
if (len == 0) return;
4735
tl_assert(aligned32(a));
4737
fn32( thr, a, opaque );
4741
if (len == 0) return;
4744
tl_assert(aligned16(a));
4746
fn16( thr, a, opaque );
4750
if (len == 0) return;
4753
fn8( thr, a, opaque );
4757
tl_assert(len == 0);
4760
/* Block-copy states (needed for implementing realloc()). */
4761
static void shadow_mem_copy_range ( Addr src, Addr dst, SizeT len )
1630
if (len > 100 * 1000 * 1000)
1631
VG_(message)(Vg_UserMsg,
1632
"Warning: set address range state: large range %d",
1635
/* Remove mutexes in recycled memory range from hash */
1636
find_mutex_range(a, a+len, cleanmx);
1638
/* Memory block may not be aligned or a whole word multiple. In neat cases,
1639
* we have to init len/4 words (len is in bytes). In nasty cases, it's
1640
* len/4+1 words. This works out which it is by aligning the block and
1641
* seeing if the end byte is in the same word as it is for the unaligned
1642
* block; if not, it's the awkward case. */
1643
end = VG_ROUNDUP(a + len, 4);
1644
a = VG_ROUNDDN(a, 4);
1648
case Vge_VirginInit:
1649
for ( ; a < end; a += 4) {
1650
//PROF_EVENT(31); PPP
1651
init_virgin_sword(a);
1655
case Vge_NonVirginInit:
1656
for ( ; a < end; a += 4) {
1657
//PROF_EVENT(31); PPP
1658
init_nonvirgin_sword(a);
1662
case Vge_SegmentInit:
1663
for ( ; a < end; a += 4) {
1664
//PROF_EVENT(31); PPP
1665
init_magically_inited_sword(a);
1670
for ( ; a < end; a += 4) {
1671
//PROF_EVENT(31); PPP
1672
init_error_sword(a);
4766
/* To be simple, just copy byte by byte. But so as not to wreck
4767
performance for later accesses to dst[0 .. len-1], normalise
4768
destination lines as we finish with them, and also normalise the
4769
line containing the first and last address. */
4770
for (i = 0; i < len; i++) {
4772
= get_cacheline_offset( dst+i+1 ) == 0 /* last in line */
4773
|| i == 0 /* first in range */
4774
|| i == len-1; /* last in range */
4775
shadow_mem_copy8( src+i, dst+i, normalise );
4779
static void shadow_mem_read_range ( Thread* thr, Addr a, SizeT len ) {
4780
shadow_mem_modify_range( thr, a, len,
4785
0/*opaque,ignored*/ );
4788
static void shadow_mem_write_range ( Thread* thr, Addr a, SizeT len ) {
4789
shadow_mem_modify_range( thr, a, len,
4794
0/*opaque,ignored*/ );
4797
static void shadow_mem_make_New ( Thread* thr, Addr a, SizeT len )
4799
if (UNLIKELY(clo_trace_level > 0)) {
4800
if (len > 0 && a <= clo_trace_addr && clo_trace_addr < a+len) {
4801
SVal sv_old = shadow_mem_get8( clo_trace_addr );
4802
msm__show_state_change( thr, a, (Int)len, 'p', sv_old, SHVAL_New );
4805
shadow_mem_modify_range( thr, a, len,
4810
SHVAL_New/*opaque*/ );
4814
/* Putting memory into the NoAccess state. This is hugely complicated
4815
by the problem of memory that contains locks.
4817
1. Examine the .mbHasLocks fields in all SecMaps in the range to be
4818
deleted. This quickly indicates if there are or might be any
4819
locks in the range to be deleted. Note that .mbHasLocks fields on
4820
SecMaps are not subject to scaching, so it safe to look at them
4821
without flushing the scache.
4823
2. Set the range to NoAccess. Clear the .mbHasShared and
4824
.mbHasLocks hint bits for any completely vacated SecMaps.
4825
Clearing the hint bits isn't necessary for correctness, but it
4826
is important to avoid ending up with hint bits being permanently
4827
set, which would render them pointless.
4829
3. If (1) indicated "definitely no locks", we're done. This is
4830
the fast and hopefully common case.
4832
Otherwise, the range contains some locks (or may do), so we have to
4833
go to considerable effort to tidy up.
4835
4. Make up a set containing the locks which are deleted:
4839
for each lk in map_locks {
4840
if lk's guest addr falls in the range to memory be deleted
4843
if lk is held, issue an error message - freeing memory
4844
containing a held lock
4847
5. If ToDelete is empty, there were in fact no locks in the range,
4848
despite what the .mbHasLocks hint bits indicated. We're done.
4850
6. Flush the scache. This is necessary both to bring the SecMap
4851
.mbHasShared fields up to date, and to bring the actual shadow
4852
values up to date. We will need to examine both of these.
4854
Invalidate the scache. This is necessary because we will be
4855
modifying values in the backing store (SecMaps) and need
4856
subsequent shmem accesses to get the new values.
4858
7. Modify all shadow words, by removing ToDelete from the lockset
4859
of all ShM and ShR states. Note this involves a complete scan
4860
over map_shmem, which is very expensive according to OProfile.
4861
Hence it depends critically on the size of each entry in
4862
map_shmem. See comments on definition of N_SECMAP_BITS above.
4864
Why is it safe to do (7) after (2) ? Because we're not
4865
interested in messing with ShR/M states which are going to be
4866
set to NoAccess anyway.
4868
Optimisation 1 (implemented): skip this step for SecMaps which
4869
do not have .mbHasShared set
4871
Optimisation 2 (not implemented): for each SecMap, have a
4872
summary lock set which is the union of all locks mentioned in
4873
locksets on this page (or any superset of it). Then skip step
4874
(2) if the summary lockset does not intersect with ToDelete.
4876
That's potentially cheap, since the usual lockset refinement
4877
only shrinks locksets; hence there is no point in updating the
4878
summary lockset for ShM/R -> ShM/R transitions. Therefore only
4879
need to do this for Excl->ShM/R transitions.
4881
8. Tell laog that these locks have disappeared.
4883
static void shadow_mem_make_NoAccess ( Thread* thr, Addr aIN, SizeT len )
4886
Addr gla, sma, firstSM, lastSM, firstA, lastA;
4887
WordSetID locksToDelete;
4891
VG_(printf)("make NoAccess ( %p, %d )\n", aIN, len );
4896
/* --- Step 1 --- */
4899
lastA = aIN + len - 1;
4901
firstSM = shmem__round_to_SecMap_base( firstA );
4902
lastSM = shmem__round_to_SecMap_base( lastA );
4903
tl_assert(firstSM <= lastSM);
4906
for (sma = firstSM; sma <= lastSM; sma += N_SECMAP_ARANGE) {
4907
if (shmem__get_mbHasLocks(sma)) {
4913
/* --- Step 2 --- */
4915
if (UNLIKELY(clo_trace_level > 0)) {
4916
if (len > 0 && firstA <= clo_trace_addr && clo_trace_addr <= lastA) {
4917
SVal sv_old = shadow_mem_get8( clo_trace_addr );
4918
msm__show_state_change( thr, firstA, (Int)len, 'p',
4919
sv_old, SHVAL_NoAccess );
4922
shadow_mem_modify_range( thr, firstA, len,
4927
SHVAL_NoAccess/*opaque*/ );
4929
for (sma = firstSM; sma <= lastSM; sma += N_SECMAP_ARANGE) {
4930
/* Is this sm entirely within the deleted range? */
4931
if (firstA <= sma && sma + N_SECMAP_ARANGE - 1 <= lastA) {
4932
/* Yes. Clear the hint bits. */
4933
shmem__set_mbHasLocks( sma, False );
4934
shmem__set_mbHasShared( sma, False );
4938
/* --- Step 3 --- */
4943
/* --- Step 4 --- */
4946
VG_(printf)("shadow_mem_make_NoAccess(%p, %u, %p): maybe slow case\n",
4947
(void*)firstA, (UWord)len, (void*)lastA);
4948
locksToDelete = HG_(emptyWS)( univ_lsets );
1677
VG_(printf)("init_status = %u\n", status);
1678
VG_(tool_panic)("Unexpected Vge_InitStatus");
1683
static void make_segment_readable ( Addr a, SizeT len )
1685
//PROF_EVENT(??); PPP
1686
set_address_range_state ( a, len, Vge_SegmentInit );
1689
static void make_writable ( Addr a, SizeT len )
1691
//PROF_EVENT(36); PPP
1692
set_address_range_state( a, len, Vge_VirginInit );
1695
static void make_readable ( Addr a, SizeT len )
1697
//PROF_EVENT(37); PPP
1698
set_address_range_state( a, len, Vge_VirginInit );
1702
/* Block-copy states (needed for implementing realloc()). */
1703
static void copy_address_range_state(Addr src, Addr dst, SizeT len)
1707
//PROF_EVENT(40); PPP
1708
for (i = 0; i < len; i += 4) {
1709
shadow_word sword = *(get_sword_addr ( src+i ));
1710
//PROF_EVENT(41); PPP
1711
set_sword ( dst+i, sword );
1715
// SSS: put these somewhere better
1716
static void hg_mem_read (Addr a, SizeT data_size, ThreadId tid);
1717
static void hg_mem_write(Addr a, SizeT data_size, ThreadId tid);
1719
__attribute__((unused))
1720
static void hg_mem_help_read_1(Addr a) VG_REGPARM(1);
1721
__attribute__((unused))
1722
static void hg_mem_help_read_2(Addr a) VG_REGPARM(1);
1723
__attribute__((unused))
1724
static void hg_mem_help_read_4(Addr a) VG_REGPARM(1);
1725
__attribute__((unused))
1726
static void hg_mem_help_read_N(Addr a, SizeT size) VG_REGPARM(2);
1728
__attribute__((unused))
1729
static void hg_mem_help_write_1(Addr a, UInt val) VG_REGPARM(2);
1730
__attribute__((unused))
1731
static void hg_mem_help_write_2(Addr a, UInt val) VG_REGPARM(2);
1732
__attribute__((unused))
1733
static void hg_mem_help_write_4(Addr a, UInt val) VG_REGPARM(2);
1734
__attribute__((unused))
1735
static void hg_mem_help_write_N(Addr a, SizeT size) VG_REGPARM(2);
1737
__attribute__((unused))
1738
static void bus_lock(void);
1739
__attribute__((unused))
1740
static void bus_unlock(void);
1743
void hg_pre_mem_read(CorePart part, ThreadId tid,
1744
Char* s, Addr base, SizeT size )
1746
if (tid > 50) { VG_(printf)("pid = %d, s = '%s', part = %d\n", tid, s, part); VG_(tool_panic)("a");}
1747
hg_mem_read(base, size, tid);
1751
void hg_pre_mem_read_asciiz(CorePart part, ThreadId tid,
1752
Char* s, Addr base )
1754
hg_mem_read(base, VG_(strlen)((Char*)base), tid);
1758
void hg_pre_mem_write(CorePart part, ThreadId tid,
1759
Char* s, Addr base, SizeT size )
1761
hg_mem_write(base, size, tid);
1767
void hg_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
1769
/* Ignore the permissions, just make it readable. Seems to work... */
1770
make_segment_readable(a, len);
1775
void hg_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
4950
/* FIXME: don't iterate over the complete lock set */
4951
HG_(initIterFM)( map_locks );
4952
while (HG_(nextIterFM)( map_locks,
4953
(Word*)&gla, (Word*)&lk )) {
4954
tl_assert(is_sane_LockN(lk));
4955
if (gla < firstA || gla > lastA)
4957
locksToDelete = HG_(addToWS)( univ_lsets, locksToDelete, (Word)lk );
4958
/* If the lock is held, we must remove it from the currlock sets
4959
of all threads that hold it. Also take the opportunity to
4960
report an error. To report an error we need to know at least
4961
one of the threads that holds it; really we should mention
4962
them all, but that's too much hassle. So choose one
4965
tl_assert(!HG_(isEmptyBag)(lk->heldBy));
4966
record_error_FreeMemLock( (Thread*)HG_(anyElementOfBag)(lk->heldBy),
4968
/* remove lock from locksets of all owning threads */
4969
remove_Lock_from_locksets_of_all_owning_Threads( lk );
4970
/* Leave lk->heldBy in place; del_Lock below will free it up. */
4973
HG_(doneIterFM)( map_locks );
4975
/* --- Step 5 --- */
4977
if (HG_(isEmptyWS)( univ_lsets, locksToDelete ))
4980
/* --- Step 6 --- */
4982
shmem__flush_and_invalidate_scache();
4984
/* --- Step 7 --- */
4987
VG_(printf)("shadow_mem_make_NoAccess(%p, %u, %p): definitely slow case\n",
4988
(void*)firstA, (UWord)len, (void*)lastA);
4990
/* Modify all shadow words, by removing locksToDelete from the lockset
4991
of all ShM and ShR states.
4992
Optimisation 1: skip SecMaps which do not have .mbHasShared set
4994
{ Int stats_SMs = 0, stats_SMs_scanned = 0;
5000
HG_(initIterFM)( map_shmem );
5001
while (HG_(nextIterFM)( map_shmem,
5002
(Word*)&ga, (Word*)&sm )) {
5005
/* Skip this SecMap if the summary bit indicates it is safe to
5007
if (!sm->mbHasShared)
5009
stats_SMs_scanned++;
5010
initSecMapIter( &itr );
5011
while (stepSecMapIter( &w32p, &itr, sm )) {
5014
UInt lset_old, tset_old, lset_new;
5016
if (LIKELY( !is_SHVAL_Sh(wold) ))
5018
isM = is_SHVAL_ShM(wold);
5019
lset_old = un_SHVAL_Sh_lset(wold);
5020
tset_old = un_SHVAL_Sh_tset(wold);
5021
lset_new = HG_(minusWS)( univ_lsets, lset_old, locksToDelete );
5022
wnew = isM ? mk_SHVAL_ShM(tset_old, lset_new)
5023
: mk_SHVAL_ShR(tset_old, lset_new);
5028
HG_(doneIterFM)( map_shmem );
5029
if (SHOW_EXPENSIVE_STUFF)
5030
VG_(printf)("shadow_mem_make_NoAccess: %d SMs, %d scanned\n",
5031
stats_SMs, stats_SMs_scanned);
5034
/* Now we have to free up the Locks in locksToDelete and remove
5035
any mention of them from admin_locks and map_locks. This is
5037
{ Lock* lkprev = NULL;
5040
if (lk == NULL) break;
5041
if (lkprev) tl_assert(lkprev->admin == lk);
5043
if (!HG_(elemWS)(univ_lsets, locksToDelete, (Word)lk)) {
5048
/* Need to delete 'lk' */
5049
if (lkprev == NULL) {
5050
admin_locks = lk->admin;
5052
lkprev->admin = lk->admin;
5054
/* and get it out of map_locks */
5055
map_locks_delete(lk->guestaddr);
5056
/* release storage (incl. associated .heldBy Bag) */
5057
{ Lock* tmp = lk->admin;
5064
/* --- Step 8 --- */
5066
/* update lock order acquisition graph */
5067
laog__handle_lock_deletions( locksToDelete );
5069
if (0) all__sanity_check("Make NoAccess");
5073
/*----------------------------------------------------------------*/
5074
/*--- Event handlers (evh__* functions) ---*/
5075
/*--- plus helpers (evhH__* functions) ---*/
5076
/*----------------------------------------------------------------*/
5078
/*--------- Event handler helpers (evhH__* functions) ---------*/
5080
/* Create a new segment for 'thr', making it depend (.prev) on its
5081
existing segment, bind together the SegmentID and Segment, and
5082
return both of them. Also update 'thr' so it references the new
5085
void evhH__start_new_segment_for_thread ( /*OUT*/SegmentID* new_segidP,
5086
/*OUT*/Segment** new_segP,
5090
tl_assert(new_segP);
5091
tl_assert(new_segidP);
5092
tl_assert(is_sane_Thread(thr));
5093
cur_seg = map_segments_lookup( thr->csegid );
5095
tl_assert(cur_seg->thr == thr); /* all sane segs should point back
5096
at their owner thread. */
5097
*new_segP = mk_Segment( thr, cur_seg, NULL/*other*/ );
5098
*new_segidP = alloc_SegmentID();
5099
map_segments_add( *new_segidP, *new_segP );
5100
thr->csegid = *new_segidP;
5104
/* The lock at 'lock_ga' has acquired a writer. Make all necessary
5105
updates, and also do all possible error checks. */
5107
void evhH__post_thread_w_acquires_lock ( Thread* thr,
5108
LockKind lkk, Addr lock_ga )
5112
/* Basically what we need to do is call lockN_acquire_writer.
5113
However, that will barf if any 'invalid' lock states would
5114
result. Therefore check before calling. Side effect is that
5115
'is_sane_LockN(lk)' is both a pre- and post-condition of this
5118
Because this routine is only called after successful lock
5119
acquisition, we should not be asked to move the lock into any
5120
invalid states. Requests to do so are bugs in libpthread, since
5121
that should have rejected any such requests. */
5123
/* be paranoid w.r.t hint bits, even if lock_ga is complete
5125
shmem__set_mbHasLocks( lock_ga, True );
5127
tl_assert(is_sane_Thread(thr));
5128
/* Try to find the lock. If we can't, then create a new one with
5130
lk = map_locks_lookup_or_create(
5131
lkk, lock_ga, map_threads_reverse_lookup_SLOW(thr) );
5132
tl_assert( is_sane_LockN(lk) );
5133
shmem__set_mbHasLocks( lock_ga, True );
5135
if (lk->heldBy == NULL) {
5136
/* the lock isn't held. Simple. */
5137
tl_assert(!lk->heldW);
5138
lockN_acquire_writer( lk, thr );
5142
/* So the lock is already held. If held as a r-lock then
5143
libpthread must be buggy. */
5144
tl_assert(lk->heldBy);
5146
record_error_Misc( thr, "Bug in libpthread: write lock "
5147
"granted on rwlock which is currently rd-held");
5151
/* So the lock is held in w-mode. If it's held by some other
5152
thread, then libpthread must be buggy. */
5153
tl_assert(HG_(sizeUniqueBag)(lk->heldBy) == 1); /* from precondition */
5155
if (thr != (Thread*)HG_(anyElementOfBag)(lk->heldBy)) {
5156
record_error_Misc( thr, "Bug in libpthread: write lock "
5157
"granted on mutex/rwlock which is currently "
5158
"wr-held by a different thread");
5162
/* So the lock is already held in w-mode by 'thr'. That means this
5163
is an attempt to lock it recursively, which is only allowable
5164
for LK_mbRec kinded locks. Since this routine is called only
5165
once the lock has been acquired, this must also be a libpthread
5167
if (lk->kind != LK_mbRec) {
5168
record_error_Misc( thr, "Bug in libpthread: recursive write lock "
5169
"granted on mutex/wrlock which does not "
5170
"support recursion");
5174
/* So we are recursively re-locking a lock we already w-hold. */
5175
lockN_acquire_writer( lk, thr );
5179
/* check lock order acquisition graph, and update. This has to
5180
happen before the lock is added to the thread's locksetA/W. */
5181
laog__pre_thread_acquires_lock( thr, lk );
5182
/* update the thread's held-locks set */
5183
thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (Word)lk );
5184
thr->locksetW = HG_(addToWS)( univ_lsets, thr->locksetW, (Word)lk );
5188
tl_assert(is_sane_LockN(lk));
5192
/* The lock at 'lock_ga' has acquired a reader. Make all necessary
5193
updates, and also do all possible error checks. */
5195
void evhH__post_thread_r_acquires_lock ( Thread* thr,
5196
LockKind lkk, Addr lock_ga )
5200
/* Basically what we need to do is call lockN_acquire_reader.
5201
However, that will barf if any 'invalid' lock states would
5202
result. Therefore check before calling. Side effect is that
5203
'is_sane_LockN(lk)' is both a pre- and post-condition of this
5206
Because this routine is only called after successful lock
5207
acquisition, we should not be asked to move the lock into any
5208
invalid states. Requests to do so are bugs in libpthread, since
5209
that should have rejected any such requests. */
5211
/* be paranoid w.r.t hint bits, even if lock_ga is complete
5213
shmem__set_mbHasLocks( lock_ga, True );
5215
tl_assert(is_sane_Thread(thr));
5216
/* Try to find the lock. If we can't, then create a new one with
5217
kind 'lkk'. Only a reader-writer lock can be read-locked,
5218
hence the first assertion. */
5219
tl_assert(lkk == LK_rdwr);
5220
lk = map_locks_lookup_or_create(
5221
lkk, lock_ga, map_threads_reverse_lookup_SLOW(thr) );
5222
tl_assert( is_sane_LockN(lk) );
5223
shmem__set_mbHasLocks( lock_ga, True );
5225
if (lk->heldBy == NULL) {
5226
/* the lock isn't held. Simple. */
5227
tl_assert(!lk->heldW);
5228
lockN_acquire_reader( lk, thr );
5232
/* So the lock is already held. If held as a w-lock then
5233
libpthread must be buggy. */
5234
tl_assert(lk->heldBy);
5236
record_error_Misc( thr, "Bug in libpthread: read lock "
5237
"granted on rwlock which is "
5238
"currently wr-held");
5242
/* Easy enough. In short anybody can get a read-lock on a rwlock
5243
provided it is either unlocked or already in rd-held. */
5244
lockN_acquire_reader( lk, thr );
5248
/* check lock order acquisition graph, and update. This has to
5249
happen before the lock is added to the thread's locksetA/W. */
5250
laog__pre_thread_acquires_lock( thr, lk );
5251
/* update the thread's held-locks set */
5252
thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (Word)lk );
5253
/* but don't update thr->locksetW, since lk is only rd-held */
5257
tl_assert(is_sane_LockN(lk));
5261
/* The lock at 'lock_ga' is just about to be unlocked. Make all
5262
necessary updates, and also do all possible error checks. */
5264
void evhH__pre_thread_releases_lock ( Thread* thr,
5265
Addr lock_ga, Bool isRDWR )
5270
/* This routine is called prior to a lock release, before
5271
libpthread has had a chance to validate the call. Hence we need
5272
to detect and reject any attempts to move the lock into an
5273
invalid state. Such attempts are bugs in the client.
5275
isRDWR is True if we know from the wrapper context that lock_ga
5276
should refer to a reader-writer lock, and is False if [ditto]
5277
lock_ga should refer to a standard mutex. */
5279
/* be paranoid w.r.t hint bits, even if lock_ga is complete
5281
shmem__set_mbHasLocks( lock_ga, True );
5283
tl_assert(is_sane_Thread(thr));
5284
lock = map_locks_maybe_lookup( lock_ga );
5287
/* We know nothing about a lock at 'lock_ga'. Nevertheless
5288
the client is trying to unlock it. So complain, then ignore
5290
record_error_UnlockBogus( thr, lock_ga );
5294
tl_assert(lock->guestaddr == lock_ga);
5295
tl_assert(is_sane_LockN(lock));
5297
if (isRDWR && lock->kind != LK_rdwr) {
5298
record_error_Misc( thr, "pthread_rwlock_unlock with a "
5299
"pthread_mutex_t* argument " );
5301
if ((!isRDWR) && lock->kind == LK_rdwr) {
5302
record_error_Misc( thr, "pthread_mutex_unlock with a "
5303
"pthread_rwlock_t* argument " );
5306
if (!lock->heldBy) {
5307
/* The lock is not held. This indicates a serious bug in the
5309
tl_assert(!lock->heldW);
5310
record_error_UnlockUnlocked( thr, lock );
5311
tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lock ));
5312
tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock ));
5316
/* The lock is held. Is this thread one of the holders? If not,
5317
report a bug in the client. */
5318
n = HG_(elemBag)( lock->heldBy, (Word)thr );
5321
/* We are not a current holder of the lock. This is a bug in
5322
the guest, and (per POSIX pthread rules) the unlock
5323
attempt will fail. So just complain and do nothing
5325
Thread* realOwner = (Thread*)HG_(anyElementOfBag)( lock->heldBy );
5326
tl_assert(is_sane_Thread(realOwner));
5327
tl_assert(realOwner != thr);
5328
tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lock ));
5329
tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock ));
5330
record_error_UnlockForeign( thr, realOwner, lock );
5334
/* Ok, we hold the lock 'n' times. */
5337
lockN_release( lock, thr );
5343
tl_assert(lock->heldBy);
5344
tl_assert(n == HG_(elemBag)( lock->heldBy, (Word)thr ));
5345
/* We still hold the lock. So either it's a recursive lock
5346
or a rwlock which is currently r-held. */
5347
tl_assert(lock->kind == LK_mbRec
5348
|| (lock->kind == LK_rdwr && !lock->heldW));
5349
tl_assert(HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lock ));
5351
tl_assert(HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock ));
5353
tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock ));
5355
/* We no longer hold the lock. */
5357
tl_assert(0 == HG_(elemBag)( lock->heldBy, (Word)thr ));
5359
/* update this thread's lockset accordingly. */
5361
= HG_(delFromWS)( univ_lsets, thr->locksetA, (Word)lock );
5363
= HG_(delFromWS)( univ_lsets, thr->locksetW, (Word)lock );
5368
tl_assert(is_sane_LockN(lock));
5372
/*--------- Event handlers proper (evh__* functions) ---------*/
5374
/* What is the Thread* for the currently running thread? This is
5375
absolutely performance critical. We receive notifications from the
5376
core for client code starts/stops, and cache the looked-up result
5377
in 'current_Thread'. Hence, for the vast majority of requests,
5378
finding the current thread reduces to a read of a global variable,
5379
provided get_current_Thread_in_C_C is inlined.
5381
Outside of client code, current_Thread is NULL, and presumably
5382
any uses of it will cause a segfault. Hence:
5384
- for uses definitely within client code, use
5385
get_current_Thread_in_C_C.
5387
- for all other uses, use get_current_Thread.
5390
static Thread* current_Thread = NULL;
5392
static void evh__start_client_code ( ThreadId tid, ULong nDisp ) {
5393
if (0) VG_(printf)("start %d %llu\n", (Int)tid, nDisp);
5394
tl_assert(current_Thread == NULL);
5395
current_Thread = map_threads_lookup( tid );
5396
tl_assert(current_Thread != NULL);
5398
static void evh__stop_client_code ( ThreadId tid, ULong nDisp ) {
5399
if (0) VG_(printf)(" stop %d %llu\n", (Int)tid, nDisp);
5400
tl_assert(current_Thread != NULL);
5401
current_Thread = NULL;
5403
static inline Thread* get_current_Thread_in_C_C ( void ) {
5404
return current_Thread;
5406
static inline Thread* get_current_Thread ( void ) {
5409
thr = get_current_Thread_in_C_C();
5412
/* evidently not in client code. Do it the slow way. */
5413
coretid = VG_(get_running_tid)();
5414
/* FIXME: get rid of the following kludge. It exists because
5415
evim__new_mem is called during initialisation (as notification
5416
of initial memory layout) and VG_(get_running_tid)() returns
5417
VG_INVALID_THREADID at that point. */
5418
if (coretid == VG_INVALID_THREADID)
5419
coretid = 1; /* KLUDGE */
5420
thr = map_threads_lookup( coretid );
5425
void evh__new_mem ( Addr a, SizeT len ) {
5426
if (SHOW_EVENTS >= 2)
5427
VG_(printf)("evh__new_mem(%p, %lu)\n", (void*)a, len );
5428
shadow_mem_make_New( get_current_Thread(), a, len );
5429
if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5430
all__sanity_check("evh__new_mem-post");
5434
void evh__new_mem_w_perms ( Addr a, SizeT len,
5435
Bool rr, Bool ww, Bool xx ) {
5436
if (SHOW_EVENTS >= 1)
5437
VG_(printf)("evh__new_mem_w_perms(%p, %lu, %d,%d,%d)\n",
5438
(void*)a, len, (Int)rr, (Int)ww, (Int)xx );
5440
shadow_mem_make_New( get_current_Thread(), a, len );
5441
if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5442
all__sanity_check("evh__new_mem_w_perms-post");
5446
void evh__set_perms ( Addr a, SizeT len,
5447
Bool rr, Bool ww, Bool xx ) {
5448
if (SHOW_EVENTS >= 1)
5449
VG_(printf)("evh__set_perms(%p, %lu, %d,%d,%d)\n",
5450
(void*)a, len, (Int)rr, (Int)ww, (Int)xx );
5451
/* Hmm. What should we do here, that actually makes any sense?
5452
Let's say: if neither readable nor writable, then declare it
5453
NoAccess, else leave it alone. */
5455
shadow_mem_make_NoAccess( get_current_Thread(), a, len );
5456
if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5457
all__sanity_check("evh__set_perms-post");
5461
void evh__die_mem ( Addr a, SizeT len ) {
5462
if (SHOW_EVENTS >= 2)
5463
VG_(printf)("evh__die_mem(%p, %lu)\n", (void*)a, len );
5464
shadow_mem_make_NoAccess( get_current_Thread(), a, len );
5465
if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5466
all__sanity_check("evh__die_mem-post");
5470
void evh__pre_thread_ll_create ( ThreadId parent, ThreadId child )
5472
if (SHOW_EVENTS >= 1)
5473
VG_(printf)("evh__pre_thread_ll_create(p=%d, c=%d)\n",
5474
(Int)parent, (Int)child );
5476
if (parent != VG_INVALID_THREADID) {
5482
tl_assert(is_sane_ThreadId(parent));
5483
tl_assert(is_sane_ThreadId(child));
5484
tl_assert(parent != child);
5486
thr_p = map_threads_maybe_lookup( parent );
5487
thr_c = map_threads_maybe_lookup( child );
5489
tl_assert(thr_p != NULL);
5490
tl_assert(thr_c == NULL);
5492
/* Create a new thread record for the child. */
5493
// FIXME: code duplication from init_data_structures
5494
segid_c = alloc_SegmentID();
5495
seg_c = mk_Segment( NULL/*thr*/, NULL/*prev*/, NULL/*other*/ );
5496
map_segments_add( segid_c, seg_c );
5498
/* a Thread for the new thread ... */
5499
thr_c = mk_Thread( segid_c );
5502
/* and bind it in the thread-map table */
5503
map_threads[child] = thr_c;
5505
/* Record where the parent is so we can later refer to this in
5508
On amd64-linux, this entails a nasty glibc-2.5 specific hack.
5509
The stack snapshot is taken immediately after the parent has
5510
returned from its sys_clone call. Unfortunately there is no
5511
unwind info for the insn following "syscall" - reading the
5512
glibc sources confirms this. So we ask for a snapshot to be
5513
taken as if RIP was 3 bytes earlier, in a place where there
5514
is unwind info. Sigh.
5516
{ Word first_ip_delta = 0;
5517
# if defined(VGP_amd64_linux)
5518
first_ip_delta = -3;
5520
thr_c->created_at = VG_(record_ExeContext)(parent, first_ip_delta);
5523
/* Now, mess with segments. */
5524
if (clo_happens_before >= 1) {
5525
/* Make the child's new segment depend on the parent */
5526
seg_c->other = map_segments_lookup( thr_p->csegid );
5527
seg_c->other_hint = 'c';
5528
seg_c->vts = tick_VTS( thr_c, seg_c->other->vts );
5529
tl_assert(seg_c->prev == NULL);
5530
/* and start a new segment for the parent. */
5531
{ SegmentID new_segid = 0; /* bogus */
5532
Segment* new_seg = NULL;
5533
evhH__start_new_segment_for_thread( &new_segid, &new_seg,
5535
tl_assert(is_sane_SegmentID(new_segid));
5536
tl_assert(is_sane_Segment(new_seg));
5537
new_seg->vts = tick_VTS( thr_p, new_seg->prev->vts );
5538
tl_assert(new_seg->other == NULL);
5543
if (clo_sanity_flags & SCE_THREADS)
5544
all__sanity_check("evh__pre_thread_create-post");
5548
void evh__pre_thread_ll_exit ( ThreadId quit_tid )
5552
if (SHOW_EVENTS >= 1)
5553
VG_(printf)("evh__pre_thread_ll_exit(thr=%d)\n",
5556
/* quit_tid has disappeared without joining to any other thread.
5557
Therefore there is no synchronisation event associated with its
5558
exit and so we have to pretty much treat it as if it was still
5559
alive but mysteriously making no progress. That is because, if
5560
we don't know when it really exited, then we can never say there
5561
is a point in time when we're sure the thread really has
5562
finished, and so we need to consider the possibility that it
5563
lingers indefinitely and continues to interact with other
5565
/* However, it might have rendezvous'd with a thread that called
5566
pthread_join with this one as arg, prior to this point (that's
5567
how NPTL works). In which case there has already been a prior
5568
sync event. So in any case, just let the thread exit. On NPTL,
5569
all thread exits go through here. */
5570
tl_assert(is_sane_ThreadId(quit_tid));
5571
thr_q = map_threads_maybe_lookup( quit_tid );
5572
tl_assert(thr_q != NULL);
5574
/* Complain if this thread holds any locks. */
5575
nHeld = HG_(cardinalityWS)( univ_lsets, thr_q->locksetA );
5576
tl_assert(nHeld >= 0);
5579
VG_(sprintf)(buf, "Exiting thread still holds %d lock%s",
5580
nHeld, nHeld > 1 ? "s" : "");
5581
record_error_Misc( thr_q, buf );
5584
/* About the only thing we do need to do is clear the map_threads
5585
entry, in order that the Valgrind core can re-use it. */
5586
map_threads_delete( quit_tid );
5588
if (clo_sanity_flags & SCE_THREADS)
5589
all__sanity_check("evh__pre_thread_ll_exit-post");
5593
void evh__HG_PTHREAD_JOIN_POST ( ThreadId stay_tid, Thread* quit_thr )
5595
Int stats_SMs, stats_SMs_scanned, stats_reExcls;
5601
if (SHOW_EVENTS >= 1)
5602
VG_(printf)("evh__post_thread_join(stayer=%d, quitter=%p)\n",
5603
(Int)stay_tid, quit_thr );
5605
tl_assert(is_sane_ThreadId(stay_tid));
5607
thr_s = map_threads_maybe_lookup( stay_tid );
5609
tl_assert(thr_s != NULL);
5610
tl_assert(thr_q != NULL);
5611
tl_assert(thr_s != thr_q);
5613
if (clo_happens_before >= 1) {
5614
/* Start a new segment for the stayer */
5615
SegmentID new_segid = 0; /* bogus */
5616
Segment* new_seg = NULL;
5617
evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr_s );
5618
tl_assert(is_sane_SegmentID(new_segid));
5619
tl_assert(is_sane_Segment(new_seg));
5620
/* and make it depend on the quitter's last segment */
5621
tl_assert(new_seg->other == NULL);
5622
new_seg->other = map_segments_lookup( thr_q->csegid );
5623
new_seg->other_hint = 'j';
5624
tl_assert(new_seg->thr == thr_s);
5625
new_seg->vts = tickL_and_joinR_VTS( thr_s, new_seg->prev->vts,
5626
new_seg->other->vts );
5629
// FIXME: error-if: exiting thread holds any locks
5630
// or should evh__pre_thread_ll_exit do that?
5632
/* Delete thread from ShM/ShR thread sets and restore Excl states
5633
where appropriate */
5635
/* When Thread(t) joins to Thread(u):
5637
scan all shadow memory. For each ShM/ShR thread set, replace
5638
't' in each set with 'u'. If this results in a singleton 'u',
5639
change the state to Excl(u->csegid).
5641
Optimisation: tag each SecMap with a superset of the union of
5642
the thread sets in the SecMap. Then if the tag set does not
5643
include 't' then the SecMap can be skipped, because there is no
5644
't' to change to anything else.
5646
Problem is that the tag set needs to be updated often, after
5647
every ShR/ShM store. (that increases the thread set of the
5650
--> Compromise. Tag each SecMap with a .mbHasShared bit which
5651
must be set true if any ShR/ShM on the page. Set this for
5652
any transitions into ShR/ShM on the page. Then skip page if
5655
.mbHasShared bits are (effectively) cached in cache_shmem.
5656
Hence that must be flushed before we can safely consult them.
5658
Since we're modifying the backing store, we also need to
5659
invalidate cache_shmem, so that subsequent memory references get
5660
up to date shadow values.
5662
shmem__flush_and_invalidate_scache();
5664
stats_SMs = stats_SMs_scanned = stats_reExcls = 0;
5665
HG_(initIterFM)( map_shmem );
5666
while (HG_(nextIterFM)( map_shmem,
5667
(Word*)&ga, (Word*)&sm )) {
5672
/* Skip this SecMap if the summary bit indicates it is safe to
5674
if (!sm->mbHasShared)
5676
stats_SMs_scanned++;
5677
initSecMapIter( &itr );
5678
while (stepSecMapIter( &w32p, &itr, sm )) {
5681
UInt lset_old, tset_old, tset_new;
5683
if (!is_SHVAL_Sh(wold))
5685
isM = is_SHVAL_ShM(wold);
5686
lset_old = un_SHVAL_Sh_lset(wold);
5687
tset_old = un_SHVAL_Sh_tset(wold);
5688
/* Subst thr_q -> thr_s in the thread set. Longwindedly, if
5689
thr_q is in the set, delete it and add thr_s; else leave
5690
it alone. FIXME: is inefficient - make a special
5691
substInWS method for this. */
5693
= HG_(elemWS)( univ_tsets, tset_old, (Word)thr_q )
5696
HG_(delFromWS)( univ_tsets, tset_old, (Word)thr_q ),
5701
tl_assert(HG_(cardinalityWS)(univ_tsets, tset_new)
5702
<= HG_(cardinalityWS)(univ_tsets, tset_old));
5705
VG_(printf)("smga %p: old 0x%x new 0x%x ",
5706
ga, tset_old, tset_new);
5707
HG_(ppWS)( univ_tsets, tset_old );
5708
VG_(printf)(" --> ");
5709
HG_(ppWS)( univ_tsets, tset_new );
5712
if (HG_(isSingletonWS)( univ_tsets, tset_new, (Word)thr_s )) {
5713
/* This word returns to Excl state */
5714
wnew = mk_SHVAL_Excl(thr_s->csegid);
5717
wnew = isM ? mk_SHVAL_ShM(tset_new, lset_old)
5718
: mk_SHVAL_ShR(tset_new, lset_old);
5723
HG_(doneIterFM)( map_shmem );
5725
if (SHOW_EXPENSIVE_STUFF)
5726
VG_(printf)("evh__post_thread_join: %d SMs, "
5727
"%d scanned, %d re-Excls\n",
5728
stats_SMs, stats_SMs_scanned, stats_reExcls);
5730
/* This holds because, at least when using NPTL as the thread
5731
library, we should be notified the low level thread exit before
5732
we hear of any join event on it. The low level exit
5733
notification feeds through into evh__pre_thread_ll_exit,
5734
which should clear the map_threads entry for it. Hence we
5735
expect there to be no map_threads entry at this point. */
5736
tl_assert( map_threads_maybe_reverse_lookup_SLOW(thr_q)
5737
== VG_INVALID_THREADID);
5739
if (clo_sanity_flags & SCE_THREADS)
5740
all__sanity_check("evh__post_thread_join-post");
5744
void evh__pre_mem_read ( CorePart part, ThreadId tid, Char* s,
5745
Addr a, SizeT size) {
5746
if (SHOW_EVENTS >= 2
5747
|| (SHOW_EVENTS >= 1 && size != 1))
5748
VG_(printf)("evh__pre_mem_read(ctid=%d, \"%s\", %p, %lu)\n",
5749
(Int)tid, s, (void*)a, size );
5750
shadow_mem_read_range( map_threads_lookup(tid), a, size);
5751
if (size >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5752
all__sanity_check("evh__pre_mem_read-post");
5756
void evh__pre_mem_read_asciiz ( CorePart part, ThreadId tid,
5759
if (SHOW_EVENTS >= 1)
5760
VG_(printf)("evh__pre_mem_asciiz(ctid=%d, \"%s\", %p)\n",
5761
(Int)tid, s, (void*)a );
5762
// FIXME: think of a less ugly hack
5763
len = VG_(strlen)( (Char*) a );
5764
shadow_mem_read_range( map_threads_lookup(tid), a, len+1 );
5765
if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5766
all__sanity_check("evh__pre_mem_read_asciiz-post");
5770
void evh__pre_mem_write ( CorePart part, ThreadId tid, Char* s,
5771
Addr a, SizeT size ) {
5772
if (SHOW_EVENTS >= 1)
5773
VG_(printf)("evh__pre_mem_write(ctid=%d, \"%s\", %p, %lu)\n",
5774
(Int)tid, s, (void*)a, size );
5775
shadow_mem_write_range( map_threads_lookup(tid), a, size);
5776
if (size >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5777
all__sanity_check("evh__pre_mem_write-post");
5781
void evh__new_mem_heap ( Addr a, SizeT len, Bool is_inited ) {
5782
if (SHOW_EVENTS >= 1)
5783
VG_(printf)("evh__new_mem_heap(%p, %lu, inited=%d)\n",
5784
(void*)a, len, (Int)is_inited );
5785
// FIXME: this is kinda stupid
1777
5786
if (is_inited) {
1778
make_readable(a, len);
1780
make_writable(a, len);
1785
void hg_set_perms (Addr a, SizeT len,
1786
Bool rr, Bool ww, Bool xx)
1788
if (rr) make_readable(a, len);
1789
else if (ww) make_writable(a, len);
1790
/* else do nothing */
1794
void hg_new_mem_stack_private(Addr a, SizeT len)
1796
set_address_range_state(a, len, Vge_NonVirginInit);
1800
void hg_new_mem_stack(Addr a, SizeT len)
1802
set_address_range_state(a, len, Vge_VirginInit);
1805
/*--------------------------------------------------------------*/
1806
/*--- Initialise the memory audit system on program startup. ---*/
1807
/*--------------------------------------------------------------*/
1810
void init_shadow_memory(void)
1814
for (i = 0; i < ESEC_MAP_WORDS; i++)
1815
distinguished_secondary_map.swords[i] = virgin_sword;
1817
/* These entries gradually get overwritten as the used address
1819
for (i = 0; i < 65536; i++)
1820
primary_map[i] = &distinguished_secondary_map;
1824
/*------------------------------------------------------------*/
1825
/*--- malloc() et al replacements ---*/
1826
/*------------------------------------------------------------*/
1828
static VgHashTable hg_malloc_list = NULL;
1830
#define N_FREED_CHUNKS 2
1831
static Int freechunkptr = 0;
1832
static HG_Chunk *freechunks[N_FREED_CHUNKS];
1835
/* Allocate a user-chunk of size bytes. Also allocate its shadow
1836
block, make the shadow block point at the user block. Put the
1837
shadow chunk on the appropriate list, and set all memory
1838
protections correctly. */
1840
static void add_HG_Chunk ( ThreadId tid, Addr p, SizeT size )
1844
hc = VG_(malloc)(sizeof(HG_Chunk));
1847
hc->where = VG_(record_ExeContext)(tid);
1850
VG_(HT_add_node)( hg_malloc_list, (VgHashNode*)hc );
1853
/* Allocate memory and note change in memory available */
1855
void* alloc_and_new_mem ( ThreadId tid, SizeT size, SizeT alignment,
1860
if (size < 0) return NULL;
1862
p = (Addr)VG_(cli_malloc)(alignment, size);
5787
shadow_mem_make_New(get_current_Thread(), a, len);
5789
shadow_mem_make_New(get_current_Thread(), a, len);
5791
if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5792
all__sanity_check("evh__pre_mem_read-post");
5796
void evh__die_mem_heap ( Addr a, SizeT len ) {
5797
if (SHOW_EVENTS >= 1)
5798
VG_(printf)("evh__die_mem_heap(%p, %lu)\n", (void*)a, len );
5799
shadow_mem_make_NoAccess( get_current_Thread(), a, len );
5800
if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
5801
all__sanity_check("evh__pre_mem_read-post");
5804
// thread async exit?
5806
static VG_REGPARM(1)
5807
void evh__mem_help_read_1(Addr a) {
5808
shadow_mem_read8( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5810
static VG_REGPARM(1)
5811
void evh__mem_help_read_2(Addr a) {
5812
shadow_mem_read16( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5814
static VG_REGPARM(1)
5815
void evh__mem_help_read_4(Addr a) {
5816
shadow_mem_read32( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5818
static VG_REGPARM(1)
5819
void evh__mem_help_read_8(Addr a) {
5820
shadow_mem_read64( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5822
static VG_REGPARM(2)
5823
void evh__mem_help_read_N(Addr a, SizeT size) {
5824
shadow_mem_read_range( get_current_Thread_in_C_C(), a, size );
5827
static VG_REGPARM(1)
5828
void evh__mem_help_write_1(Addr a) {
5829
shadow_mem_write8( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5831
static VG_REGPARM(1)
5832
void evh__mem_help_write_2(Addr a) {
5833
shadow_mem_write16( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5835
static VG_REGPARM(1)
5836
void evh__mem_help_write_4(Addr a) {
5837
shadow_mem_write32( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5839
static VG_REGPARM(1)
5840
void evh__mem_help_write_8(Addr a) {
5841
shadow_mem_write64( get_current_Thread_in_C_C(), a, 0/*unused*/ );
5843
static VG_REGPARM(2)
5844
void evh__mem_help_write_N(Addr a, SizeT size) {
5845
shadow_mem_write_range( get_current_Thread_in_C_C(), a, size );
5848
static void evh__bus_lock(void) {
5850
if (0) VG_(printf)("evh__bus_lock()\n");
5851
thr = get_current_Thread();
5852
tl_assert(thr); /* cannot fail - Thread* must already exist */
5853
evhH__post_thread_w_acquires_lock( thr, LK_nonRec, (Addr)&__bus_lock );
5855
static void evh__bus_unlock(void) {
5857
if (0) VG_(printf)("evh__bus_unlock()\n");
5858
thr = get_current_Thread();
5859
tl_assert(thr); /* cannot fail - Thread* must already exist */
5860
evhH__pre_thread_releases_lock( thr, (Addr)&__bus_lock, False/*!isRDWR*/ );
5864
/* -------------- events to do with mutexes -------------- */
5866
/* EXPOSITION only: by intercepting lock init events we can show the
5867
user where the lock was initialised, rather than only being able to
5868
show where it was first locked. Intercepting lock initialisations
5869
is not necessary for the basic operation of the race checker. */
5871
void evh__HG_PTHREAD_MUTEX_INIT_POST( ThreadId tid,
5872
void* mutex, Word mbRec )
5874
if (SHOW_EVENTS >= 1)
5875
VG_(printf)("evh__hg_PTHREAD_MUTEX_INIT_POST(ctid=%d, mbRec=%ld, %p)\n",
5876
(Int)tid, mbRec, (void*)mutex );
5877
tl_assert(mbRec == 0 || mbRec == 1);
5878
map_locks_lookup_or_create( mbRec ? LK_mbRec : LK_nonRec,
5880
if (clo_sanity_flags & SCE_LOCKS)
5881
all__sanity_check("evh__hg_PTHREAD_MUTEX_INIT_POST");
5885
void evh__HG_PTHREAD_MUTEX_DESTROY_PRE( ThreadId tid, void* mutex )
5889
if (SHOW_EVENTS >= 1)
5890
VG_(printf)("evh__hg_PTHREAD_MUTEX_DESTROY_PRE(ctid=%d, %p)\n",
5891
(Int)tid, (void*)mutex );
5893
thr = map_threads_maybe_lookup( tid );
5894
/* cannot fail - Thread* must already exist */
5895
tl_assert( is_sane_Thread(thr) );
5897
lk = map_locks_maybe_lookup( (Addr)mutex );
5899
if (lk == NULL || (lk->kind != LK_nonRec && lk->kind != LK_mbRec)) {
5900
record_error_Misc( thr,
5901
"pthread_mutex_destroy with invalid argument" );
5905
tl_assert( is_sane_LockN(lk) );
5906
tl_assert( lk->guestaddr == (Addr)mutex );
5908
/* Basically act like we unlocked the lock */
5909
record_error_Misc( thr, "pthread_mutex_destroy of a locked mutex" );
5910
/* remove lock from locksets of all owning threads */
5911
remove_Lock_from_locksets_of_all_owning_Threads( lk );
5912
HG_(deleteBag)( lk->heldBy );
5915
lk->acquired_at = NULL;
5917
tl_assert( !lk->heldBy );
5918
tl_assert( is_sane_LockN(lk) );
5921
if (clo_sanity_flags & SCE_LOCKS)
5922
all__sanity_check("evh__hg_PTHREAD_MUTEX_DESTROY_PRE");
5925
static void evh__HG_PTHREAD_MUTEX_LOCK_PRE ( ThreadId tid,
5926
void* mutex, Word isTryLock )
5928
/* Just check the mutex is sane; nothing else to do. */
5929
// 'mutex' may be invalid - not checked by wrapper
5932
if (SHOW_EVENTS >= 1)
5933
VG_(printf)("evh__hg_PTHREAD_MUTEX_LOCK_PRE(ctid=%d, mutex=%p)\n",
5934
(Int)tid, (void*)mutex );
5936
tl_assert(isTryLock == 0 || isTryLock == 1);
5937
thr = map_threads_maybe_lookup( tid );
5938
tl_assert(thr); /* cannot fail - Thread* must already exist */
5940
lk = map_locks_maybe_lookup( (Addr)mutex );
5942
if (lk && (lk->kind == LK_rdwr)) {
5943
record_error_Misc( thr, "pthread_mutex_lock with a "
5944
"pthread_rwlock_t* argument " );
5949
&& (lk->kind == LK_nonRec || lk->kind == LK_rdwr)
5952
&& HG_(elemBag)( lk->heldBy, (Word)thr ) > 0 ) {
5953
/* uh, it's a non-recursive lock and we already w-hold it, and
5954
this is a real lock operation (not a speculative "tryLock"
5955
kind of thing). Duh. Deadlock coming up; but at least
5956
produce an error message. */
5957
record_error_Misc( thr, "Attempt to re-lock a "
5958
"non-recursive lock I already hold" );
5962
static void evh__HG_PTHREAD_MUTEX_LOCK_POST ( ThreadId tid, void* mutex )
5964
// only called if the real library call succeeded - so mutex is sane
5966
if (SHOW_EVENTS >= 1)
5967
VG_(printf)("evh__HG_PTHREAD_MUTEX_LOCK_POST(ctid=%d, mutex=%p)\n",
5968
(Int)tid, (void*)mutex );
5970
thr = map_threads_maybe_lookup( tid );
5971
tl_assert(thr); /* cannot fail - Thread* must already exist */
5973
evhH__post_thread_w_acquires_lock(
5975
LK_mbRec, /* if not known, create new lock with this LockKind */
5980
static void evh__HG_PTHREAD_MUTEX_UNLOCK_PRE ( ThreadId tid, void* mutex )
5982
// 'mutex' may be invalid - not checked by wrapper
5984
if (SHOW_EVENTS >= 1)
5985
VG_(printf)("evh__HG_PTHREAD_MUTEX_UNLOCK_PRE(ctid=%d, mutex=%p)\n",
5986
(Int)tid, (void*)mutex );
5988
thr = map_threads_maybe_lookup( tid );
5989
tl_assert(thr); /* cannot fail - Thread* must already exist */
5991
evhH__pre_thread_releases_lock( thr, (Addr)mutex, False/*!isRDWR*/ );
5994
static void evh__HG_PTHREAD_MUTEX_UNLOCK_POST ( ThreadId tid, void* mutex )
5996
// only called if the real library call succeeded - so mutex is sane
5998
if (SHOW_EVENTS >= 1)
5999
VG_(printf)("evh__hg_PTHREAD_MUTEX_UNLOCK_POST(ctid=%d, mutex=%p)\n",
6000
(Int)tid, (void*)mutex );
6001
thr = map_threads_maybe_lookup( tid );
6002
tl_assert(thr); /* cannot fail - Thread* must already exist */
6004
// anything we should do here?
6008
/* --------------- events to do with CVs --------------- */
6010
/* A mapping from CV to the thread segment which has most recently
6011
signalled/broadcasted on it. This makes it possible to create
6012
thread segments to model happens-before events arising from CV
6013
signallings/broadcasts.
6016
/* pthread_mutex_cond* -> Segment* */
6017
static WordFM* map_cond_to_Segment = NULL;
6019
static void map_cond_to_Segment_INIT ( void ) {
6020
if (UNLIKELY(map_cond_to_Segment == NULL)) {
6021
map_cond_to_Segment = HG_(newFM)( hg_zalloc, hg_free, NULL );
6022
tl_assert(map_cond_to_Segment != NULL);
6026
static void evh__HG_PTHREAD_COND_SIGNAL_PRE ( ThreadId tid, void* cond )
6028
/* 'tid' has signalled on 'cond'. Start a new segment for this
6029
thread, and make a binding from 'cond' to our old segment in the
6030
mapping. This is later used by other thread(s) which
6031
successfully exit from a pthread_cond_wait on the same cv; then
6032
they know what the signalling segment was, so a dependency edge
6033
back to it can be constructed. */
6036
SegmentID new_segid;
6039
if (SHOW_EVENTS >= 1)
6040
VG_(printf)("evh__HG_PTHREAD_COND_SIGNAL_PRE(ctid=%d, cond=%p)\n",
6041
(Int)tid, (void*)cond );
6043
map_cond_to_Segment_INIT();
6044
thr = map_threads_maybe_lookup( tid );
6045
tl_assert(thr); /* cannot fail - Thread* must already exist */
6047
// error-if: mutex is bogus
6048
// error-if: mutex is not locked
6050
if (clo_happens_before >= 2) {
6051
/* create a new segment ... */
6052
new_segid = 0; /* bogus */
6054
evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
6055
tl_assert( is_sane_SegmentID(new_segid) );
6056
tl_assert( is_sane_Segment(new_seg) );
6057
tl_assert( new_seg->thr == thr );
6058
tl_assert( is_sane_Segment(new_seg->prev) );
6059
tl_assert( new_seg->prev->vts );
6060
new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
6062
/* ... and add the binding. */
6063
HG_(addToFM)( map_cond_to_Segment, (Word)cond,
6064
(Word)(new_seg->prev) );
6068
/* returns True if it reckons 'mutex' is valid and held by this
6069
thread, else False */
6070
static Bool evh__HG_PTHREAD_COND_WAIT_PRE ( ThreadId tid,
6071
void* cond, void* mutex )
6075
Bool lk_valid = True;
6077
if (SHOW_EVENTS >= 1)
6078
VG_(printf)("evh__hg_PTHREAD_COND_WAIT_PRE"
6079
"(ctid=%d, cond=%p, mutex=%p)\n",
6080
(Int)tid, (void*)cond, (void*)mutex );
6082
map_cond_to_Segment_INIT();
6083
thr = map_threads_maybe_lookup( tid );
6084
tl_assert(thr); /* cannot fail - Thread* must already exist */
6086
lk = map_locks_maybe_lookup( (Addr)mutex );
6088
/* Check for stupid mutex arguments. There are various ways to be
6089
a bozo. Only complain once, though, even if more than one thing
6095
"pthread_cond_{timed}wait called with invalid mutex" );
6097
tl_assert( is_sane_LockN(lk) );
6098
if (lk->kind == LK_rdwr) {
6101
thr, "pthread_cond_{timed}wait called with mutex "
6102
"of type pthread_rwlock_t*" );
6104
if (lk->heldBy == NULL) {
6107
thr, "pthread_cond_{timed}wait called with un-held mutex");
6109
if (lk->heldBy != NULL
6110
&& HG_(elemBag)( lk->heldBy, (Word)thr ) == 0) {
6113
thr, "pthread_cond_{timed}wait called with mutex "
6114
"held by a different thread" );
6118
// error-if: cond is also associated with a different mutex
6123
static void evh__HG_PTHREAD_COND_WAIT_POST ( ThreadId tid,
6124
void* cond, void* mutex )
6126
/* A pthread_cond_wait(cond, mutex) completed successfully. Start
6127
a new segment for this thread. Look up the signalling-segment
6128
for the 'cond' in the mapping, and add a dependency edge from
6129
the new segment back to it. */
6132
SegmentID new_segid;
6134
Segment* signalling_seg;
6137
if (SHOW_EVENTS >= 1)
6138
VG_(printf)("evh__HG_PTHREAD_COND_WAIT_POST"
6139
"(ctid=%d, cond=%p, mutex=%p)\n",
6140
(Int)tid, (void*)cond, (void*)mutex );
6142
map_cond_to_Segment_INIT();
6143
thr = map_threads_maybe_lookup( tid );
6144
tl_assert(thr); /* cannot fail - Thread* must already exist */
6146
// error-if: cond is also associated with a different mutex
6148
if (clo_happens_before >= 2) {
6149
/* create a new segment ... */
6150
new_segid = 0; /* bogus */
6152
evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
6153
tl_assert( is_sane_SegmentID(new_segid) );
6154
tl_assert( is_sane_Segment(new_seg) );
6155
tl_assert( new_seg->thr == thr );
6156
tl_assert( is_sane_Segment(new_seg->prev) );
6157
tl_assert( new_seg->other == NULL);
6159
/* and find out which thread signalled us; then add a dependency
6161
signalling_seg = NULL;
6162
found = HG_(lookupFM)( map_cond_to_Segment,
6163
NULL, (Word*)&signalling_seg,
6166
tl_assert(is_sane_Segment(signalling_seg));
6167
tl_assert(new_seg->prev);
6168
tl_assert(new_seg->prev->vts);
6169
new_seg->other = signalling_seg;
6170
new_seg->other_hint = 's';
6171
tl_assert(new_seg->other->vts);
6172
new_seg->vts = tickL_and_joinR_VTS(
6175
new_seg->other->vts );
6177
/* Hmm. How can a wait on 'cond' succeed if nobody signalled
6178
it? If this happened it would surely be a bug in the
6179
threads library. Or one of those fabled "spurious
6181
record_error_Misc( thr, "Bug in libpthread: pthread_cond_wait "
6183
" without prior pthread_cond_post");
6184
tl_assert(new_seg->prev->vts);
6185
new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
6191
/* -------------- events to do with rwlocks -------------- */
6193
/* EXPOSITION only */
6195
void evh__HG_PTHREAD_RWLOCK_INIT_POST( ThreadId tid, void* rwl )
6197
if (SHOW_EVENTS >= 1)
6198
VG_(printf)("evh__hg_PTHREAD_RWLOCK_INIT_POST(ctid=%d, %p)\n",
6199
(Int)tid, (void*)rwl );
6200
map_locks_lookup_or_create( LK_rdwr, (Addr)rwl, tid );
6201
if (clo_sanity_flags & SCE_LOCKS)
6202
all__sanity_check("evh__hg_PTHREAD_RWLOCK_INIT_POST");
6206
void evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( ThreadId tid, void* rwl )
6210
if (SHOW_EVENTS >= 1)
6211
VG_(printf)("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE(ctid=%d, %p)\n",
6212
(Int)tid, (void*)rwl );
6214
thr = map_threads_maybe_lookup( tid );
6215
/* cannot fail - Thread* must already exist */
6216
tl_assert( is_sane_Thread(thr) );
6218
lk = map_locks_maybe_lookup( (Addr)rwl );
6220
if (lk == NULL || lk->kind != LK_rdwr) {
6221
record_error_Misc( thr,
6222
"pthread_rwlock_destroy with invalid argument" );
6226
tl_assert( is_sane_LockN(lk) );
6227
tl_assert( lk->guestaddr == (Addr)rwl );
6229
/* Basically act like we unlocked the lock */
6230
record_error_Misc( thr, "pthread_rwlock_destroy of a locked mutex" );
6231
/* remove lock from locksets of all owning threads */
6232
remove_Lock_from_locksets_of_all_owning_Threads( lk );
6233
HG_(deleteBag)( lk->heldBy );
6236
lk->acquired_at = NULL;
6238
tl_assert( !lk->heldBy );
6239
tl_assert( is_sane_LockN(lk) );
6242
if (clo_sanity_flags & SCE_LOCKS)
6243
all__sanity_check("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE");
6247
void evh__HG_PTHREAD_RWLOCK_LOCK_PRE ( ThreadId tid,
6249
Word isW, Word isTryLock )
6251
/* Just check the rwl is sane; nothing else to do. */
6252
// 'rwl' may be invalid - not checked by wrapper
6255
if (SHOW_EVENTS >= 1)
6256
VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_PRE(ctid=%d, isW=%d, %p)\n",
6257
(Int)tid, (Int)isW, (void*)rwl );
6259
tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */
6260
tl_assert(isTryLock == 0 || isTryLock == 1); /* assured us by wrapper */
6261
thr = map_threads_maybe_lookup( tid );
6262
tl_assert(thr); /* cannot fail - Thread* must already exist */
6264
lk = map_locks_maybe_lookup( (Addr)rwl );
6266
&& (lk->kind == LK_nonRec || lk->kind == LK_mbRec) ) {
6267
/* Wrong kind of lock. Duh. */
6268
record_error_Misc( thr, "pthread_rwlock_{rd,rw}lock with a "
6269
"pthread_mutex_t* argument " );
6274
void evh__HG_PTHREAD_RWLOCK_LOCK_POST ( ThreadId tid, void* rwl, Word isW )
6276
// only called if the real library call succeeded - so mutex is sane
6278
if (SHOW_EVENTS >= 1)
6279
VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_POST(ctid=%d, isW=%d, %p)\n",
6280
(Int)tid, (Int)isW, (void*)rwl );
6282
tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */
6283
thr = map_threads_maybe_lookup( tid );
6284
tl_assert(thr); /* cannot fail - Thread* must already exist */
6286
(isW ? evhH__post_thread_w_acquires_lock
6287
: evhH__post_thread_r_acquires_lock)(
6289
LK_rdwr, /* if not known, create new lock with this LockKind */
6294
static void evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE ( ThreadId tid, void* rwl )
6296
// 'rwl' may be invalid - not checked by wrapper
6298
if (SHOW_EVENTS >= 1)
6299
VG_(printf)("evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE(ctid=%d, rwl=%p)\n",
6300
(Int)tid, (void*)rwl );
6302
thr = map_threads_maybe_lookup( tid );
6303
tl_assert(thr); /* cannot fail - Thread* must already exist */
6305
evhH__pre_thread_releases_lock( thr, (Addr)rwl, True/*isRDWR*/ );
6308
static void evh__HG_PTHREAD_RWLOCK_UNLOCK_POST ( ThreadId tid, void* rwl )
6310
// only called if the real library call succeeded - so mutex is sane
6312
if (SHOW_EVENTS >= 1)
6313
VG_(printf)("evh__hg_PTHREAD_RWLOCK_UNLOCK_POST(ctid=%d, rwl=%p)\n",
6314
(Int)tid, (void*)rwl );
6315
thr = map_threads_maybe_lookup( tid );
6316
tl_assert(thr); /* cannot fail - Thread* must already exist */
6318
// anything we should do here?
6322
/* --------------- events to do with semaphores --------------- */
6324
/* This is similar to but not identical to the handling for condition
6327
/* For each semaphore, we maintain a stack of Segments. When a 'post'
6328
operation is done on a semaphore (unlocking, essentially), a new
6329
segment is created for the posting thread, and the old segment is
6330
pushed on the semaphore's stack.
6332
Later, when a (probably different) thread completes 'wait' on the
6333
semaphore, we pop a Segment off the semaphore's stack (which should
6334
be nonempty). We start a new segment for the thread and make it
6335
also depend on the just-popped segment. This mechanism creates
6336
dependencies between posters and waiters of the semaphore.
6338
It may not be necessary to use a stack - perhaps a bag of Segments
6339
would do. But we do need to keep track of how many unused-up posts
6340
have happened for the semaphore.
6342
Imagine T1 and T2 both post once on a semphore S, and T3 waits
6343
twice on S. T3 cannot complete its waits without both T1 and T2
6344
posting. The above mechanism will ensure that T3 acquires
6345
dependencies on both T1 and T2.
6347
When a semaphore is initialised with value N, the initialising
6348
thread starts a new segment, the semaphore's stack is emptied out,
6349
and the old segment is pushed on the stack N times. This allows up
6350
to N waits on the semaphore to acquire a dependency on the
6351
initialisation point, which AFAICS is the correct behaviour.
6353
We don't emit an error for DESTROY_PRE on a semaphore we don't know
6357
/* sem_t* -> XArray* Segment* */
6358
static WordFM* map_sem_to_Segment_stack = NULL;
6360
static void map_sem_to_Segment_stack_INIT ( void ) {
6361
if (map_sem_to_Segment_stack == NULL) {
6362
map_sem_to_Segment_stack = HG_(newFM)( hg_zalloc, hg_free, NULL );
6363
tl_assert(map_sem_to_Segment_stack != NULL);
6367
static void push_Segment_for_sem ( void* sem, Segment* seg ) {
6370
map_sem_to_Segment_stack_INIT();
6371
if (HG_(lookupFM)( map_sem_to_Segment_stack,
6372
NULL, (Word*)&xa, (Word)sem )) {
6374
VG_(addToXA)( xa, &seg );
6376
xa = VG_(newXA)( hg_zalloc, hg_free, sizeof(Segment*) );
6377
VG_(addToXA)( xa, &seg );
6378
HG_(addToFM)( map_sem_to_Segment_stack, (Word)sem, (Word)xa );
6382
static Segment* mb_pop_Segment_for_sem ( void* sem ) {
6385
map_sem_to_Segment_stack_INIT();
6386
if (HG_(lookupFM)( map_sem_to_Segment_stack,
6387
NULL, (Word*)&xa, (Word)sem )) {
6388
/* xa is the stack for this semaphore. */
6389
Word sz = VG_(sizeXA)( xa );
6392
return NULL; /* odd, the stack is empty */
6393
seg = *(Segment**)VG_(indexXA)( xa, sz-1 );
6395
VG_(dropTailXA)( xa, 1 );
6398
/* hmm, that's odd. No stack for this semaphore. */
6403
static void evh__HG_POSIX_SEM_DESTROY_PRE ( ThreadId tid, void* sem )
6407
if (SHOW_EVENTS >= 1)
6408
VG_(printf)("evh__HG_POSIX_SEM_DESTROY_PRE(ctid=%d, sem=%p)\n",
6409
(Int)tid, (void*)sem );
6411
/* Empty out the semaphore's segment stack. This way of doing it
6412
is stupid, but at least it's easy. */
6414
seg = mb_pop_Segment_for_sem( sem );
6421
void evh__HG_POSIX_SEM_INIT_POST ( ThreadId tid, void* sem, UWord value )
6425
if (SHOW_EVENTS >= 1)
6426
VG_(printf)("evh__HG_POSIX_SEM_INIT_POST(ctid=%d, sem=%p, value=%lu)\n",
6427
(Int)tid, (void*)sem, value );
6429
/* Empty out the semaphore's segment stack. This way of doing it
6430
is stupid, but at least it's easy. */
6432
seg = mb_pop_Segment_for_sem( sem );
6436
/* Now create a new segment for the thread, and push the old
6437
segment on the stack 'value' times. Skip this if the initial
6438
value is zero -- no point in creating unnecessary segments. */
6440
/* create a new segment ... */
6441
SegmentID new_segid = 0; /* bogus */
6442
Segment* new_seg = NULL;
6443
Thread* thr = map_threads_maybe_lookup( tid );
6444
tl_assert(thr); /* cannot fail - Thread* must already exist */
6446
evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
6447
tl_assert( is_sane_SegmentID(new_segid) );
6448
tl_assert( is_sane_Segment(new_seg) );
6449
tl_assert( new_seg->thr == thr );
6450
tl_assert( is_sane_Segment(new_seg->prev) );
6451
tl_assert( new_seg->prev->vts );
6452
new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
6454
if (value > 10000) {
6455
/* If we don't do this, the following while loop runs us out
6456
of memory for stupid initial values of 'sem'. */
6458
thr, "sem_init: initial value exceeds 10000; using 10000" );
6463
push_Segment_for_sem( sem, new_seg->prev );
6469
static void evh__HG_POSIX_SEM_POST_PRE ( ThreadId tid, void* sem )
6471
/* 'tid' has posted on 'sem'. Start a new segment for this thread,
6472
and push the old segment on a stack of segments associated with
6473
'sem'. This is later used by other thread(s) which successfully
6474
exit from a sem_wait on the same sem; then they know what the
6475
posting segment was, so a dependency edge back to it can be
6479
SegmentID new_segid;
6482
if (SHOW_EVENTS >= 1)
6483
VG_(printf)("evh__HG_POSIX_SEM_POST_PRE(ctid=%d, sem=%p)\n",
6484
(Int)tid, (void*)sem );
6486
thr = map_threads_maybe_lookup( tid );
6487
tl_assert(thr); /* cannot fail - Thread* must already exist */
6489
// error-if: sem is bogus
6491
if (clo_happens_before >= 2) {
6492
/* create a new segment ... */
6493
new_segid = 0; /* bogus */
6495
evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
6496
tl_assert( is_sane_SegmentID(new_segid) );
6497
tl_assert( is_sane_Segment(new_seg) );
6498
tl_assert( new_seg->thr == thr );
6499
tl_assert( is_sane_Segment(new_seg->prev) );
6500
tl_assert( new_seg->prev->vts );
6501
new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
6503
/* ... and add the binding. */
6504
push_Segment_for_sem( sem, new_seg->prev );
6508
static void evh__HG_POSIX_SEM_WAIT_POST ( ThreadId tid, void* sem )
6510
/* A sem_wait(sem) completed successfully. Start a new segment for
6511
this thread. Pop the posting-segment for the 'sem' in the
6512
mapping, and add a dependency edge from the new segment back to
6516
SegmentID new_segid;
6518
Segment* posting_seg;
6520
if (SHOW_EVENTS >= 1)
6521
VG_(printf)("evh__HG_POSIX_SEM_WAIT_POST(ctid=%d, sem=%p)\n",
6522
(Int)tid, (void*)sem );
6524
thr = map_threads_maybe_lookup( tid );
6525
tl_assert(thr); /* cannot fail - Thread* must already exist */
6527
// error-if: sem is bogus
6529
if (clo_happens_before >= 2) {
6530
/* create a new segment ... */
6531
new_segid = 0; /* bogus */
6533
evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
6534
tl_assert( is_sane_SegmentID(new_segid) );
6535
tl_assert( is_sane_Segment(new_seg) );
6536
tl_assert( new_seg->thr == thr );
6537
tl_assert( is_sane_Segment(new_seg->prev) );
6538
tl_assert( new_seg->other == NULL);
6540
/* and find out which thread posted last on sem; then add a
6541
dependency edge back to it. */
6542
posting_seg = mb_pop_Segment_for_sem( sem );
6544
tl_assert(is_sane_Segment(posting_seg));
6545
tl_assert(new_seg->prev);
6546
tl_assert(new_seg->prev->vts);
6547
new_seg->other = posting_seg;
6548
new_seg->other_hint = 'S';
6549
tl_assert(new_seg->other->vts);
6550
new_seg->vts = tickL_and_joinR_VTS(
6553
new_seg->other->vts );
6555
/* Hmm. How can a wait on 'sem' succeed if nobody posted to
6556
it? If this happened it would surely be a bug in the
6558
record_error_Misc( thr, "Bug in libpthread: sem_wait succeeded on"
6559
" semaphore without prior sem_post");
6560
tl_assert(new_seg->prev->vts);
6561
new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
6567
/*--------------------------------------------------------------*/
6568
/*--- Lock acquisition order monitoring ---*/
6569
/*--------------------------------------------------------------*/
6571
/* FIXME: here are some optimisations still to do in
6572
laog__pre_thread_acquires_lock.
6574
The graph is structured so that if L1 --*--> L2 then L1 must be
6577
The common case is that some thread T holds (eg) L1 L2 and L3 and
6578
is repeatedly acquiring and releasing Ln, and there is no ordering
6579
error in what it is doing. Hence it repeatly:
6581
(1) searches laog to see if Ln --*--> {L1,L2,L3}, which always
6582
produces the answer No (because there is no error).
6584
(2) adds edges {L1,L2,L3} --> Ln to laog, which are already present
6585
(because they already got added the first time T acquired Ln).
6587
Hence cache these two events:
6589
(1) Cache result of the query from last time. Invalidate the cache
6590
any time any edges are added to or deleted from laog.
6592
(2) Cache these add-edge requests and ignore them if said edges
6593
have already been added to laog. Invalidate the cache any time
6594
any edges are deleted from laog.
6599
WordSetID inns; /* in univ_laog */
6600
WordSetID outs; /* in univ_laog */
6604
/* lock order acquisition graph */
6605
static WordFM* laog = NULL; /* WordFM Lock* LAOGLinks* */
6607
/* EXPOSITION ONLY: for each edge in 'laog', record the two places
6608
where that edge was created, so that we can show the user later if
6612
Addr src_ga; /* Lock guest addresses for */
6613
Addr dst_ga; /* src/dst of the edge */
6614
ExeContext* src_ec; /* And corresponding places where that */
6615
ExeContext* dst_ec; /* ordering was established */
6619
static Word cmp_LAOGLinkExposition ( Word llx1W, Word llx2W ) {
6620
/* Compare LAOGLinkExposition*s by (src_ga,dst_ga) field pair. */
6621
LAOGLinkExposition* llx1 = (LAOGLinkExposition*)llx1W;
6622
LAOGLinkExposition* llx2 = (LAOGLinkExposition*)llx2W;
6623
if (llx1->src_ga < llx2->src_ga) return -1;
6624
if (llx1->src_ga > llx2->src_ga) return 1;
6625
if (llx1->dst_ga < llx2->dst_ga) return -1;
6626
if (llx1->dst_ga > llx2->dst_ga) return 1;
6630
static WordFM* laog_exposition = NULL; /* WordFM LAOGLinkExposition* NULL */
6631
/* end EXPOSITION ONLY */
6634
static void laog__show ( Char* who ) {
6639
VG_(printf)("laog (requested by %s) {\n", who);
6640
HG_(initIterFM)( laog );
6643
while (HG_(nextIterFM)( laog, (Word*)&me,
6647
VG_(printf)(" node %p:\n", me);
6648
HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns );
6649
for (i = 0; i < ws_size; i++)
6650
VG_(printf)(" inn %p\n", ws_words[i] );
6651
HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs );
6652
for (i = 0; i < ws_size; i++)
6653
VG_(printf)(" out %p\n", ws_words[i] );
6657
HG_(doneIterFM)( laog );
6661
__attribute__((noinline))
6662
static void laog__add_edge ( Lock* src, Lock* dst ) {
6665
Bool presentF, presentR;
6666
if (0) VG_(printf)("laog__add_edge %p %p\n", src, dst);
6668
/* Take the opportunity to sanity check the graph. Record in
6669
presentF if there is already a src->dst mapping in this node's
6670
forwards links, and presentR if there is already a src->dst
6671
mapping in this node's backwards links. They should agree!
6672
Also, we need to know whether the edge was already present so as
6673
to decide whether or not to update the link details mapping. We
6674
can compute presentF and presentR essentially for free, so may
6675
as well do this always. */
6676
presentF = presentR = False;
6678
/* Update the out edges for src */
6681
if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) {
6684
tl_assert(keyW == (Word)src);
6685
outs_new = HG_(addToWS)( univ_laog, links->outs, (Word)dst );
6686
presentF = outs_new == links->outs;
6687
links->outs = outs_new;
6689
links = hg_zalloc(sizeof(LAOGLinks));
6690
links->inns = HG_(emptyWS)( univ_laog );
6691
links->outs = HG_(singletonWS)( univ_laog, (Word)dst );
6692
HG_(addToFM)( laog, (Word)src, (Word)links );
6694
/* Update the in edges for dst */
6697
if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) {
6700
tl_assert(keyW == (Word)dst);
6701
inns_new = HG_(addToWS)( univ_laog, links->inns, (Word)src );
6702
presentR = inns_new == links->inns;
6703
links->inns = inns_new;
6705
links = hg_zalloc(sizeof(LAOGLinks));
6706
links->inns = HG_(singletonWS)( univ_laog, (Word)src );
6707
links->outs = HG_(emptyWS)( univ_laog );
6708
HG_(addToFM)( laog, (Word)dst, (Word)links );
6711
tl_assert( (presentF && presentR) || (!presentF && !presentR) );
6713
if (!presentF && src->acquired_at && dst->acquired_at) {
6714
LAOGLinkExposition expo;
6715
/* If this edge is entering the graph, and we have acquired_at
6716
information for both src and dst, record those acquisition
6717
points. Hence, if there is later a violation of this
6718
ordering, we can show the user the two places in which the
6719
required src-dst ordering was previously established. */
6720
if (0) VG_(printf)("acquire edge %p %p\n",
6721
src->guestaddr, dst->guestaddr);
6722
expo.src_ga = src->guestaddr;
6723
expo.dst_ga = dst->guestaddr;
6726
tl_assert(laog_exposition);
6727
if (HG_(lookupFM)( laog_exposition, NULL, NULL, (Word)&expo )) {
6728
/* we already have it; do nothing */
6730
LAOGLinkExposition* expo2 = hg_zalloc(sizeof(LAOGLinkExposition));
6731
expo2->src_ga = src->guestaddr;
6732
expo2->dst_ga = dst->guestaddr;
6733
expo2->src_ec = src->acquired_at;
6734
expo2->dst_ec = dst->acquired_at;
6735
HG_(addToFM)( laog_exposition, (Word)expo2, (Word)NULL );
6740
__attribute__((noinline))
6741
static void laog__del_edge ( Lock* src, Lock* dst ) {
6744
if (0) VG_(printf)("laog__del_edge %p %p\n", src, dst);
6745
/* Update the out edges for src */
6748
if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) {
6750
tl_assert(keyW == (Word)src);
6751
links->outs = HG_(delFromWS)( univ_laog, links->outs, (Word)dst );
6753
/* Update the in edges for dst */
6756
if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) {
6758
tl_assert(keyW == (Word)dst);
6759
links->inns = HG_(delFromWS)( univ_laog, links->inns, (Word)src );
6763
__attribute__((noinline))
6764
static WordSetID /* in univ_laog */ laog__succs ( Lock* lk ) {
6769
if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) {
6771
tl_assert(keyW == (Word)lk);
6774
return HG_(emptyWS)( univ_laog );
6778
__attribute__((noinline))
6779
static WordSetID /* in univ_laog */ laog__preds ( Lock* lk ) {
6784
if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) {
6786
tl_assert(keyW == (Word)lk);
6789
return HG_(emptyWS)( univ_laog );
6793
__attribute__((noinline))
6794
static void laog__sanity_check ( Char* who ) {
6800
return; /* nothing much we can do */
6801
HG_(initIterFM)( laog );
6804
if (0) VG_(printf)("laog sanity check\n");
6805
while (HG_(nextIterFM)( laog, (Word*)&me,
6809
HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns );
6810
for (i = 0; i < ws_size; i++) {
6811
if ( ! HG_(elemWS)( univ_laog,
6812
laog__succs( (Lock*)ws_words[i] ),
6816
HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs );
6817
for (i = 0; i < ws_size; i++) {
6818
if ( ! HG_(elemWS)( univ_laog,
6819
laog__preds( (Lock*)ws_words[i] ),
6826
HG_(doneIterFM)( laog );
6830
VG_(printf)("laog__sanity_check(%s) FAILED\n", who);
6835
/* If there is a path in laog from 'src' to any of the elements in
6836
'dst', return an arbitrarily chosen element of 'dst' reachable from
6837
'src'. If no path exist from 'src' to any element in 'dst', return
6839
__attribute__((noinline))
6841
Lock* laog__do_dfs_from_to ( Lock* src, WordSetID dsts /* univ_lsets */ )
6845
XArray* stack; /* of Lock* */
6846
WordFM* visited; /* Lock* -> void, iow, Set(Lock*) */
6851
//laog__sanity_check();
6853
/* If the destination set is empty, we can never get there from
6854
'src' :-), so don't bother to try */
6855
if (HG_(isEmptyWS)( univ_lsets, dsts ))
6859
stack = VG_(newXA)( hg_zalloc, hg_free, sizeof(Lock*) );
6860
visited = HG_(newFM)( hg_zalloc, hg_free, NULL/*unboxedcmp*/ );
6862
(void) VG_(addToXA)( stack, &src );
6866
ssz = VG_(sizeXA)( stack );
6868
if (ssz == 0) { ret = NULL; break; }
6870
here = *(Lock**) VG_(indexXA)( stack, ssz-1 );
6871
VG_(dropTailXA)( stack, 1 );
6873
if (HG_(elemWS)( univ_lsets, dsts, (Word)here )) { ret = here; break; }
6875
if (HG_(lookupFM)( visited, NULL, NULL, (Word)here ))
6878
HG_(addToFM)( visited, (Word)here, 0 );
6880
succs = laog__succs( here );
6881
HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs );
6882
for (i = 0; i < succs_size; i++)
6883
(void) VG_(addToXA)( stack, &succs_words[i] );
6886
HG_(deleteFM)( visited, NULL, NULL );
6887
VG_(deleteXA)( stack );
6892
/* Thread 'thr' is acquiring 'lk'. Check for inconsistent ordering
6893
between 'lk' and the locks already held by 'thr' and issue a
6894
complaint if so. Also, update the ordering graph appropriately.
6896
__attribute__((noinline))
6897
static void laog__pre_thread_acquires_lock (
6898
Thread* thr, /* NB: BEFORE lock is added */
6906
/* It may be that 'thr' already holds 'lk' and is recursively
6907
relocking in. In this case we just ignore the call. */
6908
/* NB: univ_lsets really is correct here */
6909
if (HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lk ))
6913
laog = HG_(newFM)( hg_zalloc, hg_free, NULL/*unboxedcmp*/ );
6914
if (!laog_exposition)
6915
laog_exposition = HG_(newFM)( hg_zalloc, hg_free,
6916
cmp_LAOGLinkExposition );
6918
/* First, the check. Complain if there is any path in laog from lk
6919
to any of the locks already held by thr, since if any such path
6920
existed, it would mean that previously lk was acquired before
6921
(rather than after, as we are doing here) at least one of those
6924
other = laog__do_dfs_from_to(lk, thr->locksetA);
6926
LAOGLinkExposition key, *found;
6927
/* So we managed to find a path lk --*--> other in the graph,
6928
which implies that 'lk' should have been acquired before
6929
'other' but is in fact being acquired afterwards. We present
6930
the lk/other arguments to record_error_LockOrder in the order
6931
in which they should have been acquired. */
6932
/* Go look in the laog_exposition mapping, to find the allocation
6933
points for this edge, so we can show the user. */
6934
key.src_ga = lk->guestaddr;
6935
key.dst_ga = other->guestaddr;
6939
if (HG_(lookupFM)( laog_exposition,
6940
(Word*)&found, NULL, (Word)&key )) {
6941
tl_assert(found != &key);
6942
tl_assert(found->src_ga == key.src_ga);
6943
tl_assert(found->dst_ga == key.dst_ga);
6944
tl_assert(found->src_ec);
6945
tl_assert(found->dst_ec);
6946
record_error_LockOrder( thr,
6947
lk->guestaddr, other->guestaddr,
6948
found->src_ec, found->dst_ec );
6950
/* Hmm. This can't happen (can it?) */
6951
record_error_LockOrder( thr,
6952
lk->guestaddr, other->guestaddr,
6957
/* Second, add to laog the pairs
6958
(old, lk) | old <- locks already held by thr
6959
Since both old and lk are currently held by thr, their acquired_at
6960
fields must be non-NULL.
6962
tl_assert(lk->acquired_at);
6963
HG_(getPayloadWS)( &ls_words, &ls_size, univ_lsets, thr->locksetA );
6964
for (i = 0; i < ls_size; i++) {
6965
Lock* old = (Lock*)ls_words[i];
6966
tl_assert(old->acquired_at);
6967
laog__add_edge( old, lk );
6970
/* Why "except_Locks" ? We're here because a lock is being
6971
acquired by a thread, and we're in an inconsistent state here.
6972
See the call points in evhH__post_thread_{r,w}_acquires_lock.
6973
When called in this inconsistent state, locks__sanity_check duly
6975
if (clo_sanity_flags & SCE_LAOG)
6976
all_except_Locks__sanity_check("laog__pre_thread_acquires_lock-post");
6980
/* Delete from 'laog' any pair mentioning a lock in locksToDelete */
6982
__attribute__((noinline))
6983
static void laog__handle_one_lock_deletion ( Lock* lk )
6985
WordSetID preds, succs;
6986
Word preds_size, succs_size, i, j;
6987
Word *preds_words, *succs_words;
6989
preds = laog__preds( lk );
6990
succs = laog__succs( lk );
6992
HG_(getPayloadWS)( &preds_words, &preds_size, univ_laog, preds );
6993
for (i = 0; i < preds_size; i++)
6994
laog__del_edge( (Lock*)preds_words[i], lk );
6996
HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs );
6997
for (j = 0; j < succs_size; j++)
6998
laog__del_edge( lk, (Lock*)succs_words[j] );
7000
for (i = 0; i < preds_size; i++) {
7001
for (j = 0; j < succs_size; j++) {
7002
if (preds_words[i] != succs_words[j]) {
7003
/* This can pass unlocked locks to laog__add_edge, since
7004
we're deleting stuff. So their acquired_at fields may
7006
laog__add_edge( (Lock*)preds_words[i], (Lock*)succs_words[j] );
7012
__attribute__((noinline))
7013
static void laog__handle_lock_deletions (
7014
WordSetID /* in univ_laog */ locksToDelete
7021
laog = HG_(newFM)( hg_zalloc, hg_free, NULL/*unboxedcmp*/ );
7022
if (!laog_exposition)
7023
laog_exposition = HG_(newFM)( hg_zalloc, hg_free,
7024
cmp_LAOGLinkExposition );
7026
HG_(getPayloadWS)( &ws_words, &ws_size, univ_lsets, locksToDelete );
7027
for (i = 0; i < ws_size; i++)
7028
laog__handle_one_lock_deletion( (Lock*)ws_words[i] );
7030
if (clo_sanity_flags & SCE_LAOG)
7031
all__sanity_check("laog__handle_lock_deletions-post");
7035
/*--------------------------------------------------------------*/
7036
/*--- Malloc/free replacements ---*/
7037
/*--------------------------------------------------------------*/
7041
void* next; /* required by m_hashtable */
7042
Addr payload; /* ptr to actual block */
7043
SizeT szB; /* size requested */
7044
ExeContext* where; /* where it was allocated */
7045
Thread* thr; /* allocating thread */
7049
/* A hash table of MallocMetas, used to track malloc'd blocks
7051
static VgHashTable hg_mallocmeta_table = NULL;
7054
static MallocMeta* new_MallocMeta ( void ) {
7055
MallocMeta* md = hg_zalloc( sizeof(MallocMeta) );
7059
static void delete_MallocMeta ( MallocMeta* md ) {
7064
/* Allocate a client block and set up the metadata for it. */
7067
void* handle_alloc ( ThreadId tid,
7068
SizeT szB, SizeT alignB, Bool is_zeroed )
7073
tl_assert( ((SSizeT)szB) >= 0 );
7074
p = (Addr)VG_(cli_malloc)(alignB, szB);
1866
if (is_zeroed) VG_(memset)((void*)p, 0, size);
1867
add_HG_Chunk ( tid, p, size );
1868
hg_new_mem_heap( p, size, is_zeroed );
7079
VG_(memset)((void*)p, 0, szB);
7081
/* Note that map_threads_lookup must succeed (cannot assert), since
7082
memory can only be allocated by currently alive threads, hence
7083
they must have an entry in map_threads. */
7084
md = new_MallocMeta();
7087
md->where = VG_(record_ExeContext)( tid, 0 );
7088
md->thr = map_threads_lookup( tid );
7090
VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md );
7092
/* Tell the lower level memory wranglers. */
7093
evh__new_mem_heap( p, szB, is_zeroed );
1870
7095
return (void*)p;
1873
static void* hg_malloc ( ThreadId tid, SizeT n )
1875
return alloc_and_new_mem ( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
1878
static void* hg___builtin_new ( ThreadId tid, SizeT n )
1880
return alloc_and_new_mem ( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
1883
static void* hg___builtin_vec_new ( ThreadId tid, SizeT n )
1885
return alloc_and_new_mem ( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
1888
static void* hg_memalign ( ThreadId tid, SizeT align, SizeT n )
1890
return alloc_and_new_mem ( tid, n, align, /*is_zeroed*/False );
1893
static void* hg_calloc ( ThreadId tid, SizeT nmemb, SizeT size )
1895
return alloc_and_new_mem ( tid, nmemb*size, VG_(clo_alignment),
1896
/*is_zeroed*/True );
1899
static ThreadId deadmx_tid;
1902
Bool deadmx(Mutex *mx) {
1903
if (mx->state != MxDead)
1904
set_mutex_state(mx, MxDead, deadmx_tid);
1910
void die_and_free_mem ( ThreadId tid, HG_Chunk* hc,
1911
HG_Chunk** prev_chunks_next_ptr )
1913
Addr start = hc->data;
1914
Addr end = start + hc->size;
1916
/* Remove hc from the malloclist using prev_chunks_next_ptr to
1917
avoid repeating the hash table lookup. Can't remove until at least
1918
after free and free_mismatch errors are done because they use
1919
describe_addr() which looks for it in malloclist. */
1920
*prev_chunks_next_ptr = hc->next;
1922
/* Record where freed */
1923
hc->where = VG_(record_ExeContext) ( tid );
1925
/* maintain a small window so that the error reporting machinery
1926
knows about this memory */
1927
if (freechunks[freechunkptr] != NULL) {
1929
HG_Chunk* sc1 = freechunks[freechunkptr];
1930
VG_(cli_free) ( (void*)(sc1->data) );
1934
freechunks[freechunkptr] = hc;
1936
if (++freechunkptr == N_FREED_CHUNKS)
1939
/* mark all mutexes in range dead */
1941
find_mutex_range(start, end, deadmx);
1946
void handle_free ( ThreadId tid, void* p )
1949
HG_Chunk** prev_chunks_next_ptr;
1951
hc = (HG_Chunk*)VG_(HT_get_node) ( hg_malloc_list, (UWord)p,
1952
(VgHashNode***)&prev_chunks_next_ptr );
1956
die_and_free_mem ( tid, hc, prev_chunks_next_ptr );
1959
static void hg_free ( ThreadId tid, void* p )
1961
handle_free(tid, p);
1964
static void hg___builtin_delete ( ThreadId tid, void* p )
1966
handle_free(tid, p);
1969
static void hg___builtin_vec_delete ( ThreadId tid, void* p )
1971
handle_free(tid, p);
1974
static void* hg_realloc ( ThreadId tid, void* p, SizeT new_size )
1977
HG_Chunk **prev_chunks_next_ptr;
1979
/* First try and find the block. */
1980
hc = (HG_Chunk*)VG_(HT_get_node) ( hg_malloc_list, (UWord)p,
1981
(VgHashNode***)&prev_chunks_next_ptr );
7098
/* Re the checks for less-than-zero (also in hg_cli__realloc below):
7099
Cast to a signed type to catch any unexpectedly negative args.
7100
We're assuming here that the size asked for is not greater than
7101
2^31 bytes (for 32-bit platforms) or 2^63 bytes (for 64-bit
7103
static void* hg_cli__malloc ( ThreadId tid, SizeT n ) {
7104
if (((SSizeT)n) < 0) return NULL;
7105
return handle_alloc ( tid, n, VG_(clo_alignment),
7106
/*is_zeroed*/False );
7108
static void* hg_cli____builtin_new ( ThreadId tid, SizeT n ) {
7109
if (((SSizeT)n) < 0) return NULL;
7110
return handle_alloc ( tid, n, VG_(clo_alignment),
7111
/*is_zeroed*/False );
7113
static void* hg_cli____builtin_vec_new ( ThreadId tid, SizeT n ) {
7114
if (((SSizeT)n) < 0) return NULL;
7115
return handle_alloc ( tid, n, VG_(clo_alignment),
7116
/*is_zeroed*/False );
7118
static void* hg_cli__memalign ( ThreadId tid, SizeT align, SizeT n ) {
7119
if (((SSizeT)n) < 0) return NULL;
7120
return handle_alloc ( tid, n, align,
7121
/*is_zeroed*/False );
7123
static void* hg_cli__calloc ( ThreadId tid, SizeT nmemb, SizeT size1 ) {
7124
if ( ((SSizeT)nmemb) < 0 || ((SSizeT)size1) < 0 ) return NULL;
7125
return handle_alloc ( tid, nmemb*size1, VG_(clo_alignment),
7126
/*is_zeroed*/True );
7130
/* Free a client block, including getting rid of the relevant
7133
static void handle_free ( ThreadId tid, void* p )
7135
MallocMeta *md, *old_md;
7138
/* First see if we can find the metadata for 'p'. */
7139
md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p );
7141
return; /* apparently freeing a bogus address. Oh well. */
7143
tl_assert(md->payload == (Addr)p);
7146
/* Nuke the metadata block */
7147
old_md = (MallocMeta*)
7148
VG_(HT_remove)( hg_mallocmeta_table, (UWord)p );
7149
tl_assert(old_md); /* it must be present - we just found it */
7150
tl_assert(old_md == md);
7151
tl_assert(old_md->payload == (Addr)p);
7153
VG_(cli_free)((void*)old_md->payload);
7154
delete_MallocMeta(old_md);
7156
/* Tell the lower level memory wranglers. */
7157
evh__die_mem_heap( (Addr)p, szB );
7160
static void hg_cli__free ( ThreadId tid, void* p ) {
7161
handle_free(tid, p);
7163
static void hg_cli____builtin_delete ( ThreadId tid, void* p ) {
7164
handle_free(tid, p);
7166
static void hg_cli____builtin_vec_delete ( ThreadId tid, void* p ) {
7167
handle_free(tid, p);
7171
static void* hg_cli__realloc ( ThreadId tid, void* payloadV, SizeT new_size )
7173
MallocMeta *md, *md_new, *md_tmp;
7176
Addr payload = (Addr)payloadV;
7178
if (((SSizeT)new_size) < 0) return NULL;
7180
md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)payload );
7182
return NULL; /* apparently realloc-ing a bogus address. Oh well. */
1987
if (hc->size == new_size) {
7184
tl_assert(md->payload == payload);
7186
if (md->szB == new_size) {
1988
7187
/* size unchanged */
1989
hc->where = VG_(record_ExeContext)(tid);
1992
} else if (hc->size > new_size) {
7188
md->where = VG_(record_ExeContext)(tid, 0);
7192
if (md->szB > new_size) {
1993
7193
/* new size is smaller */
1994
hc->size = new_size;
1995
hc->where = VG_(record_ExeContext)(tid);
7195
md->where = VG_(record_ExeContext)(tid, 0);
7196
evh__die_mem_heap( md->payload + new_size, md->szB - new_size );
1999
7201
/* new size is bigger */
2002
/* Get new memory */
2003
p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
2006
/* First half kept and copied, second half new */
2007
copy_address_range_state( (Addr)p, p_new, hc->size );
2008
hg_new_mem_heap ( p_new+hc->size, new_size-hc->size,
7202
Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
7204
/* First half kept and copied, second half new */
7205
// FIXME: shouldn't we use a copier which implements the
7206
// memory state machine?
7207
shadow_mem_copy_range( payload, p_new, md->szB );
7208
evh__new_mem_heap ( p_new + md->szB, new_size - md->szB,
2009
7209
/*inited*/False );
2011
/* Copy from old to new */
2012
VG_(memcpy)((void *)p_new, p, hc->size);
2014
/* Free old memory */
2015
die_and_free_mem ( tid, hc, prev_chunks_next_ptr );
2017
/* this has to be after die_and_free_mem, otherwise the
2018
former succeeds in shorting out the new block, not the
2019
old, in the case when both are on the same list. */
2020
add_HG_Chunk ( tid, p_new, new_size );
7210
/* FIXME: can anything funny happen here? specifically, if the
7211
old range contained a lock, then die_mem_heap will complain.
7212
Is that the correct behaviour? Not sure. */
7213
evh__die_mem_heap( payload, md->szB );
7215
/* Copy from old to new */
7216
for (i = 0; i < md->szB; i++)
7217
((UChar*)p_new)[i] = ((UChar*)payload)[i];
7219
/* Because the metadata hash table is index by payload address,
7220
we have to get rid of the old hash table entry and make a new
7221
one. We can't just modify the existing metadata in place,
7222
because then it would (almost certainly) be in the wrong hash
7224
md_new = new_MallocMeta();
7227
md_tmp = VG_(HT_remove)( hg_mallocmeta_table, payload );
7229
tl_assert(md_tmp == md);
7231
VG_(cli_free)((void*)md->payload);
7232
delete_MallocMeta(md);
7235
md_new->where = VG_(record_ExeContext)( tid, 0 );
7236
md_new->szB = new_size;
7237
md_new->payload = p_new;
7238
md_new->thr = map_threads_lookup( tid );
7241
VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md_new );
2023
7243
return (void*)p_new;
2027
/*--------------------------------------------------------------*/
2028
/*--- Machinery to support sanity checking ---*/
2029
/*--------------------------------------------------------------*/
2031
static Bool hg_cheap_sanity_check ( void )
2033
/* nothing useful we can rapidly check */
2037
static Bool hg_expensive_sanity_check(void)
2041
/* Make sure nobody changed the distinguished secondary. */
2042
for (i = 0; i < ESEC_MAP_WORDS; i++)
2043
if (distinguished_secondary_map.swords[i].other != virgin_sword.other ||
2044
distinguished_secondary_map.swords[i].state != virgin_sword.state)
2051
7248
/*--------------------------------------------------------------*/
2052
7249
/*--- Instrumentation ---*/
2053
7250
/*--------------------------------------------------------------*/
2055
static UInt stk_ld, nonstk_ld, stk_st, nonstk_st;
2058
/* Create and return an instrumented version of cb_in. Free cb_in
2059
before returning. */
2060
UCodeBlock* TL_(instrument) ( UCodeBlock* cb_in, Addr not_used )
7252
static void instrument_mem_access ( IRSB* bbOut,
2065
Int t_size = INVALID_TEMPREG;
2067
Bool *stackref = NULL;
2068
Bool locked = False; /* lock prefix */
2070
cb = VG_(setup_UCodeBlock)(cb_in);
2072
/* stackref[] is used for super-simple value tracking to keep note
2073
of which tempregs currently hold a value which is derived from
2074
the stack pointer or frame pointer, and is therefore likely
2075
stack-relative if used as the address for LOAD or STORE. */
2076
ntemps = VG_(get_num_temps)(cb);
2077
stackref = VG_(malloc)(sizeof(*stackref) * ntemps);
2078
VG_(memset)(stackref, 0, sizeof(*stackref) * ntemps);
2080
for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
2081
u_in = VG_(get_instr)(cb_in, i);
2083
switch (u_in->opcode) {
2085
case NOP: case CALLM_S: case CALLM_E:
2090
uInstr0(cb, CCALL, 0);
2091
uCCall(cb, (Addr)bus_lock, 0, 0, False);
2094
case JMP: case INCEIP:
2096
uInstr0(cb, CCALL, 0);
2097
uCCall(cb, (Addr)bus_unlock, 0, 0, False);
2100
VG_(copy_UInstr)(cb, u_in);
2104
tl_assert(u_in->tag1 == ArchReg);
2105
tl_assert(u_in->tag2 == TempReg);
2106
tl_assert(u_in->val2 < ntemps);
2108
stackref[u_in->val2] = (u_in->size == 4 &&
2109
(u_in->val1 == VG_R_STACK_PTR ||
2110
u_in->val1 == VG_R_FRAME_PTR));
2111
VG_(copy_UInstr)(cb, u_in);
2115
if (u_in->size == 4 && u_in->tag1 == TempReg) {
2116
tl_assert(u_in->tag2 == TempReg);
2117
stackref[u_in->val2] = stackref[u_in->val1];
2119
VG_(copy_UInstr)(cb, u_in);
2124
if (u_in->size == 4 && u_in->tag1 == TempReg) {
2125
tl_assert(u_in->tag2 == TempReg);
2126
stackref[u_in->val2] |= stackref[u_in->val1];
2128
VG_(copy_UInstr)(cb, u_in);
2133
tl_assert(1 == u_in->size || 2 == u_in->size || 4 == u_in->size);
2134
tl_assert(u_in->tag1 == TempReg);
2136
if (!clo_priv_stacks || !stackref[u_in->val1]) {
2139
switch(u_in->size) {
2140
case 1: help = hg_mem_help_read_1; break;
2141
case 2: help = hg_mem_help_read_2; break;
2142
case 4: help = hg_mem_help_read_4; break;
2144
VG_(tool_panic)("bad size");
2147
/* XXX all registers should be flushed to baseblock
2149
uInstr1(cb, CCALL, 0, TempReg, u_in->val1);
2150
uCCall(cb, (Addr)help, 1, 1, False);
2154
VG_(copy_UInstr)(cb, u_in);
2155
t_size = INVALID_TEMPREG;
2161
tl_assert(1 == u_in->size || 2 == u_in->size || 4 == u_in->size ||
2162
8 == u_in->size || 10 == u_in->size || 108 == u_in->size);
2164
t_size = newTemp(cb);
2165
uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
2166
uLiteral(cb, (UInt)u_in->size);
2168
/* XXX all registers should be flushed to baseblock
2170
uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
2171
uCCall(cb, (Addr) & hg_mem_help_read_N, 2, 2, False);
2173
VG_(copy_UInstr)(cb, u_in);
2174
t_size = INVALID_TEMPREG;
2178
case MMX2a1_MemRd: {
2179
tl_assert(8 == u_in->size);
2181
t_size = newTemp(cb);
2182
uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
2183
uLiteral(cb, (UInt)u_in->size);
2185
/* XXX all registers should be flushed to baseblock
2187
uInstr2(cb, CCALL, 0, TempReg, u_in->val3, TempReg, t_size);
2188
uCCall(cb, (Addr) & hg_mem_help_read_N, 2, 2, False);
2190
VG_(copy_UInstr)(cb, u_in);
2191
t_size = INVALID_TEMPREG;
2199
case SSE3ag_MemRd_RegWr: {
2200
Int addr = (u_in->opcode == SSE3ag_MemRd_RegWr) ? u_in->val1 : u_in->val3;
2202
tl_assert(u_in->size == 4 || u_in->size == 8 || u_in->size == 16 || u_in->size == 512);
2204
t_size = newTemp(cb);
2205
uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
2206
uLiteral(cb, (UInt)u_in->size);
2208
uInstr2(cb, CCALL, 0, TempReg, addr, TempReg, t_size);
2209
uCCall(cb, (Addr) & hg_mem_help_read_N, 2, 2, False);
2211
VG_(copy_UInstr)(cb, u_in);
2212
t_size = INVALID_TEMPREG;
2217
void (*help)(Addr, UInt);
2218
tl_assert(1 == u_in->size || 2 == u_in->size || 4 == u_in->size);
2219
tl_assert(u_in->tag2 == TempReg);
2221
if (!clo_priv_stacks || !stackref[u_in->val2]) {
2224
switch(u_in->size) {
2225
case 1: help = hg_mem_help_write_1; break;
2226
case 2: help = hg_mem_help_write_2; break;
2227
case 4: help = hg_mem_help_write_4; break;
2229
VG_(tool_panic)("bad size");
2232
/* XXX all registers should be flushed to baseblock
2234
uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, u_in->val1);
2235
uCCall(cb, (Addr)help, 2, 2, False);
2239
VG_(copy_UInstr)(cb, u_in);
2240
t_size = INVALID_TEMPREG;
2246
tl_assert(1 == u_in->size || 2 == u_in->size || 4 == u_in->size ||
2247
8 == u_in->size || 10 == u_in->size || 108 == u_in->size);
2249
t_size = newTemp(cb);
2250
uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
2251
uLiteral(cb, (UInt)u_in->size);
2252
/* XXX all registers should be flushed to baseblock
2254
uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
2255
uCCall(cb, (Addr) & hg_mem_help_write_N, 2, 2, False);
2257
VG_(copy_UInstr)(cb, u_in);
2258
t_size = INVALID_TEMPREG;
2264
tl_assert(4 == u_in->size || 8 == u_in->size || 16 == u_in->size ||
2267
t_size = newTemp(cb);
2268
uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
2269
uLiteral(cb, (UInt)u_in->size);
2270
/* XXX all registers should be flushed to baseblock
2272
uInstr2(cb, CCALL, 0, TempReg, u_in->val3, TempReg, t_size);
2273
uCCall(cb, (Addr) & hg_mem_help_write_N, 2, 2, False);
2275
VG_(copy_UInstr)(cb, u_in);
2276
t_size = INVALID_TEMPREG;
7258
IRType tyAddr = Ity_INVALID;
7259
HChar* hName = NULL;
7262
IRExpr** argv = NULL;
7265
tl_assert(isIRAtom(addr));
7266
tl_assert(hWordTy_szB == 4 || hWordTy_szB == 8);
7268
tyAddr = typeOfIRExpr( bbOut->tyenv, addr );
7269
tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
7271
/* So the effective address is in 'addr' now. */
7272
regparms = 1; // unless stated otherwise
7276
hName = "evh__mem_help_write_1";
7277
hAddr = &evh__mem_help_write_1;
7278
argv = mkIRExprVec_1( addr );
7281
hName = "evh__mem_help_write_2";
7282
hAddr = &evh__mem_help_write_2;
7283
argv = mkIRExprVec_1( addr );
7286
hName = "evh__mem_help_write_4";
7287
hAddr = &evh__mem_help_write_4;
7288
argv = mkIRExprVec_1( addr );
7291
hName = "evh__mem_help_write_8";
7292
hAddr = &evh__mem_help_write_8;
7293
argv = mkIRExprVec_1( addr );
2281
/* conservative tromping */
2282
if (0 && u_in->tag1 == TempReg) /* can val1 ever be dest? */
2283
stackref[u_in->val1] = False;
2284
if (u_in->tag2 == TempReg)
2285
stackref[u_in->val2] = False;
2286
if (u_in->tag3 == TempReg)
2287
stackref[u_in->val3] = False;
2288
VG_(copy_UInstr)(cb, u_in);
2293
VG_(free)(stackref);
2294
VG_(free_UCodeBlock)(cb_in);
7296
tl_assert(szB > 8 && szB <= 512); /* stay sane */
7298
hName = "evh__mem_help_write_N";
7299
hAddr = &evh__mem_help_write_N;
7300
argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB ));
7306
hName = "evh__mem_help_read_1";
7307
hAddr = &evh__mem_help_read_1;
7308
argv = mkIRExprVec_1( addr );
7311
hName = "evh__mem_help_read_2";
7312
hAddr = &evh__mem_help_read_2;
7313
argv = mkIRExprVec_1( addr );
7316
hName = "evh__mem_help_read_4";
7317
hAddr = &evh__mem_help_read_4;
7318
argv = mkIRExprVec_1( addr );
7321
hName = "evh__mem_help_read_8";
7322
hAddr = &evh__mem_help_read_8;
7323
argv = mkIRExprVec_1( addr );
7326
tl_assert(szB > 8 && szB <= 512); /* stay sane */
7328
hName = "evh__mem_help_read_N";
7329
hAddr = &evh__mem_help_read_N;
7330
argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB ));
7335
/* Add the helper. */
7339
di = unsafeIRDirty_0_N( regparms,
7340
hName, VG_(fnptr_to_fnentry)( hAddr ),
7342
addStmtToIRSB( bbOut, IRStmt_Dirty(di) );
7346
static void instrument_memory_bus_event ( IRSB* bbOut, IRMBusEvent event )
7350
break; /* not interesting */
7352
case Imbe_BusUnlock:
7358
event == Imbe_BusLock ? "evh__bus_lock"
7359
: "evh__bus_unlock",
7360
VG_(fnptr_to_fnentry)(
7361
event == Imbe_BusLock ? &evh__bus_lock
2299
IRBB* hg_instrument ( VgCallbackClosure* closure,
2301
VexGuestLayout* layout,
7376
IRSB* hg_instrument ( VgCallbackClosure* closure,
7378
VexGuestLayout* layout,
2302
7379
VexGuestExtents* vge,
2303
7380
IRType gWordTy, IRType hWordTy )
2305
tl_assert(0); // Need to convert to Vex
2308
/*--------------------------------------------------------------------*/
2309
/*--- Error and suppression handling ---*/
2310
/*--------------------------------------------------------------------*/
2314
/* Possible data race */
2319
/* What kind of error it is. */
2322
RaceErr, /* data-race */
2323
MutexErr, /* mutex operations */
2324
LockGraphErr, /* mutex order error */
2328
/* The classification of a faulting address. */
2330
enum { Undescribed, /* as-yet unclassified */
2332
Unknown, /* classification yielded nothing useful */
2338
/* Records info about a faulting address. */
2343
/* Freed, Mallocd */
2345
/* Freed, Mallocd */
2347
/* Freed, Mallocd */
2348
ExeContext* lastchange;
2353
const Char* filename;
2354
const Char* section;
2355
/* True if is just-below the stack pointer -- could be a gcc bug. */
2357
/* symbolic address description */
2362
/* What kind of memory access is involved in the error? */
2364
enum { ReadAxs, WriteAxs, ExecAxs }
2367
/* Extra context for memory errors */
2374
shadow_word prevstate;
2375
/* MutexErr, LockGraphErr */
2380
const LockSet *held_lockset;
2381
const LockSet *prev_lockset;
2386
void clear_AddrInfo ( AddrInfo* ai )
2388
ai->akind = Unknown;
2391
ai->lastchange = NULL;
2392
ai->lasttid = VG_INVALID_THREADID;
2393
ai->filename = NULL;
2394
ai->section = "???";
2395
ai->stack_tid = VG_INVALID_THREADID;
2396
ai->maybe_gcc = False;
2401
void clear_HelgrindError ( HelgrindError* err_extra )
2403
err_extra->axskind = ReadAxs;
2404
err_extra->size = 0;
2405
err_extra->mutex = NULL;
2406
err_extra->lasttouched= NULL_EC_IP;
2407
err_extra->lasttid = VG_INVALID_THREADID;
2408
err_extra->prev_lockset = 0;
2409
err_extra->held_lockset = 0;
2410
err_extra->prevstate = SW(Vge_Virgin, 0);
2411
clear_AddrInfo ( &err_extra->addrinfo );
2412
err_extra->isWrite = False;
2417
/* Describe an address as best you can, for error messages,
2418
putting the result in ai. */
2420
/* Callback for searching malloc'd and free'd lists */
2421
static Bool addr_is_in_block(VgHashNode *node, void *ap)
2423
HG_Chunk* hc2 = (HG_Chunk*)node;
2424
Addr a = *(Addr *)ap;
2426
return (hc2->data <= a && a < hc2->data + hc2->size);
2429
static void describe_addr ( Addr a, AddrInfo* ai )
2434
/* Search for it in segments */
2438
for (si = VG_(next_seginfo)(NULL);
2440
si = VG_(next_seginfo)(si))
2442
Addr base = VG_(seginfo_start)(si);
2443
SizeT size = VG_(seginfo_size)(si);
2444
const UChar *filename = VG_(seginfo_filename)(si);
2446
if (a >= base && a < base+size) {
2447
ai->akind = Segment;
2449
ai->rwoffset = a - base;
2450
ai->filename = filename;
2452
switch(VG_(seginfo_sect_kind)(a)) {
2453
case Vg_SectText: ai->section = "text"; break;
2454
case Vg_SectData: ai->section = "data"; break;
2455
case Vg_SectBSS: ai->section = "BSS"; break;
2456
case Vg_SectGOT: ai->section = "GOT"; break;
2457
case Vg_SectPLT: ai->section = "PLT"; break;
2458
case Vg_SectUnknown:
2460
ai->section = "???"; break;
2468
/* Search for a currently malloc'd block which might bracket it. */
2469
hc = (HG_Chunk*)VG_(HT_first_match)(hg_malloc_list, addr_is_in_block, &a);
2471
ai->akind = Mallocd;
2472
ai->blksize = hc->size;
2473
ai->rwoffset = (Int)a - (Int)(hc->data);
2474
ai->lastchange = hc->where;
2475
ai->lasttid = hc->tid;
2479
/* Look in recently freed memory */
2480
for(i = 0; i < N_FREED_CHUNKS; i++) {
2485
if (a >= hc->data && a < hc->data + hc->size) {
2487
ai->blksize = hc->size;
2488
ai->rwoffset = a - hc->data;
2489
ai->lastchange = hc->where;
2490
ai->lasttid = hc->tid;
2496
ai->akind = Unknown;
7385
if (gWordTy != hWordTy) {
7386
/* We don't currently support this case. */
7387
VG_(tool_panic)("host/guest word size mismatch");
7391
bbOut = emptyIRSB();
7392
bbOut->tyenv = deepCopyIRTypeEnv(bbIn->tyenv);
7393
bbOut->next = deepCopyIRExpr(bbIn->next);
7394
bbOut->jumpkind = bbIn->jumpkind;
7396
// Copy verbatim any IR preamble preceding the first IMark
7398
while (i < bbIn->stmts_used && bbIn->stmts[i]->tag != Ist_IMark) {
7399
addStmtToIRSB( bbOut, bbIn->stmts[i] );
7403
for (/*use current i*/; i < bbIn->stmts_used; i++) {
7404
IRStmt* st = bbIn->stmts[i];
7406
tl_assert(isFlatIRStmt(st));
7414
/* None of these can contain any memory references. */
7418
instrument_memory_bus_event( bbOut, st->Ist.MBE.event );
7422
instrument_mem_access(
7425
sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)),
7427
sizeofIRType(hWordTy)
7432
IRExpr* data = st->Ist.WrTmp.data;
7433
if (data->tag == Iex_Load) {
7434
instrument_mem_access(
7436
data->Iex.Load.addr,
7437
sizeofIRType(data->Iex.Load.ty),
7439
sizeofIRType(hWordTy)
7447
IRDirty* d = st->Ist.Dirty.details;
7448
if (d->mFx != Ifx_None) {
7449
/* This dirty helper accesses memory. Collect the
7451
tl_assert(d->mAddr != NULL);
7452
tl_assert(d->mSize != 0);
7453
dataSize = d->mSize;
7454
if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
7455
instrument_mem_access(
7456
bbOut, d->mAddr, dataSize, False/*!isStore*/,
7457
sizeofIRType(hWordTy)
7460
if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
7461
instrument_mem_access(
7462
bbOut, d->mAddr, dataSize, True/*isStore*/,
7463
sizeofIRType(hWordTy)
7467
tl_assert(d->mAddr == NULL);
7468
tl_assert(d->mSize == 0);
7476
} /* switch (st->tag) */
7478
addStmtToIRSB( bbOut, st );
7479
} /* iterate over bbIn->stmts */
7485
/*----------------------------------------------------------------*/
7486
/*--- Client requests ---*/
7487
/*----------------------------------------------------------------*/
7489
/* Sheesh. Yet another goddam finite map. */
7490
static WordFM* map_pthread_t_to_Thread = NULL; /* pthread_t -> Thread* */
7492
static void map_pthread_t_to_Thread_INIT ( void ) {
7493
if (UNLIKELY(map_pthread_t_to_Thread == NULL)) {
7494
map_pthread_t_to_Thread = HG_(newFM)( hg_zalloc, hg_free, NULL );
7495
tl_assert(map_pthread_t_to_Thread != NULL);
7501
Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret)
7503
if (!VG_IS_TOOL_USERREQ('H','G',args[0]))
7506
/* Anything that gets past the above check is one of ours, so we
7507
should be able to handle it. */
7509
/* default, meaningless return value, unless otherwise set */
7514
/* --- --- User-visible client requests --- --- */
7516
case VG_USERREQ__HG_CLEAN_MEMORY:
7517
if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY(%p,%d)\n",
7519
/* Call die_mem to (expensively) tidy up properly, if there
7520
are any held locks etc in the area */
7521
if (args[2] > 0) { /* length */
7522
evh__die_mem(args[1], args[2]);
7523
/* and then set it to New */
7524
evh__new_mem(args[1], args[2]);
7528
/* --- --- Client requests for Helgrind's use only --- --- */
7530
/* Some thread is telling us its pthread_t value. Record the
7531
binding between that and the associated Thread*, so we can
7532
later find the Thread* again when notified of a join by the
7534
case _VG_USERREQ__HG_SET_MY_PTHREAD_T: {
7535
Thread* my_thr = NULL;
7537
VG_(printf)("SET_MY_PTHREAD_T (tid %d): pthread_t = %p\n", (Int)tid,
7539
map_pthread_t_to_Thread_INIT();
7540
my_thr = map_threads_maybe_lookup( tid );
7541
/* This assertion should hold because the map_threads (tid to
7542
Thread*) binding should have been made at the point of
7543
low-level creation of this thread, which should have
7544
happened prior to us getting this client request for it.
7545
That's because this client request is sent from
7546
client-world from the 'thread_wrapper' function, which
7547
only runs once the thread has been low-level created. */
7548
tl_assert(my_thr != NULL);
7549
/* So now we know that (pthread_t)args[1] is associated with
7550
(Thread*)my_thr. Note that down. */
7552
VG_(printf)("XXXX: bind pthread_t %p to Thread* %p\n",
7553
(void*)args[1], (void*)my_thr );
7554
HG_(addToFM)( map_pthread_t_to_Thread, (Word)args[1], (Word)my_thr );
7558
case _VG_USERREQ__HG_PTH_API_ERROR: {
7559
Thread* my_thr = NULL;
7560
map_pthread_t_to_Thread_INIT();
7561
my_thr = map_threads_maybe_lookup( tid );
7562
tl_assert(my_thr); /* See justification above in SET_MY_PTHREAD_T */
7563
record_error_PthAPIerror( my_thr, (HChar*)args[1],
7564
(Word)args[2], (HChar*)args[3] );
7568
/* This thread (tid) has completed a join with the quitting
7569
thread whose pthread_t is in args[1]. */
7570
case _VG_USERREQ__HG_PTHREAD_JOIN_POST: {
7571
Thread* thr_q = NULL; /* quitter Thread* */
7574
VG_(printf)("NOTIFY_JOIN_COMPLETE (tid %d): quitter = %p\n", (Int)tid,
7576
map_pthread_t_to_Thread_INIT();
7577
found = HG_(lookupFM)( map_pthread_t_to_Thread,
7578
NULL, (Word*)&thr_q, (Word)args[1] );
7579
/* Can this fail? It would mean that our pthread_join
7580
wrapper observed a successful join on args[1] yet that
7581
thread never existed (or at least, it never lodged an
7582
entry in the mapping (via SET_MY_PTHREAD_T)). Which
7583
sounds like a bug in the threads library. */
7584
// FIXME: get rid of this assertion; handle properly
7588
VG_(printf)(".................... quitter Thread* = %p\n",
7590
evh__HG_PTHREAD_JOIN_POST( tid, thr_q );
7595
/* EXPOSITION only: by intercepting lock init events we can show
7596
the user where the lock was initialised, rather than only
7597
being able to show where it was first locked. Intercepting
7598
lock initialisations is not necessary for the basic operation
7599
of the race checker. */
7600
case _VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST:
7601
evh__HG_PTHREAD_MUTEX_INIT_POST( tid, (void*)args[1], args[2] );
7604
case _VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE:
7605
evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, (void*)args[1] );
7608
case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE: // pth_mx_t*
7609
evh__HG_PTHREAD_MUTEX_UNLOCK_PRE( tid, (void*)args[1] );
7612
case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST: // pth_mx_t*
7613
evh__HG_PTHREAD_MUTEX_UNLOCK_POST( tid, (void*)args[1] );
7616
case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE: // pth_mx_t*, Word
7617
evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, (void*)args[1], args[2] );
7620
case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST: // pth_mx_t*
7621
evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, (void*)args[1] );
7624
/* This thread is about to do pthread_cond_signal on the
7625
pthread_cond_t* in arg[1]. Ditto pthread_cond_broadcast. */
7626
case _VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE:
7627
case _VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE:
7628
evh__HG_PTHREAD_COND_SIGNAL_PRE( tid, (void*)args[1] );
7631
/* Entry into pthread_cond_wait, cond=arg[1], mutex=arg[2].
7632
Returns a flag indicating whether or not the mutex is believed to be
7633
valid for this operation. */
7634
case _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE: {
7636
= evh__HG_PTHREAD_COND_WAIT_PRE( tid, (void*)args[1],
7638
*ret = mutex_is_valid ? 1 : 0;
7642
/* Thread successfully completed pthread_cond_wait, cond=arg[1],
7644
case _VG_USERREQ__HG_PTHREAD_COND_WAIT_POST:
7645
evh__HG_PTHREAD_COND_WAIT_POST( tid,
7646
(void*)args[1], (void*)args[2] );
7649
case _VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST:
7650
evh__HG_PTHREAD_RWLOCK_INIT_POST( tid, (void*)args[1] );
7653
case _VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE:
7654
evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( tid, (void*)args[1] );
7657
/* rwlock=arg[1], isW=arg[2], isTryLock=arg[3] */
7658
case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE:
7659
evh__HG_PTHREAD_RWLOCK_LOCK_PRE( tid, (void*)args[1],
7663
/* rwlock=arg[1], isW=arg[2] */
7664
case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST:
7665
evh__HG_PTHREAD_RWLOCK_LOCK_POST( tid, (void*)args[1], args[2] );
7668
case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE:
7669
evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE( tid, (void*)args[1] );
7672
case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST:
7673
evh__HG_PTHREAD_RWLOCK_UNLOCK_POST( tid, (void*)args[1] );
7676
case _VG_USERREQ__HG_POSIX_SEM_INIT_POST: /* sem_t*, unsigned long */
7677
evh__HG_POSIX_SEM_INIT_POST( tid, (void*)args[1], args[2] );
7680
case _VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE: /* sem_t* */
7681
evh__HG_POSIX_SEM_DESTROY_PRE( tid, (void*)args[1] );
7684
case _VG_USERREQ__HG_POSIX_SEM_POST_PRE: /* sem_t* */
7685
evh__HG_POSIX_SEM_POST_PRE( tid, (void*)args[1] );
7688
case _VG_USERREQ__HG_POSIX_SEM_WAIT_POST: /* sem_t* */
7689
evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] );
7692
case _VG_USERREQ__HG_GET_MY_SEGMENT: { // -> Segment*
7696
thr = map_threads_maybe_lookup( tid );
7697
tl_assert(thr); /* cannot fail */
7698
segid = thr->csegid;
7699
tl_assert(is_sane_SegmentID(segid));
7700
seg = map_segments_lookup( segid );
7707
/* Unhandled Helgrind client request! */
7708
tl_assert2(0, "unhandled Helgrind client request!");
7715
/*----------------------------------------------------------------*/
7716
/*--- Error management ---*/
7717
/*----------------------------------------------------------------*/
7719
/* maps (by value) strings to a copy of them in ARENA_TOOL */
7720
static UWord stats__string_table_queries = 0;
7721
static WordFM* string_table = NULL;
7722
static Word string_table_cmp ( Word s1, Word s2 ) {
7723
return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
7725
static HChar* string_table_strdup ( HChar* str ) {
7727
stats__string_table_queries++;
7730
if (!string_table) {
7731
string_table = HG_(newFM)( hg_zalloc, hg_free, string_table_cmp );
7732
tl_assert(string_table);
7734
if (HG_(lookupFM)( string_table,
7735
NULL, (Word*)©, (Word)str )) {
7737
if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
7740
copy = VG_(strdup)(str);
7742
HG_(addToFM)( string_table, (Word)copy, (Word)copy );
7747
/* maps from Lock .unique fields to LockP*s */
7748
static UWord stats__ga_LockN_to_P_queries = 0;
7749
static WordFM* yaWFM = NULL;
7750
static Word lock_unique_cmp ( Word lk1W, Word lk2W )
7752
Lock* lk1 = (Lock*)lk1W;
7753
Lock* lk2 = (Lock*)lk2W;
7754
tl_assert( is_sane_LockNorP(lk1) );
7755
tl_assert( is_sane_LockNorP(lk2) );
7756
if (lk1->unique < lk2->unique) return -1;
7757
if (lk1->unique > lk2->unique) return 1;
7760
static Lock* mk_LockP_from_LockN ( Lock* lkn )
7763
stats__ga_LockN_to_P_queries++;
7764
tl_assert( is_sane_LockN(lkn) );
7766
yaWFM = HG_(newFM)( hg_zalloc, hg_free, lock_unique_cmp );
7769
if (!HG_(lookupFM)( yaWFM, NULL, (Word*)&lkp, (Word)lkn)) {
7770
lkp = hg_zalloc( sizeof(Lock) );
7773
lkp->magic = LockP_MAGIC;
7774
/* Forget about the bag of lock holders - don't copy that.
7775
Also, acquired_at should be NULL whenever heldBy is, and vice
7779
lkp->acquired_at = NULL;
7780
HG_(addToFM)( yaWFM, (Word)lkp, (Word)lkp );
7782
tl_assert( is_sane_LockP(lkp) );
7788
race: program counter
7794
FIXME: how does state printing interact with lockset gc?
7795
Are the locksets in prev/curr state always valid?
7796
Ditto question for the threadsets
7797
ThreadSets - probably are always valid if Threads
7798
are never thrown away.
7799
LockSets - could at least print the lockset elements that
7800
correspond to actual locks at the time of printing. Hmm.
7806
XE_Race=1101, // race
7807
XE_FreeMemLock, // freeing memory containing a locked lock
7808
XE_UnlockUnlocked, // unlocking a not-locked lock
7809
XE_UnlockForeign, // unlocking a lock held by some other thread
7810
XE_UnlockBogus, // unlocking an address not known to be a lock
7811
XE_PthAPIerror, // error from the POSIX pthreads API
7812
XE_LockOrder, // lock order error
7813
XE_Misc // misc other error (w/ string to describe it)
7817
/* Extra contexts for kinds */
7828
ExeContext* mb_lastlock;
7832
Thread* thr; /* doing the freeing */
7833
Lock* lock; /* lock which is locked */
7836
Thread* thr; /* doing the unlocking */
7837
Lock* lock; /* lock (that is already unlocked) */
7840
Thread* thr; /* doing the unlocking */
7841
Thread* owner; /* thread that actually holds the lock */
7842
Lock* lock; /* lock (that is held by 'owner') */
7845
Thread* thr; /* doing the unlocking */
7846
Addr lock_ga; /* purported address of the lock */
7850
HChar* fnname; /* persistent, in tool-arena */
7851
Word err; /* pth error code */
7852
HChar* errstr; /* persistent, in tool-arena */
7856
Addr before_ga; /* always locked first in prog. history */
7858
ExeContext* before_ec;
7859
ExeContext* after_ec;
7863
HChar* errstr; /* persistent, in tool-arena */
7869
static void init_XError ( XError* xe ) {
7870
VG_(memset)(xe, 0, sizeof(*xe) );
7871
xe->tag = XE_Race-1; /* bogus */
7875
/* Extensions of suppressions */
7878
XS_Race=1201, /* race */
2501
7890
/* Updates the copy with address info if necessary. */
2502
static UInt hg_update_extra(Error* err)
2504
HelgrindError* extra;
2506
extra = (HelgrindError*)VG_(get_error_extra)(err);
2507
if (extra != NULL && Undescribed == extra->addrinfo.akind) {
2508
describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
2510
return sizeof(HelgrindError);
2513
static void record_race_error ( ThreadId tid, Addr a, Bool is_write,
2514
shadow_word prevstate )
2517
HelgrindError err_extra;
2521
clear_HelgrindError(&err_extra);
2522
err_extra.isWrite = is_write;
2523
err_extra.addrinfo.akind = Undescribed;
2524
err_extra.prevstate = prevstate;
2526
err_extra.lasttouched = getExeContext(a);
2527
/* JRS 4 Apr 06: VG_(describe_addr) disappeared from m_debuginfo,
2528
at least for the time being. */
2529
err_extra.addrinfo.expr = "???"; /* VG_(describe_addr)(tid, a); */
2531
VG_(maybe_record_error)( tid, RaceErr, a,
2532
(is_write ? "writing" : "reading"),
2535
sw = get_sword_addr(a);
2536
if (sw->state == Vge_Excl && sw->other != TLSP_INDICATING_ALL) {
2537
ThreadLifeSeg *tls = unpackTLS(sw->other);
2541
set_sword(a, error_sword);
2544
static void record_mutex_error(ThreadId tid, Mutex *mutex,
2545
Char *str, ExeContext *ec)
2547
HelgrindError err_extra;
2549
clear_HelgrindError(&err_extra);
2550
err_extra.addrinfo.akind = Undescribed;
2551
err_extra.mutex = mutex;
2552
err_extra.lasttouched = EC(ec, virgin_sword, thread_seg[tid]);
2553
err_extra.lasttid = tid;
2555
VG_(maybe_record_error)(tid, MutexErr,
2556
(Addr)mutex->mutexp, str, &err_extra);
2559
static void record_lockgraph_error(ThreadId tid, Mutex *mutex,
2560
const LockSet *lockset_holding,
2561
const LockSet *lockset_prev)
2563
HelgrindError err_extra;
2565
n_lockorder_warnings++;
2567
clear_HelgrindError(&err_extra);
2568
err_extra.addrinfo.akind = Undescribed;
2569
err_extra.mutex = mutex;
2571
err_extra.lasttouched = EC(mutex->location, virgin_sword, 0);
2572
err_extra.held_lockset = lockset_holding;
2573
err_extra.prev_lockset = lockset_prev;
2575
VG_(maybe_record_error)(tid, LockGraphErr, mutex->mutexp, "", &err_extra);
7891
static UInt hg_update_extra ( Error* err )
7893
XError* extra = (XError*)VG_(get_error_extra)(err);
7895
//if (extra != NULL && Undescribed == extra->addrinfo.akind) {
7896
// describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
7898
return sizeof(XError);
7901
static void record_error_Race ( Thread* thr,
7902
Addr data_addr, Bool isWrite, Int szB,
7903
SVal old_sv, SVal new_sv,
7904
ExeContext* mb_lastlock ) {
7906
tl_assert( is_sane_Thread(thr) );
7909
xe.XE.Race.data_addr = data_addr;
7910
xe.XE.Race.szB = szB;
7911
xe.XE.Race.isWrite = isWrite;
7912
xe.XE.Race.new_state = new_sv;
7913
xe.XE.Race.old_state = old_sv;
7914
xe.XE.Race.mb_lastlock = mb_lastlock;
7915
xe.XE.Race.thr = thr;
7916
// FIXME: tid vs thr
7917
tl_assert(isWrite == False || isWrite == True);
7918
tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
7919
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
7920
XE_Race, data_addr, NULL, &xe );
7923
static void record_error_FreeMemLock ( Thread* thr, Lock* lk ) {
7925
tl_assert( is_sane_Thread(thr) );
7926
tl_assert( is_sane_LockN(lk) );
7928
xe.tag = XE_FreeMemLock;
7929
xe.XE.FreeMemLock.thr = thr;
7930
xe.XE.FreeMemLock.lock = mk_LockP_from_LockN(lk);
7931
// FIXME: tid vs thr
7932
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
7933
XE_FreeMemLock, 0, NULL, &xe );
7936
static void record_error_UnlockUnlocked ( Thread* thr, Lock* lk ) {
7938
tl_assert( is_sane_Thread(thr) );
7939
tl_assert( is_sane_LockN(lk) );
7941
xe.tag = XE_UnlockUnlocked;
7942
xe.XE.UnlockUnlocked.thr = thr;
7943
xe.XE.UnlockUnlocked.lock = mk_LockP_from_LockN(lk);
7944
// FIXME: tid vs thr
7945
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
7946
XE_UnlockUnlocked, 0, NULL, &xe );
7949
static void record_error_UnlockForeign ( Thread* thr,
7950
Thread* owner, Lock* lk ) {
7952
tl_assert( is_sane_Thread(thr) );
7953
tl_assert( is_sane_Thread(owner) );
7954
tl_assert( is_sane_LockN(lk) );
7956
xe.tag = XE_UnlockForeign;
7957
xe.XE.UnlockForeign.thr = thr;
7958
xe.XE.UnlockForeign.owner = owner;
7959
xe.XE.UnlockForeign.lock = mk_LockP_from_LockN(lk);
7960
// FIXME: tid vs thr
7961
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
7962
XE_UnlockForeign, 0, NULL, &xe );
7965
static void record_error_UnlockBogus ( Thread* thr, Addr lock_ga ) {
7967
tl_assert( is_sane_Thread(thr) );
7969
xe.tag = XE_UnlockBogus;
7970
xe.XE.UnlockBogus.thr = thr;
7971
xe.XE.UnlockBogus.lock_ga = lock_ga;
7972
// FIXME: tid vs thr
7973
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
7974
XE_UnlockBogus, 0, NULL, &xe );
7978
void record_error_LockOrder ( Thread* thr, Addr before_ga, Addr after_ga,
7979
ExeContext* before_ec, ExeContext* after_ec ) {
7981
tl_assert( is_sane_Thread(thr) );
7983
xe.tag = XE_LockOrder;
7984
xe.XE.LockOrder.thr = thr;
7985
xe.XE.LockOrder.before_ga = before_ga;
7986
xe.XE.LockOrder.before_ec = before_ec;
7987
xe.XE.LockOrder.after_ga = after_ga;
7988
xe.XE.LockOrder.after_ec = after_ec;
7989
// FIXME: tid vs thr
7990
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
7991
XE_LockOrder, 0, NULL, &xe );
7995
void record_error_PthAPIerror ( Thread* thr, HChar* fnname,
7996
Word err, HChar* errstr ) {
7998
tl_assert( is_sane_Thread(thr) );
8002
xe.tag = XE_PthAPIerror;
8003
xe.XE.PthAPIerror.thr = thr;
8004
xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
8005
xe.XE.PthAPIerror.err = err;
8006
xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
8007
// FIXME: tid vs thr
8008
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
8009
XE_PthAPIerror, 0, NULL, &xe );
8012
static void record_error_Misc ( Thread* thr, HChar* errstr ) {
8014
tl_assert( is_sane_Thread(thr) );
8018
xe.XE.Misc.thr = thr;
8019
xe.XE.Misc.errstr = string_table_strdup(errstr);
8020
// FIXME: tid vs thr
8021
VG_(maybe_record_error)( map_threads_reverse_lookup_SLOW(thr),
8022
XE_Misc, 0, NULL, &xe );
2578
8025
static Bool hg_eq_Error ( VgRes not_used, Error* e1, Error* e2 )
2582
8029
tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
8031
xe1 = (XError*)VG_(get_error_extra)(e1);
8032
xe2 = (XError*)VG_(get_error_extra)(e2);
2584
8036
switch (VG_(get_error_kind)(e1)) {
2586
return VG_(get_error_address)(e1) == VG_(get_error_address)(e2);
2589
return VG_(get_error_address)(e1) == VG_(get_error_address)(e2);
2592
e1s = VG_(get_error_string)(e1);
2593
e2s = VG_(get_error_string)(e2);
2594
if (e1s != e2s) return False;
2595
if (0 != VG_(strcmp)(e1s, e2s)) return False;
2599
static void pp_AddrInfo ( Addr a, AddrInfo* ai )
2601
if (ai->expr != NULL)
2602
VG_(message)(Vg_UserMsg,
2603
" Address %p == %s", a, ai->expr);
2605
switch (ai->akind) {
2607
VG_(message)(Vg_UserMsg,
2608
" Address %p is on thread %d's stack",
2612
if (ai->expr != NULL)
2615
/* maybe_gcc is never set to True! This is a hangover from code
2617
if (ai->maybe_gcc) {
2618
VG_(message)(Vg_UserMsg,
2619
" Address %p is just below the stack pointer. Possibly a bug in GCC/G++",
2621
VG_(message)(Vg_UserMsg,
2622
" v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
2624
VG_(message)(Vg_UserMsg,
2625
" Address %p is not stack'd, malloc'd or (recently) free'd", a);
2629
VG_(message)(Vg_UserMsg,
2630
" Address %p is in %s section of %s",
2631
a, ai->section, ai->filename);
2637
if (ai->rwoffset < 0) {
2638
delta = (SizeT)(- ai->rwoffset);
2639
relative = "before";
2640
} else if (ai->rwoffset >= ai->blksize) {
2641
delta = ai->rwoffset - ai->blksize;
2644
delta = ai->rwoffset;
2645
relative = "inside";
2647
VG_(message)(Vg_UserMsg,
2648
" Address %p is %llu bytes %s a block of size %d %s by thread %d",
2649
a, (ULong)delta, relative,
2651
ai->akind == Mallocd ? "alloc'd" : "freed",
2654
VG_(pp_ExeContext)(ai->lastchange);
8038
return xe1->XE.Race.szB == xe2->XE.Race.szB
8039
&& xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
8040
&& (clo_cmp_race_err_addrs
8041
? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
8043
case XE_FreeMemLock:
8044
return xe1->XE.FreeMemLock.thr == xe2->XE.FreeMemLock.thr
8045
&& xe1->XE.FreeMemLock.lock == xe2->XE.FreeMemLock.lock;
8046
case XE_UnlockUnlocked:
8047
return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
8048
&& xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
8049
case XE_UnlockForeign:
8050
return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
8051
&& xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
8052
&& xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
8053
case XE_UnlockBogus:
8054
return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
8055
&& xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
8056
case XE_PthAPIerror:
8057
return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
8058
&& 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
8059
xe2->XE.PthAPIerror.fnname)
8060
&& xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
8062
return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
8064
return xe1->XE.Misc.thr == xe2->XE.Misc.thr
8065
&& 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
2658
VG_(tool_panic)("pp_AddrInfo");
2662
static Char *lockset_str(const Char *prefix, const LockSet *lockset)
2667
buf = VG_(malloc)((prefix == NULL ? 0 : VG_(strlen)(prefix)) +
2668
lockset->setsize * 120 +
2673
cp += VG_(sprintf)(cp, "%s", prefix);
2675
for(i = 0; i < lockset->setsize; i++)
2676
cp += VG_(sprintf)(cp, "%p%(y, ", lockset->mutex[i]->mutexp,
2677
lockset->mutex[i]->mutexp);
2679
if (lockset->setsize)
8074
/* Given a WordSetID in univ_tsets (that is, a Thread set ID), produce
8075
an XArray* with the corresponding Thread*'s sorted by their
8076
errmsg_index fields. This is for printing out thread sets in
8077
repeatable orders, which is important for for repeatable regression
8078
testing. The returned XArray* is dynamically allocated (of course)
8079
and so must be hg_freed by the caller. */
8080
static Int cmp_Thread_by_errmsg_index ( void* thr1V, void* thr2V ) {
8081
Thread* thr1 = *(Thread**)thr1V;
8082
Thread* thr2 = *(Thread**)thr2V;
8083
if (thr1->errmsg_index < thr2->errmsg_index) return -1;
8084
if (thr1->errmsg_index > thr2->errmsg_index) return 1;
8087
static XArray* /* of Thread* */ get_sorted_thread_set ( WordSetID tset )
8092
xa = VG_(newXA)( hg_zalloc, hg_free, sizeof(Thread*) );
8094
HG_(getPayloadWS)( &ts_words, &ts_size, univ_tsets, tset );
8095
tl_assert(ts_words);
8096
tl_assert(ts_size >= 0);
8097
/* This isn't a very clever scheme, but we don't expect this to be
8098
called very often. */
8099
for (i = 0; i < ts_size; i++) {
8100
Thread* thr = (Thread*)ts_words[i];
8101
tl_assert(is_sane_Thread(thr));
8102
VG_(addToXA)( xa, (void*)&thr );
8104
tl_assert(ts_size == VG_(sizeXA)( xa ));
8105
VG_(setCmpFnXA)( xa, cmp_Thread_by_errmsg_index );
8111
/* Announce (that is, print the point-of-creation) of the threads in
8112
'tset'. Only do this once, as we only want to see these
8113
announcements once each. Also, first sort the threads by their
8114
errmsg_index fields, and show only the first N_THREADS_TO_ANNOUNCE.
8115
That's because we only want to bother to announce threads
8116
enumerated by summarise_threadset() below, and that in turn does
8117
the same: it sorts them and then only shows the first
8118
N_THREADS_TO_ANNOUNCE. */
8120
static void announce_threadset ( WordSetID tset )
8122
const Word limit = N_THREADS_TO_ANNOUNCE;
8125
Word ts_size, i, loopmax;
8126
sorted = get_sorted_thread_set( tset );
8127
ts_size = VG_(sizeXA)( sorted );
8128
tl_assert(ts_size >= 0);
8129
loopmax = limit < ts_size ? limit : ts_size; /* min(limit, ts_size) */
8130
tl_assert(loopmax >= 0 && loopmax <= limit);
8131
for (i = 0; i < loopmax; i++) {
8132
thr = *(Thread**)VG_(indexXA)( sorted, i );
8133
tl_assert(is_sane_Thread(thr));
8134
tl_assert(thr->errmsg_index >= 1);
8137
if (thr->errmsg_index == 1/*FIXME: this hardwires an assumption
8138
about the identity of the root
8140
tl_assert(thr->created_at == NULL);
8141
VG_(message)(Vg_UserMsg, "Thread #%d is the program's root thread",
8144
tl_assert(thr->created_at != NULL);
8145
VG_(message)(Vg_UserMsg, "Thread #%d was created",
8147
VG_(pp_ExeContext)( thr->created_at );
8149
VG_(message)(Vg_UserMsg, "");
8150
thr->announced = True;
8152
VG_(deleteXA)( sorted );
8154
static void announce_one_thread ( Thread* thr ) {
8155
announce_threadset( HG_(singletonWS)(univ_tsets, (Word)thr ));
8158
/* Generate into buf[0 .. nBuf-1] a 1-line summary of a thread set, of
8159
the form "#1, #3, #77, #78, #79 and 42 others". The first
8160
N_THREADS_TO_ANNOUNCE are listed explicitly (as '#n') and the
8161
leftovers lumped into the 'and n others' bit. */
8163
static void summarise_threadset ( WordSetID tset, Char* buf, UInt nBuf )
8165
const Word limit = N_THREADS_TO_ANNOUNCE;
8168
Word ts_size, i, loopmax;
8170
tl_assert(nBuf > 0);
8171
tl_assert(nBuf >= 40 + 20*limit);
8173
sorted = get_sorted_thread_set( tset );
8174
ts_size = VG_(sizeXA)( sorted );
8175
tl_assert(ts_size >= 0);
8176
loopmax = limit < ts_size ? limit : ts_size; /* min(limit, ts_size) */
8177
tl_assert(loopmax >= 0 && loopmax <= limit);
8178
VG_(memset)(buf, 0, nBuf);
8179
for (i = 0; i < loopmax; i++) {
8180
thr = *(Thread**)VG_(indexXA)( sorted, i );
8181
tl_assert(is_sane_Thread(thr));
8182
tl_assert(thr->errmsg_index >= 1);
8183
off += VG_(sprintf)(&buf[off], "#%d", (Int)thr->errmsg_index);
8185
off += VG_(sprintf)(&buf[off], ", ");
8187
if (limit < ts_size) {
8188
Word others = ts_size - limit;
8189
off += VG_(sprintf)(&buf[off], " and %d other%s",
8190
(Int)others, others > 1 ? "s" : "");
8192
tl_assert(off < nBuf);
8193
tl_assert(buf[nBuf-1] == 0);
8194
VG_(deleteXA)( sorted );
2687
8197
static void hg_pp_Error ( Error* err )
2689
HelgrindError *extra = (HelgrindError *)VG_(get_error_extra)(err);
2696
switch(VG_(get_error_kind)(err)) {
2698
Addr err_addr = VG_(get_error_address)(err);
2700
VG_(message)(Vg_UserMsg, "Possible data race %s variable at %p %(y",
2701
VG_(get_error_string)(err), err_addr, err_addr);
2702
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
2703
pp_AddrInfo(err_addr, &extra->addrinfo);
2705
switch(extra->prevstate.state) {
2707
/* shouldn't be possible to go directly from virgin -> error */
2708
VG_(sprintf)(buf, "virgin!?");
2712
ThreadLifeSeg *tls = unpackTLS(extra->prevstate.other);
2714
tl_assert(tls != unpackTLS(TLSP_INDICATING_ALL));
2715
VG_(sprintf)(buf, "exclusively owned by thread %u", tls->tid);
2721
ls = unpackLockSet(extra->prevstate.other);
2724
VG_(sprintf)(buf, "shared %s, no locks",
2725
extra->prevstate.state == Vge_Shar ? "RO" : "RW");
2729
msg = lockset_str(extra->prevstate.state == Vge_Shar ?
2730
"shared RO, locked by:" :
2731
"shared RW, locked by:", ls);
2737
VG_(message)(Vg_UserMsg, " Previous state: %s", msg);
2739
if (clo_execontext == EC_Some
2740
&& extra->lasttouched.uu_ec_ip.ip != 0) {
2743
Addr ip = extra->lasttouched.uu_ec_ip.ip;
2745
VG_(message)(Vg_UserMsg, " Word at %p last changed state from %s by thread %u",
2747
pp_state(extra->lasttouched.state),
2748
unpackTLS(extra->lasttouched.tls)->tid);
2750
if (VG_(get_filename_linenum)(ip, file, sizeof(file),
2751
NULL, 0, NULL, &line)) {
2752
VG_(message)(Vg_UserMsg, " at %p: %y (%s:%u)",
2753
ip, ip, file, line);
2754
} else if (VG_(get_objname)(ip, file, sizeof(file))) {
2755
VG_(message)(Vg_UserMsg, " at %p: %y (in %s)",
2758
VG_(message)(Vg_UserMsg, " at %p: %y", ip, ip);
2760
} else if (clo_execontext == EC_All
2761
&& extra->lasttouched.uu_ec_ip.ec != NULL) {
2762
VG_(message)(Vg_UserMsg, " Word at %p last changed state from %s in tid %u",
2764
pp_state(extra->lasttouched.state),
2765
unpackTLS(extra->lasttouched.tls)->tid);
2766
VG_(pp_ExeContext)(extra->lasttouched.uu_ec_ip.ec);
2772
VG_(message)(Vg_UserMsg, "Mutex problem at %p%(y trying to %s",
2773
VG_(get_error_address)(err),
2774
VG_(get_error_address)(err),
2775
VG_(get_error_string)(err));
2776
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
2777
if (extra->lasttouched.uu_ec_ip.ec != NULL) {
2778
VG_(message)(Vg_UserMsg, " last touched by thread %d", extra->lasttid);
2779
VG_(pp_ExeContext)(extra->lasttouched.uu_ec_ip.ec);
2781
pp_AddrInfo(VG_(get_error_address)(err), &extra->addrinfo);
2784
case LockGraphErr: {
2785
const LockSet *heldset = extra->held_lockset;
2786
Addr err_addr = VG_(get_error_address)(err);
2789
msg = lockset_str(NULL, heldset);
2791
VG_(message)(Vg_UserMsg, "Mutex %p%(y locked in inconsistent order",
2792
err_addr, err_addr);
2793
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
2794
VG_(message)(Vg_UserMsg, " while holding locks %s", msg);
2796
for(i = 0; i < heldset->setsize; i++) {
2797
const Mutex *lsmx = heldset->mutex[i];
2799
/* needs to be a recursive search+display */
2800
if (0 && !ismember(lsmx->lockdep, extra->mutex))
2803
VG_(message)(Vg_UserMsg, " %p%(y last locked at",
2804
lsmx->mutexp, lsmx->mutexp);
2805
VG_(pp_ExeContext)(lsmx->location);
2807
msg = lockset_str(NULL, lsmx->lockdep);
2808
VG_(message)(Vg_UserMsg, " while depending on locks %s", msg);
8199
const Bool show_raw_states = False;
8200
XError *xe = (XError*)VG_(get_error_extra)(err);
8202
switch (VG_(get_error_kind)(err)) {
8206
tl_assert( is_sane_Thread( xe->XE.Misc.thr ) );
8207
announce_one_thread( xe->XE.Misc.thr );
8208
VG_(message)(Vg_UserMsg,
8210
(Int)xe->XE.Misc.thr->errmsg_index,
8211
xe->XE.Misc.errstr);
8212
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8216
case XE_LockOrder: {
8218
tl_assert( is_sane_Thread( xe->XE.LockOrder.thr ) );
8219
announce_one_thread( xe->XE.LockOrder.thr );
8220
VG_(message)(Vg_UserMsg,
8221
"Thread #%d: lock order \"%p before %p\" violated",
8222
(Int)xe->XE.LockOrder.thr->errmsg_index,
8223
(void*)xe->XE.LockOrder.before_ga,
8224
(void*)xe->XE.LockOrder.after_ga);
8225
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8226
if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
8227
VG_(message)(Vg_UserMsg,
8228
" Required order was established by acquisition of lock at %p",
8229
(void*)xe->XE.LockOrder.before_ga);
8230
VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
8231
VG_(message)(Vg_UserMsg,
8232
" followed by a later acquisition of lock at %p",
8233
(void*)xe->XE.LockOrder.after_ga);
8234
VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
8239
case XE_PthAPIerror: {
8241
tl_assert( is_sane_Thread( xe->XE.PthAPIerror.thr ) );
8242
announce_one_thread( xe->XE.PthAPIerror.thr );
8243
VG_(message)(Vg_UserMsg,
8244
"Thread #%d's call to %s failed",
8245
(Int)xe->XE.PthAPIerror.thr->errmsg_index,
8246
xe->XE.PthAPIerror.fnname);
8247
VG_(message)(Vg_UserMsg,
8248
" with error code %ld (%s)",
8249
xe->XE.PthAPIerror.err,
8250
xe->XE.PthAPIerror.errstr);
8251
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8255
case XE_UnlockBogus: {
8257
tl_assert( is_sane_Thread( xe->XE.UnlockBogus.thr ) );
8258
announce_one_thread( xe->XE.UnlockBogus.thr );
8259
VG_(message)(Vg_UserMsg,
8260
"Thread #%d unlocked an invalid lock at %p ",
8261
(Int)xe->XE.UnlockBogus.thr->errmsg_index,
8262
(void*)xe->XE.UnlockBogus.lock_ga);
8263
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8267
case XE_UnlockForeign: {
8269
tl_assert( is_sane_LockP( xe->XE.UnlockForeign.lock ) );
8270
tl_assert( is_sane_Thread( xe->XE.UnlockForeign.owner ) );
8271
tl_assert( is_sane_Thread( xe->XE.UnlockForeign.thr ) );
8272
announce_one_thread( xe->XE.UnlockForeign.thr );
8273
announce_one_thread( xe->XE.UnlockForeign.owner );
8274
VG_(message)(Vg_UserMsg,
8275
"Thread #%d unlocked lock at %p "
8276
"currently held by thread #%d",
8277
(Int)xe->XE.UnlockForeign.thr->errmsg_index,
8278
(void*)xe->XE.UnlockForeign.lock->guestaddr,
8279
(Int)xe->XE.UnlockForeign.owner->errmsg_index );
8280
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8281
if (xe->XE.UnlockForeign.lock->appeared_at) {
8282
VG_(message)(Vg_UserMsg,
8283
" Lock at %p was first observed",
8284
(void*)xe->XE.UnlockForeign.lock->guestaddr);
8285
VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
8290
case XE_UnlockUnlocked: {
8292
tl_assert( is_sane_LockP( xe->XE.UnlockUnlocked.lock ) );
8293
tl_assert( is_sane_Thread( xe->XE.UnlockUnlocked.thr ) );
8294
announce_one_thread( xe->XE.UnlockUnlocked.thr );
8295
VG_(message)(Vg_UserMsg,
8296
"Thread #%d unlocked a not-locked lock at %p ",
8297
(Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
8298
(void*)xe->XE.UnlockUnlocked.lock->guestaddr);
8299
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8300
if (xe->XE.UnlockUnlocked.lock->appeared_at) {
8301
VG_(message)(Vg_UserMsg,
8302
" Lock at %p was first observed",
8303
(void*)xe->XE.UnlockUnlocked.lock->guestaddr);
8304
VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
8309
case XE_FreeMemLock: {
8311
tl_assert( is_sane_LockP( xe->XE.FreeMemLock.lock ) );
8312
tl_assert( is_sane_Thread( xe->XE.FreeMemLock.thr ) );
8313
announce_one_thread( xe->XE.FreeMemLock.thr );
8314
VG_(message)(Vg_UserMsg,
8315
"Thread #%d deallocated location %p "
8316
"containing a locked lock",
8317
(Int)xe->XE.FreeMemLock.thr->errmsg_index,
8318
(void*)xe->XE.FreeMemLock.lock->guestaddr);
8319
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8320
if (xe->XE.FreeMemLock.lock->appeared_at) {
8321
VG_(message)(Vg_UserMsg,
8322
" Lock at %p was first observed",
8323
(void*)xe->XE.FreeMemLock.lock->guestaddr);
8324
VG_(pp_ExeContext)( xe->XE.FreeMemLock.lock->appeared_at );
8331
Char old_buf[100], new_buf[100];
8332
Char old_tset_buf[140], new_tset_buf[140];
8333
SVal old_state, new_state;
8337
WordSetID tset_to_announce = HG_(emptyWS)( univ_tsets );
8339
/* First extract some essential info */
8341
old_state = xe->XE.Race.old_state;
8342
new_state = xe->XE.Race.new_state;
8343
thr_acc = xe->XE.Race.thr;
8344
what = xe->XE.Race.isWrite ? "write" : "read";
8345
szB = xe->XE.Race.szB;
8346
tl_assert(is_sane_Thread(thr_acc));
8347
err_ga = VG_(get_error_address)(err);
8349
/* Format the low level state print descriptions */
8350
show_shadow_w32(old_buf, sizeof(old_buf), old_state);
8351
show_shadow_w32(new_buf, sizeof(new_buf), new_state);
8353
/* Now we have to 'announce' the threadset mentioned in the
8354
error message, if it hasn't already been announced.
8355
Unfortunately the precise threadset and error message text
8356
depends on the nature of the transition involved. So now
8357
fall into a case analysis of the error state transitions. */
8359
/* CASE of Excl -> ShM */
8360
if (is_SHVAL_Excl(old_state) && is_SHVAL_ShM(new_state)) {
8361
SegmentID old_segid;
8365
old_segid = un_SHVAL_Excl( old_state );
8366
tl_assert(is_sane_SegmentID(old_segid));
8367
old_seg = map_segments_lookup( old_segid );
8368
tl_assert(is_sane_Segment(old_seg));
8369
tl_assert(old_seg->thr);
8370
old_thr = old_seg->thr;
8371
tl_assert(is_sane_Thread(old_thr));
8373
new_tset = un_SHVAL_ShM_tset(new_state);
8374
tset_to_announce = HG_(addToWS)( univ_tsets,
8375
new_tset, (Word)old_thr );
8376
announce_threadset( tset_to_announce );
8378
VG_(message)(Vg_UserMsg,
8379
"Possible data race during %s of size %d at %p",
8381
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8382
/* pp_AddrInfo(err_addr, &extra->addrinfo); */
8383
if (show_raw_states)
8384
VG_(message)(Vg_UserMsg,
8385
" Old state 0x%08x=%s, new state 0x%08x=%s",
8386
old_state, old_buf, new_state, new_buf);
8387
VG_(message)(Vg_UserMsg,
8388
" Old state: owned exclusively by thread #%d",
8389
old_thr->errmsg_index);
8390
// This should always show exactly 2 threads
8391
summarise_threadset( new_tset, new_tset_buf, sizeof(new_tset_buf) );
8392
VG_(message)(Vg_UserMsg,
8393
" New state: shared-modified by threads %s",
8395
VG_(message)(Vg_UserMsg,
8396
" Reason: this thread, #%d, holds no locks at all",
8397
thr_acc->errmsg_index);
8400
/* Case of ShR/M -> ShM */
8401
if (is_SHVAL_Sh(old_state) && is_SHVAL_ShM(new_state)) {
8402
WordSetID old_tset = un_SHVAL_Sh_tset(old_state);
8403
WordSetID new_tset = un_SHVAL_Sh_tset(new_state);
8405
tset_to_announce = HG_(unionWS)( univ_tsets, old_tset, new_tset );
8406
announce_threadset( tset_to_announce );
8408
VG_(message)(Vg_UserMsg,
8409
"Possible data race during %s of size %d at %p",
8411
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8412
/* pp_AddrInfo(err_addr, &extra->addrinfo); */
8413
if (show_raw_states)
8414
VG_(message)(Vg_UserMsg,
8415
" Old state 0x%08x=%s, new state 0x%08x=%s",
8416
old_state, old_buf, new_state, new_buf);
8418
summarise_threadset( old_tset, old_tset_buf, sizeof(old_tset_buf) );
8419
summarise_threadset( new_tset, new_tset_buf, sizeof(new_tset_buf) );
8421
VG_(message)(Vg_UserMsg,
8422
" Old state: shared-%s by threads %s",
8423
is_SHVAL_ShM(old_state) ? "modified" : "readonly",
8425
VG_(message)(Vg_UserMsg,
8426
" New state: shared-modified by threads %s",
8428
VG_(message)(Vg_UserMsg,
8429
" Reason: this thread, #%d, holds no "
8431
thr_acc->errmsg_index);
8432
if (xe->XE.Race.mb_lastlock) {
8433
VG_(message)(Vg_UserMsg, " Last consistently used lock for %p was "
8434
"first observed", err_ga);
8435
VG_(pp_ExeContext)(xe->XE.Race.mb_lastlock);
8437
VG_(message)(Vg_UserMsg, " Location %p has never been protected "
8438
"by any lock", err_ga);
8441
/* Hmm, unknown transition. Just print what we do know. */
8443
VG_(message)(Vg_UserMsg,
8444
"Possible data race during %s of size %d at %p",
8446
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
8448
//pp_AddrInfo(err_addr, &extra->addrinfo);
8449
VG_(message)(Vg_UserMsg,
8450
" Old state 0x%08x=%s, new state 0x%08x=%s",
8451
old_state, old_buf, new_state, new_buf);
8454
break; /* case XE_Race */
8455
} /* case XE_Race */
8459
} /* switch (VG_(get_error_kind)(err)) */
8462
static Char* hg_get_error_name ( Error* err )
8464
switch (VG_(get_error_kind)(err)) {
8465
case XE_Race: return "Race";
8466
case XE_FreeMemLock: return "FreeMemLock";
8467
case XE_UnlockUnlocked: return "UnlockUnlocked";
8468
case XE_UnlockForeign: return "UnlockForeign";
8469
case XE_UnlockBogus: return "UnlockBogus";
8470
case XE_PthAPIerror: return "PthAPIerror";
8471
case XE_LockOrder: return "LockOrder";
8472
case XE_Misc: return "Misc";
8473
default: tl_assert(0); /* fill in missing case */
2820
8477
static Bool hg_recognised_suppression ( Char* name, Supp *su )
2822
if (0 == VG_(strcmp)(name, "Eraser")) {
2823
VG_(set_supp_kind)(su, RaceSupp);
8479
# define TRY(_name,_xskind) \
8480
if (0 == VG_(strcmp)(name, (_name))) { \
8481
VG_(set_supp_kind)(su, (_xskind)); \
8484
TRY("Race", XS_Race);
8485
TRY("FreeMemLock", XS_FreeMemLock);
8486
TRY("UnlockUnlocked", XS_UnlockUnlocked);
8487
TRY("UnlockForeign", XS_UnlockForeign);
8488
TRY("UnlockBogus", XS_UnlockBogus);
8489
TRY("PthAPIerror", XS_PthAPIerror);
8490
TRY("LockOrder", XS_LockOrder);
8491
TRY("Misc", XS_Misc);
2831
static Bool hg_read_extra_suppression_info ( Int fd, Char* buf, Int nBuf, Supp* su )
8496
static Bool hg_read_extra_suppression_info ( Int fd, Char* buf, Int nBuf,
2833
8499
/* do nothing -- no extra suppression info present. Return True to
2834
8500
indicate nothing bad happened. */
2839
static Bool hg_error_matches_suppression(Error* err, Supp* su)
2841
tl_assert(VG_(get_supp_kind)(su) == RaceSupp);
2843
return (VG_(get_error_kind)(err) == RaceErr);
2846
static Char* hg_get_error_name ( Error* err )
2848
if (RaceErr == VG_(get_error_kind)(err)) {
2849
return "Eraser"; // old name, required for backwards compatibility
2851
return NULL; /* Other errors types can't be suppressed */
8504
static Bool hg_error_matches_suppression ( Error* err, Supp* su )
8506
switch (VG_(get_supp_kind)(su)) {
8507
case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
8508
case XS_FreeMemLock: return VG_(get_error_kind)(err) == XE_FreeMemLock;
8509
case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
8510
case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
8511
case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
8512
case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
8513
case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
8514
case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
8515
//case XS_: return VG_(get_error_kind)(err) == XE_;
8516
default: tl_assert(0); /* fill in missing cases */