1 /*
2   This file is part of drd, a thread error detector.
3 
4   Copyright (C) 2006-2017 Bart Van Assche <bvanassche@acm.org>.
5 
6   This program is free software; you can redistribute it and/or
7   modify it under the terms of the GNU General Public License as
8   published by the Free Software Foundation; either version 2 of the
9   License, or (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   02111-1307, USA.
20 
21   The GNU General Public License is contained in the file COPYING.
22 */
23 
24 
25 #ifndef __DRD_BITMAP_H
26 #define __DRD_BITMAP_H
27 
28 
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"
35 #endif
36 
37 
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.
42  */
43 
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  * ------------------------------------------------------
50  */
51 
52 
53 
54 /* Address MSB / LSB split. */
55 
56 
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)
61 
62 /**
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.
66  */
67 #define SCALED_SIZE(a)                                                  \
68    (((((a) - 1U) | ADDR_IGNORED_MASK) + 1U) >> ADDR_IGNORED_BITS)
69 
70 /**
71  * Number of bits assigned to the least significant component of an address.
72  */
73 #define ADDR_LSB_BITS 12
74 
75 /**
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.
79  */
80 #define ADDR_LSB_MASK (((UWord)1 << ADDR_LSB_BITS) - 1U)
81 
82 /** Compute least significant bits of an address of type Addr. */
83 static __inline__
84 UWord address_lsb(const Addr a)
85 { return (a >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK; }
86 
87 /**
88  * Compute the first address for which address_lsb() is equal to
89  * address_lsb(a).
90  */
91 static __inline__
92 Addr first_address_with_same_lsb(const Addr a)
93 {
94    return ((a | ADDR_IGNORED_MASK) ^ ADDR_IGNORED_MASK);
95 }
96 
97 /**
98  * Compute the first address for which address_lsb() is greater than
99  * address_lsb(a).
100  */
101 static __inline__
102 Addr first_address_with_higher_lsb(const Addr a)
103 {
104    return ((a | ADDR_IGNORED_MASK) + 1U);
105 }
106 
107 /** Compute most significant bits of an address of type Addr. */
108 static __inline__
109 UWord address_msb(const Addr a)
110 { return a >> (ADDR_LSB_BITS + ADDR_IGNORED_BITS); }
111 
112 static __inline__
113 Addr first_address_with_higher_msb(const Addr a)
114 {
115    return ((a | ((ADDR_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
116            + 1U);
117 }
118 
119 /**
120  * Convert LSB and MSB back into an address.
121  *
122  * @note It is assumed that sizeof(Addr) == sizeof(UWord).
123  */
124 static __inline__
125 Addr make_address(const UWord a1, const UWord a0)
126 {
127    return ((a1 << (ADDR_LSB_BITS + ADDR_IGNORED_BITS))
128            | (a0 << ADDR_IGNORED_BITS));
129 }
130 
131 
132 
133 
134 
135 /** Number of bits that fit in a variable of type UWord. */
136 #define BITS_PER_UWORD (8U * sizeof(UWord))
137 
138 /** Log2 of BITS_PER_UWORD. */
139 #if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) \
140     || defined(VGA_mips32)
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(VGA_arm64)
144 #define BITS_PER_BITS_PER_UWORD 6
145 #else
146 #error Unknown platform.
147 #endif
148 
149 /** Number of UWord's needed to store one bit per address LSB. */
150 #define BITMAP1_UWORD_COUNT (1U << (ADDR_LSB_BITS - BITS_PER_BITS_PER_UWORD))
151 
152 /**
153  * Mask that has to be applied to an (Addr >> ADDR_IGNORED_BITS) expression
154  * in order to compute the least significant part of an UWord.
155  */
156 #define UWORD_LSB_MASK (((UWord)1 << BITS_PER_BITS_PER_UWORD) - 1)
157 
158 /**
159  * Compute index into bm0[] array.
160  *
161  * @param a Address shifted right ADDR_IGNORED_BITS bits.
162  */
163 static __inline__
164 UWord uword_msb(const UWord a)
165 {
166 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
167    tl_assert(a < (1U << ADDR_LSB_BITS));
168 #endif
169    return a >> BITS_PER_BITS_PER_UWORD;
170 }
171 
172 /**
173  * Return the least significant bits.
174  *
175  * @param a Address shifted right ADDR_IGNORED_BITS bits.
176  */
177 static __inline__
178 UWord uword_lsb(const UWord a)
179 {
180 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
181    tl_assert(a < (1U << ADDR_LSB_BITS));
182 #endif
183    return a & UWORD_LSB_MASK;
184 }
185 
186 /**
187  * Compute the highest address lower than a for which
188  * uword_lsb(address_lsb(a)) == 0.
189  *
190  * @param a Address.
191  */
192 static __inline__
193 Addr first_address_with_same_uword_lsb(const Addr a)
194 {
195    return (a & (~UWORD_LSB_MASK << ADDR_IGNORED_BITS));
196 }
197 
198 /**
199  * First address that will go in the UWord past the one 'a' goes in.
200  *
201  *  @param a Address.
202  */
203 static __inline__
204 Addr first_address_with_higher_uword_msb(const Addr a)
205 {
206    return ((a | ((UWORD_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
207            + 1);
208 }
209 
210 
211 
212 /* Local variables. */
213 
214 static ULong s_bitmap2_creation_count;
215 
216 
217 
218 /*********************************************************************/
219 /*           Functions for manipulating a struct bitmap1.            */
220 /*********************************************************************/
221 
222 
223 /* Lowest level, corresponding to the lowest ADDR_LSB_BITS of an address. */
224 struct bitmap1
225 {
226    UWord bm0_r[BITMAP1_UWORD_COUNT];
227    UWord bm0_w[BITMAP1_UWORD_COUNT];
228 };
229 
230 static __inline__ UWord bm0_mask(const UWord a)
231 {
232 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
233    tl_assert(address_msb(make_address(0, a)) == 0);
234 #endif
235    return ((UWord)1 << uword_lsb(a));
236 }
237 
238 /** Set the bit corresponding to address a in bitmap bm0. */
239 static __inline__ void bm0_set(UWord* bm0, const UWord a)
240 {
241 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
242    tl_assert(address_msb(make_address(0, a)) == 0);
243 #endif
244    bm0[uword_msb(a)] |= (UWord)1 << uword_lsb(a);
245 }
246 
247 /**
248  * Set the bits corresponding to all of the addresses in range
249  * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
250  * in bitmap bm0.
251  */
252 static __inline__ void bm0_set_range(UWord* bm0,
253                                      const UWord a, const SizeT size)
254 {
255 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
256    tl_assert(size > 0);
257    tl_assert(address_msb(make_address(0, a)) == 0);
258    tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
259    tl_assert(uword_msb(a) == uword_msb(a + size - 1));
260 #endif
261    bm0[uword_msb(a)]
262       |= (((UWord)1 << size) - 1) << uword_lsb(a);
263 }
264 
265 /** Clear the bit corresponding to address a in bitmap bm0. */
266 static __inline__ void bm0_clear(UWord* bm0, const UWord a)
267 {
268 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
269    tl_assert(address_msb(make_address(0, a)) == 0);
270 #endif
271    bm0[uword_msb(a)] &= ~((UWord)1 << uword_lsb(a));
272 }
273 
274 /**
275  * Clear all of the addresses in range
276  * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
277  * in bitmap bm0.
278  */
279 static __inline__ void bm0_clear_range(UWord* bm0,
280                                        const UWord a, const SizeT size)
281 {
282 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
283    tl_assert(address_msb(make_address(0, a)) == 0);
284    tl_assert(size == 0 || address_msb(make_address(0, a + size - 1)) == 0);
285    tl_assert(size == 0 || uword_msb(a) == uword_msb(a + size - 1));
286 #endif
287    /*
288     * Note: although the expression below yields a correct result even if
289     * size == 0, do not touch bm0[] if size == 0 because this might otherwise
290     * cause an access of memory just past the end of the bm0[] array.
291     */
292    if (size > 0)
293    {
294       bm0[uword_msb(a)]
295          &= ~((((UWord)1 << size) - 1) << uword_lsb(a));
296    }
297 }
298 
299 /** Test whether the bit corresponding to address a is set in bitmap bm0. */
300 static __inline__ UWord bm0_is_set(const UWord* bm0, const UWord a)
301 {
302 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
303    tl_assert(address_msb(make_address(0, a)) == 0);
304 #endif
305    return (bm0[uword_msb(a)] & ((UWord)1 << uword_lsb(a)));
306 }
307 
308 /**
309  * Return true if a bit corresponding to any of the addresses in range
310  * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
311  * is set in bm0.
312  */
313 static __inline__ UWord bm0_is_any_set(const UWord* bm0,
314                                        const Addr a, const SizeT size)
315 {
316 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
317    tl_assert(size > 0);
318    tl_assert(address_msb(make_address(0, a)) == 0);
319    tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
320    tl_assert(uword_msb(a) == uword_msb(a + size - 1));
321 #endif
322    return (bm0[uword_msb(a)] & ((((UWord)1 << size) - 1) << uword_lsb(a)));
323 }
324 
325 
326 
327 /*********************************************************************/
328 /*           Functions for manipulating a struct bitmap.             */
329 /*********************************************************************/
330 
331 
332 /* Second level bitmap. */
333 struct bitmap2
334 {
335    Addr           addr;   ///< address_msb(...)
336    Bool           recalc;
337    struct bitmap1 bm1;
338 };
339 
340 
341 static void bm2_clear(struct bitmap2* const bm2);
342 static __inline__
343 struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1);
344 
345 
346 
347 /**
348  * Rotate elements cache[0..n-1] such that the element at position n-1 is
349  * moved to position 0. This allows to speed up future cache lookups.
350  */
351 static __inline__
352 void bm_cache_rotate(struct bm_cache_elem cache[], const int n)
353 {
354 #if 0
355    struct bm_cache_elem t;
356 
357    tl_assert(2 <= n && n <= 8);
358 
359    t = cache[0];
360    if (n > 1)
361       cache[0] = cache[1];
362    if (n > 2)
363       cache[1] = cache[2];
364    if (n > 3)
365       cache[2] = cache[3];
366    if (n > 4)
367       cache[3] = cache[4];
368    if (n > 5)
369       cache[4] = cache[5];
370    if (n > 6)
371       cache[5] = cache[6];
372    if (n > 7)
373       cache[6] = cache[7];
374    cache[n - 1] = t;
375 #endif
376 }
377 
378 static __inline__
379 Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1,
380                      struct bitmap2** bm2)
381 {
382 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
383    tl_assert(bm);
384    tl_assert(bm2);
385 #endif
386 
387 #if DRD_BITMAP_N_CACHE_ELEM > 8
388 #error Please update the code below.
389 #endif
390 #if DRD_BITMAP_N_CACHE_ELEM >= 1
391    if (a1 == bm->cache[0].a1)
392    {
393       *bm2 = bm->cache[0].bm2;
394       return True;
395    }
396 #endif
397 #if DRD_BITMAP_N_CACHE_ELEM >= 2
398    if (a1 == bm->cache[1].a1)
399    {
400       *bm2 = bm->cache[1].bm2;
401       return True;
402    }
403 #endif
404 #if DRD_BITMAP_N_CACHE_ELEM >= 3
405    if (a1 == bm->cache[2].a1)
406    {
407       *bm2 = bm->cache[2].bm2;
408       bm_cache_rotate(bm->cache, 3);
409       return True;
410    }
411 #endif
412 #if DRD_BITMAP_N_CACHE_ELEM >= 4
413    if (a1 == bm->cache[3].a1)
414    {
415       *bm2 = bm->cache[3].bm2;
416       bm_cache_rotate(bm->cache, 4);
417       return True;
418    }
419 #endif
420 #if DRD_BITMAP_N_CACHE_ELEM >= 5
421    if (a1 == bm->cache[4].a1)
422    {
423       *bm2 = bm->cache[4].bm2;
424       bm_cache_rotate(bm->cache, 5);
425       return True;
426    }
427 #endif
428 #if DRD_BITMAP_N_CACHE_ELEM >= 6
429    if (a1 == bm->cache[5].a1)
430    {
431       *bm2 = bm->cache[5].bm2;
432       bm_cache_rotate(bm->cache, 6);
433       return True;
434    }
435 #endif
436 #if DRD_BITMAP_N_CACHE_ELEM >= 7
437    if (a1 == bm->cache[6].a1)
438    {
439       *bm2 = bm->cache[6].bm2;
440       bm_cache_rotate(bm->cache, 7);
441       return True;
442    }
443 #endif
444 #if DRD_BITMAP_N_CACHE_ELEM >= 8
445    if (a1 == bm->cache[7].a1)
446    {
447       *bm2 = bm->cache[7].bm2;
448       bm_cache_rotate(bm->cache, 8);
449       return True;
450    }
451 #endif
452    *bm2 = 0;
453    return False;
454 }
455 
456 static __inline__
457 void bm_update_cache(struct bitmap* const bm,
458                      const UWord a1,
459                      struct bitmap2* const bm2)
460 {
461 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
462    tl_assert(bm);
463 #endif
464 
465 #if DRD_BITMAP_N_CACHE_ELEM > 8
466 #error Please update the code below.
467 #endif
468 #if DRD_BITMAP_N_CACHE_ELEM >= 8
469    bm->cache[7] = bm->cache[6];
470 #endif
471 #if DRD_BITMAP_N_CACHE_ELEM >= 7
472    bm->cache[6] = bm->cache[5];
473 #endif
474 #if DRD_BITMAP_N_CACHE_ELEM >= 6
475    bm->cache[5] = bm->cache[4];
476 #endif
477 #if DRD_BITMAP_N_CACHE_ELEM >= 5
478    bm->cache[4] = bm->cache[3];
479 #endif
480 #if DRD_BITMAP_N_CACHE_ELEM >= 4
481    bm->cache[3] = bm->cache[2];
482 #endif
483 #if DRD_BITMAP_N_CACHE_ELEM >= 3
484    bm->cache[2] = bm->cache[1];
485 #endif
486 #if DRD_BITMAP_N_CACHE_ELEM >= 2
487    bm->cache[1] = bm->cache[0];
488 #endif
489    bm->cache[0].a1  = a1;
490    bm->cache[0].bm2 = bm2;
491 }
492 
493 /**
494  * Look up the address a1 in bitmap bm and return a pointer to a potentially
495  * shared second level bitmap. The bitmap where the returned pointer points
496  * at may not be modified by the caller.
497  *
498  * @param a1 client address shifted right by ADDR_LSB_BITS.
499  * @param bm bitmap pointer.
500  */
501 static __inline__
502 const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1)
503 {
504    struct bitmap2* bm2;
505 
506 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
507    tl_assert(bm);
508 #endif
509 
510    if (! bm_cache_lookup(bm, a1, &bm2))
511    {
512       bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
513       bm_update_cache(bm, a1, bm2);
514    }
515    return bm2;
516 }
517 
518 /**
519  * Look up the address a1 in bitmap bm and return a pointer to a second
520  * level bitmap that is not shared and hence may be modified.
521  *
522  * @param a1 client address shifted right by ADDR_LSB_BITS.
523  * @param bm bitmap pointer.
524  */
525 static __inline__
526 struct bitmap2*
527 bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1)
528 {
529    struct bitmap2* bm2;
530 
531 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
532    tl_assert(bm);
533 #endif
534 
535    if (! bm_cache_lookup(bm, a1, &bm2))
536    {
537       bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
538    }
539 
540    return bm2;
541 }
542 
543 /** Clear the content of the second-level bitmap. */
544 static __inline__
545 void bm2_clear(struct bitmap2* const bm2)
546 {
547 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
548    tl_assert(bm2);
549 #endif
550    VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
551 }
552 
553 /**
554  * Insert an uninitialized second level bitmap for the address a1.
555  *
556  * @param bm bitmap pointer.
557  * @param a1 client address shifted right by ADDR_LSB_BITS.
558  *
559  * @note bitmap2::recalc isn't initialized here on purpose.
560  */
561 static __inline__
562 struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1)
563 {
564    struct bitmap2* bm2;
565 
566 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
567    tl_assert(bm);
568 #endif
569 
570    s_bitmap2_creation_count++;
571 
572    bm2 = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2));
573    bm2->addr = a1;
574    VG_(OSetGen_Insert)(bm->oset, bm2);
575 
576    bm_update_cache(bm, a1, bm2);
577 
578    return bm2;
579 }
580 
581 static __inline__
582 struct bitmap2* bm2_insert_copy(struct bitmap* const bm,
583                                 struct bitmap2* const bm2)
584 {
585    struct bitmap2* bm2_copy;
586 
587    bm2_copy = bm2_insert(bm, bm2->addr);
588    VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1));
589    return bm2_copy;
590 }
591 
592 /**
593  * Look up the address a1 in bitmap bm, and insert it if not found.
594  * The returned second level bitmap may not be modified.
595  *
596  * @param bm bitmap pointer.
597  * @param a1 client address shifted right by ADDR_LSB_BITS.
598  */
599 static __inline__
600 struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1)
601 {
602    struct bitmap2* bm2;
603 
604 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
605    tl_assert(bm);
606 #endif
607 
608    if (bm_cache_lookup(bm, a1, &bm2))
609    {
610       if (bm2 == 0)
611       {
612          bm2 = bm2_insert(bm, a1);
613          bm2_clear(bm2);
614       }
615    }
616    else
617    {
618       bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
619       if (! bm2)
620       {
621          bm2 = bm2_insert(bm, a1);
622          bm2_clear(bm2);
623       }
624       bm_update_cache(bm, a1, bm2);
625    }
626    return bm2;
627 }
628 
629 /**
630  * Look up the address a1 in bitmap bm, and insert it if not found.
631  * The returned second level bitmap may be modified.
632  *
633  * @param a1 client address shifted right by ADDR_LSB_BITS.
634  * @param bm bitmap pointer.
635  */
636 static __inline__
637 struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
638                                                const UWord a1)
639 {
640    return bm2_lookup_or_insert(bm, a1);
641 }
642 
643 static __inline__
644 void bm2_remove(struct bitmap* const bm, const UWord a1)
645 {
646    struct bitmap2* bm2;
647 
648 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
649    tl_assert(bm);
650 #endif
651 
652    bm2 = VG_(OSetGen_Remove)(bm->oset, &a1);
653    VG_(OSetGen_FreeNode)(bm->oset, bm2);
654 
655    bm_update_cache(bm, a1, NULL);
656 }
657 
658 static __inline__
659 void bm_access_aligned_load(struct bitmap* const bm,
660                             const Addr a1, const SizeT size)
661 {
662    struct bitmap2* bm2;
663 
664 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
665    tl_assert(bm);
666 #endif
667 
668    bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
669    bm0_set_range(bm2->bm1.bm0_r,
670                  (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
671                  SCALED_SIZE(size));
672 }
673 
674 static __inline__
675 void bm_access_aligned_store(struct bitmap* const bm,
676                              const Addr a1, const SizeT size)
677 {
678    struct bitmap2* bm2;
679 
680 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
681    tl_assert(bm);
682 #endif
683 
684    bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
685    bm0_set_range(bm2->bm1.bm0_w,
686                  (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
687                  SCALED_SIZE(size));
688 }
689 
690 static __inline__
691 Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm,
692                                        const Addr a, const SizeT size)
693 {
694    const struct bitmap2* bm2;
695 
696 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
697    tl_assert(bm);
698 #endif
699 
700    bm2 = bm2_lookup(bm, address_msb(a));
701    return (bm2
702            && bm0_is_any_set(bm2->bm1.bm0_w,
703                              address_lsb(a),
704                              SCALED_SIZE(size)));
705 }
706 
707 static __inline__
708 Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm,
709                                         const Addr a, const SizeT size)
710 {
711    const struct bitmap2* bm2;
712 
713 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
714    tl_assert(bm);
715 #endif
716 
717    bm2 = bm2_lookup(bm, address_msb(a));
718    if (bm2)
719    {
720       if (bm0_is_any_set(bm2->bm1.bm0_r, address_lsb(a), SCALED_SIZE(size))
721           | bm0_is_any_set(bm2->bm1.bm0_w, address_lsb(a), SCALED_SIZE(size)))
722       {
723          return True;
724       }
725    }
726    return False;
727 }
728 
729 #endif /* __DRD_BITMAP_H */
730