2 This file is part of drd, a thread error detector.
4 Copyright (C) 2006-2017 Bart Van Assche <bvanassche@acm.org>.
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.
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.
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
21 The GNU General Public License is contained in the file COPYING.
25 #ifndef __DRD_BITMAP_H
26 #define __DRD_BITMAP_H
29 #include "pub_drd_bitmap.h"
30 #include "pub_tool_basics.h"
31 #include "pub_tool_oset.h"
32 #include "pub_tool_libcbase.h"
33 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
34 #include "pub_tool_libcassert.h"
38 /* 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.
44 /* Client addresses are split into bitfields as follows:
45 * ------------------------------------------------------
46 * | Address MSB | Address LSB | Ignored bits |
47 * ------------------------------------------------------
48 * | Address MSB | UWord MSB | UWord LSB | Ignored bits |
49 * ------------------------------------------------------
54 /* Address MSB / LSB split. */
57 /** 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)
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.
67 #define SCALED_SIZE(a) \
68 (((((a) - 1U) | ADDR_IGNORED_MASK) + 1U) >> ADDR_IGNORED_BITS)
71 * Number of bits assigned to the least significant component of an address.
73 #define ADDR_LSB_BITS 12
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.
80 #define ADDR_LSB_MASK (((UWord)1 << ADDR_LSB_BITS) - 1U)
82 /** Compute least significant bits of an address of type Addr. */
84 UWord
address_lsb(const Addr a
)
85 { return (a
>> ADDR_IGNORED_BITS
) & ADDR_LSB_MASK
; }
88 * Compute the first address for which address_lsb() is equal to
92 Addr
first_address_with_same_lsb(const Addr a
)
94 return ((a
| ADDR_IGNORED_MASK
) ^ ADDR_IGNORED_MASK
);
98 * Compute the first address for which address_lsb() is greater than
102 Addr
first_address_with_higher_lsb(const Addr a
)
104 return ((a
| ADDR_IGNORED_MASK
) + 1U);
107 /** Compute most significant bits of an address of type Addr. */
109 UWord
address_msb(const Addr a
)
110 { return a
>> (ADDR_LSB_BITS
+ ADDR_IGNORED_BITS
); }
113 Addr
first_address_with_higher_msb(const Addr a
)
115 return ((a
| ((ADDR_LSB_MASK
<< ADDR_IGNORED_BITS
) | ADDR_IGNORED_MASK
))
120 * Convert LSB and MSB back into an address.
122 * @note It is assumed that sizeof(Addr) == sizeof(UWord).
125 Addr
make_address(const UWord a1
, const UWord a0
)
127 return ((a1
<< (ADDR_LSB_BITS
+ ADDR_IGNORED_BITS
))
128 | (a0
<< ADDR_IGNORED_BITS
));
135 /** Number of bits that fit in a variable of type UWord. */
136 #define BITS_PER_UWORD (8U * sizeof(UWord))
138 /** Log2 of BITS_PER_UWORD. */
139 #if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) \
140 || defined(VGA_mips32) || (defined(VGA_mips64) && defined(VGABI_N32))
141 #define BITS_PER_BITS_PER_UWORD 5
142 #elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
143 || defined(VGA_s390x) || (defined(VGA_mips64) && !defined(VGABI_N32)) \
144 || defined(VGA_arm64) || defined(VGA_tilegx)
145 #define BITS_PER_BITS_PER_UWORD 6
147 #error Unknown platform.
150 /** Number of UWord's needed to store one bit per address LSB. */
151 #define BITMAP1_UWORD_COUNT (1U << (ADDR_LSB_BITS - BITS_PER_BITS_PER_UWORD))
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.
157 #define UWORD_LSB_MASK (((UWord)1 << BITS_PER_BITS_PER_UWORD) - 1)
160 * Compute index into bm0[] array.
162 * @param a Address shifted right ADDR_IGNORED_BITS bits.
165 UWord
uword_msb(const UWord a
)
167 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
168 tl_assert(a
< (1U << ADDR_LSB_BITS
));
170 return a
>> BITS_PER_BITS_PER_UWORD
;
174 * Return the least significant bits.
176 * @param a Address shifted right ADDR_IGNORED_BITS bits.
179 UWord
uword_lsb(const UWord a
)
181 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
182 tl_assert(a
< (1U << ADDR_LSB_BITS
));
184 return a
& UWORD_LSB_MASK
;
188 * Compute the highest address lower than a for which
189 * uword_lsb(address_lsb(a)) == 0.
194 Addr
first_address_with_same_uword_lsb(const Addr a
)
196 return (a
& (~UWORD_LSB_MASK
<< ADDR_IGNORED_BITS
));
200 * First address that will go in the UWord past the one 'a' goes in.
205 Addr
first_address_with_higher_uword_msb(const Addr a
)
207 return ((a
| ((UWORD_LSB_MASK
<< ADDR_IGNORED_BITS
) | ADDR_IGNORED_MASK
))
213 /* Local variables. */
215 static ULong s_bitmap2_creation_count
;
219 /*********************************************************************/
220 /* Functions for manipulating a struct bitmap1. */
221 /*********************************************************************/
224 /* Lowest level, corresponding to the lowest ADDR_LSB_BITS of an address. */
227 UWord bm0_r
[BITMAP1_UWORD_COUNT
];
228 UWord bm0_w
[BITMAP1_UWORD_COUNT
];
231 static __inline__ UWord
bm0_mask(const UWord a
)
233 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
234 tl_assert(address_msb(make_address(0, a
)) == 0);
236 return ((UWord
)1 << uword_lsb(a
));
239 /** Set the bit corresponding to address a in bitmap bm0. */
240 static __inline__
void bm0_set(UWord
* bm0
, const UWord a
)
242 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
243 tl_assert(address_msb(make_address(0, a
)) == 0);
245 bm0
[uword_msb(a
)] |= (UWord
)1 << uword_lsb(a
);
249 * Set the bits corresponding to all of the addresses in range
250 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
253 static __inline__
void bm0_set_range(UWord
* bm0
,
254 const UWord a
, const SizeT size
)
256 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
258 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));
263 |= (((UWord
)1 << size
) - 1) << uword_lsb(a
);
266 /** Clear the bit corresponding to address a in bitmap bm0. */
267 static __inline__
void bm0_clear(UWord
* bm0
, const UWord a
)
269 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
270 tl_assert(address_msb(make_address(0, a
)) == 0);
272 bm0
[uword_msb(a
)] &= ~((UWord
)1 << uword_lsb(a
));
276 * Clear all of the addresses in range
277 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
280 static __inline__
void bm0_clear_range(UWord
* bm0
,
281 const UWord a
, const SizeT size
)
283 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
284 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));
289 * Note: although the expression below yields a correct result even if
290 * 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.
296 &= ~((((UWord
)1 << size
) - 1) << uword_lsb(a
));
300 /** Test whether the bit corresponding to address a is set in bitmap bm0. */
301 static __inline__ UWord
bm0_is_set(const UWord
* bm0
, const UWord a
)
303 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
304 tl_assert(address_msb(make_address(0, a
)) == 0);
306 return (bm0
[uword_msb(a
)] & ((UWord
)1 << uword_lsb(a
)));
310 * Return true if a bit corresponding to any of the addresses in range
311 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
314 static __inline__ UWord
bm0_is_any_set(const UWord
* bm0
,
315 const Addr a
, const SizeT size
)
317 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
319 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));
323 return (bm0
[uword_msb(a
)] & ((((UWord
)1 << size
) - 1) << uword_lsb(a
)));
328 /*********************************************************************/
329 /* Functions for manipulating a struct bitmap. */
330 /*********************************************************************/
333 /* Second level bitmap. */
336 Addr addr
; ///< address_msb(...)
342 static void bm2_clear(struct bitmap2
* const bm2
);
344 struct bitmap2
* bm2_insert(struct bitmap
* const bm
, const UWord a1
);
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.
353 void bm_cache_rotate(struct bm_cache_elem cache
[], const int n
)
356 struct bm_cache_elem t
;
358 tl_assert(2 <= n
&& n
<= 8);
380 Bool
bm_cache_lookup(struct bitmap
* const bm
, const UWord a1
,
381 struct bitmap2
** bm2
)
383 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
388 #if DRD_BITMAP_N_CACHE_ELEM > 8
389 #error Please update the code below.
391 #if DRD_BITMAP_N_CACHE_ELEM >= 1
392 if (a1
== bm
->cache
[0].a1
)
394 *bm2
= bm
->cache
[0].bm2
;
398 #if DRD_BITMAP_N_CACHE_ELEM >= 2
399 if (a1
== bm
->cache
[1].a1
)
401 *bm2
= bm
->cache
[1].bm2
;
405 #if DRD_BITMAP_N_CACHE_ELEM >= 3
406 if (a1
== bm
->cache
[2].a1
)
408 *bm2
= bm
->cache
[2].bm2
;
409 bm_cache_rotate(bm
->cache
, 3);
413 #if DRD_BITMAP_N_CACHE_ELEM >= 4
414 if (a1
== bm
->cache
[3].a1
)
416 *bm2
= bm
->cache
[3].bm2
;
417 bm_cache_rotate(bm
->cache
, 4);
421 #if DRD_BITMAP_N_CACHE_ELEM >= 5
422 if (a1
== bm
->cache
[4].a1
)
424 *bm2
= bm
->cache
[4].bm2
;
425 bm_cache_rotate(bm
->cache
, 5);
429 #if DRD_BITMAP_N_CACHE_ELEM >= 6
430 if (a1
== bm
->cache
[5].a1
)
432 *bm2
= bm
->cache
[5].bm2
;
433 bm_cache_rotate(bm
->cache
, 6);
437 #if DRD_BITMAP_N_CACHE_ELEM >= 7
438 if (a1
== bm
->cache
[6].a1
)
440 *bm2
= bm
->cache
[6].bm2
;
441 bm_cache_rotate(bm
->cache
, 7);
445 #if DRD_BITMAP_N_CACHE_ELEM >= 8
446 if (a1
== bm
->cache
[7].a1
)
448 *bm2
= bm
->cache
[7].bm2
;
449 bm_cache_rotate(bm
->cache
, 8);
458 void bm_update_cache(struct bitmap
* const bm
,
460 struct bitmap2
* const bm2
)
462 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
466 #if DRD_BITMAP_N_CACHE_ELEM > 8
467 #error Please update the code below.
469 #if DRD_BITMAP_N_CACHE_ELEM >= 8
470 bm
->cache
[7] = bm
->cache
[6];
472 #if DRD_BITMAP_N_CACHE_ELEM >= 7
473 bm
->cache
[6] = bm
->cache
[5];
475 #if DRD_BITMAP_N_CACHE_ELEM >= 6
476 bm
->cache
[5] = bm
->cache
[4];
478 #if DRD_BITMAP_N_CACHE_ELEM >= 5
479 bm
->cache
[4] = bm
->cache
[3];
481 #if DRD_BITMAP_N_CACHE_ELEM >= 4
482 bm
->cache
[3] = bm
->cache
[2];
484 #if DRD_BITMAP_N_CACHE_ELEM >= 3
485 bm
->cache
[2] = bm
->cache
[1];
487 #if DRD_BITMAP_N_CACHE_ELEM >= 2
488 bm
->cache
[1] = bm
->cache
[0];
490 bm
->cache
[0].a1
= a1
;
491 bm
->cache
[0].bm2
= bm2
;
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.
499 * @param a1 client address shifted right by ADDR_LSB_BITS.
500 * @param bm bitmap pointer.
503 const struct bitmap2
* bm2_lookup(struct bitmap
* const bm
, const UWord a1
)
507 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
511 if (! bm_cache_lookup(bm
, a1
, &bm2
))
513 bm2
= VG_(OSetGen_Lookup
)(bm
->oset
, &a1
);
514 bm_update_cache(bm
, a1
, bm2
);
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.
523 * @param a1 client address shifted right by ADDR_LSB_BITS.
524 * @param bm bitmap pointer.
528 bm2_lookup_exclusive(struct bitmap
* const bm
, const UWord a1
)
532 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
536 if (! bm_cache_lookup(bm
, a1
, &bm2
))
538 bm2
= VG_(OSetGen_Lookup
)(bm
->oset
, &a1
);
544 /** Clear the content of the second-level bitmap. */
546 void bm2_clear(struct bitmap2
* const bm2
)
548 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
551 VG_(memset
)(&bm2
->bm1
, 0, sizeof(bm2
->bm1
));
555 * Insert an uninitialized second level bitmap for the address a1.
557 * @param bm bitmap pointer.
558 * @param a1 client address shifted right by ADDR_LSB_BITS.
560 * @note bitmap2::recalc isn't initialized here on purpose.
563 struct bitmap2
* bm2_insert(struct bitmap
* const bm
, const UWord a1
)
567 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
571 s_bitmap2_creation_count
++;
573 bm2
= VG_(OSetGen_AllocNode
)(bm
->oset
, sizeof(*bm2
));
575 VG_(OSetGen_Insert
)(bm
->oset
, bm2
);
577 bm_update_cache(bm
, a1
, bm2
);
583 struct bitmap2
* bm2_insert_copy(struct bitmap
* const bm
,
584 struct bitmap2
* const bm2
)
586 struct bitmap2
* bm2_copy
;
588 bm2_copy
= bm2_insert(bm
, bm2
->addr
);
589 VG_(memcpy
)(&bm2_copy
->bm1
, &bm2
->bm1
, sizeof(bm2
->bm1
));
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.
597 * @param bm bitmap pointer.
598 * @param a1 client address shifted right by ADDR_LSB_BITS.
601 struct bitmap2
* bm2_lookup_or_insert(struct bitmap
* const bm
, const UWord a1
)
605 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
609 if (bm_cache_lookup(bm
, a1
, &bm2
))
613 bm2
= bm2_insert(bm
, a1
);
619 bm2
= VG_(OSetGen_Lookup
)(bm
->oset
, &a1
);
622 bm2
= bm2_insert(bm
, a1
);
625 bm_update_cache(bm
, a1
, bm2
);
631 * Look up the address a1 in bitmap bm, and insert it if not found.
632 * The returned second level bitmap may be modified.
634 * @param a1 client address shifted right by ADDR_LSB_BITS.
635 * @param bm bitmap pointer.
638 struct bitmap2
* bm2_lookup_or_insert_exclusive(struct bitmap
* const bm
,
641 return bm2_lookup_or_insert(bm
, a1
);
645 void bm2_remove(struct bitmap
* const bm
, const UWord a1
)
649 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
653 bm2
= VG_(OSetGen_Remove
)(bm
->oset
, &a1
);
654 VG_(OSetGen_FreeNode
)(bm
->oset
, bm2
);
656 bm_update_cache(bm
, a1
, NULL
);
660 void bm_access_aligned_load(struct bitmap
* const bm
,
661 const Addr a1
, const SizeT size
)
665 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
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
,
676 void bm_access_aligned_store(struct bitmap
* const bm
,
677 const Addr a1
, const SizeT size
)
681 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
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
,
692 Bool
bm_aligned_load_has_conflict_with(struct bitmap
* const bm
,
693 const Addr a
, const SizeT size
)
695 const struct bitmap2
* bm2
;
697 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
701 bm2
= bm2_lookup(bm
, address_msb(a
));
703 && bm0_is_any_set(bm2
->bm1
.bm0_w
,
709 Bool
bm_aligned_store_has_conflict_with(struct bitmap
* const bm
,
710 const Addr a
, const SizeT size
)
712 const struct bitmap2
* bm2
;
714 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
718 bm2
= bm2_lookup(bm
, address_msb(a
));
721 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
)))
730 #endif /* __DRD_BITMAP_H */