blob: d56062ff7c93f068187548ddb5316f019c15dc3d [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,
139 const Addr a1, const Addr a2)
140{
bart3772a982008-03-15 08:11:03 +0000141 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000142
143#if 0
bart3772a982008-03-15 08:11:03 +0000144 /* Commented out the statements below because of performance reasons. */
145 tl_assert(bm);
146 tl_assert(a1 < a2);
147 tl_assert((a2 - a1) == 1 || (a2 - a1) == 2
148 || (a2 - a1) == 4 || (a2 - a1) == 8);
149 tl_assert((a1 & (a2 - a1 - 1)) == 0);
barta79df6e2008-03-14 17:07:51 +0000150#endif
151
bart3772a982008-03-15 08:11:03 +0000152 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
153 tl_assert(bm2);
barta79df6e2008-03-14 17:07:51 +0000154
bart3772a982008-03-15 08:11:03 +0000155 bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, (a2 - 1) & ADDR0_MASK);
barta79df6e2008-03-14 17:07:51 +0000156}
157
158static inline
159void bm_access_aligned_store(struct bitmap* const bm,
160 const Addr a1, const Addr a2)
161{
bart3772a982008-03-15 08:11:03 +0000162 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000163
164#if 0
bart3772a982008-03-15 08:11:03 +0000165 /* Commented out the statements below because of performance reasons. */
166 tl_assert(bm);
167 tl_assert(a1 < a2);
168 tl_assert((a2 - a1) == 1 || (a2 - a1) == 2
169 || (a2 - a1) == 4 || (a2 - a1) == 8);
170 tl_assert((a1 & (a2 - a1 - 1)) == 0);
barta79df6e2008-03-14 17:07:51 +0000171#endif
172
bart3772a982008-03-15 08:11:03 +0000173 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
174 tl_assert(bm2);
barta79df6e2008-03-14 17:07:51 +0000175
bart3772a982008-03-15 08:11:03 +0000176 bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, (a2 - 1) & ADDR0_MASK);
barta79df6e2008-03-14 17:07:51 +0000177}
178
bart36556122008-03-13 19:24:30 +0000179void bm_access_range_load(struct bitmap* const bm,
180 const Addr a1, const Addr a2)
181{
bart3772a982008-03-15 08:11:03 +0000182 bm_access_range(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000183}
184
barta79df6e2008-03-14 17:07:51 +0000185void bm_access_load_1(struct bitmap* const bm, const Addr a1)
186{
bart3772a982008-03-15 08:11:03 +0000187 bm_access_aligned_load(bm, a1, a1 + 1);
barta79df6e2008-03-14 17:07:51 +0000188}
189
190void bm_access_load_2(struct bitmap* const bm, const Addr a1)
191{
bart3772a982008-03-15 08:11:03 +0000192 if ((a1 & 1) == 0)
193 bm_access_aligned_load(bm, a1, a1 + 2);
194 else
195 bm_access_range(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000196}
197
198void bm_access_load_4(struct bitmap* const bm, const Addr a1)
199{
bart3772a982008-03-15 08:11:03 +0000200 if ((a1 & 3) == 0)
201 bm_access_aligned_load(bm, a1, a1 + 4);
202 else
203 bm_access_range(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000204}
205
206void bm_access_load_8(struct bitmap* const bm, const Addr a1)
207{
bart3772a982008-03-15 08:11:03 +0000208 if ((a1 & 7) == 0)
209 bm_access_aligned_load(bm, a1, a1 + 8);
210 else if ((a1 & 3) == 0)
211 {
212 bm_access_aligned_load(bm, a1 + 0, a1 + 4);
213 bm_access_aligned_load(bm, a1 + 4, a1 + 8);
214 }
215 else
216 bm_access_range(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000217}
218
219void bm_access_store_1(struct bitmap* const bm, const Addr a1)
220{
bart3772a982008-03-15 08:11:03 +0000221 bm_access_aligned_store(bm, a1, a1 + 1);
barta79df6e2008-03-14 17:07:51 +0000222}
223
224void bm_access_store_2(struct bitmap* const bm, const Addr a1)
225{
bart3772a982008-03-15 08:11:03 +0000226 if ((a1 & 1) == 0)
227 bm_access_aligned_store(bm, a1, a1 + 2);
228 else
229 bm_access_range(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000230}
231
232void bm_access_store_4(struct bitmap* const bm, const Addr a1)
233{
bart3772a982008-03-15 08:11:03 +0000234 if ((a1 & 3) == 0)
235 bm_access_aligned_store(bm, a1, a1 + 4);
236 else
237 bm_access_range(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000238}
239
240void bm_access_store_8(struct bitmap* const bm, const Addr a1)
241{
bart3772a982008-03-15 08:11:03 +0000242 if ((a1 & 7) == 0)
243 bm_access_aligned_store(bm, a1, a1 + 8);
244 else if ((a1 & 3) == 0)
245 {
246 bm_access_aligned_store(bm, a1 + 0, a1 + 4);
247 bm_access_aligned_store(bm, a1 + 4, a1 + 8);
248 }
249 else
250 bm_access_range(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000251}
252
bart36556122008-03-13 19:24:30 +0000253void bm_access_range_store(struct bitmap* const bm,
254 const Addr a1, const Addr a2)
255{
bart3772a982008-03-15 08:11:03 +0000256 bm_access_range(bm, a1, a2, eStore);
bart36556122008-03-13 19:24:30 +0000257}
258
259Bool bm_has(const struct bitmap* const bm, const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000260 const BmAccessTypeT access_type)
261{
bart3772a982008-03-15 08:11:03 +0000262 Addr b;
263 for (b = a1; b < a2; b++)
264 {
265 if (! bm_has_1(bm, b, access_type))
266 {
267 return False;
268 }
269 }
270 return True;
sewardjaf44c822007-11-25 14:01:38 +0000271}
272
273Bool bm_has_any(const struct bitmap* const bm,
bart36556122008-03-13 19:24:30 +0000274 const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000275 const BmAccessTypeT access_type)
276{
bart3772a982008-03-15 08:11:03 +0000277 Addr b;
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++)
282 {
283 if (bm_has_1(bm, b, access_type))
284 {
285 return True;
286 }
287 }
288 return False;
sewardjaf44c822007-11-25 14:01:38 +0000289}
290
291/* Return a non-zero value if there is a read access, write access or both */
292/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
293UWord bm_has_any_access(const struct bitmap* const bm,
294 const Addr a1,
295 const Addr a2)
296{
bart3772a982008-03-15 08:11:03 +0000297 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000298
bart3772a982008-03-15 08:11:03 +0000299 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000300
bart3772a982008-03-15 08:11:03 +0000301 for (b = a1; b < a2; b = b_next)
302 {
303 struct bitmap2* bm2 = bm_lookup(bm, b);
sewardjaf44c822007-11-25 14:01:38 +0000304
bart3772a982008-03-15 08:11:03 +0000305 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
306 if (b_next > a2)
307 {
308 b_next = a2;
309 }
sewardjaf44c822007-11-25 14:01:38 +0000310
bart3772a982008-03-15 08:11:03 +0000311 if (bm2)
312 {
313 Addr b_start;
314 Addr b_end;
315 UWord b0;
316 const struct bitmap1* const p1 = &bm2->bm1;
sewardjaf44c822007-11-25 14:01:38 +0000317
bart3772a982008-03-15 08:11:03 +0000318 if ((bm2->addr << ADDR0_BITS) < a1)
319 b_start = a1;
320 else
321 if ((bm2->addr << ADDR0_BITS) < a2)
322 b_start = (bm2->addr << ADDR0_BITS);
323 else
324 break;
325 tl_assert(a1 <= b_start && b_start <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000326
bart3772a982008-03-15 08:11:03 +0000327 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
328 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
329 else
330 b_end = a2;
331 tl_assert(a1 <= b_end && b_end <= a2);
332 tl_assert(b_start < b_end);
333 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
sewardjaf44c822007-11-25 14:01:38 +0000334
bart3772a982008-03-15 08:11:03 +0000335 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
336 {
337 const UWord mask
338 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
339 if (mask)
340 {
341 return mask;
342 }
sewardjaf44c822007-11-25 14:01:38 +0000343 }
bart3772a982008-03-15 08:11:03 +0000344 }
345 }
346 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000347}
348
349/**
350 * Report whether an access of type access_type at address a is recorded in
351 * bitmap bm.
352 * @return != 0 means true, and == 0 means false
353 */
354UWord bm_has_1(const struct bitmap* const bm,
355 const Addr a,
356 const BmAccessTypeT access_type)
357{
bart3772a982008-03-15 08:11:03 +0000358 struct bitmap2* p2;
359 struct bitmap1* p1;
360 UWord* p0;
361 const UWord a0 = a & ADDR0_MASK;
sewardjaf44c822007-11-25 14:01:38 +0000362
bart3772a982008-03-15 08:11:03 +0000363 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000364
bart3772a982008-03-15 08:11:03 +0000365 p2 = bm_lookup(bm, a);
366 if (p2)
367 {
368 p1 = &p2->bm1;
369 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
370 return bm0_is_set(p0, a0);
371 }
372 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000373}
374
375static __inline__
376void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
377{
bart3772a982008-03-15 08:11:03 +0000378 UWord idx;
379 UWord mask;
sewardjaf44c822007-11-25 14:01:38 +0000380
381#if 0
bart3772a982008-03-15 08:11:03 +0000382 /* Commented out the statements below because of performance reasons. */
383 tl_assert(a1);
384 tl_assert(a1 <= a2);
385 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
386 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
sewardjaf44c822007-11-25 14:01:38 +0000387#endif
388
bart3772a982008-03-15 08:11:03 +0000389 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
390 /* mask: a contiguous series of one bits. The first bit set is bit */
391 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
392 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
393 bm1->bm0_r[idx] &= ~mask;
394 bm1->bm0_w[idx] &= ~mask;
sewardjaf44c822007-11-25 14:01:38 +0000395}
396
397void bm_clear_all(const struct bitmap* const bm)
398{
bart3772a982008-03-15 08:11:03 +0000399 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000400
bart3772a982008-03-15 08:11:03 +0000401 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000402
bart3772a982008-03-15 08:11:03 +0000403 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
404 {
405 struct bitmap1* const bm1 = &bm2->bm1;
406 tl_assert(bm1);
407 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
408 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
409 }
sewardjaf44c822007-11-25 14:01:38 +0000410}
411
sewardjaf44c822007-11-25 14:01:38 +0000412void bm_clear(const struct bitmap* const bm,
413 const Addr a1,
414 const Addr a2)
415{
bart3772a982008-03-15 08:11:03 +0000416 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000417
bart3772a982008-03-15 08:11:03 +0000418 tl_assert(bm);
419 tl_assert(a1);
420 tl_assert(a1 <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000421
bart3772a982008-03-15 08:11:03 +0000422 for (b = a1; b < a2; b = b_next)
423 {
424 struct bitmap2* const p2 = bm_lookup(bm, b);
sewardjaf44c822007-11-25 14:01:38 +0000425
bart3772a982008-03-15 08:11:03 +0000426 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
427 if (b_next > a2)
428 {
429 b_next = a2;
430 }
431
432 if (p2)
433 {
434 Addr c = b;
435 if (UWORD_LSB(c))
sewardjaf44c822007-11-25 14:01:38 +0000436 {
bart3772a982008-03-15 08:11:03 +0000437 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
438 if (c_next > b_next)
439 c_next = b_next;
440 bm1_clear(&p2->bm1, c, c_next);
441 c = c_next;
sewardjaf44c822007-11-25 14:01:38 +0000442 }
bart3772a982008-03-15 08:11:03 +0000443 if (UWORD_LSB(c) == 0)
sewardjaf44c822007-11-25 14:01:38 +0000444 {
bart3772a982008-03-15 08:11:03 +0000445 const Addr c_next = UWORD_MSB(b_next);
446 tl_assert(UWORD_LSB(c) == 0);
447 tl_assert(UWORD_LSB(c_next) == 0);
448 tl_assert(c_next <= b_next);
449 tl_assert(c <= c_next);
450 if (c_next > c)
451 {
452 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
453 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
454 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
455 c = c_next;
456 }
sewardjaf44c822007-11-25 14:01:38 +0000457 }
bart3772a982008-03-15 08:11:03 +0000458 if (c != b_next)
459 {
460 bm1_clear(&p2->bm1, c, b_next);
461 }
462 }
463 }
sewardjaf44c822007-11-25 14:01:38 +0000464}
sewardjaf44c822007-11-25 14:01:38 +0000465
bart36556122008-03-13 19:24:30 +0000466Bool bm_has_conflict_with(const struct bitmap* const bm,
467 const Addr a1, const Addr a2,
468 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000469{
bart3772a982008-03-15 08:11:03 +0000470 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000471
bart3772a982008-03-15 08:11:03 +0000472 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000473
bart3772a982008-03-15 08:11:03 +0000474 for (b = a1; b < a2; b = b_next)
475 {
476 struct bitmap2* bm2 = bm_lookup(bm, b);
bart36556122008-03-13 19:24:30 +0000477
bart3772a982008-03-15 08:11:03 +0000478 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
479 if (b_next > a2)
480 {
481 b_next = a2;
482 }
bart36556122008-03-13 19:24:30 +0000483
bart3772a982008-03-15 08:11:03 +0000484 if (bm2)
485 {
486 Addr b_start;
487 Addr b_end;
488 UWord b0;
489 const struct bitmap1* const p1 = &bm2->bm1;
bart36556122008-03-13 19:24:30 +0000490
bart3772a982008-03-15 08:11:03 +0000491 if ((bm2->addr << ADDR0_BITS) < a1)
492 b_start = a1;
493 else
494 if ((bm2->addr << ADDR0_BITS) < a2)
495 b_start = (bm2->addr << ADDR0_BITS);
496 else
497 break;
498 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000499
bart3772a982008-03-15 08:11:03 +0000500 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
501 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
502 else
503 b_end = a2;
504 tl_assert(a1 <= b_end && b_end <= a2);
505 tl_assert(b_start < b_end);
506 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000507
bart3772a982008-03-15 08:11:03 +0000508 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
509 {
510 if (access_type == eLoad)
511 {
512 if (bm0_is_set(p1->bm0_w, b0))
513 {
514 return True;
515 }
516 }
517 else
518 {
519 tl_assert(access_type == eStore);
520 if (bm0_is_set(p1->bm0_r, b0)
521 | bm0_is_set(p1->bm0_w, b0))
522 {
523 return True;
524 }
525 }
sewardjaf44c822007-11-25 14:01:38 +0000526 }
bart3772a982008-03-15 08:11:03 +0000527 }
528 }
529 return False;
sewardjaf44c822007-11-25 14:01:38 +0000530}
531
barta79df6e2008-03-14 17:07:51 +0000532static inline
533Bool bm_aligned_load_has_conflict_with(const struct bitmap* const bm,
534 const Addr a1, const Addr a2)
535{
bart3772a982008-03-15 08:11:03 +0000536 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000537
538#if 0
bart3772a982008-03-15 08:11:03 +0000539 /* Commented out the statements below because of performance reasons. */
540 tl_assert(bm);
541 tl_assert(a1 < a2);
542 tl_assert((a2 - a1) == 1 || (a2 - a1) == 2
543 || (a2 - a1) == 4 || (a2 - a1) == 8);
544 tl_assert((a1 & (a2 - a1 - 1)) == 0);
barta79df6e2008-03-14 17:07:51 +0000545#endif
546
bart3772a982008-03-15 08:11:03 +0000547 bm2 = bm_lookup(bm, a1);
barta79df6e2008-03-14 17:07:51 +0000548
bart3772a982008-03-15 08:11:03 +0000549 if (bm2
550 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, (a2-1) & ADDR0_MASK))
551 {
552 return True;
553 }
554 return False;
barta79df6e2008-03-14 17:07:51 +0000555}
556
557static inline
558Bool bm_aligned_store_has_conflict_with(const struct bitmap* const bm,
559 const Addr a1, const Addr a2)
560{
bart3772a982008-03-15 08:11:03 +0000561 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000562
563#if 0
bart3772a982008-03-15 08:11:03 +0000564 /* Commented out the statements below because of performance reasons. */
565 tl_assert(bm);
566 tl_assert(a1 < a2);
567 tl_assert((a2 - a1) == 1 || (a2 - a1) == 2
568 || (a2 - a1) == 4 || (a2 - a1) == 8);
569 tl_assert((a1 & (a2 - a1 - 1)) == 0);
barta79df6e2008-03-14 17:07:51 +0000570#endif
571
bart3772a982008-03-15 08:11:03 +0000572 bm2 = bm_lookup(bm, a1);
barta79df6e2008-03-14 17:07:51 +0000573
bart3772a982008-03-15 08:11:03 +0000574 if (bm2)
575 {
576 const struct bitmap1* const p1 = &bm2->bm1;
barta79df6e2008-03-14 17:07:51 +0000577
bart3772a982008-03-15 08:11:03 +0000578 if (bm0_is_any_set(p1->bm0_r, a1 & ADDR0_MASK, (a2-1) & ADDR0_MASK)
579 | bm0_is_any_set(p1->bm0_w, a1 & ADDR0_MASK, (a2-1) & ADDR0_MASK))
580 {
581 return True;
582 }
583 }
584 return False;
barta79df6e2008-03-14 17:07:51 +0000585}
586
bart36556122008-03-13 19:24:30 +0000587Bool bm_load_has_conflict_with(const struct bitmap* const bm,
588 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000589{
bart3772a982008-03-15 08:11:03 +0000590 return bm_has_conflict_with(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000591}
592
barta79df6e2008-03-14 17:07:51 +0000593Bool bm_load_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
594{
bart3772a982008-03-15 08:11:03 +0000595 return bm_aligned_load_has_conflict_with(bm, a1, a1 + 1);
barta79df6e2008-03-14 17:07:51 +0000596}
597
598Bool bm_load_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
599{
bart3772a982008-03-15 08:11:03 +0000600 if ((a1 & 1) == 0)
601 return bm_aligned_load_has_conflict_with(bm, a1, a1 + 2);
602 else
603 return bm_has_conflict_with(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000604}
605
606Bool bm_load_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
607{
bart3772a982008-03-15 08:11:03 +0000608 if ((a1 & 3) == 0)
609 return bm_aligned_load_has_conflict_with(bm, a1, a1 + 4);
610 else
611 return bm_has_conflict_with(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000612}
613
614Bool bm_load_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
615{
bart3772a982008-03-15 08:11:03 +0000616 if ((a1 & 7) == 0)
617 return bm_aligned_load_has_conflict_with(bm, a1, a1 + 8);
618 else
619 return bm_has_conflict_with(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000620}
621
622Bool bm_store_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
623{
bart3772a982008-03-15 08:11:03 +0000624 return bm_aligned_store_has_conflict_with(bm, a1, a1 + 1);
barta79df6e2008-03-14 17:07:51 +0000625}
626
627Bool bm_store_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
628{
bart3772a982008-03-15 08:11:03 +0000629 if ((a1 & 1) == 0)
630 return bm_aligned_store_has_conflict_with(bm, a1, a1 + 2);
631 else
632 return bm_has_conflict_with(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000633}
634
635Bool bm_store_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
636{
bart3772a982008-03-15 08:11:03 +0000637 if ((a1 & 3) == 0)
638 return bm_aligned_store_has_conflict_with(bm, a1, a1 + 4);
639 else
640 return bm_has_conflict_with(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000641}
642
643Bool bm_store_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
644{
bart3772a982008-03-15 08:11:03 +0000645 if ((a1 & 7) == 0)
646 return bm_aligned_store_has_conflict_with(bm, a1, a1 + 8);
647 else
648 return bm_has_conflict_with(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000649}
650
bart36556122008-03-13 19:24:30 +0000651Bool bm_store_has_conflict_with(const struct bitmap* const bm,
652 const Addr a1, const Addr a2)
653{
bart3772a982008-03-15 08:11:03 +0000654 return bm_has_conflict_with(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000655}
656
657void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
658{
bart3772a982008-03-15 08:11:03 +0000659 OSet* const tmp = bm1->oset;
660 bm1->oset = bm2->oset;
661 bm2->oset = tmp;
sewardjaf44c822007-11-25 14:01:38 +0000662}
663
664void bm_merge2(struct bitmap* const lhs,
665 const struct bitmap* const rhs)
666{
bart3772a982008-03-15 08:11:03 +0000667 struct bitmap2* bm2l;
668 const struct bitmap2* bm2r;
sewardjaf44c822007-11-25 14:01:38 +0000669
bart3772a982008-03-15 08:11:03 +0000670 // First step: allocate any missing bitmaps in *lhs.
671 VG_(OSetGen_ResetIter)(rhs->oset);
672 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
673 {
674 bm2_lookup_or_insert(lhs, bm2r->addr);
675 }
sewardjaf44c822007-11-25 14:01:38 +0000676
bart3772a982008-03-15 08:11:03 +0000677 VG_(OSetGen_ResetIter)(lhs->oset);
678 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000679
bart3772a982008-03-15 08:11:03 +0000680 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
681 {
682 do
683 {
684 bm2l = VG_(OSetGen_Next)(lhs->oset);
685 } while (bm2l->addr < bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000686
bart3772a982008-03-15 08:11:03 +0000687 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000688
bart3772a982008-03-15 08:11:03 +0000689 bm2_merge(bm2l, bm2r);
690 }
sewardjaf44c822007-11-25 14:01:38 +0000691}
692
693/**
694 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
695 * @param lhs First bitmap.
696 * @param rhs Bitmap to be compared with lhs.
697 * @return !=0 if there are data races, == 0 if there are none.
698 */
699int bm_has_races(const struct bitmap* const lhs,
700 const struct bitmap* const rhs)
701{
bart3772a982008-03-15 08:11:03 +0000702 VG_(OSetGen_ResetIter)(lhs->oset);
703 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000704
bart3772a982008-03-15 08:11:03 +0000705 for (;;)
706 {
707 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
708 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
709 const struct bitmap1* bm1l;
710 const struct bitmap1* bm1r;
711 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000712
bart3772a982008-03-15 08:11:03 +0000713 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
714 {
715 if (bm2l->addr < bm2r->addr)
716 bm2l = VG_(OSetGen_Next)(lhs->oset);
717 else
718 bm2r = VG_(OSetGen_Next)(rhs->oset);
719 }
720 if (bm2l == 0 || bm2r == 0)
721 break;
722
723 bm1l = &bm2l->bm1;
724 bm1r = &bm2r->bm1;
725
726 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
727 {
728 unsigned b;
729 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000730 {
bart3772a982008-03-15 08:11:03 +0000731 UWord const access
732 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
733 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
734 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
735 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
736 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
737 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
738 {
739 return 1;
740 }
sewardjaf44c822007-11-25 14:01:38 +0000741 }
bart3772a982008-03-15 08:11:03 +0000742 }
743 }
744 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000745}
746
sewardjaf44c822007-11-25 14:01:38 +0000747void bm_print(const struct bitmap* const bm)
748{
bart3772a982008-03-15 08:11:03 +0000749 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000750
bart3772a982008-03-15 08:11:03 +0000751 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000752
bart3772a982008-03-15 08:11:03 +0000753 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
754 {
755 const struct bitmap1* const bm1 = &bm2->bm1;
756 unsigned k;
757 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
758 {
759 unsigned b;
760 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000761 {
bart3772a982008-03-15 08:11:03 +0000762 int const r = bm1->bm0_r[k] & bm0_mask(b);
763 int const w = bm1->bm0_w[k] & bm0_mask(b);
764 Addr const a = MAKE_ADDRESS(bm2->addr, k * BITS_PER_UWORD | b);
765 if (r || w)
766 {
767 VG_(printf)("0x%08lx %c %c\n",
768 (Addr)(a),
769 w ? 'W' : ' ', r ? 'R' : ' ');
770 }
sewardjaf44c822007-11-25 14:01:38 +0000771 }
bart3772a982008-03-15 08:11:03 +0000772 }
773 }
sewardjaf44c822007-11-25 14:01:38 +0000774}
775
776ULong bm_get_bitmap_creation_count(void)
777{
bart3772a982008-03-15 08:11:03 +0000778 return s_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000779}
780
781ULong bm_get_bitmap2_creation_count(void)
782{
bart3772a982008-03-15 08:11:03 +0000783 return s_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000784}
785
786static void bm2_merge(struct bitmap2* const bm2l,
787 const struct bitmap2* const bm2r)
788{
bart3772a982008-03-15 08:11:03 +0000789 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000790
bart3772a982008-03-15 08:11:03 +0000791 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000792
bart3772a982008-03-15 08:11:03 +0000793 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
794 {
795 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
796 }
797 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
798 {
799 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
800 }
sewardjaf44c822007-11-25 14:01:38 +0000801}
802
803#if 0
804
805/* Unit test */
806static
807struct { Addr address; SizeT size; BmAccessTypeT access_type; }
bart3772a982008-03-15 08:11:03 +0000808 s_args[] = {
809 { 0, 1, eLoad },
810 { 666, 4, eLoad },
811 { 667, 2, eStore },
812 { 1024, 1, eStore },
813 { 0x0000ffff, 1, eLoad },
814 { 0x0001ffff, 1, eLoad },
815 { 0x00ffffff, 1, eLoad },
816 { 0xffffffff, 1, eStore },
817 };
sewardjaf44c822007-11-25 14:01:38 +0000818
819void bm_test(void)
820{
bart3772a982008-03-15 08:11:03 +0000821 struct bitmap* bm;
822 struct bitmap* bm2;
823 int i, j;
sewardjaf44c822007-11-25 14:01:38 +0000824
bart3772a982008-03-15 08:11:03 +0000825 VG_(printf)("Start of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000826
bart3772a982008-03-15 08:11:03 +0000827 bm = bm_new();
sewardjaf44c822007-11-25 14:01:38 +0000828
bart3772a982008-03-15 08:11:03 +0000829 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
830 {
831 bm_access_range(bm,
832 s_args[i].address,
833 s_args[i].address + s_args[i].size,
834 s_args[i].access_type);
835 }
sewardjaf44c822007-11-25 14:01:38 +0000836
bart3772a982008-03-15 08:11:03 +0000837 VG_(printf)("Map contents -- should contain 10 addresses:\n");
838 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000839
bart3772a982008-03-15 08:11:03 +0000840 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
841 {
842 for (j = 0; j < s_args[i].size; j++)
843 {
844 tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
845 }
846 }
sewardjaf44c822007-11-25 14:01:38 +0000847
bart3772a982008-03-15 08:11:03 +0000848 VG_(printf)("Merge result:\n");
849 bm2 = bm_merge(bm, bm);
850 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000851
bart3772a982008-03-15 08:11:03 +0000852 bm_delete(bm);
853 bm_delete(bm2);
sewardjaf44c822007-11-25 14:01:38 +0000854
bart3772a982008-03-15 08:11:03 +0000855 VG_(printf)("End of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000856}
857#endif