blob: 94b52855daa0a6a42165c8b1a4727a0b26bbb3c8 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
bart86562bd2009-02-16 19:43:56 +00002 This file is part of drd, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00003
sewardjb3a1e4b2015-08-21 11:32:26 +00004 Copyright (C) 2006-2015 Bart Van Assche <bvanassche@acm.org>.
sewardjaf44c822007-11-25 14:01:38 +00005
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307, USA.
20
21 The GNU General Public License is contained in the file COPYING.
22*/
23
24
bart33e56c92008-03-24 06:41:30 +000025#ifndef __DRD_BITMAP_H
26#define __DRD_BITMAP_H
sewardjaf44c822007-11-25 14:01:38 +000027
28
bart7b706b32009-05-10 06:55:39 +000029#include "pub_drd_bitmap.h"
bart82a0c5d2009-02-14 14:49:23 +000030#include "pub_tool_basics.h"
sewardjaf44c822007-11-25 14:01:38 +000031#include "pub_tool_oset.h"
bartd59bb0f2008-06-08 08:08:31 +000032#include "pub_tool_libcbase.h"
bart67cb4fb2010-09-02 14:43:50 +000033#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
34#include "pub_tool_libcassert.h"
35#endif
sewardjaf44c822007-11-25 14:01:38 +000036
37
bart7b706b32009-05-10 06:55:39 +000038/* Bitmap representation. A bitmap is a data structure in which two bits are
39 * reserved per 32 bit address: one bit that indicates that the data at the
40 * specified address has been read, and one bit that indicates that the data
41 * has been written to.
42 */
43
44/* Client addresses are split into bitfields as follows:
45 * ------------------------------------------------------
bart31b983d2010-02-21 14:52:59 +000046 * | Address MSB | Address LSB | Ignored bits |
bart7b706b32009-05-10 06:55:39 +000047 * ------------------------------------------------------
48 * | Address MSB | UWord MSB | UWord LSB | Ignored bits |
49 * ------------------------------------------------------
50 */
sewardjaf44c822007-11-25 14:01:38 +000051
52
sewardjaf44c822007-11-25 14:01:38 +000053
bart7b706b32009-05-10 06:55:39 +000054/* Address MSB / LSB split. */
sewardjaf44c822007-11-25 14:01:38 +000055
sewardjaf44c822007-11-25 14:01:38 +000056
bart7b706b32009-05-10 06:55:39 +000057/** Number of least significant address bits that are ignored. */
58#define ADDR_IGNORED_BITS 0
59#define ADDR_IGNORED_MASK ((1U << ADDR_IGNORED_BITS) - 1U)
60#define ADDR_GRANULARITY (1U << ADDR_IGNORED_BITS)
sewardjaf44c822007-11-25 14:01:38 +000061
bart8f822af2009-06-08 18:20:42 +000062/**
63 * Round argument a up to a multiple of (1 << ADDR_GRANULARITY), and next
64 * shift it right ADDR_GRANULARITY bits. The expression below is optimized
65 * for the case where a is a constant.
bart7b706b32009-05-10 06:55:39 +000066 */
67#define SCALED_SIZE(a) \
68 (((((a) - 1U) | ADDR_IGNORED_MASK) + 1U) >> ADDR_IGNORED_BITS)
sewardjaf44c822007-11-25 14:01:38 +000069
bart8f822af2009-06-08 18:20:42 +000070/**
71 * Number of bits assigned to the least significant component of an address.
bart7b706b32009-05-10 06:55:39 +000072 */
73#define ADDR_LSB_BITS 12
sewardjaf44c822007-11-25 14:01:38 +000074
bart8f822af2009-06-08 18:20:42 +000075/**
76 * Mask that has to be applied to an address of type Addr in order to
77 * compute the least significant part of an address split, after having
78 * shifted the address bits ADDR_GRANULARITY to the right.
bart7b706b32009-05-10 06:55:39 +000079 */
80#define ADDR_LSB_MASK (((UWord)1 << ADDR_LSB_BITS) - 1U)
81
82/** Compute least significant bits of an address of type Addr. */
83static __inline__
84UWord address_lsb(const Addr a)
85{ return (a >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK; }
86
87/**
88 * Compute the first address for which address_lsb() is equal to
89 * address_lsb(a).
90 */
91static __inline__
92Addr first_address_with_same_lsb(const Addr a)
93{
94 return ((a | ADDR_IGNORED_MASK) ^ ADDR_IGNORED_MASK);
95}
96
97/**
98 * Compute the first address for which address_lsb() is greater than
99 * address_lsb(a).
100 */
101static __inline__
102Addr first_address_with_higher_lsb(const Addr a)
103{
104 return ((a | ADDR_IGNORED_MASK) + 1U);
105}
106
107/** Compute most significant bits of an address of type Addr. */
108static __inline__
109UWord address_msb(const Addr a)
110{ return a >> (ADDR_LSB_BITS + ADDR_IGNORED_BITS); }
111
112static __inline__
113Addr first_address_with_higher_msb(const Addr a)
114{
115 return ((a | ((ADDR_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
116 + 1U);
117}
118
bart8f822af2009-06-08 18:20:42 +0000119/**
120 * Convert LSB and MSB back into an address.
bart7b706b32009-05-10 06:55:39 +0000121 *
bart8f822af2009-06-08 18:20:42 +0000122 * @note It is assumed that sizeof(Addr) == sizeof(UWord).
bart7b706b32009-05-10 06:55:39 +0000123 */
124static __inline__
125Addr make_address(const UWord a1, const UWord a0)
126{
127 return ((a1 << (ADDR_LSB_BITS + ADDR_IGNORED_BITS))
128 | (a0 << ADDR_IGNORED_BITS));
129}
130
131
132
133
134
bart8f822af2009-06-08 18:20:42 +0000135/** Number of bits that fit in a variable of type UWord. */
bart7b706b32009-05-10 06:55:39 +0000136#define BITS_PER_UWORD (8U * sizeof(UWord))
137
bart8f822af2009-06-08 18:20:42 +0000138/** Log2 of BITS_PER_UWORD. */
sewardj5db15402012-06-07 09:13:21 +0000139#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) \
140 || defined(VGA_mips32)
sewardjaf44c822007-11-25 14:01:38 +0000141#define BITS_PER_BITS_PER_UWORD 5
carllcae0cc22014-08-07 23:17:29 +0000142#elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
sewardj112711a2015-04-10 12:30:09 +0000143 || defined(VGA_s390x) || defined(VGA_mips64) || defined(VGA_arm64) \
144 || defined(VGA_tilegx)
sewardjaf44c822007-11-25 14:01:38 +0000145#define BITS_PER_BITS_PER_UWORD 6
146#else
147#error Unknown platform.
148#endif
149
bart8f822af2009-06-08 18:20:42 +0000150/** Number of UWord's needed to store one bit per address LSB. */
bart7b706b32009-05-10 06:55:39 +0000151#define BITMAP1_UWORD_COUNT (1U << (ADDR_LSB_BITS - BITS_PER_BITS_PER_UWORD))
sewardjaf44c822007-11-25 14:01:38 +0000152
bart8f822af2009-06-08 18:20:42 +0000153/**
154 * Mask that has to be applied to an (Addr >> ADDR_IGNORED_BITS) expression
155 * in order to compute the least significant part of an UWord.
bart7b706b32009-05-10 06:55:39 +0000156 */
157#define UWORD_LSB_MASK (((UWord)1 << BITS_PER_BITS_PER_UWORD) - 1)
sewardjaf44c822007-11-25 14:01:38 +0000158
bart8f822af2009-06-08 18:20:42 +0000159/**
160 * Compute index into bm0[] array.
bart7b706b32009-05-10 06:55:39 +0000161 *
bart8f822af2009-06-08 18:20:42 +0000162 * @param a Address shifted right ADDR_IGNORED_BITS bits.
bart7b706b32009-05-10 06:55:39 +0000163 */
164static __inline__
165UWord uword_msb(const UWord a)
166{
167#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
168 tl_assert(a < (1U << ADDR_LSB_BITS));
169#endif
170 return a >> BITS_PER_BITS_PER_UWORD;
171}
sewardjaf44c822007-11-25 14:01:38 +0000172
bart8f822af2009-06-08 18:20:42 +0000173/**
174 * Return the least significant bits.
bart7b706b32009-05-10 06:55:39 +0000175 *
bart8f822af2009-06-08 18:20:42 +0000176 * @param a Address shifted right ADDR_IGNORED_BITS bits.
bart7b706b32009-05-10 06:55:39 +0000177 */
178static __inline__
179UWord uword_lsb(const UWord a)
180{
181#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
182 tl_assert(a < (1U << ADDR_LSB_BITS));
183#endif
184 return a & UWORD_LSB_MASK;
185}
186
bart8f822af2009-06-08 18:20:42 +0000187/**
188 * Compute the highest address lower than a for which
189 * uword_lsb(address_lsb(a)) == 0.
bart7b706b32009-05-10 06:55:39 +0000190 *
bart8f822af2009-06-08 18:20:42 +0000191 * @param a Address.
bart7b706b32009-05-10 06:55:39 +0000192 */
193static __inline__
194Addr first_address_with_same_uword_lsb(const Addr a)
195{
196 return (a & (~UWORD_LSB_MASK << ADDR_IGNORED_BITS));
197}
198
199/**
200 * First address that will go in the UWord past the one 'a' goes in.
201 *
202 * @param a Address.
203 */
204static __inline__
205Addr first_address_with_higher_uword_msb(const Addr a)
206{
207 return ((a | ((UWORD_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
208 + 1);
209}
210
sewardjaf44c822007-11-25 14:01:38 +0000211
212
bart33e56c92008-03-24 06:41:30 +0000213/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +0000214
215static ULong s_bitmap2_creation_count;
216
217
bart0008f5b2008-03-22 17:07:39 +0000218
219/*********************************************************************/
220/* Functions for manipulating a struct bitmap1. */
221/*********************************************************************/
222
223
bart7b706b32009-05-10 06:55:39 +0000224/* Lowest level, corresponding to the lowest ADDR_LSB_BITS of an address. */
sewardjaf44c822007-11-25 14:01:38 +0000225struct bitmap1
226{
bartbedfd232009-03-26 19:07:15 +0000227 UWord bm0_r[BITMAP1_UWORD_COUNT];
228 UWord bm0_w[BITMAP1_UWORD_COUNT];
sewardjaf44c822007-11-25 14:01:38 +0000229};
230
bart7b706b32009-05-10 06:55:39 +0000231static __inline__ UWord bm0_mask(const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000232{
bart3c9989f2008-06-11 19:17:01 +0000233#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000234 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000235#endif
bart7b706b32009-05-10 06:55:39 +0000236 return ((UWord)1 << uword_lsb(a));
barta79df6e2008-03-14 17:07:51 +0000237}
238
bart7b706b32009-05-10 06:55:39 +0000239/** Set the bit corresponding to address a in bitmap bm0. */
240static __inline__ void bm0_set(UWord* bm0, const UWord a)
241{
242#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
243 tl_assert(address_msb(make_address(0, a)) == 0);
244#endif
245 bm0[uword_msb(a)] |= (UWord)1 << uword_lsb(a);
246}
247
248/**
249 * Set the bits corresponding to all of the addresses in range
250 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
251 * in bitmap bm0.
252 */
bartf8bc71d2008-03-15 11:42:34 +0000253static __inline__ void bm0_set_range(UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000254 const UWord a, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000255{
bart8b4b2ee2008-06-11 13:17:56 +0000256#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000257 tl_assert(size > 0);
bart7b706b32009-05-10 06:55:39 +0000258 tl_assert(address_msb(make_address(0, a)) == 0);
259 tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
260 tl_assert(uword_msb(a) == uword_msb(a + size - 1));
barta79df6e2008-03-14 17:07:51 +0000261#endif
bart7b706b32009-05-10 06:55:39 +0000262 bm0[uword_msb(a)]
263 |= (((UWord)1 << size) - 1) << uword_lsb(a);
sewardjaf44c822007-11-25 14:01:38 +0000264}
265
bart7b706b32009-05-10 06:55:39 +0000266/** Clear the bit corresponding to address a in bitmap bm0. */
267static __inline__ void bm0_clear(UWord* bm0, const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000268{
bart3c9989f2008-06-11 19:17:01 +0000269#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000270 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000271#endif
bart7b706b32009-05-10 06:55:39 +0000272 bm0[uword_msb(a)] &= ~((UWord)1 << uword_lsb(a));
sewardjaf44c822007-11-25 14:01:38 +0000273}
274
bart7b706b32009-05-10 06:55:39 +0000275/**
276 * Clear all of the addresses in range
277 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
278 * in bitmap bm0.
279 */
bart5955f332008-03-25 17:19:20 +0000280static __inline__ void bm0_clear_range(UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000281 const UWord a, const SizeT size)
bart5955f332008-03-25 17:19:20 +0000282{
bart8b4b2ee2008-06-11 13:17:56 +0000283#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000284 tl_assert(address_msb(make_address(0, a)) == 0);
285 tl_assert(size == 0 || address_msb(make_address(0, a + size - 1)) == 0);
286 tl_assert(size == 0 || uword_msb(a) == uword_msb(a + size - 1));
bart5955f332008-03-25 17:19:20 +0000287#endif
bart8c046732009-04-25 06:52:01 +0000288 /*
bart31b983d2010-02-21 14:52:59 +0000289 * Note: although the expression below yields a correct result even if
bart8c046732009-04-25 06:52:01 +0000290 * size == 0, do not touch bm0[] if size == 0 because this might otherwise
291 * cause an access of memory just past the end of the bm0[] array.
292 */
293 if (size > 0)
294 {
bart7b706b32009-05-10 06:55:39 +0000295 bm0[uword_msb(a)]
296 &= ~((((UWord)1 << size) - 1) << uword_lsb(a));
bart8c046732009-04-25 06:52:01 +0000297 }
bart5955f332008-03-25 17:19:20 +0000298}
299
bart7b706b32009-05-10 06:55:39 +0000300/** Test whether the bit corresponding to address a is set in bitmap bm0. */
301static __inline__ UWord bm0_is_set(const UWord* bm0, const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000302{
bart3c9989f2008-06-11 19:17:01 +0000303#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000304 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000305#endif
bart7b706b32009-05-10 06:55:39 +0000306 return (bm0[uword_msb(a)] & ((UWord)1 << uword_lsb(a)));
sewardjaf44c822007-11-25 14:01:38 +0000307}
308
bart7b706b32009-05-10 06:55:39 +0000309/**
310 * Return true if a bit corresponding to any of the addresses in range
311 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
312 * is set in bm0.
313 */
barta79df6e2008-03-14 17:07:51 +0000314static __inline__ UWord bm0_is_any_set(const UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000315 const Addr a, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000316{
bart8b4b2ee2008-06-11 13:17:56 +0000317#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000318 tl_assert(size > 0);
bart7b706b32009-05-10 06:55:39 +0000319 tl_assert(address_msb(make_address(0, a)) == 0);
320 tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
321 tl_assert(uword_msb(a) == uword_msb(a + size - 1));
barta79df6e2008-03-14 17:07:51 +0000322#endif
bart7b706b32009-05-10 06:55:39 +0000323 return (bm0[uword_msb(a)] & ((((UWord)1 << size) - 1) << uword_lsb(a)));
barta79df6e2008-03-14 17:07:51 +0000324}
sewardjaf44c822007-11-25 14:01:38 +0000325
bartadbdf142008-03-19 17:00:12 +0000326
bart0008f5b2008-03-22 17:07:39 +0000327
328/*********************************************************************/
329/* Functions for manipulating a struct bitmap. */
bartadbdf142008-03-19 17:00:12 +0000330/*********************************************************************/
331
332
bart33e56c92008-03-24 06:41:30 +0000333/* Second level bitmap. */
sewardjaf44c822007-11-25 14:01:38 +0000334struct bitmap2
335{
bart7b706b32009-05-10 06:55:39 +0000336 Addr addr; ///< address_msb(...)
bart8f822af2009-06-08 18:20:42 +0000337 Bool recalc;
bartbedfd232009-03-26 19:07:15 +0000338 struct bitmap1 bm1;
sewardjaf44c822007-11-25 14:01:38 +0000339};
340
bart33e56c92008-03-24 06:41:30 +0000341
bart7b706b32009-05-10 06:55:39 +0000342static void bm2_clear(struct bitmap2* const bm2);
343static __inline__
344struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1);
345
346
bartf647d342008-03-24 19:12:12 +0000347
bart8f822af2009-06-08 18:20:42 +0000348/**
349 * Rotate elements cache[0..n-1] such that the element at position n-1 is
350 * moved to position 0. This allows to speed up future cache lookups.
bart7e81a172008-06-09 19:50:51 +0000351 */
352static __inline__
353void bm_cache_rotate(struct bm_cache_elem cache[], const int n)
354{
bart45af5ea2008-06-12 06:04:59 +0000355#if 0
bartbedfd232009-03-26 19:07:15 +0000356 struct bm_cache_elem t;
bart7e81a172008-06-09 19:50:51 +0000357
bartbedfd232009-03-26 19:07:15 +0000358 tl_assert(2 <= n && n <= 8);
bartea2fa4c2008-06-10 06:32:49 +0000359
bartbedfd232009-03-26 19:07:15 +0000360 t = cache[0];
361 if (n > 1)
362 cache[0] = cache[1];
363 if (n > 2)
364 cache[1] = cache[2];
365 if (n > 3)
366 cache[2] = cache[3];
367 if (n > 4)
368 cache[3] = cache[4];
369 if (n > 5)
370 cache[4] = cache[5];
371 if (n > 6)
372 cache[5] = cache[6];
373 if (n > 7)
374 cache[6] = cache[7];
375 cache[n - 1] = t;
bartea2fa4c2008-06-10 06:32:49 +0000376#endif
bart7e81a172008-06-09 19:50:51 +0000377}
bartf647d342008-03-24 19:12:12 +0000378
bartf647d342008-03-24 19:12:12 +0000379static __inline__
bart7e81a172008-06-09 19:50:51 +0000380Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1,
bartf29205e2008-03-25 18:51:06 +0000381 struct bitmap2** bm2)
bart33e56c92008-03-24 06:41:30 +0000382{
bart8b4b2ee2008-06-11 13:17:56 +0000383#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000384 tl_assert(bm);
385 tl_assert(bm2);
bart7e81a172008-06-09 19:50:51 +0000386#endif
bart33e56c92008-03-24 06:41:30 +0000387
bart8f822af2009-06-08 18:20:42 +0000388#if DRD_BITMAP_N_CACHE_ELEM > 8
bart33e56c92008-03-24 06:41:30 +0000389#error Please update the code below.
390#endif
bart8f822af2009-06-08 18:20:42 +0000391#if DRD_BITMAP_N_CACHE_ELEM >= 1
bartbedfd232009-03-26 19:07:15 +0000392 if (a1 == bm->cache[0].a1)
393 {
394 *bm2 = bm->cache[0].bm2;
395 return True;
396 }
bart33e56c92008-03-24 06:41:30 +0000397#endif
bart8f822af2009-06-08 18:20:42 +0000398#if DRD_BITMAP_N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000399 if (a1 == bm->cache[1].a1)
400 {
401 *bm2 = bm->cache[1].bm2;
402 return True;
403 }
bart33e56c92008-03-24 06:41:30 +0000404#endif
bart8f822af2009-06-08 18:20:42 +0000405#if DRD_BITMAP_N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000406 if (a1 == bm->cache[2].a1)
407 {
408 *bm2 = bm->cache[2].bm2;
409 bm_cache_rotate(bm->cache, 3);
410 return True;
411 }
bart33e56c92008-03-24 06:41:30 +0000412#endif
bart8f822af2009-06-08 18:20:42 +0000413#if DRD_BITMAP_N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000414 if (a1 == bm->cache[3].a1)
415 {
416 *bm2 = bm->cache[3].bm2;
417 bm_cache_rotate(bm->cache, 4);
418 return True;
419 }
bart33e56c92008-03-24 06:41:30 +0000420#endif
bart8f822af2009-06-08 18:20:42 +0000421#if DRD_BITMAP_N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000422 if (a1 == bm->cache[4].a1)
423 {
424 *bm2 = bm->cache[4].bm2;
425 bm_cache_rotate(bm->cache, 5);
426 return True;
427 }
bart33e56c92008-03-24 06:41:30 +0000428#endif
bart8f822af2009-06-08 18:20:42 +0000429#if DRD_BITMAP_N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000430 if (a1 == bm->cache[5].a1)
431 {
432 *bm2 = bm->cache[5].bm2;
433 bm_cache_rotate(bm->cache, 6);
434 return True;
435 }
bart33e56c92008-03-24 06:41:30 +0000436#endif
bart8f822af2009-06-08 18:20:42 +0000437#if DRD_BITMAP_N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000438 if (a1 == bm->cache[6].a1)
439 {
440 *bm2 = bm->cache[6].bm2;
441 bm_cache_rotate(bm->cache, 7);
442 return True;
443 }
bart33e56c92008-03-24 06:41:30 +0000444#endif
bart8f822af2009-06-08 18:20:42 +0000445#if DRD_BITMAP_N_CACHE_ELEM >= 8
bartbedfd232009-03-26 19:07:15 +0000446 if (a1 == bm->cache[7].a1)
447 {
448 *bm2 = bm->cache[7].bm2;
449 bm_cache_rotate(bm->cache, 8);
450 return True;
451 }
bart33e56c92008-03-24 06:41:30 +0000452#endif
bartbedfd232009-03-26 19:07:15 +0000453 *bm2 = 0;
454 return False;
bart33e56c92008-03-24 06:41:30 +0000455}
456
457static __inline__
458void bm_update_cache(struct bitmap* const bm,
459 const UWord a1,
460 struct bitmap2* const bm2)
461{
bart3c9989f2008-06-11 19:17:01 +0000462#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000463 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000464#endif
bart33e56c92008-03-24 06:41:30 +0000465
bart8f822af2009-06-08 18:20:42 +0000466#if DRD_BITMAP_N_CACHE_ELEM > 8
bart33e56c92008-03-24 06:41:30 +0000467#error Please update the code below.
468#endif
bart8f822af2009-06-08 18:20:42 +0000469#if DRD_BITMAP_N_CACHE_ELEM >= 8
bartbedfd232009-03-26 19:07:15 +0000470 bm->cache[7] = bm->cache[6];
bart33e56c92008-03-24 06:41:30 +0000471#endif
bart8f822af2009-06-08 18:20:42 +0000472#if DRD_BITMAP_N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000473 bm->cache[6] = bm->cache[5];
bart33e56c92008-03-24 06:41:30 +0000474#endif
bart8f822af2009-06-08 18:20:42 +0000475#if DRD_BITMAP_N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000476 bm->cache[5] = bm->cache[4];
bart33e56c92008-03-24 06:41:30 +0000477#endif
bart8f822af2009-06-08 18:20:42 +0000478#if DRD_BITMAP_N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000479 bm->cache[4] = bm->cache[3];
bart33e56c92008-03-24 06:41:30 +0000480#endif
bart8f822af2009-06-08 18:20:42 +0000481#if DRD_BITMAP_N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000482 bm->cache[3] = bm->cache[2];
bart33e56c92008-03-24 06:41:30 +0000483#endif
bart8f822af2009-06-08 18:20:42 +0000484#if DRD_BITMAP_N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000485 bm->cache[2] = bm->cache[1];
bart33e56c92008-03-24 06:41:30 +0000486#endif
bart8f822af2009-06-08 18:20:42 +0000487#if DRD_BITMAP_N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000488 bm->cache[1] = bm->cache[0];
bart33e56c92008-03-24 06:41:30 +0000489#endif
bartbedfd232009-03-26 19:07:15 +0000490 bm->cache[0].a1 = a1;
491 bm->cache[0].bm2 = bm2;
bart33e56c92008-03-24 06:41:30 +0000492}
493
bart8f822af2009-06-08 18:20:42 +0000494/**
495 * Look up the address a1 in bitmap bm and return a pointer to a potentially
496 * shared second level bitmap. The bitmap where the returned pointer points
497 * at may not be modified by the caller.
bartf647d342008-03-24 19:12:12 +0000498 *
bart8f822af2009-06-08 18:20:42 +0000499 * @param a1 client address shifted right by ADDR_LSB_BITS.
500 * @param bm bitmap pointer.
bart0008f5b2008-03-22 17:07:39 +0000501 */
sewardjaf44c822007-11-25 14:01:38 +0000502static __inline__
bart7e81a172008-06-09 19:50:51 +0000503const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000504{
bart7b706b32009-05-10 06:55:39 +0000505 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000506
bart3c9989f2008-06-11 19:17:01 +0000507#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000508 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000509#endif
bart7b706b32009-05-10 06:55:39 +0000510
bartbedfd232009-03-26 19:07:15 +0000511 if (! bm_cache_lookup(bm, a1, &bm2))
512 {
bart7b706b32009-05-10 06:55:39 +0000513 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
514 bm_update_cache(bm, a1, bm2);
bartbedfd232009-03-26 19:07:15 +0000515 }
516 return bm2;
bartf647d342008-03-24 19:12:12 +0000517}
518
bart8f822af2009-06-08 18:20:42 +0000519/**
520 * Look up the address a1 in bitmap bm and return a pointer to a second
521 * level bitmap that is not shared and hence may be modified.
bartf647d342008-03-24 19:12:12 +0000522 *
bart8f822af2009-06-08 18:20:42 +0000523 * @param a1 client address shifted right by ADDR_LSB_BITS.
524 * @param bm bitmap pointer.
bartf647d342008-03-24 19:12:12 +0000525 */
526static __inline__
527struct bitmap2*
bart7e81a172008-06-09 19:50:51 +0000528bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1)
bartf647d342008-03-24 19:12:12 +0000529{
bartbedfd232009-03-26 19:07:15 +0000530 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000531
bart3c9989f2008-06-11 19:17:01 +0000532#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000533 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000534#endif
bartf647d342008-03-24 19:12:12 +0000535
bart7b706b32009-05-10 06:55:39 +0000536 if (! bm_cache_lookup(bm, a1, &bm2))
bartbedfd232009-03-26 19:07:15 +0000537 {
bart7b706b32009-05-10 06:55:39 +0000538 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
bartbedfd232009-03-26 19:07:15 +0000539 }
bartf647d342008-03-24 19:12:12 +0000540
bartbedfd232009-03-26 19:07:15 +0000541 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000542}
543
bart6584b692009-06-21 10:11:15 +0000544/** Clear the content of the second-level bitmap. */
545static __inline__
546void bm2_clear(struct bitmap2* const bm2)
547{
548#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
549 tl_assert(bm2);
550#endif
551 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
552}
553
bart8f822af2009-06-08 18:20:42 +0000554/**
555 * Insert an uninitialized second level bitmap for the address a1.
bartf647d342008-03-24 19:12:12 +0000556 *
bart8f822af2009-06-08 18:20:42 +0000557 * @param bm bitmap pointer.
558 * @param a1 client address shifted right by ADDR_LSB_BITS.
559 *
560 * @note bitmap2::recalc isn't initialized here on purpose.
bartf647d342008-03-24 19:12:12 +0000561 */
sewardjaf44c822007-11-25 14:01:38 +0000562static __inline__
bart7e81a172008-06-09 19:50:51 +0000563struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000564{
bartbedfd232009-03-26 19:07:15 +0000565 struct bitmap2* bm2;
bart33e56c92008-03-24 06:41:30 +0000566
bart7b706b32009-05-10 06:55:39 +0000567#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
568 tl_assert(bm);
569#endif
570
571 s_bitmap2_creation_count++;
572
573 bm2 = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2));
574 bm2->addr = a1;
575 VG_(OSetGen_Insert)(bm->oset, bm2);
576
577 bm_update_cache(bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000578
bartbedfd232009-03-26 19:07:15 +0000579 return bm2;
bartf647d342008-03-24 19:12:12 +0000580}
581
bartf647d342008-03-24 19:12:12 +0000582static __inline__
bart7b706b32009-05-10 06:55:39 +0000583struct bitmap2* bm2_insert_copy(struct bitmap* const bm,
584 struct bitmap2* const bm2)
bartf647d342008-03-24 19:12:12 +0000585{
bart7b706b32009-05-10 06:55:39 +0000586 struct bitmap2* bm2_copy;
bartf647d342008-03-24 19:12:12 +0000587
bart7b706b32009-05-10 06:55:39 +0000588 bm2_copy = bm2_insert(bm, bm2->addr);
589 VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1));
590 return bm2_copy;
sewardjaf44c822007-11-25 14:01:38 +0000591}
592
bart8f822af2009-06-08 18:20:42 +0000593/**
594 * Look up the address a1 in bitmap bm, and insert it if not found.
595 * The returned second level bitmap may not be modified.
bart0008f5b2008-03-22 17:07:39 +0000596 *
bart8f822af2009-06-08 18:20:42 +0000597 * @param bm bitmap pointer.
598 * @param a1 client address shifted right by ADDR_LSB_BITS.
bart0008f5b2008-03-22 17:07:39 +0000599 */
sewardjaf44c822007-11-25 14:01:38 +0000600static __inline__
bart7e81a172008-06-09 19:50:51 +0000601struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000602{
bartbedfd232009-03-26 19:07:15 +0000603 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000604
bart3c9989f2008-06-11 19:17:01 +0000605#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000606 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000607#endif
bart7b706b32009-05-10 06:55:39 +0000608
bartbedfd232009-03-26 19:07:15 +0000609 if (bm_cache_lookup(bm, a1, &bm2))
610 {
611 if (bm2 == 0)
612 {
613 bm2 = bm2_insert(bm, a1);
bart7b706b32009-05-10 06:55:39 +0000614 bm2_clear(bm2);
bartbedfd232009-03-26 19:07:15 +0000615 }
616 }
617 else
618 {
bart7b706b32009-05-10 06:55:39 +0000619 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
620 if (! bm2)
bartbedfd232009-03-26 19:07:15 +0000621 {
622 bm2 = bm2_insert(bm, a1);
bart7b706b32009-05-10 06:55:39 +0000623 bm2_clear(bm2);
bartbedfd232009-03-26 19:07:15 +0000624 }
bart7b706b32009-05-10 06:55:39 +0000625 bm_update_cache(bm, a1, bm2);
bartbedfd232009-03-26 19:07:15 +0000626 }
627 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000628}
629
bart8f822af2009-06-08 18:20:42 +0000630/**
631 * Look up the address a1 in bitmap bm, and insert it if not found.
632 * The returned second level bitmap may be modified.
bartf647d342008-03-24 19:12:12 +0000633 *
bart8f822af2009-06-08 18:20:42 +0000634 * @param a1 client address shifted right by ADDR_LSB_BITS.
635 * @param bm bitmap pointer.
bartf647d342008-03-24 19:12:12 +0000636 */
637static __inline__
638struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
639 const UWord a1)
640{
bart7b706b32009-05-10 06:55:39 +0000641 return bm2_lookup_or_insert(bm, a1);
bartf647d342008-03-24 19:12:12 +0000642}
643
bartd59bb0f2008-06-08 08:08:31 +0000644static __inline__
bart8f822af2009-06-08 18:20:42 +0000645void bm2_remove(struct bitmap* const bm, const UWord a1)
646{
647 struct bitmap2* bm2;
648
649#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
650 tl_assert(bm);
651#endif
652
653 bm2 = VG_(OSetGen_Remove)(bm->oset, &a1);
654 VG_(OSetGen_FreeNode)(bm->oset, bm2);
655
656 bm_update_cache(bm, a1, NULL);
657}
658
659static __inline__
bartd59bb0f2008-06-08 08:08:31 +0000660void bm_access_aligned_load(struct bitmap* const bm,
661 const Addr a1, const SizeT size)
662{
bartbedfd232009-03-26 19:07:15 +0000663 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000664
bart7b706b32009-05-10 06:55:39 +0000665#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
666 tl_assert(bm);
667#endif
668
669 bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
670 bm0_set_range(bm2->bm1.bm0_r,
671 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
672 SCALED_SIZE(size));
bartd59bb0f2008-06-08 08:08:31 +0000673}
674
675static __inline__
676void bm_access_aligned_store(struct bitmap* const bm,
677 const Addr a1, const SizeT size)
678{
bartbedfd232009-03-26 19:07:15 +0000679 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000680
bart7b706b32009-05-10 06:55:39 +0000681#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
682 tl_assert(bm);
683#endif
684
685 bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
686 bm0_set_range(bm2->bm1.bm0_w,
687 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
688 SCALED_SIZE(size));
bartd59bb0f2008-06-08 08:08:31 +0000689}
690
691static __inline__
bart7e81a172008-06-09 19:50:51 +0000692Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm,
bart7b706b32009-05-10 06:55:39 +0000693 const Addr a, const SizeT size)
bartd59bb0f2008-06-08 08:08:31 +0000694{
bartbedfd232009-03-26 19:07:15 +0000695 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000696
bart7b706b32009-05-10 06:55:39 +0000697#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
698 tl_assert(bm);
699#endif
bartd59bb0f2008-06-08 08:08:31 +0000700
bart7b706b32009-05-10 06:55:39 +0000701 bm2 = bm2_lookup(bm, address_msb(a));
702 return (bm2
703 && bm0_is_any_set(bm2->bm1.bm0_w,
704 address_lsb(a),
705 SCALED_SIZE(size)));
bartd59bb0f2008-06-08 08:08:31 +0000706}
707
708static __inline__
bart7e81a172008-06-09 19:50:51 +0000709Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm,
bart7b706b32009-05-10 06:55:39 +0000710 const Addr a, const SizeT size)
bartd59bb0f2008-06-08 08:08:31 +0000711{
bartbedfd232009-03-26 19:07:15 +0000712 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000713
bart7b706b32009-05-10 06:55:39 +0000714#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
715 tl_assert(bm);
716#endif
bartd59bb0f2008-06-08 08:08:31 +0000717
bart7b706b32009-05-10 06:55:39 +0000718 bm2 = bm2_lookup(bm, address_msb(a));
bartbedfd232009-03-26 19:07:15 +0000719 if (bm2)
720 {
bart7b706b32009-05-10 06:55:39 +0000721 if (bm0_is_any_set(bm2->bm1.bm0_r, address_lsb(a), SCALED_SIZE(size))
722 | bm0_is_any_set(bm2->bm1.bm0_w, address_lsb(a), SCALED_SIZE(size)))
bartbedfd232009-03-26 19:07:15 +0000723 {
724 return True;
725 }
726 }
727 return False;
bartd59bb0f2008-06-08 08:08:31 +0000728}
sewardjaf44c822007-11-25 14:01:38 +0000729
bart33e56c92008-03-24 06:41:30 +0000730#endif /* __DRD_BITMAP_H */