blob: 992e1eae0c76c1c188fc14e1717924c9f888f6d8 [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
bart0008f5b2008-03-22 17:07:39 +0000125 if (access_type == eLoad)
bart3772a982008-03-15 08:11:03 +0000126 {
bart0008f5b2008-03-22 17:07:39 +0000127 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
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 }
bart0008f5b2008-03-22 17:07:39 +0000131 }
132 else
133 {
134 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
bart3772a982008-03-15 08:11:03 +0000135 {
136 bm0_set(bm2->bm1.bm0_w, b0);
137 }
138 }
139 }
sewardjaf44c822007-11-25 14:01:38 +0000140}
141
barta79df6e2008-03-14 17:07:51 +0000142static inline
143void bm_access_aligned_load(struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000144 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000145{
bart3772a982008-03-15 08:11:03 +0000146 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000147
bart3772a982008-03-15 08:11:03 +0000148 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
bartf8bc71d2008-03-15 11:42:34 +0000149 bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size);
barta79df6e2008-03-14 17:07:51 +0000150}
151
152static inline
153void bm_access_aligned_store(struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000154 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000155{
bart3772a982008-03-15 08:11:03 +0000156 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000157
bart3772a982008-03-15 08:11:03 +0000158 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
bartf8bc71d2008-03-15 11:42:34 +0000159 bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size);
barta79df6e2008-03-14 17:07:51 +0000160}
161
bart36556122008-03-13 19:24:30 +0000162void bm_access_range_load(struct bitmap* const bm,
163 const Addr a1, const Addr a2)
164{
bart3772a982008-03-15 08:11:03 +0000165 bm_access_range(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000166}
167
barta79df6e2008-03-14 17:07:51 +0000168void bm_access_load_1(struct bitmap* const bm, const Addr a1)
169{
bartf8bc71d2008-03-15 11:42:34 +0000170 bm_access_aligned_load(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000171}
172
173void bm_access_load_2(struct bitmap* const bm, const Addr a1)
174{
bart3772a982008-03-15 08:11:03 +0000175 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000176 bm_access_aligned_load(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000177 else
178 bm_access_range(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000179}
180
181void bm_access_load_4(struct bitmap* const bm, const Addr a1)
182{
bart3772a982008-03-15 08:11:03 +0000183 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000184 bm_access_aligned_load(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000185 else
186 bm_access_range(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000187}
188
189void bm_access_load_8(struct bitmap* const bm, const Addr a1)
190{
bart3772a982008-03-15 08:11:03 +0000191 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000192 bm_access_aligned_load(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000193 else if ((a1 & 3) == 0)
194 {
bartf8bc71d2008-03-15 11:42:34 +0000195 bm_access_aligned_load(bm, a1 + 0, 4);
196 bm_access_aligned_load(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000197 }
198 else
199 bm_access_range(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000200}
201
202void bm_access_store_1(struct bitmap* const bm, const Addr a1)
203{
bartf8bc71d2008-03-15 11:42:34 +0000204 bm_access_aligned_store(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000205}
206
207void bm_access_store_2(struct bitmap* const bm, const Addr a1)
208{
bart3772a982008-03-15 08:11:03 +0000209 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000210 bm_access_aligned_store(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000211 else
212 bm_access_range(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000213}
214
215void bm_access_store_4(struct bitmap* const bm, const Addr a1)
216{
bart3772a982008-03-15 08:11:03 +0000217 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000218 bm_access_aligned_store(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000219 else
220 bm_access_range(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000221}
222
223void bm_access_store_8(struct bitmap* const bm, const Addr a1)
224{
bart3772a982008-03-15 08:11:03 +0000225 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000226 bm_access_aligned_store(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000227 else if ((a1 & 3) == 0)
228 {
bartf8bc71d2008-03-15 11:42:34 +0000229 bm_access_aligned_store(bm, a1 + 0, 4);
230 bm_access_aligned_store(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000231 }
232 else
233 bm_access_range(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000234}
235
bart36556122008-03-13 19:24:30 +0000236void bm_access_range_store(struct bitmap* const bm,
237 const Addr a1, const Addr a2)
238{
bart3772a982008-03-15 08:11:03 +0000239 bm_access_range(bm, a1, a2, eStore);
bart36556122008-03-13 19:24:30 +0000240}
241
242Bool bm_has(const struct bitmap* const bm, const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000243 const BmAccessTypeT access_type)
244{
bart3772a982008-03-15 08:11:03 +0000245 Addr b;
246 for (b = a1; b < a2; b++)
247 {
248 if (! bm_has_1(bm, b, access_type))
249 {
250 return False;
251 }
252 }
253 return True;
sewardjaf44c822007-11-25 14:01:38 +0000254}
255
256Bool bm_has_any(const struct bitmap* const bm,
bart36556122008-03-13 19:24:30 +0000257 const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000258 const BmAccessTypeT access_type)
259{
bart3772a982008-03-15 08:11:03 +0000260 Addr b;
sewardjaf44c822007-11-25 14:01:38 +0000261
bart3772a982008-03-15 08:11:03 +0000262 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000263
bart3772a982008-03-15 08:11:03 +0000264 for (b = a1; b < a2; b++)
265 {
266 if (bm_has_1(bm, b, access_type))
267 {
268 return True;
269 }
270 }
271 return False;
sewardjaf44c822007-11-25 14:01:38 +0000272}
273
274/* Return a non-zero value if there is a read access, write access or both */
275/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
276UWord bm_has_any_access(const struct bitmap* const bm,
277 const Addr a1,
278 const Addr a2)
279{
bart3772a982008-03-15 08:11:03 +0000280 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000281
bart3772a982008-03-15 08:11:03 +0000282 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000283
bart3772a982008-03-15 08:11:03 +0000284 for (b = a1; b < a2; b = b_next)
285 {
bart11d0b502008-03-22 16:44:03 +0000286 struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000287
bart3772a982008-03-15 08:11:03 +0000288 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
289 if (b_next > a2)
290 {
291 b_next = a2;
292 }
sewardjaf44c822007-11-25 14:01:38 +0000293
bart3772a982008-03-15 08:11:03 +0000294 if (bm2)
295 {
296 Addr b_start;
297 Addr b_end;
298 UWord b0;
299 const struct bitmap1* const p1 = &bm2->bm1;
sewardjaf44c822007-11-25 14:01:38 +0000300
bart3772a982008-03-15 08:11:03 +0000301 if ((bm2->addr << ADDR0_BITS) < a1)
302 b_start = a1;
303 else
304 if ((bm2->addr << ADDR0_BITS) < a2)
305 b_start = (bm2->addr << ADDR0_BITS);
306 else
307 break;
308 tl_assert(a1 <= b_start && b_start <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000309
bart3772a982008-03-15 08:11:03 +0000310 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
311 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
312 else
313 b_end = a2;
314 tl_assert(a1 <= b_end && b_end <= a2);
315 tl_assert(b_start < b_end);
316 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
sewardjaf44c822007-11-25 14:01:38 +0000317
bart3772a982008-03-15 08:11:03 +0000318 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
319 {
320 const UWord mask
321 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
322 if (mask)
323 {
324 return mask;
325 }
sewardjaf44c822007-11-25 14:01:38 +0000326 }
bart3772a982008-03-15 08:11:03 +0000327 }
328 }
329 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000330}
331
332/**
333 * Report whether an access of type access_type at address a is recorded in
334 * bitmap bm.
335 * @return != 0 means true, and == 0 means false
336 */
337UWord bm_has_1(const struct bitmap* const bm,
338 const Addr a,
339 const BmAccessTypeT access_type)
340{
bart3772a982008-03-15 08:11:03 +0000341 struct bitmap2* p2;
342 struct bitmap1* p1;
343 UWord* p0;
344 const UWord a0 = a & ADDR0_MASK;
sewardjaf44c822007-11-25 14:01:38 +0000345
bart3772a982008-03-15 08:11:03 +0000346 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000347
bart11d0b502008-03-22 16:44:03 +0000348 p2 = bm2_lookup(bm, a >> ADDR0_BITS);
bart3772a982008-03-15 08:11:03 +0000349 if (p2)
350 {
351 p1 = &p2->bm1;
352 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
353 return bm0_is_set(p0, a0);
354 }
355 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000356}
357
358static __inline__
359void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
360{
bart3772a982008-03-15 08:11:03 +0000361 UWord idx;
362 UWord mask;
sewardjaf44c822007-11-25 14:01:38 +0000363
364#if 0
bart3772a982008-03-15 08:11:03 +0000365 /* Commented out the statements below because of performance reasons. */
366 tl_assert(a1);
367 tl_assert(a1 <= a2);
368 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
369 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
sewardjaf44c822007-11-25 14:01:38 +0000370#endif
371
bart3772a982008-03-15 08:11:03 +0000372 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
373 /* mask: a contiguous series of one bits. The first bit set is bit */
374 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
375 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
376 bm1->bm0_r[idx] &= ~mask;
377 bm1->bm0_w[idx] &= ~mask;
sewardjaf44c822007-11-25 14:01:38 +0000378}
379
380void bm_clear_all(const struct bitmap* const bm)
381{
bart3772a982008-03-15 08:11:03 +0000382 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000383
bart3772a982008-03-15 08:11:03 +0000384 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000385
bart3772a982008-03-15 08:11:03 +0000386 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
387 {
388 struct bitmap1* const bm1 = &bm2->bm1;
389 tl_assert(bm1);
390 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
391 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
392 }
sewardjaf44c822007-11-25 14:01:38 +0000393}
394
sewardjaf44c822007-11-25 14:01:38 +0000395void bm_clear(const struct bitmap* const bm,
396 const Addr a1,
397 const Addr a2)
398{
bart3772a982008-03-15 08:11:03 +0000399 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000400
bart3772a982008-03-15 08:11:03 +0000401 tl_assert(bm);
402 tl_assert(a1);
403 tl_assert(a1 <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000404
bart3772a982008-03-15 08:11:03 +0000405 for (b = a1; b < a2; b = b_next)
406 {
bart11d0b502008-03-22 16:44:03 +0000407 struct bitmap2* const p2 = bm2_lookup(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000408
bart3772a982008-03-15 08:11:03 +0000409 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
410 if (b_next > a2)
411 {
412 b_next = a2;
413 }
414
415 if (p2)
416 {
417 Addr c = b;
418 if (UWORD_LSB(c))
sewardjaf44c822007-11-25 14:01:38 +0000419 {
bart3772a982008-03-15 08:11:03 +0000420 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
421 if (c_next > b_next)
422 c_next = b_next;
423 bm1_clear(&p2->bm1, c, c_next);
424 c = c_next;
sewardjaf44c822007-11-25 14:01:38 +0000425 }
bart3772a982008-03-15 08:11:03 +0000426 if (UWORD_LSB(c) == 0)
sewardjaf44c822007-11-25 14:01:38 +0000427 {
bart3772a982008-03-15 08:11:03 +0000428 const Addr c_next = UWORD_MSB(b_next);
429 tl_assert(UWORD_LSB(c) == 0);
430 tl_assert(UWORD_LSB(c_next) == 0);
431 tl_assert(c_next <= b_next);
432 tl_assert(c <= c_next);
433 if (c_next > c)
434 {
435 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
436 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
437 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
438 c = c_next;
439 }
sewardjaf44c822007-11-25 14:01:38 +0000440 }
bart3772a982008-03-15 08:11:03 +0000441 if (c != b_next)
442 {
443 bm1_clear(&p2->bm1, c, b_next);
444 }
445 }
446 }
sewardjaf44c822007-11-25 14:01:38 +0000447}
sewardjaf44c822007-11-25 14:01:38 +0000448
bart36556122008-03-13 19:24:30 +0000449Bool bm_has_conflict_with(const struct bitmap* const bm,
450 const Addr a1, const Addr a2,
451 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000452{
bart3772a982008-03-15 08:11:03 +0000453 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000454
bart3772a982008-03-15 08:11:03 +0000455 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000456
bart3772a982008-03-15 08:11:03 +0000457 for (b = a1; b < a2; b = b_next)
458 {
bart11d0b502008-03-22 16:44:03 +0000459 struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
bart36556122008-03-13 19:24:30 +0000460
bart3772a982008-03-15 08:11:03 +0000461 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
462 if (b_next > a2)
463 {
464 b_next = a2;
465 }
bart36556122008-03-13 19:24:30 +0000466
bart3772a982008-03-15 08:11:03 +0000467 if (bm2)
468 {
469 Addr b_start;
470 Addr b_end;
471 UWord b0;
472 const struct bitmap1* const p1 = &bm2->bm1;
bart36556122008-03-13 19:24:30 +0000473
bart3772a982008-03-15 08:11:03 +0000474 if ((bm2->addr << ADDR0_BITS) < a1)
475 b_start = a1;
476 else
477 if ((bm2->addr << ADDR0_BITS) < a2)
478 b_start = (bm2->addr << ADDR0_BITS);
479 else
480 break;
481 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000482
bart3772a982008-03-15 08:11:03 +0000483 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
484 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
485 else
486 b_end = a2;
487 tl_assert(a1 <= b_end && b_end <= a2);
488 tl_assert(b_start < b_end);
489 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000490
bart3772a982008-03-15 08:11:03 +0000491 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
492 {
493 if (access_type == eLoad)
494 {
495 if (bm0_is_set(p1->bm0_w, b0))
496 {
497 return True;
498 }
499 }
500 else
501 {
502 tl_assert(access_type == eStore);
503 if (bm0_is_set(p1->bm0_r, b0)
504 | bm0_is_set(p1->bm0_w, b0))
505 {
506 return True;
507 }
508 }
sewardjaf44c822007-11-25 14:01:38 +0000509 }
bart3772a982008-03-15 08:11:03 +0000510 }
511 }
512 return False;
sewardjaf44c822007-11-25 14:01:38 +0000513}
514
barta79df6e2008-03-14 17:07:51 +0000515static inline
516Bool bm_aligned_load_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000517 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000518{
bart3772a982008-03-15 08:11:03 +0000519 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000520
bart11d0b502008-03-22 16:44:03 +0000521 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
barta79df6e2008-03-14 17:07:51 +0000522
bartf8bc71d2008-03-15 11:42:34 +0000523 return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size));
barta79df6e2008-03-14 17:07:51 +0000524}
525
526static inline
527Bool bm_aligned_store_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000528 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000529{
bart3772a982008-03-15 08:11:03 +0000530 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000531
bart11d0b502008-03-22 16:44:03 +0000532 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
barta79df6e2008-03-14 17:07:51 +0000533
bart3772a982008-03-15 08:11:03 +0000534 if (bm2)
535 {
bartf8bc71d2008-03-15 11:42:34 +0000536 if (bm0_is_any_set(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size)
537 | bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size))
bart3772a982008-03-15 08:11:03 +0000538 {
539 return True;
540 }
541 }
542 return False;
barta79df6e2008-03-14 17:07:51 +0000543}
544
bart36556122008-03-13 19:24:30 +0000545Bool bm_load_has_conflict_with(const struct bitmap* const bm,
546 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000547{
bart3772a982008-03-15 08:11:03 +0000548 return bm_has_conflict_with(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000549}
550
barta79df6e2008-03-14 17:07:51 +0000551Bool bm_load_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
552{
bartf8bc71d2008-03-15 11:42:34 +0000553 return bm_aligned_load_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000554}
555
556Bool bm_load_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
557{
bart3772a982008-03-15 08:11:03 +0000558 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000559 return bm_aligned_load_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000560 else
561 return bm_has_conflict_with(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000562}
563
564Bool bm_load_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
565{
bart3772a982008-03-15 08:11:03 +0000566 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000567 return bm_aligned_load_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000568 else
569 return bm_has_conflict_with(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000570}
571
572Bool bm_load_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
573{
bart3772a982008-03-15 08:11:03 +0000574 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000575 return bm_aligned_load_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000576 else
577 return bm_has_conflict_with(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000578}
579
580Bool bm_store_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
581{
bartf8bc71d2008-03-15 11:42:34 +0000582 return bm_aligned_store_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000583}
584
585Bool bm_store_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
586{
bart3772a982008-03-15 08:11:03 +0000587 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000588 return bm_aligned_store_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000589 else
590 return bm_has_conflict_with(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000591}
592
593Bool bm_store_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
594{
bart3772a982008-03-15 08:11:03 +0000595 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000596 return bm_aligned_store_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000597 else
598 return bm_has_conflict_with(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000599}
600
601Bool bm_store_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
602{
bart3772a982008-03-15 08:11:03 +0000603 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000604 return bm_aligned_store_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000605 else
606 return bm_has_conflict_with(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000607}
608
bart36556122008-03-13 19:24:30 +0000609Bool bm_store_has_conflict_with(const struct bitmap* const bm,
610 const Addr a1, const Addr a2)
611{
bart3772a982008-03-15 08:11:03 +0000612 return bm_has_conflict_with(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000613}
614
615void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
616{
bart3772a982008-03-15 08:11:03 +0000617 OSet* const tmp = bm1->oset;
618 bm1->oset = bm2->oset;
619 bm2->oset = tmp;
sewardjaf44c822007-11-25 14:01:38 +0000620}
621
622void bm_merge2(struct bitmap* const lhs,
623 const struct bitmap* const rhs)
624{
bart3772a982008-03-15 08:11:03 +0000625 struct bitmap2* bm2l;
626 const struct bitmap2* bm2r;
sewardjaf44c822007-11-25 14:01:38 +0000627
bart3772a982008-03-15 08:11:03 +0000628 // First step: allocate any missing bitmaps in *lhs.
629 VG_(OSetGen_ResetIter)(rhs->oset);
630 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
631 {
632 bm2_lookup_or_insert(lhs, bm2r->addr);
633 }
sewardjaf44c822007-11-25 14:01:38 +0000634
bart3772a982008-03-15 08:11:03 +0000635 VG_(OSetGen_ResetIter)(lhs->oset);
636 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000637
bart3772a982008-03-15 08:11:03 +0000638 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
639 {
640 do
641 {
642 bm2l = VG_(OSetGen_Next)(lhs->oset);
643 } while (bm2l->addr < bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000644
bart3772a982008-03-15 08:11:03 +0000645 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000646
bart3772a982008-03-15 08:11:03 +0000647 bm2_merge(bm2l, bm2r);
648 }
sewardjaf44c822007-11-25 14:01:38 +0000649}
650
651/**
652 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
653 * @param lhs First bitmap.
654 * @param rhs Bitmap to be compared with lhs.
655 * @return !=0 if there are data races, == 0 if there are none.
656 */
657int bm_has_races(const struct bitmap* const lhs,
658 const struct bitmap* const rhs)
659{
bart3772a982008-03-15 08:11:03 +0000660 VG_(OSetGen_ResetIter)(lhs->oset);
661 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000662
bart3772a982008-03-15 08:11:03 +0000663 for (;;)
664 {
665 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
666 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
667 const struct bitmap1* bm1l;
668 const struct bitmap1* bm1r;
669 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000670
bart3772a982008-03-15 08:11:03 +0000671 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
672 {
673 if (bm2l->addr < bm2r->addr)
674 bm2l = VG_(OSetGen_Next)(lhs->oset);
675 else
676 bm2r = VG_(OSetGen_Next)(rhs->oset);
677 }
678 if (bm2l == 0 || bm2r == 0)
679 break;
680
681 bm1l = &bm2l->bm1;
682 bm1r = &bm2r->bm1;
683
684 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
685 {
686 unsigned b;
687 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000688 {
bart3772a982008-03-15 08:11:03 +0000689 UWord const access
690 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
691 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
692 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
693 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
694 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
695 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
696 {
697 return 1;
698 }
sewardjaf44c822007-11-25 14:01:38 +0000699 }
bart3772a982008-03-15 08:11:03 +0000700 }
701 }
702 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000703}
704
sewardjaf44c822007-11-25 14:01:38 +0000705void bm_print(const struct bitmap* const bm)
706{
bart3772a982008-03-15 08:11:03 +0000707 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000708
bart3772a982008-03-15 08:11:03 +0000709 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000710
bart3772a982008-03-15 08:11:03 +0000711 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
712 {
713 const struct bitmap1* const bm1 = &bm2->bm1;
bart0008f5b2008-03-22 17:07:39 +0000714 unsigned b;
715 for (b = 0; b < ADDR0_COUNT; b++)
bart3772a982008-03-15 08:11:03 +0000716 {
bart0008f5b2008-03-22 17:07:39 +0000717 const Addr a = (bm2->addr << ADDR0_BITS) | b;
718 const Bool r = bm0_is_set(bm1->bm0_r, b) != 0;
719 const Bool w = bm0_is_set(bm1->bm0_w, b) != 0;
720 if (r || w)
sewardjaf44c822007-11-25 14:01:38 +0000721 {
bart0008f5b2008-03-22 17:07:39 +0000722 VG_(printf)("0x%08lx %c %c\n",
723 a,
724 w ? 'W' : ' ',
725 r ? 'R' : ' ');
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[] = {
bart0008f5b2008-03-22 17:07:39 +0000764 { 0 + ADDR0_COUNT, 1, eLoad },
765 { 666 + ADDR0_COUNT, 4, eLoad },
766 { 667 + ADDR0_COUNT, 2, eStore },
767 { -1 + 2*ADDR0_COUNT, 1, eStore },
768 { 0x0001ffffUL, 1, eLoad },
769 { 0x0002ffffUL, 1, eLoad },
770 { 0x00ffffffUL, 1, eLoad },
771 { 0xffffffffUL, 1, eStore },
bart3772a982008-03-15 08:11:03 +0000772 };
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;
bart0008f5b2008-03-22 17:07:39 +0000778 unsigned 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");
bart0008f5b2008-03-22 17:07:39 +0000804 bm2 = bm_new();
805 bm_merge2(bm2, bm);
806 bm_merge2(bm2, bm);
bart3772a982008-03-15 08:11:03 +0000807 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000808
bart0008f5b2008-03-22 17:07:39 +0000809 VG_(printf)("Deleting bitmap bm\n");
bart3772a982008-03-15 08:11:03 +0000810 bm_delete(bm);
bart0008f5b2008-03-22 17:07:39 +0000811 VG_(printf)("Deleting bitmap bm2\n");
bart3772a982008-03-15 08:11:03 +0000812 bm_delete(bm2);
sewardjaf44c822007-11-25 14:01:38 +0000813
bart3772a982008-03-15 08:11:03 +0000814 VG_(printf)("End of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000815}
816#endif