blob: 3ff24d759df1f9457901d791939ed1f4e34180f4 [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);
62 bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
sewardjaf44c822007-11-25 14:01:38 +000063
bart3772a982008-03-15 08:11:03 +000064 s_bitmap_creation_count++;
sewardjaf44c822007-11-25 14:01:38 +000065
bart3772a982008-03-15 08:11:03 +000066 return bm;
sewardjaf44c822007-11-25 14:01:38 +000067}
68
69void bm_delete(struct bitmap* const bm)
70{
bart3772a982008-03-15 08:11:03 +000071 tl_assert(bm);
72 VG_(OSetGen_Destroy)(bm->oset);
73 VG_(free)(bm);
sewardjaf44c822007-11-25 14:01:38 +000074}
75
76/**
bart36556122008-03-13 19:24:30 +000077 * Record an access of type access_type at addresses a .. a + size - 1 in
sewardjaf44c822007-11-25 14:01:38 +000078 * bitmap bm.
79 */
barta79df6e2008-03-14 17:07:51 +000080static
sewardjaf44c822007-11-25 14:01:38 +000081void bm_access_range(struct bitmap* const bm,
bart9036dea2008-03-13 19:10:06 +000082 const Addr a1, const Addr a2,
bart0268dfa2008-03-11 20:10:21 +000083 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +000084{
bart3772a982008-03-15 08:11:03 +000085 Addr b, b_next;
bart36556122008-03-13 19:24:30 +000086
bart3772a982008-03-15 08:11:03 +000087 tl_assert(bm);
88 tl_assert(a1 < a2);
sewardjaf44c822007-11-25 14:01:38 +000089
bart3772a982008-03-15 08:11:03 +000090 for (b = a1; b < a2; b = b_next)
91 {
92 Addr b_start;
93 Addr b_end;
94 struct bitmap2* bm2;
95 SPLIT_ADDRESS(b);
bart36556122008-03-13 19:24:30 +000096
bart3772a982008-03-15 08:11:03 +000097 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
98 if (b_next > a2)
99 {
100 b_next = a2;
101 }
bart36556122008-03-13 19:24:30 +0000102
bart3772a982008-03-15 08:11:03 +0000103 bm2 = bm2_lookup_or_insert(bm, b1);
104 tl_assert(bm2);
bart36556122008-03-13 19:24:30 +0000105
bart3772a982008-03-15 08:11:03 +0000106 if ((bm2->addr << ADDR0_BITS) < a1)
107 b_start = a1;
108 else
109 if ((bm2->addr << ADDR0_BITS) < a2)
110 b_start = (bm2->addr << ADDR0_BITS);
bart36556122008-03-13 19:24:30 +0000111 else
bart3772a982008-03-15 08:11:03 +0000112 break;
113 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000114
bart3772a982008-03-15 08:11:03 +0000115 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
116 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
117 else
118 b_end = a2;
119 tl_assert(a1 <= b_end && b_end <= a2);
120 tl_assert(b_start < b_end);
121 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000122
bart3772a982008-03-15 08:11:03 +0000123 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
124 {
125 if (access_type == eLoad)
bart36556122008-03-13 19:24:30 +0000126 {
bart3772a982008-03-15 08:11:03 +0000127 bm0_set(bm2->bm1.bm0_r, b0);
sewardjaf44c822007-11-25 14:01:38 +0000128 }
bart3772a982008-03-15 08:11:03 +0000129 else
130 {
131 bm0_set(bm2->bm1.bm0_w, b0);
132 }
133 }
134 }
sewardjaf44c822007-11-25 14:01:38 +0000135}
136
barta79df6e2008-03-14 17:07:51 +0000137static inline
138void bm_access_aligned_load(struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000139 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000140{
bart3772a982008-03-15 08:11:03 +0000141 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000142
bart3772a982008-03-15 08:11:03 +0000143 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
144 tl_assert(bm2);
barta79df6e2008-03-14 17:07:51 +0000145
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);
156 tl_assert(bm2);
barta79df6e2008-03-14 17:07:51 +0000157
bartf8bc71d2008-03-15 11:42:34 +0000158 bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size);
barta79df6e2008-03-14 17:07:51 +0000159}
160
bart36556122008-03-13 19:24:30 +0000161void bm_access_range_load(struct bitmap* const bm,
162 const Addr a1, const Addr a2)
163{
bart3772a982008-03-15 08:11:03 +0000164 bm_access_range(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000165}
166
barta79df6e2008-03-14 17:07:51 +0000167void bm_access_load_1(struct bitmap* const bm, const Addr a1)
168{
bartf8bc71d2008-03-15 11:42:34 +0000169 bm_access_aligned_load(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000170}
171
172void bm_access_load_2(struct bitmap* const bm, const Addr a1)
173{
bart3772a982008-03-15 08:11:03 +0000174 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000175 bm_access_aligned_load(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000176 else
177 bm_access_range(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000178}
179
180void bm_access_load_4(struct bitmap* const bm, const Addr a1)
181{
bart3772a982008-03-15 08:11:03 +0000182 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000183 bm_access_aligned_load(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000184 else
185 bm_access_range(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000186}
187
188void bm_access_load_8(struct bitmap* const bm, const Addr a1)
189{
bart3772a982008-03-15 08:11:03 +0000190 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000191 bm_access_aligned_load(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000192 else if ((a1 & 3) == 0)
193 {
bartf8bc71d2008-03-15 11:42:34 +0000194 bm_access_aligned_load(bm, a1 + 0, 4);
195 bm_access_aligned_load(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000196 }
197 else
198 bm_access_range(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000199}
200
201void bm_access_store_1(struct bitmap* const bm, const Addr a1)
202{
bartf8bc71d2008-03-15 11:42:34 +0000203 bm_access_aligned_store(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000204}
205
206void bm_access_store_2(struct bitmap* const bm, const Addr a1)
207{
bart3772a982008-03-15 08:11:03 +0000208 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000209 bm_access_aligned_store(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000210 else
211 bm_access_range(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000212}
213
214void bm_access_store_4(struct bitmap* const bm, const Addr a1)
215{
bart3772a982008-03-15 08:11:03 +0000216 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000217 bm_access_aligned_store(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000218 else
219 bm_access_range(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000220}
221
222void bm_access_store_8(struct bitmap* const bm, const Addr a1)
223{
bart3772a982008-03-15 08:11:03 +0000224 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000225 bm_access_aligned_store(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000226 else if ((a1 & 3) == 0)
227 {
bartf8bc71d2008-03-15 11:42:34 +0000228 bm_access_aligned_store(bm, a1 + 0, 4);
229 bm_access_aligned_store(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000230 }
231 else
232 bm_access_range(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000233}
234
bart36556122008-03-13 19:24:30 +0000235void bm_access_range_store(struct bitmap* const bm,
236 const Addr a1, const Addr a2)
237{
bart3772a982008-03-15 08:11:03 +0000238 bm_access_range(bm, a1, a2, eStore);
bart36556122008-03-13 19:24:30 +0000239}
240
241Bool bm_has(const struct bitmap* const bm, const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000242 const BmAccessTypeT access_type)
243{
bart3772a982008-03-15 08:11:03 +0000244 Addr b;
245 for (b = a1; b < a2; b++)
246 {
247 if (! bm_has_1(bm, b, access_type))
248 {
249 return False;
250 }
251 }
252 return True;
sewardjaf44c822007-11-25 14:01:38 +0000253}
254
255Bool bm_has_any(const struct bitmap* const bm,
bart36556122008-03-13 19:24:30 +0000256 const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000257 const BmAccessTypeT access_type)
258{
bart3772a982008-03-15 08:11:03 +0000259 Addr b;
sewardjaf44c822007-11-25 14:01:38 +0000260
bart3772a982008-03-15 08:11:03 +0000261 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000262
bart3772a982008-03-15 08:11:03 +0000263 for (b = a1; b < a2; b++)
264 {
265 if (bm_has_1(bm, b, access_type))
266 {
267 return True;
268 }
269 }
270 return False;
sewardjaf44c822007-11-25 14:01:38 +0000271}
272
273/* Return a non-zero value if there is a read access, write access or both */
274/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
275UWord bm_has_any_access(const struct bitmap* const bm,
276 const Addr a1,
277 const Addr a2)
278{
bart3772a982008-03-15 08:11:03 +0000279 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000280
bart3772a982008-03-15 08:11:03 +0000281 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000282
bart3772a982008-03-15 08:11:03 +0000283 for (b = a1; b < a2; b = b_next)
284 {
285 struct bitmap2* bm2 = bm_lookup(bm, b);
sewardjaf44c822007-11-25 14:01:38 +0000286
bart3772a982008-03-15 08:11:03 +0000287 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
288 if (b_next > a2)
289 {
290 b_next = a2;
291 }
sewardjaf44c822007-11-25 14:01:38 +0000292
bart3772a982008-03-15 08:11:03 +0000293 if (bm2)
294 {
295 Addr b_start;
296 Addr b_end;
297 UWord b0;
298 const struct bitmap1* const p1 = &bm2->bm1;
sewardjaf44c822007-11-25 14:01:38 +0000299
bart3772a982008-03-15 08:11:03 +0000300 if ((bm2->addr << ADDR0_BITS) < a1)
301 b_start = a1;
302 else
303 if ((bm2->addr << ADDR0_BITS) < a2)
304 b_start = (bm2->addr << ADDR0_BITS);
305 else
306 break;
307 tl_assert(a1 <= b_start && b_start <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000308
bart3772a982008-03-15 08:11:03 +0000309 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
310 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
311 else
312 b_end = a2;
313 tl_assert(a1 <= b_end && b_end <= a2);
314 tl_assert(b_start < b_end);
315 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
sewardjaf44c822007-11-25 14:01:38 +0000316
bart3772a982008-03-15 08:11:03 +0000317 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
318 {
319 const UWord mask
320 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
321 if (mask)
322 {
323 return mask;
324 }
sewardjaf44c822007-11-25 14:01:38 +0000325 }
bart3772a982008-03-15 08:11:03 +0000326 }
327 }
328 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000329}
330
331/**
332 * Report whether an access of type access_type at address a is recorded in
333 * bitmap bm.
334 * @return != 0 means true, and == 0 means false
335 */
336UWord bm_has_1(const struct bitmap* const bm,
337 const Addr a,
338 const BmAccessTypeT access_type)
339{
bart3772a982008-03-15 08:11:03 +0000340 struct bitmap2* p2;
341 struct bitmap1* p1;
342 UWord* p0;
343 const UWord a0 = a & ADDR0_MASK;
sewardjaf44c822007-11-25 14:01:38 +0000344
bart3772a982008-03-15 08:11:03 +0000345 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000346
bart3772a982008-03-15 08:11:03 +0000347 p2 = bm_lookup(bm, a);
348 if (p2)
349 {
350 p1 = &p2->bm1;
351 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
352 return bm0_is_set(p0, a0);
353 }
354 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000355}
356
357static __inline__
358void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
359{
bart3772a982008-03-15 08:11:03 +0000360 UWord idx;
361 UWord mask;
sewardjaf44c822007-11-25 14:01:38 +0000362
363#if 0
bart3772a982008-03-15 08:11:03 +0000364 /* Commented out the statements below because of performance reasons. */
365 tl_assert(a1);
366 tl_assert(a1 <= a2);
367 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
368 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
sewardjaf44c822007-11-25 14:01:38 +0000369#endif
370
bart3772a982008-03-15 08:11:03 +0000371 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
372 /* mask: a contiguous series of one bits. The first bit set is bit */
373 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
374 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
375 bm1->bm0_r[idx] &= ~mask;
376 bm1->bm0_w[idx] &= ~mask;
sewardjaf44c822007-11-25 14:01:38 +0000377}
378
379void bm_clear_all(const struct bitmap* const bm)
380{
bart3772a982008-03-15 08:11:03 +0000381 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000382
bart3772a982008-03-15 08:11:03 +0000383 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000384
bart3772a982008-03-15 08:11:03 +0000385 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
386 {
387 struct bitmap1* const bm1 = &bm2->bm1;
388 tl_assert(bm1);
389 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
390 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
391 }
sewardjaf44c822007-11-25 14:01:38 +0000392}
393
sewardjaf44c822007-11-25 14:01:38 +0000394void bm_clear(const struct bitmap* const bm,
395 const Addr a1,
396 const Addr a2)
397{
bart3772a982008-03-15 08:11:03 +0000398 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000399
bart3772a982008-03-15 08:11:03 +0000400 tl_assert(bm);
401 tl_assert(a1);
402 tl_assert(a1 <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000403
bart3772a982008-03-15 08:11:03 +0000404 for (b = a1; b < a2; b = b_next)
405 {
406 struct bitmap2* const p2 = bm_lookup(bm, b);
sewardjaf44c822007-11-25 14:01:38 +0000407
bart3772a982008-03-15 08:11:03 +0000408 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
409 if (b_next > a2)
410 {
411 b_next = a2;
412 }
413
414 if (p2)
415 {
416 Addr c = b;
417 if (UWORD_LSB(c))
sewardjaf44c822007-11-25 14:01:38 +0000418 {
bart3772a982008-03-15 08:11:03 +0000419 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
420 if (c_next > b_next)
421 c_next = b_next;
422 bm1_clear(&p2->bm1, c, c_next);
423 c = c_next;
sewardjaf44c822007-11-25 14:01:38 +0000424 }
bart3772a982008-03-15 08:11:03 +0000425 if (UWORD_LSB(c) == 0)
sewardjaf44c822007-11-25 14:01:38 +0000426 {
bart3772a982008-03-15 08:11:03 +0000427 const Addr c_next = UWORD_MSB(b_next);
428 tl_assert(UWORD_LSB(c) == 0);
429 tl_assert(UWORD_LSB(c_next) == 0);
430 tl_assert(c_next <= b_next);
431 tl_assert(c <= c_next);
432 if (c_next > c)
433 {
434 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
435 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
436 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
437 c = c_next;
438 }
sewardjaf44c822007-11-25 14:01:38 +0000439 }
bart3772a982008-03-15 08:11:03 +0000440 if (c != b_next)
441 {
442 bm1_clear(&p2->bm1, c, b_next);
443 }
444 }
445 }
sewardjaf44c822007-11-25 14:01:38 +0000446}
sewardjaf44c822007-11-25 14:01:38 +0000447
bart36556122008-03-13 19:24:30 +0000448Bool bm_has_conflict_with(const struct bitmap* const bm,
449 const Addr a1, const Addr a2,
450 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000451{
bart3772a982008-03-15 08:11:03 +0000452 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000453
bart3772a982008-03-15 08:11:03 +0000454 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000455
bart3772a982008-03-15 08:11:03 +0000456 for (b = a1; b < a2; b = b_next)
457 {
458 struct bitmap2* bm2 = bm_lookup(bm, b);
bart36556122008-03-13 19:24:30 +0000459
bart3772a982008-03-15 08:11:03 +0000460 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
461 if (b_next > a2)
462 {
463 b_next = a2;
464 }
bart36556122008-03-13 19:24:30 +0000465
bart3772a982008-03-15 08:11:03 +0000466 if (bm2)
467 {
468 Addr b_start;
469 Addr b_end;
470 UWord b0;
471 const struct bitmap1* const p1 = &bm2->bm1;
bart36556122008-03-13 19:24:30 +0000472
bart3772a982008-03-15 08:11:03 +0000473 if ((bm2->addr << ADDR0_BITS) < a1)
474 b_start = a1;
475 else
476 if ((bm2->addr << ADDR0_BITS) < a2)
477 b_start = (bm2->addr << ADDR0_BITS);
478 else
479 break;
480 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000481
bart3772a982008-03-15 08:11:03 +0000482 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
483 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
484 else
485 b_end = a2;
486 tl_assert(a1 <= b_end && b_end <= a2);
487 tl_assert(b_start < b_end);
488 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000489
bart3772a982008-03-15 08:11:03 +0000490 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
491 {
492 if (access_type == eLoad)
493 {
494 if (bm0_is_set(p1->bm0_w, b0))
495 {
496 return True;
497 }
498 }
499 else
500 {
501 tl_assert(access_type == eStore);
502 if (bm0_is_set(p1->bm0_r, b0)
503 | bm0_is_set(p1->bm0_w, b0))
504 {
505 return True;
506 }
507 }
sewardjaf44c822007-11-25 14:01:38 +0000508 }
bart3772a982008-03-15 08:11:03 +0000509 }
510 }
511 return False;
sewardjaf44c822007-11-25 14:01:38 +0000512}
513
barta79df6e2008-03-14 17:07:51 +0000514static inline
515Bool bm_aligned_load_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000516 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000517{
bart3772a982008-03-15 08:11:03 +0000518 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000519
bart3772a982008-03-15 08:11:03 +0000520 bm2 = bm_lookup(bm, a1);
barta79df6e2008-03-14 17:07:51 +0000521
bartf8bc71d2008-03-15 11:42:34 +0000522 return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size));
barta79df6e2008-03-14 17:07:51 +0000523}
524
525static inline
526Bool bm_aligned_store_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000527 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000528{
bart3772a982008-03-15 08:11:03 +0000529 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000530
bart3772a982008-03-15 08:11:03 +0000531 bm2 = bm_lookup(bm, a1);
barta79df6e2008-03-14 17:07:51 +0000532
bart3772a982008-03-15 08:11:03 +0000533 if (bm2)
534 {
bartf8bc71d2008-03-15 11:42:34 +0000535 if (bm0_is_any_set(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size)
536 | bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size))
bart3772a982008-03-15 08:11:03 +0000537 {
538 return True;
539 }
540 }
541 return False;
barta79df6e2008-03-14 17:07:51 +0000542}
543
bart36556122008-03-13 19:24:30 +0000544Bool bm_load_has_conflict_with(const struct bitmap* const bm,
545 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000546{
bart3772a982008-03-15 08:11:03 +0000547 return bm_has_conflict_with(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000548}
549
barta79df6e2008-03-14 17:07:51 +0000550Bool bm_load_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
551{
bartf8bc71d2008-03-15 11:42:34 +0000552 return bm_aligned_load_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000553}
554
555Bool bm_load_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
556{
bart3772a982008-03-15 08:11:03 +0000557 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000558 return bm_aligned_load_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000559 else
560 return bm_has_conflict_with(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000561}
562
563Bool bm_load_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
564{
bart3772a982008-03-15 08:11:03 +0000565 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000566 return bm_aligned_load_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000567 else
568 return bm_has_conflict_with(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000569}
570
571Bool bm_load_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
572{
bart3772a982008-03-15 08:11:03 +0000573 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000574 return bm_aligned_load_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000575 else
576 return bm_has_conflict_with(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000577}
578
579Bool bm_store_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
580{
bartf8bc71d2008-03-15 11:42:34 +0000581 return bm_aligned_store_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000582}
583
584Bool bm_store_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
585{
bart3772a982008-03-15 08:11:03 +0000586 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000587 return bm_aligned_store_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000588 else
589 return bm_has_conflict_with(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000590}
591
592Bool bm_store_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
593{
bart3772a982008-03-15 08:11:03 +0000594 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000595 return bm_aligned_store_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000596 else
597 return bm_has_conflict_with(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000598}
599
600Bool bm_store_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
601{
bart3772a982008-03-15 08:11:03 +0000602 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000603 return bm_aligned_store_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000604 else
605 return bm_has_conflict_with(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000606}
607
bart36556122008-03-13 19:24:30 +0000608Bool bm_store_has_conflict_with(const struct bitmap* const bm,
609 const Addr a1, const Addr a2)
610{
bart3772a982008-03-15 08:11:03 +0000611 return bm_has_conflict_with(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000612}
613
614void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
615{
bart3772a982008-03-15 08:11:03 +0000616 OSet* const tmp = bm1->oset;
617 bm1->oset = bm2->oset;
618 bm2->oset = tmp;
sewardjaf44c822007-11-25 14:01:38 +0000619}
620
621void bm_merge2(struct bitmap* const lhs,
622 const struct bitmap* const rhs)
623{
bart3772a982008-03-15 08:11:03 +0000624 struct bitmap2* bm2l;
625 const struct bitmap2* bm2r;
sewardjaf44c822007-11-25 14:01:38 +0000626
bart3772a982008-03-15 08:11:03 +0000627 // First step: allocate any missing bitmaps in *lhs.
628 VG_(OSetGen_ResetIter)(rhs->oset);
629 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
630 {
631 bm2_lookup_or_insert(lhs, bm2r->addr);
632 }
sewardjaf44c822007-11-25 14:01:38 +0000633
bart3772a982008-03-15 08:11:03 +0000634 VG_(OSetGen_ResetIter)(lhs->oset);
635 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000636
bart3772a982008-03-15 08:11:03 +0000637 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
638 {
639 do
640 {
641 bm2l = VG_(OSetGen_Next)(lhs->oset);
642 } while (bm2l->addr < bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000643
bart3772a982008-03-15 08:11:03 +0000644 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000645
bart3772a982008-03-15 08:11:03 +0000646 bm2_merge(bm2l, bm2r);
647 }
sewardjaf44c822007-11-25 14:01:38 +0000648}
649
650/**
651 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
652 * @param lhs First bitmap.
653 * @param rhs Bitmap to be compared with lhs.
654 * @return !=0 if there are data races, == 0 if there are none.
655 */
656int bm_has_races(const struct bitmap* const lhs,
657 const struct bitmap* const rhs)
658{
bart3772a982008-03-15 08:11:03 +0000659 VG_(OSetGen_ResetIter)(lhs->oset);
660 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000661
bart3772a982008-03-15 08:11:03 +0000662 for (;;)
663 {
664 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
665 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
666 const struct bitmap1* bm1l;
667 const struct bitmap1* bm1r;
668 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000669
bart3772a982008-03-15 08:11:03 +0000670 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
671 {
672 if (bm2l->addr < bm2r->addr)
673 bm2l = VG_(OSetGen_Next)(lhs->oset);
674 else
675 bm2r = VG_(OSetGen_Next)(rhs->oset);
676 }
677 if (bm2l == 0 || bm2r == 0)
678 break;
679
680 bm1l = &bm2l->bm1;
681 bm1r = &bm2r->bm1;
682
683 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
684 {
685 unsigned b;
686 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000687 {
bart3772a982008-03-15 08:11:03 +0000688 UWord const access
689 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
690 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
691 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
692 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
693 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
694 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
695 {
696 return 1;
697 }
sewardjaf44c822007-11-25 14:01:38 +0000698 }
bart3772a982008-03-15 08:11:03 +0000699 }
700 }
701 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000702}
703
sewardjaf44c822007-11-25 14:01:38 +0000704void bm_print(const struct bitmap* const bm)
705{
bart3772a982008-03-15 08:11:03 +0000706 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000707
bart3772a982008-03-15 08:11:03 +0000708 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000709
bart3772a982008-03-15 08:11:03 +0000710 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
711 {
712 const struct bitmap1* const bm1 = &bm2->bm1;
713 unsigned k;
714 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
715 {
716 unsigned b;
717 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000718 {
bart3772a982008-03-15 08:11:03 +0000719 int const r = bm1->bm0_r[k] & bm0_mask(b);
720 int const w = bm1->bm0_w[k] & bm0_mask(b);
721 Addr const a = MAKE_ADDRESS(bm2->addr, k * BITS_PER_UWORD | b);
722 if (r || w)
723 {
724 VG_(printf)("0x%08lx %c %c\n",
725 (Addr)(a),
726 w ? 'W' : ' ', r ? 'R' : ' ');
727 }
sewardjaf44c822007-11-25 14:01:38 +0000728 }
bart3772a982008-03-15 08:11:03 +0000729 }
730 }
sewardjaf44c822007-11-25 14:01:38 +0000731}
732
733ULong bm_get_bitmap_creation_count(void)
734{
bart3772a982008-03-15 08:11:03 +0000735 return s_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000736}
737
738ULong bm_get_bitmap2_creation_count(void)
739{
bart3772a982008-03-15 08:11:03 +0000740 return s_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000741}
742
743static void bm2_merge(struct bitmap2* const bm2l,
744 const struct bitmap2* const bm2r)
745{
bart3772a982008-03-15 08:11:03 +0000746 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000747
bart3772a982008-03-15 08:11:03 +0000748 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000749
bart3772a982008-03-15 08:11:03 +0000750 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
751 {
752 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
753 }
754 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
755 {
756 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
757 }
sewardjaf44c822007-11-25 14:01:38 +0000758}
759
760#if 0
761
762/* Unit test */
763static
764struct { Addr address; SizeT size; BmAccessTypeT access_type; }
bart3772a982008-03-15 08:11:03 +0000765 s_args[] = {
766 { 0, 1, eLoad },
767 { 666, 4, eLoad },
768 { 667, 2, eStore },
769 { 1024, 1, eStore },
770 { 0x0000ffff, 1, eLoad },
771 { 0x0001ffff, 1, eLoad },
772 { 0x00ffffff, 1, eLoad },
773 { 0xffffffff, 1, eStore },
774 };
sewardjaf44c822007-11-25 14:01:38 +0000775
776void bm_test(void)
777{
bart3772a982008-03-15 08:11:03 +0000778 struct bitmap* bm;
779 struct bitmap* bm2;
780 int i, j;
sewardjaf44c822007-11-25 14:01:38 +0000781
bart3772a982008-03-15 08:11:03 +0000782 VG_(printf)("Start of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000783
bart3772a982008-03-15 08:11:03 +0000784 bm = bm_new();
sewardjaf44c822007-11-25 14:01:38 +0000785
bart3772a982008-03-15 08:11:03 +0000786 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
787 {
788 bm_access_range(bm,
789 s_args[i].address,
790 s_args[i].address + s_args[i].size,
791 s_args[i].access_type);
792 }
sewardjaf44c822007-11-25 14:01:38 +0000793
bart3772a982008-03-15 08:11:03 +0000794 VG_(printf)("Map contents -- should contain 10 addresses:\n");
795 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000796
bart3772a982008-03-15 08:11:03 +0000797 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
798 {
799 for (j = 0; j < s_args[i].size; j++)
800 {
801 tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
802 }
803 }
sewardjaf44c822007-11-25 14:01:38 +0000804
bart3772a982008-03-15 08:11:03 +0000805 VG_(printf)("Merge result:\n");
806 bm2 = bm_merge(bm, bm);
807 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000808
bart3772a982008-03-15 08:11:03 +0000809 bm_delete(bm);
810 bm_delete(bm2);
sewardjaf44c822007-11-25 14:01:38 +0000811
bart3772a982008-03-15 08:11:03 +0000812 VG_(printf)("End of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000813}
814#endif