~bkerensa/ubuntu/raring/valgrind/merge-from-deb

« back to all changes in this revision

Viewing changes to helgrind/hg_main.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrés Roldán
  • Date: 2008-06-13 02:31:40 UTC
  • mto: (1.4.1 upstream) (2.2.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: james.westby@ubuntu.com-20080613023140-iwk33rz9rhvfkr96
Import upstream version 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*--------------------------------------------------------------------*/
3
 
/*--- Helgrind: checking for data races in threaded programs.      ---*/
4
 
/*---                                                    hg_main.c ---*/
 
3
/*--- Helgrind: a Valgrind tool for detecting errors               ---*/
 
4
/*--- in threaded programs.                              hg_main.c ---*/
5
5
/*--------------------------------------------------------------------*/
6
6
 
7
7
/*
8
 
   This file is part of Helgrind, a Valgrind tool for detecting
9
 
   data races in threaded programs.
 
8
   This file is part of Helgrind, a Valgrind tool for detecting errors
 
9
   in threaded programs.
10
10
 
11
 
   Copyright (C) 2002-2006 Nicholas Nethercote
12
 
      njn@valgrind.org
 
11
   Copyright (C) 2007-2007 OpenWorks LLP
 
12
      info@open-works.co.uk
13
13
 
14
14
   This program is free software; you can redistribute it and/or
15
15
   modify it under the terms of the GNU General Public License as
27
27
   02111-1307, USA.
28
28
 
29
29
   The GNU General Public License is contained in the file COPYING.
 
30
 
 
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.
30
35
*/
31
36
 
32
 
// *** WARNING *** 
33
 
// Helgrind is not 64-bit clean.
34
 
 
35
 
// For anyone wanting to understand race conditions better, this paper might
36
 
// be instructive:
37
 
//
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
41
 
//
42
 
// It nicely describes several example race conditions, emphasising the
43
 
// fundamentals in each case.
44
 
 
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"
59
51
 
60
52
#include "helgrind.h"
61
53
 
62
 
static UInt n_hg_warnings = 0;
63
 
static UInt n_lockorder_warnings = 0;
64
 
 
65
 
/*------------------------------------------------------------*/
66
 
/*--- Debug guff                                           ---*/
67
 
/*------------------------------------------------------------*/
68
 
 
69
 
#define DEBUG_LOCK_TABLE    0   /* Print lock table at end */
70
 
 
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
78
 
                                   DEBUG_ACCESSES */
79
 
#define SLOW_ASSERTS        0   /* do expensive asserts */
80
 
#define DEBUG_VIRGIN_READS  0   /* Dump around address on VIRGIN reads */
81
 
 
82
 
#if SLOW_ASSERTS
83
 
#define TL_ASSERT(x)    tl_assert(x)
84
 
#else
85
 
#define TL_ASSERT(x)
86
 
#endif
87
 
 
88
 
/* heavyweight LockSet sanity checking:
89
 
   0 == never
90
 
   1 == after important ops
91
 
   2 == As 1 and also after pthread_mutex_* ops (excessively slow)
92
 
 */
93
 
#define LOCKSET_SANITY 0
94
 
 
95
 
/* Rotate an unsigned quantity left */
96
 
#define ROTL(x, n)      (((x) << (n)) | ((x) >> ((sizeof(x)*8)-(n))))
97
 
 
98
 
/*------------------------------------------------------------*/
99
 
/*--- Command line options                                 ---*/
100
 
/*------------------------------------------------------------*/
101
 
 
102
 
static enum {
103
 
   EC_None,
104
 
   EC_Some,
105
 
   EC_All
106
 
} clo_execontext = EC_None;
107
 
 
108
 
static Bool clo_priv_stacks = False;
109
 
 
110
 
/*------------------------------------------------------------*/
111
 
/*--- Crude profiling machinery.                           ---*/
112
 
/*------------------------------------------------------------*/
113
 
 
114
 
// PPP: work out if I want this
115
 
 
116
 
#define PROF_EVENT(x)
117
 
#if 0
118
 
#ifdef VG_PROFILE_MEMORY
119
 
 
120
 
#define N_PROF_EVENTS 150
121
 
 
122
 
static UInt event_ctr[N_PROF_EVENTS];
123
 
 
124
 
void VGE_(done_prof_mem) ( void )
 
54
#define HG_(str) VGAPPEND(vgHelgrind_,str)
 
55
#include "hg_wordfm.h"
 
56
#include "hg_wordset.h"
 
57
 
 
58
/*----------------------------------------------------------------*/
 
59
/*---                                                          ---*/
 
60
/*----------------------------------------------------------------*/
 
61
 
 
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.
 
67
*/
 
68
 
 
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.
 
73
 
 
74
// FIXME what is supposed to happen to locks in memory which
 
75
// is relocated as a result of client realloc?
 
76
 
 
77
// FIXME put referencing ThreadId into Thread and get
 
78
// rid of the slow reverse mapping function.
 
79
 
 
80
// FIXME accesses to NoAccess areas: change state to Excl?
 
81
 
 
82
// FIXME report errors for accesses of NoAccess memory?
 
83
 
 
84
// FIXME pth_cond_wait/timedwait wrappers.  Even if these fail,
 
85
// the thread still holds the lock.
 
86
 
 
87
/* ------------ Debug/trace options ------------ */
 
88
 
 
89
// this is:
 
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
 
94
 
 
95
// 0 for silent, 1 for some stuff, 2 for lots of stuff
 
96
#define SHOW_EVENTS 0
 
97
 
 
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
 
105
 
 
106
#define SCE_BIGRANGE_T 256  // big mem range minimum size
 
107
 
 
108
 
 
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. */
 
113
#if 0
 
114
#  define SCE_CACHELINE 1  /* do sanity-check CacheLine stuff */
 
115
#  define inline __attribute__((noinline))
 
116
   /* probably want to ditch -fomit-frame-pointer too */
 
117
#else
 
118
#  define SCE_CACHELINE 0   /* don't sanity-check CacheLine stuff */
 
119
#endif
 
120
 
 
121
static void all__sanity_check ( Char* who ); /* fwds */
 
122
 
 
123
#define HG_CLI__MALLOC_REDZONE_SZB 16 /* let's say */
 
124
 
 
125
// 0 for none, 1 for dump at end of run
 
126
#define SHOW_DATA_STRUCTURES 0
 
127
 
 
128
 
 
129
/* ------------ Command line options ------------ */
 
130
 
 
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 */
 
136
 
 
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;
 
140
 
 
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;
 
145
 
 
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;
 
151
 
 
152
/* Sanity check level.  This is an or-ing of
 
153
   SCE_{THREADS,LOCKS,BIGRANGE,ACCESS,LAOG}. */
 
154
static Int clo_sanity_flags = 0;
 
155
 
 
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
 
160
 
 
161
 
 
162
/* ------------ Misc comments ------------ */
 
163
 
 
164
// FIXME: don't hardwire initial entries for root thread.
 
165
// Instead, let the pre_thread_ll_create handler do this.
 
166
 
 
167
// FIXME: when a SecMap is completely set via and address range
 
168
// setting operation to a non-ShR/M state, clear its .mbHasShared 
 
169
// bit
 
170
 
 
171
/* FIXME: figure out what the real rules are for Excl->ShR/M
 
172
   transitions w.r.t locksets.
 
173
 
 
174
   Muelenfeld thesis Sec 2.2.1 p 8/9 says that
 
175
 
 
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.
 
179
 
 
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?
 
182
 
 
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:
 
186
 
 
187
     *sword = SW(Vge_Shar, packLockSet(thread_locks_rd[tid]));
 
188
 
 
189
   Original Eraser paper also says "all active locks".
 
190
*/
 
191
 
 
192
// Major stuff to fix:
 
193
// - reader-writer locks
 
194
 
 
195
/* Thread async exit:
 
196
   
 
197
   remove the map_threads entry
 
198
   leave the Thread object in place
 
199
   complain if holds any locks
 
200
   
 
201
   unlike with Join, do not change any memory states
 
202
 
 
203
   I _think_ this is correctly handled now.
 
204
*/
 
205
 
 
206
/*----------------------------------------------------------------*/
 
207
/*--- Some very basic stuff                                    ---*/
 
208
/*----------------------------------------------------------------*/
 
209
 
 
210
static void* hg_zalloc ( SizeT n ) {
 
211
   void* p;
 
212
   tl_assert(n > 0);
 
213
   p = VG_(malloc)( n );
 
214
   tl_assert(p);
 
215
   VG_(memset)(p, 0, n);
 
216
   return p;
 
217
}
 
218
static void hg_free ( void* p ) {
 
219
   tl_assert(p);
 
220
   VG_(free)(p);
 
221
}
 
222
 
 
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))
 
227
 
 
228
#ifdef HAVE_BUILTIN_EXPECT
 
229
#define LIKELY(cond)   __builtin_expect(!!(cond),1)
 
230
#define UNLIKELY(cond) __builtin_expect(!!(cond),0)
 
231
#else
 
232
#define LIKELY(cond)   (cond)
 
233
#define UNLIKELY(cond) (cond)
 
234
#endif
 
235
 
 
236
 
 
237
/*----------------------------------------------------------------*/
 
238
/*--- Primary data definitions                                 ---*/
 
239
/*----------------------------------------------------------------*/
 
240
 
 
241
/* Shadow values. */
 
242
typedef  UInt  SVal;
 
243
 
 
244
 
 
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;
 
250
 
 
251
 
 
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;
 
256
 
 
257
 
 
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. */
 
261
typedef
 
262
   struct _Thread {
 
263
      /* ADMIN */
 
264
      struct _Thread* admin;
 
265
      UInt            magic;
 
266
      /* USEFUL */
 
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 */
 
270
      /* EXPOSITION */
 
271
      /* Place where parent was when this thread was created. */
 
272
      ExeContext* created_at;
 
273
      Bool        announced;
 
274
      /* Index for generating references in error messages. */
 
275
      Int         errmsg_index;
 
276
   }
 
277
   Thread;
 
278
 
 
279
 
 
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
 
287
   LockP_Magic. */
 
288
 
 
289
/* Lock kinds. */
 
290
typedef
 
291
   enum {
 
292
      LK_mbRec=1001, /* normal mutex, possibly recursive */
 
293
      LK_nonRec,     /* normal mutex, definitely non recursive */
 
294
      LK_rdwr        /* reader-writer lock */
 
295
   }
 
296
   LockKind;
 
297
 
 
298
typedef
 
299
   struct _Lock {
 
300
      /* ADMIN */
 
301
      struct _Lock* admin;
 
302
      ULong         unique; /* used for persistence-hashing */
 
303
      UInt          magic;  /* LockN_MAGIC or LockP_MAGIC */
 
304
      /* EXPOSITION */
 
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;
 
311
      /* USEFUL-STATIC */
 
312
      Addr          guestaddr; /* Guest address of lock */
 
313
      LockKind      kind;      /* what kind of lock this is */
 
314
      /* USEFUL-DYNAMIC */
 
315
      Bool          heldW; 
 
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
 
319
         .heldBy is non-NULL:
 
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.
 
323
 
 
324
         for LK_nonRec, r-holdings are not allowed, and w-holdings may
 
325
         only have sizeTotal(heldBy) == 1
 
326
 
 
327
         for LK_mbRec, r-holdings are not allowed, and w-holdings may
 
328
         only have sizeUnique(heldBy) == 1
 
329
 
 
330
         for LK_rdwr, w-holdings may only have sizeTotal(heldBy) == 1 */
 
331
   }
 
332
   Lock;
 
333
 
 
334
 
 
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 (!) */
 
339
typedef
 
340
   struct _Segment {
 
341
      /* ADMIN */
 
342
      struct _Segment* admin;
 
343
      UInt             magic;
 
344
      /* USEFUL */
 
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 */
 
353
      Char other_hint;
 
354
   }
 
355
   Segment;
 
356
 
 
357
 
 
358
/* ------ CacheLine ------ */
 
359
 
 
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)
 
363
 
 
364
typedef
 
365
   struct {
 
366
      UShort descrs[N_LINE_TREES];
 
367
      SVal   svals[N_LINE_ARANGE]; // == N_LINE_TREES * 8
 
368
   }
 
369
   CacheLine;
 
370
 
 
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)
 
387
 
 
388
typedef
 
389
   struct {
 
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
 
392
                                      dict indexes */
 
393
      /* if dict[0] == 0 then dict[1] is the index of the CacheLineF
 
394
         to use */
 
395
   }
 
396
   CacheLineZ; /* compressed rep for a cache line */
 
397
 
 
398
typedef
 
399
   struct {
 
400
      Bool inUse;
 
401
      SVal w32s[N_LINE_ARANGE];
 
402
   }
 
403
   CacheLineF; /* full rep for a cache line */
 
404
 
 
405
 
 
406
/* Shadow memory.
 
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.
 
414
*/
 
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
 
421
 
 
422
   Each SecMap must hold a power-of-2 number of CacheLines.  Hence
 
423
   N_SECMAP_BITS must >= N_LINE_BITS.
 
424
*/
 
425
#define N_SECMAP_BITS   13
 
426
#define N_SECMAP_ARANGE (1 << N_SECMAP_BITS)
 
427
 
 
428
// # CacheLines held by a SecMap
 
429
#define N_SECMAP_ZLINES (N_SECMAP_ARANGE / N_LINE_ARANGE)
 
430
typedef
 
431
   struct {
 
432
      UInt magic;
 
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];
 
436
      CacheLineF* linesF;
 
437
      Int         linesF_size;
 
438
   }
 
439
   SecMap;
 
440
 
 
441
typedef
 
442
   struct {
 
443
      Int line_no; /* which Z-line are we in? */
 
444
      Int word_no; /* inside the line, which word is current? */
 
445
   }
 
446
   SecMapIter;
 
447
 
 
448
static void initSecMapIter ( SecMapIter* itr ) {
 
449
   itr->line_no = 0;
 
450
   itr->word_no = 0;
 
451
}
 
452
 
 
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
 
455
   'inline'. */
 
456
static UWord stats__secmap_iterator_steppings; /* fwds */
 
457
 
 
458
inline
 
459
static Bool stepSecMapIter ( /*OUT*/SVal** pVal, 
 
460
                             /*MOD*/SecMapIter* itr, SecMap* sm )
 
461
{
 
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);
 
468
      return False;
 
469
   }
 
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];
 
483
      itr->word_no++;
 
484
      if (itr->word_no == N_LINE_ARANGE)
 
485
         itr->word_no = 0;
 
486
   } else {
 
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];
 
490
      itr->word_no++;
 
491
      if (itr->word_no == 4 || lineZ->dict[itr->word_no] == 0)
 
492
         itr->word_no = 0;
 
493
   }
 
494
 
 
495
   if (itr->word_no == 0) {
 
496
      itr->line_no++;
 
497
      if (itr->line_no == N_SECMAP_ZLINES) {
 
498
         itr->line_no = -1;
 
499
         itr->word_no = -1;
 
500
      }
 
501
   }
 
502
 
 
503
   return True;
 
504
}
 
505
 
 
506
/* ------ Cache ------ */
 
507
 
 
508
#define N_WAY_BITS 16
 
509
#define N_WAY_NENT (1 << N_WAY_BITS)
 
510
 
 
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
 
517
   with a bogus tag. */
 
518
typedef
 
519
   struct {
 
520
      CacheLine lyns0[N_WAY_NENT];
 
521
      Addr      tags0[N_WAY_NENT];
 
522
   }
 
523
   Cache;
 
524
 
 
525
 
 
526
/* --------- Primary data structures --------- */
 
527
 
 
528
/* Admin linked list of Threads */
 
529
static Thread* admin_threads = NULL;
 
530
 
 
531
/* Admin linked list of Locks */
 
532
static Lock* admin_locks = NULL;
 
533
 
 
534
/* Admin linked list of Segments */
 
535
static Segment* admin_segments = NULL;
 
536
 
 
537
/* Shadow memory primary map */
 
538
static WordFM* map_shmem = NULL; /* WordFM Addr SecMap* */
 
539
static Cache   cache_shmem;
 
540
 
 
541
/* Mapping table for core ThreadIds to Thread* */
 
542
static Thread** map_threads = NULL; /* Array[VG_N_THREADS] of Thread* */
 
543
 
 
544
/* Mapping table for thread segments IDs to Segment* */
 
545
static WordFM* map_segments = NULL; /* WordFM SegmentID Segment* */
 
546
 
 
547
/* Mapping table for lock guest addresses to Lock* */
 
548
static WordFM* map_locks = NULL; /* WordFM LockAddr Lock* */
 
549
 
 
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 */
 
554
 
 
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;
 
560
 
 
561
 
 
562
/*----------------------------------------------------------------*/
 
563
/*--- Simple helpers for the data structures                   ---*/
 
564
/*----------------------------------------------------------------*/
 
565
 
 
566
static UWord stats__lockN_acquires = 0;
 
567
static UWord stats__lockN_releases = 0;
 
568
 
 
569
static ThreadId map_threads_maybe_reverse_lookup_SLOW ( Thread* ); /*fwds*/
 
570
 
 
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
 
576
 
 
577
static UWord stats__mk_Segment = 0;
 
578
 
 
579
/* --------- Constructors --------- */
 
580
 
 
581
static inline Bool is_sane_LockN ( Lock* lock ); /* fwds */
 
582
 
 
583
static Thread* mk_Thread ( SegmentID csegid ) {
 
584
   static Int indx      = 1;
 
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;
 
595
   return thread;
 
596
}
 
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;
 
607
   lock->kind             = kind;
 
608
   lock->heldW            = False;
 
609
   lock->heldBy           = NULL;
 
610
   tl_assert(is_sane_LockN(lock));
 
611
   admin_locks            = lock;
 
612
   return lock;
 
613
}
 
614
static Segment* mk_Segment ( Thread* thr, Segment* prev, Segment* other ) {
 
615
   Segment* seg    = hg_zalloc( sizeof(Segment) );
 
616
   seg->dfsver     = 0;
 
617
   seg->thr        = thr;
 
618
   seg->prev       = prev;
 
619
   seg->other      = other;
 
620
   seg->vts        = NULL;
 
621
   seg->other_hint = ' ';
 
622
   seg->magic      = Segment_MAGIC;
 
623
   seg->admin      = admin_segments;
 
624
   admin_segments = seg;
 
625
   stats__mk_Segment++;
 
626
   return seg;
 
627
}
 
628
 
 
629
static inline Bool is_sane_Segment ( Segment* seg ) {
 
630
   return seg != NULL && seg->magic == Segment_MAGIC;
 
631
}
 
632
static inline Bool is_sane_Thread ( Thread* thr ) {
 
633
   return thr != NULL && thr->magic == Thread_MAGIC;
 
634
}
 
635
 
 
636
static Bool is_sane_Bag_of_Threads ( WordBag* bag )
 
637
{
 
638
   Thread* thr;
 
639
   Word    count;
 
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;
 
644
   }
 
645
   HG_(doneIterBag)( bag );
 
646
   return True;
 
647
}
 
648
static Bool is_sane_Lock_BASE ( Lock* lock )
 
649
{
 
650
   if (lock == NULL
 
651
       || (lock->magic != LockN_MAGIC && lock->magic != LockP_MAGIC))
 
652
      return False;
 
653
   switch (lock->kind) { 
 
654
      case LK_mbRec: case LK_nonRec: case LK_rdwr: break; 
 
655
      default: return False; 
 
656
   }
 
657
   if (lock->heldBy == NULL) {
 
658
      if (lock->acquired_at != NULL) return False;
 
659
      /* Unheld.  We arbitrarily require heldW to be False. */
 
660
      return !lock->heldW;
 
661
   } else {
 
662
      if (lock->acquired_at == NULL) return False;
 
663
   }
 
664
 
 
665
   /* If heldBy is non-NULL, we require it to contain at least one
 
666
      thread. */
 
667
   if (HG_(isEmptyBag)(lock->heldBy))
 
668
      return False;
 
669
 
 
670
   /* Lock is either r- or w-held. */
 
671
   if (!is_sane_Bag_of_Threads(lock->heldBy)) 
 
672
      return False;
 
673
   if (lock->heldW) {
 
674
      /* Held in write-mode */
 
675
      if ((lock->kind == LK_nonRec || lock->kind == LK_rdwr)
 
676
          && !HG_(isSingletonTotalBag)(lock->heldBy))
 
677
         return False;
 
678
   } else {
 
679
      /* Held in read-mode */
 
680
      if (lock->kind != LK_rdwr) return False;
 
681
   }
 
682
   return True;
 
683
}
 
684
static inline Bool is_sane_LockP ( Lock* lock ) {
 
685
   return lock != NULL 
 
686
          && lock->magic == LockP_MAGIC
 
687
          && is_sane_Lock_BASE(lock);
 
688
}
 
689
static inline Bool is_sane_LockN ( Lock* lock ) {
 
690
   return lock != NULL 
 
691
          && lock->magic == LockN_MAGIC
 
692
          && is_sane_Lock_BASE(lock);
 
693
}
 
694
static inline Bool is_sane_LockNorP ( Lock* lock ) {
 
695
   return is_sane_Lock_BASE(lock);
 
696
}
 
697
 
 
698
/* Release storage for a Lock.  Also release storage in .heldBy, if
 
699
   any. */
 
700
static void del_LockN ( Lock* lk ) 
 
701
{
 
702
   tl_assert(is_sane_LockN(lk));
 
703
   if (lk->heldBy)
 
704
      HG_(deleteBag)( lk->heldBy );
 
705
   VG_(memset)(lk, 0xAA, sizeof(*lk));
 
706
   hg_free(lk);
 
707
}
 
708
 
 
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 ) 
 
713
{
 
714
   tl_assert(is_sane_LockN(lk));
 
715
   tl_assert(is_sane_Thread(thr));
 
716
 
 
717
   stats__lockN_acquires++;
 
718
 
 
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) {
 
723
      ThreadId tid;
 
724
      tl_assert(lk->heldBy == NULL);
 
725
      tid = map_threads_maybe_reverse_lookup_SLOW(thr);
 
726
      lk->acquired_at
 
727
         = VG_(record_ExeContext(tid, 0/*first_ip_delta*/));
 
728
   } else {
 
729
      tl_assert(lk->heldBy != NULL);
 
730
   }
 
731
   /* end EXPOSITION only */
 
732
 
 
733
   switch (lk->kind) {
 
734
      case LK_nonRec:
 
735
      case_LK_nonRec:
 
736
         tl_assert(lk->heldBy == NULL); /* can't w-lock recursively */
 
737
         tl_assert(!lk->heldW);
 
738
         lk->heldW  = True;
 
739
         lk->heldBy = HG_(newBag)( hg_zalloc, hg_free );
 
740
         HG_(addToBag)( lk->heldBy, (Word)thr );
 
741
         break;
 
742
      case LK_mbRec:
 
743
         if (lk->heldBy == NULL)
 
744
            goto case_LK_nonRec;
 
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);
 
753
         break;
 
754
      case LK_rdwr:
 
755
         tl_assert(lk->heldBy == NULL && !lk->heldW); /* must be unheld */
 
756
         goto case_LK_nonRec;
 
757
      default: 
 
758
         tl_assert(0);
 
759
  }
 
760
  tl_assert(is_sane_LockN(lk));
 
761
}
 
762
 
 
763
static void lockN_acquire_reader ( Lock* lk, Thread* thr )
 
764
{
 
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));
 
772
 
 
773
   stats__lockN_acquires++;
 
774
 
 
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) {
 
779
      ThreadId tid;
 
780
      tl_assert(lk->heldBy == NULL);
 
781
      tid = map_threads_maybe_reverse_lookup_SLOW(thr);
 
782
      lk->acquired_at
 
783
         = VG_(record_ExeContext(tid, 0/*first_ip_delta*/));
 
784
   } else {
 
785
      tl_assert(lk->heldBy != NULL);
 
786
   }
 
787
   /* end EXPOSITION only */
 
788
 
 
789
   if (lk->heldBy) {
 
790
      HG_(addToBag)(lk->heldBy, (Word)thr);
 
791
   } else {
 
792
      lk->heldW  = False;
 
793
      lk->heldBy = HG_(newBag)( hg_zalloc, hg_free );
 
794
      HG_(addToBag)( lk->heldBy, (Word)thr );
 
795
   }
 
796
   tl_assert(!lk->heldW);
 
797
   tl_assert(is_sane_LockN(lk));
 
798
}
 
799
 
 
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. */
 
803
 
 
804
static void lockN_release ( Lock* lk, Thread* thr )
 
805
{
 
806
   Bool b;
 
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 */
 
815
   tl_assert(b);
 
816
   /* normalise */
 
817
   tl_assert(lk->acquired_at);
 
818
   if (HG_(isEmptyBag)(lk->heldBy)) {
 
819
      HG_(deleteBag)(lk->heldBy);
 
820
      lk->heldBy      = NULL;
 
821
      lk->heldW       = False;
 
822
      lk->acquired_at = NULL;
 
823
   }
 
824
   tl_assert(is_sane_LockN(lk));
 
825
}
 
826
 
 
827
static void remove_Lock_from_locksets_of_all_owning_Threads( Lock* lk )
 
828
{
 
829
   Thread* thr;
 
830
   if (!lk->heldBy) {
 
831
      tl_assert(!lk->heldW);
 
832
      return;
 
833
   }
 
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 ));
 
840
      thr->locksetA
 
841
         = HG_(delFromWS)( univ_lsets, thr->locksetA, (Word)lk );
 
842
 
 
843
      if (lk->heldW) {
 
844
         tl_assert(HG_(elemWS)( univ_lsets,
 
845
                                thr->locksetW, (Word)lk ));
 
846
         thr->locksetW
 
847
            = HG_(delFromWS)( univ_lsets, thr->locksetW, (Word)lk );
 
848
      }
 
849
   }
 
850
   HG_(doneIterBag)( lk->heldBy );
 
851
}
 
852
 
 
853
/* --------- xxxID functions --------- */
 
854
 
 
855
/* Proposal (for debugging sanity):
 
856
 
 
857
   SegmentIDs from 0x1000000 .. 0x1FFFFFF (16777216)
 
858
 
 
859
   All other xxxID handles are invalid.
 
860
*/
 
861
static inline Bool is_sane_SegmentID ( SegmentID tseg ) {
 
862
   return tseg >= 0x1000000 && tseg <= 0x1FFFFFF;
 
863
}
 
864
static inline Bool is_sane_ThreadId ( ThreadId coretid ) {
 
865
   return coretid >= 0 && coretid < VG_N_THREADS;
 
866
}
 
867
static SegmentID alloc_SegmentID ( void ) {
 
868
   static SegmentID next = 0x1000000;
 
869
   tl_assert(is_sane_SegmentID(next));
 
870
   return next++;
 
871
}
 
872
 
 
873
/* --------- Shadow memory --------- */
 
874
 
 
875
static inline Bool is_valid_scache_tag ( Addr tag ) {
 
876
   /* a valid tag should be naturally aligned to the start of
 
877
      a CacheLine. */
 
878
   return 0 == (tag & (N_LINE_ARANGE - 1));
 
879
}
 
880
 
 
881
static inline Bool is_sane_SecMap ( SecMap* sm ) {
 
882
   return sm != NULL && sm->magic == SecMap_MAGIC;
 
883
}
 
884
 
 
885
/* Shadow value encodings:
 
886
 
 
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
 
893
 
 
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.
 
897
*/
 
898
 
 
899
#define N_LSID_BITS  17
 
900
#define N_LSID_MASK  ((1 << (N_LSID_BITS)) - 1)
 
901
#define N_LSID_SHIFT 0
 
902
 
 
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)
 
906
 
 
907
static inline Bool is_sane_WordSetID_LSet ( WordSetID wset ) {
 
908
   return wset >= 0 && wset <= N_LSID_MASK;
 
909
}
 
910
static inline Bool is_sane_WordSetID_TSet ( WordSetID wset ) {
 
911
   return wset >= 0 && wset <= N_TSID_MASK;
 
912
}
 
913
 
 
914
 
 
915
__attribute__((noinline))
 
916
__attribute__((noreturn))
 
917
static void mk_SHVAL_fail ( WordSetID tset, WordSetID lset, HChar* who ) {
 
918
   VG_(printf)("\n");
 
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");
 
926
   tl_assert(0);
 
927
}
 
928
 
 
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));
 
934
   } else {
 
935
      mk_SHVAL_fail(tset, lset, "mk_SHVAL_ShM");
 
936
   }
 
937
}
 
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) );
 
943
   } else {
 
944
      mk_SHVAL_fail(tset, lset, "mk_SHVAL_ShR");
 
945
   }
 
946
}
 
947
static inline SVal mk_SHVAL_Excl ( SegmentID tseg ) {
 
948
   tl_assert(is_sane_SegmentID(tseg));
 
949
   return (SVal)( (1<<30) | tseg );
 
950
}
 
951
#define SHVAL_New      ((SVal)(2<<8))
 
952
#define SHVAL_NoAccess ((SVal)(1<<8))
 
953
#define SHVAL_Invalid  ((SVal)(0<<8))
 
954
 
 
955
static inline Bool is_SHVAL_ShM ( SVal w32 ) { 
 
956
   return (w32 >> 30) == 3;
 
957
}
 
958
static inline Bool is_SHVAL_ShR ( SVal w32 ) {
 
959
   return (w32 >> 30) == 2;
 
960
}
 
961
static inline Bool is_SHVAL_Sh ( SVal w32 ) {
 
962
   return (w32 >> 31) == 1;
 
963
}
 
964
static inline Bool is_SHVAL_Excl ( SVal w32 ) {
 
965
   return (w32 >> 30) == 1; 
 
966
}
 
967
static inline Bool is_SHVAL_New ( SVal w32 ) {
 
968
   return w32 == SHVAL_New;
 
969
}
 
970
static inline Bool is_SHVAL_NoAccess ( SVal w32 ) { 
 
971
   return w32 == SHVAL_NoAccess;
 
972
}
 
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);
 
976
}
 
977
 
 
978
static inline SegmentID un_SHVAL_Excl ( SVal w32 ) {
 
979
   tl_assert(is_SHVAL_Excl(w32));
 
980
   return w32 & ~(3<<30);
 
981
}
 
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;
 
985
}
 
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;
 
989
}
 
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;
 
993
}
 
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;
 
997
}
 
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;
 
1001
}
 
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;
 
1005
}
 
1006
 
 
1007
 
 
1008
/*----------------------------------------------------------------*/
 
1009
/*--- Print out the primary data structures                    ---*/
 
1010
/*----------------------------------------------------------------*/
 
1011
 
 
1012
static WordSetID del_BHL ( WordSetID lockset ); /* fwds */
 
1013
static 
 
1014
void get_ZF_by_index ( /*OUT*/CacheLineZ** zp, /*OUT*/CacheLineF** fp,
 
1015
                       SecMap* sm, Int zix ); /* fwds */
 
1016
static 
 
1017
Segment* map_segments_maybe_lookup ( SegmentID segid ); /* fwds */
 
1018
 
 
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)
 
1024
 
 
1025
 
 
1026
static const Int sHOW_ADMIN = 0;
 
1027
 
 
1028
static void space ( Int n )
 
1029
{
 
1030
   Int  i;
 
1031
   Char spaces[128+1];
 
1032
   tl_assert(n >= 0 && n < 128);
 
1033
   if (n == 0)
 
1034
      return;
 
1035
   for (i = 0; i < n; i++)
 
1036
      spaces[i] = ' ';
 
1037
   spaces[i] = 0;
 
1038
   tl_assert(i < 128+1);
 
1039
   VG_(printf)("%s", spaces);
 
1040
}
 
1041
 
 
1042
static void pp_Thread ( Int d, Thread* t )
 
1043
{
 
1044
   space(d+0); VG_(printf)("Thread %p {\n", t);
 
1045
   if (sHOW_ADMIN) {
 
1046
   space(d+3); VG_(printf)("admin    %p\n",   t->admin);
 
1047
   space(d+3); VG_(printf)("magic    0x%x\n", (UInt)t->magic);
 
1048
   }
 
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");
 
1053
}
 
1054
 
 
1055
static void pp_admin_threads ( Int d )
 
1056
{
 
1057
   Int     i, n;
 
1058
   Thread* t;
 
1059
   for (n = 0, t = admin_threads;  t;  n++, t = t->admin) {
 
1060
      /* nothing */
 
1061
   }
 
1062
   space(d); VG_(printf)("admin_threads (%d records) {\n", n);
 
1063
   for (i = 0, t = admin_threads;  t;  i++, t = t->admin) {
 
1064
      if (0) {
 
1065
         space(n); 
 
1066
         VG_(printf)("admin_threads record %d of %d:\n", i, n);
 
1067
      }
 
1068
      pp_Thread(d+3, t);
 
1069
   }
 
1070
   space(d); VG_(printf)("}\n", n);
 
1071
}
 
1072
 
 
1073
static void pp_map_threads ( Int d )
 
1074
{
 
1075
   Int i, n;
 
1076
   n = 0;
 
1077
   space(d); VG_(printf)("map_threads ");
 
1078
   n = 0;
 
1079
   for (i = 0; i < VG_N_THREADS; i++) {
 
1080
      if (map_threads[i] != NULL)
 
1081
         n++;
 
1082
   }
 
1083
   VG_(printf)("(%d entries) {\n", n);
 
1084
   for (i = 0; i < VG_N_THREADS; i++) {
 
1085
      if (map_threads[i] == NULL)
 
1086
         continue;
 
1087
      space(d+3);
 
1088
      VG_(printf)("coretid %d -> Thread %p\n", i, map_threads[i]);
 
1089
   }
 
1090
   space(d); VG_(printf)("}\n");
 
1091
}
 
1092
 
 
1093
static const HChar* show_LockKind ( LockKind lkk ) {
 
1094
   switch (lkk) {
 
1095
      case LK_mbRec:  return "mbRec";
 
1096
      case LK_nonRec: return "nonRec";
 
1097
      case LK_rdwr:   return "rdwr";
 
1098
      default:        tl_assert(0);
 
1099
   }
 
1100
}
 
1101
 
 
1102
static void pp_Lock ( Int d, Lock* lk )
 
1103
{
 
1104
   space(d+0); VG_(printf)("Lock %p (ga %p) {\n", lk, lk->guestaddr);
 
1105
   if (sHOW_ADMIN) {
 
1106
      space(d+3); VG_(printf)("admin  %p\n",   lk->admin);
 
1107
      space(d+3); VG_(printf)("magic  0x%x\n", (UInt)lk->magic);
 
1108
   }
 
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);
 
1113
   if (lk->heldBy) {
 
1114
      Thread* thr;
 
1115
      Word    count;
 
1116
      VG_(printf)(" { ");
 
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 );
 
1121
      VG_(printf)("}");
 
1122
   }
 
1123
   VG_(printf)("\n");
 
1124
   space(d+0); VG_(printf)("}\n");
 
1125
}
 
1126
 
 
1127
static void pp_admin_locks ( Int d )
 
1128
{
 
1129
   Int   i, n;
 
1130
   Lock* lk;
 
1131
   for (n = 0, lk = admin_locks;  lk;  n++, lk = lk->admin) {
 
1132
      /* nothing */
 
1133
   }
 
1134
   space(d); VG_(printf)("admin_locks (%d records) {\n", n);
 
1135
   for (i = 0, lk = admin_locks;  lk;  i++, lk = lk->admin) {
 
1136
      if (0) {
 
1137
         space(n); 
 
1138
         VG_(printf)("admin_locks record %d of %d:\n", i, n);
 
1139
      }
 
1140
      pp_Lock(d+3, lk);
 
1141
   }
 
1142
   space(d); VG_(printf)("}\n", n);
 
1143
}
 
1144
 
 
1145
static void pp_map_locks ( Int d )
 
1146
{
 
1147
   void* gla;
 
1148
   Lock* lk;
 
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,
 
1153
                                      (Word*)&lk )) {
 
1154
      space(d+3);
 
1155
      VG_(printf)("guest %p -> Lock %p\n", gla, lk);
 
1156
   }
 
1157
   HG_(doneIterFM)( map_locks );
 
1158
   space(d); VG_(printf)("}\n");
 
1159
}
 
1160
 
 
1161
static void pp_Segment ( Int d, Segment* s )
 
1162
{
 
1163
   space(d+0); VG_(printf)("Segment %p {\n", s);
 
1164
   if (sHOW_ADMIN) {
 
1165
   space(d+3); VG_(printf)("admin  %p\n",   s->admin);
 
1166
   space(d+3); VG_(printf)("magic  0x%x\n", (UInt)s->magic);
 
1167
   }
 
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");
 
1173
}
 
1174
 
 
1175
static void pp_admin_segments ( Int d )
 
1176
{
 
1177
   Int      i, n;
 
1178
   Segment* s;
 
1179
   for (n = 0, s = admin_segments;  s;  n++, s = s->admin) {
 
1180
      /* nothing */
 
1181
   }
 
1182
   space(d); VG_(printf)("admin_segments (%d records) {\n", n);
 
1183
   for (i = 0, s = admin_segments;  s;  i++, s = s->admin) {
 
1184
      if (0) {
 
1185
         space(n); 
 
1186
         VG_(printf)("admin_segments record %d of %d:\n", i, n);
 
1187
      }
 
1188
      pp_Segment(d+3, s);
 
1189
   }
 
1190
   space(d); VG_(printf)("}\n", n);
 
1191
}
 
1192
 
 
1193
static void pp_map_segments ( Int d )
 
1194
{
 
1195
   SegmentID segid;
 
1196
   Segment*  seg;
 
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,
 
1201
                                         (Word*)&seg )) {
 
1202
      space(d+3);
 
1203
      VG_(printf)("segid 0x%x -> Segment %p\n", (UInt)segid, seg);
 
1204
   }
 
1205
   HG_(doneIterFM)( map_segments );
 
1206
   space(d); VG_(printf)("}\n");
 
1207
}
 
1208
 
 
1209
static void show_shadow_w32 ( /*OUT*/Char* buf, Int nBuf, SVal w32 )
 
1210
{
 
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));
 
1216
   }
 
1217
   else
 
1218
   if (is_SHVAL_ShR(w32)) {
 
1219
      VG_(sprintf)(buf, "ShR(%u,%u)", 
 
1220
                   un_SHVAL_ShR_tset(w32), un_SHVAL_ShR_lset(w32));
 
1221
   }
 
1222
   else
 
1223
   if (is_SHVAL_Excl(w32)) {
 
1224
      VG_(sprintf)(buf, "Excl(%u)", un_SHVAL_Excl(w32));
 
1225
   }
 
1226
   else
 
1227
   if (is_SHVAL_New(w32)) {
 
1228
      VG_(sprintf)(buf, "%s", "New");
 
1229
   }
 
1230
   else
 
1231
   if (is_SHVAL_NoAccess(w32)) {
 
1232
      VG_(sprintf)(buf, "%s", "NoAccess");
 
1233
   }
 
1234
   else {
 
1235
      VG_(sprintf)(buf, "Invalid-shadow-word(%u)", w32);
 
1236
   }
 
1237
}
 
1238
 
 
1239
static
 
1240
void show_shadow_w32_for_user ( /*OUT*/Char* buf, Int nBuf, SVal w32 )
 
1241
{
 
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));
 
1250
   }
 
1251
   else
 
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));
 
1258
   }
 
1259
   else
 
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);
 
1265
      } else {
 
1266
         VG_(sprintf)(buf, "Exclusive(segid=%u)", un_SHVAL_Excl(w32));
 
1267
      }
 
1268
   }
 
1269
   else
 
1270
   if (is_SHVAL_New(w32)) {
 
1271
      VG_(sprintf)(buf, "%s", "New");
 
1272
   }
 
1273
   else
 
1274
   if (is_SHVAL_NoAccess(w32)) {
 
1275
      VG_(sprintf)(buf, "%s", "NoAccess");
 
1276
   }
 
1277
   else {
 
1278
      VG_(sprintf)(buf, "Invalid-shadow-word(%u)", w32);
 
1279
   }
 
1280
}
 
1281
 
 
1282
static void pp_SecMap_shared ( Int d, SecMap* sm, Addr ga )
 
1283
{
 
1284
   Int  i;
 
1285
#if 0
 
1286
   Addr a;
 
1287
   SVal w32;
 
1288
   Char buf[100];
 
1289
#endif
 
1290
   CacheLineZ* lineZ;
 
1291
   CacheLineF* lineF;
 
1292
   space(d+0); VG_(printf)("SecMap %p (ga %p) {\n", sm, (void*)ga);
 
1293
 
 
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");
 
1297
   }
 
1298
 
 
1299
#if 0
 
1300
   for (i = 0; i < N_SECMAP_ARANGE; i++) {
 
1301
      w32 = sm->w32s[i];
 
1302
      a   = ga + 1 * i;
 
1303
      if (! (is_SHVAL_ShM(w32) || is_SHVAL_ShR(w32)))
 
1304
         continue;
 
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);
 
1308
   }
 
1309
#endif
 
1310
 
 
1311
   space(d+0); VG_(printf)("}\n");
 
1312
}
 
1313
 
 
1314
static void pp_map_shmem_shared ( Int d )
 
1315
{
 
1316
   Addr    ga;
 
1317
   SecMap* sm;
 
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,
 
1321
                                      (Word*)&sm )) {
 
1322
      pp_SecMap_shared( d+3, sm, ga );
 
1323
   }
 
1324
   HG_(doneIterFM) ( map_shmem );
 
1325
   space(d); VG_(printf)("}\n");
 
1326
}
 
1327
 
 
1328
static void pp_everything ( Int flags, Char* caller )
 
1329
{
 
1330
   Int d = 0;
 
1331
   VG_(printf)("\n");
 
1332
   VG_(printf)("All_Data_Structures (caller = \"%s\") {\n", caller);
 
1333
   if (flags & PP_THREADS) {
 
1334
      VG_(printf)("\n");
 
1335
      pp_admin_threads(d+3);
 
1336
      VG_(printf)("\n");
 
1337
      pp_map_threads(d+3);
 
1338
   }
 
1339
   if (flags & PP_LOCKS) {
 
1340
      VG_(printf)("\n");
 
1341
      pp_admin_locks(d+3);
 
1342
      VG_(printf)("\n");
 
1343
      pp_map_locks(d+3);
 
1344
   }
 
1345
   if (flags & PP_SEGMENTS) {
 
1346
      VG_(printf)("\n");
 
1347
      pp_admin_segments(d+3);
 
1348
      VG_(printf)("\n");
 
1349
      pp_map_segments(d+3);
 
1350
   }
 
1351
   if (flags & PP_SHMEM_SHARED) {
 
1352
      VG_(printf)("\n");
 
1353
      pp_map_shmem_shared( d+3 );
 
1354
   }
 
1355
 
 
1356
   VG_(printf)("\n");
 
1357
   VG_(printf)("}\n");
 
1358
   VG_(printf)("\n");
 
1359
}
 
1360
 
 
1361
#undef SHOW_ADMIN
 
1362
 
 
1363
 
 
1364
/*----------------------------------------------------------------*/
 
1365
/*--- Initialise the primary data structures                   ---*/
 
1366
/*----------------------------------------------------------------*/
 
1367
 
 
1368
/* fwds */
 
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 );
 
1376
 
 
1377
static void initialise_data_structures ( void )
 
1378
{
 
1379
   SegmentID segid;
 
1380
   Segment*  seg;
 
1381
   Thread*   thr;
 
1382
 
 
1383
   /* Get everything initialised and zeroed. */
 
1384
   tl_assert(admin_threads == NULL);
 
1385
   tl_assert(admin_locks == NULL);
 
1386
   tl_assert(admin_segments == NULL);
 
1387
 
 
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();
 
1393
 
 
1394
   tl_assert(map_threads == NULL);
 
1395
   map_threads = hg_zalloc( VG_N_THREADS * sizeof(Thread*) );
 
1396
   tl_assert(map_threads != NULL);
 
1397
 
 
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();
 
1405
 
 
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);
 
1410
 
 
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 );
 
1414
 
 
1415
   tl_assert(univ_tsets == NULL);
 
1416
   univ_tsets = HG_(newWordSetU)( hg_zalloc, hg_free, 8/*cacheSize*/ );
 
1417
   tl_assert(univ_tsets != NULL);
 
1418
 
 
1419
   tl_assert(univ_lsets == NULL);
 
1420
   univ_lsets = HG_(newWordSetU)( hg_zalloc, hg_free, 8/*cacheSize*/ );
 
1421
   tl_assert(univ_lsets != NULL);
 
1422
 
 
1423
   tl_assert(univ_laog == NULL);
 
1424
   univ_laog = HG_(newWordSetU)( hg_zalloc, hg_free, 24/*cacheSize*/ );
 
1425
   tl_assert(univ_laog != NULL);
 
1426
 
 
1427
   /* Set up entries for the root thread */
 
1428
   // FIXME: this assumes that the first real ThreadId is 1
 
1429
 
 
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 );
 
1435
 
 
1436
   /* a Thread for the new thread ... */
 
1437
   thr = mk_Thread( segid );
 
1438
   seg->thr = thr;
 
1439
 
 
1440
   /* Give the thread a starting-off vector timestamp. */
 
1441
   seg->vts = singleton_VTS( seg->thr, 1 );
 
1442
 
 
1443
   /* and bind it in the thread-map table.
 
1444
      FIXME: assumes root ThreadId == 1. */
 
1445
   map_threads[1] = thr;
 
1446
 
 
1447
   tl_assert(VG_INVALID_THREADID == 0);
 
1448
 
 
1449
   /* Mark the new bus lock correctly (to stop the sanity checks
 
1450
      complaining) */
 
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 );
 
1455
 
 
1456
   all__sanity_check("initialise_data_structures");
 
1457
}
 
1458
 
 
1459
 
 
1460
/*----------------------------------------------------------------*/
 
1461
/*--- map_threads :: WordFM core-ThreadId Thread*              ---*/
 
1462
/*----------------------------------------------------------------*/
 
1463
 
 
1464
/* Doesn't assert if the relevant map_threads entry is NULL. */
 
1465
static Thread* map_threads_maybe_lookup ( ThreadId coretid )
 
1466
{
 
1467
   Thread* thr;
 
1468
   tl_assert( is_sane_ThreadId(coretid) );
 
1469
   thr = map_threads[coretid];
 
1470
   return thr;
 
1471
}
 
1472
 
 
1473
/* Asserts if the relevant map_threads entry is NULL. */
 
1474
static inline Thread* map_threads_lookup ( ThreadId coretid )
 
1475
{
 
1476
   Thread* thr;
 
1477
   tl_assert( is_sane_ThreadId(coretid) );
 
1478
   thr = map_threads[coretid];
 
1479
   tl_assert(thr);
 
1480
   return thr;
 
1481
}
 
1482
 
 
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 )
125
1486
{
126
1487
   Int i;
127
 
   for (i = 0; i < N_PROF_EVENTS; i++) {
128
 
      if ((i % 10) == 0)
129
 
         VG_(printf)("\n");
130
 
      if (event_ctr[i] > 0)
131
 
         VG_(printf)( "prof mem event %2d: %d\n", i, event_ctr[i] );
132
 
   }
133
 
   VG_(printf)("\n");
134
 
}
135
 
 
136
 
#define PROF_EVENT(ev)                                  \
137
 
   do { tl_assert((ev) >= 0 && (ev) < N_PROF_EVENTS);   \
138
 
        event_ctr[ev]++;                                \
139
 
   } while (False);
140
 
 
141
 
#else
142
 
 
143
 
//static void init_prof_mem ( void ) { }
144
 
//       void VG_(done_prof_mem) ( void ) { }
145
 
 
146
 
#define PROF_EVENT(ev) /* */
147
 
 
148
 
#endif /* VG_PROFILE_MEMORY */
149
 
 
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.
152
 
 
153
 
   [PPP: snip event numbers...]
154
 
*/
155
 
#endif /* 0 */
156
 
 
157
 
 
158
 
/*------------------------------------------------------------*/
159
 
/*--- Data defns.                                          ---*/
160
 
/*------------------------------------------------------------*/
161
 
 
162
 
typedef
163
 
   struct _HG_Chunk {
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                */
169
 
   }
170
 
   HG_Chunk;
171
 
 
172
 
typedef enum 
173
 
   { Vge_VirginInit, Vge_NonVirginInit, Vge_SegmentInit, Vge_Error } 
174
 
   VgeInitStatus;
175
 
 
176
 
 
177
 
// XXX: not 64-bit clean!
178
 
/* Should add up to 32 to fit in one word */
179
 
#define OTHER_BITS      30
180
 
#define STATE_BITS      2
181
 
 
182
 
#define ESEC_MAP_WORDS  16384   /* Words per secondary map */
183
 
 
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
189
 
 
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)
194
 
 
195
 
/* Number of entries must fit in STATE_BITS bits */
196
 
typedef enum { Vge_Virgin, Vge_Excl, Vge_Shar, Vge_SharMod } pth_state;
197
 
 
198
 
static inline const Char *pp_state(pth_state st)
199
 
{
200
 
   const Char *ret;
201
 
 
202
 
   switch(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 = "???";
208
 
   }
209
 
   return ret;
210
 
}
211
 
 
212
 
typedef
213
 
   struct {
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;
218
 
   } shadow_word;
219
 
 
220
 
#define SW(st, other)   ((shadow_word) { st, other })
221
 
 
222
 
typedef
223
 
   struct {
224
 
      shadow_word swords[ESEC_MAP_WORDS];
225
 
   }
226
 
   ESecMap;
227
 
 
228
 
static ESecMap* primary_map[ 65536 ];
229
 
static ESecMap  distinguished_secondary_map;
230
 
 
231
 
static const shadow_word virgin_sword = SW(Vge_Virgin, 0);
232
 
static const shadow_word error_sword = SW(Vge_Excl, TLSP_INDICATING_ALL);
233
 
 
234
 
#define VGE_IS_DISTINGUISHED_SM(smap) \
235
 
   ((smap) == &distinguished_secondary_map)
236
 
 
237
 
#define ENSURE_MAPPABLE(addr,caller)                                  \
238
 
   do {                                                               \
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);*/           \
242
 
      } \
243
 
   } while(0)
244
 
 
245
 
 
246
 
/* Parallel map which contains execution contexts when words last
247
 
  changed state (if required) */
248
 
 
249
 
typedef struct EC_IP {
250
 
   union u_ec_ip {
251
 
      Addr              ip;
252
 
      ExeContext        *ec;
253
 
   } uu_ec_ip;
254
 
   UInt                 state:STATE_BITS;
255
 
   UInt                 tls:OTHER_BITS;         /* packed TLS */
256
 
} EC_IP;
257
 
 
258
 
#define NULL_EC_IP      ((EC_IP){ { 0 }, 0, 0})
259
 
 
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) })
262
 
 
263
 
static inline UInt packEC(ExeContext *ec)
264
 
{
265
 
   TL_ASSERT(((UWord)ec & ((1 << STATE_BITS)-1)) == 0);
266
 
   return ((UWord)ec) >> STATE_BITS;
267
 
}
268
 
 
269
 
/* Lose 2 LSB of IP */
270
 
static inline UInt packIP(Addr ip)
271
 
{
272
 
   return ip >> STATE_BITS;
273
 
}
274
 
 
275
 
static inline Addr unpackIP(UInt i)
276
 
{
277
 
   return (Addr)(i << STATE_BITS);
278
 
}
279
 
 
280
 
typedef struct {
281
 
   EC_IP execontext[ESEC_MAP_WORDS];
282
 
} ExeContextMap;
283
 
 
284
 
static ExeContextMap** execontext_map;
285
 
 
286
 
static inline void setExeContext(Addr a, EC_IP ec)
287
 
{
288
 
   UInt idx = (a >> 16) & 0xffff;
289
 
   UInt off = (a >>  2) & 0x3fff;
290
 
 
291
 
   if (execontext_map[idx] == NULL) {
292
 
      execontext_map[idx] = VG_(malloc)(sizeof(ExeContextMap));
293
 
      VG_(memset)(execontext_map[idx], 0, sizeof(ExeContextMap));
294
 
   }
295
 
 
296
 
   execontext_map[idx]->execontext[off] = ec;
297
 
}
298
 
 
299
 
static inline EC_IP getExeContext(Addr a)
300
 
{
301
 
   UInt idx = (a >> 16) & 0xffff;
302
 
   UInt off = (a >>  2) & 0x3fff;
303
 
   EC_IP ec = NULL_EC_IP;
304
 
 
305
 
   if (execontext_map[idx] != NULL)
306
 
      ec = execontext_map[idx]->execontext[off];
307
 
 
308
 
   return ec;
309
 
}
310
 
 
311
 
/*------------------------------------------------------------*/
312
 
/*--- Thread lifetime segments                             ---*/
313
 
/*------------------------------------------------------------*/
314
 
 
315
 
/*
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
320
 
 * on it.
321
 
 *
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.
328
 
 *
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).
332
 
 */
333
 
 
334
 
typedef struct _ThreadLifeSeg ThreadLifeSeg;
335
 
 
336
 
struct _ThreadLifeSeg {
337
 
   ThreadId              tid;
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 */
342
 
};
343
 
 
344
 
static ThreadLifeSeg *all_tls;
345
 
static UInt tls_since_gc;
346
 
#define TLS_SINCE_GC    10000
347
 
 
348
 
/* current mark used for TLS graph traversal */
349
 
static UInt tlsmark;
350
 
 
351
 
static ThreadLifeSeg *thread_seg[VG_N_THREADS];
352
 
 
353
 
 
354
 
static void tls_gc(void)
355
 
{
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");
361
 
}
362
 
 
363
 
static void newTLS(ThreadId tid)
364
 
{
365
 
   static const Bool debug = False;
366
 
   ThreadLifeSeg *tls;
367
 
 
368
 
   /* Initial NULL */
369
 
   if (thread_seg[tid] == NULL) {
370
 
      tls = VG_(malloc)(sizeof(*tls));
371
 
      tls->tid = tid;
372
 
      tls->prior[0] = tls->prior[1] = NULL;
373
 
      tls->refcount = 0;
374
 
      tls->mark = tlsmark-1;
375
 
 
376
 
      tls->next = all_tls;
377
 
      all_tls = tls;
378
 
      tls_since_gc++;
379
 
 
380
 
      thread_seg[tid] = tls;
381
 
      return;
382
 
   }
383
 
   
384
 
   /* Previous TLS was unused, so just recycle */
385
 
   if (thread_seg[tid]->refcount == 0) {
386
 
      if (debug)
387
 
         VG_(printf)("newTLS; recycling TLS %p for tid %u\n", 
388
 
                     thread_seg[tid], tid);
389
 
      return;
390
 
   }
391
 
 
392
 
   /* Use existing TLS for this tid as a prior for new TLS */
393
 
   tls = VG_(malloc)(sizeof(*tls));
394
 
   tls->tid = tid;
395
 
   tls->prior[0] = thread_seg[tid];
396
 
   tls->prior[1] = NULL;
397
 
   tls->refcount = 0;
398
 
   tls->mark = tlsmark-1;
399
 
 
400
 
   tls->next = all_tls;
401
 
   all_tls = tls;
402
 
   if (++tls_since_gc > TLS_SINCE_GC) {
403
 
      tls_gc();
404
 
      tls_since_gc = 0;
405
 
   }
406
 
   
407
 
   if (debug)
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);
410
 
 
411
 
   thread_seg[tid] = tls;
412
 
}
413
 
 
414
 
/* clear out a TLS for a thread that's died */
415
 
static void clearTLS(ThreadId tid)
416
 
{
417
 
   newTLS(tid);
418
 
 
419
 
   thread_seg[tid]->prior[0] = NULL;
420
 
   thread_seg[tid]->prior[1] = NULL;
421
 
}
422
 
 
423
 
static void addPriorTLS(ThreadId tid, ThreadId prior)
424
 
{
425
 
   static const Bool debug = False;
426
 
   ThreadLifeSeg *tls = thread_seg[tid];
427
 
 
428
 
   if (debug)
429
 
      VG_(printf)("making TLS %p(%u) prior to TLS %p(%u)\n",
430
 
                  thread_seg[prior], prior, tls, tid);
431
 
 
432
 
   tl_assert(thread_seg[tid] != NULL);
433
 
   tl_assert(thread_seg[prior] != NULL);
434
 
 
435
 
   if (tls->prior[0] == NULL)
436
 
      tls->prior[0] = thread_seg[prior];
437
 
   else {
438
 
      tl_assert(tls->prior[1] == NULL);
439
 
      tls->prior[1] = thread_seg[prior];
440
 
   }
441
 
}
442
 
 
443
 
static Bool isPrior(const ThreadLifeSeg *t, const ThreadLifeSeg *prior)
444
 
{
445
 
   if (t == NULL || t->mark == tlsmark)
446
 
      return False;
447
 
 
448
 
   if (t == prior)
449
 
      return True;
450
 
 
451
 
   ((ThreadLifeSeg *)t)->mark = tlsmark;
452
 
 
453
 
   return isPrior(t->prior[0], prior) || isPrior(t->prior[1], prior);
454
 
}
455
 
 
456
 
/* Return True if prior is definitely not concurrent with tls */
457
 
static Bool tlsIsDisjoint(const ThreadLifeSeg *tls, 
458
 
                          const ThreadLifeSeg *prior)
459
 
{
460
 
   tlsmark++;                   /* new traversal mark */
461
 
 
462
 
   return isPrior(tls, prior);
463
 
}
464
 
 
465
 
static inline UInt packTLS(ThreadLifeSeg *tls)
466
 
{
467
 
   TL_ASSERT(((UWord)tls & ((1 << STATE_BITS)-1)) == 0);
468
 
   return ((UWord)tls) >> STATE_BITS;
469
 
}
470
 
 
471
 
static inline ThreadLifeSeg *unpackTLS(UInt i)
472
 
{
473
 
   /* HACK ALERT -- DUBIOUS CAST */
474
 
   return (ThreadLifeSeg *)ULong_to_Ptr(i << STATE_BITS);
475
 
}
476
 
 
477
 
/*------------------------------------------------------------*/
478
 
/*--- Low-level support for memory tracking.               ---*/
479
 
/*------------------------------------------------------------*/
480
 
 
481
 
/*
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).  
487
 
 
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:
491
 
 
492
 
     bits 31..16:   primary map lookup
493
 
     bits 15.. 2:   secondary map lookup
494
 
     bits  1.. 0:   ignored
495
 
*/
496
 
 
497
 
 
498
 
/*------------------------------------------------------------*/
499
 
/*--- Basic bitmap management, reading and writing.        ---*/
500
 
/*------------------------------------------------------------*/
501
 
 
502
 
/* Allocate and initialise a secondary map, marking all words as virgin. */
503
 
 
504
 
/* Just a value that isn't a real pointer */
505
 
#define SEC_MAP_ACCESS  (shadow_word*)0x99    
506
 
 
507
 
 
508
 
static 
509
 
ESecMap* alloc_secondary_map ( __attribute__ ((unused)) Char* caller )
510
 
{
511
 
   ESecMap* map;
512
 
   UInt  i;
513
 
   //PROF_EVENT(10); PPP
514
 
 
515
 
   // Mark all words as virgin.
516
 
   map = (ESecMap *)VG_(am_shadow_alloc)(sizeof(ESecMap));
517
 
   if (map == NULL)
518
 
      VG_(out_of_memory_NORETURN)( "helgrind:allocate new ESecMap", 
519
 
                                   sizeof(ESecMap) );
520
 
   for (i = 0; i < ESEC_MAP_WORDS; i++)
521
 
      map->swords[i] = virgin_sword;
522
 
 
523
 
   return map;
524
 
}
525
 
 
526
 
 
527
 
/* Set a word.  The byte give by 'a' could be anywhere in the word -- the whole
528
 
 * word gets set. */
529
 
static /* __inline__ */
530
 
void set_sword ( Addr a, shadow_word sword )
531
 
{
532
 
   ESecMap* sm;
533
 
   shadow_word *oldsw;
534
 
 
535
 
   //PROF_EVENT(23); PPP
536
 
   ENSURE_MAPPABLE(a, "VGE_(set_sword)");
537
 
 
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);
544
 
      tls->refcount--;
545
 
   }
546
 
 
547
 
   if (sword.state == Vge_Excl && sword.other != TLSP_INDICATING_ALL) {
548
 
      ThreadLifeSeg *tls = unpackTLS(sword.other);
549
 
      tls->refcount++;
550
 
   }
551
 
   
552
 
   sm->swords[(a & 0xFFFC) >> 2] = sword;
553
 
 
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!");
558
 
   }
559
 
}
560
 
 
561
 
 
562
 
static __inline__ 
563
 
shadow_word* get_sword_addr ( Addr a )
564
 
{
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;
568
 
 
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;
574
 
   }
575
 
 
576
 
   //PROF_EVENT(21); PPP
577
 
   return & (sm->swords[sm_off]);
578
 
}
579
 
 
580
 
 
581
 
// SSS: rename these so they're not so similar to memcheck, unless it's
582
 
// appropriate of course
583
 
 
584
 
static __inline__ 
585
 
void init_virgin_sword(Addr a)
586
 
{
587
 
   if (clo_execontext != EC_None)
588
 
      setExeContext(a, NULL_EC_IP);
589
 
   set_sword(a, virgin_sword);
590
 
}
591
 
 
592
 
static __inline__
593
 
void init_error_sword(Addr a)
594
 
{
595
 
   set_sword(a, error_sword);
596
 
}
597
 
 
598
 
static __inline__ 
599
 
void init_nonvirgin_sword(Addr a)
600
 
{
601
 
   shadow_word sword;
602
 
   ThreadId tid;
603
 
   ThreadLifeSeg *tls;
604
 
 
605
 
   // The tid must be passed in here now;  this requires more events to be
606
 
   // given the tid in the first place.
607
 
   //
608
 
   //tid = VG_(get_current_or_recent_tid)();
609
 
   VG_(message)(Vg_DebugMsg, "tid needs to be passed in here");
610
 
   VG_(exit)(1);
611
 
 
 
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)
 
1494
         return (ThreadId)i;
 
1495
   }
 
1496
   return VG_INVALID_THREADID;
 
1497
}
 
1498
 
 
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 )
 
1502
{
 
1503
   ThreadId tid = map_threads_maybe_reverse_lookup_SLOW( thr );
612
1504
   tl_assert(tid != VG_INVALID_THREADID);
613
 
   tls = thread_seg[tid];
614
 
 
615
 
   sword = SW(Vge_Excl, packTLS(tls));
616
 
   set_sword(a, sword);
617
 
}
618
 
 
619
 
 
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 
623
 
 * uninited read. */
624
 
static __inline__ 
625
 
void init_magically_inited_sword(Addr a)
626
 
{
627
 
   shadow_word sword;
628
 
 
629
 
   sword = SW(Vge_Virgin, TID_INDICATING_NONVIRGIN);
630
 
 
631
 
   set_sword(a, virgin_sword);
632
 
}
633
 
 
634
 
 
635
 
/*------------------------------------------------------------*/
636
 
/*--- Implementation of lock sets.                         ---*/
637
 
/*------------------------------------------------------------*/
638
 
 
639
 
typedef struct _Mutex Mutex; /* forward decl */
640
 
typedef struct _LockSet LockSet;
641
 
 
642
 
typedef enum MutexState {
643
 
   MxUnknown,                   /* don't know */
644
 
   MxUnlocked,                  /* unlocked */
645
 
   MxLocked,                    /* locked */
646
 
   MxDead                       /* destroyed */
647
 
} MutexState;
648
 
 
649
 
struct _Mutex {
650
 
   Addr               mutexp;
651
 
   Mutex             *next;
652
 
 
653
 
   MutexState         state;    /* mutex state */
654
 
   ThreadId           tid;      /* owner */
655
 
   ExeContext        *location; /* where the last change happened */
656
 
 
657
 
   const LockSet     *lockdep;  /* set of locks we depend on */
658
 
   UInt               mark;     /* mark for graph traversal */
659
 
};
660
 
 
661
 
static inline Int mutex_cmp(const Mutex *a, const Mutex *b)
662
 
{
663
 
   return a->mutexp - b->mutexp;
664
 
}
665
 
 
666
 
struct _LockSet {
667
 
   Int                setsize;  /* number of members */
668
 
   UInt               hash;     /* hash code */
669
 
   LockSet           *next;     /* next in hash chain */
670
 
   const Mutex       *mutex[0]; /* locks */
671
 
};
672
 
 
673
 
static const LockSet *emptyset;
674
 
 
675
 
/* Each one is an index into the lockset table. */
676
 
static const LockSet *thread_locks[VG_N_THREADS];
677
 
 
678
 
#define LOCKSET_HASH_SZ 1021
679
 
 
680
 
static LockSet *lockset_hash[LOCKSET_HASH_SZ];
681
 
 
682
 
/* Pack and unpack a LockSet pointer into shadow_word.other */
683
 
static inline UInt packLockSet(const LockSet *p)
684
 
{
685
 
   UInt id;
686
 
 
687
 
   TL_ASSERT(((UWord)p & ((1 << STATE_BITS)-1)) == 0);
688
 
   id = ((UWord)p) >> STATE_BITS;
689
 
 
690
 
   return id;
691
 
}
692
 
 
693
 
static inline const LockSet *unpackLockSet(UInt id)
694
 
{
695
 
   /* HACK ALERT -- DUBIOUS CAST */
696
 
   return (LockSet *)ULong_to_Ptr(id << STATE_BITS);
697
 
}
698
 
 
 
1505
   return tid;
 
1506
}
 
1507
 
 
1508
static void map_threads_delete ( ThreadId coretid )
 
1509
{
 
1510
   Thread* thr;
 
1511
   tl_assert(coretid != 0);
 
1512
   tl_assert( is_sane_ThreadId(coretid) );
 
1513
   thr = map_threads[coretid];
 
1514
   tl_assert(thr);
 
1515
   map_threads[coretid] = NULL;
 
1516
}
 
1517
 
 
1518
 
 
1519
/*----------------------------------------------------------------*/
 
1520
/*--- map_locks :: WordFM guest-Addr-of-lock Lock*             ---*/
 
1521
/*----------------------------------------------------------------*/
 
1522
 
 
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. */
699
1526
static 
700
 
void pp_LockSet(const LockSet* p)
701
 
{
702
 
   Int i;
703
 
   VG_(printf)("{ ");
704
 
   for(i = 0; i < p->setsize; i++) {
705
 
      const Mutex *mx = p->mutex[i];
706
 
 
707
 
      VG_(printf)("%p%(y ", mx->mutexp, mx->mutexp);
708
 
   }
709
 
   VG_(printf)("}\n");
710
 
}
711
 
 
712
 
 
713
 
static void print_LockSet(const Char *s, const LockSet *ls)
714
 
{
715
 
   VG_(printf)("%s: ", s);
716
 
   pp_LockSet(ls);
717
 
}
718
 
 
719
 
/* Compute the hash of a LockSet */
720
 
static UInt hash_LockSet_w_wo(const LockSet *ls, 
721
 
                              const Mutex *with,
722
 
                              const Mutex *without)
723
 
{
724
 
   Int  i;
725
 
   UInt hash = ls->setsize + (with != NULL) - (without != NULL);
726
 
   
727
 
   tl_assert(with == NULL || with != without);
728
 
 
729
 
   for(i = 0; with != NULL || i < ls->setsize; i++) {
730
 
      const Mutex *mx = i >= ls->setsize ? NULL : ls->mutex[i];
731
 
 
732
 
      if (without && mutex_cmp(without, mx) == 0)
733
 
         continue;
734
 
 
735
 
      if (with && (mx == NULL || mutex_cmp(with, mx) < 0)) {
736
 
         mx = with;
737
 
         with = NULL;
738
 
         i--;
 
1527
Lock* map_locks_lookup_or_create ( LockKind lkk, Addr ga, ThreadId tid )
 
1528
{
 
1529
   Bool  found;
 
1530
   Lock* oldlock = NULL;
 
1531
   tl_assert(is_sane_ThreadId(tid));
 
1532
   found = HG_(lookupFM)( map_locks, 
 
1533
                          NULL, (Word*)&oldlock, (Word)ga );
 
1534
   if (!found) {
 
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 );
 
1542
      return lock;
 
1543
   } else {
 
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);
 
1549
      return oldlock;
 
1550
   }
 
1551
}
 
1552
 
 
1553
static Lock* map_locks_maybe_lookup ( Addr ga )
 
1554
{
 
1555
   Bool  found;
 
1556
   Lock* lk = NULL;
 
1557
   found = HG_(lookupFM)( map_locks, NULL, (Word*)&lk, (Word)ga );
 
1558
   tl_assert(found  ?  lk != NULL  :  lk == NULL);
 
1559
   if (found) {
 
1560
      // check the relevant secondary map has .mbHasLocks?
 
1561
      tl_assert(shmem__get_mbHasLocks(ga) == True);
 
1562
   }
 
1563
   return lk;
 
1564
}
 
1565
 
 
1566
static void map_locks_delete ( Addr ga )
 
1567
{
 
1568
   Addr  ga2 = 0;
 
1569
   Lock* lk  = NULL;
 
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);
 
1577
}
 
1578
 
 
1579
 
 
1580
/*----------------------------------------------------------------*/
 
1581
/*--- map_segments :: WordFM SegmentID Segment*                ---*/
 
1582
/*--- the DAG of thread segments                               ---*/
 
1583
/*----------------------------------------------------------------*/
 
1584
 
 
1585
static void segments__generate_vcg ( void ); /* fwds */
 
1586
 
 
1587
/*--------------- SegmentID to Segment* maps ---------------*/
 
1588
 
 
1589
static Segment* map_segments_lookup ( SegmentID segid )
 
1590
{
 
1591
   Bool     found;
 
1592
   Segment* seg = NULL;
 
1593
   tl_assert( is_sane_SegmentID(segid) );
 
1594
   found = HG_(lookupFM)( map_segments,
 
1595
                          NULL, (Word*)&seg, (Word)segid );
 
1596
   tl_assert(found);
 
1597
   tl_assert(seg != NULL);
 
1598
   return seg;
 
1599
}
 
1600
 
 
1601
static Segment* map_segments_maybe_lookup ( SegmentID segid )
 
1602
{
 
1603
   Bool     found;
 
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);
 
1609
   return seg;
 
1610
}
 
1611
 
 
1612
static void map_segments_add ( SegmentID segid, Segment* seg )
 
1613
{
 
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 );
 
1617
}
 
1618
 
 
1619
/*--------------- to do with Vector Timestamps ---------------*/
 
1620
 
 
1621
/* Scalar Timestamp */
 
1622
typedef
 
1623
   struct {
 
1624
      Thread* thr;
 
1625
      UWord   tym;
 
1626
   }
 
1627
   ScalarTS;
 
1628
 
 
1629
/* Vector Timestamp = XArray* ScalarTS */
 
1630
 
 
1631
static Bool is_sane_VTS ( XArray* vts )
 
1632
{
 
1633
   UWord     i, n;
 
1634
   ScalarTS  *st1, *st2;
 
1635
   n = VG_(sizeXA)( vts );
 
1636
   if (n >= 2) {
 
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)
 
1641
            return False;
 
1642
         if (st1->tym == 0 || st2->tym == 0)
 
1643
            return False;
739
1644
      }
740
 
 
741
 
      hash = ROTL(hash, 17);
742
 
      hash ^= mx->mutexp;
743
 
   }
744
 
 
745
 
   return hash % LOCKSET_HASH_SZ;
746
 
}
747
 
 
748
 
static inline UInt hash_LockSet_with(const LockSet *ls, const Mutex *with)
749
 
{
750
 
   UInt hash = hash_LockSet_w_wo(ls, with, NULL);
751
 
 
752
 
   if (0)
753
 
      VG_(printf)("hash_with %p+%p -> %d\n", ls, with->mutexp, hash);
754
 
 
755
 
   return hash;
756
 
}
757
 
 
758
 
static inline UInt hash_LockSet_without(const LockSet *ls, const Mutex *without)
759
 
{
760
 
   UInt hash = hash_LockSet_w_wo(ls, NULL, without);
761
 
 
762
 
   if (0)
763
 
      VG_(printf)("hash_with %p-%p -> %d\n", ls, without->mutexp, hash);
764
 
 
765
 
   return hash;
766
 
}
767
 
 
768
 
static inline UInt hash_LockSet(const LockSet *ls)
769
 
{
770
 
   UInt hash = hash_LockSet_w_wo(ls, NULL, NULL);
771
 
 
772
 
   if (0)
773
 
      VG_(printf)("hash %p -> %d\n", ls, hash);
774
 
 
775
 
   return hash;
776
 
}
777
 
 
778
 
static 
779
 
Bool structural_eq_LockSet(const LockSet* a, const LockSet* b)
780
 
{
781
 
   Int i;
782
 
 
783
 
   if (a == b)
784
 
      return True;
785
 
   if (a->setsize != b->setsize)
786
 
      return False;
787
 
 
788
 
   for(i = 0; i < a->setsize; i++) {
789
 
      if (mutex_cmp(a->mutex[i], b->mutex[i]) != 0)
790
 
         return False;
791
 
   }
792
 
 
 
1645
   }
793
1646
   return True;
794
1647
}
795
1648
 
796
 
 
797
 
/* Tricky: equivalent to (compare(insert(missing_elem, a), b)), but
798
 
 * doesn't do the insertion.  Returns True if they match.
799
 
 */
800
 
static Bool 
801
 
weird_LockSet_equals(const LockSet* a, const LockSet* b, 
802
 
                     const Mutex *missing_mutex)
803
 
{
804
 
   static const Bool debug = False;
805
 
   Int ia, ib;
806
 
 
807
 
   /* Idea is to try and match each element of b against either an
808
 
      element of a, or missing_mutex. */
809
 
 
810
 
   if (debug) {
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);
815
 
   }
816
 
 
817
 
   if ((a->setsize + 1) != b->setsize) {
818
 
      if (debug)
819
 
         VG_(printf)("   fastpath length mismatch -> 0\n");
820
 
      return False;
821
 
   }
822
 
 
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
827
 
    */
828
 
 
829
 
   ia = 0;
830
 
   ib = 0;
831
 
 
832
 
   /* 1: up to missing_mutex */
833
 
   for(; ia < a->setsize && mutex_cmp(a->mutex[ia], missing_mutex) < 0; ia++, ib++) {
834
 
      if (debug) {
835
 
         print_LockSet("     1:a", a);
836
 
         print_LockSet("     1:b", b);
837
 
      }
838
 
      if (ib == b->setsize || mutex_cmp(a->mutex[ia], b->mutex[ib]) != 0)
839
 
         return False;
840
 
   }
841
 
 
842
 
   /* 2: missing_mutex itself */
843
 
   if (debug) {
844
 
      VG_(printf)(  "     2:missing: %p%(y\n", 
845
 
                    missing_mutex->mutexp, missing_mutex->mutexp);
846
 
      print_LockSet("     2:      b", b);
847
 
   }
848
 
 
849
 
   tl_assert(ia == a->setsize || mutex_cmp(a->mutex[ia], missing_mutex) >= 0);
850
 
 
851
 
   if (ib == b->setsize || mutex_cmp(missing_mutex, b->mutex[ib]) != 0)
852
 
      return False;
853
 
 
854
 
   ib++;
855
 
 
856
 
   /* 3: after missing_mutex to end */
857
 
 
858
 
   for(; ia < a->setsize && ib < b->setsize; ia++, ib++) {
859
 
      if (debug) {
860
 
         print_LockSet("     3:a", a);
861
 
         print_LockSet("     3:b", b);
862
 
      }
863
 
      if (mutex_cmp(a->mutex[ia], b->mutex[ib]) != 0)
864
 
         return False;
865
 
   }
866
 
 
867
 
   if (debug)
868
 
      VG_(printf)("  ia=%d ib=%d --> %d\n", ia, ib, ia == a->setsize && ib == b->setsize);
869
 
 
870
 
   return ia == a->setsize && ib == b->setsize;
871
 
}
872
 
 
873
 
 
874
 
 
875
 
static const LockSet *lookup_LockSet(const LockSet *set)
876
 
{
877
 
   UInt bucket = set->hash;
878
 
   LockSet *ret;
879
 
 
880
 
   for(ret = lockset_hash[bucket]; ret != NULL; ret = ret->next)
881
 
      if (set == ret || structural_eq_LockSet(set, ret))
882
 
         return ret;
883
 
 
884
 
   return NULL;
885
 
}
886
 
 
887
 
static const LockSet *lookup_LockSet_with(const LockSet *set, Mutex *mutex)
888
 
{
889
 
   UInt bucket = hash_LockSet_with(set, mutex);
890
 
   const LockSet *ret;
891
 
   
892
 
   for(ret = lockset_hash[bucket]; ret != NULL; ret = ret->next)
893
 
      if (weird_LockSet_equals(set, ret, mutex))
894
 
         return ret;
895
 
 
896
 
   return NULL;
897
 
}
898
 
 
899
 
static const LockSet *lookup_LockSet_without(const LockSet *set, Mutex *mutex)
900
 
{
901
 
   UInt bucket = hash_LockSet_without(set, mutex);
902
 
   const LockSet *ret;
903
 
   
904
 
   for(ret = lockset_hash[bucket]; ret != NULL; ret = ret->next)
905
 
      if (weird_LockSet_equals(ret, set, mutex))
906
 
         return ret;
907
 
 
908
 
   return NULL;
909
 
}
910
 
 
911
 
static void insert_LockSet(LockSet *set)
912
 
{
913
 
   UInt hash = hash_LockSet(set);
914
 
   
915
 
   set->hash = hash;
916
 
 
917
 
   tl_assert(lookup_LockSet(set) == NULL);
918
 
 
919
 
   set->next = lockset_hash[hash];
920
 
   lockset_hash[hash] = set;
921
 
}
922
 
 
923
 
static inline
924
 
LockSet *alloc_LockSet(UInt setsize)
925
 
{
926
 
   LockSet *ret = VG_(malloc)(sizeof(*ret) + sizeof(Mutex *) * setsize);
927
 
   ret->setsize = setsize;
928
 
   return ret;
929
 
}
930
 
 
931
 
static inline
932
 
void free_LockSet(LockSet *p)
933
 
{
934
 
   /* assert: not present in hash */
935
 
   VG_(free)(p);
936
 
}
937
 
 
938
 
static
939
 
void pp_all_LockSets ( void )
940
 
{
941
 
   Int i;
942
 
   Int sets, buckets;
943
 
 
944
 
   sets = buckets = 0;
945
 
   for (i = 0; i < LOCKSET_HASH_SZ; i++) {
946
 
      const LockSet *ls = lockset_hash[i];
947
 
      Bool first = True;
948
 
      
949
 
      for(; ls != NULL; ls = ls->next) {
950
 
         if (first) {
951
 
            buckets++;
952
 
            VG_(printf)("[%4d] = ", i);
953
 
         } else
954
 
            VG_(printf)("         ");
955
 
 
956
 
         sets++;
957
 
         first = False;
958
 
         pp_LockSet(ls);
959
 
      }
960
 
   }
961
 
 
962
 
   VG_(printf)("%d distinct LockSets in %d buckets\n", sets, buckets);
963
 
}
964
 
 
965
 
static inline Bool isempty(const LockSet *ls)
966
 
{
967
 
   return ls == NULL || ls->setsize == 0;
968
 
}
969
 
 
970
 
static Bool ismember(const LockSet *ls, const Mutex *mx)
971
 
{
972
 
   Int i;
973
 
 
974
 
   /* XXX use binary search */
975
 
   for(i = 0; i < ls->setsize; i++)
976
 
      if (mutex_cmp(mx, ls->mutex[i]) == 0)
977
 
         return True;
978
 
 
979
 
   return False;
980
 
}
981
 
 
982
 
/* Check invariants:
983
 
   - all locksets are unique
984
 
   - each set is an array in strictly increasing order of mutex addr 
985
 
*/
986
 
static
987
 
void sanity_check_locksets ( const Char* caller )
988
 
{
989
 
   Int              i;
990
 
   const Char *badness;
991
 
   LockSet *ls;
992
 
 
993
 
   for(i = 0; i < LOCKSET_HASH_SZ; i++) {
994
 
 
995
 
      for(ls = lockset_hash[i]; ls != NULL; ls = ls->next) {
996
 
         const Mutex *prev;
997
 
         Int j;
998
 
 
999
 
         if (hash_LockSet(ls) != ls->hash) {
1000
 
            badness = "mismatched hash";
1001
 
            goto bad;
1002
 
         }
1003
 
         if (ls->hash != (UInt)i) {
1004
 
            badness = "wrong bucket";
1005
 
            goto bad;
1006
 
         }
1007
 
         if (lookup_LockSet(ls) != ls) {
1008
 
            badness = "non-unique set";
1009
 
            goto bad;
1010
 
         }
1011
 
 
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";
1016
 
               goto bad;
1017
 
            }
1018
 
         }
1019
 
      }
1020
 
   }
1021
 
   return;
1022
 
 
1023
 
  bad:
1024
 
   VG_(printf)("sanity_check_locksets: "
1025
 
               "i = %d, ls=%p badness = %s, caller = %s\n", 
1026
 
               i, ls, badness, caller);
1027
 
   pp_all_LockSets();
1028
 
   VG_(tool_panic)("sanity_check_locksets");
1029
 
}
1030
 
 
1031
 
static
1032
 
LockSet *add_LockSet(const LockSet *ls, const Mutex *mx)
1033
 
{
1034
 
   static const Bool debug = False;
1035
 
   LockSet *ret = NULL;
1036
 
   Int i, j;
1037
 
 
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);
1041
 
   }
1042
 
 
1043
 
   if (debug || LOCKSET_SANITY)
1044
 
      sanity_check_locksets("add-IN");
1045
 
 
1046
 
   tl_assert(!ismember(ls, mx));
1047
 
 
1048
 
   ret = alloc_LockSet(ls->setsize+1);
1049
 
 
1050
 
   for(i = j = 0; i < ls->setsize; i++) {
1051
 
      if (debug)
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;
1056
 
         mx = NULL;
1057
 
      }
1058
 
      ret->mutex[j++] = ls->mutex[i];
1059
 
   }
1060
 
 
1061
 
   /* not added in loop - must be after */
1062
 
   if (mx)
1063
 
      ret->mutex[j++] = mx;
1064
 
 
1065
 
   tl_assert(j == ret->setsize);
1066
 
 
1067
 
   if (debug || LOCKSET_SANITY) {
1068
 
      print_LockSet("add-OUT", ret);
1069
 
      sanity_check_locksets("add-OUT");
1070
 
   }
1071
 
   return ret;
1072
 
}
1073
 
 
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).
1077
 
*/
1078
 
static 
1079
 
LockSet *remove_LockSet ( const LockSet *ls, const Mutex *mx )
1080
 
{
1081
 
   static const Bool debug = False;
1082
 
   LockSet   *ret = NULL;
1083
 
   Int        i, j;
1084
 
 
1085
 
   if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1086
 
      print_LockSet("remove-IN", ls);
1087
 
   }
1088
 
 
1089
 
   if (debug || LOCKSET_SANITY)
1090
 
      sanity_check_locksets("remove-IN");
1091
 
 
1092
 
   tl_assert(ismember(ls, mx));
1093
 
 
1094
 
   ret = alloc_LockSet(ls->setsize-1);
1095
 
 
1096
 
   for(i = j = 0; i < ls->setsize; i++) {
1097
 
      if (mutex_cmp(ls->mutex[i], mx) == 0)
1098
 
              continue;
1099
 
      ret->mutex[j++] = ls->mutex[i];
1100
 
   }
1101
 
 
1102
 
   tl_assert(j == ret->setsize);
1103
 
 
1104
 
   if (debug || LOCKSET_SANITY) {
1105
 
      print_LockSet("remove-OUT", ret);
1106
 
      sanity_check_locksets("remove-OUT");
1107
 
   }
1108
 
   return ret;
1109
 
}
1110
 
 
1111
 
 
1112
 
/* Builds the intersection, and then unbuilds it if it's already in the table.
1113
 
 */
1114
 
static const LockSet *_intersect(const LockSet *a, const LockSet *b)
1115
 
{
1116
 
   static const Bool debug = False;
1117
 
   Int       iret;
1118
 
   Int       ia, ib;
1119
 
   Int       size;
1120
 
   LockSet   *ret;
1121
 
   const LockSet   *found;
1122
 
 
1123
 
   if (debug || LOCKSET_SANITY)
1124
 
      sanity_check_locksets("intersect-IN");
1125
 
 
1126
 
   if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1127
 
      print_LockSet("intersect a", a);
1128
 
      print_LockSet("intersect b", b);
1129
 
   }
1130
 
 
1131
 
   /* count the size of the new set */
1132
 
   size = 0;
 
1649
static XArray* new_VTS ( void ) {
 
1650
   return VG_(newXA)( hg_zalloc, hg_free, sizeof(ScalarTS) );
 
1651
}
 
1652
static XArray* singleton_VTS ( Thread* thr, UWord tym ) {
 
1653
   ScalarTS st;
 
1654
   XArray*  vts;
 
1655
   tl_assert(thr);
 
1656
   tl_assert(tym >= 1);
 
1657
   vts = new_VTS();
 
1658
   tl_assert(vts);
 
1659
   st.thr = thr;
 
1660
   st.tym = tym;
 
1661
   VG_(addToXA)( vts, &st );
 
1662
   return vts;
 
1663
}
 
1664
 
 
1665
 
 
1666
static Bool cmpGEQ_VTS ( XArray* a, XArray* b )
 
1667
{
 
1668
   Word     ia, ib, useda, usedb;
 
1669
   UWord    tyma, tymb;
 
1670
   Thread*  thr;
 
1671
   ScalarTS *tmpa, *tmpb;
 
1672
 
 
1673
   Bool all_leq = True;
 
1674
   Bool all_geq = True;
 
1675
 
 
1676
   tl_assert(a);
 
1677
   tl_assert(b);
 
1678
   useda = VG_(sizeXA)( a );
 
1679
   usedb = VG_(sizeXA)( b );
 
1680
 
1133
1681
   ia = ib = 0;
1134
 
   for(size = ia = ib = 0; ia < a->setsize && ib < b->setsize; ) {
1135
 
      if (mutex_cmp(a->mutex[ia], b->mutex[ib]) == 0) {
1136
 
         size++;
1137
 
         ia++;
1138
 
         ib++;
1139
 
      } else if (mutex_cmp(a->mutex[ia], b->mutex[ib]) < 0) {
1140
 
         ia++;
1141
 
      } else {
1142
 
         tl_assert(mutex_cmp(a->mutex[ia], b->mutex[ib]) > 0);
1143
 
         ib++;
1144
 
      } 
1145
 
   }
1146
 
 
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];
1153
 
         ia++;
1154
 
         ib++;
1155
 
      } else if (mutex_cmp(a->mutex[ia], b->mutex[ib]) < 0) {
1156
 
         ia++;
1157
 
      } else {
1158
 
         tl_assert(mutex_cmp(a->mutex[ia], b->mutex[ib]) > 0);
1159
 
         ib++;
1160
 
      } 
1161
 
   }
1162
 
 
1163
 
   ret->hash = hash_LockSet(ret);
1164
 
 
1165
 
   /* Now search for it in the table, adding it if not seen before */
1166
 
   found = lookup_LockSet(ret);
1167
 
 
1168
 
   if (found != NULL) {
1169
 
      free_LockSet(ret);
1170
 
   } else {
1171
 
      insert_LockSet(ret);
1172
 
      found = ret;
1173
 
   }
1174
 
 
1175
 
   if (debug || LOCKSET_SANITY) {
1176
 
      print_LockSet("intersect-OUT", found);
1177
 
      sanity_check_locksets("intersect-OUT");
1178
 
   }
1179
 
 
1180
 
   return found;
1181
 
}
1182
 
 
1183
 
/* inline the fastpath */
1184
 
static inline const LockSet *intersect(const LockSet *a, const LockSet *b)
1185
 
{
1186
 
   static const Bool debug = False;
1187
 
 
1188
 
   /* Fast case -- when the two are the same */
1189
 
   if (a == b) {
1190
 
      if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1191
 
         print_LockSet("intersect-same fastpath", a);
1192
 
      }
1193
 
      return a;
1194
 
   }
1195
 
 
1196
 
   if (isempty(a) || isempty(b)) {
1197
 
      if (debug)
1198
 
         VG_(printf)("intersect empty fastpath\n");
1199
 
      return emptyset;
1200
 
   }
1201
 
 
1202
 
   return _intersect(a, b);
1203
 
}
1204
 
 
1205
 
 
1206
 
static const LockSet *ls_union(const LockSet *a, const LockSet *b)
1207
 
{
1208
 
   static const Bool debug = False;
1209
 
   Int       iret;
1210
 
   Int       ia, ib;
1211
 
   Int       size;
1212
 
   LockSet   *ret;
1213
 
   const LockSet   *found;
1214
 
 
1215
 
   if (debug || LOCKSET_SANITY)
1216
 
      sanity_check_locksets("union-IN");
1217
 
 
1218
 
   /* Fast case -- when the two are the same */
1219
 
   if (a == b) {
1220
 
      if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1221
 
         print_LockSet("union-same fastpath", a);
1222
 
      }
1223
 
      return a;
1224
 
   }
1225
 
 
1226
 
   if (isempty(a)) {
1227
 
      if (debug)
1228
 
         print_LockSet("union a=empty b", b);
1229
 
      return b;
1230
 
   }
1231
 
   if (isempty(b)) {
1232
 
      if (debug)
1233
 
         print_LockSet("union b=empty a", a);
1234
 
      return a;
1235
 
   }
1236
 
 
1237
 
   if (debug || DEBUG_MEM_LOCKSET_CHANGES) {
1238
 
      print_LockSet("union a", a);
1239
 
      print_LockSet("union b", b);
1240
 
   }
1241
 
 
1242
 
   /* count the size of the new set */
1243
 
   for(size = ia = ib = 0; (ia < a->setsize) || (ib < b->setsize); ) {
1244
 
      Int cmp;
1245
 
 
1246
 
      if ((ia < a->setsize) && (ib < b->setsize))
1247
 
         cmp = mutex_cmp(a->mutex[ia], b->mutex[ib]);
1248
 
      else if (ia == a->setsize)
1249
 
         cmp = 1;
1250
 
      else 
1251
 
         cmp = -1;
1252
 
 
1253
 
      if (cmp == 0) {
1254
 
         size++;
1255
 
         ia++;
1256
 
         ib++;
1257
 
      } else if (cmp < 0) {
1258
 
         size++;
1259
 
         ia++;
1260
 
      } else {
1261
 
         tl_assert(cmp > 0);
1262
 
         size++;
1263
 
         ib++;
1264
 
      } 
1265
 
   }
1266
 
 
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); ) {
1270
 
      Int cmp;
1271
 
      tl_assert(iret < ret->setsize);
1272
 
 
1273
 
      if ((ia < a->setsize) && (ib < b->setsize))
1274
 
         cmp = mutex_cmp(a->mutex[ia], b->mutex[ib]);
1275
 
      else if (ia == a->setsize)
1276
 
         cmp = 1;
1277
 
      else 
1278
 
         cmp = -1;
1279
 
 
1280
 
      if (cmp == 0) {
1281
 
         ret->mutex[iret++] = a->mutex[ia];
1282
 
         ia++;
1283
 
         ib++;
1284
 
      } else if (cmp < 0) {
1285
 
         ret->mutex[iret++] = a->mutex[ia];
1286
 
         ia++;
1287
 
      } else {
1288
 
         tl_assert(cmp > 0);
1289
 
         ret->mutex[iret++] = b->mutex[ib];
1290
 
         ib++;
1291
 
      } 
1292
 
   }
1293
 
 
1294
 
   tl_assert(iret == ret->setsize);
1295
 
 
1296
 
   ret->hash = hash_LockSet(ret);
1297
 
 
1298
 
   /* Now search for it in the table, adding it if not seen before */
1299
 
   found = lookup_LockSet(ret);
1300
 
 
1301
 
   if (found != NULL) {
1302
 
      if (debug)
1303
 
         print_LockSet("union found existing set", found);
1304
 
      free_LockSet(ret);
1305
 
   } else {
1306
 
      if (debug)
1307
 
         print_LockSet("union inserting new set", ret);
1308
 
      insert_LockSet(ret);
1309
 
      found = ret;
1310
 
   }
1311
 
 
1312
 
   if (debug || LOCKSET_SANITY) {
1313
 
      print_LockSet("union-OUT", found);
1314
 
      sanity_check_locksets("union-OUT");
1315
 
   }
1316
 
 
1317
 
   return found;
1318
 
}
1319
 
 
1320
 
/*------------------------------------------------------------*/
1321
 
/*--- Implementation of mutex structure.                   ---*/
1322
 
/*------------------------------------------------------------*/
1323
 
 
1324
 
static UInt graph_mark;         /* current mark we're using for graph traversal */
1325
 
 
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);
1331
 
 
1332
 
static void set_mutex_state(Mutex *mutex, MutexState state, ThreadId tid);
1333
 
 
1334
 
#define M_MUTEX_HASHSZ  1021
1335
 
 
1336
 
static Mutex *mutex_hash[M_MUTEX_HASHSZ];
1337
 
static UInt total_mutexes;
1338
 
 
1339
 
static const Char *pp_MutexState(MutexState st)
1340
 
{
1341
 
   switch(st) {
1342
 
   case MxLocked:       return "Locked";
1343
 
   case MxUnlocked:     return "Unlocked";
1344
 
   case MxDead:         return "Dead";
1345
 
   case MxUnknown:      return "Unknown";
1346
 
   }
1347
 
   return "???";
1348
 
}
1349
 
 
1350
 
static void pp_all_mutexes(void)
1351
 
{
1352
 
   Int i;
1353
 
   Int locks, buckets;
1354
 
 
1355
 
   locks = buckets = 0;
1356
 
   for(i = 0; i < M_MUTEX_HASHSZ; i++) {
1357
 
      Mutex *mx;
1358
 
      Bool first = True;
1359
 
 
1360
 
      for(mx = mutex_hash[i]; mx != NULL; mx = mx->next) {
1361
 
         if (first) {
1362
 
            buckets++;
1363
 
            VG_(printf)("[%4d] = ", i);
1364
 
         } else
1365
 
            VG_(printf)("         ");
1366
 
         locks++;
1367
 
         first = False;
1368
 
         VG_(printf)("%p [%8s] -> %p%(y\n",
1369
 
                     mx, pp_MutexState(mx->state), mx->mutexp, mx->mutexp);
1370
 
      }
1371
 
   }
1372
 
 
1373
 
   VG_(printf)("%d locks in %d buckets (%d allocated)\n", 
1374
 
               locks, buckets, total_mutexes);
1375
 
}
1376
 
 
1377
 
/* find or create a Mutex for a program's mutex use */
1378
 
static Mutex *get_mutex(Addr mutexp)
1379
 
{
1380
 
   UInt bucket = mutexp % M_MUTEX_HASHSZ;
1381
 
   Mutex *mp;
1382
 
   
1383
 
   for(mp = mutex_hash[bucket]; mp != NULL; mp = mp->next)
1384
 
      if (mp->mutexp == mutexp)
1385
 
         return mp;
1386
 
 
1387
 
   total_mutexes++;
1388
 
 
1389
 
   mp = VG_(malloc)(sizeof(*mp));
1390
 
   mp->mutexp = mutexp;
1391
 
   mp->next = mutex_hash[bucket];
1392
 
   mutex_hash[bucket] = mp;
1393
 
 
1394
 
   mp->state = MxUnknown;
1395
 
   mp->tid = VG_INVALID_THREADID;
1396
 
   mp->location = NULL;
1397
 
 
1398
 
   mp->lockdep = emptyset;
1399
 
   mp->mark = graph_mark - 1;
1400
 
 
1401
 
   return mp;
1402
 
}
1403
 
 
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
1407
 
   LockSet. */
1408
 
static void find_mutex_range(Addr start, Addr end, Bool (*action)(Mutex *))
1409
 
{
1410
 
   UInt first = start % M_MUTEX_HASHSZ;
1411
 
   UInt last = (end+1) % M_MUTEX_HASHSZ;
1412
 
   UInt i;
1413
 
 
1414
 
   /* Single pass over the hash table, looking for likely hashes */
1415
 
   for(i = first; i != last; ) {
1416
 
      Mutex *mx;
1417
 
      Mutex **prev = &mutex_hash[i];
1418
 
 
1419
 
      for(mx = mutex_hash[i]; mx != NULL; prev = &mx->next, mx = mx->next) {
1420
 
         if (mx->mutexp >= start && mx->mutexp < end && (*action)(mx))
1421
 
             *prev = mx->next;
1422
 
      }
1423
 
      
1424
 
      if (++i == M_MUTEX_HASHSZ)
1425
 
         i = 0;
1426
 
   }
1427
 
}
1428
 
 
1429
 
#define MARK_LOOP       (graph_mark+0)
1430
 
#define MARK_DONE       (graph_mark+1)
1431
 
 
1432
 
static Bool check_cycle_inner(const Mutex *mutex, const LockSet *ls)
1433
 
{
1434
 
   static const Bool debug = False;
1435
 
   Int i;
1436
 
 
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 */
1441
 
   
1442
 
   ((Mutex*)mutex)->mark = MARK_LOOP;
1443
 
   
1444
 
   if (debug)
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];
1449
 
     
1450
 
      if (debug)
1451
 
         VG_(printf)("   %y ls=%p (ls->mutex=%p%(y)\n", 
1452
 
                     mutex->mutexp, ls,
1453
 
                     mx->mutexp, mx->mutexp);
1454
 
      if (check_cycle_inner(mx, mx->lockdep))
1455
 
         return True;
1456
 
   }
1457
 
   ((Mutex*)mutex)->mark = MARK_DONE;
1458
 
   
 
1682
 
 
1683
   while (1) {
 
1684
 
 
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);
 
1691
      tmpa = tmpb = NULL;
 
1692
 
 
1693
      if (ia == useda && ib == usedb) {
 
1694
         /* both empty - done */
 
1695
         break;
 
1696
      }
 
1697
      else
 
1698
      if (ia == useda && ib != usedb) {
 
1699
         /* a empty, use up b */
 
1700
         tmpb = VG_(indexXA)( b, ib );
 
1701
         thr  = tmpb->thr;
 
1702
         tyma = 0;
 
1703
         tymb = tmpb->tym;
 
1704
         ib++;
 
1705
      }
 
1706
      else
 
1707
      if (ia != useda && ib == usedb) {
 
1708
         /* b empty, use up a */
 
1709
         tmpa = VG_(indexXA)( a, ia );
 
1710
         thr  = tmpa->thr;
 
1711
         tyma = tmpa->tym;
 
1712
         tymb = 0;
 
1713
         ia++;
 
1714
      }
 
1715
      else {
 
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* */
 
1721
            thr  = tmpa->thr;
 
1722
            tyma = tmpa->tym;
 
1723
            tymb = 0;
 
1724
            ia++;
 
1725
         }
 
1726
         else
 
1727
         if (tmpa->thr > tmpb->thr) {
 
1728
            /* b has the lowest unconsidered Thread* */
 
1729
            thr  = tmpb->thr;
 
1730
            tyma = 0;
 
1731
            tymb = tmpb->tym;
 
1732
            ib++;
 
1733
         } else {
 
1734
            /* they both next mention the same Thread* */
 
1735
            tl_assert(tmpa->thr == tmpb->thr);
 
1736
            thr  = tmpa->thr; /* == tmpb->thr */
 
1737
            tyma = tmpa->tym;
 
1738
            tymb = tmpb->tym;
 
1739
            ia++;
 
1740
            ib++;
 
1741
         }
 
1742
      }
 
1743
 
 
1744
      /* having laboriously determined (thr, tyma, tymb), do something
 
1745
         useful with it. */
 
1746
      if (tyma < tymb)
 
1747
         all_geq = False;
 
1748
      if (tyma > tymb)
 
1749
         all_leq = False;
 
1750
   }
 
1751
 
 
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
 
1755
      both are false. */
 
1756
   if (all_leq)
 
1757
      return False; /* PordLT */
 
1758
   if (all_geq)
 
1759
      return True; /* PordGT */
 
1760
   /* hmm, neither all_geq or all_leq.  This means unordered. */
 
1761
   return False; /* PordUN */
 
1762
}
 
1763
 
 
1764
 
 
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',
 
1767
   assert. */
 
1768
static
 
1769
XArray* tickL_and_joinR_VTS ( Thread* thra, XArray* a, XArray* b )
 
1770
{
 
1771
   Word     ia, ib, useda, usedb, ticks_found;
 
1772
   UWord    tyma, tymb, tymMax;
 
1773
   Thread*  thr;
 
1774
   XArray*  res;
 
1775
   ScalarTS *tmpa, *tmpb;
 
1776
 
 
1777
   tl_assert(a);
 
1778
   tl_assert(b);
 
1779
   tl_assert(thra);
 
1780
   useda = VG_(sizeXA)( a );
 
1781
   usedb = VG_(sizeXA)( b );
 
1782
 
 
1783
   res = new_VTS();
 
1784
   ia = ib = ticks_found = 0;
 
1785
 
 
1786
   while (1) {
 
1787
 
 
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);
 
1794
      tmpa = tmpb = NULL;
 
1795
 
 
1796
      if (ia == useda && ib == usedb) {
 
1797
         /* both empty - done */
 
1798
         break;
 
1799
      }
 
1800
      else
 
1801
      if (ia == useda && ib != usedb) {
 
1802
         /* a empty, use up b */
 
1803
         tmpb = VG_(indexXA)( b, ib );
 
1804
         thr  = tmpb->thr;
 
1805
         tyma = 0;
 
1806
         tymb = tmpb->tym;
 
1807
         ib++;
 
1808
      }
 
1809
      else
 
1810
      if (ia != useda && ib == usedb) {
 
1811
         /* b empty, use up a */
 
1812
         tmpa = VG_(indexXA)( a, ia );
 
1813
         thr  = tmpa->thr;
 
1814
         tyma = tmpa->tym;
 
1815
         tymb = 0;
 
1816
         ia++;
 
1817
      }
 
1818
      else {
 
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* */
 
1824
            thr  = tmpa->thr;
 
1825
            tyma = tmpa->tym;
 
1826
            tymb = 0;
 
1827
            ia++;
 
1828
         }
 
1829
         else
 
1830
         if (tmpa->thr > tmpb->thr) {
 
1831
            /* b has the lowest unconsidered Thread* */
 
1832
            thr  = tmpb->thr;
 
1833
            tyma = 0;
 
1834
            tymb = tmpb->tym;
 
1835
            ib++;
 
1836
         } else {
 
1837
            /* they both next mention the same Thread* */
 
1838
            tl_assert(tmpa->thr == tmpb->thr);
 
1839
            thr  = tmpa->thr; /* == tmpb->thr */
 
1840
            tyma = tmpa->tym;
 
1841
            tymb = tmpb->tym;
 
1842
            ia++;
 
1843
            ib++;
 
1844
         }
 
1845
      }
 
1846
 
 
1847
      /* having laboriously determined (thr, tyma, tymb), do something
 
1848
         useful with it. */
 
1849
      if (thr == thra) {
 
1850
         if (tyma > 0) {
 
1851
            /* VTS 'a' actually supplied this value; it is not a
 
1852
               default zero.  Do the required 'tick' action. */
 
1853
            tyma++;
 
1854
            ticks_found++;
 
1855
         } else {
 
1856
            /* 'a' didn't supply this value, so 'b' must have. */
 
1857
            tl_assert(tymb > 0);
 
1858
         }
 
1859
      }
 
1860
      tymMax = tyma > tymb ? tyma : tymb;
 
1861
      if (tymMax > 0) {
 
1862
         ScalarTS st;
 
1863
         st.thr = thr;
 
1864
         st.tym = tymMax;
 
1865
         VG_(addToXA)( res, &st );
 
1866
      }
 
1867
 
 
1868
   }
 
1869
 
 
1870
   tl_assert(is_sane_VTS( res ));
 
1871
 
 
1872
   if (thra != NULL) {
 
1873
      tl_assert(ticks_found == 1);
 
1874
   } else {
 
1875
      tl_assert(ticks_found == 0);
 
1876
   }
 
1877
 
 
1878
   return res;
 
1879
}
 
1880
 
 
1881
 
 
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. */
 
1884
 
 
1885
static XArray* tick_VTS ( Thread* me, XArray* vts ) {
 
1886
   ScalarTS* here = NULL;
 
1887
   ScalarTS  tmp;
 
1888
   XArray*   res;
 
1889
   Word      i, n; 
 
1890
   tl_assert(me);
 
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) );
 
1894
   res = new_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. */
 
1900
         tmp.thr = me;
 
1901
         tmp.tym = 1;
 
1902
         VG_(addToXA)( res, &tmp );
 
1903
         tmp = *here;
 
1904
         VG_(addToXA)( res, &tmp );
 
1905
         i++;
 
1906
         break;
 
1907
      } 
 
1908
      else if (me == here->thr) {
 
1909
         tmp = *here;
 
1910
         tmp.tym++;
 
1911
         VG_(addToXA)( res, &tmp );
 
1912
         i++;
 
1913
         break;
 
1914
      }
 
1915
      else /* me > here->thr */ {
 
1916
         tmp = *here;
 
1917
         VG_(addToXA)( res, &tmp );
 
1918
      }
 
1919
   }
 
1920
   tl_assert(i >= 0 && i <= n);
 
1921
   if (i == n && here && here->thr < me) {
 
1922
      tmp.thr = me;
 
1923
      tmp.tym = 1;
 
1924
      VG_(addToXA)( res, &tmp );
 
1925
   } else {
 
1926
      for (/*keepgoing*/; i < n; i++) {
 
1927
         here = VG_(indexXA)( vts, i );
 
1928
         tmp = *here;
 
1929
         VG_(addToXA)( res, &tmp );
 
1930
      }
 
1931
   }
 
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) );
 
1935
   return res;
 
1936
}
 
1937
 
 
1938
static void show_VTS ( HChar* buf, Int nBuf, XArray* vts ) {
 
1939
   ScalarTS* st;
 
1940
   HChar     unit[64];
 
1941
   Word      i, n;
 
1942
   Int       avail = nBuf;
 
1943
   tl_assert(avail > 16);
 
1944
   buf[0] = '[';
 
1945
   buf[1] = 0;
 
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, " ...]");
 
1955
         return;
 
1956
      }
 
1957
      VG_(strcat)(buf, unit);
 
1958
      avail -= VG_(strlen)(unit);
 
1959
   }
 
1960
   VG_(strcat)(buf, "]");
 
1961
}
 
1962
 
 
1963
 
 
1964
/*------------ searching the happens-before graph ------------*/
 
1965
 
 
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
 
1974
 
 
1975
/* Running marker for depth-first searches */
 
1976
/* NOTE: global variable */
 
1977
static UInt dfsver_current = 0;
 
1978
 
 
1979
/* A stack of possibly-unexplored nodes used in the depth first search */
 
1980
/* NOTE: global variable */
 
1981
static XArray* dfsver_stack = NULL;
 
1982
 
 
1983
// FIXME: check this - is it really correct?
 
1984
__attribute__((noinline))
 
1985
static Bool happens_before_do_dfs_from_to ( Segment* src, Segment* dst )
 
1986
{
 
1987
   Segment* here;
 
1988
   Word     ssz;
 
1989
 
 
1990
   /* begin SPEEDUP HACK -- the following can safely be omitted */
 
1991
   /* fast track common case, without favouring either the
 
1992
      ->prev or ->other links */
 
1993
   tl_assert(src);
 
1994
   tl_assert(dst);
 
1995
   if ((src->prev && src->prev == dst)
 
1996
       || (src->other && src->other == dst)) {
 
1997
      stats__hbefore_gsearchFs++;
 
1998
      return True;
 
1999
   }
 
2000
   /* end SPEEDUP HACK */
 
2001
 
 
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);
 
2006
 
 
2007
   /* push starting point */
 
2008
   (void) VG_(addToXA)( dfsver_stack, &src );
 
2009
 
 
2010
   while (True) {
 
2011
      /* While the stack is not empty, pop the next node off it and
 
2012
         consider. */
 
2013
      ssz = VG_(sizeXA)( dfsver_stack );
 
2014
      tl_assert(ssz >= 0);
 
2015
      if (ssz == 0)
 
2016
         return False; /* stack empty ==> no path from src to dst */
 
2017
 
 
2018
      if (UNLIKELY( ((UWord)ssz) > stats__hbefore_stk_hwm ))
 
2019
         stats__hbefore_stk_hwm = (UWord)ssz;
 
2020
 
 
2021
      /* here = pop(stack) */
 
2022
      here = *(Segment**) VG_(indexXA)( dfsver_stack, ssz-1 );
 
2023
      VG_(dropTailXA)( dfsver_stack, 1 );
 
2024
 
 
2025
     again:
 
2026
      /* consider the node 'here' */
 
2027
      if (here == dst)
 
2028
         return True; /* found a path from src and dst */
 
2029
 
 
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*/
 
2034
 
 
2035
      /* Mark that we've been here */
 
2036
      here->dfsver = dfsver_current;
 
2037
 
 
2038
      /* Now push both children on the stack */
 
2039
 
 
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) {
 
2045
         here = here->prev;
 
2046
         goto again;
 
2047
      }
 
2048
      if (here->other && !here->prev) {
 
2049
         here = here->other;
 
2050
         goto again;
 
2051
      }
 
2052
      /* end of SPEEDUP HACK */
 
2053
 
 
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. */
 
2058
      if (here->prev)
 
2059
         (void) VG_(addToXA)( dfsver_stack, &(here->prev) );
 
2060
      if (here->other)
 
2061
         (void) VG_(addToXA)( dfsver_stack, &(here->other) );
 
2062
   }
 
2063
}
 
2064
 
 
2065
__attribute__((noinline))
 
2066
static Bool happens_before_wrk ( Segment* seg1, Segment* seg2 )
 
2067
{
 
2068
   Bool reachable;
 
2069
 
 
2070
   { static Int nnn = 0;
 
2071
     if (SHOW_EXPENSIVE_STUFF && (nnn++ % 1000) == 0)
 
2072
        VG_(printf)("happens_before_wrk: %d\n", nnn);
 
2073
   }
 
2074
 
 
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);
 
2078
   dfsver_current++;
 
2079
   
 
2080
   if (dfsver_stack == NULL) {
 
2081
     dfsver_stack = VG_(newXA)( hg_zalloc, hg_free, sizeof(Segment*) );
 
2082
     tl_assert(dfsver_stack);
 
2083
   }
 
2084
 
 
2085
   reachable = happens_before_do_dfs_from_to( seg2, seg1 );
 
2086
 
 
2087
   return reachable;
 
2088
}
 
2089
 
 
2090
/*--------------- the happens_before cache ---------------*/
 
2091
 
 
2092
#define HBEFORE__N_CACHE 64
 
2093
typedef 
 
2094
   struct { SegmentID segid1; SegmentID segid2; Bool result; } 
 
2095
   HBeforeCacheEnt;
 
2096
 
 
2097
static HBeforeCacheEnt hbefore__cache[HBEFORE__N_CACHE];
 
2098
 
 
2099
static void hbefore__invalidate_cache ( void ) 
 
2100
{
 
2101
   Int i;
 
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;
 
2109
   }
 
2110
}
 
2111
 
 
2112
static Bool happens_before ( SegmentID segid1, SegmentID segid2 )
 
2113
{
 
2114
   Bool    hbG, hbV;
 
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;
 
2126
   }
 
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++;
 
2136
         return tmp.result;
 
2137
      }
 
2138
   }
 
2139
   /* Not found.  Search the graph and add an entry to the cache. */
 
2140
   stats__hbefore_gsearches++;
 
2141
 
 
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);
 
2149
 
 
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
 
2154
         slow. */
 
2155
      hbG = happens_before_wrk( seg1, seg2 );
 
2156
   } else {
 
2157
      /* Assume the vector-timestamp comparison result is correct, and
 
2158
         use it as-is. */
 
2159
      hbG = hbV;
 
2160
   }
 
2161
 
 
2162
   if (hbV != hbG) {
 
2163
      VG_(printf)("seg1 %p  seg2 %p  hbV %d  hbG %d\n", 
 
2164
                  seg1,seg2,(Int)hbV,(Int)hbG);
 
2165
      segments__generate_vcg();
 
2166
   }
 
2167
   tl_assert(hbV == hbG);
 
2168
 
 
2169
   iNSERT_POINT = (1*HBEFORE__N_CACHE)/4 - 1;
 
2170
   /* if (iNSERT_POINT > 4) iNSERT_POINT = 4; */
 
2171
 
 
2172
   for (j = HBEFORE__N_CACHE-1; j > iNSERT_POINT; j--) {
 
2173
      hbefore__cache[j] = hbefore__cache[j-1];
 
2174
   }
 
2175
   hbefore__cache[iNSERT_POINT].segid1 = segid1;
 
2176
   hbefore__cache[iNSERT_POINT].segid2 = segid2;
 
2177
   hbefore__cache[iNSERT_POINT].result = hbG;
 
2178
 
 
2179
   if (0)
 
2180
   VG_(printf)("hb %d %d\n", (Int)segid1-(1<<24), (Int)segid2-(1<<24));
 
2181
   return hbG;
 
2182
}
 
2183
 
 
2184
/*--------------- generating .vcg output ---------------*/
 
2185
 
 
2186
static void segments__generate_vcg ( void )
 
2187
{
 
2188
#define PFX "xxxxxx"
 
2189
   /* Edge colours:
 
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
 
2195
   */
 
2196
   Segment* seg;
 
2197
   HChar vtsstr[128];
 
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) {
 
2206
 
 
2207
      VG_(printf)(PFX "node: { title: \"%p\" color: lightcyan "
 
2208
                  "textcolor: darkgreen label: \"Seg %p\\n", 
 
2209
                  seg, seg);
 
2210
      if (seg->thr->errmsg_index == 1) {
 
2211
         VG_(printf)("ROOT_THREAD");
 
2212
      } else {
 
2213
         VG_(printf)("Thr# %d", seg->thr->errmsg_index);
 
2214
      }
 
2215
 
 
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);
 
2220
      }
 
2221
 
 
2222
      VG_(printf)("\" }\n", vtsstr);
 
2223
 
 
2224
      if (seg->prev)
 
2225
         VG_(printf)(PFX "edge: { sourcename: \"%p\" targetname: \"%p\""
 
2226
                     "color: black }\n", seg->prev, seg );
 
2227
      if (seg->other) {
 
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);
 
2236
         }
 
2237
         VG_(printf)(PFX "edge: { sourcename: \"%p\" targetname: \"%p\""
 
2238
                     " color: %s }\n", seg->other, seg, colour );
 
2239
      }
 
2240
   }
 
2241
   VG_(printf)(PFX "}\n");
 
2242
#undef PFX
 
2243
}
 
2244
 
 
2245
 
 
2246
/*----------------------------------------------------------------*/
 
2247
/*--- map_shmem :: WordFM Addr SecMap                          ---*/
 
2248
/*--- shadow memory (low level handlers) (shmem__* fns)        ---*/
 
2249
/*----------------------------------------------------------------*/
 
2250
 
 
2251
 
 
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
 
2288
 
 
2289
 
 
2290
static SVal shadow_mem_get8 ( Addr a ); /* fwds */
 
2291
 
 
2292
static inline Addr shmem__round_to_SecMap_base ( Addr a ) {
 
2293
   return a & ~(N_SECMAP_ARANGE - 1);
 
2294
}
 
2295
static inline UWord shmem__get_SecMap_offset ( Addr a ) {
 
2296
   return a & (N_SECMAP_ARANGE - 1);
 
2297
}
 
2298
 
 
2299
/*--------------- SecMap allocation --------------- */
 
2300
 
 
2301
static HChar* shmem__bigchunk_next = NULL;
 
2302
static HChar* shmem__bigchunk_end1 = NULL;
 
2303
 
 
2304
static void* shmem__bigchunk_alloc ( SizeT n )
 
2305
{
 
2306
   const SizeT sHMEM__BIGCHUNK_SIZE = 4096 * 256;
 
2307
   tl_assert(n > 0);
 
2308
   n = ROUNDUP(n, 16);
 
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) {
 
2313
      if (0)
 
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;
 
2318
   }
 
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;
 
2324
}
 
2325
 
 
2326
static SecMap* shmem__alloc_SecMap ( void )
 
2327
{
 
2328
   Word    i, j;
 
2329
   SecMap* sm = shmem__bigchunk_alloc( sizeof(SecMap) );
 
2330
   if (0) VG_(printf)("alloc_SecMap %p\n",sm);
 
2331
   tl_assert(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] */
 
2342
   }
 
2343
   sm->linesF      = NULL;
 
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);
 
2349
   return sm;
 
2350
}
 
2351
 
 
2352
static SecMap* shmem__find_or_alloc_SecMap ( Addr ga )
 
2353
{
 
2354
   SecMap* sm    = NULL;
 
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 */
 
2359
      tl_assert(sm);
 
2360
   } else {
 
2361
      /* create a new one */
 
2362
      sm = shmem__alloc_SecMap();
 
2363
      tl_assert(sm);
 
2364
      HG_(addToFM)( map_shmem, (Word)gaKey, (Word)sm );
 
2365
   }
 
2366
   return sm;
 
2367
}
 
2368
 
 
2369
 
 
2370
/*--------------- cache management/lookup --------------- */
 
2371
 
 
2372
/*--------------- misc --------------- */
 
2373
 
 
2374
static Bool shmem__get_mbHasLocks ( Addr a )
 
2375
{
 
2376
   SecMap* sm;
 
2377
   Addr aKey = shmem__round_to_SecMap_base(a);
 
2378
   if (HG_(lookupFM)( map_shmem,
 
2379
                      NULL/*keyP*/, (Word*)&sm, (Word)aKey )) {
 
2380
      /* Found */
 
2381
      return sm->mbHasLocks;
 
2382
   } else {
 
2383
      return False;
 
2384
   }
 
2385
}
 
2386
 
 
2387
static void shmem__set_mbHasLocks ( Addr a, Bool b )
 
2388
{
 
2389
   SecMap* sm;
 
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 */
 
2395
   } else {
 
2396
      /* create a new one */
 
2397
      sm = shmem__alloc_SecMap();
 
2398
      tl_assert(sm);
 
2399
      HG_(addToFM)( map_shmem, (Word)aKey, (Word)sm );
 
2400
   }
 
2401
   sm->mbHasLocks = b;
 
2402
}
 
2403
 
 
2404
static void shmem__set_mbHasShared ( Addr a, Bool b )
 
2405
{
 
2406
   SecMap* sm;
 
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 */
 
2412
   } else {
 
2413
      /* create a new one */
 
2414
      sm = shmem__alloc_SecMap();
 
2415
      tl_assert(sm);
 
2416
      HG_(addToFM)( map_shmem, (Word)aKey, (Word)sm );
 
2417
   }
 
2418
   sm->mbHasShared = b;
 
2419
}
 
2420
 
 
2421
 
 
2422
/*----------------------------------------------------------------*/
 
2423
/*--- Sanity checking the data structures                      ---*/
 
2424
/*----------------------------------------------------------------*/
 
2425
 
 
2426
static UWord stats__sanity_checks = 0;
 
2427
 
 
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 */
 
2431
 
 
2432
/* REQUIRED INVARIANTS:
 
2433
 
 
2434
   Thread vs Segment/Lock/SecMaps
 
2435
 
 
2436
      for each t in Threads {
 
2437
 
 
2438
         // Thread.lockset: each element is really a valid Lock
 
2439
 
 
2440
         // Thread.lockset: each Lock in set is actually held by that thread
 
2441
         for lk in Thread.lockset 
 
2442
            lk == LockedBy(t)
 
2443
 
 
2444
         // Thread.csegid is a valid SegmentID
 
2445
         // and the associated Segment has .thr == t
 
2446
 
 
2447
      }
 
2448
 
 
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
 
2452
      owner threads
 
2453
 
 
2454
   Lock vs Thread/Segment/SecMaps
 
2455
 
 
2456
      for each entry (gla, la) in map_locks
 
2457
         gla == la->guest_addr
 
2458
 
 
2459
      for each lk in Locks {
 
2460
 
 
2461
         lk->tag is valid
 
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)
 
2468
 
 
2469
         secmaps for lk has .mbHasLocks == True
 
2470
 
 
2471
      }
 
2472
 
 
2473
   Segment vs Thread/Lock/SecMaps
 
2474
 
 
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
 
2478
 
 
2479
      for seg in Segments {
 
2480
 
 
2481
         seg->thr is a sane Thread
 
2482
 
 
2483
      }
 
2484
 
 
2485
   SecMaps vs Segment/Thread/Lock
 
2486
 
 
2487
      for sm in SecMaps {
 
2488
 
 
2489
         sm properly aligned
 
2490
         if any shadow word is ShR or ShM then .mbHasShared == True
 
2491
 
 
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
 
2497
 
 
2498
      }
 
2499
*/
 
2500
 
 
2501
 
 
2502
/* Return True iff 'thr' holds 'lk' in some mode. */
 
2503
static Bool thread_is_a_holder_of_Lock ( Thread* thr, Lock* lk )
 
2504
{
 
2505
   if (lk->heldBy)
 
2506
      return HG_(elemBag)( lk->heldBy, (Word)thr ) > 0;
 
2507
   else
 
2508
      return False;
 
2509
}
 
2510
 
 
2511
/* Sanity check Threads, as far as possible */
 
2512
__attribute__((noinline))
 
2513
static void threads__sanity_check ( Char* who )
 
2514
{
 
2515
#define BAD(_str) do { how = (_str); goto bad; } while (0)
 
2516
   Char*     how = "no error";
 
2517
   Thread*   thr;
 
2518
   WordSetID wsA, wsW;
 
2519
   Word*     ls_words;
 
2520
   Word      ls_size, i;
 
2521
   Lock*     lk;
 
2522
   Segment*  seg;
 
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
 
2535
         // thread
 
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");
 
2543
      }
 
2544
   }
 
2545
   return;
 
2546
  bad:
 
2547
   VG_(printf)("threads__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how);
 
2548
   tl_assert(0);
 
2549
#undef BAD
 
2550
}
 
2551
 
 
2552
 
 
2553
/* Sanity check Locks, as far as possible */
 
2554
__attribute__((noinline))
 
2555
static void locks__sanity_check ( Char* who )
 
2556
{
 
2557
#define BAD(_str) do { how = (_str); goto bad; } while (0)
 
2558
   Char*     how = "no error";
 
2559
   Addr      gla;
 
2560
   Lock*     lk;
 
2561
   Int       i;
 
2562
   // # entries in admin_locks == # entries in map_locks
 
2563
   for (i = 0, lk = admin_locks;  lk;  i++, lk = lk->admin)
 
2564
      ;
 
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");
 
2572
   }
 
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.
 
2588
      if (lk->heldBy) {
 
2589
         Thread* thr;
 
2590
         Word    count;
 
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)) 
 
2598
               BAD("6");
 
2599
            // also check the w-only lockset
 
2600
            if (lk->heldW 
 
2601
                && !HG_(elemWS)(univ_lsets, thr->locksetW, (Word)lk)) 
 
2602
               BAD("7");
 
2603
            if ((!lk->heldW)
 
2604
                && HG_(elemWS)(univ_lsets, thr->locksetW, (Word)lk)) 
 
2605
               BAD("8");
 
2606
         }
 
2607
         HG_(doneIterBag)( lk->heldBy );
 
2608
      } else {
 
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.
 
2613
      }
 
2614
      // secmaps for lk has .mbHasLocks == True
 
2615
      if (!shmem__get_mbHasLocks(lk->guestaddr)) BAD("10");
 
2616
   }
 
2617
 
 
2618
   return;
 
2619
  bad:
 
2620
   VG_(printf)("locks__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how);
 
2621
   tl_assert(0);
 
2622
#undef BAD
 
2623
}
 
2624
 
 
2625
 
 
2626
/* Sanity check Segments, as far as possible */
 
2627
__attribute__((noinline))
 
2628
static void segments__sanity_check ( Char* who )
 
2629
{
 
2630
#define BAD(_str) do { how = (_str); goto bad; } while (0)
 
2631
   Char*    how = "no error";
 
2632
   Int      i;
 
2633
   Segment* seg;
 
2634
   // FIXME
 
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)
 
2640
      ;
 
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))
 
2649
         BAD("5");
 
2650
      if (seg->other && seg->other->vts
 
2651
          && !cmpGEQ_VTS(seg->vts, seg->other->vts))
 
2652
         BAD("6");
 
2653
   }
 
2654
   return;
 
2655
  bad:
 
2656
   VG_(printf)("segments__sanity_check: who=\"%s\", bad=\"%s\"\n", 
 
2657
               who, how);
 
2658
   tl_assert(0);
 
2659
#undef BAD
 
2660
}
 
2661
 
 
2662
 
 
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;
 
2669
   return 0;
 
2670
}
 
2671
__attribute__((noinline))
 
2672
static void shmem__sanity_check ( Char* who )
 
2673
{
 
2674
#define BAD(_str) do { how = (_str); goto bad; } while (0)
 
2675
   Char*   how = "no error";
 
2676
   Word    smga;
 
2677
   SecMap* sm;
 
2678
   Word    i, j, ws_size, n_valid_tags;
 
2679
   Word*   ws_words;
 
2680
   Addr*   valid_tags;
 
2681
   HG_(initIterFM)( map_shmem );
 
2682
   // for sm in SecMaps {
 
2683
   while (HG_(nextIterFM)( map_shmem,
 
2684
                           (Word*)&smga, (Word*)&sm )) {
 
2685
      SecMapIter itr;
 
2686
      SVal*      w32p = NULL;
 
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 )) {
 
2695
         SVal w32 = *w32p;
 
2696
         if (is_SHVAL_Sh(w32)) 
 
2697
            mbHasShared = True;
 
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)
 
2703
            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");
 
2708
         } 
 
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");
 
2723
            }
 
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");
 
2730
            }
 
2731
         }
 
2732
         else if (is_SHVAL_NoAccess(w32) || is_SHVAL_New(w32)) {
 
2733
            /* nothing to check */
 
2734
         }
 
2735
         else {
 
2736
            /* bogus shadow mem value */
 
2737
            BAD("12");
 
2738
         }
 
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");
 
2746
   }
 
2747
   HG_(doneIterFM)( map_shmem );
 
2748
 
 
2749
   // check the cache
 
2750
   valid_tags   = hg_zalloc(N_WAY_NENT * sizeof(Addr));
 
2751
   n_valid_tags = 0;
 
2752
   tl_assert(valid_tags);
 
2753
   for (i = 0; i < N_WAY_NENT; i++) {
 
2754
      CacheLine* cl;
 
2755
      Addr       tag; 
 
2756
      /* way0, dude */
 
2757
      cl  = &cache_shmem.lyns0[i];
 
2758
      tag =  cache_shmem.tags0[i];
 
2759
      if (tag != 1) {
 
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;
 
2767
      }
 
2768
   }
 
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])
 
2775
            BAD("16-2");
 
2776
      }
 
2777
   }
 
2778
   hg_free(valid_tags);
 
2779
   return;
 
2780
  bad:
 
2781
   VG_(printf)("shmem__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how);
 
2782
   tl_assert(0);
 
2783
#undef BAD
 
2784
}
 
2785
 
 
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);
 
2793
}
 
2794
static void all__sanity_check ( Char* who ) {
 
2795
   all_except_Locks__sanity_check(who);
 
2796
   locks__sanity_check(who);
 
2797
}
 
2798
 
 
2799
 
 
2800
/*----------------------------------------------------------------*/
 
2801
/*--- the core memory state machine (msm__* functions)         ---*/
 
2802
/*----------------------------------------------------------------*/
 
2803
 
 
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;
 
2811
 
 
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;
 
2819
 
 
2820
/* fwds */
 
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 );
 
2825
 
 
2826
static void record_error_FreeMemLock ( Thread* thr, Lock* lk );
 
2827
 
 
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* );
 
2834
 
 
2835
static void record_error_Misc ( Thread*, HChar* );
 
2836
static void announce_one_thread ( Thread* thr ); /* fwds */
 
2837
 
 
2838
static WordSetID add_BHL ( WordSetID lockset ) {
 
2839
   return HG_(addToWS)( univ_lsets, lockset, (Word)__bus_lock_Lock );
 
2840
}
 
2841
static WordSetID del_BHL ( WordSetID lockset ) {
 
2842
   return HG_(delFromWS)( univ_lsets, lockset, (Word)__bus_lock_Lock );
 
2843
}
 
2844
 
 
2845
 
 
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.
 
2856
 
 
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
 
2865
   transition to ShM.
 
2866
 
 
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.
 
2873
 
 
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.
 
2876
*/
 
2877
 
 
2878
static UWord stats__ga_LL_adds = 0;
 
2879
 
 
2880
static WordFM* ga_to_lastlock = NULL; /* GuestAddr -> ExeContext* */
 
2881
 
 
2882
static 
 
2883
void record_last_lock_lossage ( Addr ga_of_access,
 
2884
                                WordSetID lset_old, WordSetID lset_new )
 
2885
{
 
2886
   Lock* lk;
 
2887
   Int   card_old, card_new;
 
2888
 
 
2889
   tl_assert(lset_old != lset_new);
 
2890
 
 
2891
   if (0) VG_(printf)("XX1: %d (card %d) -> %d (card %d) %p\n", 
 
2892
                      (Int)lset_old, 
 
2893
                      HG_(cardinalityWS)(univ_lsets,lset_old),
 
2894
                      (Int)lset_new, 
 
2895
                      HG_(cardinalityWS)(univ_lsets,lset_new),
 
2896
                      ga_of_access );
 
2897
 
 
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 );
 
2902
 
 
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. */
 
2907
      return;
 
2908
   }
 
2909
 
 
2910
   /* lset_new is now empty */
 
2911
   card_new = HG_(cardinalityWS)( univ_lsets, lset_new );
 
2912
   tl_assert(card_new == 0);
 
2913
 
 
2914
   lset_old = del_BHL( lset_old );
 
2915
   card_old = HG_(cardinalityWS)( univ_lsets, lset_old );
 
2916
 
 
2917
   if (0) VG_(printf)(" X2: %d (card %d) -> %d (card %d)\n",
 
2918
                      (Int)lset_old, card_old, (Int)lset_new, card_new );
 
2919
 
 
2920
   if (card_old == 0) {
 
2921
      /* The old lockset was also empty.  Not interesting. */
 
2922
      return;
 
2923
   }
 
2924
 
 
2925
   tl_assert(card_old > 0);
 
2926
   tl_assert(!HG_(isEmptyWS)( univ_lsets, lset_old ));
 
2927
 
 
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
 
2932
      it's simple. */
 
2933
 
 
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++;
 
2942
   }
 
2943
}
 
2944
 
 
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'. */
 
2949
 
 
2950
static ExeContext* maybe_get_lastlock_initpoint ( Addr ga ) 
 
2951
{
 
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);
 
2957
      return ec_hint;
 
2958
   } else {
 
2959
      return NULL;
 
2960
   }
 
2961
}
 
2962
 
 
2963
 
 
2964
static void msm__show_state_change ( Thread* thr_acc, Addr a, Int szB,
 
2965
                                     Char howC,
 
2966
                                     SVal sv_old, SVal sv_new )
 
2967
{
 
2968
   ThreadId tid;
 
2969
   UChar txt_old[100], txt_new[100];
 
2970
   Char* how = "";
 
2971
   tl_assert(is_sane_Thread(thr_acc));
 
2972
   tl_assert(clo_trace_level == 1 || clo_trace_level == 2);
 
2973
   switch (howC) {
 
2974
      case 'r': how = "rd"; break;
 
2975
      case 'w': how = "wr"; break;
 
2976
      case 'p': how = "pa"; break;
 
2977
      default: tl_assert(0);
 
2978
   }
 
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 );
 
2993
      }
 
2994
   } else {
 
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 );
 
2999
   }
 
3000
}
 
3001
 
 
3002
 
 
3003
/* Here are some MSM stats from startup/shutdown of OpenOffice.
 
3004
 
 
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
 
3012
 
 
3013
   This says how the clauses should be ordered for greatest speed:
 
3014
 
 
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
 
3018
     comparison.
 
3019
 
 
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
 
3024
     insignificant. */
 
3025
 
 
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. */
 
3032
static
 
3033
SVal msm__handle_read ( Thread* thr_acc, Addr a, SVal wold, Int szB )
 
3034
{
 
3035
   SVal wnew = SHVAL_Invalid;
 
3036
 
 
3037
   tl_assert(is_sane_Thread(thr_acc));
 
3038
 
 
3039
   if (0) VG_(printf)("read thr=%p %p\n", thr_acc, a);
 
3040
 
 
3041
   /* Exclusive */
 
3042
   if (LIKELY(is_SHVAL_Excl(wold))) {
 
3043
      /* read Excl(segid) 
 
3044
           |  segid_old == segid-of-thread
 
3045
           -> no change
 
3046
           |  segid_old `happens_before` segid-of-this-thread
 
3047
           -> Excl(segid-of-this-thread)
 
3048
           |  otherwise
 
3049
           -> ShR
 
3050
      */
 
3051
      SegmentID segid_old = un_SHVAL_Excl(wold);
 
3052
      tl_assert(is_sane_SegmentID(segid_old));
 
3053
      if (LIKELY(segid_old == thr_acc->csegid)) {
 
3054
         /* no change */
 
3055
         stats__msm_read_Excl_nochange++;
 
3056
         /*NOCHANGE*/return wold;
 
3057
      }
 
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++;
 
3062
         goto changed;
 
3063
      }
 
3064
      /* else */ {
 
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++;
 
3077
         goto changed;
 
3078
      }
 
3079
      /*NOTREACHED*/
 
3080
   } 
 
3081
 
 
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,
 
3093
                                             lset_old, 
 
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++;
 
3100
      goto changed;
 
3101
   }
 
3102
 
 
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,
 
3114
                                             lset_old,
 
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) );
 
3125
      }
 
3126
      stats__msm_read_ShM_to_ShM++;
 
3127
      goto changed;
 
3128
   }
 
3129
 
 
3130
   /* New */
 
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++;
 
3135
      goto changed;
 
3136
   } 
 
3137
 
 
3138
   /* NoAccess */
 
3139
   if (is_SHVAL_NoAccess(wold)) {
 
3140
      // FIXME: complain if accessing here
 
3141
      // FIXME: transition to Excl?
 
3142
      if (0)
 
3143
      VG_(printf)(
 
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 */
 
3148
   }
 
3149
 
 
3150
   /* hmm, bogus state */
 
3151
   tl_assert(0);
 
3152
 
 
3153
  changed:
 
3154
   if (UNLIKELY(clo_trace_level > 0)) {
 
3155
      if (a <= clo_trace_addr && clo_trace_addr < a+szB
 
3156
          && wold != wnew) {
 
3157
         msm__show_state_change( thr_acc, a, szB, 'r', wold, wnew );
 
3158
      }
 
3159
   }
 
3160
   return wnew;
 
3161
}
 
3162
 
 
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. */
 
3166
static
 
3167
SVal msm__handle_write ( Thread* thr_acc, Addr a, SVal wold, Int szB )
 
3168
{
 
3169
   SVal wnew = SHVAL_Invalid;
 
3170
 
 
3171
   tl_assert(is_sane_Thread(thr_acc));
 
3172
 
 
3173
   if (0) VG_(printf)("write32 thr=%p %p\n", thr_acc, a);
 
3174
 
 
3175
   /* New */
 
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++;
 
3180
      goto changed;
 
3181
   }
 
3182
 
 
3183
   /* Exclusive */
 
3184
   if (is_SHVAL_Excl(wold)) {
 
3185
      // I believe is identical to case for read Excl
 
3186
      // apart from enters ShM rather than ShR 
 
3187
      /* read Excl(segid) 
 
3188
           |  segid_old == segid-of-thread
 
3189
           -> no change
 
3190
           |  segid_old `happens_before` segid-of-this-thread
 
3191
           -> Excl(segid-of-this-thread)
 
3192
           |  otherwise
 
3193
           -> ShM
 
3194
      */
 
3195
      SegmentID segid_old = un_SHVAL_Excl(wold);
 
3196
      tl_assert(is_sane_SegmentID(segid_old));
 
3197
      if (segid_old == thr_acc->csegid) {
 
3198
         /* no change */
 
3199
         stats__msm_write_Excl_nochange++;
 
3200
         /*NOCHANGE*/return wold;
 
3201
      }
 
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++;
 
3206
         goto changed;
 
3207
      }
 
3208
      /* else */ {
 
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) );
 
3224
         }
 
3225
         stats__msm_write_Excl_to_ShM++;
 
3226
         goto changed;
 
3227
      }
 
3228
      /*NOTREACHED*/
 
3229
   } 
 
3230
 
 
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)(
 
3242
                              univ_lsets, 
 
3243
                              lset_old, 
 
3244
                              thr_acc->locksetW
 
3245
                              /* write ==> use only w-held locks */
 
3246
                           );
 
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) );
 
3254
      }
 
3255
      stats__msm_write_ShR_to_ShM++;
 
3256
      goto changed;
 
3257
   }
 
3258
 
 
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)( 
 
3270
                              univ_lsets,
 
3271
                              lset_old, 
 
3272
                              thr_acc->locksetW 
 
3273
                              /* write ==> use only w-held locks */
 
3274
                           ); 
 
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) );
 
3283
      }
 
3284
      stats__msm_write_ShM_to_ShM++;
 
3285
      goto changed;
 
3286
   }
 
3287
 
 
3288
   /* NoAccess */
 
3289
   if (is_SHVAL_NoAccess(wold)) {
 
3290
      // FIXME: complain if accessing here
 
3291
      // FIXME: transition to Excl?
 
3292
      if (0)
 
3293
      VG_(printf)(
 
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;
 
3298
   } 
 
3299
 
 
3300
   /* hmm, bogus state */
 
3301
   VG_(printf)("msm__handle_write_aligned_32: bogus old state 0x%x\n", 
 
3302
               wold);
 
3303
   tl_assert(0);
 
3304
 
 
3305
  changed:
 
3306
   if (UNLIKELY(clo_trace_level > 0)) {
 
3307
      if (a <= clo_trace_addr && clo_trace_addr < a+szB
 
3308
          && wold != wnew) {
 
3309
         msm__show_state_change( thr_acc, a, szB, 'w', wold, wnew );
 
3310
      }
 
3311
   }
 
3312
   return wnew;
 
3313
}
 
3314
 
 
3315
 
 
3316
/*----------------------------------------------------------------*/
 
3317
/*--- Shadow value and address range handlers                  ---*/
 
3318
/*----------------------------------------------------------------*/
 
3319
 
 
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 */
 
3323
 
 
3324
/* ------------ CacheLineF and CacheLineZ related ------------ */
 
3325
 
 
3326
static void write_twobit_array ( UChar* arr, UWord ix, UWord b2 ) {
 
3327
   Word bix, shft, mask, prep;
 
3328
   tl_assert((b2 & ~3) == 0);
 
3329
   tl_assert(ix >= 0);
 
3330
   bix  = ix >> 2;
 
3331
   shft = 2 * (ix & 3); /* 0, 2, 4 or 6 */
 
3332
   mask = 3 << shft;
 
3333
   prep = b2 << shft;
 
3334
   arr[bix] = (arr[bix] & ~mask) | prep;
 
3335
}
 
3336
 
 
3337
static UWord read_twobit_array ( UChar* arr, UWord ix ) {
 
3338
   Word bix, shft;
 
3339
   tl_assert(ix >= 0);
 
3340
   bix  = ix >> 2;
 
3341
   shft = 2 * (ix & 3); /* 0, 2, 4 or 6 */
 
3342
   return (arr[bix] >> shft) & 3;
 
3343
}
 
3344
 
 
3345
/* Given a lineZ index and a SecMap, return the CacheLineZ* and CacheLineF*
 
3346
   for that index. */
 
3347
static void get_ZF_by_index ( /*OUT*/CacheLineZ** zp,
 
3348
                              /*OUT*/CacheLineF** fp,
 
3349
                              SecMap* sm, Int zix ) {
 
3350
   CacheLineZ* lineZ;
 
3351
   tl_assert(zp);
 
3352
   tl_assert(fp);
 
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);
 
3361
      *zp = NULL;
 
3362
      *fp = &sm->linesF[fix];
 
3363
      tl_assert(sm->linesF[fix].inUse);
 
3364
   } else {
 
3365
      *zp = lineZ;
 
3366
      *fp = NULL;
 
3367
   }
 
3368
}
 
3369
 
 
3370
static void find_ZF_for_reading ( /*OUT*/CacheLineZ** zp,
 
3371
                                  /*OUT*/CacheLineF** fp, Addr tag ) {
 
3372
   CacheLineZ* lineZ;
 
3373
   CacheLineF* lineF;
 
3374
   UWord   zix;
 
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];
 
3383
   lineF = NULL;
 
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);
 
3391
      lineZ = NULL;
 
3392
   }
 
3393
   *zp = lineZ;
 
3394
   *fp = lineF;
 
3395
}
 
3396
 
 
3397
static void find_Z_for_writing ( /*OUT*/SecMap** smp,
 
3398
                                 /*OUT*/Word* zixp,
 
3399
                                 Addr tag ) {
 
3400
   CacheLineZ* lineZ;
 
3401
   CacheLineF* lineF;
 
3402
   UWord   zix;
 
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];
 
3411
   lineF = NULL;
 
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;
 
3421
   }
 
3422
   *smp  = sm;
 
3423
   *zixp = zix;
 
3424
}
 
3425
 
 
3426
static 
 
3427
void alloc_F_for_writing ( /*MOD*/SecMap* sm, /*OUT*/Word* fixp ) {
 
3428
   Word        i, new_size;
 
3429
   CacheLineF* nyu;
 
3430
 
 
3431
   if (sm->linesF) {
 
3432
      tl_assert(sm->linesF_size > 0);
 
3433
   } else {
 
3434
      tl_assert(sm->linesF_size == 0);
 
3435
   }
 
3436
 
 
3437
   if (sm->linesF) {
 
3438
      for (i = 0; i < sm->linesF_size; i++) {
 
3439
         if (!sm->linesF[i].inUse) {
 
3440
            *fixp = (Word)i;
 
3441
            return;
 
3442
         }
 
3443
      }
 
3444
   }
 
3445
 
 
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) );
 
3449
   tl_assert(nyu);
 
3450
 
 
3451
   stats__secmap_linesF_allocd += (new_size - sm->linesF_size);
 
3452
   stats__secmap_linesF_bytes  += (new_size - sm->linesF_size)
 
3453
                                  * sizeof(CacheLineF);
 
3454
 
 
3455
   if (0)
 
3456
   VG_(printf)("SM %p: expand F array from %d to %d\n", 
 
3457
               sm, (Int)sm->linesF_size, new_size);
 
3458
 
 
3459
   for (i = 0; i < new_size; i++)
 
3460
      nyu[i].inUse = False;
 
3461
 
 
3462
   if (sm->linesF) {
 
3463
      for (i = 0; i < sm->linesF_size; i++) {
 
3464
         tl_assert(sm->linesF[i].inUse);
 
3465
         nyu[i] = sm->linesF[i];
 
3466
      }
 
3467
      VG_(memset)(sm->linesF, 0, sm->linesF_size * sizeof(CacheLineF) );
 
3468
      hg_free(sm->linesF);
 
3469
   }
 
3470
 
 
3471
   sm->linesF      = nyu;
 
3472
   sm->linesF_size = new_size;
 
3473
 
 
3474
   for (i = 0; i < sm->linesF_size; i++) {
 
3475
      if (!sm->linesF[i].inUse) {
 
3476
         *fixp = (Word)i;
 
3477
         return;
 
3478
      }
 
3479
    }
 
3480
 
 
3481
    /*NOTREACHED*/
 
3482
    tl_assert(0);
 
3483
}
 
3484
 
 
3485
 
 
3486
/* ------------ CacheLine and implicit-tree related ------------ */
 
3487
 
 
3488
__attribute__((unused))
 
3489
static void pp_CacheLine ( CacheLine* cl ) {
 
3490
   Word i;
 
3491
   if (!cl) {
 
3492
      VG_(printf)("pp_CacheLine(NULL)\n");
 
3493
      return;
 
3494
   }
 
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]);
 
3499
}
 
3500
 
 
3501
static UChar descr_to_validbits ( UShort descr )
 
3502
{
 
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)  | \
 
3513
                          ( (b16_0) << 0) ) )
 
3514
 
 
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) ) )
 
3520
 
 
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);
 
3531
 
 
3532
   switch (descr) {
 
3533
   /*
 
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
 
3543
              |             |  | | |  |  | | |
 
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);
 
3553
 
 
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);
 
3562
 
 
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);
 
3571
 
 
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);
 
3580
 
 
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);
 
3589
 
 
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);
 
3598
 
 
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);
 
3601
 
 
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);
 
3604
 
 
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]*/
 
3608
   }
 
3609
   /* NOTREACHED*/
 
3610
   tl_assert(0);
 
3611
 
 
3612
#  undef DESCR
 
3613
#  undef BYTE
 
3614
}
 
3615
 
 
3616
__attribute__((unused))
 
3617
static Bool is_sane_Descr ( UShort descr ) {
 
3618
   return descr_to_validbits(descr) != 0;
 
3619
}
 
3620
 
 
3621
static void sprintf_Descr ( /*OUT*/UChar* dst, UShort descr ) {
 
3622
   VG_(sprintf)(dst, 
 
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)
 
3639
   );
 
3640
}
 
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)
 
3651
   );
 
3652
}
 
3653
 
 
3654
static Bool is_sane_Descr_and_Tree ( UShort descr, SVal* tree ) {
 
3655
   Word  i;
 
3656
   UChar validbits = descr_to_validbits(descr);
 
3657
   UChar buf[128], buf2[128];
 
3658
   if (validbits == 0)
 
3659
      goto bad;
 
3660
   for (i = 0; i < 8; i++) {
 
3661
      if (validbits & (1<<i)) {
 
3662
         if (!is_SHVAL_valid(tree[i]))
 
3663
            goto bad;
 
3664
      } else {
 
3665
         if (tree[i] != 0)
 
3666
            goto bad;
 
3667
      }
 
3668
   }
 
3669
   return True;
 
3670
  bad:
 
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]);
 
3678
   VG_(printf)("}\n");
 
3679
   return 0;
 
3680
}
 
3681
 
 
3682
 
 
3683
static Bool is_sane_CacheLine ( CacheLine* cl )
 
3684
{
 
3685
   Word tno, cloff;
 
3686
 
 
3687
   if (!cl) goto bad;
 
3688
 
 
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))
 
3693
         goto bad;
 
3694
   }
 
3695
   tl_assert(cloff == N_LINE_ARANGE);
 
3696
   return True;
 
3697
  bad:
 
3698
   pp_CacheLine(cl);
1459
3699
   return False;
1460
3700
}
1461
3701
 
1462
 
static Bool check_cycle(const Mutex *start, const LockSet* lockset)
1463
 
{
1464
 
 
1465
 
   graph_mark += 2;             /* clear all marks */
1466
 
 
1467
 
   return check_cycle_inner(start, lockset);
1468
 
}
1469
 
 
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)
1474
 
{
1475
 
   static const Bool debug = False;
1476
 
 
1477
 
   if (mutex->state == MxDead) {
1478
 
      Char *str;
1479
 
 
1480
 
      switch(state) {
1481
 
      case MxLocked:    str = "lock dead mutex"; break;
1482
 
      case MxUnlocked:  str = "unlock dead mutex"; break;
1483
 
      default:          str = "operate on dead mutex"; break;
1484
 
      }
1485
 
 
1486
 
      /* can't do anything legal to a destroyed mutex */
1487
 
      record_mutex_error(tid, mutex, str, mutex->location);
1488
 
      return;
1489
 
   }
1490
 
 
1491
 
   switch(state) {
1492
 
   case MxLocked:
1493
 
      tl_assert(!check_cycle(mutex, mutex->lockdep));
1494
 
 
1495
 
      if (debug)
1496
 
         print_LockSet("thread holding", thread_locks[tid]);
1497
 
 
1498
 
      if (check_cycle(mutex, thread_locks[tid]))
1499
 
         record_lockgraph_error(tid, mutex, thread_locks[tid], mutex->lockdep);
1500
 
      else {
1501
 
         mutex->lockdep = ls_union(mutex->lockdep, thread_locks[tid]);
1502
 
 
1503
 
         if (debug) {
1504
 
            VG_(printf)("giving mutex %p%(y lockdep = %p ", 
1505
 
                        mutex->mutexp, mutex->mutexp, mutex->lockdep);
1506
 
            print_LockSet("lockdep", mutex->lockdep);
1507
 
         }
1508
 
      }
1509
 
      break;
1510
 
 
1511
 
   case MxUnlocked:
1512
 
      if (debug)
1513
 
         print_LockSet("thread holding", thread_locks[tid]);
1514
 
 
1515
 
      if (mutex->state != MxLocked) {
1516
 
         record_mutex_error(tid, mutex, 
1517
 
                            "unlock non-locked mutex", mutex->location);
1518
 
      }
1519
 
      if (mutex->tid != tid) {
1520
 
         record_mutex_error(tid, mutex, 
1521
 
                            "unlock someone else's mutex", mutex->location);
1522
 
      }
1523
 
      break;
1524
 
 
1525
 
   case MxDead:
1526
 
      break;
1527
 
 
1528
 
   default:
1529
 
      break;
1530
 
   }
1531
 
}
1532
 
 
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
1537
 
   atomically.  
1538
 
 
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.
1542
 
*/
1543
 
static void set_mutex_state(Mutex *mutex, MutexState state, ThreadId tid)
1544
 
{
1545
 
   static const Bool debug = False;
1546
 
 
1547
 
   if (debug)
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));
1551
 
 
1552
 
   if (mutex->state == MxDead) {
1553
 
      /* can't do anything legal to a destroyed mutex */
1554
 
      return;
1555
 
   }
1556
 
 
1557
 
   switch(state) {
1558
 
   case MxLocked:
1559
 
      if (mutex->state == MxLocked) {
1560
 
         if (mutex->tid != tid)
1561
 
            record_mutex_error(tid, mutex, "take lock held by someone else", 
1562
 
                               mutex->location);
1563
 
         else
1564
 
            record_mutex_error(tid, mutex, "take lock we already hold", 
1565
 
                               mutex->location);
1566
 
 
1567
 
         VG_(tool_panic)("core should have checked this\n");
1568
 
         break;
1569
 
      }
1570
 
 
1571
 
      tl_assert(!check_cycle(mutex, mutex->lockdep));
1572
 
 
1573
 
      mutex->tid = tid;
1574
 
      break;
1575
 
 
1576
 
   case MxUnlocked:
1577
 
      if (debug)
1578
 
         print_LockSet("thread holding", thread_locks[tid]);
1579
 
 
1580
 
      if (mutex->state != MxLocked || mutex->tid != tid)
1581
 
         break;
1582
 
 
1583
 
      mutex->tid = VG_INVALID_THREADID;
1584
 
      break;
1585
 
 
1586
 
   case MxDead:
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;
1592
 
 
1593
 
         record_mutex_error(tid, mutex,
1594
 
                            "free locked mutex", mutex->location);
1595
 
      }
1596
 
      break;
1597
 
 
1598
 
   default:
1599
 
      break;
1600
 
   }
1601
 
 
1602
 
   mutex->location = VG_(record_ExeContext)(tid);
1603
 
   mutex->state = state;
1604
 
}
1605
 
 
1606
 
/*------------------------------------------------------------*/
1607
 
/*--- Setting and checking permissions.                    ---*/
1608
 
/*------------------------------------------------------------*/
1609
 
 
1610
 
/* only clean up dead mutexes */
1611
 
static
1612
 
Bool cleanmx(Mutex *mx) {
1613
 
   return mx->state == MxDead;
1614
 
}
1615
 
 
1616
 
static
1617
 
void set_address_range_state ( Addr a, SizeT len /* in bytes */, 
1618
 
                               VgeInitStatus status )
1619
 
{
1620
 
   Addr end;
1621
 
 
1622
 
#  if DEBUG_MAKE_ACCESSES
1623
 
   VG_(printf)("make_access: 0x%x, %u, status=%u\n", a, len, status);
1624
 
#  endif
1625
 
   //PROF_EVENT(30); PPP
1626
 
 
 
3702
 
 
3703
static UShort normalise_tree ( /*MOD*/SVal* tree ) {
 
3704
   Word   i;
 
3705
   UShort descr;
 
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);
 
3710
   
 
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;
 
3719
   }
 
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;
 
3724
   }
 
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;
 
3729
   }
 
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;
 
3734
   }
 
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;
 
3741
   }
 
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;
 
3747
   }
 
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;
 
3754
   }
 
3755
   return descr;
 
3756
}
 
3757
 
 
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 )
 
3761
{
 
3762
   Word tno, cloff;
 
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 );
 
3766
   }
 
3767
   tl_assert(cloff == N_LINE_ARANGE);
 
3768
   if (SCE_CACHELINE)
 
3769
      tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
3770
   stats__cline_normalises++;
 
3771
}
 
3772
 
 
3773
 
 
3774
static 
 
3775
SVal* sequentialise_tree ( /*MOD*/SVal* dst, /*OUT*/Bool* anyShared,
 
3776
                           UShort descr, SVal* tree ) {
 
3777
   SVal* dst0 = dst;
 
3778
   *anyShared = False;
 
3779
 
 
3780
#  define PUT(_n,_v)                                \
 
3781
      do { Word i;                                  \
 
3782
           if (is_SHVAL_Sh(_v))                     \
 
3783
              *anyShared = True;                    \
 
3784
           for (i = 0; i < (_n); i++)               \
 
3785
                  *dst++ = (_v);                    \
 
3786
      } while (0)
 
3787
 
 
3788
   /* byte 0 */
 
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]);
 
3793
   /* byte 1 */
 
3794
   if (descr & TREE_DESCR_8_1)  PUT(1, tree[1]);
 
3795
   /* byte 2 */
 
3796
   if (descr & TREE_DESCR_16_1) PUT(2, tree[2]); else
 
3797
   if (descr & TREE_DESCR_8_2)  PUT(1, tree[2]);
 
3798
   /* byte 3 */
 
3799
   if (descr & TREE_DESCR_8_3)  PUT(1, tree[3]);
 
3800
   /* byte 4 */
 
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]);
 
3804
   /* byte 5 */
 
3805
   if (descr & TREE_DESCR_8_5)  PUT(1, tree[5]);
 
3806
   /* byte 6 */
 
3807
   if (descr & TREE_DESCR_16_3) PUT(2, tree[6]); else
 
3808
   if (descr & TREE_DESCR_8_6)  PUT(1, tree[6]);
 
3809
   /* byte 7 */
 
3810
   if (descr & TREE_DESCR_8_7)  PUT(1, tree[7]);
 
3811
 
 
3812
#  undef PUT
 
3813
 
 
3814
   tl_assert( (((Char*)dst) - ((Char*)dst0)) == 8 * sizeof(SVal) );
 
3815
   return dst;
 
3816
}
 
3817
 
 
3818
/* Write the cacheline 'wix' to backing store.  Where it ends up
 
3819
   is determined by its tag field. */
 
3820
static
 
3821
Bool sequentialise_CacheLine ( /*OUT*/SVal* dst, Word nDst, CacheLine* src )
 
3822
{
 
3823
   Word  tno, cloff;
 
3824
   Bool  anyShared = False;
 
3825
   SVal* dst0      = dst;
 
3826
 
 
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];
 
3830
      Bool   bTmp  = False;
 
3831
      dst = sequentialise_tree ( dst, &bTmp, descr, tree );
 
3832
      anyShared |= bTmp;
 
3833
   }
 
3834
   tl_assert(cloff == N_LINE_ARANGE);
 
3835
 
 
3836
   /* Assert we wrote N_LINE_ARANGE shadow values. */
 
3837
   tl_assert( ((HChar*)dst) - ((HChar*)dst0) 
 
3838
              == nDst * sizeof(SVal) );
 
3839
 
 
3840
   return anyShared;
 
3841
}
 
3842
 
 
3843
 
 
3844
static __attribute__((noinline)) void cacheline_wback ( UWord wix )
 
3845
{
 
3846
   Word        i, j;
 
3847
   Bool        anyShared = False;
 
3848
   Addr        tag;
 
3849
   SecMap*     sm;
 
3850
   CacheLine*  cl;
 
3851
   CacheLineZ* lineZ;
 
3852
   CacheLineF* lineF;
 
3853
   Word        zix, fix;
 
3854
   SVal        shvals[N_LINE_ARANGE];
 
3855
   SVal        sv;
 
3856
 
 
3857
   if (0)
 
3858
   VG_(printf)("scache wback line %d\n", (Int)wix);
 
3859
 
 
3860
   tl_assert(wix >= 0 && wix < N_WAY_NENT);
 
3861
 
 
3862
   tag =  cache_shmem.tags0[wix];
 
3863
   cl  = &cache_shmem.lyns0[wix];
 
3864
 
 
3865
   /* The cache line may have been invalidated; if so, ignore it. */
 
3866
   if (!is_valid_scache_tag(tag))
 
3867
      return;
 
3868
 
 
3869
   /* Where are we going to put it? */
 
3870
   sm         = NULL;
 
3871
   lineZ      = NULL;
 
3872
   lineF      = NULL;
 
3873
   zix = fix = -1;
 
3874
 
 
3875
   find_Z_for_writing( &sm, &zix, tag );
 
3876
   tl_assert(sm);
 
3877
   tl_assert(zix >= 0 && zix < N_SECMAP_ZLINES);
 
3878
   lineZ = &sm->linesZ[zix];
 
3879
 
 
3880
   /* Generate the data to be stored */
 
3881
   if (SCE_CACHELINE)
 
3882
      tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
3883
   anyShared = sequentialise_CacheLine( shvals, N_LINE_ARANGE, cl );
 
3884
 
 
3885
   lineZ->dict[0] = lineZ->dict[1] 
 
3886
                  = lineZ->dict[2] = lineZ->dict[3] = 0;
 
3887
 
 
3888
   for (i = 0; i < N_LINE_ARANGE; i++) {
 
3889
 
 
3890
      sv = shvals[i];
 
3891
      for (j = 0; j < 4; j++) {
 
3892
         if (sv == lineZ->dict[j])
 
3893
            goto dict_ok;
 
3894
      }
 
3895
      for (j = 0; j < 4; j++) {
 
3896
         if (lineZ->dict[j] == 0)
 
3897
            break;
 
3898
      }
 
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;
 
3903
     dict_ok:
 
3904
      write_twobit_array( lineZ->ix2s, i, j );
 
3905
 
 
3906
   }
 
3907
 
 
3908
   tl_assert(i >= 0 && i <= N_LINE_ARANGE);
 
3909
 
 
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++) {
 
3922
         sv = shvals[i];
 
3923
         tl_assert(is_SHVAL_valid(sv));
 
3924
         lineF->w32s[i] = sv;
 
3925
      }
 
3926
      stats__cache_F_wbacks++;
 
3927
   } else {
 
3928
      stats__cache_Z_wbacks++;
 
3929
   }
 
3930
 
 
3931
   if (anyShared)
 
3932
      sm->mbHasShared = True;
 
3933
 
 
3934
   /* mb_tidy_one_cacheline(); */
 
3935
}
 
3936
 
 
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
 
3940
   from. */
 
3941
static __attribute__((noinline)) void cacheline_fetch ( UWord wix )
 
3942
{
 
3943
   Word        i;
 
3944
   Addr        tag;
 
3945
   CacheLine*  cl;
 
3946
   CacheLineZ* lineZ;
 
3947
   CacheLineF* lineF;
 
3948
 
 
3949
   if (0)
 
3950
   VG_(printf)("scache fetch line %d\n", (Int)wix);
 
3951
 
 
3952
   tl_assert(wix >= 0 && wix < N_WAY_NENT);
 
3953
 
 
3954
   tag =  cache_shmem.tags0[wix];
 
3955
   cl  = &cache_shmem.lyns0[wix];
 
3956
 
 
3957
   /* reject nonsense requests */
 
3958
   tl_assert(is_valid_scache_tag(tag));
 
3959
 
 
3960
   lineZ = NULL;
 
3961
   lineF = NULL;
 
3962
   find_ZF_for_reading( &lineZ, &lineF, tag );
 
3963
   tl_assert( (lineZ && !lineF) || (!lineZ && lineF) );
 
3964
 
 
3965
   /* expand the data into the bottom layer of the tree, then get
 
3966
      cacheline_normalise to build the descriptor array. */
 
3967
   if (lineF) {
 
3968
      tl_assert(lineF->inUse);
 
3969
      for (i = 0; i < N_LINE_ARANGE; i++) {
 
3970
         cl->svals[i] = lineF->w32s[i];
 
3971
      }
 
3972
      stats__cache_F_fetches++;
 
3973
   } else {
 
3974
      for (i = 0; i < N_LINE_ARANGE; i++) {
 
3975
         SVal sv;
 
3976
         UWord ix = read_twobit_array( lineZ->ix2s, i );
 
3977
         tl_assert(ix >= 0 && ix <= 3);
 
3978
         sv = lineZ->dict[ix];
 
3979
         tl_assert(sv != 0);
 
3980
         cl->svals[i] = sv;
 
3981
      }
 
3982
      stats__cache_Z_fetches++;
 
3983
   }
 
3984
   normalise_CacheLine( cl );
 
3985
}
 
3986
 
 
3987
static void shmem__invalidate_scache ( void ) {
 
3988
   Word wix;
 
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*/;
 
3993
   }
 
3994
   stats__cache_invals++;
 
3995
}
 
3996
 
 
3997
static void shmem__flush_and_invalidate_scache ( void ) {
 
3998
   Word wix;
 
3999
   Addr tag;
 
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 */
 
4006
      } else {
 
4007
         tl_assert(is_valid_scache_tag(tag));
 
4008
         cacheline_wback( wix );
 
4009
      }
 
4010
      cache_shmem.tags0[wix] = 1/*INVALID*/;
 
4011
   }
 
4012
   stats__cache_flushes++;
 
4013
   stats__cache_invals++;
 
4014
}
 
4015
 
 
4016
 
 
4017
/* ------------ Basic shadow memory read/write ops ------------ */
 
4018
 
 
4019
static inline Bool aligned16 ( Addr a ) {
 
4020
   return 0 == (a & 1);
 
4021
}
 
4022
static inline Bool aligned32 ( Addr a ) {
 
4023
   return 0 == (a & 3);
 
4024
}
 
4025
static inline Bool aligned64 ( Addr a ) {
 
4026
   return 0 == (a & 7);
 
4027
}
 
4028
static inline UWord get_cacheline_offset ( Addr a ) {
 
4029
   return (UWord)(a & (N_LINE_ARANGE - 1));
 
4030
}
 
4031
static inline UWord get_treeno ( Addr a ) {
 
4032
   return get_cacheline_offset(a) >> 3;
 
4033
}
 
4034
static inline UWord get_tree_offset ( Addr a ) {
 
4035
   return a & 7;
 
4036
}
 
4037
 
 
4038
static __attribute__((noinline))
 
4039
       CacheLine* get_cacheline_MISS ( Addr a ); /* fwds */
 
4040
static inline CacheLine* get_cacheline ( Addr a )
 
4041
{
 
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];
 
4049
   } else {
 
4050
      return get_cacheline_MISS( a );
 
4051
   }
 
4052
}
 
4053
 
 
4054
static __attribute__((noinline))
 
4055
       CacheLine* get_cacheline_MISS ( Addr a )
 
4056
{
 
4057
   /* tag is 'a' with the in-line offset masked out, 
 
4058
      eg a[31]..a[4] 0000 */
 
4059
 
 
4060
   CacheLine* cl;
 
4061
   Addr*      tag_old_p;
 
4062
   Addr       tag = a & ~(N_LINE_ARANGE - 1);
 
4063
   UWord      wix = (a >> N_LINE_BITS) & (N_WAY_NENT - 1);
 
4064
 
 
4065
   tl_assert(tag != cache_shmem.tags0[wix]);
 
4066
 
 
4067
   /* Dump the old line into the backing store. */
 
4068
   stats__cache_totmisses++;
 
4069
 
 
4070
   cl        = &cache_shmem.lyns0[wix];
 
4071
   tag_old_p = &cache_shmem.tags0[wix];
 
4072
 
 
4073
   if (is_valid_scache_tag( *tag_old_p )) {
 
4074
      /* EXPENSIVE and REDUNDANT: callee does it */
 
4075
      if (SCE_CACHELINE)
 
4076
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4077
      cacheline_wback( wix );
 
4078
   }
 
4079
   /* and reload the new one */
 
4080
   *tag_old_p = tag;
 
4081
   cacheline_fetch( wix );
 
4082
   if (SCE_CACHELINE)
 
4083
      tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4084
   return cl;
 
4085
}
 
4086
 
 
4087
static UShort pulldown_to_32 ( /*MOD*/SVal* tree, UWord toff, UShort descr ) {
 
4088
   stats__cline_64to32pulldown++;
 
4089
   switch (toff) {
 
4090
      case 0: case 4:
 
4091
         tl_assert(descr & TREE_DESCR_64);
 
4092
         tree[4] = tree[0];
 
4093
         descr &= ~TREE_DESCR_64;
 
4094
         descr |= (TREE_DESCR_32_1 | TREE_DESCR_32_0);
 
4095
         break;
 
4096
      default:
 
4097
         tl_assert(0);
 
4098
   }
 
4099
   return descr;
 
4100
}
 
4101
 
 
4102
static UShort pulldown_to_16 ( /*MOD*/SVal* tree, UWord toff, UShort descr ) {
 
4103
   stats__cline_32to16pulldown++;
 
4104
   switch (toff) {
 
4105
      case 0: case 2:
 
4106
         if (!(descr & TREE_DESCR_32_0)) {
 
4107
            descr = pulldown_to_32(tree, 0, descr);
 
4108
         }
 
4109
         tl_assert(descr & TREE_DESCR_32_0);
 
4110
         tree[2] = tree[0];
 
4111
         descr &= ~TREE_DESCR_32_0;
 
4112
         descr |= (TREE_DESCR_16_1 | TREE_DESCR_16_0);
 
4113
         break;
 
4114
      case 4: case 6:
 
4115
         if (!(descr & TREE_DESCR_32_1)) {
 
4116
            descr = pulldown_to_32(tree, 4, descr);
 
4117
         }
 
4118
         tl_assert(descr & TREE_DESCR_32_1);
 
4119
         tree[6] = tree[4];
 
4120
         descr &= ~TREE_DESCR_32_1;
 
4121
         descr |= (TREE_DESCR_16_3 | TREE_DESCR_16_2);
 
4122
         break;
 
4123
      default:
 
4124
         tl_assert(0);
 
4125
   }
 
4126
   return descr;
 
4127
}
 
4128
 
 
4129
static UShort pulldown_to_8 ( /*MOD*/SVal* tree, UWord toff, UShort descr ) {
 
4130
   stats__cline_16to8pulldown++;
 
4131
   switch (toff) {
 
4132
      case 0: case 1:
 
4133
         if (!(descr & TREE_DESCR_16_0)) {
 
4134
            descr = pulldown_to_16(tree, 0, descr);
 
4135
         }
 
4136
         tl_assert(descr & TREE_DESCR_16_0);
 
4137
         tree[1] = tree[0];
 
4138
         descr &= ~TREE_DESCR_16_0;
 
4139
         descr |= (TREE_DESCR_8_1 | TREE_DESCR_8_0);
 
4140
         break;
 
4141
      case 2: case 3:
 
4142
         if (!(descr & TREE_DESCR_16_1)) {
 
4143
            descr = pulldown_to_16(tree, 2, descr);
 
4144
         }
 
4145
         tl_assert(descr & TREE_DESCR_16_1);
 
4146
         tree[3] = tree[2];
 
4147
         descr &= ~TREE_DESCR_16_1;
 
4148
         descr |= (TREE_DESCR_8_3 | TREE_DESCR_8_2);
 
4149
         break;
 
4150
      case 4: case 5:
 
4151
         if (!(descr & TREE_DESCR_16_2)) {
 
4152
            descr = pulldown_to_16(tree, 4, descr);
 
4153
         }
 
4154
         tl_assert(descr & TREE_DESCR_16_2);
 
4155
         tree[5] = tree[4];
 
4156
         descr &= ~TREE_DESCR_16_2;
 
4157
         descr |= (TREE_DESCR_8_5 | TREE_DESCR_8_4);
 
4158
         break;
 
4159
      case 6: case 7:
 
4160
         if (!(descr & TREE_DESCR_16_3)) {
 
4161
            descr = pulldown_to_16(tree, 6, descr);
 
4162
         }
 
4163
         tl_assert(descr & TREE_DESCR_16_3);
 
4164
         tree[7] = tree[6];
 
4165
         descr &= ~TREE_DESCR_16_3;
 
4166
         descr |= (TREE_DESCR_8_7 | TREE_DESCR_8_6);
 
4167
         break;
 
4168
      default:
 
4169
         tl_assert(0);
 
4170
   }
 
4171
   return descr;
 
4172
}
 
4173
 
 
4174
 
 
4175
static UShort pullup_descr_to_16 ( UShort descr, UWord toff ) {
 
4176
   UShort mask;
 
4177
   switch (toff) {
 
4178
      case 0:
 
4179
         mask = TREE_DESCR_8_1 | TREE_DESCR_8_0;
 
4180
         tl_assert( (descr & mask) == mask );
 
4181
         descr &= ~mask;
 
4182
         descr |= TREE_DESCR_16_0;
 
4183
         break;
 
4184
      case 2:
 
4185
         mask = TREE_DESCR_8_3 | TREE_DESCR_8_2;
 
4186
         tl_assert( (descr & mask) == mask );
 
4187
         descr &= ~mask;
 
4188
         descr |= TREE_DESCR_16_1;
 
4189
         break;
 
4190
      case 4:
 
4191
         mask = TREE_DESCR_8_5 | TREE_DESCR_8_4;
 
4192
         tl_assert( (descr & mask) == mask );
 
4193
         descr &= ~mask;
 
4194
         descr |= TREE_DESCR_16_2;
 
4195
         break;
 
4196
      case 6:
 
4197
         mask = TREE_DESCR_8_7 | TREE_DESCR_8_6;
 
4198
         tl_assert( (descr & mask) == mask );
 
4199
         descr &= ~mask;
 
4200
         descr |= TREE_DESCR_16_3;
 
4201
         break;
 
4202
      default:
 
4203
         tl_assert(0);
 
4204
   }
 
4205
   return descr;
 
4206
}
 
4207
 
 
4208
static UShort pullup_descr_to_32 ( UShort descr, UWord toff ) {
 
4209
   UShort mask;
 
4210
   switch (toff) {
 
4211
      case 0:
 
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 );
 
4218
         descr &= ~mask;
 
4219
         descr |= TREE_DESCR_32_0;
 
4220
         break;
 
4221
      case 4:
 
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 );
 
4228
         descr &= ~mask;
 
4229
         descr |= TREE_DESCR_32_1;
 
4230
         break;
 
4231
      default:
 
4232
         tl_assert(0);
 
4233
   }
 
4234
   return descr;
 
4235
}
 
4236
 
 
4237
static Bool valid_value_is_above_me_32 ( UShort descr, UWord toff ) {
 
4238
   switch (toff) {
 
4239
      case 0: case 4:
 
4240
         return 0 != (descr & TREE_DESCR_64);
 
4241
      default:
 
4242
         tl_assert(0);
 
4243
   }
 
4244
}
 
4245
 
 
4246
static Bool valid_value_is_below_me_16 ( UShort descr, UWord toff ) {
 
4247
   switch (toff) {
 
4248
      case 0:
 
4249
         return 0 != (descr & (TREE_DESCR_8_1 | TREE_DESCR_8_0));
 
4250
      case 2:
 
4251
         return 0 != (descr & (TREE_DESCR_8_3 | TREE_DESCR_8_2));
 
4252
      case 4:
 
4253
         return 0 != (descr & (TREE_DESCR_8_5 | TREE_DESCR_8_4));
 
4254
      case 6:
 
4255
         return 0 != (descr & (TREE_DESCR_8_7 | TREE_DESCR_8_6));
 
4256
      default:
 
4257
         tl_assert(0);
 
4258
   }
 
4259
}
 
4260
 
 
4261
static void shadow_mem_read8 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4262
   CacheLine* cl; 
 
4263
   UWord      cloff, tno, toff;
 
4264
   SVal       svOld, svNew;
 
4265
   UShort     descr;
 
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);
 
4275
      if (SCE_CACHELINE)
 
4276
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4277
   }
 
4278
   svOld = cl->svals[cloff];
 
4279
   svNew = msm__handle_read( thr_acc, a, svOld, 1 );
 
4280
   cl->svals[cloff] = svNew;
 
4281
}
 
4282
static void shadow_mem_read16 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4283
   CacheLine* cl; 
 
4284
   UWord      cloff, tno, toff;
 
4285
   SVal       svOld, svNew;
 
4286
   UShort     descr;
 
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)) {
 
4296
         goto slowcase;
 
4297
      } else {
 
4298
         SVal* tree = &cl->svals[tno << 3];
 
4299
         cl->descrs[tno] = pulldown_to_16(tree, toff, descr);
 
4300
      }
 
4301
      if (SCE_CACHELINE)
 
4302
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4303
   }
 
4304
   svOld = cl->svals[cloff];
 
4305
   svNew = msm__handle_read( thr_acc, a, svOld, 2 );
 
4306
   cl->svals[cloff] = svNew;
 
4307
   return;
 
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*/ );
 
4312
}
 
4313
 
 
4314
__attribute__((noinline))
 
4315
static void shadow_mem_read32_SLOW ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4316
   CacheLine* cl; 
 
4317
   UWord      cloff, tno, toff;
 
4318
   SVal       svOld, svNew;
 
4319
   UShort     descr;
 
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);
 
4330
      } else {
 
4331
         goto slowcase;
 
4332
      }
 
4333
      if (SCE_CACHELINE)
 
4334
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4335
   }
 
4336
   svOld = cl->svals[cloff];
 
4337
   svNew = msm__handle_read( thr_acc, a, svOld, 4 );
 
4338
   cl->svals[cloff] = svNew;
 
4339
   return;
 
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*/ );
 
4344
}
 
4345
inline
 
4346
static void shadow_mem_read32 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4347
   CacheLine* cl; 
 
4348
   UWord      cloff, tno, toff;
 
4349
   UShort     descr;
 
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 );
 
4360
   }
 
4361
   return;
 
4362
  slowcase: /* misaligned, or not at this level in the tree */
 
4363
   shadow_mem_read32_SLOW( thr_acc, a, uuOpaque );
 
4364
}
 
4365
 
 
4366
inline
 
4367
static void shadow_mem_read64 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4368
   CacheLine* cl; 
 
4369
   UWord      cloff, tno, toff;
 
4370
   SVal       svOld, svNew;
 
4371
   UShort     descr;
 
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) )) {
 
4380
      goto slowcase;
 
4381
   }
 
4382
   svOld = cl->svals[cloff];
 
4383
   svNew = msm__handle_read( thr_acc, a, svOld, 8 );
 
4384
   cl->svals[cloff] = svNew;
 
4385
   return;
 
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*/ );
 
4390
}
 
4391
 
 
4392
static void shadow_mem_write8 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4393
   CacheLine* cl; 
 
4394
   UWord      cloff, tno, toff;
 
4395
   SVal       svOld, svNew;
 
4396
   UShort     descr;
 
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);
 
4406
      if (SCE_CACHELINE)
 
4407
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4408
   }
 
4409
   svOld = cl->svals[cloff];
 
4410
   svNew = msm__handle_write( thr_acc, a, svOld, 1 );
 
4411
   cl->svals[cloff] = svNew;
 
4412
}
 
4413
static void shadow_mem_write16 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4414
   CacheLine* cl; 
 
4415
   UWord      cloff, tno, toff;
 
4416
   SVal       svOld, svNew;
 
4417
   UShort     descr;
 
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)) {
 
4427
         goto slowcase;
 
4428
      } else {
 
4429
         SVal* tree = &cl->svals[tno << 3];
 
4430
         cl->descrs[tno] = pulldown_to_16(tree, toff, descr);
 
4431
      }
 
4432
      if (SCE_CACHELINE)
 
4433
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4434
   }
 
4435
   svOld = cl->svals[cloff];
 
4436
   svNew = msm__handle_write( thr_acc, a, svOld, 2 );
 
4437
   cl->svals[cloff] = svNew;
 
4438
   return;
 
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*/ );
 
4443
}
 
4444
 
 
4445
__attribute__((noinline))
 
4446
static void shadow_mem_write32_SLOW ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4447
   CacheLine* cl; 
 
4448
   UWord      cloff, tno, toff;
 
4449
   SVal       svOld, svNew;
 
4450
   UShort     descr;
 
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);
 
4461
      } else {
 
4462
         goto slowcase;
 
4463
      }
 
4464
      if (SCE_CACHELINE)
 
4465
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4466
   }
 
4467
   svOld = cl->svals[cloff];
 
4468
   svNew = msm__handle_write( thr_acc, a, svOld, 4 );
 
4469
   cl->svals[cloff] = svNew;
 
4470
   return;
 
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*/ );
 
4475
}
 
4476
inline
 
4477
static void shadow_mem_write32 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4478
   CacheLine* cl; 
 
4479
   UWord      cloff, tno, toff;
 
4480
   UShort     descr;
 
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 );
 
4491
   }
 
4492
   return;
 
4493
  slowcase: /* misaligned, or must go further down the tree */
 
4494
   shadow_mem_write32_SLOW( thr_acc, a, uuOpaque );
 
4495
}
 
4496
 
 
4497
inline
 
4498
static void shadow_mem_write64 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
 
4499
   CacheLine* cl; 
 
4500
   UWord      cloff, tno, toff;
 
4501
   SVal       svOld, svNew;
 
4502
   UShort     descr;
 
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) )) {
 
4511
      goto slowcase;
 
4512
   }
 
4513
   svOld = cl->svals[cloff];
 
4514
   svNew = msm__handle_write( thr_acc, a, svOld, 8 );
 
4515
   cl->svals[cloff] = svNew;
 
4516
   return;
 
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*/ );
 
4521
}
 
4522
 
 
4523
static void shadow_mem_set8 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
 
4524
   CacheLine* cl; 
 
4525
   UWord      cloff, tno, toff;
 
4526
   UShort     descr;
 
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);
 
4536
      if (SCE_CACHELINE)
 
4537
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4538
   }
 
4539
   cl->svals[cloff] = svNew;
 
4540
}
 
4541
static void shadow_mem_set16 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
 
4542
   CacheLine* cl; 
 
4543
   UWord      cloff, tno, toff;
 
4544
   UShort     descr;
 
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. */
 
4558
      } else {
 
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);
 
4564
      if (SCE_CACHELINE)
 
4565
         tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4566
      }
 
4567
   }
 
4568
   cl->svals[cloff + 0] = svNew;
 
4569
   cl->svals[cloff + 1] = 0;
 
4570
   return;
 
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 );
 
4575
}
 
4576
static void shadow_mem_set32 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
 
4577
   CacheLine* cl; 
 
4578
   UWord      cloff, tno, toff;
 
4579
   UShort     descr;
 
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);
 
4594
         if (SCE_CACHELINE)
 
4595
            tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
 
4596
      } else {
 
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. */
 
4601
      }
 
4602
   }
 
4603
   cl->svals[cloff + 0] = svNew;
 
4604
   cl->svals[cloff + 1] = 0;
 
4605
   cl->svals[cloff + 2] = 0;
 
4606
   cl->svals[cloff + 3] = 0;
 
4607
   return;
 
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 );
 
4612
}
 
4613
inline
 
4614
static void shadow_mem_set64 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
 
4615
   CacheLine* cl; 
 
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;
 
4632
   return;
 
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 );
 
4637
}
 
4638
 
 
4639
static SVal shadow_mem_get8 ( Addr a ) {
 
4640
   CacheLine* cl; 
 
4641
   UWord      cloff, tno, toff;
 
4642
   UShort     descr;
 
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);
 
4652
   }
 
4653
   return cl->svals[cloff];
 
4654
}
 
4655
 
 
4656
static void shadow_mem_copy8 ( Addr src, Addr dst, Bool normalise ) {
 
4657
   SVal       sv;
 
4658
   stats__cline_copy8s++;
 
4659
   sv = shadow_mem_get8( src );
 
4660
 
 
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 );
 
4666
      }
 
4667
   }
 
4668
 
 
4669
   shadow_mem_set8( NULL/*unused*/, dst, sv );
 
4670
}
 
4671
 
 
4672
 
 
4673
/* ------------ Shadow memory range setting ops ------------ */
 
4674
 
 
4675
static void shadow_mem_modify_range(
 
4676
               Thread* thr, 
 
4677
               Addr    a, 
 
4678
               SizeT   len,
 
4679
               void    (*fn8) (Thread*,Addr,SVal),
 
4680
               void    (*fn16)(Thread*,Addr,SVal),
 
4681
               void    (*fn32)(Thread*,Addr,SVal),
 
4682
               void    (*fn64)(Thread*,Addr,SVal),
 
4683
               SVal    opaque
 
4684
            )
 
4685
{
 
4686
   /* fast track a couple of common cases */
 
4687
   if (len == 4 && aligned32(a)) {
 
4688
      fn32( thr, a, opaque );
 
4689
      return;
 
4690
   }
 
4691
   if (len == 8 && aligned64(a)) {
 
4692
      fn64( thr, a, opaque );
 
4693
      return;
 
4694
   }
 
4695
 
 
4696
   /* be completely general (but as efficient as possible) */
 
4697
   if (len == 0) return;
 
4698
 
 
4699
   if (!aligned16(a) && len >= 1) {
 
4700
      fn8( thr, a, opaque );
 
4701
      a += 1;
 
4702
      len -= 1;
 
4703
      tl_assert(aligned16(a));
 
4704
   }
 
4705
   if (len == 0) return;
 
4706
 
 
4707
   if (!aligned32(a) && len >= 2) {
 
4708
      fn16( thr, a, opaque );
 
4709
      a += 2;
 
4710
      len -= 2;
 
4711
      tl_assert(aligned32(a));
 
4712
   }
 
4713
   if (len == 0) return;
 
4714
 
 
4715
   if (!aligned64(a) && len >= 4) {
 
4716
      fn32( thr, a, opaque );
 
4717
      a += 4;
 
4718
      len -= 4;
 
4719
      tl_assert(aligned64(a));
 
4720
   }
 
4721
   if (len == 0) return;
 
4722
 
 
4723
   if (len >= 8) {
 
4724
      tl_assert(aligned64(a));
 
4725
      while (len >= 8) {
 
4726
         fn64( thr, a, opaque );
 
4727
         a += 8;
 
4728
         len -= 8;
 
4729
      }
 
4730
      tl_assert(aligned64(a));
 
4731
   }
 
4732
   if (len == 0) return;
 
4733
 
 
4734
   if (len >= 4)
 
4735
      tl_assert(aligned32(a));
 
4736
   if (len >= 4) {
 
4737
      fn32( thr, a, opaque );
 
4738
      a += 4;
 
4739
      len -= 4;
 
4740
   }
 
4741
   if (len == 0) return;
 
4742
 
 
4743
   if (len >= 2)
 
4744
      tl_assert(aligned16(a));
 
4745
   if (len >= 2) {
 
4746
      fn16( thr, a, opaque );
 
4747
      a += 2;
 
4748
      len -= 2;
 
4749
   }
 
4750
   if (len == 0) return;
 
4751
 
 
4752
   if (len >= 1) {
 
4753
      fn8( thr, a, opaque );
 
4754
      a += 1;
 
4755
      len -= 1;
 
4756
   }
 
4757
   tl_assert(len == 0);
 
4758
}
 
4759
 
 
4760
/* Block-copy states (needed for implementing realloc()). */
 
4761
static void shadow_mem_copy_range ( Addr src, Addr dst, SizeT len )
 
4762
{
 
4763
   SizeT i;
1627
4764
   if (len == 0)
1628
4765
      return;
1629
 
 
1630
 
   if (len > 100 * 1000 * 1000)
1631
 
      VG_(message)(Vg_UserMsg,
1632
 
                   "Warning: set address range state: large range %d",
1633
 
                   len);
1634
 
 
1635
 
   /* Remove mutexes in recycled memory range from hash */
1636
 
   find_mutex_range(a, a+len, cleanmx);
1637
 
 
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);
1645
 
 
1646
 
   /* Do it ... */
1647
 
   switch (status) {
1648
 
   case Vge_VirginInit:
1649
 
      for ( ; a < end; a += 4) {
1650
 
         //PROF_EVENT(31);  PPP
1651
 
         init_virgin_sword(a);
1652
 
      }
1653
 
      break;
1654
 
 
1655
 
   case Vge_NonVirginInit:
1656
 
      for ( ; a < end; a += 4) {
1657
 
         //PROF_EVENT(31);  PPP
1658
 
         init_nonvirgin_sword(a);
1659
 
      }
1660
 
      break;
1661
 
 
1662
 
   case Vge_SegmentInit:
1663
 
      for ( ; a < end; a += 4) {
1664
 
         //PROF_EVENT(31);  PPP
1665
 
         init_magically_inited_sword(a);
1666
 
      }
1667
 
      break;
1668
 
 
1669
 
   case Vge_Error:
1670
 
      for ( ; a < end; a += 4) {
1671
 
         //PROF_EVENT(31);  PPP
1672
 
         init_error_sword(a);
1673
 
      }
1674
 
      break;
 
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++) {
 
4771
      Bool normalise
 
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 );
 
4776
   }
 
4777
}
 
4778
 
 
4779
static void shadow_mem_read_range ( Thread* thr, Addr a, SizeT len ) {
 
4780
   shadow_mem_modify_range( thr, a, len, 
 
4781
                            shadow_mem_read8,
 
4782
                            shadow_mem_read16,
 
4783
                            shadow_mem_read32,
 
4784
                            shadow_mem_read64,
 
4785
                            0/*opaque,ignored*/ );
 
4786
}
 
4787
 
 
4788
static void shadow_mem_write_range ( Thread* thr, Addr a, SizeT len ) {
 
4789
   shadow_mem_modify_range( thr, a, len, 
 
4790
                            shadow_mem_write8,
 
4791
                            shadow_mem_write16,
 
4792
                            shadow_mem_write32,
 
4793
                            shadow_mem_write64,
 
4794
                            0/*opaque,ignored*/ );
 
4795
}
 
4796
 
 
4797
static void shadow_mem_make_New ( Thread* thr, Addr a, SizeT len )
 
4798
{
 
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 );
 
4803
      }
 
4804
   }
 
4805
   shadow_mem_modify_range( thr, a, len, 
 
4806
                            shadow_mem_set8,
 
4807
                            shadow_mem_set16,
 
4808
                            shadow_mem_set32,
 
4809
                            shadow_mem_set64,
 
4810
                            SHVAL_New/*opaque*/ );
 
4811
}
 
4812
 
 
4813
 
 
4814
/* Putting memory into the NoAccess state.  This is hugely complicated
 
4815
   by the problem of memory that contains locks.
 
4816
 
 
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.
 
4822
 
 
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.
 
4828
 
 
4829
   3. If (1) indicated "definitely no locks", we're done.  This is
 
4830
      the fast and hopefully common case.
 
4831
 
 
4832
   Otherwise, the range contains some locks (or may do), so we have to
 
4833
   go to considerable effort to tidy up.
 
4834
 
 
4835
   4. Make up a set containing the locks which are deleted:
 
4836
 
 
4837
      ToDelete = NULL
 
4838
 
 
4839
      for each lk in map_locks {
 
4840
         if lk's guest addr falls in the range to memory be deleted
 
4841
            add lk to ToDelete
 
4842
 
 
4843
         if lk is held, issue an error message - freeing memory
 
4844
            containing a held lock
 
4845
      }
 
4846
 
 
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.
 
4849
 
 
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.
 
4853
 
 
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.
 
4857
 
 
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.
 
4863
 
 
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.
 
4867
 
 
4868
      Optimisation 1 (implemented): skip this step for SecMaps which
 
4869
      do not have .mbHasShared set
 
4870
 
 
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.
 
4875
 
 
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.
 
4880
 
 
4881
   8. Tell laog that these locks have disappeared.
 
4882
*/
 
4883
static void shadow_mem_make_NoAccess ( Thread* thr, Addr aIN, SizeT len )
 
4884
{
 
4885
   Lock*     lk;
 
4886
   Addr      gla, sma, firstSM, lastSM, firstA, lastA;
 
4887
   WordSetID locksToDelete;
 
4888
   Bool      mbHasLocks;
 
4889
 
 
4890
   if (0 && len > 500)
 
4891
      VG_(printf)("make NoAccess ( %p, %d )\n", aIN, len );
 
4892
 
 
4893
   if (len == 0) 
 
4894
      return;
 
4895
 
 
4896
   /* --- Step 1 --- */
 
4897
 
 
4898
   firstA  = aIN;
 
4899
   lastA   = aIN + len - 1;
 
4900
 
 
4901
   firstSM = shmem__round_to_SecMap_base( firstA );
 
4902
   lastSM  = shmem__round_to_SecMap_base( lastA );
 
4903
   tl_assert(firstSM <= lastSM);
 
4904
 
 
4905
   mbHasLocks = False;
 
4906
   for (sma = firstSM; sma <= lastSM; sma += N_SECMAP_ARANGE) {
 
4907
      if (shmem__get_mbHasLocks(sma)) {
 
4908
         mbHasLocks = True;
 
4909
         break;
 
4910
      }
 
4911
   }
 
4912
 
 
4913
   /* --- Step 2 --- */
 
4914
 
 
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 );
 
4920
      }
 
4921
   }
 
4922
   shadow_mem_modify_range( thr, firstA, len, 
 
4923
                            shadow_mem_set8,
 
4924
                            shadow_mem_set16,
 
4925
                            shadow_mem_set32,
 
4926
                            shadow_mem_set64,
 
4927
                            SHVAL_NoAccess/*opaque*/ );
 
4928
 
 
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 );
 
4935
      }
 
4936
   }
 
4937
 
 
4938
   /* --- Step 3 --- */
 
4939
 
 
4940
   if (!mbHasLocks)
 
4941
      return;
 
4942
 
 
4943
   /* --- Step 4 --- */
 
4944
 
 
4945
   if (0) 
 
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 );
1675
4949
   
1676
 
   default:
1677
 
      VG_(printf)("init_status = %u\n", status);
1678
 
      VG_(tool_panic)("Unexpected Vge_InitStatus");
1679
 
   }
1680
 
}
1681
 
 
1682
 
 
1683
 
static void make_segment_readable ( Addr a, SizeT len )
1684
 
{
1685
 
   //PROF_EVENT(??);    PPP
1686
 
   set_address_range_state ( a, len, Vge_SegmentInit );
1687
 
}
1688
 
 
1689
 
static void make_writable ( Addr a, SizeT len )
1690
 
{
1691
 
   //PROF_EVENT(36);  PPP
1692
 
   set_address_range_state( a, len, Vge_VirginInit );
1693
 
}
1694
 
 
1695
 
static void make_readable ( Addr a, SizeT len )
1696
 
{
1697
 
   //PROF_EVENT(37);  PPP
1698
 
   set_address_range_state( a, len, Vge_VirginInit );
1699
 
}
1700
 
 
1701
 
 
1702
 
/* Block-copy states (needed for implementing realloc()). */
1703
 
static void copy_address_range_state(Addr src, Addr dst, SizeT len)
1704
 
{
1705
 
   UInt i;
1706
 
 
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 );
1712
 
   }
1713
 
}
1714
 
 
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);
1718
 
 
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);
1727
 
 
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);
1736
 
 
1737
 
__attribute__((unused))
1738
 
static void bus_lock(void);
1739
 
__attribute__((unused))
1740
 
static void bus_unlock(void);
1741
 
 
1742
 
static
1743
 
void hg_pre_mem_read(CorePart part, ThreadId tid,
1744
 
                     Char* s, Addr base, SizeT size )
1745
 
{
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);
1748
 
}
1749
 
 
1750
 
static
1751
 
void hg_pre_mem_read_asciiz(CorePart part, ThreadId tid,
1752
 
                            Char* s, Addr base )
1753
 
{
1754
 
   hg_mem_read(base, VG_(strlen)((Char*)base), tid);
1755
 
}
1756
 
 
1757
 
static
1758
 
void hg_pre_mem_write(CorePart part, ThreadId tid,
1759
 
                      Char* s, Addr base, SizeT size )
1760
 
{
1761
 
   hg_mem_write(base, size, tid);
1762
 
}
1763
 
 
1764
 
 
1765
 
 
1766
 
static
1767
 
void hg_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
1768
 
{
1769
 
   /* Ignore the permissions, just make it readable.  Seems to work... */
1770
 
   make_segment_readable(a, len);
1771
 
}
1772
 
 
1773
 
 
1774
 
static
1775
 
void hg_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
1776
 
{
 
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)
 
4956
         continue;
 
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
 
4963
         arbitrarily. */
 
4964
      if (lk->heldBy) {
 
4965
         tl_assert(!HG_(isEmptyBag)(lk->heldBy));
 
4966
         record_error_FreeMemLock( (Thread*)HG_(anyElementOfBag)(lk->heldBy),
 
4967
                                   lk );
 
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. */
 
4971
      }
 
4972
   }
 
4973
   HG_(doneIterFM)( map_locks );
 
4974
 
 
4975
   /* --- Step 5 --- */
 
4976
 
 
4977
   if (HG_(isEmptyWS)( univ_lsets, locksToDelete ))
 
4978
      return;
 
4979
 
 
4980
   /* --- Step 6 --- */
 
4981
 
 
4982
   shmem__flush_and_invalidate_scache();
 
4983
 
 
4984
   /* --- Step 7 --- */
 
4985
 
 
4986
   if (0) 
 
4987
   VG_(printf)("shadow_mem_make_NoAccess(%p, %u, %p): definitely slow case\n",
 
4988
               (void*)firstA, (UWord)len, (void*)lastA);
 
4989
 
 
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
 
4993
   */
 
4994
   { Int        stats_SMs = 0, stats_SMs_scanned = 0;
 
4995
     Addr       ga;
 
4996
     SecMap*    sm;
 
4997
     SecMapIter itr;
 
4998
     SVal*      w32p = NULL;
 
4999
 
 
5000
     HG_(initIterFM)( map_shmem );
 
5001
     while (HG_(nextIterFM)( map_shmem,
 
5002
                             (Word*)&ga, (Word*)&sm )) {
 
5003
        tl_assert(sm);
 
5004
        stats_SMs++;
 
5005
        /* Skip this SecMap if the summary bit indicates it is safe to
 
5006
           do so. */
 
5007
        if (!sm->mbHasShared)
 
5008
           continue;
 
5009
        stats_SMs_scanned++;
 
5010
        initSecMapIter( &itr );
 
5011
        while (stepSecMapIter( &w32p, &itr, sm )) {
 
5012
           Bool isM;
 
5013
           SVal wold, wnew; 
 
5014
           UInt lset_old, tset_old, lset_new;
 
5015
           wold = *w32p;
 
5016
           if (LIKELY( !is_SHVAL_Sh(wold) ))
 
5017
              continue;
 
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);
 
5024
           if (wnew != wold)
 
5025
              *w32p = wnew;
 
5026
        }
 
5027
     }
 
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);
 
5032
   }
 
5033
 
 
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
 
5036
      inefficient. */
 
5037
   { Lock* lkprev = NULL;
 
5038
     lk = admin_locks;
 
5039
     while (True) {
 
5040
        if (lk == NULL) break;
 
5041
        if (lkprev) tl_assert(lkprev->admin == lk);
 
5042
 
 
5043
        if (!HG_(elemWS)(univ_lsets, locksToDelete, (Word)lk)) {
 
5044
           lkprev = lk;
 
5045
           lk = lk->admin;
 
5046
           continue;
 
5047
        }
 
5048
        /* Need to delete 'lk' */
 
5049
        if (lkprev == NULL) {
 
5050
           admin_locks = lk->admin;
 
5051
        } else {
 
5052
           lkprev->admin = lk->admin;
 
5053
        }
 
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;
 
5058
          del_LockN(lk);
 
5059
          lk = tmp;
 
5060
        }
 
5061
     }
 
5062
   }
 
5063
 
 
5064
   /* --- Step 8 --- */
 
5065
 
 
5066
   /* update lock order acquisition graph */
 
5067
   laog__handle_lock_deletions( locksToDelete );
 
5068
 
 
5069
   if (0) all__sanity_check("Make NoAccess");
 
5070
}
 
5071
 
 
5072
 
 
5073
/*----------------------------------------------------------------*/
 
5074
/*--- Event handlers (evh__* functions)                        ---*/
 
5075
/*--- plus helpers (evhH__* functions)                         ---*/
 
5076
/*----------------------------------------------------------------*/
 
5077
 
 
5078
/*--------- Event handler helpers (evhH__* functions) ---------*/
 
5079
 
 
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
 
5083
   Segment. */
 
5084
static 
 
5085
void evhH__start_new_segment_for_thread ( /*OUT*/SegmentID* new_segidP,
 
5086
                                          /*OUT*/Segment** new_segP,
 
5087
                                          Thread* thr )
 
5088
{
 
5089
   Segment* cur_seg;
 
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 );
 
5094
   tl_assert(cur_seg);
 
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;
 
5101
}
 
5102
 
 
5103
 
 
5104
/* The lock at 'lock_ga' has acquired a writer.  Make all necessary
 
5105
   updates, and also do all possible error checks. */
 
5106
static 
 
5107
void evhH__post_thread_w_acquires_lock ( Thread* thr, 
 
5108
                                         LockKind lkk, Addr lock_ga )
 
5109
{
 
5110
   Lock* lk; 
 
5111
 
 
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
 
5116
      routine. 
 
5117
 
 
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. */
 
5122
 
 
5123
   /* be paranoid w.r.t hint bits, even if lock_ga is complete
 
5124
      nonsense */
 
5125
   shmem__set_mbHasLocks( lock_ga, True );
 
5126
 
 
5127
   tl_assert(is_sane_Thread(thr));
 
5128
   /* Try to find the lock.  If we can't, then create a new one with
 
5129
      kind 'lkk'. */
 
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 );
 
5134
 
 
5135
   if (lk->heldBy == NULL) {
 
5136
      /* the lock isn't held.  Simple. */
 
5137
      tl_assert(!lk->heldW);
 
5138
      lockN_acquire_writer( lk, thr );
 
5139
      goto noerror;
 
5140
   }
 
5141
 
 
5142
   /* So the lock is already held.  If held as a r-lock then
 
5143
      libpthread must be buggy. */
 
5144
   tl_assert(lk->heldBy);
 
5145
   if (!lk->heldW) {
 
5146
      record_error_Misc( thr, "Bug in libpthread: write lock "
 
5147
                              "granted on rwlock which is currently rd-held");
 
5148
      goto error;
 
5149
   }
 
5150
 
 
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 */
 
5154
 
 
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");
 
5159
      goto error;
 
5160
   }
 
5161
 
 
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
 
5166
      bug. */
 
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");
 
5171
      goto error;
 
5172
   }
 
5173
 
 
5174
   /* So we are recursively re-locking a lock we already w-hold. */
 
5175
   lockN_acquire_writer( lk, thr );
 
5176
   goto noerror;
 
5177
 
 
5178
  noerror:
 
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 );
 
5185
   /* fall through */
 
5186
 
 
5187
  error:
 
5188
   tl_assert(is_sane_LockN(lk));
 
5189
}
 
5190
 
 
5191
 
 
5192
/* The lock at 'lock_ga' has acquired a reader.  Make all necessary
 
5193
   updates, and also do all possible error checks. */
 
5194
static 
 
5195
void evhH__post_thread_r_acquires_lock ( Thread* thr, 
 
5196
                                         LockKind lkk, Addr lock_ga )
 
5197
{
 
5198
   Lock* lk; 
 
5199
 
 
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
 
5204
      routine. 
 
5205
 
 
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. */
 
5210
 
 
5211
   /* be paranoid w.r.t hint bits, even if lock_ga is complete
 
5212
      nonsense */
 
5213
   shmem__set_mbHasLocks( lock_ga, True );
 
5214
 
 
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 );
 
5224
 
 
5225
   if (lk->heldBy == NULL) {
 
5226
      /* the lock isn't held.  Simple. */
 
5227
      tl_assert(!lk->heldW);
 
5228
      lockN_acquire_reader( lk, thr );
 
5229
      goto noerror;
 
5230
   }
 
5231
 
 
5232
   /* So the lock is already held.  If held as a w-lock then
 
5233
      libpthread must be buggy. */
 
5234
   tl_assert(lk->heldBy);
 
5235
   if (lk->heldW) {
 
5236
      record_error_Misc( thr, "Bug in libpthread: read lock "
 
5237
                              "granted on rwlock which is "
 
5238
                              "currently wr-held");
 
5239
      goto error;
 
5240
   }
 
5241
 
 
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 );
 
5245
   goto noerror;
 
5246
 
 
5247
  noerror:
 
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 */
 
5254
   /* fall through */
 
5255
 
 
5256
  error:
 
5257
   tl_assert(is_sane_LockN(lk));
 
5258
}
 
5259
 
 
5260
 
 
5261
/* The lock at 'lock_ga' is just about to be unlocked.  Make all
 
5262
   necessary updates, and also do all possible error checks. */
 
5263
static 
 
5264
void evhH__pre_thread_releases_lock ( Thread* thr,
 
5265
                                      Addr lock_ga, Bool isRDWR )
 
5266
{
 
5267
   Lock* lock;
 
5268
   Word  n;
 
5269
 
 
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.
 
5274
 
 
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. */
 
5278
 
 
5279
   /* be paranoid w.r.t hint bits, even if lock_ga is complete
 
5280
      nonsense */
 
5281
   shmem__set_mbHasLocks( lock_ga, True );
 
5282
 
 
5283
   tl_assert(is_sane_Thread(thr));
 
5284
   lock = map_locks_maybe_lookup( lock_ga );
 
5285
 
 
5286
   if (!lock) {
 
5287
      /* We know nothing about a lock at 'lock_ga'.  Nevertheless
 
5288
         the client is trying to unlock it.  So complain, then ignore
 
5289
         the attempt. */
 
5290
      record_error_UnlockBogus( thr, lock_ga );
 
5291
      return;
 
5292
   }
 
5293
 
 
5294
   tl_assert(lock->guestaddr == lock_ga);
 
5295
   tl_assert(is_sane_LockN(lock));
 
5296
 
 
5297
   if (isRDWR && lock->kind != LK_rdwr) {
 
5298
      record_error_Misc( thr, "pthread_rwlock_unlock with a "
 
5299
                              "pthread_mutex_t* argument " );
 
5300
   }
 
5301
   if ((!isRDWR) && lock->kind == LK_rdwr) {
 
5302
      record_error_Misc( thr, "pthread_mutex_unlock with a "
 
5303
                              "pthread_rwlock_t* argument " );
 
5304
   }
 
5305
 
 
5306
   if (!lock->heldBy) {
 
5307
      /* The lock is not held.  This indicates a serious bug in the
 
5308
         client. */
 
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 ));
 
5313
      goto error;
 
5314
   }
 
5315
 
 
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 );
 
5319
   tl_assert(n >= 0);
 
5320
   if (n == 0) {
 
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
 
5324
         else. */
 
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 );
 
5331
      goto error;
 
5332
   }
 
5333
 
 
5334
   /* Ok, we hold the lock 'n' times. */
 
5335
   tl_assert(n >= 1);
 
5336
 
 
5337
   lockN_release( lock, thr );
 
5338
 
 
5339
   n--;
 
5340
   tl_assert(n >= 0);
 
5341
 
 
5342
   if (n > 0) {
 
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 ));
 
5350
      if (lock->heldW)
 
5351
         tl_assert(HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock ));
 
5352
      else
 
5353
         tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (Word)lock ));
 
5354
   } else {
 
5355
      /* We no longer hold the lock. */
 
5356
      if (lock->heldBy) {
 
5357
         tl_assert(0 == HG_(elemBag)( lock->heldBy, (Word)thr ));
 
5358
      }
 
5359
      /* update this thread's lockset accordingly. */
 
5360
      thr->locksetA
 
5361
         = HG_(delFromWS)( univ_lsets, thr->locksetA, (Word)lock );
 
5362
      thr->locksetW
 
5363
         = HG_(delFromWS)( univ_lsets, thr->locksetW, (Word)lock );
 
5364
   }
 
5365
   /* fall through */
 
5366
 
 
5367
  error:
 
5368
   tl_assert(is_sane_LockN(lock));
 
5369
}
 
5370
 
 
5371
 
 
5372
/*--------- Event handlers proper (evh__* functions) ---------*/
 
5373
 
 
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.
 
5380
 
 
5381
   Outside of client code, current_Thread is NULL, and presumably
 
5382
   any uses of it will cause a segfault.  Hence:
 
5383
 
 
5384
   - for uses definitely within client code, use
 
5385
     get_current_Thread_in_C_C.
 
5386
 
 
5387
   - for all other uses, use get_current_Thread.
 
5388
*/
 
5389
 
 
5390
static Thread* current_Thread = NULL;
 
5391
 
 
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);
 
5397
}
 
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;
 
5402
}
 
5403
static inline Thread* get_current_Thread_in_C_C ( void ) {
 
5404
   return current_Thread;
 
5405
}
 
5406
static inline Thread* get_current_Thread ( void ) {
 
5407
   ThreadId coretid;
 
5408
   Thread*  thr;
 
5409
   thr = get_current_Thread_in_C_C();
 
5410
   if (LIKELY(thr))
 
5411
      return thr;
 
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 );
 
5421
   return thr;
 
5422
}
 
5423
 
 
5424
static
 
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");
 
5431
}
 
5432
 
 
5433
static
 
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 );
 
5439
   if (rr || ww || 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");
 
5443
}
 
5444
 
 
5445
static
 
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. */
 
5454
   if (!(rr || ww))
 
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");
 
5458
}
 
5459
 
 
5460
static
 
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");
 
5467
}
 
5468
 
 
5469
static
 
5470
void evh__pre_thread_ll_create ( ThreadId parent, ThreadId child )
 
5471
{
 
5472
   if (SHOW_EVENTS >= 1)
 
5473
      VG_(printf)("evh__pre_thread_ll_create(p=%d, c=%d)\n",
 
5474
                  (Int)parent, (Int)child );
 
5475
 
 
5476
   if (parent != VG_INVALID_THREADID) {
 
5477
      Thread*   thr_p;
 
5478
      Thread*   thr_c;
 
5479
      SegmentID segid_c;
 
5480
      Segment*  seg_c;
 
5481
 
 
5482
      tl_assert(is_sane_ThreadId(parent));
 
5483
      tl_assert(is_sane_ThreadId(child));
 
5484
      tl_assert(parent != child);
 
5485
 
 
5486
      thr_p = map_threads_maybe_lookup( parent );
 
5487
      thr_c = map_threads_maybe_lookup( child );
 
5488
 
 
5489
      tl_assert(thr_p != NULL);
 
5490
      tl_assert(thr_c == NULL);
 
5491
 
 
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 );
 
5497
 
 
5498
      /* a Thread for the new thread ... */
 
5499
      thr_c = mk_Thread( segid_c );
 
5500
      seg_c->thr = thr_c;
 
5501
 
 
5502
      /* and bind it in the thread-map table */
 
5503
      map_threads[child] = thr_c;
 
5504
 
 
5505
      /* Record where the parent is so we can later refer to this in
 
5506
         error messages.
 
5507
 
 
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.
 
5515
      */
 
5516
      { Word first_ip_delta = 0;
 
5517
#       if defined(VGP_amd64_linux)
 
5518
        first_ip_delta = -3;
 
5519
#       endif
 
5520
        thr_c->created_at = VG_(record_ExeContext)(parent, first_ip_delta);
 
5521
      }
 
5522
 
 
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, 
 
5534
                                               thr_p );
 
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);
 
5539
         }
 
5540
      }
 
5541
   }
 
5542
 
 
5543
   if (clo_sanity_flags & SCE_THREADS)
 
5544
      all__sanity_check("evh__pre_thread_create-post");
 
5545
}
 
5546
 
 
5547
static
 
5548
void evh__pre_thread_ll_exit ( ThreadId quit_tid )
 
5549
{
 
5550
   Int     nHeld;
 
5551
   Thread* thr_q;
 
5552
   if (SHOW_EVENTS >= 1)
 
5553
      VG_(printf)("evh__pre_thread_ll_exit(thr=%d)\n",
 
5554
                  (Int)quit_tid );
 
5555
 
 
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
 
5564
      threads. */
 
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);
 
5573
 
 
5574
   /* Complain if this thread holds any locks. */
 
5575
   nHeld = HG_(cardinalityWS)( univ_lsets, thr_q->locksetA );
 
5576
   tl_assert(nHeld >= 0);
 
5577
   if (nHeld > 0) {
 
5578
      HChar buf[80];
 
5579
      VG_(sprintf)(buf, "Exiting thread still holds %d lock%s",
 
5580
                        nHeld, nHeld > 1 ? "s" : "");
 
5581
      record_error_Misc( thr_q, buf );
 
5582
   }
 
5583
 
 
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 );
 
5587
 
 
5588
   if (clo_sanity_flags & SCE_THREADS)
 
5589
      all__sanity_check("evh__pre_thread_ll_exit-post");
 
5590
}
 
5591
 
 
5592
static
 
5593
void evh__HG_PTHREAD_JOIN_POST ( ThreadId stay_tid, Thread* quit_thr )
 
5594
{
 
5595
   Int      stats_SMs, stats_SMs_scanned, stats_reExcls;
 
5596
   Addr     ga;
 
5597
   SecMap*  sm;
 
5598
   Thread*  thr_s;
 
5599
   Thread*  thr_q;
 
5600
 
 
5601
   if (SHOW_EVENTS >= 1)
 
5602
      VG_(printf)("evh__post_thread_join(stayer=%d, quitter=%p)\n",
 
5603
                  (Int)stay_tid, quit_thr );
 
5604
 
 
5605
   tl_assert(is_sane_ThreadId(stay_tid));
 
5606
 
 
5607
   thr_s = map_threads_maybe_lookup( stay_tid );
 
5608
   thr_q = quit_thr;
 
5609
   tl_assert(thr_s != NULL);
 
5610
   tl_assert(thr_q != NULL);
 
5611
   tl_assert(thr_s != thr_q);
 
5612
 
 
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 );
 
5627
   }
 
5628
 
 
5629
   // FIXME: error-if: exiting thread holds any locks
 
5630
   //        or should evh__pre_thread_ll_exit do that?
 
5631
 
 
5632
   /* Delete thread from ShM/ShR thread sets and restore Excl states
 
5633
      where appropriate */
 
5634
 
 
5635
   /* When Thread(t) joins to Thread(u):
 
5636
 
 
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).
 
5640
 
 
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.
 
5645
 
 
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
 
5648
      shadow value.)
 
5649
 
 
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
 
5653
          not set.
 
5654
 
 
5655
      .mbHasShared bits are (effectively) cached in cache_shmem.
 
5656
      Hence that must be flushed before we can safely consult them.
 
5657
 
 
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.
 
5661
   */
 
5662
   shmem__flush_and_invalidate_scache();
 
5663
 
 
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 )) {
 
5668
      SecMapIter itr;
 
5669
      SVal*      w32p = NULL;
 
5670
      tl_assert(sm);
 
5671
      stats_SMs++;
 
5672
      /* Skip this SecMap if the summary bit indicates it is safe to
 
5673
         do so. */
 
5674
      if (!sm->mbHasShared)
 
5675
         continue;
 
5676
      stats_SMs_scanned++;
 
5677
      initSecMapIter( &itr );
 
5678
      while (stepSecMapIter( &w32p, &itr, sm )) {
 
5679
         Bool isM;
 
5680
         SVal wnew, wold;
 
5681
         UInt lset_old, tset_old, tset_new;
 
5682
         wold = *w32p;
 
5683
         if (!is_SHVAL_Sh(wold))
 
5684
            continue;
 
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. */
 
5692
         tset_new 
 
5693
            = HG_(elemWS)( univ_tsets, tset_old, (Word)thr_q )
 
5694
              ? HG_(addToWS)(
 
5695
                   univ_tsets, 
 
5696
                   HG_(delFromWS)( univ_tsets, tset_old, (Word)thr_q ),
 
5697
                   (Word)thr_s 
 
5698
                )
 
5699
              : tset_old;
 
5700
 
 
5701
         tl_assert(HG_(cardinalityWS)(univ_tsets, tset_new) 
 
5702
                   <= HG_(cardinalityWS)(univ_tsets, tset_old));
 
5703
 
 
5704
         if (0) {
 
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 );
 
5710
            VG_(printf)("\n");
 
5711
         }
 
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);
 
5715
            stats_reExcls++;
 
5716
         } else {
 
5717
            wnew = isM ? mk_SHVAL_ShM(tset_new, lset_old)
 
5718
                       : mk_SHVAL_ShR(tset_new, lset_old);
 
5719
         }
 
5720
         *w32p = wnew;
 
5721
      }
 
5722
   }
 
5723
   HG_(doneIterFM)( map_shmem );
 
5724
 
 
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);
 
5729
 
 
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);
 
5738
 
 
5739
   if (clo_sanity_flags & SCE_THREADS)
 
5740
      all__sanity_check("evh__post_thread_join-post");
 
5741
}
 
5742
 
 
5743
static
 
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");
 
5753
}
 
5754
 
 
5755
static
 
5756
void evh__pre_mem_read_asciiz ( CorePart part, ThreadId tid,
 
5757
                                Char* s, Addr a ) {
 
5758
   Int len;
 
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");
 
5767
}
 
5768
 
 
5769
static
 
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");
 
5778
}
 
5779
 
 
5780
static
 
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);
1779
 
   } else {
1780
 
      make_writable(a, len);
1781
 
   }
1782
 
}
1783
 
 
1784
 
static
1785
 
void hg_set_perms (Addr a, SizeT len,
1786
 
                   Bool rr, Bool ww, Bool xx)
1787
 
{
1788
 
   if      (rr) make_readable(a, len);
1789
 
   else if (ww) make_writable(a, len);
1790
 
   /* else do nothing */
1791
 
}
1792
 
 
1793
 
static
1794
 
void hg_new_mem_stack_private(Addr a, SizeT len)
1795
 
{
1796
 
   set_address_range_state(a, len, Vge_NonVirginInit);
1797
 
}
1798
 
 
1799
 
static
1800
 
void hg_new_mem_stack(Addr a, SizeT len)
1801
 
{
1802
 
   set_address_range_state(a, len, Vge_VirginInit);
1803
 
}
1804
 
 
1805
 
/*--------------------------------------------------------------*/
1806
 
/*--- Initialise the memory audit system on program startup. ---*/
1807
 
/*--------------------------------------------------------------*/
1808
 
 
1809
 
static 
1810
 
void init_shadow_memory(void)
1811
 
{
1812
 
   Int i;
1813
 
 
1814
 
   for (i = 0; i < ESEC_MAP_WORDS; i++)
1815
 
      distinguished_secondary_map.swords[i] = virgin_sword;
1816
 
 
1817
 
   /* These entries gradually get overwritten as the used address
1818
 
      space expands. */
1819
 
   for (i = 0; i < 65536; i++)
1820
 
      primary_map[i] = &distinguished_secondary_map;
1821
 
}
1822
 
 
1823
 
 
1824
 
/*------------------------------------------------------------*/
1825
 
/*--- malloc() et al replacements                          ---*/
1826
 
/*------------------------------------------------------------*/
1827
 
 
1828
 
static VgHashTable hg_malloc_list = NULL;
1829
 
 
1830
 
#define N_FREED_CHUNKS  2
1831
 
static Int freechunkptr = 0;
1832
 
static HG_Chunk *freechunks[N_FREED_CHUNKS];
1833
 
 
1834
 
 
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. */
1839
 
 
1840
 
static void add_HG_Chunk ( ThreadId tid, Addr p, SizeT size )
1841
 
{
1842
 
   HG_Chunk* hc;
1843
 
 
1844
 
   hc            = VG_(malloc)(sizeof(HG_Chunk));
1845
 
   hc->data      = p;
1846
 
   hc->size      = size;
1847
 
   hc->where     = VG_(record_ExeContext)(tid);
1848
 
   hc->tid       = tid;
1849
 
 
1850
 
   VG_(HT_add_node)( hg_malloc_list, (VgHashNode*)hc );
1851
 
}
1852
 
 
1853
 
/* Allocate memory and note change in memory available */
1854
 
static __inline__
1855
 
void* alloc_and_new_mem ( ThreadId tid, SizeT size, SizeT alignment,
1856
 
                          Bool is_zeroed )
1857
 
{
1858
 
   Addr p;
1859
 
 
1860
 
   if (size < 0) return NULL;
1861
 
 
1862
 
   p = (Addr)VG_(cli_malloc)(alignment, size);
 
5787
      shadow_mem_make_New(get_current_Thread(), a, len);
 
5788
   } else {
 
5789
      shadow_mem_make_New(get_current_Thread(), a, len);
 
5790
   }
 
5791
   if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE))
 
5792
      all__sanity_check("evh__pre_mem_read-post");
 
5793
}
 
5794
 
 
5795
static
 
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");
 
5802
}
 
5803
 
 
5804
// thread async exit?
 
5805
 
 
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*/ );
 
5809
}
 
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*/ );
 
5813
}
 
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*/ );
 
5817
}
 
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*/ );
 
5821
}
 
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 );
 
5825
}
 
5826
 
 
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*/ );
 
5830
}
 
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*/ );
 
5834
}
 
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*/ );
 
5838
}
 
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*/ );
 
5842
}
 
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 );
 
5846
}
 
5847
 
 
5848
static void evh__bus_lock(void) {
 
5849
   Thread* thr;
 
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 );
 
5854
}
 
5855
static void evh__bus_unlock(void) {
 
5856
   Thread* thr;
 
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*/ );
 
5861
}
 
5862
 
 
5863
 
 
5864
/* -------------- events to do with mutexes -------------- */
 
5865
 
 
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. */
 
5870
static
 
5871
void evh__HG_PTHREAD_MUTEX_INIT_POST( ThreadId tid, 
 
5872
                                      void* mutex, Word mbRec )
 
5873
{
 
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,
 
5879
                               (Addr)mutex, tid );
 
5880
   if (clo_sanity_flags & SCE_LOCKS)
 
5881
      all__sanity_check("evh__hg_PTHREAD_MUTEX_INIT_POST");
 
5882
}
 
5883
 
 
5884
static
 
5885
void evh__HG_PTHREAD_MUTEX_DESTROY_PRE( ThreadId tid, void* mutex )
 
5886
{
 
5887
   Thread* thr;
 
5888
   Lock*   lk;
 
5889
   if (SHOW_EVENTS >= 1)
 
5890
      VG_(printf)("evh__hg_PTHREAD_MUTEX_DESTROY_PRE(ctid=%d, %p)\n", 
 
5891
                  (Int)tid, (void*)mutex );
 
5892
 
 
5893
   thr = map_threads_maybe_lookup( tid );
 
5894
   /* cannot fail - Thread* must already exist */
 
5895
   tl_assert( is_sane_Thread(thr) );
 
5896
 
 
5897
   lk = map_locks_maybe_lookup( (Addr)mutex );
 
5898
 
 
5899
   if (lk == NULL || (lk->kind != LK_nonRec && lk->kind != LK_mbRec)) {
 
5900
      record_error_Misc( thr,
 
5901
                         "pthread_mutex_destroy with invalid argument" );
 
5902
   }
 
5903
 
 
5904
   if (lk) {
 
5905
      tl_assert( is_sane_LockN(lk) );
 
5906
      tl_assert( lk->guestaddr == (Addr)mutex );
 
5907
      if (lk->heldBy) {
 
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 );
 
5913
         lk->heldBy = NULL;
 
5914
         lk->heldW = False;
 
5915
         lk->acquired_at = NULL;
 
5916
      }
 
5917
      tl_assert( !lk->heldBy );
 
5918
      tl_assert( is_sane_LockN(lk) );
 
5919
   }
 
5920
 
 
5921
   if (clo_sanity_flags & SCE_LOCKS)
 
5922
      all__sanity_check("evh__hg_PTHREAD_MUTEX_DESTROY_PRE");
 
5923
}
 
5924
 
 
5925
static void evh__HG_PTHREAD_MUTEX_LOCK_PRE ( ThreadId tid,
 
5926
                                             void* mutex, Word isTryLock )
 
5927
{
 
5928
   /* Just check the mutex is sane; nothing else to do. */
 
5929
   // 'mutex' may be invalid - not checked by wrapper
 
5930
   Thread* thr;
 
5931
   Lock*   lk;
 
5932
   if (SHOW_EVENTS >= 1)
 
5933
      VG_(printf)("evh__hg_PTHREAD_MUTEX_LOCK_PRE(ctid=%d, mutex=%p)\n", 
 
5934
                  (Int)tid, (void*)mutex );
 
5935
 
 
5936
   tl_assert(isTryLock == 0 || isTryLock == 1);
 
5937
   thr = map_threads_maybe_lookup( tid );
 
5938
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
5939
 
 
5940
   lk = map_locks_maybe_lookup( (Addr)mutex );
 
5941
 
 
5942
   if (lk && (lk->kind == LK_rdwr)) {
 
5943
      record_error_Misc( thr, "pthread_mutex_lock with a "
 
5944
                              "pthread_rwlock_t* argument " );
 
5945
   }
 
5946
 
 
5947
   if ( lk 
 
5948
        && isTryLock == 0
 
5949
        && (lk->kind == LK_nonRec || lk->kind == LK_rdwr)
 
5950
        && lk->heldBy
 
5951
        && lk->heldW
 
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" );
 
5959
   }
 
5960
}
 
5961
 
 
5962
static void evh__HG_PTHREAD_MUTEX_LOCK_POST ( ThreadId tid, void* mutex )
 
5963
{
 
5964
   // only called if the real library call succeeded - so mutex is sane
 
5965
   Thread* thr;
 
5966
   if (SHOW_EVENTS >= 1)
 
5967
      VG_(printf)("evh__HG_PTHREAD_MUTEX_LOCK_POST(ctid=%d, mutex=%p)\n", 
 
5968
                  (Int)tid, (void*)mutex );
 
5969
 
 
5970
   thr = map_threads_maybe_lookup( tid );
 
5971
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
5972
 
 
5973
   evhH__post_thread_w_acquires_lock( 
 
5974
      thr, 
 
5975
      LK_mbRec, /* if not known, create new lock with this LockKind */
 
5976
      (Addr)mutex
 
5977
   );
 
5978
}
 
5979
 
 
5980
static void evh__HG_PTHREAD_MUTEX_UNLOCK_PRE ( ThreadId tid, void* mutex )
 
5981
{
 
5982
   // 'mutex' may be invalid - not checked by wrapper
 
5983
   Thread* thr;
 
5984
   if (SHOW_EVENTS >= 1)
 
5985
      VG_(printf)("evh__HG_PTHREAD_MUTEX_UNLOCK_PRE(ctid=%d, mutex=%p)\n", 
 
5986
                  (Int)tid, (void*)mutex );
 
5987
 
 
5988
   thr = map_threads_maybe_lookup( tid );
 
5989
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
5990
 
 
5991
   evhH__pre_thread_releases_lock( thr, (Addr)mutex, False/*!isRDWR*/ );
 
5992
}
 
5993
 
 
5994
static void evh__HG_PTHREAD_MUTEX_UNLOCK_POST ( ThreadId tid, void* mutex )
 
5995
{
 
5996
   // only called if the real library call succeeded - so mutex is sane
 
5997
   Thread* thr;
 
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 */
 
6003
 
 
6004
   // anything we should do here?
 
6005
}
 
6006
 
 
6007
 
 
6008
/* --------------- events to do with CVs --------------- */
 
6009
 
 
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.
 
6014
*/
 
6015
 
 
6016
/* pthread_mutex_cond* -> Segment* */
 
6017
static WordFM* map_cond_to_Segment = NULL;
 
6018
 
 
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);
 
6023
   }
 
6024
}
 
6025
 
 
6026
static void evh__HG_PTHREAD_COND_SIGNAL_PRE ( ThreadId tid, void* cond )
 
6027
{
 
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. */
 
6034
 
 
6035
   Thread*   thr;
 
6036
   SegmentID new_segid;
 
6037
   Segment*  new_seg;
 
6038
 
 
6039
   if (SHOW_EVENTS >= 1)
 
6040
      VG_(printf)("evh__HG_PTHREAD_COND_SIGNAL_PRE(ctid=%d, cond=%p)\n", 
 
6041
                  (Int)tid, (void*)cond );
 
6042
 
 
6043
   map_cond_to_Segment_INIT();
 
6044
   thr = map_threads_maybe_lookup( tid );
 
6045
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
6046
 
 
6047
   // error-if: mutex is bogus
 
6048
   // error-if: mutex is not locked
 
6049
 
 
6050
   if (clo_happens_before >= 2) {
 
6051
      /* create a new segment ... */
 
6052
      new_segid = 0; /* bogus */
 
6053
      new_seg   = NULL;
 
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 );
 
6061
 
 
6062
      /* ... and add the binding. */
 
6063
      HG_(addToFM)( map_cond_to_Segment, (Word)cond,
 
6064
                                         (Word)(new_seg->prev) );
 
6065
   }
 
6066
}
 
6067
 
 
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 )
 
6072
{
 
6073
   Thread* thr;
 
6074
   Lock*   lk;
 
6075
   Bool    lk_valid = True;
 
6076
 
 
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 );
 
6081
 
 
6082
   map_cond_to_Segment_INIT();
 
6083
   thr = map_threads_maybe_lookup( tid );
 
6084
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
6085
 
 
6086
   lk = map_locks_maybe_lookup( (Addr)mutex );
 
6087
 
 
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
 
6090
      is wrong. */
 
6091
   if (lk == NULL) {
 
6092
      lk_valid = False;
 
6093
      record_error_Misc( 
 
6094
         thr, 
 
6095
         "pthread_cond_{timed}wait called with invalid mutex" );
 
6096
   } else {
 
6097
      tl_assert( is_sane_LockN(lk) );
 
6098
      if (lk->kind == LK_rdwr) {
 
6099
         lk_valid = False;
 
6100
         record_error_Misc( 
 
6101
            thr, "pthread_cond_{timed}wait called with mutex "
 
6102
                 "of type pthread_rwlock_t*" );
 
6103
      } else
 
6104
         if (lk->heldBy == NULL) {
 
6105
         lk_valid = False;
 
6106
         record_error_Misc( 
 
6107
            thr, "pthread_cond_{timed}wait called with un-held mutex");
 
6108
      } else
 
6109
      if (lk->heldBy != NULL
 
6110
          && HG_(elemBag)( lk->heldBy, (Word)thr ) == 0) {
 
6111
         lk_valid = False;
 
6112
         record_error_Misc( 
 
6113
            thr, "pthread_cond_{timed}wait called with mutex "
 
6114
                 "held by a different thread" );
 
6115
      }
 
6116
   }
 
6117
 
 
6118
   // error-if: cond is also associated with a different mutex
 
6119
 
 
6120
   return lk_valid;
 
6121
}
 
6122
 
 
6123
static void evh__HG_PTHREAD_COND_WAIT_POST ( ThreadId tid,
 
6124
                                             void* cond, void* mutex )
 
6125
{
 
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. */
 
6130
 
 
6131
   Thread*   thr;
 
6132
   SegmentID new_segid;
 
6133
   Segment*  new_seg;
 
6134
   Segment*  signalling_seg;
 
6135
   Bool      found;
 
6136
 
 
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 );
 
6141
 
 
6142
   map_cond_to_Segment_INIT();
 
6143
   thr = map_threads_maybe_lookup( tid );
 
6144
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
6145
 
 
6146
   // error-if: cond is also associated with a different mutex
 
6147
 
 
6148
   if (clo_happens_before >= 2) {
 
6149
      /* create a new segment ... */
 
6150
      new_segid = 0; /* bogus */
 
6151
      new_seg   = NULL;
 
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);
 
6158
 
 
6159
      /* and find out which thread signalled us; then add a dependency
 
6160
         edge back to it. */
 
6161
      signalling_seg = NULL;
 
6162
      found = HG_(lookupFM)( map_cond_to_Segment, 
 
6163
                             NULL, (Word*)&signalling_seg,
 
6164
                                   (Word)cond );
 
6165
      if (found) {
 
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( 
 
6173
                           new_seg->thr, 
 
6174
                           new_seg->prev->vts,
 
6175
                           new_seg->other->vts );
 
6176
      } else {
 
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
 
6180
            wakeups". */
 
6181
         record_error_Misc( thr, "Bug in libpthread: pthread_cond_wait "
 
6182
                                 "succeeded on"
 
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 );
 
6186
      }
 
6187
   }
 
6188
}
 
6189
 
 
6190
 
 
6191
/* -------------- events to do with rwlocks -------------- */
 
6192
 
 
6193
/* EXPOSITION only */
 
6194
static
 
6195
void evh__HG_PTHREAD_RWLOCK_INIT_POST( ThreadId tid, void* rwl )
 
6196
{
 
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");
 
6203
}
 
6204
 
 
6205
static
 
6206
void evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( ThreadId tid, void* rwl )
 
6207
{
 
6208
   Thread* thr;
 
6209
   Lock*   lk;
 
6210
   if (SHOW_EVENTS >= 1)
 
6211
      VG_(printf)("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE(ctid=%d, %p)\n", 
 
6212
                  (Int)tid, (void*)rwl );
 
6213
 
 
6214
   thr = map_threads_maybe_lookup( tid );
 
6215
   /* cannot fail - Thread* must already exist */
 
6216
   tl_assert( is_sane_Thread(thr) );
 
6217
 
 
6218
   lk = map_locks_maybe_lookup( (Addr)rwl );
 
6219
 
 
6220
   if (lk == NULL || lk->kind != LK_rdwr) {
 
6221
      record_error_Misc( thr,
 
6222
                         "pthread_rwlock_destroy with invalid argument" );
 
6223
   }
 
6224
 
 
6225
   if (lk) {
 
6226
      tl_assert( is_sane_LockN(lk) );
 
6227
      tl_assert( lk->guestaddr == (Addr)rwl );
 
6228
      if (lk->heldBy) {
 
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 );
 
6234
         lk->heldBy = NULL;
 
6235
         lk->heldW = False;
 
6236
         lk->acquired_at = NULL;
 
6237
      }
 
6238
      tl_assert( !lk->heldBy );
 
6239
      tl_assert( is_sane_LockN(lk) );
 
6240
   }
 
6241
 
 
6242
   if (clo_sanity_flags & SCE_LOCKS)
 
6243
      all__sanity_check("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE");
 
6244
}
 
6245
 
 
6246
static 
 
6247
void evh__HG_PTHREAD_RWLOCK_LOCK_PRE ( ThreadId tid,
 
6248
                                       void* rwl,
 
6249
                                       Word isW, Word isTryLock )
 
6250
{
 
6251
   /* Just check the rwl is sane; nothing else to do. */
 
6252
   // 'rwl' may be invalid - not checked by wrapper
 
6253
   Thread* thr;
 
6254
   Lock*   lk;
 
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 );
 
6258
 
 
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 */
 
6263
 
 
6264
   lk = map_locks_maybe_lookup( (Addr)rwl );
 
6265
   if ( lk 
 
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 " );
 
6270
   }
 
6271
}
 
6272
 
 
6273
static 
 
6274
void evh__HG_PTHREAD_RWLOCK_LOCK_POST ( ThreadId tid, void* rwl, Word isW )
 
6275
{
 
6276
   // only called if the real library call succeeded - so mutex is sane
 
6277
   Thread* thr;
 
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 );
 
6281
 
 
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 */
 
6285
 
 
6286
   (isW ? evhH__post_thread_w_acquires_lock 
 
6287
        : evhH__post_thread_r_acquires_lock)( 
 
6288
      thr, 
 
6289
      LK_rdwr, /* if not known, create new lock with this LockKind */
 
6290
      (Addr)rwl
 
6291
   );
 
6292
}
 
6293
 
 
6294
static void evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE ( ThreadId tid, void* rwl )
 
6295
{
 
6296
   // 'rwl' may be invalid - not checked by wrapper
 
6297
   Thread* thr;
 
6298
   if (SHOW_EVENTS >= 1)
 
6299
      VG_(printf)("evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE(ctid=%d, rwl=%p)\n", 
 
6300
                  (Int)tid, (void*)rwl );
 
6301
 
 
6302
   thr = map_threads_maybe_lookup( tid );
 
6303
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
6304
 
 
6305
   evhH__pre_thread_releases_lock( thr, (Addr)rwl, True/*isRDWR*/ );
 
6306
}
 
6307
 
 
6308
static void evh__HG_PTHREAD_RWLOCK_UNLOCK_POST ( ThreadId tid, void* rwl )
 
6309
{
 
6310
   // only called if the real library call succeeded - so mutex is sane
 
6311
   Thread* thr;
 
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 */
 
6317
 
 
6318
   // anything we should do here?
 
6319
}
 
6320
 
 
6321
 
 
6322
/* --------------- events to do with semaphores --------------- */
 
6323
 
 
6324
/* This is similar to but not identical to the handling for condition
 
6325
   variables. */
 
6326
 
 
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.
 
6331
 
 
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.
 
6337
 
 
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.
 
6341
 
 
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.
 
6346
 
 
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.
 
6352
 
 
6353
   We don't emit an error for DESTROY_PRE on a semaphore we don't know
 
6354
   about.  We should.
 
6355
*/
 
6356
 
 
6357
/* sem_t* -> XArray* Segment* */
 
6358
static WordFM* map_sem_to_Segment_stack = NULL;
 
6359
 
 
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);
 
6364
   }
 
6365
}
 
6366
 
 
6367
static void push_Segment_for_sem ( void* sem, Segment* seg ) {
 
6368
   XArray* xa;
 
6369
   tl_assert(seg);
 
6370
   map_sem_to_Segment_stack_INIT();
 
6371
   if (HG_(lookupFM)( map_sem_to_Segment_stack, 
 
6372
                      NULL, (Word*)&xa, (Word)sem )) {
 
6373
      tl_assert(xa);
 
6374
      VG_(addToXA)( xa, &seg );
 
6375
   } else {
 
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 );
 
6379
   }
 
6380
}
 
6381
 
 
6382
static Segment* mb_pop_Segment_for_sem ( void* sem ) {
 
6383
   XArray*  xa;
 
6384
   Segment* seg;
 
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 );
 
6390
      tl_assert(sz >= 0);
 
6391
      if (sz == 0)
 
6392
         return NULL; /* odd, the stack is empty */
 
6393
      seg = *(Segment**)VG_(indexXA)( xa, sz-1 );
 
6394
      tl_assert(seg);
 
6395
      VG_(dropTailXA)( xa, 1 );
 
6396
      return seg;
 
6397
   } else {
 
6398
      /* hmm, that's odd.  No stack for this semaphore. */
 
6399
      return NULL;
 
6400
   }
 
6401
}
 
6402
 
 
6403
static void evh__HG_POSIX_SEM_DESTROY_PRE ( ThreadId tid, void* sem )
 
6404
{
 
6405
   Segment* seg;
 
6406
 
 
6407
   if (SHOW_EVENTS >= 1)
 
6408
      VG_(printf)("evh__HG_POSIX_SEM_DESTROY_PRE(ctid=%d, sem=%p)\n", 
 
6409
                  (Int)tid, (void*)sem );
 
6410
 
 
6411
   /* Empty out the semaphore's segment stack.  This way of doing it
 
6412
      is stupid, but at least it's easy. */
 
6413
   do {
 
6414
     seg = mb_pop_Segment_for_sem( sem );
 
6415
   } while (seg);
 
6416
 
 
6417
   tl_assert(!seg);
 
6418
}
 
6419
 
 
6420
static 
 
6421
void evh__HG_POSIX_SEM_INIT_POST ( ThreadId tid, void* sem, UWord value )
 
6422
{
 
6423
   Segment* seg;
 
6424
 
 
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 );
 
6428
 
 
6429
   /* Empty out the semaphore's segment stack.  This way of doing it
 
6430
      is stupid, but at least it's easy. */
 
6431
   do {
 
6432
     seg = mb_pop_Segment_for_sem( sem );
 
6433
   } while (seg);
 
6434
   tl_assert(!seg);
 
6435
 
 
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. */
 
6439
   if (value > 0) {
 
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 */
 
6445
 
 
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 );
 
6453
 
 
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'. */
 
6457
         record_error_Misc(
 
6458
            thr, "sem_init: initial value exceeds 10000; using 10000" );
 
6459
         value = 10000;
 
6460
      }
 
6461
 
 
6462
      while (value > 0) {
 
6463
         push_Segment_for_sem( sem, new_seg->prev );
 
6464
         value--;
 
6465
      }
 
6466
   }
 
6467
}
 
6468
 
 
6469
static void evh__HG_POSIX_SEM_POST_PRE ( ThreadId tid, void* sem )
 
6470
{
 
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
 
6476
      constructed. */
 
6477
 
 
6478
   Thread*   thr;
 
6479
   SegmentID new_segid;
 
6480
   Segment*  new_seg;
 
6481
 
 
6482
   if (SHOW_EVENTS >= 1)
 
6483
      VG_(printf)("evh__HG_POSIX_SEM_POST_PRE(ctid=%d, sem=%p)\n", 
 
6484
                  (Int)tid, (void*)sem );
 
6485
 
 
6486
   thr = map_threads_maybe_lookup( tid );
 
6487
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
6488
 
 
6489
   // error-if: sem is bogus
 
6490
 
 
6491
   if (clo_happens_before >= 2) {
 
6492
      /* create a new segment ... */
 
6493
      new_segid = 0; /* bogus */
 
6494
      new_seg   = NULL;
 
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 );
 
6502
 
 
6503
      /* ... and add the binding. */
 
6504
      push_Segment_for_sem( sem, new_seg->prev );
 
6505
   }
 
6506
}
 
6507
 
 
6508
static void evh__HG_POSIX_SEM_WAIT_POST ( ThreadId tid, void* sem )
 
6509
{
 
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
 
6513
      it. */
 
6514
 
 
6515
   Thread*   thr;
 
6516
   SegmentID new_segid;
 
6517
   Segment*  new_seg;
 
6518
   Segment*  posting_seg;
 
6519
 
 
6520
   if (SHOW_EVENTS >= 1)
 
6521
      VG_(printf)("evh__HG_POSIX_SEM_WAIT_POST(ctid=%d, sem=%p)\n", 
 
6522
                  (Int)tid, (void*)sem );
 
6523
 
 
6524
   thr = map_threads_maybe_lookup( tid );
 
6525
   tl_assert(thr); /* cannot fail - Thread* must already exist */
 
6526
 
 
6527
   // error-if: sem is bogus
 
6528
 
 
6529
   if (clo_happens_before >= 2) {
 
6530
      /* create a new segment ... */
 
6531
      new_segid = 0; /* bogus */
 
6532
      new_seg   = NULL;
 
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);
 
6539
 
 
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 );
 
6543
      if (posting_seg) {
 
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( 
 
6551
                           new_seg->thr, 
 
6552
                           new_seg->prev->vts,
 
6553
                           new_seg->other->vts );
 
6554
      } else {
 
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
 
6557
            threads library. */
 
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 );
 
6562
      }
 
6563
   }
 
6564
}
 
6565
 
 
6566
 
 
6567
/*--------------------------------------------------------------*/
 
6568
/*--- Lock acquisition order monitoring                      ---*/
 
6569
/*--------------------------------------------------------------*/
 
6570
 
 
6571
/* FIXME: here are some optimisations still to do in
 
6572
          laog__pre_thread_acquires_lock.
 
6573
 
 
6574
   The graph is structured so that if L1 --*--> L2 then L1 must be
 
6575
   acquired before L2.
 
6576
 
 
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:
 
6580
 
 
6581
   (1) searches laog to see if Ln --*--> {L1,L2,L3}, which always 
 
6582
       produces the answer No (because there is no error).
 
6583
 
 
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).
 
6586
 
 
6587
   Hence cache these two events:
 
6588
 
 
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.
 
6591
 
 
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.
 
6595
*/
 
6596
 
 
6597
typedef
 
6598
   struct {
 
6599
      WordSetID inns; /* in univ_laog */
 
6600
      WordSetID outs; /* in univ_laog */
 
6601
   }
 
6602
   LAOGLinks;
 
6603
 
 
6604
/* lock order acquisition graph */
 
6605
static WordFM* laog = NULL; /* WordFM Lock* LAOGLinks* */
 
6606
 
 
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
 
6609
   we need to. */
 
6610
typedef
 
6611
   struct {
 
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 */
 
6616
   }
 
6617
   LAOGLinkExposition;
 
6618
 
 
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;
 
6627
   return 0;
 
6628
}
 
6629
 
 
6630
static WordFM* laog_exposition = NULL; /* WordFM LAOGLinkExposition* NULL */
 
6631
/* end EXPOSITION ONLY */
 
6632
 
 
6633
 
 
6634
static void laog__show ( Char* who ) {
 
6635
   Word i, ws_size;
 
6636
   Word* ws_words;
 
6637
   Lock* me;
 
6638
   LAOGLinks* links;
 
6639
   VG_(printf)("laog (requested by %s) {\n", who);
 
6640
   HG_(initIterFM)( laog );
 
6641
   me = NULL;
 
6642
   links = NULL;
 
6643
   while (HG_(nextIterFM)( laog, (Word*)&me,
 
6644
                                 (Word*)&links )) {
 
6645
      tl_assert(me);
 
6646
      tl_assert(links);
 
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] );
 
6654
      me = NULL;
 
6655
      links = NULL;
 
6656
   }
 
6657
   HG_(doneIterFM)( laog );
 
6658
   VG_(printf)("}\n");
 
6659
}
 
6660
 
 
6661
__attribute__((noinline))
 
6662
static void laog__add_edge ( Lock* src, Lock* dst ) {
 
6663
   Word       keyW;
 
6664
   LAOGLinks* links;
 
6665
   Bool       presentF, presentR;
 
6666
   if (0) VG_(printf)("laog__add_edge %p %p\n", src, dst);
 
6667
 
 
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;
 
6677
 
 
6678
   /* Update the out edges for src */
 
6679
   keyW  = 0;
 
6680
   links = NULL;
 
6681
   if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) {
 
6682
      WordSetID outs_new;
 
6683
      tl_assert(links);
 
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;
 
6688
   } else {
 
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 );
 
6693
   }
 
6694
   /* Update the in edges for dst */
 
6695
   keyW  = 0;
 
6696
   links = NULL;
 
6697
   if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) {
 
6698
      WordSetID inns_new;
 
6699
      tl_assert(links);
 
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;
 
6704
   } else {
 
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 );
 
6709
   }
 
6710
 
 
6711
   tl_assert( (presentF && presentR) || (!presentF && !presentR) );
 
6712
 
 
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;
 
6724
      expo.src_ec = NULL;
 
6725
      expo.dst_ec = NULL;
 
6726
      tl_assert(laog_exposition);
 
6727
      if (HG_(lookupFM)( laog_exposition, NULL, NULL, (Word)&expo )) {
 
6728
         /* we already have it; do nothing */
 
6729
      } else {
 
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 );
 
6736
      }
 
6737
   }
 
6738
}
 
6739
 
 
6740
__attribute__((noinline))
 
6741
static void laog__del_edge ( Lock* src, Lock* dst ) {
 
6742
   Word       keyW;
 
6743
   LAOGLinks* links;
 
6744
   if (0) VG_(printf)("laog__del_edge %p %p\n", src, dst);
 
6745
   /* Update the out edges for src */
 
6746
   keyW  = 0;
 
6747
   links = NULL;
 
6748
   if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) {
 
6749
      tl_assert(links);
 
6750
      tl_assert(keyW == (Word)src);
 
6751
      links->outs = HG_(delFromWS)( univ_laog, links->outs, (Word)dst );
 
6752
   }
 
6753
   /* Update the in edges for dst */
 
6754
   keyW  = 0;
 
6755
   links = NULL;
 
6756
   if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) {
 
6757
      tl_assert(links);
 
6758
      tl_assert(keyW == (Word)dst);
 
6759
      links->inns = HG_(delFromWS)( univ_laog, links->inns, (Word)src );
 
6760
   }
 
6761
}
 
6762
 
 
6763
__attribute__((noinline))
 
6764
static WordSetID /* in univ_laog */ laog__succs ( Lock* lk ) {
 
6765
   Word       keyW;
 
6766
   LAOGLinks* links;
 
6767
   keyW  = 0;
 
6768
   links = NULL;
 
6769
   if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) {
 
6770
      tl_assert(links);
 
6771
      tl_assert(keyW == (Word)lk);
 
6772
      return links->outs;
 
6773
   } else {
 
6774
      return HG_(emptyWS)( univ_laog );
 
6775
   }
 
6776
}
 
6777
 
 
6778
__attribute__((noinline))
 
6779
static WordSetID /* in univ_laog */ laog__preds ( Lock* lk ) {
 
6780
   Word       keyW;
 
6781
   LAOGLinks* links;
 
6782
   keyW  = 0;
 
6783
   links = NULL;
 
6784
   if (HG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) {
 
6785
      tl_assert(links);
 
6786
      tl_assert(keyW == (Word)lk);
 
6787
      return links->inns;
 
6788
   } else {
 
6789
      return HG_(emptyWS)( univ_laog );
 
6790
   }
 
6791
}
 
6792
 
 
6793
__attribute__((noinline))
 
6794
static void laog__sanity_check ( Char* who ) {
 
6795
   Word i, ws_size;
 
6796
   Word* ws_words;
 
6797
   Lock* me;
 
6798
   LAOGLinks* links;
 
6799
   if ( !laog )
 
6800
      return; /* nothing much we can do */
 
6801
   HG_(initIterFM)( laog );
 
6802
   me = NULL;
 
6803
   links = NULL;
 
6804
   if (0) VG_(printf)("laog sanity check\n");
 
6805
   while (HG_(nextIterFM)( laog, (Word*)&me,
 
6806
                                 (Word*)&links )) {
 
6807
      tl_assert(me);
 
6808
      tl_assert(links);
 
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] ), 
 
6813
                             (Word)me ))
 
6814
            goto bad;
 
6815
      }
 
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] ), 
 
6820
                             (Word)me ))
 
6821
            goto bad;
 
6822
      }
 
6823
      me = NULL;
 
6824
      links = NULL;
 
6825
   }
 
6826
   HG_(doneIterFM)( laog );
 
6827
   return;
 
6828
 
 
6829
  bad:
 
6830
   VG_(printf)("laog__sanity_check(%s) FAILED\n", who);
 
6831
   laog__show(who);
 
6832
   tl_assert(0);
 
6833
}
 
6834
 
 
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
 
6838
   NULL. */
 
6839
__attribute__((noinline))
 
6840
static
 
6841
Lock* laog__do_dfs_from_to ( Lock* src, WordSetID dsts /* univ_lsets */ )
 
6842
{
 
6843
   Lock*     ret;
 
6844
   Word      i, ssz;
 
6845
   XArray*   stack;   /* of Lock* */
 
6846
   WordFM*   visited; /* Lock* -> void, iow, Set(Lock*) */
 
6847
   Lock*     here;
 
6848
   WordSetID succs;
 
6849
   Word      succs_size;
 
6850
   Word*     succs_words;
 
6851
   //laog__sanity_check();
 
6852
 
 
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 ))
 
6856
      return NULL;
 
6857
 
 
6858
   ret     = NULL;
 
6859
   stack   = VG_(newXA)( hg_zalloc, hg_free, sizeof(Lock*) );
 
6860
   visited = HG_(newFM)( hg_zalloc, hg_free, NULL/*unboxedcmp*/ );
 
6861
 
 
6862
   (void) VG_(addToXA)( stack, &src );
 
6863
 
 
6864
   while (True) {
 
6865
 
 
6866
      ssz = VG_(sizeXA)( stack );
 
6867
 
 
6868
      if (ssz == 0) { ret = NULL; break; }
 
6869
 
 
6870
      here = *(Lock**) VG_(indexXA)( stack, ssz-1 );
 
6871
      VG_(dropTailXA)( stack, 1 );
 
6872
 
 
6873
      if (HG_(elemWS)( univ_lsets, dsts, (Word)here )) { ret = here; break; }
 
6874
 
 
6875
      if (HG_(lookupFM)( visited, NULL, NULL, (Word)here ))
 
6876
         continue;
 
6877
 
 
6878
      HG_(addToFM)( visited, (Word)here, 0 );
 
6879
 
 
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] );
 
6884
   }
 
6885
 
 
6886
   HG_(deleteFM)( visited, NULL, NULL );
 
6887
   VG_(deleteXA)( stack );
 
6888
   return ret;
 
6889
}
 
6890
 
 
6891
 
 
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.
 
6895
*/
 
6896
__attribute__((noinline))
 
6897
static void laog__pre_thread_acquires_lock ( 
 
6898
               Thread* thr, /* NB: BEFORE lock is added */
 
6899
               Lock*   lk
 
6900
            )
 
6901
{
 
6902
   Word*    ls_words;
 
6903
   Word     ls_size, i;
 
6904
   Lock*    other;
 
6905
 
 
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 ))
 
6910
      return;
 
6911
 
 
6912
   if (!laog)
 
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 );
 
6917
 
 
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
 
6922
      locks.
 
6923
   */
 
6924
   other = laog__do_dfs_from_to(lk, thr->locksetA);
 
6925
   if (other) {
 
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;
 
6936
      key.src_ec = NULL;
 
6937
      key.dst_ec = NULL;
 
6938
      found = NULL;
 
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 );
 
6949
      } else {
 
6950
         /* Hmm.  This can't happen (can it?) */
 
6951
         record_error_LockOrder( thr, 
 
6952
                                 lk->guestaddr,        other->guestaddr,
 
6953
                                 NULL, NULL );
 
6954
      }
 
6955
   }
 
6956
 
 
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.
 
6961
   */
 
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 );
 
6968
   }
 
6969
 
 
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
 
6974
      barfs. */
 
6975
   if (clo_sanity_flags & SCE_LAOG)
 
6976
      all_except_Locks__sanity_check("laog__pre_thread_acquires_lock-post");
 
6977
}
 
6978
 
 
6979
 
 
6980
/* Delete from 'laog' any pair mentioning a lock in locksToDelete */
 
6981
 
 
6982
__attribute__((noinline))
 
6983
static void laog__handle_one_lock_deletion ( Lock* lk )
 
6984
{
 
6985
   WordSetID preds, succs;
 
6986
   Word preds_size, succs_size, i, j;
 
6987
   Word *preds_words, *succs_words;
 
6988
 
 
6989
   preds = laog__preds( lk );
 
6990
   succs = laog__succs( lk );
 
6991
 
 
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 );
 
6995
 
 
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] );
 
6999
 
 
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
 
7005
               be NULL. */
 
7006
            laog__add_edge( (Lock*)preds_words[i], (Lock*)succs_words[j] );
 
7007
         }
 
7008
      }
 
7009
   }
 
7010
}
 
7011
 
 
7012
__attribute__((noinline))
 
7013
static void laog__handle_lock_deletions (
 
7014
               WordSetID /* in univ_laog */ locksToDelete
 
7015
            )
 
7016
{
 
7017
   Word  i, ws_size;
 
7018
   Word* ws_words;
 
7019
 
 
7020
   if (!laog)
 
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 );
 
7025
 
 
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] );
 
7029
 
 
7030
   if (clo_sanity_flags & SCE_LAOG)
 
7031
      all__sanity_check("laog__handle_lock_deletions-post");
 
7032
}
 
7033
 
 
7034
 
 
7035
/*--------------------------------------------------------------*/
 
7036
/*--- Malloc/free replacements                               ---*/
 
7037
/*--------------------------------------------------------------*/
 
7038
 
 
7039
typedef
 
7040
   struct {
 
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      */
 
7046
   }
 
7047
   MallocMeta;
 
7048
 
 
7049
/* A hash table of MallocMetas, used to track malloc'd blocks
 
7050
   (obviously). */
 
7051
static VgHashTable hg_mallocmeta_table = NULL;
 
7052
 
 
7053
 
 
7054
static MallocMeta* new_MallocMeta ( void ) {
 
7055
   MallocMeta* md = hg_zalloc( sizeof(MallocMeta) );
 
7056
   tl_assert(md);
 
7057
   return md;
 
7058
}
 
7059
static void delete_MallocMeta ( MallocMeta* md ) {
 
7060
   hg_free(md);
 
7061
}
 
7062
 
 
7063
 
 
7064
/* Allocate a client block and set up the metadata for it. */
 
7065
 
 
7066
static
 
7067
void* handle_alloc ( ThreadId tid, 
 
7068
                     SizeT szB, SizeT alignB, Bool is_zeroed )
 
7069
{
 
7070
   Addr        p;
 
7071
   MallocMeta* md;
 
7072
 
 
7073
   tl_assert( ((SSizeT)szB) >= 0 );
 
7074
   p = (Addr)VG_(cli_malloc)(alignB, szB);
1863
7075
   if (!p) {
1864
7076
      return NULL;
1865
7077
   }
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 );
 
7078
   if (is_zeroed)
 
7079
      VG_(memset)((void*)p, 0, szB);
 
7080
 
 
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();
 
7085
   md->payload = p;
 
7086
   md->szB     = szB;
 
7087
   md->where   = VG_(record_ExeContext)( tid, 0 );
 
7088
   md->thr     = map_threads_lookup( tid );
 
7089
 
 
7090
   VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md );
 
7091
 
 
7092
   /* Tell the lower level memory wranglers. */
 
7093
   evh__new_mem_heap( p, szB, is_zeroed );
1869
7094
 
1870
7095
   return (void*)p;
1871
7096
}
1872
7097
 
1873
 
static void* hg_malloc ( ThreadId tid, SizeT n )
1874
 
{
1875
 
   return alloc_and_new_mem ( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
1876
 
}
1877
 
 
1878
 
static void* hg___builtin_new ( ThreadId tid, SizeT n )
1879
 
{
1880
 
   return alloc_and_new_mem ( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
1881
 
}
1882
 
 
1883
 
static void* hg___builtin_vec_new ( ThreadId tid, SizeT n )
1884
 
{
1885
 
   return alloc_and_new_mem ( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
1886
 
}
1887
 
 
1888
 
static void* hg_memalign ( ThreadId tid, SizeT align, SizeT n )
1889
 
{
1890
 
   return alloc_and_new_mem ( tid, n, align,              /*is_zeroed*/False );
1891
 
}
1892
 
 
1893
 
static void* hg_calloc ( ThreadId tid, SizeT nmemb, SizeT size )
1894
 
{
1895
 
   return alloc_and_new_mem ( tid, nmemb*size, VG_(clo_alignment),
1896
 
                              /*is_zeroed*/True );
1897
 
}
1898
 
 
1899
 
static ThreadId deadmx_tid;
1900
 
 
1901
 
static
1902
 
Bool deadmx(Mutex *mx) {
1903
 
   if (mx->state != MxDead)
1904
 
      set_mutex_state(mx, MxDead, deadmx_tid);
1905
 
   
1906
 
   return False;
1907
 
}
1908
 
 
1909
 
static
1910
 
void die_and_free_mem ( ThreadId tid, HG_Chunk* hc,
1911
 
                        HG_Chunk** prev_chunks_next_ptr )
1912
 
{
1913
 
   Addr start = hc->data;
1914
 
   Addr end   = start + hc->size;
1915
 
 
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;
1921
 
 
1922
 
   /* Record where freed */
1923
 
   hc->where = VG_(record_ExeContext) ( tid );
1924
 
 
1925
 
   /* maintain a small window so that the error reporting machinery
1926
 
      knows about this memory */
1927
 
   if (freechunks[freechunkptr] != NULL) {
1928
 
      /* free HG_Chunk */
1929
 
      HG_Chunk* sc1 = freechunks[freechunkptr];
1930
 
      VG_(cli_free) ( (void*)(sc1->data) );
1931
 
      VG_(free) ( sc1 );
1932
 
   }
1933
 
 
1934
 
   freechunks[freechunkptr] = hc;
1935
 
 
1936
 
   if (++freechunkptr == N_FREED_CHUNKS)
1937
 
      freechunkptr = 0;
1938
 
 
1939
 
   /* mark all mutexes in range dead */
1940
 
   deadmx_tid = tid;
1941
 
   find_mutex_range(start, end, deadmx);
1942
 
}
1943
 
 
1944
 
 
1945
 
static __inline__
1946
 
void handle_free ( ThreadId tid, void* p )
1947
 
{
1948
 
   HG_Chunk*  hc;
1949
 
   HG_Chunk** prev_chunks_next_ptr;
1950
 
 
1951
 
   hc = (HG_Chunk*)VG_(HT_get_node) ( hg_malloc_list, (UWord)p,
1952
 
                                      (VgHashNode***)&prev_chunks_next_ptr );
1953
 
   if (hc == NULL) {
1954
 
      return;
1955
 
   }
1956
 
   die_and_free_mem ( tid, hc, prev_chunks_next_ptr );
1957
 
}
1958
 
 
1959
 
static void hg_free ( ThreadId tid, void* p )
1960
 
{
1961
 
   handle_free(tid, p);
1962
 
}
1963
 
 
1964
 
static void hg___builtin_delete ( ThreadId tid, void* p )
1965
 
{
1966
 
   handle_free(tid, p);
1967
 
}
1968
 
 
1969
 
static void hg___builtin_vec_delete ( ThreadId tid, void* p )
1970
 
{
1971
 
   handle_free(tid, p);
1972
 
}
1973
 
 
1974
 
static void* hg_realloc ( ThreadId tid, void* p, SizeT new_size )
1975
 
{
1976
 
   HG_Chunk  *hc;
1977
 
   HG_Chunk **prev_chunks_next_ptr;
1978
 
 
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 );
1982
 
 
1983
 
   if (hc == NULL) {
1984
 
      return NULL;
1985
 
   }
 
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
 
7102
   platforms). */
 
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 );
 
7107
}
 
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 );
 
7112
}
 
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 );
 
7117
}
 
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 );
 
7122
}
 
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 );
 
7127
}
 
7128
 
 
7129
 
 
7130
/* Free a client block, including getting rid of the relevant
 
7131
   metadata. */
 
7132
 
 
7133
static void handle_free ( ThreadId tid, void* p )
 
7134
{
 
7135
   MallocMeta *md, *old_md;
 
7136
   SizeT      szB;
 
7137
 
 
7138
   /* First see if we can find the metadata for 'p'. */
 
7139
   md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p );
 
7140
   if (!md)
 
7141
      return; /* apparently freeing a bogus address.  Oh well. */
 
7142
 
 
7143
   tl_assert(md->payload == (Addr)p);
 
7144
   szB = md->szB;
 
7145
 
 
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);
 
7152
 
 
7153
   VG_(cli_free)((void*)old_md->payload);
 
7154
   delete_MallocMeta(old_md);
 
7155
 
 
7156
   /* Tell the lower level memory wranglers. */
 
7157
   evh__die_mem_heap( (Addr)p, szB );
 
7158
}
 
7159
 
 
7160
static void hg_cli__free ( ThreadId tid, void* p ) {
 
7161
   handle_free(tid, p);
 
7162
}
 
7163
static void hg_cli____builtin_delete ( ThreadId tid, void* p ) {
 
7164
   handle_free(tid, p);
 
7165
}
 
7166
static void hg_cli____builtin_vec_delete ( ThreadId tid, void* p ) {
 
7167
   handle_free(tid, p);
 
7168
}
 
7169
 
 
7170
 
 
7171
static void* hg_cli__realloc ( ThreadId tid, void* payloadV, SizeT new_size )
 
7172
{
 
7173
   MallocMeta *md, *md_new, *md_tmp;
 
7174
   SizeT      i;
 
7175
 
 
7176
   Addr payload = (Addr)payloadV;
 
7177
 
 
7178
   if (((SSizeT)new_size) < 0) return NULL;
 
7179
 
 
7180
   md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)payload );
 
7181
   if (!md)
 
7182
      return NULL; /* apparently realloc-ing a bogus address.  Oh well. */
1986
7183
  
1987
 
   if (hc->size == new_size) {
 
7184
   tl_assert(md->payload == payload);
 
7185
 
 
7186
   if (md->szB == new_size) {
1988
7187
      /* size unchanged */
1989
 
      hc->where = VG_(record_ExeContext)(tid);
1990
 
      return p;
1991
 
      
1992
 
   } else if (hc->size > new_size) {
 
7188
      md->where = VG_(record_ExeContext)(tid, 0);
 
7189
      return payloadV;
 
7190
   }
 
7191
 
 
7192
   if (md->szB > new_size) {
1993
7193
      /* new size is smaller */
1994
 
      hc->size = new_size;
1995
 
      hc->where = VG_(record_ExeContext)(tid);
1996
 
      return p;
 
7194
      md->szB   = new_size;
 
7195
      md->where = VG_(record_ExeContext)(tid, 0);
 
7196
      evh__die_mem_heap( md->payload + new_size, md->szB - new_size );
 
7197
      return payloadV;
 
7198
   }
1997
7199
 
1998
 
   } else {
 
7200
   /* else */ {
1999
7201
      /* new size is bigger */
2000
 
      Addr p_new;
2001
 
 
2002
 
      /* Get new memory */
2003
 
      p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
2004
 
 
2005
 
      if (p_new) {
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);
 
7203
 
 
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 );
2010
 
 
2011
 
         /* Copy from old to new */
2012
 
         VG_(memcpy)((void *)p_new, p, hc->size);
2013
 
 
2014
 
         /* Free old memory */
2015
 
         die_and_free_mem ( tid, hc, prev_chunks_next_ptr );
2016
 
 
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 );
2021
 
      }
 
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 );
 
7214
 
 
7215
      /* Copy from old to new */
 
7216
      for (i = 0; i < md->szB; i++)
 
7217
         ((UChar*)p_new)[i] = ((UChar*)payload)[i];
 
7218
 
 
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
 
7223
         chain. */
 
7224
      md_new = new_MallocMeta();
 
7225
      *md_new = *md;
 
7226
 
 
7227
      md_tmp = VG_(HT_remove)( hg_mallocmeta_table, payload );
 
7228
      tl_assert(md_tmp);
 
7229
      tl_assert(md_tmp == md);
 
7230
 
 
7231
      VG_(cli_free)((void*)md->payload);
 
7232
      delete_MallocMeta(md);
 
7233
 
 
7234
      /* Update fields */
 
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 );
 
7239
 
 
7240
      /* and add */
 
7241
      VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md_new );
2022
7242
 
2023
7243
      return (void*)p_new;
2024
7244
   }  
2025
7245
}
2026
7246
 
2027
 
/*--------------------------------------------------------------*/
2028
 
/*--- Machinery to support sanity checking                   ---*/
2029
 
/*--------------------------------------------------------------*/
2030
 
 
2031
 
static Bool hg_cheap_sanity_check ( void )
2032
 
{
2033
 
   /* nothing useful we can rapidly check */
2034
 
   return True;
2035
 
}
2036
 
 
2037
 
static Bool hg_expensive_sanity_check(void)
2038
 
{
2039
 
   Int i;
2040
 
 
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)
2045
 
         return False;
2046
 
 
2047
 
   return True;
2048
 
}
2049
 
 
2050
7247
 
2051
7248
/*--------------------------------------------------------------*/
2052
7249
/*--- Instrumentation                                        ---*/
2053
7250
/*--------------------------------------------------------------*/
2054
7251
 
2055
 
static UInt stk_ld, nonstk_ld, stk_st, nonstk_st;
2056
 
 
2057
 
#if 0
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, 
 
7253
                                    IRExpr* addr,
 
7254
                                    Int     szB,
 
7255
                                    Bool    isStore,
 
7256
                                    Int     hWordTy_szB )
2061
7257
{
2062
 
   UCodeBlock* cb;
2063
 
   Int         i;
2064
 
   UInstr*     u_in;
2065
 
   Int         t_size = INVALID_TEMPREG;
2066
 
   Int         ntemps;
2067
 
   Bool        *stackref = NULL;
2068
 
   Bool        locked = False;  /* lock prefix */
2069
 
 
2070
 
   cb = VG_(setup_UCodeBlock)(cb_in);
2071
 
 
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);
2079
 
 
2080
 
   for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
2081
 
      u_in = VG_(get_instr)(cb_in, i);
2082
 
 
2083
 
      switch (u_in->opcode) {
2084
 
 
2085
 
         case NOP: case CALLM_S: case CALLM_E:
2086
 
            break;
2087
 
    
2088
 
         case LOCK:
2089
 
            locked = True;
2090
 
            uInstr0(cb, CCALL, 0);
2091
 
            uCCall(cb, (Addr)bus_lock, 0, 0, False);
2092
 
            break;
2093
 
 
2094
 
         case JMP: case INCEIP:
2095
 
            if (locked) {
2096
 
               uInstr0(cb, CCALL, 0);
2097
 
               uCCall(cb, (Addr)bus_unlock, 0, 0, False);
2098
 
            }
2099
 
            locked = False;
2100
 
            VG_(copy_UInstr)(cb, u_in);
2101
 
            break;
2102
 
 
2103
 
         case GET:
2104
 
            tl_assert(u_in->tag1 == ArchReg);
2105
 
            tl_assert(u_in->tag2 == TempReg);
2106
 
            tl_assert(u_in->val2 < ntemps);
2107
 
 
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);
2112
 
            break;
2113
 
 
2114
 
         case MOV:
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];
2118
 
            }
2119
 
            VG_(copy_UInstr)(cb, u_in);
2120
 
            break;
2121
 
 
2122
 
         case LEA1:
2123
 
         case ADD: case SUB:
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];
2127
 
            }
2128
 
            VG_(copy_UInstr)(cb, u_in);
2129
 
            break;
2130
 
 
2131
 
         case LOAD: {
2132
 
            void (*help)(Addr);
2133
 
            tl_assert(1 == u_in->size || 2 == u_in->size || 4 == u_in->size);
2134
 
            tl_assert(u_in->tag1 == TempReg);
2135
 
 
2136
 
            if (!clo_priv_stacks || !stackref[u_in->val1]) {
2137
 
               nonstk_ld++;
2138
 
 
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;
2143
 
               default:
2144
 
                  VG_(tool_panic)("bad size");
2145
 
               }
2146
 
 
2147
 
               /* XXX all registers should be flushed to baseblock
2148
 
                  here */
2149
 
               uInstr1(cb, CCALL, 0, TempReg, u_in->val1);
2150
 
               uCCall(cb, (Addr)help, 1, 1, False);
2151
 
            } else
2152
 
               stk_ld++;
2153
 
 
2154
 
            VG_(copy_UInstr)(cb, u_in);
2155
 
            t_size = INVALID_TEMPREG;
2156
 
            break;
2157
 
         }
2158
 
 
2159
 
         case MMX2_MemRd:
2160
 
         case FPU_R: {
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);
2163
 
            
2164
 
            t_size = newTemp(cb);
2165
 
            uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_size);
2166
 
            uLiteral(cb, (UInt)u_in->size);
2167
 
 
2168
 
            /* XXX all registers should be flushed to baseblock
2169
 
               here */
2170
 
            uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
2171
 
            uCCall(cb, (Addr) & hg_mem_help_read_N, 2, 2, False);
2172
 
            
2173
 
            VG_(copy_UInstr)(cb, u_in);
2174
 
            t_size = INVALID_TEMPREG;
2175
 
            break;
2176
 
         } 
2177
 
 
2178
 
         case MMX2a1_MemRd: {
2179
 
            tl_assert(8 == u_in->size);
2180
 
            
2181
 
            t_size = newTemp(cb);
2182
 
            uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_size);
2183
 
            uLiteral(cb, (UInt)u_in->size);
2184
 
 
2185
 
            /* XXX all registers should be flushed to baseblock
2186
 
               here */
2187
 
            uInstr2(cb, CCALL, 0, TempReg, u_in->val3, TempReg, t_size);
2188
 
            uCCall(cb, (Addr) & hg_mem_help_read_N, 2, 2, False);
2189
 
            
2190
 
            VG_(copy_UInstr)(cb, u_in);
2191
 
            t_size = INVALID_TEMPREG;
2192
 
            break;
2193
 
         } 
2194
 
 
2195
 
         case SSE2a_MemRd:
2196
 
         case SSE2a1_MemRd:
2197
 
         case SSE3a_MemRd:
2198
 
         case SSE3a1_MemRd:
2199
 
         case SSE3ag_MemRd_RegWr: {
2200
 
            Int addr = (u_in->opcode == SSE3ag_MemRd_RegWr) ? u_in->val1 : u_in->val3;
2201
 
 
2202
 
            tl_assert(u_in->size == 4 || u_in->size == 8 || u_in->size == 16 || u_in->size == 512);
2203
 
            
2204
 
            t_size = newTemp(cb);
2205
 
            uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_size);
2206
 
            uLiteral(cb, (UInt)u_in->size);
2207
 
 
2208
 
            uInstr2(cb, CCALL, 0, TempReg, addr, TempReg, t_size);
2209
 
            uCCall(cb, (Addr) & hg_mem_help_read_N, 2, 2, False);
2210
 
            
2211
 
            VG_(copy_UInstr)(cb, u_in);
2212
 
            t_size = INVALID_TEMPREG;
2213
 
            break;
2214
 
         }
2215
 
 
2216
 
         case STORE: {
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);
2220
 
 
2221
 
            if (!clo_priv_stacks || !stackref[u_in->val2]) {
2222
 
               nonstk_st++;
2223
 
 
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;
2228
 
               default:
2229
 
                  VG_(tool_panic)("bad size");
2230
 
               }
2231
 
 
2232
 
               /* XXX all registers should be flushed to baseblock
2233
 
                  here */
2234
 
               uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, u_in->val1);
2235
 
               uCCall(cb, (Addr)help, 2, 2, False);
2236
 
            } else
2237
 
               stk_st++;
2238
 
 
2239
 
            VG_(copy_UInstr)(cb, u_in);
2240
 
            t_size = INVALID_TEMPREG;
2241
 
            break;
2242
 
         }
2243
 
 
2244
 
         case MMX2_MemWr:
2245
 
         case FPU_W: {
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);
2248
 
 
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
2253
 
                  here */
2254
 
            uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
2255
 
            uCCall(cb, (Addr) & hg_mem_help_write_N, 2, 2, False);
2256
 
 
2257
 
            VG_(copy_UInstr)(cb, u_in);
2258
 
            t_size = INVALID_TEMPREG;
2259
 
            break;
2260
 
         }
2261
 
 
2262
 
         case SSE2a_MemWr:
2263
 
         case SSE3a_MemWr: {
2264
 
            tl_assert(4 == u_in->size || 8 == u_in->size || 16 == u_in->size ||
2265
 
                      512 == u_in->size);
2266
 
 
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
2271
 
                  here */
2272
 
            uInstr2(cb, CCALL, 0, TempReg, u_in->val3, TempReg, t_size);
2273
 
            uCCall(cb, (Addr) & hg_mem_help_write_N, 2, 2, False);
2274
 
 
2275
 
            VG_(copy_UInstr)(cb, u_in);
2276
 
            t_size = INVALID_TEMPREG;
2277
 
            break;
2278
 
         }
2279
 
 
 
7258
   IRType   tyAddr   = Ity_INVALID;
 
7259
   HChar*   hName    = NULL;
 
7260
   void*    hAddr    = NULL;
 
7261
   Int      regparms = 0;
 
7262
   IRExpr** argv     = NULL;
 
7263
   IRDirty* di       = NULL;
 
7264
 
 
7265
   tl_assert(isIRAtom(addr));
 
7266
   tl_assert(hWordTy_szB == 4 || hWordTy_szB == 8);
 
7267
 
 
7268
   tyAddr = typeOfIRExpr( bbOut->tyenv, addr );
 
7269
   tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
 
7270
 
 
7271
   /* So the effective address is in 'addr' now. */
 
7272
   regparms = 1; // unless stated otherwise
 
7273
   if (isStore) {
 
7274
      switch (szB) {
 
7275
         case 1:
 
7276
            hName = "evh__mem_help_write_1";
 
7277
            hAddr = &evh__mem_help_write_1;
 
7278
            argv = mkIRExprVec_1( addr );
 
7279
            break;
 
7280
         case 2:
 
7281
            hName = "evh__mem_help_write_2";
 
7282
            hAddr = &evh__mem_help_write_2;
 
7283
            argv = mkIRExprVec_1( addr );
 
7284
            break;
 
7285
         case 4:
 
7286
            hName = "evh__mem_help_write_4";
 
7287
            hAddr = &evh__mem_help_write_4;
 
7288
            argv = mkIRExprVec_1( addr );
 
7289
            break;
 
7290
         case 8:
 
7291
            hName = "evh__mem_help_write_8";
 
7292
            hAddr = &evh__mem_help_write_8;
 
7293
            argv = mkIRExprVec_1( addr );
 
7294
            break;
2280
7295
         default:
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);
2289
 
            break;
2290
 
      }
2291
 
   }
2292
 
 
2293
 
   VG_(free)(stackref);
2294
 
   VG_(free_UCodeBlock)(cb_in);
2295
 
   return cb;
2296
 
}
2297
 
#endif
 
7296
            tl_assert(szB > 8 && szB <= 512); /* stay sane */
 
7297
            regparms = 2;
 
7298
            hName = "evh__mem_help_write_N";
 
7299
            hAddr = &evh__mem_help_write_N;
 
7300
            argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB ));
 
7301
            break;
 
7302
      }
 
7303
   } else {
 
7304
      switch (szB) {
 
7305
         case 1:
 
7306
            hName = "evh__mem_help_read_1";
 
7307
            hAddr = &evh__mem_help_read_1;
 
7308
            argv = mkIRExprVec_1( addr );
 
7309
            break;
 
7310
         case 2:
 
7311
            hName = "evh__mem_help_read_2";
 
7312
            hAddr = &evh__mem_help_read_2;
 
7313
            argv = mkIRExprVec_1( addr );
 
7314
            break;
 
7315
         case 4:
 
7316
            hName = "evh__mem_help_read_4";
 
7317
            hAddr = &evh__mem_help_read_4;
 
7318
            argv = mkIRExprVec_1( addr );
 
7319
            break;
 
7320
         case 8:
 
7321
            hName = "evh__mem_help_read_8";
 
7322
            hAddr = &evh__mem_help_read_8;
 
7323
            argv = mkIRExprVec_1( addr );
 
7324
            break;
 
7325
         default: 
 
7326
            tl_assert(szB > 8 && szB <= 512); /* stay sane */
 
7327
            regparms = 2;
 
7328
            hName = "evh__mem_help_read_N";
 
7329
            hAddr = &evh__mem_help_read_N;
 
7330
            argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB ));
 
7331
            break;
 
7332
      }
 
7333
   }
 
7334
 
 
7335
   /* Add the helper. */
 
7336
   tl_assert(hName);
 
7337
   tl_assert(hAddr);
 
7338
   tl_assert(argv);
 
7339
   di = unsafeIRDirty_0_N( regparms,
 
7340
                           hName, VG_(fnptr_to_fnentry)( hAddr ),
 
7341
                           argv );
 
7342
   addStmtToIRSB( bbOut, IRStmt_Dirty(di) );
 
7343
}
 
7344
 
 
7345
 
 
7346
static void instrument_memory_bus_event ( IRSB* bbOut, IRMBusEvent event )
 
7347
{
 
7348
   switch (event) {
 
7349
      case Imbe_Fence:
 
7350
         break; /* not interesting */
 
7351
      case Imbe_BusLock:
 
7352
      case Imbe_BusUnlock:
 
7353
         addStmtToIRSB(
 
7354
            bbOut,
 
7355
            IRStmt_Dirty(
 
7356
               unsafeIRDirty_0_N( 
 
7357
                  0/*regparms*/, 
 
7358
                  event == Imbe_BusLock ? "evh__bus_lock"
 
7359
                                        : "evh__bus_unlock",
 
7360
                  VG_(fnptr_to_fnentry)(
 
7361
                     event == Imbe_BusLock ? &evh__bus_lock 
 
7362
                                           : &evh__bus_unlock 
 
7363
                  ),
 
7364
                  mkIRExprVec_0() 
 
7365
               )
 
7366
            )
 
7367
         );
 
7368
         break;
 
7369
      default:
 
7370
         tl_assert(0);
 
7371
   }
 
7372
}
 
7373
 
 
7374
 
2298
7375
static
2299
 
IRBB* hg_instrument ( VgCallbackClosure* closure,
2300
 
                      IRBB* bb,
2301
 
                      VexGuestLayout* layout, 
 
7376
IRSB* hg_instrument ( VgCallbackClosure* closure,
 
7377
                      IRSB* bbIn,
 
7378
                      VexGuestLayout* layout,
2302
7379
                      VexGuestExtents* vge,
2303
7380
                      IRType gWordTy, IRType hWordTy )
2304
7381
{
2305
 
   tl_assert(0);  // Need to convert to Vex
2306
 
}
2307
 
 
2308
 
/*--------------------------------------------------------------------*/
2309
 
/*--- Error and suppression handling                               ---*/
2310
 
/*--------------------------------------------------------------------*/
2311
 
 
2312
 
typedef
2313
 
   enum {
2314
 
      /* Possible data race */
2315
 
      RaceSupp
2316
 
   }
2317
 
   RaceSuppKind;
2318
 
 
2319
 
/* What kind of error it is. */
2320
 
typedef
2321
 
   enum { 
2322
 
      RaceErr,                  /* data-race */
2323
 
      MutexErr,                 /* mutex operations */
2324
 
      LockGraphErr,             /* mutex order error */
2325
 
   }
2326
 
   RaceErrorKind;
2327
 
 
2328
 
/* The classification of a faulting address. */
2329
 
typedef 
2330
 
   enum { Undescribed, /* as-yet unclassified */
2331
 
          Stack, 
2332
 
          Unknown, /* classification yielded nothing useful */
2333
 
          Mallocd,
2334
 
          Freed,
2335
 
          Segment
2336
 
   }
2337
 
   AddrKind;
2338
 
/* Records info about a faulting address. */
2339
 
typedef
2340
 
   struct {
2341
 
      /* ALL */
2342
 
      AddrKind akind;
2343
 
      /* Freed, Mallocd */
2344
 
      Int blksize;
2345
 
      /* Freed, Mallocd */
2346
 
      Int rwoffset;
2347
 
      /* Freed, Mallocd */
2348
 
      ExeContext* lastchange;
2349
 
      ThreadId lasttid;
2350
 
      /* Stack */
2351
 
      ThreadId stack_tid;
2352
 
      /* Segment */
2353
 
      const Char* filename;
2354
 
      const Char* section;
2355
 
      /* True if is just-below the stack pointer -- could be a gcc bug. */
2356
 
      Bool maybe_gcc;
2357
 
      /* symbolic address description */
2358
 
      Char *expr;
2359
 
   }
2360
 
   AddrInfo;
2361
 
 
2362
 
/* What kind of memory access is involved in the error? */
2363
 
typedef
2364
 
   enum { ReadAxs, WriteAxs, ExecAxs }
2365
 
   AxsKind;
2366
 
 
2367
 
/* Extra context for memory errors */
2368
 
typedef
2369
 
   struct {
2370
 
      AxsKind axskind;
2371
 
      Int size;
2372
 
      AddrInfo addrinfo;
2373
 
      Bool isWrite;
2374
 
      shadow_word prevstate;
2375
 
      /* MutexErr, LockGraphErr */
2376
 
      Mutex      *mutex;
2377
 
      EC_IP      lasttouched;
2378
 
      ThreadId    lasttid;
2379
 
      /* LockGraphErr */
2380
 
      const LockSet    *held_lockset;
2381
 
      const LockSet    *prev_lockset;
2382
 
   }
2383
 
   HelgrindError;
2384
 
 
2385
 
static __inline__
2386
 
void clear_AddrInfo ( AddrInfo* ai )
2387
 
{
2388
 
   ai->akind      = Unknown;
2389
 
   ai->blksize    = 0;
2390
 
   ai->rwoffset   = 0;
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;
2397
 
   ai->expr       = NULL;
2398
 
}
2399
 
 
2400
 
static __inline__
2401
 
void clear_HelgrindError ( HelgrindError* err_extra )
2402
 
{
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;
2413
 
}
2414
 
 
2415
 
 
2416
 
 
2417
 
/* Describe an address as best you can, for error messages,
2418
 
   putting the result in ai. */
2419
 
 
2420
 
/* Callback for searching malloc'd and free'd lists */
2421
 
static Bool addr_is_in_block(VgHashNode *node, void *ap)
2422
 
{
2423
 
   HG_Chunk* hc2 = (HG_Chunk*)node;
2424
 
   Addr a = *(Addr *)ap;
2425
 
   
2426
 
   return (hc2->data <= a && a < hc2->data + hc2->size);
2427
 
}
2428
 
 
2429
 
static void describe_addr ( Addr a, AddrInfo* ai )
2430
 
{
2431
 
   HG_Chunk* hc;
2432
 
   Int i;
2433
 
 
2434
 
   /* Search for it in segments */
2435
 
   {
2436
 
      const SegInfo *si;
2437
 
 
2438
 
      for (si = VG_(next_seginfo)(NULL); 
2439
 
           si != NULL; 
2440
 
           si = VG_(next_seginfo)(si)) 
2441
 
      {
2442
 
         Addr base = VG_(seginfo_start)(si);
2443
 
         SizeT size = VG_(seginfo_size)(si);
2444
 
         const UChar *filename = VG_(seginfo_filename)(si);
2445
 
 
2446
 
         if (a >= base && a < base+size) {
2447
 
            ai->akind = Segment;
2448
 
            ai->blksize = size;
2449
 
            ai->rwoffset = a - base;
2450
 
            ai->filename = filename;
2451
 
 
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:
2459
 
            default:
2460
 
               ai->section = "???"; break;
2461
 
            }
2462
 
 
2463
 
            return;
2464
 
         }
2465
 
      }
2466
 
   }
2467
 
 
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);
2470
 
   if (NULL != hc) {
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;
2476
 
      return;
2477
 
   } 
2478
 
 
2479
 
   /* Look in recently freed memory */
2480
 
   for(i = 0; i < N_FREED_CHUNKS; i++) {
2481
 
      hc = freechunks[i];
2482
 
      if (hc == NULL)
2483
 
         continue;
2484
 
 
2485
 
      if (a >= hc->data && a < hc->data + hc->size) {
2486
 
         ai->akind      = Freed;
2487
 
         ai->blksize    = hc->size;
2488
 
         ai->rwoffset   = a - hc->data;
2489
 
         ai->lastchange = hc->where;
2490
 
         ai->lasttid    = hc->tid;
2491
 
         return;
2492
 
      } 
2493
 
   }
2494
 
 
2495
 
   /* Clueless ... */
2496
 
   ai->akind = Unknown;
2497
 
   return;
2498
 
}
 
7382
   Int   i;
 
7383
   IRSB* bbOut;
 
7384
 
 
7385
   if (gWordTy != hWordTy) {
 
7386
      /* We don't currently support this case. */
 
7387
      VG_(tool_panic)("host/guest word size mismatch");
 
7388
   }
 
7389
 
 
7390
   /* Set up BB */
 
7391
   bbOut           = emptyIRSB();
 
7392
   bbOut->tyenv    = deepCopyIRTypeEnv(bbIn->tyenv);
 
7393
   bbOut->next     = deepCopyIRExpr(bbIn->next);
 
7394
   bbOut->jumpkind = bbIn->jumpkind;
 
7395
 
 
7396
   // Copy verbatim any IR preamble preceding the first IMark
 
7397
   i = 0;
 
7398
   while (i < bbIn->stmts_used && bbIn->stmts[i]->tag != Ist_IMark) {
 
7399
      addStmtToIRSB( bbOut, bbIn->stmts[i] );
 
7400
      i++;
 
7401
   }
 
7402
 
 
7403
   for (/*use current i*/; i < bbIn->stmts_used; i++) {
 
7404
      IRStmt* st = bbIn->stmts[i];
 
7405
      tl_assert(st);
 
7406
      tl_assert(isFlatIRStmt(st));
 
7407
      switch (st->tag) {
 
7408
         case Ist_NoOp:
 
7409
         case Ist_AbiHint:
 
7410
         case Ist_Put:
 
7411
         case Ist_PutI:
 
7412
         case Ist_IMark:
 
7413
         case Ist_Exit:
 
7414
            /* None of these can contain any memory references. */
 
7415
            break;
 
7416
 
 
7417
         case Ist_MBE:
 
7418
            instrument_memory_bus_event( bbOut, st->Ist.MBE.event );
 
7419
            break;
 
7420
 
 
7421
         case Ist_Store:
 
7422
            instrument_mem_access( 
 
7423
               bbOut, 
 
7424
               st->Ist.Store.addr, 
 
7425
               sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)),
 
7426
               True/*isStore*/,
 
7427
               sizeofIRType(hWordTy)
 
7428
            );
 
7429
            break;
 
7430
 
 
7431
         case Ist_WrTmp: {
 
7432
            IRExpr* data = st->Ist.WrTmp.data;
 
7433
            if (data->tag == Iex_Load) {
 
7434
               instrument_mem_access(
 
7435
                  bbOut,
 
7436
                  data->Iex.Load.addr,
 
7437
                  sizeofIRType(data->Iex.Load.ty),
 
7438
                  False/*!isStore*/,
 
7439
                  sizeofIRType(hWordTy)
 
7440
               );
 
7441
            }
 
7442
            break;
 
7443
         }
 
7444
 
 
7445
         case Ist_Dirty: {
 
7446
            Int      dataSize;
 
7447
            IRDirty* d = st->Ist.Dirty.details;
 
7448
            if (d->mFx != Ifx_None) {
 
7449
               /* This dirty helper accesses memory.  Collect the
 
7450
                  details. */
 
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)
 
7458
                  );
 
7459
               }
 
7460
               if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
 
7461
                  instrument_mem_access( 
 
7462
                     bbOut, d->mAddr, dataSize, True/*isStore*/,
 
7463
                     sizeofIRType(hWordTy)
 
7464
                  );
 
7465
               }
 
7466
            } else {
 
7467
               tl_assert(d->mAddr == NULL);
 
7468
               tl_assert(d->mSize == 0);
 
7469
            }
 
7470
            break;
 
7471
         }
 
7472
 
 
7473
         default:
 
7474
            tl_assert(0);
 
7475
 
 
7476
      } /* switch (st->tag) */
 
7477
 
 
7478
      addStmtToIRSB( bbOut, st );
 
7479
   } /* iterate over bbIn->stmts */
 
7480
 
 
7481
   return bbOut;
 
7482
}
 
7483
 
 
7484
 
 
7485
/*----------------------------------------------------------------*/
 
7486
/*--- Client requests                                          ---*/
 
7487
/*----------------------------------------------------------------*/
 
7488
 
 
7489
/* Sheesh.  Yet another goddam finite map. */
 
7490
static WordFM* map_pthread_t_to_Thread = NULL; /* pthread_t -> Thread* */
 
7491
 
 
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);
 
7496
   }
 
7497
}
 
7498
 
 
7499
 
 
7500
static 
 
7501
Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret)
 
7502
{
 
7503
   if (!VG_IS_TOOL_USERREQ('H','G',args[0]))
 
7504
      return False;
 
7505
 
 
7506
   /* Anything that gets past the above check is one of ours, so we
 
7507
      should be able to handle it. */
 
7508
 
 
7509
   /* default, meaningless return value, unless otherwise set */
 
7510
   *ret = 0;
 
7511
 
 
7512
   switch (args[0]) {
 
7513
 
 
7514
      /* --- --- User-visible client requests --- --- */
 
7515
 
 
7516
      case VG_USERREQ__HG_CLEAN_MEMORY:
 
7517
         if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY(%p,%d)\n",
 
7518
                            args[1], args[2]);
 
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]);
 
7525
         }
 
7526
         break;
 
7527
 
 
7528
      /* --- --- Client requests for Helgrind's use only --- --- */
 
7529
 
 
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
 
7533
         thread. */
 
7534
      case _VG_USERREQ__HG_SET_MY_PTHREAD_T: {
 
7535
         Thread* my_thr = NULL;
 
7536
         if (0)
 
7537
         VG_(printf)("SET_MY_PTHREAD_T (tid %d): pthread_t = %p\n", (Int)tid,
 
7538
                     (void*)args[1]);
 
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. */
 
7551
         if (0)
 
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 );
 
7555
         break;
 
7556
      }
 
7557
 
 
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] );
 
7565
         break;
 
7566
      }
 
7567
 
 
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* */
 
7572
         Bool    found = False;
 
7573
         if (0)
 
7574
         VG_(printf)("NOTIFY_JOIN_COMPLETE (tid %d): quitter = %p\n", (Int)tid,
 
7575
                     (void*)args[1]);
 
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
 
7585
         tl_assert(found);
 
7586
         if (found) {
 
7587
            if (0)
 
7588
            VG_(printf)(".................... quitter Thread* = %p\n", 
 
7589
                        thr_q);
 
7590
            evh__HG_PTHREAD_JOIN_POST( tid, thr_q );
 
7591
         }
 
7592
         break;
 
7593
      }
 
7594
 
 
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] );
 
7602
         break;
 
7603
 
 
7604
      case _VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE:
 
7605
         evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, (void*)args[1] );
 
7606
         break;
 
7607
 
 
7608
      case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE:   // pth_mx_t*
 
7609
         evh__HG_PTHREAD_MUTEX_UNLOCK_PRE( tid, (void*)args[1] );
 
7610
         break;
 
7611
 
 
7612
      case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST:  // pth_mx_t*
 
7613
         evh__HG_PTHREAD_MUTEX_UNLOCK_POST( tid, (void*)args[1] );
 
7614
         break;
 
7615
 
 
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] );
 
7618
         break;
 
7619
 
 
7620
      case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST:    // pth_mx_t*
 
7621
         evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, (void*)args[1] );
 
7622
         break;
 
7623
 
 
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] );
 
7629
         break;
 
7630
 
 
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: {
 
7635
         Bool mutex_is_valid
 
7636
            = evh__HG_PTHREAD_COND_WAIT_PRE( tid, (void*)args[1], 
 
7637
                                                  (void*)args[2] );
 
7638
         *ret = mutex_is_valid ? 1 : 0;
 
7639
         break;
 
7640
      }
 
7641
 
 
7642
      /* Thread successfully completed pthread_cond_wait, cond=arg[1],
 
7643
         mutex=arg[2] */
 
7644
      case _VG_USERREQ__HG_PTHREAD_COND_WAIT_POST:
 
7645
         evh__HG_PTHREAD_COND_WAIT_POST( tid,
 
7646
                                         (void*)args[1], (void*)args[2] );
 
7647
         break;
 
7648
 
 
7649
      case _VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST:
 
7650
         evh__HG_PTHREAD_RWLOCK_INIT_POST( tid, (void*)args[1] );
 
7651
         break;
 
7652
 
 
7653
      case _VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE:
 
7654
         evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( tid, (void*)args[1] );
 
7655
         break;
 
7656
 
 
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],
 
7660
                                               args[2], args[3] );
 
7661
         break;
 
7662
 
 
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] );
 
7666
         break;
 
7667
 
 
7668
      case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE:
 
7669
         evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE( tid, (void*)args[1] );
 
7670
         break;
 
7671
 
 
7672
      case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST:
 
7673
         evh__HG_PTHREAD_RWLOCK_UNLOCK_POST( tid, (void*)args[1] );
 
7674
         break;
 
7675
 
 
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] );
 
7678
         break;
 
7679
 
 
7680
      case _VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE: /* sem_t* */
 
7681
         evh__HG_POSIX_SEM_DESTROY_PRE( tid, (void*)args[1] );
 
7682
         break;
 
7683
 
 
7684
      case _VG_USERREQ__HG_POSIX_SEM_POST_PRE: /* sem_t* */
 
7685
         evh__HG_POSIX_SEM_POST_PRE( tid, (void*)args[1] );
 
7686
         break;
 
7687
 
 
7688
      case _VG_USERREQ__HG_POSIX_SEM_WAIT_POST: /* sem_t* */
 
7689
         evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] );
 
7690
         break;
 
7691
 
 
7692
      case _VG_USERREQ__HG_GET_MY_SEGMENT: { // -> Segment*
 
7693
         Thread*   thr;
 
7694
         SegmentID segid;
 
7695
         Segment*  seg;
 
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 );
 
7701
         tl_assert(seg);
 
7702
         *ret = (UWord)seg;
 
7703
         break;
 
7704
      }
 
7705
 
 
7706
      default:
 
7707
         /* Unhandled Helgrind client request! */
 
7708
        tl_assert2(0, "unhandled Helgrind client request!");
 
7709
   }
 
7710
 
 
7711
   return True;
 
7712
}
 
7713
 
 
7714
 
 
7715
/*----------------------------------------------------------------*/
 
7716
/*--- Error management                                         ---*/
 
7717
/*----------------------------------------------------------------*/
 
7718
 
 
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 );
 
7724
}
 
7725
static HChar* string_table_strdup ( HChar* str ) {
 
7726
   HChar* copy = NULL;
 
7727
   stats__string_table_queries++;
 
7728
   if (!str)
 
7729
      str = "(null)";
 
7730
   if (!string_table) {
 
7731
      string_table = HG_(newFM)( hg_zalloc, hg_free, string_table_cmp );
 
7732
      tl_assert(string_table);
 
7733
   }
 
7734
   if (HG_(lookupFM)( string_table,
 
7735
                      NULL, (Word*)&copy, (Word)str )) {
 
7736
      tl_assert(copy);
 
7737
      if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
 
7738
      return copy;
 
7739
   } else {
 
7740
      copy = VG_(strdup)(str);
 
7741
      tl_assert(copy);
 
7742
      HG_(addToFM)( string_table, (Word)copy, (Word)copy );
 
7743
      return copy;
 
7744
   }
 
7745
}
 
7746
 
 
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 )
 
7751
{
 
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;
 
7758
   return 0;
 
7759
}
 
7760
static Lock* mk_LockP_from_LockN ( Lock* lkn )
 
7761
{
 
7762
   Lock* lkp = NULL;
 
7763
   stats__ga_LockN_to_P_queries++;
 
7764
   tl_assert( is_sane_LockN(lkn) );
 
7765
   if (!yaWFM) {
 
7766
      yaWFM = HG_(newFM)( hg_zalloc, hg_free, lock_unique_cmp );
 
7767
      tl_assert(yaWFM);
 
7768
   }
 
7769
   if (!HG_(lookupFM)( yaWFM, NULL, (Word*)&lkp, (Word)lkn)) {
 
7770
      lkp = hg_zalloc( sizeof(Lock) );
 
7771
      *lkp = *lkn;
 
7772
      lkp->admin = NULL;
 
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
 
7776
         versa. */
 
7777
      lkp->heldW  = False;
 
7778
      lkp->heldBy = NULL;
 
7779
      lkp->acquired_at = NULL;
 
7780
      HG_(addToFM)( yaWFM, (Word)lkp, (Word)lkp );
 
7781
   }
 
7782
   tl_assert( is_sane_LockP(lkp) );
 
7783
   return lkp;
 
7784
}
 
7785
 
 
7786
/* Errors:
 
7787
 
 
7788
      race: program counter
 
7789
            read or write
 
7790
            data size
 
7791
            previous state
 
7792
            current state
 
7793
 
 
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.
 
7801
*/
 
7802
 
 
7803
/* Error kinds */
 
7804
typedef
 
7805
   enum {
 
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)
 
7814
   }
 
7815
   XErrorTag;
 
7816
 
 
7817
/* Extra contexts for kinds */
 
7818
typedef
 
7819
   struct  {
 
7820
      XErrorTag tag;
 
7821
      union {
 
7822
         struct {
 
7823
            Addr  data_addr;
 
7824
            Int   szB;
 
7825
            Bool  isWrite;
 
7826
            SVal  new_state;
 
7827
            SVal  old_state;
 
7828
            ExeContext* mb_lastlock;
 
7829
            Thread* thr;
 
7830
         } Race;
 
7831
         struct {
 
7832
            Thread* thr;  /* doing the freeing */
 
7833
            Lock*   lock; /* lock which is locked */
 
7834
         } FreeMemLock;
 
7835
         struct {
 
7836
            Thread* thr;  /* doing the unlocking */
 
7837
            Lock*   lock; /* lock (that is already unlocked) */
 
7838
         } UnlockUnlocked;
 
7839
         struct {
 
7840
            Thread* thr;    /* doing the unlocking */
 
7841
            Thread* owner;  /* thread that actually holds the lock */
 
7842
            Lock*   lock;   /* lock (that is held by 'owner') */
 
7843
         } UnlockForeign;
 
7844
         struct {
 
7845
            Thread* thr;     /* doing the unlocking */
 
7846
            Addr    lock_ga; /* purported address of the lock */
 
7847
         } UnlockBogus;
 
7848
         struct {
 
7849
            Thread* thr; 
 
7850
            HChar*  fnname; /* persistent, in tool-arena */
 
7851
            Word    err;    /* pth error code */
 
7852
            HChar*  errstr; /* persistent, in tool-arena */
 
7853
         } PthAPIerror;
 
7854
         struct {
 
7855
            Thread*     thr;
 
7856
            Addr        before_ga; /* always locked first in prog. history */
 
7857
            Addr        after_ga;
 
7858
            ExeContext* before_ec;
 
7859
            ExeContext* after_ec;
 
7860
         } LockOrder;
 
7861
         struct {
 
7862
            Thread* thr;
 
7863
            HChar*  errstr; /* persistent, in tool-arena */
 
7864
         } Misc;
 
7865
      } XE;
 
7866
   }
 
7867
   XError;
 
7868
 
 
7869
static void init_XError ( XError* xe ) {
 
7870
   VG_(memset)(xe, 0, sizeof(*xe) );
 
7871
   xe->tag = XE_Race-1; /* bogus */
 
7872
}
 
7873
 
 
7874
 
 
7875
/* Extensions of suppressions */
 
7876
typedef
 
7877
   enum {
 
7878
      XS_Race=1201, /* race */
 
7879
      XS_FreeMemLock,
 
7880
      XS_UnlockUnlocked,
 
7881
      XS_UnlockForeign,
 
7882
      XS_UnlockBogus,
 
7883
      XS_PthAPIerror,
 
7884
      XS_LockOrder,
 
7885
      XS_Misc
 
7886
   }
 
7887
   XSuppTag;
2499
7888
 
2500
7889
 
2501
7890
/* Updates the copy with address info if necessary. */
2502
 
static UInt hg_update_extra(Error* err)
2503
 
{
2504
 
   HelgrindError* extra;
2505
 
 
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) );
2509
 
   }
2510
 
   return sizeof(HelgrindError);
2511
 
}
2512
 
 
2513
 
static void record_race_error ( ThreadId tid, Addr a, Bool is_write,
2514
 
                                shadow_word prevstate )
2515
 
{
2516
 
   shadow_word *sw;
2517
 
   HelgrindError err_extra;
2518
 
 
2519
 
   n_hg_warnings++;
2520
 
 
2521
 
   clear_HelgrindError(&err_extra);
2522
 
   err_extra.isWrite = is_write;
2523
 
   err_extra.addrinfo.akind = Undescribed;
2524
 
   err_extra.prevstate = prevstate;
2525
 
   if (clo_execontext)
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); */
2530
 
 
2531
 
   VG_(maybe_record_error)( tid, RaceErr, a, 
2532
 
                            (is_write ? "writing" : "reading"),
2533
 
                            &err_extra);
2534
 
 
2535
 
   sw = get_sword_addr(a);
2536
 
   if (sw->state == Vge_Excl && sw->other != TLSP_INDICATING_ALL) {
2537
 
      ThreadLifeSeg *tls = unpackTLS(sw->other);
2538
 
      tls->refcount--;
2539
 
   }
2540
 
 
2541
 
   set_sword(a, error_sword);
2542
 
}
2543
 
 
2544
 
static void record_mutex_error(ThreadId tid, Mutex *mutex, 
2545
 
                               Char *str, ExeContext *ec)
2546
 
{
2547
 
   HelgrindError err_extra;
2548
 
 
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;
2554
 
 
2555
 
   VG_(maybe_record_error)(tid, MutexErr, 
2556
 
                           (Addr)mutex->mutexp, str, &err_extra);
2557
 
}
2558
 
 
2559
 
static void record_lockgraph_error(ThreadId tid, Mutex *mutex,
2560
 
                                   const LockSet *lockset_holding,
2561
 
                                   const LockSet *lockset_prev)
2562
 
{
2563
 
   HelgrindError err_extra;
2564
 
 
2565
 
   n_lockorder_warnings++;
2566
 
 
2567
 
   clear_HelgrindError(&err_extra);
2568
 
   err_extra.addrinfo.akind = Undescribed;
2569
 
   err_extra.mutex = mutex;
2570
 
   
2571
 
   err_extra.lasttouched = EC(mutex->location, virgin_sword, 0);
2572
 
   err_extra.held_lockset = lockset_holding;
2573
 
   err_extra.prev_lockset = lockset_prev;
2574
 
   
2575
 
   VG_(maybe_record_error)(tid, LockGraphErr, mutex->mutexp, "", &err_extra);
 
7891
static UInt hg_update_extra ( Error* err )
 
7892
{
 
7893
   XError* extra = (XError*)VG_(get_error_extra)(err);
 
7894
   tl_assert(extra);
 
7895
   //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
 
7896
   //   describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
 
7897
   //}
 
7898
   return sizeof(XError);
 
7899
}
 
7900
 
 
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 ) {
 
7905
   XError xe;
 
7906
   tl_assert( is_sane_Thread(thr) );
 
7907
   init_XError(&xe);
 
7908
   xe.tag = XE_Race;
 
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 );
 
7921
}
 
7922
 
 
7923
static void record_error_FreeMemLock ( Thread* thr, Lock* lk ) {
 
7924
   XError xe;
 
7925
   tl_assert( is_sane_Thread(thr) );
 
7926
   tl_assert( is_sane_LockN(lk) );
 
7927
   init_XError(&xe);
 
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 );
 
7934
}
 
7935
 
 
7936
static void record_error_UnlockUnlocked ( Thread* thr, Lock* lk ) {
 
7937
   XError xe;
 
7938
   tl_assert( is_sane_Thread(thr) );
 
7939
   tl_assert( is_sane_LockN(lk) );
 
7940
   init_XError(&xe);
 
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 );
 
7947
}
 
7948
 
 
7949
static void record_error_UnlockForeign ( Thread* thr,
 
7950
                                         Thread* owner, Lock* lk ) {
 
7951
   XError xe;
 
7952
   tl_assert( is_sane_Thread(thr) );
 
7953
   tl_assert( is_sane_Thread(owner) );
 
7954
   tl_assert( is_sane_LockN(lk) );
 
7955
   init_XError(&xe);
 
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 );
 
7963
}
 
7964
 
 
7965
static void record_error_UnlockBogus ( Thread* thr, Addr lock_ga ) {
 
7966
   XError xe;
 
7967
   tl_assert( is_sane_Thread(thr) );
 
7968
   init_XError(&xe);
 
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 );
 
7975
}
 
7976
 
 
7977
static 
 
7978
void record_error_LockOrder ( Thread* thr, Addr before_ga, Addr after_ga,
 
7979
                              ExeContext* before_ec, ExeContext* after_ec ) {
 
7980
   XError xe;
 
7981
   tl_assert( is_sane_Thread(thr) );
 
7982
   init_XError(&xe);
 
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 );
 
7992
}
 
7993
 
 
7994
static 
 
7995
void record_error_PthAPIerror ( Thread* thr, HChar* fnname, 
 
7996
                                Word err, HChar* errstr ) {
 
7997
   XError xe;
 
7998
   tl_assert( is_sane_Thread(thr) );
 
7999
   tl_assert(fnname);
 
8000
   tl_assert(errstr);
 
8001
   init_XError(&xe);
 
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 );
 
8010
}
 
8011
 
 
8012
static void record_error_Misc ( Thread* thr, HChar* errstr ) {
 
8013
   XError xe;
 
8014
   tl_assert( is_sane_Thread(thr) );
 
8015
   tl_assert(errstr);
 
8016
   init_XError(&xe);
 
8017
   xe.tag = XE_Misc;
 
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 );
2576
8023
}
2577
8024
 
2578
8025
static Bool hg_eq_Error ( VgRes not_used, Error* e1, Error* e2 )
2579
8026
{
2580
 
   Char *e1s, *e2s;
 
8027
   XError *xe1, *xe2;
2581
8028
 
2582
8029
   tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
2583
8030
 
 
8031
   xe1 = (XError*)VG_(get_error_extra)(e1);
 
8032
   xe2 = (XError*)VG_(get_error_extra)(e2);
 
8033
   tl_assert(xe1);
 
8034
   tl_assert(xe2);
 
8035
 
2584
8036
   switch (VG_(get_error_kind)(e1)) {
2585
 
   case RaceErr:
2586
 
      return VG_(get_error_address)(e1) == VG_(get_error_address)(e2);
2587
 
 
2588
 
   case MutexErr:
2589
 
      return VG_(get_error_address)(e1) == VG_(get_error_address)(e2);
2590
 
   }
2591
 
 
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;
2596
 
   return True;
2597
 
}
2598
 
 
2599
 
static void pp_AddrInfo ( Addr a, AddrInfo* ai )
2600
 
{
2601
 
   if (ai->expr != NULL)
2602
 
      VG_(message)(Vg_UserMsg, 
2603
 
                   " Address %p == %s", a, ai->expr);
2604
 
   
2605
 
   switch (ai->akind) {
2606
 
      case Stack: 
2607
 
         VG_(message)(Vg_UserMsg, 
2608
 
                      " Address %p is on thread %d's stack", 
2609
 
                      a, ai->stack_tid);
2610
 
         break;
2611
 
      case Unknown:
2612
 
         if (ai->expr != NULL)
2613
 
            break;
2614
 
 
2615
 
         /* maybe_gcc is never set to True!  This is a hangover from code
2616
 
            in Memcheck */
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++",
2620
 
               a);
2621
 
            VG_(message)(Vg_UserMsg, 
2622
 
               "   v 2.96 or 3.0.X.  To suppress, use: --workaround-gcc296-bugs=yes");
2623
 
         } else {
2624
 
            VG_(message)(Vg_UserMsg, 
2625
 
               " Address %p is not stack'd, malloc'd or (recently) free'd", a);
2626
 
         }
2627
 
         break;
2628
 
      case Segment:
2629
 
        VG_(message)(Vg_UserMsg,
2630
 
                     " Address %p is in %s section of %s", 
2631
 
                     a, ai->section, ai->filename);
2632
 
        break;
2633
 
      case Mallocd:
2634
 
      case Freed: {
2635
 
         SizeT delta;
2636
 
         UChar* relative;
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;
2642
 
            relative = "after";
2643
 
         } else {
2644
 
            delta    = ai->rwoffset;
2645
 
            relative = "inside";
2646
 
         }
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, 
2650
 
                      ai->blksize,
2651
 
                      ai->akind == Mallocd ? "alloc'd" : "freed",
2652
 
                      ai->lasttid);
2653
 
 
2654
 
         VG_(pp_ExeContext)(ai->lastchange);
2655
 
         break;
2656
 
      }   
 
8037
      case XE_Race:
 
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
 
8042
                       : True);
 
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;
 
8061
      case XE_LockOrder:
 
8062
         return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
 
8063
      case XE_Misc:
 
8064
         return xe1->XE.Misc.thr == xe2->XE.Misc.thr
 
8065
                && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
2657
8066
      default:
2658
 
         VG_(tool_panic)("pp_AddrInfo");
2659
 
   }
2660
 
}
2661
 
 
2662
 
static Char *lockset_str(const Char *prefix, const LockSet *lockset)
2663
 
{
2664
 
   Char *buf, *cp;
2665
 
   Int i;
2666
 
 
2667
 
   buf = VG_(malloc)((prefix == NULL ? 0 : VG_(strlen)(prefix)) +
2668
 
                     lockset->setsize * 120 +
2669
 
                     1);
2670
 
 
2671
 
   cp = buf;
2672
 
   if (prefix)
2673
 
      cp += VG_(sprintf)(cp, "%s", prefix);
2674
 
 
2675
 
   for(i = 0; i < lockset->setsize; i++)
2676
 
      cp += VG_(sprintf)(cp, "%p%(y, ", lockset->mutex[i]->mutexp, 
2677
 
                         lockset->mutex[i]->mutexp);
2678
 
 
2679
 
   if (lockset->setsize)
2680
 
      cp[-2] = '\0';
2681
 
   else
2682
 
      *cp = '\0';
2683
 
 
2684
 
   return buf;
 
8067
         tl_assert(0);
 
8068
   }
 
8069
 
 
8070
   /*NOTREACHED*/
 
8071
   tl_assert(0);
 
8072
}
 
8073
 
 
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;
 
8085
   return 0;
 
8086
}
 
8087
static XArray* /* of Thread* */ get_sorted_thread_set ( WordSetID tset )
 
8088
{
 
8089
   XArray* xa;
 
8090
   Word*   ts_words;
 
8091
   Word    ts_size, i;
 
8092
   xa = VG_(newXA)( hg_zalloc, hg_free, sizeof(Thread*) );
 
8093
   tl_assert(xa);
 
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 );
 
8103
   }
 
8104
   tl_assert(ts_size == VG_(sizeXA)( xa ));
 
8105
   VG_(setCmpFnXA)( xa, cmp_Thread_by_errmsg_index );
 
8106
   VG_(sortXA)( xa );
 
8107
   return xa;
 
8108
}
 
8109
 
 
8110
 
 
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. */
 
8119
 
 
8120
static void announce_threadset ( WordSetID tset )
 
8121
{
 
8122
   const Word limit = N_THREADS_TO_ANNOUNCE;
 
8123
   Thread* thr;
 
8124
   XArray* sorted;
 
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);
 
8135
      if (thr->announced)
 
8136
         continue;
 
8137
      if (thr->errmsg_index == 1/*FIXME: this hardwires an assumption
 
8138
                                  about the identity of the root
 
8139
                                  thread*/) {
 
8140
         tl_assert(thr->created_at == NULL);
 
8141
         VG_(message)(Vg_UserMsg, "Thread #%d is the program's root thread",
 
8142
                                  thr->errmsg_index);
 
8143
      } else {
 
8144
         tl_assert(thr->created_at != NULL);
 
8145
         VG_(message)(Vg_UserMsg, "Thread #%d was created",
 
8146
                                  thr->errmsg_index);
 
8147
         VG_(pp_ExeContext)( thr->created_at );
 
8148
      }
 
8149
      VG_(message)(Vg_UserMsg, "");
 
8150
      thr->announced = True;
 
8151
   }
 
8152
   VG_(deleteXA)( sorted );
 
8153
}
 
8154
static void announce_one_thread ( Thread* thr ) {
 
8155
   announce_threadset( HG_(singletonWS)(univ_tsets, (Word)thr ));
 
8156
}
 
8157
 
 
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. */
 
8162
 
 
8163
static void summarise_threadset ( WordSetID tset, Char* buf, UInt nBuf )
 
8164
{
 
8165
   const Word limit = N_THREADS_TO_ANNOUNCE;
 
8166
   Thread* thr;
 
8167
   XArray* sorted;
 
8168
   Word    ts_size, i, loopmax;
 
8169
   UInt    off = 0;
 
8170
   tl_assert(nBuf > 0);
 
8171
   tl_assert(nBuf >= 40 + 20*limit);
 
8172
   tl_assert(buf);
 
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);
 
8184
      if (i < loopmax-1)
 
8185
         off += VG_(sprintf)(&buf[off], ", ");
 
8186
   }
 
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" : "");
 
8191
   }
 
8192
   tl_assert(off < nBuf);
 
8193
   tl_assert(buf[nBuf-1] == 0);
 
8194
   VG_(deleteXA)( sorted );
2685
8195
}
2686
8196
 
2687
8197
static void hg_pp_Error ( Error* err )
2688
8198
{
2689
 
   HelgrindError *extra = (HelgrindError *)VG_(get_error_extra)(err);
2690
 
   Char buf[100];
2691
 
   Char *msg = buf;
2692
 
   const LockSet *ls;
2693
 
 
2694
 
   *msg = '\0';
2695
 
 
2696
 
   switch(VG_(get_error_kind)(err)) {
2697
 
   case RaceErr: {
2698
 
      Addr err_addr = VG_(get_error_address)(err);
2699
 
                      
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);
2704
 
 
2705
 
      switch(extra->prevstate.state) {
2706
 
      case Vge_Virgin:
2707
 
         /* shouldn't be possible to go directly from virgin -> error */
2708
 
         VG_(sprintf)(buf, "virgin!?");
2709
 
         break;
2710
 
 
2711
 
      case Vge_Excl: {
2712
 
         ThreadLifeSeg *tls = unpackTLS(extra->prevstate.other);
2713
 
 
2714
 
         tl_assert(tls != unpackTLS(TLSP_INDICATING_ALL));
2715
 
         VG_(sprintf)(buf, "exclusively owned by thread %u", tls->tid);
2716
 
         break;
2717
 
      }
2718
 
 
2719
 
      case Vge_Shar:
2720
 
      case Vge_SharMod:
2721
 
         ls = unpackLockSet(extra->prevstate.other);
2722
 
 
2723
 
         if (isempty(ls)) {
2724
 
            VG_(sprintf)(buf, "shared %s, no locks", 
2725
 
                         extra->prevstate.state == Vge_Shar ? "RO" : "RW");
2726
 
            break;
2727
 
         }
2728
 
 
2729
 
         msg = lockset_str(extra->prevstate.state == Vge_Shar ?
2730
 
                           "shared RO, locked by:" :
2731
 
                           "shared RW, locked by:", ls);
2732
 
 
2733
 
         break;
2734
 
      }
2735
 
 
2736
 
      if (*msg)
2737
 
         VG_(message)(Vg_UserMsg, " Previous state: %s", msg);
2738
 
 
2739
 
      if (clo_execontext == EC_Some 
2740
 
          && extra->lasttouched.uu_ec_ip.ip != 0) {
2741
 
         Char file[100];
2742
 
         UInt line;
2743
 
         Addr ip = extra->lasttouched.uu_ec_ip.ip;
2744
 
         
2745
 
         VG_(message)(Vg_UserMsg, " Word at %p last changed state from %s by thread %u",
2746
 
                      err_addr,
2747
 
                      pp_state(extra->lasttouched.state),
2748
 
                      unpackTLS(extra->lasttouched.tls)->tid);
2749
 
         
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)",
2756
 
                         ip, ip, file);
2757
 
         } else {
2758
 
            VG_(message)(Vg_UserMsg, "   at %p: %y", ip, ip);
2759
 
         }
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",
2763
 
                      err_addr,
2764
 
                      pp_state(extra->lasttouched.state),
2765
 
                      unpackTLS(extra->lasttouched.tls)->tid);
2766
 
         VG_(pp_ExeContext)(extra->lasttouched.uu_ec_ip.ec);
2767
 
      }
2768
 
      break;
2769
 
   }
2770
 
 
2771
 
   case MutexErr:
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);
2780
 
      }
2781
 
      pp_AddrInfo(VG_(get_error_address)(err), &extra->addrinfo);
2782
 
      break;
2783
 
 
2784
 
   case LockGraphErr: {
2785
 
      const LockSet *heldset = extra->held_lockset;
2786
 
      Addr err_addr = VG_(get_error_address)(err);
2787
 
      Int i;
2788
 
 
2789
 
      msg = lockset_str(NULL, heldset);
2790
 
 
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);
2795
 
 
2796
 
      for(i = 0; i < heldset->setsize; i++) {
2797
 
         const Mutex *lsmx = heldset->mutex[i];
2798
 
 
2799
 
         /* needs to be a recursive search+display */
2800
 
         if (0 && !ismember(lsmx->lockdep, extra->mutex))
2801
 
            continue;
2802
 
      
2803
 
         VG_(message)(Vg_UserMsg, " %p%(y last locked at", 
2804
 
                      lsmx->mutexp, lsmx->mutexp);
2805
 
         VG_(pp_ExeContext)(lsmx->location);
2806
 
         VG_(free)(msg);
2807
 
         msg = lockset_str(NULL, lsmx->lockdep);
2808
 
         VG_(message)(Vg_UserMsg, " while depending on locks %s", msg);
2809
 
      }
2810
 
      
2811
 
      break;
2812
 
   }
2813
 
   }
2814
 
 
2815
 
   if (msg != buf)
2816
 
      VG_(free)(msg);
2817
 
}
2818
 
 
 
8199
   const Bool show_raw_states = False;
 
8200
   XError *xe = (XError*)VG_(get_error_extra)(err);
 
8201
 
 
8202
   switch (VG_(get_error_kind)(err)) {
 
8203
 
 
8204
   case XE_Misc: {
 
8205
      tl_assert(xe);
 
8206
      tl_assert( is_sane_Thread( xe->XE.Misc.thr ) );
 
8207
      announce_one_thread( xe->XE.Misc.thr );
 
8208
      VG_(message)(Vg_UserMsg,
 
8209
                  "Thread #%d: %s",
 
8210
                  (Int)xe->XE.Misc.thr->errmsg_index,
 
8211
                  xe->XE.Misc.errstr);
 
8212
      VG_(pp_ExeContext)( VG_(get_error_where)(err) );
 
8213
      break;
 
8214
   }
 
8215
 
 
8216
   case XE_LockOrder: {
 
8217
      tl_assert(xe);
 
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 );
 
8235
      }
 
8236
      break;
 
8237
   }
 
8238
 
 
8239
   case XE_PthAPIerror: {
 
8240
      tl_assert(xe);
 
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) );
 
8252
      break;
 
8253
   }
 
8254
 
 
8255
   case XE_UnlockBogus: {
 
8256
      tl_assert(xe);
 
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) );
 
8264
      break;
 
8265
   }
 
8266
 
 
8267
   case XE_UnlockForeign: {
 
8268
      tl_assert(xe);
 
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 );
 
8286
      }
 
8287
      break;
 
8288
   }
 
8289
 
 
8290
   case XE_UnlockUnlocked: {
 
8291
      tl_assert(xe);
 
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 );
 
8305
      }
 
8306
      break;
 
8307
   }
 
8308
 
 
8309
   case XE_FreeMemLock: {
 
8310
      tl_assert(xe);
 
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 );
 
8325
      }
 
8326
      break;
 
8327
   }
 
8328
 
 
8329
   case XE_Race: {
 
8330
      Addr      err_ga;
 
8331
      Char      old_buf[100], new_buf[100];
 
8332
      Char      old_tset_buf[140], new_tset_buf[140];
 
8333
      SVal      old_state, new_state;
 
8334
      Thread*   thr_acc;
 
8335
      HChar*    what;
 
8336
      Int       szB;
 
8337
      WordSetID tset_to_announce = HG_(emptyWS)( univ_tsets );
 
8338
 
 
8339
      /* First extract some essential info */
 
8340
      tl_assert(xe);
 
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);
 
8348
 
 
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);
 
8352
 
 
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. */
 
8358
 
 
8359
      /* CASE of Excl -> ShM */
 
8360
      if (is_SHVAL_Excl(old_state) && is_SHVAL_ShM(new_state)) {
 
8361
         SegmentID old_segid;
 
8362
         Segment*  old_seg;
 
8363
         Thread*   old_thr; 
 
8364
         WordSetID new_tset;
 
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));
 
8372
 
 
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 );
 
8377
 
 
8378
         VG_(message)(Vg_UserMsg,
 
8379
                      "Possible data race during %s of size %d at %p",
 
8380
                      what, szB, err_ga);
 
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",
 
8394
                      new_tset_buf );
 
8395
         VG_(message)(Vg_UserMsg,
 
8396
                      "  Reason:    this thread, #%d, holds no locks at all",
 
8397
                      thr_acc->errmsg_index);
 
8398
      }
 
8399
      else 
 
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);
 
8404
 
 
8405
         tset_to_announce = HG_(unionWS)( univ_tsets, old_tset, new_tset );
 
8406
         announce_threadset( tset_to_announce );
 
8407
 
 
8408
         VG_(message)(Vg_UserMsg,
 
8409
                      "Possible data race during %s of size %d at %p",
 
8410
                      what, szB, err_ga);
 
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);
 
8417
 
 
8418
         summarise_threadset( old_tset, old_tset_buf, sizeof(old_tset_buf) );
 
8419
         summarise_threadset( new_tset, new_tset_buf, sizeof(new_tset_buf) );
 
8420
 
 
8421
         VG_(message)(Vg_UserMsg,
 
8422
                      "  Old state: shared-%s by threads %s", 
 
8423
                      is_SHVAL_ShM(old_state) ? "modified" : "readonly", 
 
8424
                      old_tset_buf);
 
8425
         VG_(message)(Vg_UserMsg,
 
8426
                      "  New state: shared-modified by threads %s", 
 
8427
                      new_tset_buf);
 
8428
         VG_(message)(Vg_UserMsg,
 
8429
                      "  Reason:    this thread, #%d, holds no "
 
8430
                      "consistent locks",
 
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);
 
8436
         } else {
 
8437
            VG_(message)(Vg_UserMsg, "  Location %p has never been protected "
 
8438
                                     "by any lock", err_ga);
 
8439
         }
 
8440
      }
 
8441
      /* Hmm, unknown transition.  Just print what we do know. */
 
8442
      else {
 
8443
         VG_(message)(Vg_UserMsg,
 
8444
                      "Possible data race during %s of size %d at %p",
 
8445
                      what, szB, err_ga);
 
8446
         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
 
8447
 
 
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);
 
8452
      }
 
8453
 
 
8454
      break; /* case XE_Race */
 
8455
   } /* case XE_Race */
 
8456
 
 
8457
   default:
 
8458
      tl_assert(0);
 
8459
   } /* switch (VG_(get_error_kind)(err)) */
 
8460
}
 
8461
 
 
8462
static Char* hg_get_error_name ( Error* err )
 
8463
{
 
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 */
 
8474
   }
 
8475
}
2819
8476
 
2820
8477
static Bool hg_recognised_suppression ( Char* name, Supp *su )
2821
8478
{
2822
 
   if (0 == VG_(strcmp)(name, "Eraser")) {
2823
 
      VG_(set_supp_kind)(su, RaceSupp);
2824
 
      return True;
2825
 
   } else {
2826
 
      return False;
2827
 
   }
 
8479
#  define TRY(_name,_xskind)                   \
 
8480
      if (0 == VG_(strcmp)(name, (_name))) {   \
 
8481
         VG_(set_supp_kind)(su, (_xskind));    \
 
8482
         return True;                          \
 
8483
      }
 
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);
 
8492
   return False;
 
8493
#  undef TRY
2828
8494
}
2829
8495
 
2830
 
 
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,
 
8497
                                             Supp* su )
2832
8498
{
2833
8499
   /* do nothing -- no extra suppression info present.  Return True to
2834
8500
      indicate nothing bad happened. */
2835
8501
   return True;
2836
8502
}
2837
8503
 
2838
 
 
2839
 
static Bool hg_error_matches_suppression(Error* err, Supp* su)
2840
 
{
2841
 
   tl_assert(VG_(get_supp_kind)(su) == RaceSupp);
2842
 
 
2843
 
   return (VG_(get_error_kind)(err) == RaceErr);
2844
 
}
2845
 
 
2846
 
static Char* hg_get_error_name ( Error* err )
2847
 
{
2848
 
   if (RaceErr == VG_(get_error_kind)(err)) {
2849
 
      return "Eraser";     // old name, required for backwards compatibility
2850
 
   } else {
2851
 
      return NULL;      /* Other errors types can't be suppressed */
 
8504
static Bool hg_error_matches_suppression ( Error* err, Supp* su )
 
8505
{
 
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 */
2852
8517
   }
2853
8518
}
2854
8519
 
2857
8522
   /* Do nothing */
2858
8523
}
2859
8524
 
2860
 
static void hg_pre_mutex_lock(ThreadId tid, void* void_mutex)
2861
 
{
2862
 
   Mutex *mutex = get_mutex((Addr)void_mutex);
2863
 
 
2864
 
   test_mutex_state(mutex, MxLocked, tid);
2865
 
}
2866
 
 
2867
 
static void hg_post_mutex_lock(ThreadId tid, void* void_mutex)
2868
 
{
2869
 
   static const Bool debug = False;
2870
 
   Mutex *mutex = get_mutex((Addr)void_mutex);
2871
 
   const LockSet*  ls;
2872
 
 
2873
 
   set_mutex_state(mutex, MxLocked, tid);
2874
 
 
2875
 
#  if DEBUG_LOCKS
2876
 
   VG_(printf)("lock  (%u, %p)\n", tid, mutex->mutexp);
2877
 
#  endif
2878
 
 
2879
 
   /* VG_(printf)("LOCK: held %d, new %p\n", thread_locks[tid], mutex); */
2880
 
#  if LOCKSET_SANITY > 1
2881
 
   sanity_check_locksets("hg_post_mutex_lock-IN");
2882
 
#  endif
2883
 
 
2884
 
   ls = lookup_LockSet_with(thread_locks[tid], mutex);
2885
 
 
2886
 
   if (ls == NULL) {
2887
 
      LockSet *newset = add_LockSet(thread_locks[tid], mutex);
2888
 
      insert_LockSet(newset);
2889
 
      ls = newset;
2890
 
   }
2891
 
   thread_locks[tid] = ls;
2892
 
 
2893
 
   if (debug || DEBUG_LOCKS)
2894
 
      VG_(printf)("tid %u now has lockset %p\n", tid, ls);
2895
 
 
2896
 
   if (debug || LOCKSET_SANITY > 1)
2897
 
      sanity_check_locksets("hg_post_mutex_lock-OUT");
2898
 
}
2899
 
 
2900
 
 
2901
 
static void hg_post_mutex_unlock(ThreadId tid, void* void_mutex)
2902
 
{
2903
 
   static const Bool debug = False;
2904
 
   Int i = 0;
2905
 
   Mutex *mutex = get_mutex((Addr)void_mutex);
2906
 
   const LockSet *ls;
2907
 
 
2908
 
   test_mutex_state(mutex, MxUnlocked, tid);
2909
 
   set_mutex_state(mutex, MxUnlocked, tid);
2910
 
 
2911
 
   if (!ismember(thread_locks[tid], mutex))
2912
 
       return;
2913
 
 
2914
 
   if (debug || DEBUG_LOCKS)
2915
 
      VG_(printf)("unlock(%u, %p%(y)\n", tid, mutex->mutexp, mutex->mutexp);
2916
 
 
2917
 
   if (debug || LOCKSET_SANITY > 1)
2918
 
      sanity_check_locksets("hg_post_mutex_unlock-IN");
2919
 
 
2920
 
   ls = lookup_LockSet_without(thread_locks[tid], mutex);
2921
 
 
2922
 
   if (ls == NULL) {
2923
 
      LockSet *newset = remove_LockSet(thread_locks[tid], mutex);
2924
 
      insert_LockSet(newset);
2925
 
      ls = newset;
2926
 
   }
2927
 
 
2928
 
   /* Update the thread's lock vector */
2929
 
   if (debug || DEBUG_LOCKS)
2930
 
      VG_(printf)("tid %u reverts from %p to lockset %p\n", 
2931
 
                  tid, thread_locks[tid], i);
2932
 
 
2933
 
   thread_locks[tid] = ls;
2934
 
 
2935
 
   if (debug || LOCKSET_SANITY > 1)
2936
 
      sanity_check_locksets("hg_post_mutex_unlock-OUT");
2937
 
}
2938
 
 
2939
 
 
2940
 
/* ---------------------------------------------------------------------
2941
 
   Checking memory reads and writes
2942
 
   ------------------------------------------------------------------ */
2943
 
 
2944
 
/* Behaviour on reads and writes:
2945
 
 *
2946
 
 *                      VIR          EXCL        SHAR        SH_MOD
2947
 
 * ----------------------------------------------------------------
2948
 
 * rd/wr, 1st thread |  -            EXCL        -           -
2949
 
 * rd, new thread    |  -            SHAR        -           -
2950
 
 * wr, new thread    |  -            SH_MOD      -           -
2951
 
 * rd                |  error!       -           SHAR        SH_MOD
2952
 
 * wr                |  EXCL         -           SH_MOD      SH_MOD
2953
 
 * ----------------------------------------------------------------
2954
 
 */
2955
 
 
2956
 
static inline
2957
 
void dump_around_a(Addr a)
2958
 
{
2959
 
   UInt i;
2960
 
   shadow_word* sword;
2961
 
   VG_(printf)("NEARBY:\n");
2962
 
   for (i = a - 12; i <= a + 12; i += 4) {
2963
 
      sword = get_sword_addr(i); 
2964
 
      VG_(printf)("    %x -- tid: %u, state: %u\n", i, sword->other, sword->state);
2965
 
   }
2966
 
}
2967
 
 
2968
 
#if DEBUG_ACCESSES
2969
 
   #define DEBUG_STATE(args...)   \
2970
 
      VG_(printf)("(%u) ", size), \
2971
 
      VG_(printf)(args)
2972
 
#else
2973
 
   #define DEBUG_STATE(args...)
2974
 
#endif
2975
 
 
2976
 
static void hg_mem_read_word(Addr a, ThreadId tid)
2977
 
{
2978
 
   shadow_word* sword /* egcs-2.91.66 complains uninit */ = NULL; 
2979
 
   shadow_word  prevstate;
2980
 
   ThreadLifeSeg *tls;
2981
 
   const LockSet *ls;
2982
 
   Bool statechange = False;
2983
 
 
2984
 
   static const void *const states[4] = {
2985
 
      [Vge_Virgin]  &&st_virgin,
2986
 
      [Vge_Excl]    &&st_excl,
2987
 
      [Vge_Shar]    &&st_shar,
2988
 
      [Vge_SharMod] &&st_sharmod,
2989
 
   };
2990
 
 
2991
 
   tls = thread_seg[tid];
2992
 
   tl_assert(tls != NULL && tls->tid == tid);
2993
 
 
2994
 
   sword = get_sword_addr(a);
2995
 
   if (sword == SEC_MAP_ACCESS) {
2996
 
      VG_(printf)("read distinguished 2ndary map! 0x%x\n", a);
2997
 
      return;
2998
 
   }
2999
 
 
3000
 
   prevstate = *sword;
3001
 
 
3002
 
   goto *states[sword->state];
3003
 
 
3004
 
   /* This looks like reading of unitialised memory, may be legit.  Eg. 
3005
 
    * calloc() zeroes its values, so untouched memory may actually be 
3006
 
    * initialised.   Leave that stuff to Valgrind.  */
3007
 
  st_virgin:
3008
 
   if (TID_INDICATING_NONVIRGIN == sword->other) {
3009
 
      DEBUG_STATE("Read  VIRGIN --> EXCL:   %8x, %u\n", a, tid);
3010
 
      if (DEBUG_VIRGIN_READS)
3011
 
         dump_around_a(a);
3012
 
   } else {
3013
 
      DEBUG_STATE("Read  SPECIAL --> EXCL:  %8x, %u\n", a, tid);
3014
 
   }
3015
 
   statechange = True;
3016
 
   *sword = SW(Vge_Excl, packTLS(tls));       /* remember exclusive owner */
3017
 
   tls->refcount++;
3018
 
   goto done;
3019
 
 
3020
 
  st_excl: {
3021
 
      ThreadLifeSeg *sw_tls = unpackTLS(sword->other);
3022
 
 
3023
 
      if (tls == sw_tls) {
3024
 
         DEBUG_STATE("Read  EXCL:              %8x, %u\n", a, tid);
3025
 
      } else if (unpackTLS(TLSP_INDICATING_ALL) == sw_tls) {
3026
 
         DEBUG_STATE("Read  EXCL/ERR:          %8x, %u\n", a, tid);
3027
 
      } else if (tlsIsDisjoint(tls, sw_tls)) {
3028
 
         DEBUG_STATE("Read  EXCL(%u) --> EXCL:  %8x, %u\n", sw_tls->tid, a, tid);
3029
 
         statechange = True;
3030
 
         sword->other = packTLS(tls);
3031
 
         sw_tls->refcount--;
3032
 
         tls->refcount++;
3033
 
      } else {
3034
 
         DEBUG_STATE("Read  EXCL(%u) --> SHAR:  %8x, %u\n", sw_tls->tid, a, tid);
3035
 
         sw_tls->refcount--;
3036
 
         statechange = True;
3037
 
         *sword = SW(Vge_Shar, packLockSet(thread_locks[tid]));
3038
 
            
3039
 
         if (DEBUG_MEM_LOCKSET_CHANGES)
3040
 
            print_LockSet("excl read locks", unpackLockSet(sword->other));
3041
 
      }
3042
 
      goto done;
3043
 
   }
3044
 
 
3045
 
  st_shar:
3046
 
   DEBUG_STATE("Read  SHAR:              %8x, %u\n", a, tid);
3047
 
   sword->other = packLockSet(intersect(unpackLockSet(sword->other), 
3048
 
                                        thread_locks[tid]));
3049
 
   statechange = sword->other != prevstate.other;
3050
 
   goto done;
3051
 
 
3052
 
  st_sharmod:
3053
 
   DEBUG_STATE("Read  SHAR_MOD:          %8x, %u\n", a, tid);
3054
 
   ls = intersect(unpackLockSet(sword->other), 
3055
 
                  thread_locks[tid]);
3056
 
   sword->other = packLockSet(ls);
3057
 
 
3058
 
   statechange = sword->other != prevstate.other;
3059
 
 
3060
 
   if (isempty(ls)) {
3061
 
      record_race_error(tid, a, False /* !is_write */, prevstate);
3062
 
   }
3063
 
   goto done;
3064
 
 
3065
 
  done:
3066
 
   if (clo_execontext != EC_None && statechange) {
3067
 
      EC_IP ecip;
3068
 
 
3069
 
      if (clo_execontext == EC_Some)
3070
 
         ecip = IP(VG_(get_IP)(tid), prevstate, tls);
3071
 
      else
3072
 
         ecip = EC(VG_(record_ExeContext)(tid), prevstate, tls);
3073
 
      setExeContext(a, ecip);
3074
 
   }
3075
 
}
3076
 
 
3077
 
static void hg_mem_read(Addr a, SizeT size, ThreadId tid)
3078
 
{
3079
 
   Addr end;
3080
 
 
3081
 
   end = VG_ROUNDUP(a+size, 4);
3082
 
   a   = VG_ROUNDDN(a, 4);
3083
 
 
3084
 
   for ( ; a < end; a += 4)
3085
 
      hg_mem_read_word(a, tid);
3086
 
}
3087
 
 
3088
 
static void hg_mem_write_word(Addr a, ThreadId tid)
3089
 
{
3090
 
   ThreadLifeSeg *tls;
3091
 
   shadow_word* sword /* egcs-2.91.66 complains uninit */ = NULL;
3092
 
   shadow_word  prevstate;
3093
 
   Bool statechange = False;
3094
 
   static const void *const states[4] = {
3095
 
      [Vge_Virgin]  &&st_virgin,
3096
 
      [Vge_Excl]    &&st_excl,
3097
 
      [Vge_Shar]    &&st_shar,
3098
 
      [Vge_SharMod] &&st_sharmod,
3099
 
   };
3100
 
 
3101
 
   tls = thread_seg[tid];
3102
 
   tl_assert(tls != NULL && tls->tid == tid);
3103
 
 
3104
 
   sword = get_sword_addr(a);
3105
 
   if (sword == SEC_MAP_ACCESS) {
3106
 
      VG_(printf)("read distinguished 2ndary map! 0x%x\n", a);
3107
 
      return;
3108
 
   }
3109
 
 
3110
 
   prevstate = *sword;
3111
 
 
3112
 
   goto *states[sword->state];
3113
 
 
3114
 
  st_virgin:
3115
 
   if (TID_INDICATING_NONVIRGIN == sword->other)
3116
 
      DEBUG_STATE("Write VIRGIN --> EXCL:   %8x, %u\n", a, tid);
3117
 
   else
3118
 
      DEBUG_STATE("Write SPECIAL --> EXCL:  %8x, %u\n", a, tid);
3119
 
   statechange = True;
3120
 
   *sword = SW(Vge_Excl, packTLS(tls));/* remember exclusive owner */
3121
 
   tls->refcount++;
3122
 
   goto done;
3123
 
 
3124
 
  st_excl: {
3125
 
      ThreadLifeSeg *sw_tls = unpackTLS(sword->other);
3126
 
 
3127
 
      if (tls == sw_tls) {
3128
 
         DEBUG_STATE("Write EXCL:              %8x, %u\n", a, tid);
3129
 
         goto done;
3130
 
      } else if (unpackTLS(TLSP_INDICATING_ALL) == sw_tls) {
3131
 
         DEBUG_STATE("Write EXCL/ERR:          %8x, %u\n", a, tid);
3132
 
         goto done;
3133
 
      } else if (tlsIsDisjoint(tls, sw_tls)) {
3134
 
         DEBUG_STATE("Write EXCL(%u) --> EXCL: %8x, %u\n", sw_tls->tid, a, tid);
3135
 
         sword->other = packTLS(tls);
3136
 
         sw_tls->refcount--;
3137
 
         tls->refcount++;
3138
 
         goto done;
3139
 
      } else {
3140
 
         DEBUG_STATE("Write EXCL(%u) --> SHAR_MOD: %8x, %u\n", sw_tls->tid, a, tid);
3141
 
         statechange = True;
3142
 
         sw_tls->refcount--;
3143
 
         *sword = SW(Vge_SharMod, packLockSet(thread_locks[tid]));
3144
 
         if(DEBUG_MEM_LOCKSET_CHANGES)
3145
 
            print_LockSet("excl write locks", unpackLockSet(sword->other));
3146
 
         goto SHARED_MODIFIED;
3147
 
      }
3148
 
   }
3149
 
 
3150
 
  st_shar:
3151
 
   DEBUG_STATE("Write SHAR --> SHAR_MOD: %8x, %u\n", a, tid);
3152
 
   sword->state = Vge_SharMod;
3153
 
   sword->other = packLockSet(intersect(unpackLockSet(sword->other),
3154
 
                                        thread_locks[tid]));
3155
 
   statechange = True;
3156
 
   goto SHARED_MODIFIED;
3157
 
 
3158
 
  st_sharmod:
3159
 
   DEBUG_STATE("Write SHAR_MOD:          %8x, %u\n", a, tid);
3160
 
   sword->other = packLockSet(intersect(unpackLockSet(sword->other), 
3161
 
                                        thread_locks[tid]));
3162
 
   statechange = sword->other != prevstate.other;
3163
 
 
3164
 
  SHARED_MODIFIED:
3165
 
   if (isempty(unpackLockSet(sword->other))) {
3166
 
      record_race_error(tid, a, True /* is_write */, prevstate);
3167
 
   }
3168
 
   goto done;
3169
 
 
3170
 
  done:
3171
 
   if (clo_execontext != EC_None && statechange) {
3172
 
      EC_IP ecip;
3173
 
 
3174
 
      if (clo_execontext == EC_Some)
3175
 
         ecip = IP(VG_(get_IP)(tid), prevstate, tls);
3176
 
      else
3177
 
         ecip = EC(VG_(record_ExeContext)(tid), prevstate, tls);
3178
 
      setExeContext(a, ecip);
3179
 
   }
3180
 
}
3181
 
 
3182
 
static void hg_mem_write(Addr a, SizeT size, ThreadId tid)
3183
 
{
3184
 
   Addr     end;
3185
 
 
3186
 
   end = VG_ROUNDUP(a+size, 4);
3187
 
   a   = VG_ROUNDDN(a, 4);
3188
 
 
3189
 
   for ( ; a < end; a += 4)
3190
 
      hg_mem_write_word(a, tid);
3191
 
}
3192
 
 
3193
 
#undef DEBUG_STATE
3194
 
 
3195
 
VG_REGPARM(1) static void hg_mem_help_read_1(Addr a)
3196
 
{
3197
 
   hg_mem_read(a, 1, VG_(get_running_tid)());
3198
 
}
3199
 
 
3200
 
VG_REGPARM(1) static void hg_mem_help_read_2(Addr a)
3201
 
{
3202
 
   hg_mem_read(a, 2, VG_(get_running_tid)());
3203
 
}
3204
 
 
3205
 
VG_REGPARM(1) static void hg_mem_help_read_4(Addr a)
3206
 
{
3207
 
   hg_mem_read(a, 4, VG_(get_running_tid)());
3208
 
}
3209
 
 
3210
 
VG_REGPARM(2) static void hg_mem_help_read_N(Addr a, SizeT size)
3211
 
{
3212
 
   hg_mem_read(a, size, VG_(get_running_tid)());
3213
 
}
3214
 
 
3215
 
VG_REGPARM(2) static void hg_mem_help_write_1(Addr a, UInt val)
3216
 
{
3217
 
   if (*(UChar *)a != val)
3218
 
      hg_mem_write(a, 1, VG_(get_running_tid)());
3219
 
}
3220
 
VG_REGPARM(2) static void hg_mem_help_write_2(Addr a, UInt val)
3221
 
{
3222
 
   if (*(UShort *)a != val)
3223
 
      hg_mem_write(a, 2, VG_(get_running_tid)());
3224
 
}
3225
 
VG_REGPARM(2) static void hg_mem_help_write_4(Addr a, UInt val)
3226
 
{
3227
 
   if (*(UInt *)a != val)
3228
 
      hg_mem_write(a, 4, VG_(get_running_tid)());
3229
 
}
3230
 
VG_REGPARM(2) static void hg_mem_help_write_N(Addr a, SizeT size)
3231
 
{
3232
 
   hg_mem_write(a, size, VG_(get_running_tid)());
3233
 
}
3234
 
 
3235
 
static void hg_thread_create(ThreadId parent, ThreadId child)
3236
 
{
3237
 
   if (0)
3238
 
      VG_(printf)("CREATE: %u creating %u\n", parent, child);
3239
 
 
3240
 
   newTLS(child);
3241
 
   addPriorTLS(child, parent);
3242
 
 
3243
 
   newTLS(parent);
3244
 
}
3245
 
 
3246
 
static void hg_thread_join(ThreadId joiner, ThreadId joinee)
3247
 
{
3248
 
   if (0)
3249
 
      VG_(printf)("JOIN: %u joining on %u\n", joiner, joinee);
3250
 
 
3251
 
   newTLS(joiner);
3252
 
   addPriorTLS(joiner, joinee);
3253
 
 
3254
 
   clearTLS(joinee);
3255
 
}
3256
 
 
3257
 
static Int __BUS_HARDWARE_LOCK__;
3258
 
 
3259
 
static void bus_lock(void)
3260
 
{
3261
 
   ThreadId tid = VG_(get_running_tid)();
3262
 
   hg_pre_mutex_lock(tid, &__BUS_HARDWARE_LOCK__);
3263
 
   hg_post_mutex_lock(tid, &__BUS_HARDWARE_LOCK__);
3264
 
}
3265
 
 
3266
 
static void bus_unlock(void)
3267
 
{
3268
 
   ThreadId tid = VG_(get_running_tid)();
3269
 
   hg_post_mutex_unlock(tid, &__BUS_HARDWARE_LOCK__);
3270
 
}
3271
 
 
3272
 
/*--------------------------------------------------------------------*/
3273
 
/*--- Client requests                                              ---*/
3274
 
/*--------------------------------------------------------------------*/
3275
 
 
3276
 
static Bool hg_handle_client_request(ThreadId tid, UWord *args, UWord *ret)
3277
 
{
3278
 
   if (!VG_IS_TOOL_USERREQ('H','G',args[0]))
3279
 
      return False;
3280
 
 
3281
 
   switch(args[0]) {
3282
 
   case VG_USERREQ__HG_CLEAN_MEMORY:
3283
 
      set_address_range_state(args[1], args[2], Vge_VirginInit);
3284
 
      *ret = 0;                 /* meaningless */
3285
 
      break;
3286
 
 
3287
 
   case VG_USERREQ__HG_KNOWN_RACE:
3288
 
      set_address_range_state(args[1], args[2], Vge_Error);
3289
 
      *ret = 0;                 /* meaningless */
3290
 
      break;
3291
 
 
3292
 
   default:
3293
 
      return False;
3294
 
   }
3295
 
 
3296
 
   return True;
3297
 
}
3298
 
 
3299
 
 
3300
 
/*--------------------------------------------------------------------*/
3301
 
/*--- Setup and finalisation                                       ---*/
3302
 
/*--------------------------------------------------------------------*/
3303
 
 
3304
 
static Bool hg_process_cmd_line_option(Char* arg)
3305
 
{
3306
 
   if      (VG_CLO_STREQ(arg, "--show-last-access=no"))
3307
 
      clo_execontext = EC_None;
3308
 
   else if (VG_CLO_STREQ(arg, "--show-last-access=some"))
3309
 
      clo_execontext = EC_Some;
3310
 
   else if (VG_CLO_STREQ(arg, "--show-last-access=all"))
3311
 
      clo_execontext = EC_All;
3312
 
 
3313
 
   else VG_BOOL_CLO(arg, "--private-stacks", clo_priv_stacks)
 
8525
 
 
8526
/*----------------------------------------------------------------*/
 
8527
/*--- Setup                                                    ---*/
 
8528
/*----------------------------------------------------------------*/
 
8529
 
 
8530
static Bool hg_process_cmd_line_option ( Char* arg )
 
8531
{
 
8532
   if      (VG_CLO_STREQ(arg, "--happens-before=none"))
 
8533
      clo_happens_before = 0;
 
8534
   else if (VG_CLO_STREQ(arg, "--happens-before=threads"))
 
8535
      clo_happens_before = 1;
 
8536
   else if (VG_CLO_STREQ(arg, "--happens-before=all"))
 
8537
      clo_happens_before = 2;
 
8538
 
 
8539
   else if (VG_CLO_STREQ(arg, "--gen-vcg=no"))
 
8540
      clo_gen_vcg = 0;
 
8541
   else if (VG_CLO_STREQ(arg, "--gen-vcg=yes"))
 
8542
      clo_gen_vcg = 1;
 
8543
   else if (VG_CLO_STREQ(arg, "--gen-vcg=yes-w-vts"))
 
8544
      clo_gen_vcg = 2;
 
8545
 
 
8546
   else if (VG_CLO_STREQ(arg, "--cmp-race-err-addrs=no"))
 
8547
      clo_cmp_race_err_addrs = False;
 
8548
   else if (VG_CLO_STREQ(arg, "--cmp-race-err-addrs=yes"))
 
8549
      clo_cmp_race_err_addrs = True;
 
8550
 
 
8551
   else if (VG_CLO_STREQN(13, arg, "--trace-addr=")) {
 
8552
      clo_trace_addr = VG_(atoll16)(&arg[13]);
 
8553
      if (clo_trace_level == 0)
 
8554
         clo_trace_level = 1;
 
8555
   }
 
8556
   else VG_BNUM_CLO(arg, "--trace-level", clo_trace_level, 0, 2)
 
8557
 
 
8558
   /* "stuvwx" --> stuvwx (binary) */
 
8559
   else if (VG_CLO_STREQN(18, arg, "--hg-sanity-flags=")) {
 
8560
      Int j;
 
8561
      Char* opt = & arg[18];
 
8562
   
 
8563
      if (6 != VG_(strlen)(opt)) {
 
8564
         VG_(message)(Vg_UserMsg, 
 
8565
                      "--hg-sanity-flags argument must have 6 digits");
 
8566
         return False;
 
8567
      }
 
8568
      for (j = 0; j < 6; j++) {
 
8569
         if      ('0' == opt[j]) { /* do nothing */ }
 
8570
         else if ('1' == opt[j]) clo_sanity_flags |= (1 << (6-1-j));
 
8571
         else {
 
8572
            VG_(message)(Vg_UserMsg, "--hg-sanity-flags argument can "
 
8573
                                     "only contain 0s and 1s");
 
8574
            return False;
 
8575
         }
 
8576
      }
 
8577
      if (0) VG_(printf)("XXX sanity flags: 0x%x\n", clo_sanity_flags);
 
8578
   }
3314
8579
 
3315
8580
   else 
3316
8581
      return VG_(replacement_malloc_process_cmd_line_option)(arg);
3318
8583
   return True;
3319
8584
}
3320
8585
 
3321
 
static void hg_print_usage(void)
 
8586
static void hg_print_usage ( void )
3322
8587
{
3323
8588
   VG_(printf)(
3324
 
"    --private-stacks=yes|no   assume thread stacks are used privately [no]\n"
3325
 
"    --show-last-access=no|some|all\n"
3326
 
"                           show location of last word access on error [no]\n"
 
8589
"    --happens-before=none|threads|all   [all] consider no events, thread\n"
 
8590
"      create/join, create/join/cvsignal/cvwait/semwait/post as sync points\n"
 
8591
"    --trace-addr=0xXXYYZZ     show all state changes for address 0xXXYYZZ\n"
 
8592
"    --trace-level=0|1|2       verbosity level of --trace-addr [1]\n"
3327
8593
   );
3328
8594
   VG_(replacement_malloc_print_usage)();
3329
8595
}
3330
8596
 
3331
 
static void hg_print_debug_usage(void)
 
8597
static void hg_print_debug_usage ( void )
3332
8598
{
3333
8599
   VG_(replacement_malloc_print_debug_usage)();
3334
 
}
3335
 
 
3336
 
static void hg_post_clo_init(void)
3337
 
{
3338
 
   void (*stack_tracker)(Addr a, SizeT len);
3339
 
   
3340
 
   if (clo_execontext) {
3341
 
      execontext_map = VG_(malloc)(sizeof(ExeContextMap *) * 65536);
3342
 
      VG_(memset)(execontext_map, 0, sizeof(ExeContextMap *) * 65536);
3343
 
   }
3344
 
 
3345
 
   if (clo_priv_stacks)
3346
 
      stack_tracker = & hg_new_mem_stack_private;
3347
 
   else
3348
 
      stack_tracker = & hg_new_mem_stack;
3349
 
 
3350
 
   VG_(track_new_mem_stack)        (stack_tracker);
3351
 
   VG_(track_new_mem_stack_signal) (stack_tracker);
3352
 
}
3353
 
 
3354
 
 
3355
 
static void hg_fini(Int exitcode)
3356
 
{
3357
 
   if (DEBUG_LOCK_TABLE) {
3358
 
      pp_all_LockSets();
3359
 
      pp_all_mutexes();
3360
 
   }
3361
 
 
3362
 
   if (LOCKSET_SANITY)
3363
 
      sanity_check_locksets("hg_fini");
3364
 
 
3365
 
   if (VG_(clo_verbosity) > 0)
3366
 
      VG_(message)(Vg_UserMsg, "%u possible data races found; %u lock order problems",
3367
 
                   n_hg_warnings, n_lockorder_warnings);
3368
 
 
3369
 
   if (0)
3370
 
      VG_(printf)("stk_ld:%u+stk_st:%u = %u  nonstk_ld:%u+nonstk_st:%u = %u  %u%%\n",
3371
 
                  stk_ld, stk_st, stk_ld + stk_st,
3372
 
                  nonstk_ld, nonstk_st, nonstk_ld + nonstk_st,
3373
 
                  ((stk_ld+stk_st)*100) / (stk_ld + stk_st + nonstk_ld + nonstk_st));
3374
 
}
3375
 
 
3376
 
static void hg_pre_clo_init(void)
3377
 
{
3378
 
   Int i;
3379
 
   LockSet *empty;
3380
 
 
 
8600
   VG_(printf)("    --gen-vcg=no|yes|yes-w-vts   show happens-before graph "
 
8601
               "in .vcg format [no]\n");
 
8602
   VG_(printf)("    --cmp-race-err-addrs=no|yes  are data addresses in "
 
8603
               "race errors significant? [no]\n");
 
8604
   VG_(printf)("    --hg-sanity-flags=<XXXXXX> sanity check "
 
8605
               "  at events (X = 0|1) [000000]\n");
 
8606
   VG_(printf)("    --hg-sanity-flags values:\n");
 
8607
   VG_(printf)("       100000   crosscheck happens-before-graph searches\n");
 
8608
   VG_(printf)("       010000   after changes to "
 
8609
               "lock-order-acquisition-graph\n");
 
8610
   VG_(printf)("       001000   at memory accesses (NB: not currently used)\n");
 
8611
   VG_(printf)("       000100   at mem permission setting for "
 
8612
               "ranges >= %d bytes\n", SCE_BIGRANGE_T);
 
8613
   VG_(printf)("       000010   at lock/unlock events\n");
 
8614
   VG_(printf)("       000001   at thread create/join events\n");
 
8615
}
 
8616
 
 
8617
static void hg_post_clo_init ( void )
 
8618
{
 
8619
}
 
8620
 
 
8621
static void hg_fini ( Int exitcode )
 
8622
{
 
8623
   if (SHOW_DATA_STRUCTURES)
 
8624
      pp_everything( PP_ALL, "SK_(fini)" );
 
8625
   if (clo_sanity_flags)
 
8626
      all__sanity_check("SK_(fini)");
 
8627
 
 
8628
   if (clo_gen_vcg > 0)
 
8629
      segments__generate_vcg();
 
8630
 
 
8631
   if (VG_(clo_verbosity) >= 2) {
 
8632
 
 
8633
      if (1) {
 
8634
         VG_(printf)("\n");
 
8635
         HG_(ppWSUstats)( univ_tsets, "univ_tsets" );
 
8636
         VG_(printf)("\n");
 
8637
         HG_(ppWSUstats)( univ_lsets, "univ_lsets" );
 
8638
         VG_(printf)("\n");
 
8639
         HG_(ppWSUstats)( univ_laog,  "univ_laog" );
 
8640
      }
 
8641
 
 
8642
      VG_(printf)("\n");
 
8643
      VG_(printf)(" hbefore: %,10lu queries\n",        stats__hbefore_queries);
 
8644
      VG_(printf)(" hbefore: %,10lu cache 0 hits\n",   stats__hbefore_cache0s);
 
8645
      VG_(printf)(" hbefore: %,10lu cache > 0 hits\n", stats__hbefore_cacheNs);
 
8646
      VG_(printf)(" hbefore: %,10lu graph searches\n", stats__hbefore_gsearches);
 
8647
      VG_(printf)(" hbefore: %,10lu   of which slow\n",
 
8648
                  stats__hbefore_gsearches - stats__hbefore_gsearchFs);
 
8649
      VG_(printf)(" hbefore: %,10lu stack high water mark\n",
 
8650
                  stats__hbefore_stk_hwm);
 
8651
      VG_(printf)(" hbefore: %,10lu cache invals\n",   stats__hbefore_invals);
 
8652
      VG_(printf)(" hbefore: %,10lu probes\n",         stats__hbefore_probes);
 
8653
 
 
8654
      VG_(printf)("\n");
 
8655
      VG_(printf)("        segments: %,8lu Segment objects allocated\n", 
 
8656
                  stats__mk_Segment);
 
8657
      VG_(printf)("        locksets: %,8d unique lock sets\n",
 
8658
                  (Int)HG_(cardinalityWSU)( univ_lsets ));
 
8659
      VG_(printf)("      threadsets: %,8d unique thread sets\n",
 
8660
                  (Int)HG_(cardinalityWSU)( univ_tsets ));
 
8661
      VG_(printf)("       univ_laog: %,8d unique lock sets\n",
 
8662
                  (Int)HG_(cardinalityWSU)( univ_laog ));
 
8663
 
 
8664
      VG_(printf)("L(ast)L(ock) map: %,8lu inserts (%d map size)\n", 
 
8665
                  stats__ga_LL_adds,
 
8666
                  (Int)(ga_to_lastlock ? HG_(sizeFM)( ga_to_lastlock ) : 0) );
 
8667
 
 
8668
      VG_(printf)("  LockN-to-P map: %,8lu queries (%d map size)\n", 
 
8669
                  stats__ga_LockN_to_P_queries,
 
8670
                  (Int)(yaWFM ? HG_(sizeFM)( yaWFM ) : 0) );
 
8671
 
 
8672
      VG_(printf)("string table map: %,8lu queries (%d map size)\n", 
 
8673
                  stats__string_table_queries,
 
8674
                  (Int)(string_table ? HG_(sizeFM)( string_table ) : 0) );
 
8675
      VG_(printf)("            LAOG: %,8d map size\n", 
 
8676
                  (Int)(laog ? HG_(sizeFM)( laog ) : 0));
 
8677
      VG_(printf)(" LAOG exposition: %,8d map size\n", 
 
8678
                  (Int)(laog_exposition ? HG_(sizeFM)( laog_exposition ) : 0));
 
8679
      VG_(printf)("           locks: %,8lu acquires, "
 
8680
                  "%,lu releases\n",
 
8681
                  stats__lockN_acquires,
 
8682
                  stats__lockN_releases
 
8683
                 );
 
8684
      VG_(printf)("   sanity checks: %,8lu\n", stats__sanity_checks);
 
8685
 
 
8686
      VG_(printf)("\n");
 
8687
      VG_(printf)("     msm: %,12lu %,12lu rd/wr_Excl_nochange\n",
 
8688
                  stats__msm_read_Excl_nochange, stats__msm_write_Excl_nochange);
 
8689
      VG_(printf)("     msm: %,12lu %,12lu rd/wr_Excl_transfer\n",
 
8690
                  stats__msm_read_Excl_transfer, stats__msm_write_Excl_transfer);
 
8691
      VG_(printf)("     msm: %,12lu %,12lu rd/wr_Excl_to_ShR/ShM\n",
 
8692
                  stats__msm_read_Excl_to_ShR,   stats__msm_write_Excl_to_ShM);
 
8693
      VG_(printf)("     msm: %,12lu %,12lu rd/wr_ShR_to_ShR/ShM\n",
 
8694
                  stats__msm_read_ShR_to_ShR,    stats__msm_write_ShR_to_ShM);
 
8695
      VG_(printf)("     msm: %,12lu %,12lu rd/wr_ShM_to_ShM\n",
 
8696
                  stats__msm_read_ShM_to_ShM,    stats__msm_write_ShM_to_ShM);
 
8697
      VG_(printf)("     msm: %,12lu %,12lu rd/wr_New_to_Excl\n",
 
8698
                  stats__msm_read_New_to_Excl,   stats__msm_write_New_to_Excl);
 
8699
      VG_(printf)("     msm: %,12lu %,12lu rd/wr_NoAccess\n",
 
8700
                  stats__msm_read_NoAccess,      stats__msm_write_NoAccess);
 
8701
 
 
8702
      VG_(printf)("\n");
 
8703
      VG_(printf)(" secmaps: %,10lu allocd (%,12lu g-a-range)\n",
 
8704
                  stats__secmaps_allocd,
 
8705
                  stats__secmap_ga_space_covered);
 
8706
      VG_(printf)("  linesZ: %,10lu allocd (%,12lu bytes occupied)\n",
 
8707
                  stats__secmap_linesZ_allocd,
 
8708
                  stats__secmap_linesZ_bytes);
 
8709
      VG_(printf)("  linesF: %,10lu allocd (%,12lu bytes occupied)\n",
 
8710
                  stats__secmap_linesF_allocd,
 
8711
                  stats__secmap_linesF_bytes);
 
8712
      VG_(printf)(" secmaps: %,10lu iterator steppings\n",
 
8713
                  stats__secmap_iterator_steppings);
 
8714
 
 
8715
      VG_(printf)("\n");
 
8716
      VG_(printf)("   cache: %,lu totrefs (%,lu misses)\n",
 
8717
                  stats__cache_totrefs, stats__cache_totmisses );
 
8718
      VG_(printf)("   cache: %,12lu Z-fetch, %,12lu F-fetch\n",
 
8719
                  stats__cache_Z_fetches, stats__cache_F_fetches );
 
8720
      VG_(printf)("   cache: %,12lu Z-wback, %,12lu F-wback\n",
 
8721
                  stats__cache_Z_wbacks, stats__cache_F_wbacks );
 
8722
      VG_(printf)("   cache: %,12lu invals,  %,12lu flushes\n",
 
8723
                  stats__cache_invals, stats__cache_flushes );
 
8724
 
 
8725
      VG_(printf)("\n");
 
8726
      VG_(printf)("   cline: %,10lu normalises\n",
 
8727
                  stats__cline_normalises );
 
8728
      VG_(printf)("   cline:  reads 8/4/2/1: %,12lu %,12lu %,12lu %,12lu\n",
 
8729
                  stats__cline_read64s,
 
8730
                  stats__cline_read32s,
 
8731
                  stats__cline_read16s,
 
8732
                  stats__cline_read8s );
 
8733
      VG_(printf)("   cline: writes 8/4/2/1: %,12lu %,12lu %,12lu %,12lu\n",
 
8734
                  stats__cline_write64s,
 
8735
                  stats__cline_write32s,
 
8736
                  stats__cline_write16s,
 
8737
                  stats__cline_write8s );
 
8738
      VG_(printf)("   cline:   sets 8/4/2/1: %,12lu %,12lu %,12lu %,12lu\n",
 
8739
                  stats__cline_set64s,
 
8740
                  stats__cline_set32s,
 
8741
                  stats__cline_set16s,
 
8742
                  stats__cline_set8s );
 
8743
      VG_(printf)("   cline: get1s %,lu, copy1s %,lu\n",
 
8744
                  stats__cline_get8s, stats__cline_copy8s );
 
8745
      VG_(printf)("   cline:    splits: 8to4 %,12lu    4to2 %,12lu    2to1 %,12lu\n",
 
8746
                 stats__cline_64to32splits,
 
8747
                 stats__cline_32to16splits,
 
8748
                 stats__cline_16to8splits );
 
8749
      VG_(printf)("   cline: pulldowns: 8to4 %,12lu    4to2 %,12lu    2to1 %,12lu\n",
 
8750
                 stats__cline_64to32pulldown,
 
8751
                 stats__cline_32to16pulldown,
 
8752
                 stats__cline_16to8pulldown );
 
8753
 
 
8754
      VG_(printf)("\n");
 
8755
   }
 
8756
}
 
8757
 
 
8758
static void hg_pre_clo_init ( void )
 
8759
{
3381
8760
   VG_(details_name)            ("Helgrind");
3382
8761
   VG_(details_version)         (NULL);
3383
 
   VG_(details_description)     ("a data race detector");
 
8762
   VG_(details_description)     ("a thread error detector");
3384
8763
   VG_(details_copyright_author)(
3385
 
      "Copyright (C) 2002-2006, and GNU GPL'd, by Nicholas Nethercote et al.");
 
8764
      "Copyright (C) 2007-2007, and GNU GPL'd, by OpenWorks LLP et al.");
3386
8765
   VG_(details_bug_reports_to)  (VG_BUGS_TO);
3387
 
   VG_(details_avg_translation_sizeB) ( 115 );
 
8766
   VG_(details_avg_translation_sizeB) ( 200 );
3388
8767
 
3389
8768
   VG_(basic_tool_funcs)          (hg_post_clo_init,
3390
8769
                                   hg_instrument,
3391
8770
                                   hg_fini);
3392
8771
 
3393
 
   VG_(printf)(
3394
 
"\n"
3395
 
"Helgrind is currently not working, because:\n"
3396
 
" (a) it is not yet ready to handle the Vex IR and the use with 64-bit\n"
3397
 
"     platforms introduced in Valgrind 3.0.0\n"
3398
 
" (b) we need to get thread operation tracking working again after\n"
3399
 
"     the changes added in Valgrind 2.4.0\n"
3400
 
" If you want to use Helgrind, you'll have to use Valgrind 2.2.0, which is\n"
3401
 
" the most recent Valgrind release that contains a working Helgrind.\n"
3402
 
"\n"
3403
 
"Sorry for the inconvenience.  Let us know if this is a problem for you.\n");
3404
 
   VG_(exit)(1);
3405
 
 
3406
8772
   VG_(needs_core_errors)         ();
3407
8773
   VG_(needs_tool_errors)         (hg_eq_Error,
3408
8774
                                   hg_pp_Error,
 
8775
                                   False,/*show TIDs for errors*/
3409
8776
                                   hg_update_extra,
3410
8777
                                   hg_recognised_suppression,
3411
8778
                                   hg_read_extra_suppression_info,
3412
8779
                                   hg_error_matches_suppression,
3413
8780
                                   hg_get_error_name,
3414
8781
                                   hg_print_extra_suppression_info);
3415
 
   VG_(needs_data_syms)           ();
3416
 
   VG_(needs_client_requests)     (hg_handle_client_request);
3417
 
   VG_(needs_sanity_checks)       (hg_cheap_sanity_check,
3418
 
                                   hg_expensive_sanity_check);
 
8782
 
3419
8783
   VG_(needs_command_line_options)(hg_process_cmd_line_option,
3420
8784
                                   hg_print_usage,
3421
8785
                                   hg_print_debug_usage);
3422
 
 
3423
 
   VG_(needs_malloc_replacement)  (hg_malloc,
3424
 
                                   hg___builtin_new,
3425
 
                                   hg___builtin_vec_new,
3426
 
                                   hg_memalign,
3427
 
                                   hg_calloc,
3428
 
                                   hg_free,
3429
 
                                   hg___builtin_delete,
3430
 
                                   hg___builtin_vec_delete,
3431
 
                                   hg_realloc,
3432
 
                                   8 );
3433
 
 
3434
 
   VG_(track_new_mem_startup)      (& hg_new_mem_startup);
3435
 
 
3436
 
   /* stack ones not decided until hg_post_clo_init() */
3437
 
 
3438
 
   VG_(track_new_mem_brk)         (& make_writable);
3439
 
   VG_(track_new_mem_mmap)        (& hg_new_mem_startup);
3440
 
 
3441
 
   VG_(track_change_mem_mprotect) (& hg_set_perms);
3442
 
 
 
8786
   VG_(needs_client_requests)     (hg_handle_client_request);
 
8787
 
 
8788
   // FIXME?
 
8789
   //VG_(needs_sanity_checks)       (hg_cheap_sanity_check,
 
8790
   //                                hg_expensive_sanity_check);
 
8791
 
 
8792
   VG_(needs_malloc_replacement)  (hg_cli__malloc,
 
8793
                                   hg_cli____builtin_new,
 
8794
                                   hg_cli____builtin_vec_new,
 
8795
                                   hg_cli__memalign,
 
8796
                                   hg_cli__calloc,
 
8797
                                   hg_cli__free,
 
8798
                                   hg_cli____builtin_delete,
 
8799
                                   hg_cli____builtin_vec_delete,
 
8800
                                   hg_cli__realloc,
 
8801
                                   HG_CLI__MALLOC_REDZONE_SZB );
 
8802
 
 
8803
   VG_(needs_data_syms)();
 
8804
 
 
8805
   //VG_(needs_xml_output)          ();
 
8806
 
 
8807
   VG_(track_new_mem_startup)     ( evh__new_mem_w_perms );
 
8808
   VG_(track_new_mem_stack_signal)( evh__die_mem );
 
8809
   VG_(track_new_mem_brk)         ( evh__new_mem );
 
8810
   VG_(track_new_mem_mmap)        ( evh__new_mem_w_perms );
 
8811
   VG_(track_new_mem_stack)       ( evh__new_mem );
 
8812
 
 
8813
   // FIXME: surely this isn't thread-aware
 
8814
   VG_(track_copy_mem_remap)      ( shadow_mem_copy_range );
 
8815
 
 
8816
   VG_(track_change_mem_mprotect) ( evh__set_perms );
 
8817
 
 
8818
   VG_(track_die_mem_stack_signal)( evh__die_mem );
 
8819
   VG_(track_die_mem_brk)         ( evh__die_mem );
 
8820
   VG_(track_die_mem_munmap)      ( evh__die_mem );
 
8821
   VG_(track_die_mem_stack)       ( evh__die_mem );
 
8822
 
 
8823
   // FIXME: what is this for?
3443
8824
   VG_(track_ban_mem_stack)       (NULL);
3444
8825
 
3445
 
   VG_(track_die_mem_stack)       (NULL);
3446
 
   VG_(track_die_mem_stack_signal)(NULL);
3447
 
   VG_(track_die_mem_brk)         (NULL);
3448
 
   VG_(track_die_mem_munmap)      (NULL);
3449
 
 
3450
 
   VG_(track_pre_mem_read)        (& hg_pre_mem_read);
3451
 
   VG_(track_pre_mem_read_asciiz) (& hg_pre_mem_read_asciiz);
3452
 
   VG_(track_pre_mem_write)       (& hg_pre_mem_write);
 
8826
   VG_(track_pre_mem_read)        ( evh__pre_mem_read );
 
8827
   VG_(track_pre_mem_read_asciiz) ( evh__pre_mem_read_asciiz );
 
8828
   VG_(track_pre_mem_write)       ( evh__pre_mem_write );
3453
8829
   VG_(track_post_mem_write)      (NULL);
3454
8830
 
3455
 
   VG_(track_post_thread_create)  (& hg_thread_create);
3456
 
   VG_(track_post_thread_join)    (& hg_thread_join);
3457
 
 
3458
 
   VG_(track_pre_mutex_lock)      (& hg_pre_mutex_lock);
3459
 
   VG_(track_post_mutex_lock)     (& hg_post_mutex_lock);
3460
 
   VG_(track_post_mutex_unlock)   (& hg_post_mutex_unlock);
3461
 
 
3462
 
   for (i = 0; i < LOCKSET_HASH_SZ; i++)
3463
 
      lockset_hash[i] = NULL;
3464
 
 
3465
 
   empty = alloc_LockSet(0);
3466
 
   insert_LockSet(empty);
3467
 
   emptyset = empty;
3468
 
 
3469
 
   /* Init lock table and thread segments */
3470
 
   for (i = 0; i < VG_N_THREADS; i++) {
3471
 
      thread_locks[i] = empty;
3472
 
 
3473
 
      newTLS(i);
3474
 
   }
3475
 
 
3476
 
   init_shadow_memory();
3477
 
   hg_malloc_list = VG_(HT_construct)( 80021 );    // prime, big
 
8831
   /////////////////
 
8832
 
 
8833
   VG_(track_pre_thread_ll_create)( evh__pre_thread_ll_create );
 
8834
   VG_(track_pre_thread_ll_exit)  ( evh__pre_thread_ll_exit );
 
8835
 
 
8836
   VG_(track_start_client_code)( evh__start_client_code );
 
8837
   VG_(track_stop_client_code)( evh__stop_client_code );
 
8838
 
 
8839
   initialise_data_structures();
 
8840
 
 
8841
   /* Ensure that requirements for "dodgy C-as-C++ style inheritance"
 
8842
      as described in comments at the top of pub_tool_hashtable.h, are
 
8843
      met.  Blargh. */
 
8844
   tl_assert( sizeof(void*) == sizeof(struct _MallocMeta*) );
 
8845
   tl_assert( sizeof(UWord) == sizeof(Addr) );
 
8846
   hg_mallocmeta_table
 
8847
      = VG_(HT_construct)( "hg_malloc_metadata_table" );
 
8848
 
 
8849
   /* a SecMap must contain an integral number of CacheLines */
 
8850
   tl_assert(0 == (N_SECMAP_ARANGE % N_LINE_ARANGE));
 
8851
   /* also ... a CacheLine holds an integral number of trees */
 
8852
   tl_assert(0 == (N_LINE_ARANGE % 8));
3478
8853
}
3479
8854
 
3480
8855
VG_DETERMINE_INTERFACE_VERSION(hg_pre_clo_init)