2 This file is part of drd, a thread error detector.
4 Copyright (C) 2006-2011 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 #include "drd_basics.h" /* DRD_() */
26 #include "drd_bitmap.h"
27 #include "drd_error.h"
28 #include "drd_suppression.h"
29 #include "pub_drd_bitmap.h"
30 #include "pub_tool_basics.h" /* Addr, SizeT */
31 #include "pub_tool_debuginfo.h" /* VG_(get_objname)() */
32 #include "pub_tool_libcassert.h" /* tl_assert() */
33 #include "pub_tool_libcbase.h" /* VG_(memset) */
34 #include "pub_tool_libcprint.h" /* VG_(printf) */
35 #include "pub_tool_machine.h" /* VG_(get_IP)() */
36 #include "pub_tool_mallocfree.h" /* VG_(malloc), VG_(free) */
39 /* Local function declarations. */
41 static void bm2_merge(struct bitmap2
* const bm2l
,
42 const struct bitmap2
* const bm2r
);
43 static void bm2_print(const struct bitmap2
* const bm2
);
46 /* Local variables. */
48 static ULong s_bitmap_creation_count
;
49 static ULong s_bitmap_merge_count
;
50 static ULong s_bitmap2_merge_count
;
53 /* Function definitions. */
55 struct bitmap
* DRD_(bm_new
)()
59 /* If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD */
60 /* in drd_bitmap.h. */
61 tl_assert((1 << BITS_PER_BITS_PER_UWORD
) == BITS_PER_UWORD
);
63 bm
= VG_(malloc
)("drd.bitmap.bn.1", sizeof(*bm
));
69 void DRD_(bm_delete
)(struct bitmap
* const bm
)
77 /** Initialize *bm. */
78 void DRD_(bm_init
)(struct bitmap
* const bm
)
84 * Cache initialization. a1 is initialized with a value that never can
85 * match any valid address: the upper (ADDR_LSB_BITS + ADDR_IGNORED_BITS)
86 * bits of a1 are always zero for a valid cache entry.
88 for (i
= 0; i
< DRD_BITMAP_N_CACHE_ELEM
; i
++)
90 bm
->cache
[i
].a1
= ~(UWord
)1;
93 bm
->oset
= VG_(OSetGen_Create
)(0, 0, DRD_(bm2_alloc_node
),
94 "drd.bitmap.bn.2", DRD_(bm2_free_node
));
96 s_bitmap_creation_count
++;
99 /** Free the memory allocated by DRD_(bm_init)(). */
100 void DRD_(bm_cleanup
)(struct bitmap
* const bm
)
102 VG_(OSetGen_Destroy
)(bm
->oset
);
106 * Record an access of type access_type at addresses a .. a + size - 1 in
109 * @note The current implementation of bm_access_range does not work for the
110 * highest addresses in the address range. At least on Linux this is
111 * not a problem since the upper part of the address space is reserved
114 void DRD_(bm_access_range
)(struct bitmap
* const bm
,
115 const Addr a1
, const Addr a2
,
116 const BmAccessTypeT access_type
)
118 tl_assert(access_type
== eLoad
|| access_type
== eStore
);
120 if (access_type
== eLoad
)
121 return DRD_(bm_access_range_load
)(bm
, a1
, a2
);
123 return DRD_(bm_access_range_store
)(bm
, a1
, a2
);
126 void DRD_(bm_access_range_load
)(struct bitmap
* const bm
, Addr a1
, Addr a2
)
132 tl_assert(a2
< first_address_with_higher_msb(a2
));
133 tl_assert(a1
== first_address_with_same_lsb(a1
));
134 tl_assert(a2
== first_address_with_same_lsb(a2
));
136 for (b
= a1
; b
< a2
; b
= b_next
)
143 b_next
= first_address_with_higher_msb(b
);
149 bm2
= bm2_lookup_or_insert_exclusive(bm
, address_msb(b
));
152 if (make_address(bm2
->addr
, 0) < a1
)
155 if (make_address(bm2
->addr
, 0) < a2
)
156 b_start
= make_address(bm2
->addr
, 0);
160 if (make_address(bm2
->addr
+ 1, 0) < a2
)
161 b_end
= make_address(bm2
->addr
+ 1, 0);
165 tl_assert(a1
<= b_start
&& b_start
< b_end
&& b_end
&& b_end
<= a2
);
166 tl_assert(address_msb(b_start
) == address_msb(b_end
- 1));
167 tl_assert(address_lsb(b_start
) <= address_lsb(b_end
- 1));
169 if (address_lsb(b_start
) == 0 && address_lsb(b_end
) == 0)
173 for (k
= 0; k
< BITMAP1_UWORD_COUNT
; k
++)
175 bm2
->bm1
.bm0_r
[k
] = ~(UWord
)0;
180 for (b0
= address_lsb(b_start
); b0
<= address_lsb(b_end
- 1); b0
++)
182 bm0_set(bm2
->bm1
.bm0_r
, b0
);
188 void DRD_(bm_access_load_1
)(struct bitmap
* const bm
, const Addr a1
)
190 bm_access_aligned_load(bm
, a1
, 1);
193 void DRD_(bm_access_load_2
)(struct bitmap
* const bm
, const Addr a1
)
196 bm_access_aligned_load(bm
, a1
, 2);
198 DRD_(bm_access_range
)(bm
, a1
, a1
+ 2, eLoad
);
201 void DRD_(bm_access_load_4
)(struct bitmap
* const bm
, const Addr a1
)
204 bm_access_aligned_load(bm
, a1
, 4);
206 DRD_(bm_access_range
)(bm
, a1
, a1
+ 4, eLoad
);
209 void DRD_(bm_access_load_8
)(struct bitmap
* const bm
, const Addr a1
)
212 bm_access_aligned_load(bm
, a1
, 8);
213 else if ((a1
& 3) == 0)
215 bm_access_aligned_load(bm
, a1
+ 0, 4);
216 bm_access_aligned_load(bm
, a1
+ 4, 4);
219 DRD_(bm_access_range
)(bm
, a1
, a1
+ 8, eLoad
);
222 void DRD_(bm_access_range_store
)(struct bitmap
* const bm
,
223 const Addr a1
, const Addr a2
)
229 tl_assert(a2
< first_address_with_higher_msb(a2
));
230 tl_assert(a1
== first_address_with_same_lsb(a1
));
231 tl_assert(a2
== first_address_with_same_lsb(a2
));
233 for (b
= a1
; b
< a2
; b
= b_next
)
240 b_next
= first_address_with_higher_msb(b
);
246 bm2
= bm2_lookup_or_insert_exclusive(bm
, address_msb(b
));
249 if (make_address(bm2
->addr
, 0) < a1
)
252 if (make_address(bm2
->addr
, 0) < a2
)
253 b_start
= make_address(bm2
->addr
, 0);
257 if (make_address(bm2
->addr
+ 1, 0) < a2
)
258 b_end
= make_address(bm2
->addr
+ 1, 0);
262 tl_assert(a1
<= b_start
&& b_start
< b_end
&& b_end
&& b_end
<= a2
);
263 tl_assert(address_msb(b_start
) == address_msb(b_end
- 1));
264 tl_assert(address_lsb(b_start
) <= address_lsb(b_end
- 1));
266 if (address_lsb(b_start
) == 0 && address_lsb(b_end
) == 0)
270 for (k
= 0; k
< BITMAP1_UWORD_COUNT
; k
++)
272 bm2
->bm1
.bm0_w
[k
] = ~(UWord
)0;
277 for (b0
= address_lsb(b_start
); b0
<= address_lsb(b_end
- 1); b0
++)
279 bm0_set(bm2
->bm1
.bm0_w
, b0
);
285 void DRD_(bm_access_store_1
)(struct bitmap
* const bm
, const Addr a1
)
287 bm_access_aligned_store(bm
, a1
, 1);
290 void DRD_(bm_access_store_2
)(struct bitmap
* const bm
, const Addr a1
)
293 bm_access_aligned_store(bm
, a1
, 2);
295 DRD_(bm_access_range
)(bm
, a1
, a1
+ 2, eStore
);
298 void DRD_(bm_access_store_4
)(struct bitmap
* const bm
, const Addr a1
)
301 bm_access_aligned_store(bm
, a1
, 4);
303 DRD_(bm_access_range
)(bm
, a1
, a1
+ 4, eStore
);
306 void DRD_(bm_access_store_8
)(struct bitmap
* const bm
, const Addr a1
)
309 bm_access_aligned_store(bm
, a1
, 8);
310 else if ((a1
& 3) == 0)
312 bm_access_aligned_store(bm
, a1
+ 0, 4);
313 bm_access_aligned_store(bm
, a1
+ 4, 4);
316 DRD_(bm_access_range
)(bm
, a1
, a1
+ 8, eStore
);
319 Bool
DRD_(bm_has
)(struct bitmap
* const bm
, const Addr a1
, const Addr a2
,
320 const BmAccessTypeT access_type
)
322 tl_assert(access_type
== eLoad
|| access_type
== eStore
);
324 if (access_type
== eLoad
)
325 return DRD_(bm_has_any_load
)(bm
, a1
, a2
);
327 return DRD_(bm_has_any_store
)(bm
, a1
, a2
);
331 DRD_(bm_has_any_load
)(struct bitmap
* const bm
, const Addr a1
, const Addr a2
)
337 for (b
= a1
; b
< a2
; b
= b_next
)
339 const struct bitmap2
* bm2
= bm2_lookup(bm
, address_msb(b
));
341 b_next
= first_address_with_higher_msb(b
);
352 const struct bitmap1
* const p1
= &bm2
->bm1
;
354 if (make_address(bm2
->addr
, 0) < a1
)
357 if (make_address(bm2
->addr
, 0) < a2
)
358 b_start
= make_address(bm2
->addr
, 0);
361 tl_assert(a1
<= b_start
&& b_start
<= a2
);
363 if (make_address(bm2
->addr
+ 1, 0) < a2
)
364 b_end
= make_address(bm2
->addr
+ 1, 0);
367 tl_assert(a1
<= b_end
&& b_end
<= a2
);
368 tl_assert(b_start
< b_end
);
369 tl_assert(address_lsb(b_start
) <= address_lsb(b_end
- 1));
371 for (b0
= address_lsb(b_start
); b0
<= address_lsb(b_end
- 1); b0
++)
373 if (bm0_is_set(p1
->bm0_r
, b0
))
383 Bool
DRD_(bm_has_any_store
)(struct bitmap
* const bm
,
384 const Addr a1
, const Addr a2
)
390 for (b
= a1
; b
< a2
; b
= b_next
)
392 const struct bitmap2
* bm2
= bm2_lookup(bm
, address_msb(b
));
394 b_next
= first_address_with_higher_msb(b
);
405 const struct bitmap1
* const p1
= &bm2
->bm1
;
407 if (make_address(bm2
->addr
, 0) < a1
)
410 if (make_address(bm2
->addr
, 0) < a2
)
411 b_start
= make_address(bm2
->addr
, 0);
414 tl_assert(a1
<= b_start
&& b_start
<= a2
);
416 if (make_address(bm2
->addr
+ 1, 0) < a2
)
417 b_end
= make_address(bm2
->addr
+ 1, 0);
420 tl_assert(a1
<= b_end
&& b_end
<= a2
);
421 tl_assert(b_start
< b_end
);
422 tl_assert(address_lsb(b_start
) <= address_lsb(b_end
- 1));
424 for (b0
= address_lsb(b_start
); b0
<= address_lsb(b_end
- 1); b0
++)
426 if (bm0_is_set(p1
->bm0_w
, b0
))
436 /* Return True if there is a read access, write access or both */
437 /* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
438 Bool
DRD_(bm_has_any_access
)(struct bitmap
* const bm
,
439 const Addr a1
, const Addr a2
)
445 for (b
= a1
; b
< a2
; b
= b_next
)
447 const struct bitmap2
* bm2
= bm2_lookup(bm
, address_msb(b
));
449 b_next
= first_address_with_higher_msb(b
);
460 const struct bitmap1
* const p1
= &bm2
->bm1
;
462 if (make_address(bm2
->addr
, 0) < a1
)
465 if (make_address(bm2
->addr
, 0) < a2
)
466 b_start
= make_address(bm2
->addr
, 0);
469 tl_assert(a1
<= b_start
&& b_start
<= a2
);
471 if (make_address(bm2
->addr
+ 1, 0) < a2
)
472 b_end
= make_address(bm2
->addr
+ 1, 0);
475 tl_assert(a1
<= b_end
&& b_end
<= a2
);
476 tl_assert(b_start
< b_end
);
477 tl_assert(address_lsb(b_start
) <= address_lsb(b_end
- 1));
479 for (b0
= address_lsb(b_start
); b0
<= address_lsb(b_end
- 1); b0
++)
482 * Note: the statement below uses a binary or instead of a logical
485 if (bm0_is_set(p1
->bm0_r
, b0
) | bm0_is_set(p1
->bm0_w
, b0
))
496 * Report whether an access of type access_type at address a is recorded in
499 Bool
DRD_(bm_has_1
)(struct bitmap
* const bm
,
500 const Addr a
, const BmAccessTypeT access_type
)
502 const struct bitmap2
* p2
;
503 const struct bitmap1
* p1
;
505 const UWord a0
= address_lsb(a
);
509 p2
= bm2_lookup(bm
, address_msb(a
));
513 p0
= (access_type
== eLoad
) ? p1
->bm0_r
: p1
->bm0_w
;
514 return bm0_is_set(p0
, a0
) ? True
: False
;
519 void DRD_(bm_clear
)(struct bitmap
* const bm
, Addr a1
, Addr a2
)
526 tl_assert(a1
== first_address_with_same_lsb(a1
));
527 tl_assert(a2
== first_address_with_same_lsb(a2
));
529 for (b
= a1
; b
< a2
; b
= b_next
)
534 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
535 tl_assert(a1
<= b
&& b
< a2
);
538 p2
= bm2_lookup_exclusive(bm
, address_msb(b
));
540 b_next
= first_address_with_higher_msb(b
);
550 /* If the first address in the bitmap that must be cleared does not */
551 /* start on an UWord boundary, start clearing the first addresses. */
552 if (uword_lsb(address_lsb(c
)))
554 Addr c_next
= first_address_with_higher_uword_msb(c
);
557 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
558 tl_assert(a1
<= b
&& b
<= c
&& c
<= c_next
&& c_next
<= b_next
561 bm0_clear_range(p2
->bm1
.bm0_r
, address_lsb(c
), SCALED_SIZE(c_next
- c
));
562 bm0_clear_range(p2
->bm1
.bm0_w
, address_lsb(c
), SCALED_SIZE(c_next
- c
));
565 /* If some UWords have to be cleared entirely, do this now. */
566 if (uword_lsb(address_lsb(c
)) == 0)
568 Addr c_next
= first_address_with_same_uword_lsb(b_next
);
569 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
570 tl_assert(uword_lsb(address_lsb(c
)) == 0);
571 tl_assert(uword_lsb(address_lsb(c_next
)) == 0);
572 tl_assert(c_next
<= b_next
);
576 UWord idx
= uword_msb(address_lsb(c
));
577 VG_(memset
)(&p2
->bm1
.bm0_r
[idx
], 0, SCALED_SIZE((c_next
- c
) / 8));
578 VG_(memset
)(&p2
->bm1
.bm0_w
[idx
], 0, SCALED_SIZE((c_next
- c
) / 8));
582 /* If the last address in the bitmap that must be cleared does not */
583 /* fall on an UWord boundary, clear the last addresses. */
584 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
585 tl_assert(a1
<= b
&& b
<= c
&& c
<= b_next
&& b_next
<= a2
);
587 bm0_clear_range(p2
->bm1
.bm0_r
, address_lsb(c
), SCALED_SIZE(b_next
- c
));
588 bm0_clear_range(p2
->bm1
.bm0_w
, address_lsb(c
), SCALED_SIZE(b_next
- c
));
593 * Clear all references to loads in bitmap bm starting at address a1 and
594 * up to but not including address a2.
596 void DRD_(bm_clear_load
)(struct bitmap
* const bm
, Addr a1
, Addr a2
)
603 tl_assert(a1
== first_address_with_same_lsb(a1
));
604 tl_assert(a2
== first_address_with_same_lsb(a2
));
606 for (b
= a1
; b
< a2
; b
= b_next
)
611 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
612 tl_assert(a1
<= b
&& b
< a2
);
615 p2
= bm2_lookup_exclusive(bm
, address_msb(b
));
617 b_next
= first_address_with_higher_msb(b
);
627 /* If the first address in the bitmap that must be cleared does not */
628 /* start on an UWord boundary, start clearing the first addresses. */
629 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
630 tl_assert(a1
<= b
&& b
<= c
&& c
< b_next
&& b_next
<= a2
);
632 if (uword_lsb(address_lsb(c
)))
634 Addr c_next
= first_address_with_higher_uword_msb(c
);
637 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
638 tl_assert(a1
<= b
&& b
<= c
&& c
< c_next
&& c_next
<= b_next
641 bm0_clear_range(p2
->bm1
.bm0_r
, address_lsb(c
), SCALED_SIZE(c_next
- c
));
644 /* If some UWords have to be cleared entirely, do this now. */
645 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
646 tl_assert(a1
<= b
&& b
<= c
&& c
<= b_next
&& b_next
<= a2
);
648 if (uword_lsb(address_lsb(c
)) == 0)
650 Addr c_next
= first_address_with_same_uword_lsb(b_next
);
651 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
652 tl_assert(uword_lsb(address_lsb(c
)) == 0);
653 tl_assert(uword_lsb(address_lsb(c_next
)) == 0);
654 tl_assert(a1
<= b
&& b
<= c
&& c
<= c_next
&& c_next
<= b_next
659 UWord idx
= uword_msb(address_lsb(c
));
660 VG_(memset
)(&p2
->bm1
.bm0_r
[idx
], 0, SCALED_SIZE((c_next
- c
) / 8));
664 /* If the last address in the bitmap that must be cleared does not */
665 /* fall on an UWord boundary, clear the last addresses. */
666 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
667 tl_assert(a1
<= b
&& b
<= c
&& c
<= b_next
&& b_next
<= a2
);
669 bm0_clear_range(p2
->bm1
.bm0_r
, address_lsb(c
), SCALED_SIZE(b_next
- c
));
674 * Clear all references to stores in bitmap bm starting at address a1 and
675 * up to but not including address a2.
677 void DRD_(bm_clear_store
)(struct bitmap
* const bm
,
678 const Addr a1
, const Addr a2
)
685 tl_assert(a1
== first_address_with_same_lsb(a1
));
686 tl_assert(a2
== first_address_with_same_lsb(a2
));
688 for (b
= a1
; b
< a2
; b
= b_next
)
693 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
694 tl_assert(a1
<= b
&& b
< a2
);
697 p2
= bm2_lookup_exclusive(bm
, address_msb(b
));
699 b_next
= first_address_with_higher_msb(b
);
709 /* If the first address in the bitmap that must be cleared does not */
710 /* start on an UWord boundary, start clearing the first addresses. */
711 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
712 tl_assert(a1
<= b
&& b
<= c
&& c
< b_next
&& b_next
<= a2
);
714 if (uword_lsb(address_lsb(c
)))
716 Addr c_next
= first_address_with_higher_uword_msb(c
);
719 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
720 tl_assert(a1
<= b
&& b
<= c
&& c
< c_next
&& c_next
<= b_next
723 bm0_clear_range(p2
->bm1
.bm0_w
, address_lsb(c
), SCALED_SIZE(c_next
- c
));
726 /* If some UWords have to be cleared entirely, do this now. */
727 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
728 tl_assert(a1
<= b
&& b
<= c
&& c
<= b_next
&& b_next
<= a2
);
730 if (uword_lsb(address_lsb(c
)) == 0)
732 Addr c_next
= first_address_with_same_uword_lsb(b_next
);
733 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
734 tl_assert(uword_lsb(address_lsb(c
)) == 0);
735 tl_assert(uword_lsb(address_lsb(c_next
)) == 0);
736 tl_assert(a1
<= b
&& b
<= c
&& c
<= c_next
&& c_next
<= b_next
741 UWord idx
= uword_msb(address_lsb(c
));
742 VG_(memset
)(&p2
->bm1
.bm0_w
[idx
], 0, SCALED_SIZE((c_next
- c
) / 8));
746 /* If the last address in the bitmap that must be cleared does not */
747 /* fall on an UWord boundary, clear the last addresses. */
748 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
749 tl_assert(a1
<= b
&& b
<= c
&& c
<= b_next
&& b_next
<= a2
);
751 bm0_clear_range(p2
->bm1
.bm0_w
, address_lsb(c
), SCALED_SIZE(b_next
- c
));
756 * Clear bitmap bm starting at address a1 and up to but not including address
757 * a2. Return True if and only if any of the addresses was set before
760 Bool
DRD_(bm_test_and_clear
)(struct bitmap
* const bm
,
761 const Addr a1
, const Addr a2
)
765 result
= DRD_(bm_has_any_access
)(bm
, a1
, a2
) != 0;
766 DRD_(bm_clear
)(bm
, a1
, a2
);
770 Bool
DRD_(bm_has_conflict_with
)(struct bitmap
* const bm
,
771 const Addr a1
, const Addr a2
,
772 const BmAccessTypeT access_type
)
778 for (b
= a1
; b
< a2
; b
= b_next
)
780 const struct bitmap2
* bm2
= bm2_lookup(bm
, address_msb(b
));
782 b_next
= first_address_with_higher_msb(b
);
793 const struct bitmap1
* const p1
= &bm2
->bm1
;
795 if (make_address(bm2
->addr
, 0) < a1
)
798 if (make_address(bm2
->addr
, 0) < a2
)
799 b_start
= make_address(bm2
->addr
, 0);
802 tl_assert(a1
<= b_start
&& b_start
<= a2
);
804 if (make_address(bm2
->addr
+ 1, 0) < a2
)
805 b_end
= make_address(bm2
->addr
+ 1, 0);
808 tl_assert(a1
<= b_end
&& b_end
<= a2
);
809 tl_assert(b_start
< b_end
);
810 tl_assert(address_lsb(b_start
) <= address_lsb(b_end
- 1));
812 for (b0
= address_lsb(b_start
); b0
<= address_lsb(b_end
- 1); b0
++)
814 if (access_type
== eLoad
)
816 if (bm0_is_set(p1
->bm0_w
, b0
))
823 tl_assert(access_type
== eStore
);
824 if (bm0_is_set(p1
->bm0_r
, b0
)
825 | bm0_is_set(p1
->bm0_w
, b0
))
836 Bool
DRD_(bm_load_has_conflict_with
)(struct bitmap
* const bm
,
837 const Addr a1
, const Addr a2
)
839 return DRD_(bm_has_conflict_with
)(bm
, a1
, a2
, eLoad
);
842 Bool
DRD_(bm_load_1_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
844 return bm_aligned_load_has_conflict_with(bm
, a1
, 1);
847 Bool
DRD_(bm_load_2_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
850 return bm_aligned_load_has_conflict_with(bm
, a1
, 2);
852 return DRD_(bm_has_conflict_with
)(bm
, a1
, a1
+ 2, eLoad
);
855 Bool
DRD_(bm_load_4_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
858 return bm_aligned_load_has_conflict_with(bm
, a1
, 4);
860 return DRD_(bm_has_conflict_with
)(bm
, a1
, a1
+ 4, eLoad
);
863 Bool
DRD_(bm_load_8_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
866 return bm_aligned_load_has_conflict_with(bm
, a1
, 8);
868 return DRD_(bm_has_conflict_with
)(bm
, a1
, a1
+ 8, eLoad
);
871 Bool
DRD_(bm_store_1_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
873 return bm_aligned_store_has_conflict_with(bm
, a1
, 1);
876 Bool
DRD_(bm_store_2_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
879 return bm_aligned_store_has_conflict_with(bm
, a1
, 2);
881 return DRD_(bm_has_conflict_with
)(bm
, a1
, a1
+ 2, eStore
);
884 Bool
DRD_(bm_store_4_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
887 return bm_aligned_store_has_conflict_with(bm
, a1
, 4);
889 return DRD_(bm_has_conflict_with
)(bm
, a1
, a1
+ 4, eStore
);
892 Bool
DRD_(bm_store_8_has_conflict_with
)(struct bitmap
* const bm
, const Addr a1
)
895 return bm_aligned_store_has_conflict_with(bm
, a1
, 8);
897 return DRD_(bm_has_conflict_with
)(bm
, a1
, a1
+ 8, eStore
);
900 Bool
DRD_(bm_store_has_conflict_with
)(struct bitmap
* const bm
,
901 const Addr a1
, const Addr a2
)
903 return DRD_(bm_has_conflict_with
)(bm
, a1
, a2
, eStore
);
907 * Return True if the two bitmaps *lhs and *rhs are identical, and false
910 Bool
DRD_(bm_equal
)(struct bitmap
* const lhs
, struct bitmap
* const rhs
)
912 struct bitmap2
* bm2l
;
913 struct bitmap2
* bm2r
;
915 /* It's not possible to have two independent iterators over the same OSet, */
916 /* so complain if lhs == rhs. */
917 tl_assert(lhs
!= rhs
);
919 VG_(OSetGen_ResetIter
)(lhs
->oset
);
920 VG_(OSetGen_ResetIter
)(rhs
->oset
);
922 for ( ; (bm2l
= VG_(OSetGen_Next
)(lhs
->oset
)) != 0; )
925 && ! DRD_(bm_has_any_access
)(lhs
,
926 make_address(bm2l
->addr
, 0),
927 make_address(bm2l
->addr
+ 1, 0)))
929 bm2l
= VG_(OSetGen_Next
)(lhs
->oset
);
937 bm2r
= VG_(OSetGen_Next
)(rhs
->oset
);
941 while (! DRD_(bm_has_any_access
)(rhs
,
942 make_address(bm2r
->addr
, 0),
943 make_address(bm2r
->addr
+ 1, 0)));
946 tl_assert(DRD_(bm_has_any_access
)(rhs
,
947 make_address(bm2r
->addr
, 0),
948 make_address(bm2r
->addr
+ 1, 0)));
951 && (bm2l
->addr
!= bm2r
->addr
952 || VG_(memcmp
)(&bm2l
->bm1
, &bm2r
->bm1
, sizeof(bm2l
->bm1
)) != 0))
960 bm2r
= VG_(OSetGen_Next
)(rhs
->oset
);
961 } while (bm2r
&& ! DRD_(bm_has_any_access
)(rhs
,
962 make_address(bm2r
->addr
, 0),
963 make_address(bm2r
->addr
+ 1, 0)));
966 tl_assert(DRD_(bm_has_any_access
)(rhs
,
967 make_address(bm2r
->addr
, 0),
968 make_address(bm2r
->addr
+ 1, 0)));
974 void DRD_(bm_swap
)(struct bitmap
* const bm1
, struct bitmap
* const bm2
)
976 OSet
* const tmp
= bm1
->oset
;
977 bm1
->oset
= bm2
->oset
;
981 /** Merge bitmaps *lhs and *rhs into *lhs. */
982 void DRD_(bm_merge2
)(struct bitmap
* const lhs
, struct bitmap
* const rhs
)
984 struct bitmap2
* bm2l
;
985 struct bitmap2
* bm2r
;
988 * It's not possible to have two independent iterators over the same OSet,
989 * so complain if lhs == rhs.
991 tl_assert(lhs
!= rhs
);
993 s_bitmap_merge_count
++;
995 VG_(OSetGen_ResetIter
)(rhs
->oset
);
997 for ( ; (bm2r
= VG_(OSetGen_Next
)(rhs
->oset
)) != 0; )
999 bm2l
= VG_(OSetGen_Lookup
)(lhs
->oset
, &bm2r
->addr
);
1002 tl_assert(bm2l
!= bm2r
);
1003 bm2_merge(bm2l
, bm2r
);
1007 bm2_insert_copy(lhs
, bm2r
);
1012 /** Clear bitmap2::recalc. */
1013 void DRD_(bm_unmark
)(struct bitmap
* bm
)
1015 struct bitmap2
* bm2
;
1017 for (VG_(OSetGen_ResetIter
)(bm
->oset
);
1018 (bm2
= VG_(OSetGen_Next
)(bm
->oset
)) != 0;
1021 bm2
->recalc
= False
;
1026 * Report whether bitmap2::recalc has been set for the second level bitmap
1027 * corresponding to address a.
1029 Bool
DRD_(bm_is_marked
)(struct bitmap
* bm
, const Addr a
)
1031 const struct bitmap2
* bm2
;
1033 bm2
= bm2_lookup(bm
, a
);
1034 return bm2
&& bm2
->recalc
;
1038 * Set bitmap2::recalc in bml for each second level bitmap in bmr that contains
1039 * at least one access.
1041 * @note Any new second-level bitmaps inserted in bml by this function are
1044 void DRD_(bm_mark
)(struct bitmap
* bml
, struct bitmap
* bmr
)
1046 struct bitmap2
* bm2l
;
1047 struct bitmap2
* bm2r
;
1049 for (VG_(OSetGen_ResetIter
)(bmr
->oset
);
1050 (bm2r
= VG_(OSetGen_Next
)(bmr
->oset
)) != 0;
1053 bm2l
= bm2_lookup_or_insert(bml
, bm2r
->addr
);
1054 bm2l
->recalc
= True
;
1058 /** Clear all second-level bitmaps for which bitmap2::recalc == True. */
1059 void DRD_(bm_clear_marked
)(struct bitmap
* bm
)
1061 struct bitmap2
* bm2
;
1063 for (VG_(OSetGen_ResetIter
)(bm
->oset
);
1064 (bm2
= VG_(OSetGen_Next
)(bm
->oset
)) != 0;
1072 /** Merge the second level bitmaps from *rhs into *lhs for which recalc == True. */
1073 void DRD_(bm_merge2_marked
)(struct bitmap
* const lhs
, struct bitmap
* const rhs
)
1075 struct bitmap2
* bm2l
;
1076 struct bitmap2
* bm2r
;
1079 * It's not possible to have two independent iterators over the same OSet,
1080 * so complain if lhs == rhs.
1082 tl_assert(lhs
!= rhs
);
1084 s_bitmap_merge_count
++;
1086 VG_(OSetGen_ResetIter
)(rhs
->oset
);
1088 for ( ; (bm2r
= VG_(OSetGen_Next
)(rhs
->oset
)) != 0; )
1090 bm2l
= VG_(OSetGen_Lookup
)(lhs
->oset
, &bm2r
->addr
);
1091 if (bm2l
&& bm2l
->recalc
)
1093 tl_assert(bm2l
!= bm2r
);
1094 bm2_merge(bm2l
, bm2r
);
1099 /** Remove all marked second-level bitmaps that do not contain any access. */
1100 void DRD_(bm_remove_cleared_marked
)(struct bitmap
* bm
)
1102 struct bitmap2
* bm2
;
1104 VG_(OSetGen_ResetIter
)(bm
->oset
);
1105 for ( ; (bm2
= VG_(OSetGen_Next
)(bm
->oset
)) != 0; )
1107 const UWord a1
= bm2
->addr
;
1109 && ! DRD_(bm_has_any_access(bm
, make_address(a1
, 0),
1110 make_address(a1
+ 1, 0))))
1113 VG_(OSetGen_ResetIterAt
)(bm
->oset
, &a1
);
1119 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
1120 * @param lhs First bitmap.
1121 * @param rhs Bitmap to be compared with lhs.
1122 * @return !=0 if there are data races, == 0 if there are none.
1124 int DRD_(bm_has_races
)(struct bitmap
* const lhs
, struct bitmap
* const rhs
)
1126 VG_(OSetGen_ResetIter
)(lhs
->oset
);
1127 VG_(OSetGen_ResetIter
)(rhs
->oset
);
1131 const struct bitmap2
* bm2l
;
1132 const struct bitmap2
* bm2r
;
1133 const struct bitmap1
* bm1l
;
1134 const struct bitmap1
* bm1r
;
1137 bm2l
= VG_(OSetGen_Next
)(lhs
->oset
);
1138 bm2r
= VG_(OSetGen_Next
)(rhs
->oset
);
1139 while (bm2l
&& bm2r
&& bm2l
->addr
!= bm2r
->addr
)
1141 if (bm2l
->addr
< bm2r
->addr
)
1142 bm2l
= VG_(OSetGen_Next
)(lhs
->oset
);
1144 bm2r
= VG_(OSetGen_Next
)(rhs
->oset
);
1146 if (bm2l
== 0 || bm2r
== 0)
1152 for (k
= 0; k
< BITMAP1_UWORD_COUNT
; k
++)
1155 for (b
= 0; b
< BITS_PER_UWORD
; b
++)
1157 UWord
const access_mask
1158 = ((bm1l
->bm0_r
[k
] & bm0_mask(b
)) ? LHS_R
: 0)
1159 | ((bm1l
->bm0_w
[k
] & bm0_mask(b
)) ? LHS_W
: 0)
1160 | ((bm1r
->bm0_r
[k
] & bm0_mask(b
)) ? RHS_R
: 0)
1161 | ((bm1r
->bm0_w
[k
] & bm0_mask(b
)) ? RHS_W
: 0);
1162 Addr
const a
= make_address(bm2l
->addr
, k
* BITS_PER_UWORD
| b
);
1163 if (HAS_RACE(access_mask
) && ! DRD_(is_suppressed
)(a
, a
+ 1))
1173 void DRD_(bm_print
)(struct bitmap
* const bm
)
1175 struct bitmap2
* bm2
;
1177 for (VG_(OSetGen_ResetIter
)(bm
->oset
);
1178 (bm2
= VG_(OSetGen_Next
)(bm
->oset
)) != 0;
1185 static void bm2_print(const struct bitmap2
* const bm2
)
1187 const struct bitmap1
* bm1
;
1193 for (a
= make_address(bm2
->addr
, 0);
1194 a
<= make_address(bm2
->addr
+ 1, 0) - 1;
1197 const Bool r
= bm0_is_set(bm1
->bm0_r
, address_lsb(a
)) != 0;
1198 const Bool w
= bm0_is_set(bm1
->bm0_w
, address_lsb(a
)) != 0;
1201 VG_(printf
)("0x%08lx %c %c\n",
1209 ULong
DRD_(bm_get_bitmap_creation_count
)(void)
1211 return s_bitmap_creation_count
;
1214 ULong
DRD_(bm_get_bitmap2_creation_count
)(void)
1216 return s_bitmap2_creation_count
;
1219 ULong
DRD_(bm_get_bitmap2_merge_count
)(void)
1221 return s_bitmap2_merge_count
;
1224 /** Compute *bm2l |= *bm2r. */
1226 void bm2_merge(struct bitmap2
* const bm2l
, const struct bitmap2
* const bm2r
)
1232 tl_assert(bm2l
->addr
== bm2r
->addr
);
1234 s_bitmap2_merge_count
++;
1236 for (k
= 0; k
< BITMAP1_UWORD_COUNT
; k
++)
1238 bm2l
->bm1
.bm0_r
[k
] |= bm2r
->bm1
.bm0_r
[k
];
1240 for (k
= 0; k
< BITMAP1_UWORD_COUNT
; k
++)
1242 bm2l
->bm1
.bm0_w
[k
] |= bm2r
->bm1
.bm0_w
[k
];