blob: 21bf7e10d8589f23d599adcc8ab334a8e8e5cbfb [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"
bart67cb4fb2010-09-02 14:43:50 +000034#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
35#include "pub_tool_libcassert.h"
36#endif
sewardjaf44c822007-11-25 14:01:38 +000037
38
bart7b706b32009-05-10 06:55:39 +000039/* Bitmap representation. A bitmap is a data structure in which two bits are
40 * reserved per 32 bit address: one bit that indicates that the data at the
41 * specified address has been read, and one bit that indicates that the data
42 * has been written to.
43 */
44
45/* Client addresses are split into bitfields as follows:
46 * ------------------------------------------------------
bart31b983d2010-02-21 14:52:59 +000047 * | Address MSB | Address LSB | Ignored bits |
bart7b706b32009-05-10 06:55:39 +000048 * ------------------------------------------------------
49 * | Address MSB | UWord MSB | UWord LSB | Ignored bits |
50 * ------------------------------------------------------
51 */
sewardjaf44c822007-11-25 14:01:38 +000052
53
sewardjaf44c822007-11-25 14:01:38 +000054
bart7b706b32009-05-10 06:55:39 +000055/* Address MSB / LSB split. */
sewardjaf44c822007-11-25 14:01:38 +000056
sewardjaf44c822007-11-25 14:01:38 +000057
bart7b706b32009-05-10 06:55:39 +000058/** Number of least significant address bits that are ignored. */
59#define ADDR_IGNORED_BITS 0
60#define ADDR_IGNORED_MASK ((1U << ADDR_IGNORED_BITS) - 1U)
61#define ADDR_GRANULARITY (1U << ADDR_IGNORED_BITS)
sewardjaf44c822007-11-25 14:01:38 +000062
bart8f822af2009-06-08 18:20:42 +000063/**
64 * Round argument a up to a multiple of (1 << ADDR_GRANULARITY), and next
65 * shift it right ADDR_GRANULARITY bits. The expression below is optimized
66 * for the case where a is a constant.
bart7b706b32009-05-10 06:55:39 +000067 */
68#define SCALED_SIZE(a) \
69 (((((a) - 1U) | ADDR_IGNORED_MASK) + 1U) >> ADDR_IGNORED_BITS)
sewardjaf44c822007-11-25 14:01:38 +000070
bart8f822af2009-06-08 18:20:42 +000071/**
72 * Number of bits assigned to the least significant component of an address.
bart7b706b32009-05-10 06:55:39 +000073 */
74#define ADDR_LSB_BITS 12
sewardjaf44c822007-11-25 14:01:38 +000075
bart8f822af2009-06-08 18:20:42 +000076/**
77 * Mask that has to be applied to an address of type Addr in order to
78 * compute the least significant part of an address split, after having
79 * shifted the address bits ADDR_GRANULARITY to the right.
bart7b706b32009-05-10 06:55:39 +000080 */
81#define ADDR_LSB_MASK (((UWord)1 << ADDR_LSB_BITS) - 1U)
82
83/** Compute least significant bits of an address of type Addr. */
84static __inline__
85UWord address_lsb(const Addr a)
86{ return (a >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK; }
87
88/**
89 * Compute the first address for which address_lsb() is equal to
90 * address_lsb(a).
91 */
92static __inline__
93Addr first_address_with_same_lsb(const Addr a)
94{
95 return ((a | ADDR_IGNORED_MASK) ^ ADDR_IGNORED_MASK);
96}
97
98/**
99 * Compute the first address for which address_lsb() is greater than
100 * address_lsb(a).
101 */
102static __inline__
103Addr first_address_with_higher_lsb(const Addr a)
104{
105 return ((a | ADDR_IGNORED_MASK) + 1U);
106}
107
108/** Compute most significant bits of an address of type Addr. */
109static __inline__
110UWord address_msb(const Addr a)
111{ return a >> (ADDR_LSB_BITS + ADDR_IGNORED_BITS); }
112
113static __inline__
114Addr first_address_with_higher_msb(const Addr a)
115{
116 return ((a | ((ADDR_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
117 + 1U);
118}
119
bart8f822af2009-06-08 18:20:42 +0000120/**
121 * Convert LSB and MSB back into an address.
bart7b706b32009-05-10 06:55:39 +0000122 *
bart8f822af2009-06-08 18:20:42 +0000123 * @note It is assumed that sizeof(Addr) == sizeof(UWord).
bart7b706b32009-05-10 06:55:39 +0000124 */
125static __inline__
126Addr make_address(const UWord a1, const UWord a0)
127{
128 return ((a1 << (ADDR_LSB_BITS + ADDR_IGNORED_BITS))
129 | (a0 << ADDR_IGNORED_BITS));
130}
131
132
133
134
135
bart8f822af2009-06-08 18:20:42 +0000136/** Number of bits that fit in a variable of type UWord. */
bart7b706b32009-05-10 06:55:39 +0000137#define BITS_PER_UWORD (8U * sizeof(UWord))
138
bart8f822af2009-06-08 18:20:42 +0000139/** Log2 of BITS_PER_UWORD. */
sewardj4cb6bf72010-01-01 18:31:41 +0000140#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm)
sewardjaf44c822007-11-25 14:01:38 +0000141#define BITS_PER_BITS_PER_UWORD 5
142#elif defined(VGA_amd64) || defined(VGA_ppc64)
143#define BITS_PER_BITS_PER_UWORD 6
144#else
145#error Unknown platform.
146#endif
147
bart8f822af2009-06-08 18:20:42 +0000148/** Number of UWord's needed to store one bit per address LSB. */
bart7b706b32009-05-10 06:55:39 +0000149#define BITMAP1_UWORD_COUNT (1U << (ADDR_LSB_BITS - BITS_PER_BITS_PER_UWORD))
sewardjaf44c822007-11-25 14:01:38 +0000150
bart8f822af2009-06-08 18:20:42 +0000151/**
152 * Mask that has to be applied to an (Addr >> ADDR_IGNORED_BITS) expression
153 * in order to compute the least significant part of an UWord.
bart7b706b32009-05-10 06:55:39 +0000154 */
155#define UWORD_LSB_MASK (((UWord)1 << BITS_PER_BITS_PER_UWORD) - 1)
sewardjaf44c822007-11-25 14:01:38 +0000156
bart8f822af2009-06-08 18:20:42 +0000157/**
158 * Compute index into bm0[] array.
bart7b706b32009-05-10 06:55:39 +0000159 *
bart8f822af2009-06-08 18:20:42 +0000160 * @param a Address shifted right ADDR_IGNORED_BITS bits.
bart7b706b32009-05-10 06:55:39 +0000161 */
162static __inline__
163UWord uword_msb(const UWord a)
164{
165#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
166 tl_assert(a < (1U << ADDR_LSB_BITS));
167#endif
168 return a >> BITS_PER_BITS_PER_UWORD;
169}
sewardjaf44c822007-11-25 14:01:38 +0000170
bart8f822af2009-06-08 18:20:42 +0000171/**
172 * Return the least significant bits.
bart7b706b32009-05-10 06:55:39 +0000173 *
bart8f822af2009-06-08 18:20:42 +0000174 * @param a Address shifted right ADDR_IGNORED_BITS bits.
bart7b706b32009-05-10 06:55:39 +0000175 */
176static __inline__
177UWord uword_lsb(const UWord a)
178{
179#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
180 tl_assert(a < (1U << ADDR_LSB_BITS));
181#endif
182 return a & UWORD_LSB_MASK;
183}
184
bart8f822af2009-06-08 18:20:42 +0000185/**
186 * Compute the highest address lower than a for which
187 * uword_lsb(address_lsb(a)) == 0.
bart7b706b32009-05-10 06:55:39 +0000188 *
bart8f822af2009-06-08 18:20:42 +0000189 * @param a Address.
bart7b706b32009-05-10 06:55:39 +0000190 */
191static __inline__
192Addr first_address_with_same_uword_lsb(const Addr a)
193{
194 return (a & (~UWORD_LSB_MASK << ADDR_IGNORED_BITS));
195}
196
197/**
198 * First address that will go in the UWord past the one 'a' goes in.
199 *
200 * @param a Address.
201 */
202static __inline__
203Addr first_address_with_higher_uword_msb(const Addr a)
204{
205 return ((a | ((UWORD_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
206 + 1);
207}
208
sewardjaf44c822007-11-25 14:01:38 +0000209
210
bart33e56c92008-03-24 06:41:30 +0000211/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +0000212
213static ULong s_bitmap2_creation_count;
214
215
bart0008f5b2008-03-22 17:07:39 +0000216
217/*********************************************************************/
218/* Functions for manipulating a struct bitmap1. */
219/*********************************************************************/
220
221
bart7b706b32009-05-10 06:55:39 +0000222/* Lowest level, corresponding to the lowest ADDR_LSB_BITS of an address. */
sewardjaf44c822007-11-25 14:01:38 +0000223struct bitmap1
224{
bartbedfd232009-03-26 19:07:15 +0000225 UWord bm0_r[BITMAP1_UWORD_COUNT];
226 UWord bm0_w[BITMAP1_UWORD_COUNT];
sewardjaf44c822007-11-25 14:01:38 +0000227};
228
bart7b706b32009-05-10 06:55:39 +0000229static __inline__ UWord bm0_mask(const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000230{
bart3c9989f2008-06-11 19:17:01 +0000231#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000232 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000233#endif
bart7b706b32009-05-10 06:55:39 +0000234 return ((UWord)1 << uword_lsb(a));
barta79df6e2008-03-14 17:07:51 +0000235}
236
bart7b706b32009-05-10 06:55:39 +0000237/** Set the bit corresponding to address a in bitmap bm0. */
238static __inline__ void bm0_set(UWord* bm0, const UWord a)
239{
240#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
241 tl_assert(address_msb(make_address(0, a)) == 0);
242#endif
243 bm0[uword_msb(a)] |= (UWord)1 << uword_lsb(a);
244}
245
246/**
247 * Set the bits corresponding to all of the addresses in range
248 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
249 * in bitmap bm0.
250 */
bartf8bc71d2008-03-15 11:42:34 +0000251static __inline__ void bm0_set_range(UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000252 const UWord a, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000253{
bart8b4b2ee2008-06-11 13:17:56 +0000254#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000255 tl_assert(size > 0);
bart7b706b32009-05-10 06:55:39 +0000256 tl_assert(address_msb(make_address(0, a)) == 0);
257 tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
258 tl_assert(uword_msb(a) == uword_msb(a + size - 1));
barta79df6e2008-03-14 17:07:51 +0000259#endif
bart7b706b32009-05-10 06:55:39 +0000260 bm0[uword_msb(a)]
261 |= (((UWord)1 << size) - 1) << uword_lsb(a);
sewardjaf44c822007-11-25 14:01:38 +0000262}
263
bart7b706b32009-05-10 06:55:39 +0000264/** Clear the bit corresponding to address a in bitmap bm0. */
265static __inline__ void bm0_clear(UWord* bm0, const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000266{
bart3c9989f2008-06-11 19:17:01 +0000267#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000268 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000269#endif
bart7b706b32009-05-10 06:55:39 +0000270 bm0[uword_msb(a)] &= ~((UWord)1 << uword_lsb(a));
sewardjaf44c822007-11-25 14:01:38 +0000271}
272
bart7b706b32009-05-10 06:55:39 +0000273/**
274 * Clear all of the addresses in range
275 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
276 * in bitmap bm0.
277 */
bart5955f332008-03-25 17:19:20 +0000278static __inline__ void bm0_clear_range(UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000279 const UWord a, const SizeT size)
bart5955f332008-03-25 17:19:20 +0000280{
bart8b4b2ee2008-06-11 13:17:56 +0000281#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000282 tl_assert(address_msb(make_address(0, a)) == 0);
283 tl_assert(size == 0 || address_msb(make_address(0, a + size - 1)) == 0);
284 tl_assert(size == 0 || uword_msb(a) == uword_msb(a + size - 1));
bart5955f332008-03-25 17:19:20 +0000285#endif
bart8c046732009-04-25 06:52:01 +0000286 /*
bart31b983d2010-02-21 14:52:59 +0000287 * Note: although the expression below yields a correct result even if
bart8c046732009-04-25 06:52:01 +0000288 * size == 0, do not touch bm0[] if size == 0 because this might otherwise
289 * cause an access of memory just past the end of the bm0[] array.
290 */
291 if (size > 0)
292 {
bart7b706b32009-05-10 06:55:39 +0000293 bm0[uword_msb(a)]
294 &= ~((((UWord)1 << size) - 1) << uword_lsb(a));
bart8c046732009-04-25 06:52:01 +0000295 }
bart5955f332008-03-25 17:19:20 +0000296}
297
bart7b706b32009-05-10 06:55:39 +0000298/** Test whether the bit corresponding to address a is set in bitmap bm0. */
299static __inline__ UWord bm0_is_set(const UWord* bm0, const UWord a)
sewardjaf44c822007-11-25 14:01:38 +0000300{
bart3c9989f2008-06-11 19:17:01 +0000301#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000302 tl_assert(address_msb(make_address(0, a)) == 0);
bart3c9989f2008-06-11 19:17:01 +0000303#endif
bart7b706b32009-05-10 06:55:39 +0000304 return (bm0[uword_msb(a)] & ((UWord)1 << uword_lsb(a)));
sewardjaf44c822007-11-25 14:01:38 +0000305}
306
bart7b706b32009-05-10 06:55:39 +0000307/**
308 * Return true if a bit corresponding to any of the addresses in range
309 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
310 * is set in bm0.
311 */
barta79df6e2008-03-14 17:07:51 +0000312static __inline__ UWord bm0_is_any_set(const UWord* bm0,
bart7b706b32009-05-10 06:55:39 +0000313 const Addr a, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000314{
bart8b4b2ee2008-06-11 13:17:56 +0000315#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000316 tl_assert(size > 0);
bart7b706b32009-05-10 06:55:39 +0000317 tl_assert(address_msb(make_address(0, a)) == 0);
318 tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
319 tl_assert(uword_msb(a) == uword_msb(a + size - 1));
barta79df6e2008-03-14 17:07:51 +0000320#endif
bart7b706b32009-05-10 06:55:39 +0000321 return (bm0[uword_msb(a)] & ((((UWord)1 << size) - 1) << uword_lsb(a)));
barta79df6e2008-03-14 17:07:51 +0000322}
sewardjaf44c822007-11-25 14:01:38 +0000323
bartadbdf142008-03-19 17:00:12 +0000324
bart0008f5b2008-03-22 17:07:39 +0000325
326/*********************************************************************/
327/* Functions for manipulating a struct bitmap. */
bartadbdf142008-03-19 17:00:12 +0000328/*********************************************************************/
329
330
bart33e56c92008-03-24 06:41:30 +0000331/* Second level bitmap. */
sewardjaf44c822007-11-25 14:01:38 +0000332struct bitmap2
333{
bart7b706b32009-05-10 06:55:39 +0000334 Addr addr; ///< address_msb(...)
bart8f822af2009-06-08 18:20:42 +0000335 Bool recalc;
bartbedfd232009-03-26 19:07:15 +0000336 struct bitmap1 bm1;
sewardjaf44c822007-11-25 14:01:38 +0000337};
338
bart33e56c92008-03-24 06:41:30 +0000339
bart7b706b32009-05-10 06:55:39 +0000340static void bm2_clear(struct bitmap2* const bm2);
341static __inline__
342struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1);
343
344
bartf647d342008-03-24 19:12:12 +0000345
bart8f822af2009-06-08 18:20:42 +0000346/**
347 * Rotate elements cache[0..n-1] such that the element at position n-1 is
348 * moved to position 0. This allows to speed up future cache lookups.
bart7e81a172008-06-09 19:50:51 +0000349 */
350static __inline__
351void bm_cache_rotate(struct bm_cache_elem cache[], const int n)
352{
bart45af5ea2008-06-12 06:04:59 +0000353#if 0
bartbedfd232009-03-26 19:07:15 +0000354 struct bm_cache_elem t;
bart7e81a172008-06-09 19:50:51 +0000355
bartbedfd232009-03-26 19:07:15 +0000356 tl_assert(2 <= n && n <= 8);
bartea2fa4c2008-06-10 06:32:49 +0000357
bartbedfd232009-03-26 19:07:15 +0000358 t = cache[0];
359 if (n > 1)
360 cache[0] = cache[1];
361 if (n > 2)
362 cache[1] = cache[2];
363 if (n > 3)
364 cache[2] = cache[3];
365 if (n > 4)
366 cache[3] = cache[4];
367 if (n > 5)
368 cache[4] = cache[5];
369 if (n > 6)
370 cache[5] = cache[6];
371 if (n > 7)
372 cache[6] = cache[7];
373 cache[n - 1] = t;
bartea2fa4c2008-06-10 06:32:49 +0000374#endif
bart7e81a172008-06-09 19:50:51 +0000375}
bartf647d342008-03-24 19:12:12 +0000376
bartf647d342008-03-24 19:12:12 +0000377static __inline__
bart7e81a172008-06-09 19:50:51 +0000378Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1,
bartf29205e2008-03-25 18:51:06 +0000379 struct bitmap2** bm2)
bart33e56c92008-03-24 06:41:30 +0000380{
bart8b4b2ee2008-06-11 13:17:56 +0000381#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000382 tl_assert(bm);
383 tl_assert(bm2);
bart7e81a172008-06-09 19:50:51 +0000384#endif
bart33e56c92008-03-24 06:41:30 +0000385
bart8f822af2009-06-08 18:20:42 +0000386#if DRD_BITMAP_N_CACHE_ELEM > 8
bart33e56c92008-03-24 06:41:30 +0000387#error Please update the code below.
388#endif
bart8f822af2009-06-08 18:20:42 +0000389#if DRD_BITMAP_N_CACHE_ELEM >= 1
bartbedfd232009-03-26 19:07:15 +0000390 if (a1 == bm->cache[0].a1)
391 {
392 *bm2 = bm->cache[0].bm2;
393 return True;
394 }
bart33e56c92008-03-24 06:41:30 +0000395#endif
bart8f822af2009-06-08 18:20:42 +0000396#if DRD_BITMAP_N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000397 if (a1 == bm->cache[1].a1)
398 {
399 *bm2 = bm->cache[1].bm2;
400 return True;
401 }
bart33e56c92008-03-24 06:41:30 +0000402#endif
bart8f822af2009-06-08 18:20:42 +0000403#if DRD_BITMAP_N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000404 if (a1 == bm->cache[2].a1)
405 {
406 *bm2 = bm->cache[2].bm2;
407 bm_cache_rotate(bm->cache, 3);
408 return True;
409 }
bart33e56c92008-03-24 06:41:30 +0000410#endif
bart8f822af2009-06-08 18:20:42 +0000411#if DRD_BITMAP_N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000412 if (a1 == bm->cache[3].a1)
413 {
414 *bm2 = bm->cache[3].bm2;
415 bm_cache_rotate(bm->cache, 4);
416 return True;
417 }
bart33e56c92008-03-24 06:41:30 +0000418#endif
bart8f822af2009-06-08 18:20:42 +0000419#if DRD_BITMAP_N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000420 if (a1 == bm->cache[4].a1)
421 {
422 *bm2 = bm->cache[4].bm2;
423 bm_cache_rotate(bm->cache, 5);
424 return True;
425 }
bart33e56c92008-03-24 06:41:30 +0000426#endif
bart8f822af2009-06-08 18:20:42 +0000427#if DRD_BITMAP_N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000428 if (a1 == bm->cache[5].a1)
429 {
430 *bm2 = bm->cache[5].bm2;
431 bm_cache_rotate(bm->cache, 6);
432 return True;
433 }
bart33e56c92008-03-24 06:41:30 +0000434#endif
bart8f822af2009-06-08 18:20:42 +0000435#if DRD_BITMAP_N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000436 if (a1 == bm->cache[6].a1)
437 {
438 *bm2 = bm->cache[6].bm2;
439 bm_cache_rotate(bm->cache, 7);
440 return True;
441 }
bart33e56c92008-03-24 06:41:30 +0000442#endif
bart8f822af2009-06-08 18:20:42 +0000443#if DRD_BITMAP_N_CACHE_ELEM >= 8
bartbedfd232009-03-26 19:07:15 +0000444 if (a1 == bm->cache[7].a1)
445 {
446 *bm2 = bm->cache[7].bm2;
447 bm_cache_rotate(bm->cache, 8);
448 return True;
449 }
bart33e56c92008-03-24 06:41:30 +0000450#endif
bartbedfd232009-03-26 19:07:15 +0000451 *bm2 = 0;
452 return False;
bart33e56c92008-03-24 06:41:30 +0000453}
454
455static __inline__
456void bm_update_cache(struct bitmap* const bm,
457 const UWord a1,
458 struct bitmap2* const bm2)
459{
bart3c9989f2008-06-11 19:17:01 +0000460#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000461 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000462#endif
bart33e56c92008-03-24 06:41:30 +0000463
bart8f822af2009-06-08 18:20:42 +0000464#if DRD_BITMAP_N_CACHE_ELEM > 8
bart33e56c92008-03-24 06:41:30 +0000465#error Please update the code below.
466#endif
bart8f822af2009-06-08 18:20:42 +0000467#if DRD_BITMAP_N_CACHE_ELEM >= 8
bartbedfd232009-03-26 19:07:15 +0000468 bm->cache[7] = bm->cache[6];
bart33e56c92008-03-24 06:41:30 +0000469#endif
bart8f822af2009-06-08 18:20:42 +0000470#if DRD_BITMAP_N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000471 bm->cache[6] = bm->cache[5];
bart33e56c92008-03-24 06:41:30 +0000472#endif
bart8f822af2009-06-08 18:20:42 +0000473#if DRD_BITMAP_N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000474 bm->cache[5] = bm->cache[4];
bart33e56c92008-03-24 06:41:30 +0000475#endif
bart8f822af2009-06-08 18:20:42 +0000476#if DRD_BITMAP_N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000477 bm->cache[4] = bm->cache[3];
bart33e56c92008-03-24 06:41:30 +0000478#endif
bart8f822af2009-06-08 18:20:42 +0000479#if DRD_BITMAP_N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000480 bm->cache[3] = bm->cache[2];
bart33e56c92008-03-24 06:41:30 +0000481#endif
bart8f822af2009-06-08 18:20:42 +0000482#if DRD_BITMAP_N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000483 bm->cache[2] = bm->cache[1];
bart33e56c92008-03-24 06:41:30 +0000484#endif
bart8f822af2009-06-08 18:20:42 +0000485#if DRD_BITMAP_N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000486 bm->cache[1] = bm->cache[0];
bart33e56c92008-03-24 06:41:30 +0000487#endif
bartbedfd232009-03-26 19:07:15 +0000488 bm->cache[0].a1 = a1;
489 bm->cache[0].bm2 = bm2;
bart33e56c92008-03-24 06:41:30 +0000490}
491
bart8f822af2009-06-08 18:20:42 +0000492/**
493 * Look up the address a1 in bitmap bm and return a pointer to a potentially
494 * shared second level bitmap. The bitmap where the returned pointer points
495 * at may not be modified by the caller.
bartf647d342008-03-24 19:12:12 +0000496 *
bart8f822af2009-06-08 18:20:42 +0000497 * @param a1 client address shifted right by ADDR_LSB_BITS.
498 * @param bm bitmap pointer.
bart0008f5b2008-03-22 17:07:39 +0000499 */
sewardjaf44c822007-11-25 14:01:38 +0000500static __inline__
bart7e81a172008-06-09 19:50:51 +0000501const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000502{
bart7b706b32009-05-10 06:55:39 +0000503 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000504
bart3c9989f2008-06-11 19:17:01 +0000505#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000506 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000507#endif
bart7b706b32009-05-10 06:55:39 +0000508
bartbedfd232009-03-26 19:07:15 +0000509 if (! bm_cache_lookup(bm, a1, &bm2))
510 {
bart7b706b32009-05-10 06:55:39 +0000511 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
512 bm_update_cache(bm, a1, bm2);
bartbedfd232009-03-26 19:07:15 +0000513 }
514 return bm2;
bartf647d342008-03-24 19:12:12 +0000515}
516
bart8f822af2009-06-08 18:20:42 +0000517/**
518 * Look up the address a1 in bitmap bm and return a pointer to a second
519 * level bitmap that is not shared and hence may be modified.
bartf647d342008-03-24 19:12:12 +0000520 *
bart8f822af2009-06-08 18:20:42 +0000521 * @param a1 client address shifted right by ADDR_LSB_BITS.
522 * @param bm bitmap pointer.
bartf647d342008-03-24 19:12:12 +0000523 */
524static __inline__
525struct bitmap2*
bart7e81a172008-06-09 19:50:51 +0000526bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1)
bartf647d342008-03-24 19:12:12 +0000527{
bartbedfd232009-03-26 19:07:15 +0000528 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000529
bart3c9989f2008-06-11 19:17:01 +0000530#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart7b706b32009-05-10 06:55:39 +0000531 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000532#endif
bartf647d342008-03-24 19:12:12 +0000533
bart7b706b32009-05-10 06:55:39 +0000534 if (! bm_cache_lookup(bm, a1, &bm2))
bartbedfd232009-03-26 19:07:15 +0000535 {
bart7b706b32009-05-10 06:55:39 +0000536 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
bartbedfd232009-03-26 19:07:15 +0000537 }
bartf647d342008-03-24 19:12:12 +0000538
bartbedfd232009-03-26 19:07:15 +0000539 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000540}
541
bart6584b692009-06-21 10:11:15 +0000542/** Clear the content of the second-level bitmap. */
543static __inline__
544void bm2_clear(struct bitmap2* const bm2)
545{
546#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
547 tl_assert(bm2);
548#endif
549 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
550}
551
bart8f822af2009-06-08 18:20:42 +0000552/**
553 * Insert an uninitialized second level bitmap for the address a1.
bartf647d342008-03-24 19:12:12 +0000554 *
bart8f822af2009-06-08 18:20:42 +0000555 * @param bm bitmap pointer.
556 * @param a1 client address shifted right by ADDR_LSB_BITS.
557 *
558 * @note bitmap2::recalc isn't initialized here on purpose.
bartf647d342008-03-24 19:12:12 +0000559 */
sewardjaf44c822007-11-25 14:01:38 +0000560static __inline__
bart7e81a172008-06-09 19:50:51 +0000561struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000562{
bartbedfd232009-03-26 19:07:15 +0000563 struct bitmap2* bm2;
bart33e56c92008-03-24 06:41:30 +0000564
bart7b706b32009-05-10 06:55:39 +0000565#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
566 tl_assert(bm);
567#endif
568
569 s_bitmap2_creation_count++;
570
571 bm2 = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2));
572 bm2->addr = a1;
573 VG_(OSetGen_Insert)(bm->oset, bm2);
574
575 bm_update_cache(bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000576
bartbedfd232009-03-26 19:07:15 +0000577 return bm2;
bartf647d342008-03-24 19:12:12 +0000578}
579
bartf647d342008-03-24 19:12:12 +0000580static __inline__
bart7b706b32009-05-10 06:55:39 +0000581struct bitmap2* bm2_insert_copy(struct bitmap* const bm,
582 struct bitmap2* const bm2)
bartf647d342008-03-24 19:12:12 +0000583{
bart7b706b32009-05-10 06:55:39 +0000584 struct bitmap2* bm2_copy;
bartf647d342008-03-24 19:12:12 +0000585
bart7b706b32009-05-10 06:55:39 +0000586 bm2_copy = bm2_insert(bm, bm2->addr);
587 VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1));
588 return bm2_copy;
sewardjaf44c822007-11-25 14:01:38 +0000589}
590
bart8f822af2009-06-08 18:20:42 +0000591/**
592 * Look up the address a1 in bitmap bm, and insert it if not found.
593 * The returned second level bitmap may not be modified.
bart0008f5b2008-03-22 17:07:39 +0000594 *
bart8f822af2009-06-08 18:20:42 +0000595 * @param bm bitmap pointer.
596 * @param a1 client address shifted right by ADDR_LSB_BITS.
bart0008f5b2008-03-22 17:07:39 +0000597 */
sewardjaf44c822007-11-25 14:01:38 +0000598static __inline__
bart7e81a172008-06-09 19:50:51 +0000599struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000600{
bartbedfd232009-03-26 19:07:15 +0000601 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000602
bart3c9989f2008-06-11 19:17:01 +0000603#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000604 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000605#endif
bart7b706b32009-05-10 06:55:39 +0000606
bartbedfd232009-03-26 19:07:15 +0000607 if (bm_cache_lookup(bm, a1, &bm2))
608 {
609 if (bm2 == 0)
610 {
611 bm2 = bm2_insert(bm, a1);
bart7b706b32009-05-10 06:55:39 +0000612 bm2_clear(bm2);
bartbedfd232009-03-26 19:07:15 +0000613 }
614 }
615 else
616 {
bart7b706b32009-05-10 06:55:39 +0000617 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
618 if (! bm2)
bartbedfd232009-03-26 19:07:15 +0000619 {
620 bm2 = bm2_insert(bm, a1);
bart7b706b32009-05-10 06:55:39 +0000621 bm2_clear(bm2);
bartbedfd232009-03-26 19:07:15 +0000622 }
bart7b706b32009-05-10 06:55:39 +0000623 bm_update_cache(bm, a1, bm2);
bartbedfd232009-03-26 19:07:15 +0000624 }
625 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000626}
627
bart8f822af2009-06-08 18:20:42 +0000628/**
629 * Look up the address a1 in bitmap bm, and insert it if not found.
630 * The returned second level bitmap may be modified.
bartf647d342008-03-24 19:12:12 +0000631 *
bart8f822af2009-06-08 18:20:42 +0000632 * @param a1 client address shifted right by ADDR_LSB_BITS.
633 * @param bm bitmap pointer.
bartf647d342008-03-24 19:12:12 +0000634 */
635static __inline__
636struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
637 const UWord a1)
638{
bart7b706b32009-05-10 06:55:39 +0000639 return bm2_lookup_or_insert(bm, a1);
bartf647d342008-03-24 19:12:12 +0000640}
641
bartd59bb0f2008-06-08 08:08:31 +0000642static __inline__
bart8f822af2009-06-08 18:20:42 +0000643void bm2_remove(struct bitmap* const bm, const UWord a1)
644{
645 struct bitmap2* bm2;
646
647#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
648 tl_assert(bm);
649#endif
650
651 bm2 = VG_(OSetGen_Remove)(bm->oset, &a1);
652 VG_(OSetGen_FreeNode)(bm->oset, bm2);
653
654 bm_update_cache(bm, a1, NULL);
655}
656
657static __inline__
bartd59bb0f2008-06-08 08:08:31 +0000658void bm_access_aligned_load(struct bitmap* const bm,
659 const Addr a1, const SizeT size)
660{
bartbedfd232009-03-26 19:07:15 +0000661 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000662
bart7b706b32009-05-10 06:55:39 +0000663#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
664 tl_assert(bm);
665#endif
666
667 bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
668 bm0_set_range(bm2->bm1.bm0_r,
669 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
670 SCALED_SIZE(size));
bartd59bb0f2008-06-08 08:08:31 +0000671}
672
673static __inline__
674void bm_access_aligned_store(struct bitmap* const bm,
675 const Addr a1, const SizeT size)
676{
bartbedfd232009-03-26 19:07:15 +0000677 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000678
bart7b706b32009-05-10 06:55:39 +0000679#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
680 tl_assert(bm);
681#endif
682
683 bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
684 bm0_set_range(bm2->bm1.bm0_w,
685 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
686 SCALED_SIZE(size));
bartd59bb0f2008-06-08 08:08:31 +0000687}
688
689static __inline__
bart7e81a172008-06-09 19:50:51 +0000690Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm,
bart7b706b32009-05-10 06:55:39 +0000691 const Addr a, const SizeT size)
bartd59bb0f2008-06-08 08:08:31 +0000692{
bartbedfd232009-03-26 19:07:15 +0000693 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000694
bart7b706b32009-05-10 06:55:39 +0000695#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
696 tl_assert(bm);
697#endif
bartd59bb0f2008-06-08 08:08:31 +0000698
bart7b706b32009-05-10 06:55:39 +0000699 bm2 = bm2_lookup(bm, address_msb(a));
700 return (bm2
701 && bm0_is_any_set(bm2->bm1.bm0_w,
702 address_lsb(a),
703 SCALED_SIZE(size)));
bartd59bb0f2008-06-08 08:08:31 +0000704}
705
706static __inline__
bart7e81a172008-06-09 19:50:51 +0000707Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm,
bart7b706b32009-05-10 06:55:39 +0000708 const Addr a, const SizeT size)
bartd59bb0f2008-06-08 08:08:31 +0000709{
bartbedfd232009-03-26 19:07:15 +0000710 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000711
bart7b706b32009-05-10 06:55:39 +0000712#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
713 tl_assert(bm);
714#endif
bartd59bb0f2008-06-08 08:08:31 +0000715
bart7b706b32009-05-10 06:55:39 +0000716 bm2 = bm2_lookup(bm, address_msb(a));
bartbedfd232009-03-26 19:07:15 +0000717 if (bm2)
718 {
bart7b706b32009-05-10 06:55:39 +0000719 if (bm0_is_any_set(bm2->bm1.bm0_r, address_lsb(a), SCALED_SIZE(size))
720 | bm0_is_any_set(bm2->bm1.bm0_w, address_lsb(a), SCALED_SIZE(size)))
bartbedfd232009-03-26 19:07:15 +0000721 {
722 return True;
723 }
724 }
725 return False;
bartd59bb0f2008-06-08 08:08:31 +0000726}
sewardjaf44c822007-11-25 14:01:38 +0000727
bart33e56c92008-03-24 06:41:30 +0000728#endif /* __DRD_BITMAP_H */