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__
address_lsb(const Addr a)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__
first_address_with_same_lsb(const Addr a)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__
first_address_with_higher_lsb(const Addr a)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__
address_msb(const Addr a)109 UWord address_msb(const Addr a)
110 { return a >> (ADDR_LSB_BITS + ADDR_IGNORED_BITS); }
111
112 static __inline__
first_address_with_higher_msb(const Addr a)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__
make_address(const UWord a1,const UWord a0)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__
uword_msb(const UWord a)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__
uword_lsb(const UWord a)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__
first_address_with_same_uword_lsb(const Addr a)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__
first_address_with_higher_uword_msb(const Addr a)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
bm0_mask(const UWord a)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. */
bm0_set(UWord * bm0,const UWord a)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 */
bm0_set_range(UWord * bm0,const UWord a,const SizeT size)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. */
bm0_clear(UWord * bm0,const UWord a)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 */
bm0_clear_range(UWord * bm0,const UWord a,const SizeT size)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. */
bm0_is_set(const UWord * bm0,const UWord a)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 */
bm0_is_any_set(const UWord * bm0,const Addr a,const SizeT size)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__
bm_cache_rotate(struct bm_cache_elem cache[],const int n)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__
bm_cache_lookup(struct bitmap * const bm,const UWord a1,struct bitmap2 ** bm2)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__
bm_update_cache(struct bitmap * const bm,const UWord a1,struct bitmap2 * const bm2)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__
bm2_lookup(struct bitmap * const bm,const UWord a1)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*
bm2_lookup_exclusive(struct bitmap * const bm,const UWord a1)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__
bm2_clear(struct bitmap2 * const bm2)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__
bm2_insert(struct bitmap * const bm,const UWord a1)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__
bm2_insert_copy(struct bitmap * const bm,struct bitmap2 * const bm2)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__
bm2_lookup_or_insert(struct bitmap * const bm,const UWord a1)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__
bm2_lookup_or_insert_exclusive(struct bitmap * const bm,const UWord a1)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__
bm2_remove(struct bitmap * const bm,const UWord a1)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__
bm_access_aligned_load(struct bitmap * const bm,const Addr a1,const SizeT size)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__
bm_access_aligned_store(struct bitmap * const bm,const Addr a1,const SizeT size)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__
bm_aligned_load_has_conflict_with(struct bitmap * const bm,const Addr a,const SizeT size)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__
bm_aligned_store_has_conflict_with(struct bitmap * const bm,const Addr a,const SizeT size)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