1 /* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */
3 This file is part of drd, a thread error detector.
5 Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
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.
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.
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
22 The GNU General Public License is contained in the file COPYING.
26 #ifndef __DRD_BITMAP_H
27 #define __DRD_BITMAP_H
30 #include "pub_drd_bitmap.h"
31 #include "pub_tool_basics.h"
32 #include "pub_tool_oset.h"
33 #include "pub_tool_libcbase.h"
34 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
35 #include "pub_tool_libcassert.h"
39 /* 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.
45 /* Client addresses are split into bitfields as follows:
46 * ------------------------------------------------------
47 * | Address MSB | Address LSB | Ignored bits |
48 * ------------------------------------------------------
49 * | Address MSB | UWord MSB | UWord LSB | Ignored bits |
50 * ------------------------------------------------------
55 /* Address MSB / LSB split. */
58 /** 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)
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.
68 #define SCALED_SIZE(a) \
69 (((((a) - 1U) | ADDR_IGNORED_MASK) + 1U) >> ADDR_IGNORED_BITS)
72 * Number of bits assigned to the least significant component of an address.
74 #define ADDR_LSB_BITS 12
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.
81 #define ADDR_LSB_MASK (((UWord)1 << ADDR_LSB_BITS) - 1U)
83 /** Compute least significant bits of an address of type Addr. */
85 UWord address_lsb(const Addr a)
86 { return (a >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK; }
89 * Compute the first address for which address_lsb() is equal to
93 Addr first_address_with_same_lsb(const Addr a)
95 return ((a | ADDR_IGNORED_MASK) ^ ADDR_IGNORED_MASK);
99 * Compute the first address for which address_lsb() is greater than
103 Addr first_address_with_higher_lsb(const Addr a)
105 return ((a | ADDR_IGNORED_MASK) + 1U);
108 /** Compute most significant bits of an address of type Addr. */
110 UWord address_msb(const Addr a)
111 { return a >> (ADDR_LSB_BITS + ADDR_IGNORED_BITS); }
114 Addr first_address_with_higher_msb(const Addr a)
116 return ((a | ((ADDR_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
121 * Convert LSB and MSB back into an address.
123 * @note It is assumed that sizeof(Addr) == sizeof(UWord).
126 Addr make_address(const UWord a1, const UWord a0)
128 return ((a1 << (ADDR_LSB_BITS + ADDR_IGNORED_BITS))
129 | (a0 << ADDR_IGNORED_BITS));
136 /** Number of bits that fit in a variable of type UWord. */
137 #define BITS_PER_UWORD (8U * sizeof(UWord))
139 /** Log2 of BITS_PER_UWORD. */
140 #if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm)
141 #define BITS_PER_BITS_PER_UWORD 5
142 #elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_s390x)
143 #define BITS_PER_BITS_PER_UWORD 6
145 #error Unknown platform.
148 /** Number of UWord's needed to store one bit per address LSB. */
149 #define BITMAP1_UWORD_COUNT (1U << (ADDR_LSB_BITS - BITS_PER_BITS_PER_UWORD))
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.
155 #define UWORD_LSB_MASK (((UWord)1 << BITS_PER_BITS_PER_UWORD) - 1)
158 * Compute index into bm0[] array.
160 * @param a Address shifted right ADDR_IGNORED_BITS bits.
163 UWord uword_msb(const UWord a)
165 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
166 tl_assert(a < (1U << ADDR_LSB_BITS));
168 return a >> BITS_PER_BITS_PER_UWORD;
172 * Return the least significant bits.
174 * @param a Address shifted right ADDR_IGNORED_BITS bits.
177 UWord uword_lsb(const UWord a)
179 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
180 tl_assert(a < (1U << ADDR_LSB_BITS));
182 return a & UWORD_LSB_MASK;
186 * Compute the highest address lower than a for which
187 * uword_lsb(address_lsb(a)) == 0.
192 Addr first_address_with_same_uword_lsb(const Addr a)
194 return (a & (~UWORD_LSB_MASK << ADDR_IGNORED_BITS));
198 * First address that will go in the UWord past the one 'a' goes in.
203 Addr first_address_with_higher_uword_msb(const Addr a)
205 return ((a | ((UWORD_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
211 /* Local variables. */
213 static ULong s_bitmap2_creation_count;
217 /*********************************************************************/
218 /* Functions for manipulating a struct bitmap1. */
219 /*********************************************************************/
222 /* Lowest level, corresponding to the lowest ADDR_LSB_BITS of an address. */
225 UWord bm0_r[BITMAP1_UWORD_COUNT];
226 UWord bm0_w[BITMAP1_UWORD_COUNT];
229 static __inline__ UWord bm0_mask(const UWord a)
231 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
232 tl_assert(address_msb(make_address(0, a)) == 0);
234 return ((UWord)1 << uword_lsb(a));
237 /** Set the bit corresponding to address a in bitmap bm0. */
238 static __inline__ void bm0_set(UWord* bm0, const UWord a)
240 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
241 tl_assert(address_msb(make_address(0, a)) == 0);
243 bm0[uword_msb(a)] |= (UWord)1 << uword_lsb(a);
247 * Set the bits corresponding to all of the addresses in range
248 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
251 static __inline__ void bm0_set_range(UWord* bm0,
252 const UWord a, const SizeT size)
254 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
256 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));
261 |= (((UWord)1 << size) - 1) << uword_lsb(a);
264 /** Clear the bit corresponding to address a in bitmap bm0. */
265 static __inline__ void bm0_clear(UWord* bm0, const UWord a)
267 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
268 tl_assert(address_msb(make_address(0, a)) == 0);
270 bm0[uword_msb(a)] &= ~((UWord)1 << uword_lsb(a));
274 * Clear all of the addresses in range
275 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
278 static __inline__ void bm0_clear_range(UWord* bm0,
279 const UWord a, const SizeT size)
281 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
282 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));
287 * Note: although the expression below yields a correct result even if
288 * 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.
294 &= ~((((UWord)1 << size) - 1) << uword_lsb(a));
298 /** Test whether the bit corresponding to address a is set in bitmap bm0. */
299 static __inline__ UWord bm0_is_set(const UWord* bm0, const UWord a)
301 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
302 tl_assert(address_msb(make_address(0, a)) == 0);
304 return (bm0[uword_msb(a)] & ((UWord)1 << uword_lsb(a)));
308 * Return true if a bit corresponding to any of the addresses in range
309 * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
312 static __inline__ UWord bm0_is_any_set(const UWord* bm0,
313 const Addr a, const SizeT size)
315 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
317 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));
321 return (bm0[uword_msb(a)] & ((((UWord)1 << size) - 1) << uword_lsb(a)));
326 /*********************************************************************/
327 /* Functions for manipulating a struct bitmap. */
328 /*********************************************************************/
331 /* Second level bitmap. */
334 Addr addr; ///< address_msb(...)
340 static void bm2_clear(struct bitmap2* const bm2);
342 struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1);
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.
351 void bm_cache_rotate(struct bm_cache_elem cache[], const int n)
354 struct bm_cache_elem t;
356 tl_assert(2 <= n && n <= 8);
378 Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1,
379 struct bitmap2** bm2)
381 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
386 #if DRD_BITMAP_N_CACHE_ELEM > 8
387 #error Please update the code below.
389 #if DRD_BITMAP_N_CACHE_ELEM >= 1
390 if (a1 == bm->cache[0].a1)
392 *bm2 = bm->cache[0].bm2;
396 #if DRD_BITMAP_N_CACHE_ELEM >= 2
397 if (a1 == bm->cache[1].a1)
399 *bm2 = bm->cache[1].bm2;
403 #if DRD_BITMAP_N_CACHE_ELEM >= 3
404 if (a1 == bm->cache[2].a1)
406 *bm2 = bm->cache[2].bm2;
407 bm_cache_rotate(bm->cache, 3);
411 #if DRD_BITMAP_N_CACHE_ELEM >= 4
412 if (a1 == bm->cache[3].a1)
414 *bm2 = bm->cache[3].bm2;
415 bm_cache_rotate(bm->cache, 4);
419 #if DRD_BITMAP_N_CACHE_ELEM >= 5
420 if (a1 == bm->cache[4].a1)
422 *bm2 = bm->cache[4].bm2;
423 bm_cache_rotate(bm->cache, 5);
427 #if DRD_BITMAP_N_CACHE_ELEM >= 6
428 if (a1 == bm->cache[5].a1)
430 *bm2 = bm->cache[5].bm2;
431 bm_cache_rotate(bm->cache, 6);
435 #if DRD_BITMAP_N_CACHE_ELEM >= 7
436 if (a1 == bm->cache[6].a1)
438 *bm2 = bm->cache[6].bm2;
439 bm_cache_rotate(bm->cache, 7);
443 #if DRD_BITMAP_N_CACHE_ELEM >= 8
444 if (a1 == bm->cache[7].a1)
446 *bm2 = bm->cache[7].bm2;
447 bm_cache_rotate(bm->cache, 8);
456 void bm_update_cache(struct bitmap* const bm,
458 struct bitmap2* const bm2)
460 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
464 #if DRD_BITMAP_N_CACHE_ELEM > 8
465 #error Please update the code below.
467 #if DRD_BITMAP_N_CACHE_ELEM >= 8
468 bm->cache[7] = bm->cache[6];
470 #if DRD_BITMAP_N_CACHE_ELEM >= 7
471 bm->cache[6] = bm->cache[5];
473 #if DRD_BITMAP_N_CACHE_ELEM >= 6
474 bm->cache[5] = bm->cache[4];
476 #if DRD_BITMAP_N_CACHE_ELEM >= 5
477 bm->cache[4] = bm->cache[3];
479 #if DRD_BITMAP_N_CACHE_ELEM >= 4
480 bm->cache[3] = bm->cache[2];
482 #if DRD_BITMAP_N_CACHE_ELEM >= 3
483 bm->cache[2] = bm->cache[1];
485 #if DRD_BITMAP_N_CACHE_ELEM >= 2
486 bm->cache[1] = bm->cache[0];
488 bm->cache[0].a1 = a1;
489 bm->cache[0].bm2 = bm2;
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.
497 * @param a1 client address shifted right by ADDR_LSB_BITS.
498 * @param bm bitmap pointer.
501 const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1)
505 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
509 if (! bm_cache_lookup(bm, a1, &bm2))
511 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
512 bm_update_cache(bm, a1, bm2);
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.
521 * @param a1 client address shifted right by ADDR_LSB_BITS.
522 * @param bm bitmap pointer.
526 bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1)
530 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
534 if (! bm_cache_lookup(bm, a1, &bm2))
536 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
542 /** Clear the content of the second-level bitmap. */
544 void bm2_clear(struct bitmap2* const bm2)
546 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
549 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
553 * Insert an uninitialized second level bitmap for the address a1.
555 * @param bm bitmap pointer.
556 * @param a1 client address shifted right by ADDR_LSB_BITS.
558 * @note bitmap2::recalc isn't initialized here on purpose.
561 struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1)
565 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
569 s_bitmap2_creation_count++;
571 bm2 = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2));
573 VG_(OSetGen_Insert)(bm->oset, bm2);
575 bm_update_cache(bm, a1, bm2);
581 struct bitmap2* bm2_insert_copy(struct bitmap* const bm,
582 struct bitmap2* const bm2)
584 struct bitmap2* bm2_copy;
586 bm2_copy = bm2_insert(bm, bm2->addr);
587 VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1));
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.
595 * @param bm bitmap pointer.
596 * @param a1 client address shifted right by ADDR_LSB_BITS.
599 struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1)
603 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
607 if (bm_cache_lookup(bm, a1, &bm2))
611 bm2 = bm2_insert(bm, a1);
617 bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
620 bm2 = bm2_insert(bm, a1);
623 bm_update_cache(bm, a1, bm2);
629 * Look up the address a1 in bitmap bm, and insert it if not found.
630 * The returned second level bitmap may be modified.
632 * @param a1 client address shifted right by ADDR_LSB_BITS.
633 * @param bm bitmap pointer.
636 struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
639 return bm2_lookup_or_insert(bm, a1);
643 void bm2_remove(struct bitmap* const bm, const UWord a1)
647 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
651 bm2 = VG_(OSetGen_Remove)(bm->oset, &a1);
652 VG_(OSetGen_FreeNode)(bm->oset, bm2);
654 bm_update_cache(bm, a1, NULL);
658 void bm_access_aligned_load(struct bitmap* const bm,
659 const Addr a1, const SizeT size)
663 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
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,
674 void bm_access_aligned_store(struct bitmap* const bm,
675 const Addr a1, const SizeT size)
679 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
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,
690 Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm,
691 const Addr a, const SizeT size)
693 const struct bitmap2* bm2;
695 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
699 bm2 = bm2_lookup(bm, address_msb(a));
701 && bm0_is_any_set(bm2->bm1.bm0_w,
707 Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm,
708 const Addr a, const SizeT size)
710 const struct bitmap2* bm2;
712 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
716 bm2 = bm2_lookup(bm, address_msb(a));
719 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)))
728 #endif /* __DRD_BITMAP_H */