blob: 912065b38c660c42fc8229a62987a50d69154287 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
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.
11
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.
16
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
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
26#include "pub_tool_basics.h" // Addr, SizeT
27#include "pub_tool_debuginfo.h" // VG_(get_objname)()
28#include "pub_tool_libcassert.h" // tl_assert()
29#include "pub_tool_libcbase.h" // VG_(memset)
30#include "pub_tool_libcprint.h" // VG_(printf)
31#include "pub_tool_machine.h" // VG_(get_IP)()
32#include "pub_tool_mallocfree.h" // VG_(malloc), VG_(free)
33#include "pub_drd_bitmap.h"
34#include "drd_bitmap.h"
35#include "drd_error.h"
36#include "drd_suppression.h"
37
38
39// Local constants.
40
41static ULong s_bitmap_creation_count;
42
43
44// Local function declarations.
45
46static void bm2_merge(struct bitmap2* const bm2l,
47 const struct bitmap2* const bm2r);
48
49
50// Function definitions.
51
52struct bitmap* bm_new()
53{
bart3772a982008-03-15 08:11:03 +000054 struct bitmap* bm;
sewardjaf44c822007-11-25 14:01:38 +000055
bart3772a982008-03-15 08:11:03 +000056 // If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD
57 // in drd_bitmap.h.
58 tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD);
sewardjaf44c822007-11-25 14:01:38 +000059
bart3772a982008-03-15 08:11:03 +000060 bm = VG_(malloc)(sizeof(*bm));
61 tl_assert(bm);
barte1d4aa62008-03-16 08:39:19 +000062 bm->last_lookup_a1 = 0;
63 bm->last_lookup_result = 0;
64 bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
sewardjaf44c822007-11-25 14:01:38 +000065
bart3772a982008-03-15 08:11:03 +000066 s_bitmap_creation_count++;
sewardjaf44c822007-11-25 14:01:38 +000067
bart3772a982008-03-15 08:11:03 +000068 return bm;
sewardjaf44c822007-11-25 14:01:38 +000069}
70
71void bm_delete(struct bitmap* const bm)
72{
bart3772a982008-03-15 08:11:03 +000073 tl_assert(bm);
74 VG_(OSetGen_Destroy)(bm->oset);
75 VG_(free)(bm);
sewardjaf44c822007-11-25 14:01:38 +000076}
77
78/**
bart36556122008-03-13 19:24:30 +000079 * Record an access of type access_type at addresses a .. a + size - 1 in
sewardjaf44c822007-11-25 14:01:38 +000080 * bitmap bm.
81 */
barta79df6e2008-03-14 17:07:51 +000082static
sewardjaf44c822007-11-25 14:01:38 +000083void bm_access_range(struct bitmap* const bm,
bart9036dea2008-03-13 19:10:06 +000084 const Addr a1, const Addr a2,
bart0268dfa2008-03-11 20:10:21 +000085 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +000086{
bart3772a982008-03-15 08:11:03 +000087 Addr b, b_next;
bart36556122008-03-13 19:24:30 +000088
bart3772a982008-03-15 08:11:03 +000089 tl_assert(bm);
90 tl_assert(a1 < a2);
sewardjaf44c822007-11-25 14:01:38 +000091
bart3772a982008-03-15 08:11:03 +000092 for (b = a1; b < a2; b = b_next)
93 {
94 Addr b_start;
95 Addr b_end;
96 struct bitmap2* bm2;
97 SPLIT_ADDRESS(b);
bart36556122008-03-13 19:24:30 +000098
bart3772a982008-03-15 08:11:03 +000099 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
100 if (b_next > a2)
101 {
102 b_next = a2;
103 }
bart36556122008-03-13 19:24:30 +0000104
bart3772a982008-03-15 08:11:03 +0000105 bm2 = bm2_lookup_or_insert(bm, b1);
106 tl_assert(bm2);
bart36556122008-03-13 19:24:30 +0000107
bart3772a982008-03-15 08:11:03 +0000108 if ((bm2->addr << ADDR0_BITS) < a1)
109 b_start = a1;
110 else
111 if ((bm2->addr << ADDR0_BITS) < a2)
112 b_start = (bm2->addr << ADDR0_BITS);
bart36556122008-03-13 19:24:30 +0000113 else
bart3772a982008-03-15 08:11:03 +0000114 break;
115 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000116
bart3772a982008-03-15 08:11:03 +0000117 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
118 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
119 else
120 b_end = a2;
121 tl_assert(a1 <= b_end && b_end <= a2);
122 tl_assert(b_start < b_end);
123 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000124
bart3772a982008-03-15 08:11:03 +0000125 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
126 {
127 if (access_type == eLoad)
bart36556122008-03-13 19:24:30 +0000128 {
bart3772a982008-03-15 08:11:03 +0000129 bm0_set(bm2->bm1.bm0_r, b0);
sewardjaf44c822007-11-25 14:01:38 +0000130 }
bart3772a982008-03-15 08:11:03 +0000131 else
132 {
133 bm0_set(bm2->bm1.bm0_w, b0);
134 }
135 }
136 }
sewardjaf44c822007-11-25 14:01:38 +0000137}
138
barta79df6e2008-03-14 17:07:51 +0000139static inline
140void bm_access_aligned_load(struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000141 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000142{
bart3772a982008-03-15 08:11:03 +0000143 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000144
bart3772a982008-03-15 08:11:03 +0000145 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
bartf8bc71d2008-03-15 11:42:34 +0000146 bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size);
barta79df6e2008-03-14 17:07:51 +0000147}
148
149static inline
150void bm_access_aligned_store(struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000151 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000152{
bart3772a982008-03-15 08:11:03 +0000153 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000154
bart3772a982008-03-15 08:11:03 +0000155 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
bartf8bc71d2008-03-15 11:42:34 +0000156 bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size);
barta79df6e2008-03-14 17:07:51 +0000157}
158
bart36556122008-03-13 19:24:30 +0000159void bm_access_range_load(struct bitmap* const bm,
160 const Addr a1, const Addr a2)
161{
bart3772a982008-03-15 08:11:03 +0000162 bm_access_range(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000163}
164
barta79df6e2008-03-14 17:07:51 +0000165void bm_access_load_1(struct bitmap* const bm, const Addr a1)
166{
bartf8bc71d2008-03-15 11:42:34 +0000167 bm_access_aligned_load(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000168}
169
170void bm_access_load_2(struct bitmap* const bm, const Addr a1)
171{
bart3772a982008-03-15 08:11:03 +0000172 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000173 bm_access_aligned_load(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000174 else
175 bm_access_range(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000176}
177
178void bm_access_load_4(struct bitmap* const bm, const Addr a1)
179{
bart3772a982008-03-15 08:11:03 +0000180 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000181 bm_access_aligned_load(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000182 else
183 bm_access_range(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000184}
185
186void bm_access_load_8(struct bitmap* const bm, const Addr a1)
187{
bart3772a982008-03-15 08:11:03 +0000188 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000189 bm_access_aligned_load(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000190 else if ((a1 & 3) == 0)
191 {
bartf8bc71d2008-03-15 11:42:34 +0000192 bm_access_aligned_load(bm, a1 + 0, 4);
193 bm_access_aligned_load(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000194 }
195 else
196 bm_access_range(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000197}
198
199void bm_access_store_1(struct bitmap* const bm, const Addr a1)
200{
bartf8bc71d2008-03-15 11:42:34 +0000201 bm_access_aligned_store(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000202}
203
204void bm_access_store_2(struct bitmap* const bm, const Addr a1)
205{
bart3772a982008-03-15 08:11:03 +0000206 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000207 bm_access_aligned_store(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000208 else
209 bm_access_range(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000210}
211
212void bm_access_store_4(struct bitmap* const bm, const Addr a1)
213{
bart3772a982008-03-15 08:11:03 +0000214 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000215 bm_access_aligned_store(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000216 else
217 bm_access_range(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000218}
219
220void bm_access_store_8(struct bitmap* const bm, const Addr a1)
221{
bart3772a982008-03-15 08:11:03 +0000222 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000223 bm_access_aligned_store(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000224 else if ((a1 & 3) == 0)
225 {
bartf8bc71d2008-03-15 11:42:34 +0000226 bm_access_aligned_store(bm, a1 + 0, 4);
227 bm_access_aligned_store(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000228 }
229 else
230 bm_access_range(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000231}
232
bart36556122008-03-13 19:24:30 +0000233void bm_access_range_store(struct bitmap* const bm,
234 const Addr a1, const Addr a2)
235{
bart3772a982008-03-15 08:11:03 +0000236 bm_access_range(bm, a1, a2, eStore);
bart36556122008-03-13 19:24:30 +0000237}
238
239Bool bm_has(const struct bitmap* const bm, const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000240 const BmAccessTypeT access_type)
241{
bart3772a982008-03-15 08:11:03 +0000242 Addr b;
243 for (b = a1; b < a2; b++)
244 {
245 if (! bm_has_1(bm, b, access_type))
246 {
247 return False;
248 }
249 }
250 return True;
sewardjaf44c822007-11-25 14:01:38 +0000251}
252
253Bool bm_has_any(const struct bitmap* const bm,
bart36556122008-03-13 19:24:30 +0000254 const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000255 const BmAccessTypeT access_type)
256{
bart3772a982008-03-15 08:11:03 +0000257 Addr b;
sewardjaf44c822007-11-25 14:01:38 +0000258
bart3772a982008-03-15 08:11:03 +0000259 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000260
bart3772a982008-03-15 08:11:03 +0000261 for (b = a1; b < a2; b++)
262 {
263 if (bm_has_1(bm, b, access_type))
264 {
265 return True;
266 }
267 }
268 return False;
sewardjaf44c822007-11-25 14:01:38 +0000269}
270
271/* Return a non-zero value if there is a read access, write access or both */
272/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
273UWord bm_has_any_access(const struct bitmap* const bm,
274 const Addr a1,
275 const Addr a2)
276{
bart3772a982008-03-15 08:11:03 +0000277 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000278
bart3772a982008-03-15 08:11:03 +0000279 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000280
bart3772a982008-03-15 08:11:03 +0000281 for (b = a1; b < a2; b = b_next)
282 {
bart11d0b502008-03-22 16:44:03 +0000283 struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000284
bart3772a982008-03-15 08:11:03 +0000285 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
286 if (b_next > a2)
287 {
288 b_next = a2;
289 }
sewardjaf44c822007-11-25 14:01:38 +0000290
bart3772a982008-03-15 08:11:03 +0000291 if (bm2)
292 {
293 Addr b_start;
294 Addr b_end;
295 UWord b0;
296 const struct bitmap1* const p1 = &bm2->bm1;
sewardjaf44c822007-11-25 14:01:38 +0000297
bart3772a982008-03-15 08:11:03 +0000298 if ((bm2->addr << ADDR0_BITS) < a1)
299 b_start = a1;
300 else
301 if ((bm2->addr << ADDR0_BITS) < a2)
302 b_start = (bm2->addr << ADDR0_BITS);
303 else
304 break;
305 tl_assert(a1 <= b_start && b_start <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000306
bart3772a982008-03-15 08:11:03 +0000307 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
308 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
309 else
310 b_end = a2;
311 tl_assert(a1 <= b_end && b_end <= a2);
312 tl_assert(b_start < b_end);
313 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
sewardjaf44c822007-11-25 14:01:38 +0000314
bart3772a982008-03-15 08:11:03 +0000315 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
316 {
317 const UWord mask
318 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
319 if (mask)
320 {
321 return mask;
322 }
sewardjaf44c822007-11-25 14:01:38 +0000323 }
bart3772a982008-03-15 08:11:03 +0000324 }
325 }
326 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000327}
328
329/**
330 * Report whether an access of type access_type at address a is recorded in
331 * bitmap bm.
332 * @return != 0 means true, and == 0 means false
333 */
334UWord bm_has_1(const struct bitmap* const bm,
335 const Addr a,
336 const BmAccessTypeT access_type)
337{
bart3772a982008-03-15 08:11:03 +0000338 struct bitmap2* p2;
339 struct bitmap1* p1;
340 UWord* p0;
341 const UWord a0 = a & ADDR0_MASK;
sewardjaf44c822007-11-25 14:01:38 +0000342
bart3772a982008-03-15 08:11:03 +0000343 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000344
bart11d0b502008-03-22 16:44:03 +0000345 p2 = bm2_lookup(bm, a >> ADDR0_BITS);
bart3772a982008-03-15 08:11:03 +0000346 if (p2)
347 {
348 p1 = &p2->bm1;
349 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
350 return bm0_is_set(p0, a0);
351 }
352 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000353}
354
355static __inline__
356void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
357{
bart3772a982008-03-15 08:11:03 +0000358 UWord idx;
359 UWord mask;
sewardjaf44c822007-11-25 14:01:38 +0000360
361#if 0
bart3772a982008-03-15 08:11:03 +0000362 /* Commented out the statements below because of performance reasons. */
363 tl_assert(a1);
364 tl_assert(a1 <= a2);
365 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
366 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
sewardjaf44c822007-11-25 14:01:38 +0000367#endif
368
bart3772a982008-03-15 08:11:03 +0000369 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
370 /* mask: a contiguous series of one bits. The first bit set is bit */
371 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
372 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
373 bm1->bm0_r[idx] &= ~mask;
374 bm1->bm0_w[idx] &= ~mask;
sewardjaf44c822007-11-25 14:01:38 +0000375}
376
377void bm_clear_all(const struct bitmap* const bm)
378{
bart3772a982008-03-15 08:11:03 +0000379 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000380
bart3772a982008-03-15 08:11:03 +0000381 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000382
bart3772a982008-03-15 08:11:03 +0000383 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
384 {
385 struct bitmap1* const bm1 = &bm2->bm1;
386 tl_assert(bm1);
387 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
388 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
389 }
sewardjaf44c822007-11-25 14:01:38 +0000390}
391
sewardjaf44c822007-11-25 14:01:38 +0000392void bm_clear(const struct bitmap* const bm,
393 const Addr a1,
394 const Addr a2)
395{
bart3772a982008-03-15 08:11:03 +0000396 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000397
bart3772a982008-03-15 08:11:03 +0000398 tl_assert(bm);
399 tl_assert(a1);
400 tl_assert(a1 <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000401
bart3772a982008-03-15 08:11:03 +0000402 for (b = a1; b < a2; b = b_next)
403 {
bart11d0b502008-03-22 16:44:03 +0000404 struct bitmap2* const p2 = bm2_lookup(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000405
bart3772a982008-03-15 08:11:03 +0000406 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
407 if (b_next > a2)
408 {
409 b_next = a2;
410 }
411
412 if (p2)
413 {
414 Addr c = b;
415 if (UWORD_LSB(c))
sewardjaf44c822007-11-25 14:01:38 +0000416 {
bart3772a982008-03-15 08:11:03 +0000417 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
418 if (c_next > b_next)
419 c_next = b_next;
420 bm1_clear(&p2->bm1, c, c_next);
421 c = c_next;
sewardjaf44c822007-11-25 14:01:38 +0000422 }
bart3772a982008-03-15 08:11:03 +0000423 if (UWORD_LSB(c) == 0)
sewardjaf44c822007-11-25 14:01:38 +0000424 {
bart3772a982008-03-15 08:11:03 +0000425 const Addr c_next = UWORD_MSB(b_next);
426 tl_assert(UWORD_LSB(c) == 0);
427 tl_assert(UWORD_LSB(c_next) == 0);
428 tl_assert(c_next <= b_next);
429 tl_assert(c <= c_next);
430 if (c_next > c)
431 {
432 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
433 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
434 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
435 c = c_next;
436 }
sewardjaf44c822007-11-25 14:01:38 +0000437 }
bart3772a982008-03-15 08:11:03 +0000438 if (c != b_next)
439 {
440 bm1_clear(&p2->bm1, c, b_next);
441 }
442 }
443 }
sewardjaf44c822007-11-25 14:01:38 +0000444}
sewardjaf44c822007-11-25 14:01:38 +0000445
bart36556122008-03-13 19:24:30 +0000446Bool bm_has_conflict_with(const struct bitmap* const bm,
447 const Addr a1, const Addr a2,
448 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000449{
bart3772a982008-03-15 08:11:03 +0000450 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000451
bart3772a982008-03-15 08:11:03 +0000452 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000453
bart3772a982008-03-15 08:11:03 +0000454 for (b = a1; b < a2; b = b_next)
455 {
bart11d0b502008-03-22 16:44:03 +0000456 struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
bart36556122008-03-13 19:24:30 +0000457
bart3772a982008-03-15 08:11:03 +0000458 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
459 if (b_next > a2)
460 {
461 b_next = a2;
462 }
bart36556122008-03-13 19:24:30 +0000463
bart3772a982008-03-15 08:11:03 +0000464 if (bm2)
465 {
466 Addr b_start;
467 Addr b_end;
468 UWord b0;
469 const struct bitmap1* const p1 = &bm2->bm1;
bart36556122008-03-13 19:24:30 +0000470
bart3772a982008-03-15 08:11:03 +0000471 if ((bm2->addr << ADDR0_BITS) < a1)
472 b_start = a1;
473 else
474 if ((bm2->addr << ADDR0_BITS) < a2)
475 b_start = (bm2->addr << ADDR0_BITS);
476 else
477 break;
478 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000479
bart3772a982008-03-15 08:11:03 +0000480 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
481 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
482 else
483 b_end = a2;
484 tl_assert(a1 <= b_end && b_end <= a2);
485 tl_assert(b_start < b_end);
486 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000487
bart3772a982008-03-15 08:11:03 +0000488 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
489 {
490 if (access_type == eLoad)
491 {
492 if (bm0_is_set(p1->bm0_w, b0))
493 {
494 return True;
495 }
496 }
497 else
498 {
499 tl_assert(access_type == eStore);
500 if (bm0_is_set(p1->bm0_r, b0)
501 | bm0_is_set(p1->bm0_w, b0))
502 {
503 return True;
504 }
505 }
sewardjaf44c822007-11-25 14:01:38 +0000506 }
bart3772a982008-03-15 08:11:03 +0000507 }
508 }
509 return False;
sewardjaf44c822007-11-25 14:01:38 +0000510}
511
barta79df6e2008-03-14 17:07:51 +0000512static inline
513Bool bm_aligned_load_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000514 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000515{
bart3772a982008-03-15 08:11:03 +0000516 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000517
bart11d0b502008-03-22 16:44:03 +0000518 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
barta79df6e2008-03-14 17:07:51 +0000519
bartf8bc71d2008-03-15 11:42:34 +0000520 return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size));
barta79df6e2008-03-14 17:07:51 +0000521}
522
523static inline
524Bool bm_aligned_store_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000525 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000526{
bart3772a982008-03-15 08:11:03 +0000527 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000528
bart11d0b502008-03-22 16:44:03 +0000529 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
barta79df6e2008-03-14 17:07:51 +0000530
bart3772a982008-03-15 08:11:03 +0000531 if (bm2)
532 {
bartf8bc71d2008-03-15 11:42:34 +0000533 if (bm0_is_any_set(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size)
534 | bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size))
bart3772a982008-03-15 08:11:03 +0000535 {
536 return True;
537 }
538 }
539 return False;
barta79df6e2008-03-14 17:07:51 +0000540}
541
bart36556122008-03-13 19:24:30 +0000542Bool bm_load_has_conflict_with(const struct bitmap* const bm,
543 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000544{
bart3772a982008-03-15 08:11:03 +0000545 return bm_has_conflict_with(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000546}
547
barta79df6e2008-03-14 17:07:51 +0000548Bool bm_load_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
549{
bartf8bc71d2008-03-15 11:42:34 +0000550 return bm_aligned_load_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000551}
552
553Bool bm_load_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
554{
bart3772a982008-03-15 08:11:03 +0000555 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000556 return bm_aligned_load_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000557 else
558 return bm_has_conflict_with(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000559}
560
561Bool bm_load_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
562{
bart3772a982008-03-15 08:11:03 +0000563 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000564 return bm_aligned_load_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000565 else
566 return bm_has_conflict_with(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000567}
568
569Bool bm_load_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
570{
bart3772a982008-03-15 08:11:03 +0000571 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000572 return bm_aligned_load_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000573 else
574 return bm_has_conflict_with(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000575}
576
577Bool bm_store_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
578{
bartf8bc71d2008-03-15 11:42:34 +0000579 return bm_aligned_store_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000580}
581
582Bool bm_store_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
583{
bart3772a982008-03-15 08:11:03 +0000584 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000585 return bm_aligned_store_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000586 else
587 return bm_has_conflict_with(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000588}
589
590Bool bm_store_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
591{
bart3772a982008-03-15 08:11:03 +0000592 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000593 return bm_aligned_store_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000594 else
595 return bm_has_conflict_with(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000596}
597
598Bool bm_store_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
599{
bart3772a982008-03-15 08:11:03 +0000600 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000601 return bm_aligned_store_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000602 else
603 return bm_has_conflict_with(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000604}
605
bart36556122008-03-13 19:24:30 +0000606Bool bm_store_has_conflict_with(const struct bitmap* const bm,
607 const Addr a1, const Addr a2)
608{
bart3772a982008-03-15 08:11:03 +0000609 return bm_has_conflict_with(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000610}
611
612void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
613{
bart3772a982008-03-15 08:11:03 +0000614 OSet* const tmp = bm1->oset;
615 bm1->oset = bm2->oset;
616 bm2->oset = tmp;
sewardjaf44c822007-11-25 14:01:38 +0000617}
618
619void bm_merge2(struct bitmap* const lhs,
620 const struct bitmap* const rhs)
621{
bart3772a982008-03-15 08:11:03 +0000622 struct bitmap2* bm2l;
623 const struct bitmap2* bm2r;
sewardjaf44c822007-11-25 14:01:38 +0000624
bart3772a982008-03-15 08:11:03 +0000625 // First step: allocate any missing bitmaps in *lhs.
626 VG_(OSetGen_ResetIter)(rhs->oset);
627 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
628 {
629 bm2_lookup_or_insert(lhs, bm2r->addr);
630 }
sewardjaf44c822007-11-25 14:01:38 +0000631
bart3772a982008-03-15 08:11:03 +0000632 VG_(OSetGen_ResetIter)(lhs->oset);
633 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000634
bart3772a982008-03-15 08:11:03 +0000635 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
636 {
637 do
638 {
639 bm2l = VG_(OSetGen_Next)(lhs->oset);
640 } while (bm2l->addr < bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000641
bart3772a982008-03-15 08:11:03 +0000642 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000643
bart3772a982008-03-15 08:11:03 +0000644 bm2_merge(bm2l, bm2r);
645 }
sewardjaf44c822007-11-25 14:01:38 +0000646}
647
648/**
649 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
650 * @param lhs First bitmap.
651 * @param rhs Bitmap to be compared with lhs.
652 * @return !=0 if there are data races, == 0 if there are none.
653 */
654int bm_has_races(const struct bitmap* const lhs,
655 const struct bitmap* const rhs)
656{
bart3772a982008-03-15 08:11:03 +0000657 VG_(OSetGen_ResetIter)(lhs->oset);
658 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000659
bart3772a982008-03-15 08:11:03 +0000660 for (;;)
661 {
662 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
663 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
664 const struct bitmap1* bm1l;
665 const struct bitmap1* bm1r;
666 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000667
bart3772a982008-03-15 08:11:03 +0000668 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
669 {
670 if (bm2l->addr < bm2r->addr)
671 bm2l = VG_(OSetGen_Next)(lhs->oset);
672 else
673 bm2r = VG_(OSetGen_Next)(rhs->oset);
674 }
675 if (bm2l == 0 || bm2r == 0)
676 break;
677
678 bm1l = &bm2l->bm1;
679 bm1r = &bm2r->bm1;
680
681 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
682 {
683 unsigned b;
684 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000685 {
bart3772a982008-03-15 08:11:03 +0000686 UWord const access
687 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
688 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
689 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
690 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
691 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
692 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
693 {
694 return 1;
695 }
sewardjaf44c822007-11-25 14:01:38 +0000696 }
bart3772a982008-03-15 08:11:03 +0000697 }
698 }
699 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000700}
701
sewardjaf44c822007-11-25 14:01:38 +0000702void bm_print(const struct bitmap* const bm)
703{
bart3772a982008-03-15 08:11:03 +0000704 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000705
bart3772a982008-03-15 08:11:03 +0000706 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000707
bart3772a982008-03-15 08:11:03 +0000708 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
709 {
710 const struct bitmap1* const bm1 = &bm2->bm1;
711 unsigned k;
712 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
713 {
714 unsigned b;
715 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000716 {
bart3772a982008-03-15 08:11:03 +0000717 int const r = bm1->bm0_r[k] & bm0_mask(b);
718 int const w = bm1->bm0_w[k] & bm0_mask(b);
719 Addr const a = MAKE_ADDRESS(bm2->addr, k * BITS_PER_UWORD | b);
720 if (r || w)
721 {
722 VG_(printf)("0x%08lx %c %c\n",
723 (Addr)(a),
724 w ? 'W' : ' ', r ? 'R' : ' ');
725 }
sewardjaf44c822007-11-25 14:01:38 +0000726 }
bart3772a982008-03-15 08:11:03 +0000727 }
728 }
sewardjaf44c822007-11-25 14:01:38 +0000729}
730
731ULong bm_get_bitmap_creation_count(void)
732{
bart3772a982008-03-15 08:11:03 +0000733 return s_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000734}
735
736ULong bm_get_bitmap2_creation_count(void)
737{
bart3772a982008-03-15 08:11:03 +0000738 return s_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000739}
740
741static void bm2_merge(struct bitmap2* const bm2l,
742 const struct bitmap2* const bm2r)
743{
bart3772a982008-03-15 08:11:03 +0000744 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000745
bart3772a982008-03-15 08:11:03 +0000746 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000747
bart3772a982008-03-15 08:11:03 +0000748 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
749 {
750 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
751 }
752 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
753 {
754 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
755 }
sewardjaf44c822007-11-25 14:01:38 +0000756}
757
758#if 0
759
760/* Unit test */
761static
762struct { Addr address; SizeT size; BmAccessTypeT access_type; }
bart3772a982008-03-15 08:11:03 +0000763 s_args[] = {
764 { 0, 1, eLoad },
765 { 666, 4, eLoad },
766 { 667, 2, eStore },
767 { 1024, 1, eStore },
768 { 0x0000ffff, 1, eLoad },
769 { 0x0001ffff, 1, eLoad },
770 { 0x00ffffff, 1, eLoad },
771 { 0xffffffff, 1, eStore },
772 };
sewardjaf44c822007-11-25 14:01:38 +0000773
774void bm_test(void)
775{
bart3772a982008-03-15 08:11:03 +0000776 struct bitmap* bm;
777 struct bitmap* bm2;
778 int i, j;
sewardjaf44c822007-11-25 14:01:38 +0000779
bart3772a982008-03-15 08:11:03 +0000780 VG_(printf)("Start of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000781
bart3772a982008-03-15 08:11:03 +0000782 bm = bm_new();
sewardjaf44c822007-11-25 14:01:38 +0000783
bart3772a982008-03-15 08:11:03 +0000784 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
785 {
786 bm_access_range(bm,
787 s_args[i].address,
788 s_args[i].address + s_args[i].size,
789 s_args[i].access_type);
790 }
sewardjaf44c822007-11-25 14:01:38 +0000791
bart3772a982008-03-15 08:11:03 +0000792 VG_(printf)("Map contents -- should contain 10 addresses:\n");
793 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000794
bart3772a982008-03-15 08:11:03 +0000795 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
796 {
797 for (j = 0; j < s_args[i].size; j++)
798 {
799 tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
800 }
801 }
sewardjaf44c822007-11-25 14:01:38 +0000802
bart3772a982008-03-15 08:11:03 +0000803 VG_(printf)("Merge result:\n");
804 bm2 = bm_merge(bm, bm);
805 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000806
bart3772a982008-03-15 08:11:03 +0000807 bm_delete(bm);
808 bm_delete(bm2);
sewardjaf44c822007-11-25 14:01:38 +0000809
bart3772a982008-03-15 08:11:03 +0000810 VG_(printf)("End of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000811}
812#endif