blob: f903945c0c0c4472c98f05d208f533635e748076 [file] [log] [blame]
bartbedfd232009-03-26 19:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardjaf44c822007-11-25 14:01:38 +00002/*
bart86562bd2009-02-16 19:43:56 +00003 This file is part of drd, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00004
sewardj9eecbbb2010-05-03 21:37:12 +00005 Copyright (C) 2006-2010 Bart Van Assche <bart.vanassche@gmail.com>.
sewardjaf44c822007-11-25 14:01:38 +00006
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
bart33e56c92008-03-24 06:41:30 +000026#ifndef __DRD_BITMAP_H
27#define __DRD_BITMAP_H
sewardjaf44c822007-11-25 14:01:38 +000028
29
bart7b706b32009-05-10 06:55:39 +000030#include "pub_drd_bitmap.h"
bart82a0c5d2009-02-14 14:49:23 +000031#include "pub_tool_basics.h"
sewardjaf44c822007-11-25 14:01:38 +000032#include "pub_tool_oset.h"
bartd59bb0f2008-06-08 08:08:31 +000033#include "pub_tool_libcbase.h"
sewardjaf44c822007-11-25 14:01:38 +000034
35
bart7b706b32009-05-10 06:55:39 +000036/* Bitmap representation. A bitmap is a data structure in which two bits are
37 * reserved per 32 bit address: one bit that indicates that the data at the
38 * specified address has been read, and one bit that indicates that the data
39 * has been written to.
40 */
41
42/* Client addresses are split into bitfields as follows:
43 * ------------------------------------------------------
bart31b983d2010-02-21 14:52:59 +000044 * | Address MSB | Address LSB | Ignored bits |
bart7b706b32009-05-10 06:55:39 +000045 * ------------------------------------------------------
46 * | Address MSB | UWord MSB | UWord LSB | Ignored bits |
47 * ------------------------------------------------------
48 */
sewardjaf44c822007-11-25 14:01:38 +000049
50
sewardjaf44c822007-11-25 14:01:38 +000051
bart7b706b32009-05-10 06:55:39 +000052/* Address MSB / LSB split. */
sewardjaf44c822007-11-25 14:01:38 +000053
sewardjaf44c822007-11-25 14:01:38 +000054
bart7b706b32009-05-10 06:55:39 +000055/** Number of least significant address bits that are ignored. */
56#define ADDR_IGNORED_BITS 0
57#define ADDR_IGNORED_MASK ((1U << ADDR_IGNORED_BITS) - 1U)
58#define ADDR_GRANULARITY (1U << ADDR_IGNORED_BITS)
sewardjaf44c822007-11-25 14:01:38 +000059
bart8f822af2009-06-08 18:20:42 +000060/**
61 * Round argument a up to a multiple of (1 << ADDR_GRANULARITY), and next
62 * shift it right ADDR_GRANULARITY bits. The expression below is optimized
63 * for the case where a is a constant.
bart7b706b32009-05-10 06:55:39 +000064 */
65#define SCALED_SIZE(a) \
66 (((((a) - 1U) | ADDR_IGNORED_MASK) + 1U) >> ADDR_IGNORED_BITS)
sewardjaf44c822007-11-25 14:01:38 +000067
bart8f822af2009-06-08 18:20:42 +000068/**
69 * Number of bits assigned to the least significant component of an address.
bart7b706b32009-05-10 06:55:39 +000070 */
71#define ADDR_LSB_BITS 12
sewardjaf44c822007-11-25 14:01:38 +000072
bart8f822af2009-06-08 18:20:42 +000073/**
74 * Mask that has to be applied to an address of type Addr in order to
75 * compute the least significant part of an address split, after having
76 * shifted the address bits ADDR_GRANULARITY to the right.
bart7b706b32009-05-10 06:55:39 +000077 */
78#define ADDR_LSB_MASK (((UWord)1 << ADDR_LSB_BITS) - 1U)
79
80/** Compute least significant bits of an address of type Addr. */
81static __inline__
82UWord address_lsb(const Addr a)
83{ return (a >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK; }
84
85/**
86 * Compute the first address for which address_lsb() is equal to
87 * address_lsb(a).
88 */
89static __inline__
90Addr first_address_with_same_lsb(const Addr a)
91{
92 return ((a | ADDR_IGNORED_MASK) ^ ADDR_IGNORED_MASK);
93}
94
95/**
96 * Compute the first address for which address_lsb() is greater than
97 * address_lsb(a).
98 */
99static __inline__
100Addr first_address_with_higher_lsb(const Addr a)
101{
102 return ((a | ADDR_IGNORED_MASK) + 1U);
103}
104
105/** Compute most significant bits of an address of type Addr. */
106static __inline__
107UWord address_msb(const Addr a)
108{ return a >> (ADDR_LSB_BITS + ADDR_IGNORED_BITS); }
109
110static __inline__
111Addr first_address_with_higher_msb(const Addr a)
112{
113 return ((a | ((ADDR_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
114 + 1U);
115}
116
bart8f822af2009-06-08 18:20:42 +0000117/**
118 * Convert LSB and MSB back into an address.
bart7b706b32009-05-10 06:55:39 +0000119 *
bart8f822af2009-06-08 18:20:42 +0000120 * @note It is assumed that sizeof(Addr) == sizeof(UWord).
bart7b706b32009-05-10 06:55:39 +0000121 */
122static __inline__
123Addr make_address(const UWord a1, const UWord a0)
124{
125 return ((a1 << (ADDR_LSB_BITS + ADDR_IGNORED_BITS))
126 | (a0 << ADDR_IGNORED_BITS));
127}
128
129
130
131
132
bart8f822af2009-06-08 18:20:42 +0000133/** Number of bits that fit in a variable of type UWord. */
bart7b706b32009-05-10 06:55:39 +0000134#define BITS_PER_UWORD (8U * sizeof(UWord))
135
bart8f822af2009-06-08 18:20:42 +0000136/** Log2 of BITS_PER_UWORD. */
sewardj4cb6bf72010-01-01 18:31:41 +0000137#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm)
sewardjaf44c822007-11-25 14:01:38 +0000138#define BITS_PER_BITS_PER_UWORD 5
139#elif defined(VGA_amd64) || defined(VGA_ppc64)
140#define BITS_PER_BITS_PER_UWORD 6
141#else
142#error Unknown platform.
143#endif
144
bart8f822af2009-06-08 18:20:42 +0000145/** Number of UWord's needed to store one bit per address LSB. */
bart7b706b32009-05-10 06:55:39 +0000146#define BITMAP1_UWORD_COUNT (1U << (ADDR_LSB_BITS - BITS_PER_BITS_PER_UWORD))
sewardjaf44c822007-11-25 14:01:38 +0000147
bart8f822af2009-06-08 18:20:42 +0000148/**
149 * Mask that has to be applied to an (Addr >> ADDR_IGNORED_BITS) expression
150 * in order to compute the least significant part of an UWord.
bart7b706b32009-05-10 06:55:39 +0000151 */
152#define UWORD_LSB_MASK (((UWord)1 << BITS_PER_BITS_PER_UWORD) - 1)
sewardjaf44c822007-11-25 14:01:38 +0000153
bart8f822af2009-06-08 18:20:42 +0000154/**
155 * Compute index into bm0[] array.
bart7b706b32009-05-10 06:55:39 +0000156 *
bart8f822af2009-06-08 18:20:42 +0000157 * @param a Address shifted right ADDR_IGNORED_BITS bits.
bart7b706b32009-05-10 06:55:39 +0000158 */
159static __inline__
160UWord uword_msb(const UWord a)
161{
162#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
163 tl_assert(a < (1U << ADDR_LSB_BITS));
164#endif
165 return a >> BITS_PER_BITS_PER_UWORD;
166}
sewardjaf44c822007-11-25 14:01:38 +0000167
bart8f822af2009-06-08 18:20:42 +0000168/**
169 * Return the least significant bits.
bart7b706b32009-05-10 06:55:39 +0000170 *
bart8f822af2009-06-08 18:20:42 +0000171 * @param a Address shifted right ADDR_IGNORED_BITS bits.
bart7b706b32009-05-10 06:55:39 +0000172 */
173static __inline__
174UWord uword_lsb(const UWord a)
175{
176#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
177 tl_assert(a < (1U << ADDR_LSB_BITS));
178#endif
179 return a & UWORD_LSB_MASK;
180}
181
bart8f822af2009-06-08 18:20:42 +0000182/**
183 * Compute the highest address lower than a for which
184 * uword_lsb(address_lsb(a)) == 0.
bart7b706b32009-05-10 06:55:39 +0000185 *
bart8f822af2009-06-08 18:20:42 +0000186 * @param a Address.
bart7b706b32009-05-10 06:55:39 +0000187 */
188static __inline__
189Addr first_address_with_same_uword_lsb(const Addr a)
190{
191 return (a & (~UWORD_LSB_MASK << ADDR_IGNORED_BITS));
192}
193
194/**
195 * First address that will go in the UWord past the one 'a' goes in.
196 *
197 * @param a Address.
198 */
199static __inline__
200Addr first_address_with_higher_uword_msb(const Addr a)
201{
202 return ((a | ((UWORD_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
203 + 1);
204}
205
sewardjaf44c822007-11-25 14:01:38 +0000206
207
bart33e56c92008-03-24 06:41:30 +0000208/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +0000209
210static ULong s_bitmap2_creation_count;
211
212
bart0008f5b2008-03-22 17:07:39 +0000213
214/*********************************************************************/
215/* Functions for manipulating a struct bitmap1. */
216/*********************************************************************/
217
218
bart7b706b32009-05-10 06:55:39 +0000219/* Lowest level, corresponding to the lowest ADDR_LSB_BITS of an address. */
sewardjaf44c822007-11-25 14:01:38 +0000220struct bitmap1
221{
bartbedfd232009-03-26 19:07:15 +0000222 UWord bm0_r[BITMAP1_UWORD_COUNT];
223 UWord bm0_w[BITMAP1_UWORD_COUNT];
sewardjaf44c822007-11-25 14:01:38 +0000224};
225
bart7b706b32009-05-10 06:55:39 +0000226static __inline__ UWord bm0_mask(const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000227{
bart3c9989f2008-06-11 19:17:01 +0000228#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000229 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000230#endif
bart7b706b32009-05-10 06:55:39 +0000231 return ((UWord)1 << uword_lsb(a));
barta79df6e2008-03-14 17:07:51 +0000232}
233
bart7b706b32009-05-10 06:55:39 +0000234/** Set the bit corresponding to address a in bitmap bm0. */
235static __inline__ void bm0_set(UWord* bm0, const UWord a)
236{
237#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
238 tl_assert(address_msb(make_address(0, a)) == 0);
239#endif
240 bm0[uword_msb(a)] |= (UWord)1 << uword_lsb(a);
241}
242
243/**
244 * Set the bits corresponding to all of the addresses in range
245 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
246 * in bitmap bm0.
247 */
bartf8bc71d2008-03-15 11:42:34 +0000248static __inline__ void bm0_set_range(UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000249 const UWord a, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000250{
bart8b4b2ee2008-06-11 13:17:56 +0000251#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000252 tl_assert(size > 0);
bart7b706b32009-05-10 06:55:39 +0000253 tl_assert(address_msb(make_address(0, a)) == 0);
254 tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
255 tl_assert(uword_msb(a) == uword_msb(a + size - 1));
barta79df6e2008-03-14 17:07:51 +0000256#endif
bart7b706b32009-05-10 06:55:39 +0000257 bm0[uword_msb(a)]
258 |= (((UWord)1 << size) - 1) << uword_lsb(a);
sewardjaf44c822007-11-25 14:01:38 +0000259}
260
bart7b706b32009-05-10 06:55:39 +0000261/** Clear the bit corresponding to address a in bitmap bm0. */
262static __inline__ void bm0_clear(UWord* bm0, const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000263{
bart3c9989f2008-06-11 19:17:01 +0000264#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000265 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000266#endif
bart7b706b32009-05-10 06:55:39 +0000267 bm0[uword_msb(a)] &= ~((UWord)1 << uword_lsb(a));
sewardjaf44c822007-11-25 14:01:38 +0000268}
269
bart7b706b32009-05-10 06:55:39 +0000270/**
271 * Clear all of the addresses in range
272 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
273 * in bitmap bm0.
274 */
bart5955f332008-03-25 17:19:20 +0000275static __inline__ void bm0_clear_range(UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000276 const UWord a, const SizeT size)
bart5955f332008-03-25 17:19:20 +0000277{
bart8b4b2ee2008-06-11 13:17:56 +0000278#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000279 tl_assert(address_msb(make_address(0, a)) == 0);
280 tl_assert(size == 0 || address_msb(make_address(0, a + size - 1)) == 0);
281 tl_assert(size == 0 || uword_msb(a) == uword_msb(a + size - 1));
bart5955f332008-03-25 17:19:20 +0000282#endif
bart8c046732009-04-25 06:52:01 +0000283 /*
bart31b983d2010-02-21 14:52:59 +0000284 * Note: although the expression below yields a correct result even if
bart8c046732009-04-25 06:52:01 +0000285 * size == 0, do not touch bm0[] if size == 0 because this might otherwise
286 * cause an access of memory just past the end of the bm0[] array.
287 */
288 if (size > 0)
289 {
bart7b706b32009-05-10 06:55:39 +0000290 bm0[uword_msb(a)]
291 &= ~((((UWord)1 << size) - 1) << uword_lsb(a));
bart8c046732009-04-25 06:52:01 +0000292 }
bart5955f332008-03-25 17:19:20 +0000293}
294
bart7b706b32009-05-10 06:55:39 +0000295/** Test whether the bit corresponding to address a is set in bitmap bm0. */
296static __inline__ UWord bm0_is_set(const UWord* bm0, const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000297{
bart3c9989f2008-06-11 19:17:01 +0000298#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000299 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000300#endif
bart7b706b32009-05-10 06:55:39 +0000301 return (bm0[uword_msb(a)] & ((UWord)1 << uword_lsb(a)));
sewardjaf44c822007-11-25 14:01:38 +0000302}
303
bart7b706b32009-05-10 06:55:39 +0000304/**
305 * Return true if a bit corresponding to any of the addresses in range
306 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
307 * is set in bm0.
308 */
barta79df6e2008-03-14 17:07:51 +0000309static __inline__ UWord bm0_is_any_set(const UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000310 const Addr a, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000311{
bart8b4b2ee2008-06-11 13:17:56 +0000312#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000313 tl_assert(size > 0);
bart7b706b32009-05-10 06:55:39 +0000314 tl_assert(address_msb(make_address(0, a)) == 0);
315 tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
316 tl_assert(uword_msb(a) == uword_msb(a + size - 1));
barta79df6e2008-03-14 17:07:51 +0000317#endif
bart7b706b32009-05-10 06:55:39 +0000318 return (bm0[uword_msb(a)] & ((((UWord)1 << size) - 1) << uword_lsb(a)));
barta79df6e2008-03-14 17:07:51 +0000319}
sewardjaf44c822007-11-25 14:01:38 +0000320
bartadbdf142008-03-19 17:00:12 +0000321
bart0008f5b2008-03-22 17:07:39 +0000322
323/*********************************************************************/
324/* Functions for manipulating a struct bitmap. */
bartadbdf142008-03-19 17:00:12 +0000325/*********************************************************************/
326
327
bart33e56c92008-03-24 06:41:30 +0000328/* Second level bitmap. */
sewardjaf44c822007-11-25 14:01:38 +0000329struct bitmap2
330{
bart7b706b32009-05-10 06:55:39 +0000331 Addr addr; ///< address_msb(...)
bart8f822af2009-06-08 18:20:42 +0000332 Bool recalc;
bartbedfd232009-03-26 19:07:15 +0000333 struct bitmap1 bm1;
sewardjaf44c822007-11-25 14:01:38 +0000334};
335
bart33e56c92008-03-24 06:41:30 +0000336
bart7b706b32009-05-10 06:55:39 +0000337static void bm2_clear(struct bitmap2* const bm2);
338static __inline__
339struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1);
340
341
bartf647d342008-03-24 19:12:12 +0000342
bart8f822af2009-06-08 18:20:42 +0000343/**
344 * Rotate elements cache[0..n-1] such that the element at position n-1 is
345 * moved to position 0. This allows to speed up future cache lookups.
bart7e81a172008-06-09 19:50:51 +0000346 */
347static __inline__
348void bm_cache_rotate(struct bm_cache_elem cache[], const int n)
349{
bart45af5ea2008-06-12 06:04:59 +0000350#if 0
bartbedfd232009-03-26 19:07:15 +0000351 struct bm_cache_elem t;
bart7e81a172008-06-09 19:50:51 +0000352
bartbedfd232009-03-26 19:07:15 +0000353 tl_assert(2 <= n && n <= 8);
bartea2fa4c2008-06-10 06:32:49 +0000354
bartbedfd232009-03-26 19:07:15 +0000355 t = cache[0];
356 if (n > 1)
357 cache[0] = cache[1];
358 if (n > 2)
359 cache[1] = cache[2];
360 if (n > 3)
361 cache[2] = cache[3];
362 if (n > 4)
363 cache[3] = cache[4];
364 if (n > 5)
365 cache[4] = cache[5];
366 if (n > 6)
367 cache[5] = cache[6];
368 if (n > 7)
369 cache[6] = cache[7];
370 cache[n - 1] = t;
bartea2fa4c2008-06-10 06:32:49 +0000371#endif
bart7e81a172008-06-09 19:50:51 +0000372}
bartf647d342008-03-24 19:12:12 +0000373
bartf647d342008-03-24 19:12:12 +0000374static __inline__
bart7e81a172008-06-09 19:50:51 +0000375Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1,
bartf29205e2008-03-25 18:51:06 +0000376 struct bitmap2** bm2)
bart33e56c92008-03-24 06:41:30 +0000377{
bart8b4b2ee2008-06-11 13:17:56 +0000378#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000379 tl_assert(bm);
380 tl_assert(bm2);
bart7e81a172008-06-09 19:50:51 +0000381#endif
bart33e56c92008-03-24 06:41:30 +0000382
bart8f822af2009-06-08 18:20:42 +0000383#if DRD_BITMAP_N_CACHE_ELEM > 8
bart33e56c92008-03-24 06:41:30 +0000384#error Please update the code below.
385#endif
bart8f822af2009-06-08 18:20:42 +0000386#if DRD_BITMAP_N_CACHE_ELEM >= 1
bartbedfd232009-03-26 19:07:15 +0000387 if (a1 == bm->cache[0].a1)
388 {
389 *bm2 = bm->cache[0].bm2;
390 return True;
391 }
bart33e56c92008-03-24 06:41:30 +0000392#endif
bart8f822af2009-06-08 18:20:42 +0000393#if DRD_BITMAP_N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000394 if (a1 == bm->cache[1].a1)
395 {
396 *bm2 = bm->cache[1].bm2;
397 return True;
398 }
bart33e56c92008-03-24 06:41:30 +0000399#endif
bart8f822af2009-06-08 18:20:42 +0000400#if DRD_BITMAP_N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000401 if (a1 == bm->cache[2].a1)
402 {
403 *bm2 = bm->cache[2].bm2;
404 bm_cache_rotate(bm->cache, 3);
405 return True;
406 }
bart33e56c92008-03-24 06:41:30 +0000407#endif
bart8f822af2009-06-08 18:20:42 +0000408#if DRD_BITMAP_N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000409 if (a1 == bm->cache[3].a1)
410 {
411 *bm2 = bm->cache[3].bm2;
412 bm_cache_rotate(bm->cache, 4);
413 return True;
414 }
bart33e56c92008-03-24 06:41:30 +0000415#endif
bart8f822af2009-06-08 18:20:42 +0000416#if DRD_BITMAP_N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000417 if (a1 == bm->cache[4].a1)
418 {
419 *bm2 = bm->cache[4].bm2;
420 bm_cache_rotate(bm->cache, 5);
421 return True;
422 }
bart33e56c92008-03-24 06:41:30 +0000423#endif
bart8f822af2009-06-08 18:20:42 +0000424#if DRD_BITMAP_N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000425 if (a1 == bm->cache[5].a1)
426 {
427 *bm2 = bm->cache[5].bm2;
428 bm_cache_rotate(bm->cache, 6);
429 return True;
430 }
bart33e56c92008-03-24 06:41:30 +0000431#endif
bart8f822af2009-06-08 18:20:42 +0000432#if DRD_BITMAP_N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000433 if (a1 == bm->cache[6].a1)
434 {
435 *bm2 = bm->cache[6].bm2;
436 bm_cache_rotate(bm->cache, 7);
437 return True;
438 }
bart33e56c92008-03-24 06:41:30 +0000439#endif
bart8f822af2009-06-08 18:20:42 +0000440#if DRD_BITMAP_N_CACHE_ELEM >= 8
bartbedfd232009-03-26 19:07:15 +0000441 if (a1 == bm->cache[7].a1)
442 {
443 *bm2 = bm->cache[7].bm2;
444 bm_cache_rotate(bm->cache, 8);
445 return True;
446 }
bart33e56c92008-03-24 06:41:30 +0000447#endif
bartbedfd232009-03-26 19:07:15 +0000448 *bm2 = 0;
449 return False;
bart33e56c92008-03-24 06:41:30 +0000450}
451
452static __inline__
453void bm_update_cache(struct bitmap* const bm,
454 const UWord a1,
455 struct bitmap2* const bm2)
456{
bart3c9989f2008-06-11 19:17:01 +0000457#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000458 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000459#endif
bart33e56c92008-03-24 06:41:30 +0000460
bart8f822af2009-06-08 18:20:42 +0000461#if DRD_BITMAP_N_CACHE_ELEM > 8
bart33e56c92008-03-24 06:41:30 +0000462#error Please update the code below.
463#endif
bart8f822af2009-06-08 18:20:42 +0000464#if DRD_BITMAP_N_CACHE_ELEM >= 8
bartbedfd232009-03-26 19:07:15 +0000465 bm->cache[7] = bm->cache[6];
bart33e56c92008-03-24 06:41:30 +0000466#endif
bart8f822af2009-06-08 18:20:42 +0000467#if DRD_BITMAP_N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000468 bm->cache[6] = bm->cache[5];
bart33e56c92008-03-24 06:41:30 +0000469#endif
bart8f822af2009-06-08 18:20:42 +0000470#if DRD_BITMAP_N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000471 bm->cache[5] = bm->cache[4];
bart33e56c92008-03-24 06:41:30 +0000472#endif
bart8f822af2009-06-08 18:20:42 +0000473#if DRD_BITMAP_N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000474 bm->cache[4] = bm->cache[3];
bart33e56c92008-03-24 06:41:30 +0000475#endif
bart8f822af2009-06-08 18:20:42 +0000476#if DRD_BITMAP_N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000477 bm->cache[3] = bm->cache[2];
bart33e56c92008-03-24 06:41:30 +0000478#endif
bart8f822af2009-06-08 18:20:42 +0000479#if DRD_BITMAP_N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000480 bm->cache[2] = bm->cache[1];
bart33e56c92008-03-24 06:41:30 +0000481#endif
bart8f822af2009-06-08 18:20:42 +0000482#if DRD_BITMAP_N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000483 bm->cache[1] = bm->cache[0];
bart33e56c92008-03-24 06:41:30 +0000484#endif
bartbedfd232009-03-26 19:07:15 +0000485 bm->cache[0].a1 = a1;
486 bm->cache[0].bm2 = bm2;
bart33e56c92008-03-24 06:41:30 +0000487}
488
bart8f822af2009-06-08 18:20:42 +0000489/**
490 * Look up the address a1 in bitmap bm and return a pointer to a potentially
491 * shared second level bitmap. The bitmap where the returned pointer points
492 * at may not be modified by the caller.
bartf647d342008-03-24 19:12:12 +0000493 *
bart8f822af2009-06-08 18:20:42 +0000494 * @param a1 client address shifted right by ADDR_LSB_BITS.
495 * @param bm bitmap pointer.
bart0008f5b2008-03-22 17:07:39 +0000496 */
sewardjaf44c822007-11-25 14:01:38 +0000497static __inline__
bart7e81a172008-06-09 19:50:51 +0000498const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000499{
bart7b706b32009-05-10 06:55:39 +0000500 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000501
bart3c9989f2008-06-11 19:17:01 +0000502#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000503 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000504#endif
bart7b706b32009-05-10 06:55:39 +0000505
bartbedfd232009-03-26 19:07:15 +0000506 if (! bm_cache_lookup(bm, a1, &bm2))
507 {
bart7b706b32009-05-10 06:55:39 +0000508 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
509 bm_update_cache(bm, a1, bm2);
bartbedfd232009-03-26 19:07:15 +0000510 }
511 return bm2;
bartf647d342008-03-24 19:12:12 +0000512}
513
bart8f822af2009-06-08 18:20:42 +0000514/**
515 * Look up the address a1 in bitmap bm and return a pointer to a second
516 * level bitmap that is not shared and hence may be modified.
bartf647d342008-03-24 19:12:12 +0000517 *
bart8f822af2009-06-08 18:20:42 +0000518 * @param a1 client address shifted right by ADDR_LSB_BITS.
519 * @param bm bitmap pointer.
bartf647d342008-03-24 19:12:12 +0000520 */
521static __inline__
522struct bitmap2*
bart7e81a172008-06-09 19:50:51 +0000523bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1)
bartf647d342008-03-24 19:12:12 +0000524{
bartbedfd232009-03-26 19:07:15 +0000525 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000526
bart3c9989f2008-06-11 19:17:01 +0000527#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000528 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000529#endif
bartf647d342008-03-24 19:12:12 +0000530
bart7b706b32009-05-10 06:55:39 +0000531 if (! bm_cache_lookup(bm, a1, &bm2))
bartbedfd232009-03-26 19:07:15 +0000532 {
bart7b706b32009-05-10 06:55:39 +0000533 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
bartbedfd232009-03-26 19:07:15 +0000534 }
bartf647d342008-03-24 19:12:12 +0000535
bartbedfd232009-03-26 19:07:15 +0000536 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000537}
538
bart6584b692009-06-21 10:11:15 +0000539/** Clear the content of the second-level bitmap. */
540static __inline__
541void bm2_clear(struct bitmap2* const bm2)
542{
543#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
544 tl_assert(bm2);
545#endif
546 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
547}
548
bart8f822af2009-06-08 18:20:42 +0000549/**
550 * Insert an uninitialized second level bitmap for the address a1.
bartf647d342008-03-24 19:12:12 +0000551 *
bart8f822af2009-06-08 18:20:42 +0000552 * @param bm bitmap pointer.
553 * @param a1 client address shifted right by ADDR_LSB_BITS.
554 *
555 * @note bitmap2::recalc isn't initialized here on purpose.
bartf647d342008-03-24 19:12:12 +0000556 */
sewardjaf44c822007-11-25 14:01:38 +0000557static __inline__
bart7e81a172008-06-09 19:50:51 +0000558struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000559{
bartbedfd232009-03-26 19:07:15 +0000560 struct bitmap2* bm2;
bart33e56c92008-03-24 06:41:30 +0000561
bart7b706b32009-05-10 06:55:39 +0000562#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
563 tl_assert(bm);
564#endif
565
566 s_bitmap2_creation_count++;
567
568 bm2 = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2));
569 bm2->addr = a1;
570 VG_(OSetGen_Insert)(bm->oset, bm2);
571
572 bm_update_cache(bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000573
bartbedfd232009-03-26 19:07:15 +0000574 return bm2;
bartf647d342008-03-24 19:12:12 +0000575}
576
bartf647d342008-03-24 19:12:12 +0000577static __inline__
bart7b706b32009-05-10 06:55:39 +0000578struct bitmap2* bm2_insert_copy(struct bitmap* const bm,
579 struct bitmap2* const bm2)
bartf647d342008-03-24 19:12:12 +0000580{
bart7b706b32009-05-10 06:55:39 +0000581 struct bitmap2* bm2_copy;
bartf647d342008-03-24 19:12:12 +0000582
bart7b706b32009-05-10 06:55:39 +0000583 bm2_copy = bm2_insert(bm, bm2->addr);
584 VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1));
585 return bm2_copy;
sewardjaf44c822007-11-25 14:01:38 +0000586}
587
bart8f822af2009-06-08 18:20:42 +0000588/**
589 * Look up the address a1 in bitmap bm, and insert it if not found.
590 * The returned second level bitmap may not be modified.
bart0008f5b2008-03-22 17:07:39 +0000591 *
bart8f822af2009-06-08 18:20:42 +0000592 * @param bm bitmap pointer.
593 * @param a1 client address shifted right by ADDR_LSB_BITS.
bart0008f5b2008-03-22 17:07:39 +0000594 */
sewardjaf44c822007-11-25 14:01:38 +0000595static __inline__
bart7e81a172008-06-09 19:50:51 +0000596struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000597{
bartbedfd232009-03-26 19:07:15 +0000598 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000599
bart3c9989f2008-06-11 19:17:01 +0000600#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000601 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000602#endif
bart7b706b32009-05-10 06:55:39 +0000603
bartbedfd232009-03-26 19:07:15 +0000604 if (bm_cache_lookup(bm, a1, &bm2))
605 {
606 if (bm2 == 0)
607 {
608 bm2 = bm2_insert(bm, a1);
bart7b706b32009-05-10 06:55:39 +0000609 bm2_clear(bm2);
bartbedfd232009-03-26 19:07:15 +0000610 }
611 }
612 else
613 {
bart7b706b32009-05-10 06:55:39 +0000614 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
615 if (! bm2)
bartbedfd232009-03-26 19:07:15 +0000616 {
617 bm2 = bm2_insert(bm, a1);
bart7b706b32009-05-10 06:55:39 +0000618 bm2_clear(bm2);
bartbedfd232009-03-26 19:07:15 +0000619 }
bart7b706b32009-05-10 06:55:39 +0000620 bm_update_cache(bm, a1, bm2);
bartbedfd232009-03-26 19:07:15 +0000621 }
622 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000623}
624
bart8f822af2009-06-08 18:20:42 +0000625/**
626 * Look up the address a1 in bitmap bm, and insert it if not found.
627 * The returned second level bitmap may be modified.
bartf647d342008-03-24 19:12:12 +0000628 *
bart8f822af2009-06-08 18:20:42 +0000629 * @param a1 client address shifted right by ADDR_LSB_BITS.
630 * @param bm bitmap pointer.
bartf647d342008-03-24 19:12:12 +0000631 */
632static __inline__
633struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
634 const UWord a1)
635{
bart7b706b32009-05-10 06:55:39 +0000636 return bm2_lookup_or_insert(bm, a1);
bartf647d342008-03-24 19:12:12 +0000637}
638
bartd59bb0f2008-06-08 08:08:31 +0000639static __inline__
bart8f822af2009-06-08 18:20:42 +0000640void bm2_remove(struct bitmap* const bm, const UWord a1)
641{
642 struct bitmap2* bm2;
643
644#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
645 tl_assert(bm);
646#endif
647
648 bm2 = VG_(OSetGen_Remove)(bm->oset, &a1);
649 VG_(OSetGen_FreeNode)(bm->oset, bm2);
650
651 bm_update_cache(bm, a1, NULL);
652}
653
654static __inline__
bartd59bb0f2008-06-08 08:08:31 +0000655void bm_access_aligned_load(struct bitmap* const bm,
656 const Addr a1, const SizeT size)
657{
bartbedfd232009-03-26 19:07:15 +0000658 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000659
bart7b706b32009-05-10 06:55:39 +0000660#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
661 tl_assert(bm);
662#endif
663
664 bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
665 bm0_set_range(bm2->bm1.bm0_r,
666 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
667 SCALED_SIZE(size));
bartd59bb0f2008-06-08 08:08:31 +0000668}
669
670static __inline__
671void bm_access_aligned_store(struct bitmap* const bm,
672 const Addr a1, const SizeT size)
673{
bartbedfd232009-03-26 19:07:15 +0000674 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000675
bart7b706b32009-05-10 06:55:39 +0000676#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
677 tl_assert(bm);
678#endif
679
680 bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
681 bm0_set_range(bm2->bm1.bm0_w,
682 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
683 SCALED_SIZE(size));
bartd59bb0f2008-06-08 08:08:31 +0000684}
685
686static __inline__
bart7e81a172008-06-09 19:50:51 +0000687Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm,
bart7b706b32009-05-10 06:55:39 +0000688 const Addr a, const SizeT size)
bartd59bb0f2008-06-08 08:08:31 +0000689{
bartbedfd232009-03-26 19:07:15 +0000690 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000691
bart7b706b32009-05-10 06:55:39 +0000692#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
693 tl_assert(bm);
694#endif
bartd59bb0f2008-06-08 08:08:31 +0000695
bart7b706b32009-05-10 06:55:39 +0000696 bm2 = bm2_lookup(bm, address_msb(a));
697 return (bm2
698 && bm0_is_any_set(bm2->bm1.bm0_w,
699 address_lsb(a),
700 SCALED_SIZE(size)));
bartd59bb0f2008-06-08 08:08:31 +0000701}
702
703static __inline__
bart7e81a172008-06-09 19:50:51 +0000704Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm,
bart7b706b32009-05-10 06:55:39 +0000705 const Addr a, const SizeT size)
bartd59bb0f2008-06-08 08:08:31 +0000706{
bartbedfd232009-03-26 19:07:15 +0000707 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000708
bart7b706b32009-05-10 06:55:39 +0000709#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
710 tl_assert(bm);
711#endif
bartd59bb0f2008-06-08 08:08:31 +0000712
bart7b706b32009-05-10 06:55:39 +0000713 bm2 = bm2_lookup(bm, address_msb(a));
bartbedfd232009-03-26 19:07:15 +0000714 if (bm2)
715 {
bart7b706b32009-05-10 06:55:39 +0000716 if (bm0_is_any_set(bm2->bm1.bm0_r, address_lsb(a), SCALED_SIZE(size))
717 | bm0_is_any_set(bm2->bm1.bm0_w, address_lsb(a), SCALED_SIZE(size)))
bartbedfd232009-03-26 19:07:15 +0000718 {
719 return True;
720 }
721 }
722 return False;
bartd59bb0f2008-06-08 08:08:31 +0000723}
sewardjaf44c822007-11-25 14:01:38 +0000724
bart33e56c92008-03-24 06:41:30 +0000725#endif /* __DRD_BITMAP_H */