blob: 542c493059bd4fb9c014df1c9fa4b533f897c658 [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{
bart33e56c92008-03-24 06:41:30 +000054 unsigned i;
bart3772a982008-03-15 08:11:03 +000055 struct bitmap* bm;
sewardjaf44c822007-11-25 14:01:38 +000056
bart3772a982008-03-15 08:11:03 +000057 // If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD
58 // in drd_bitmap.h.
59 tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD);
sewardjaf44c822007-11-25 14:01:38 +000060
bart3772a982008-03-15 08:11:03 +000061 bm = VG_(malloc)(sizeof(*bm));
62 tl_assert(bm);
bart33e56c92008-03-24 06:41:30 +000063 for (i = 0; i < N_CACHE_ELEM; i++)
64 {
65 bm->cache[i].a1 = 0;
66 bm->cache[i].bm2 = 0;
67 }
barte1d4aa62008-03-16 08:39:19 +000068 bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
sewardjaf44c822007-11-25 14:01:38 +000069
bart3772a982008-03-15 08:11:03 +000070 s_bitmap_creation_count++;
sewardjaf44c822007-11-25 14:01:38 +000071
bart3772a982008-03-15 08:11:03 +000072 return bm;
sewardjaf44c822007-11-25 14:01:38 +000073}
74
75void bm_delete(struct bitmap* const bm)
76{
bart3772a982008-03-15 08:11:03 +000077 tl_assert(bm);
78 VG_(OSetGen_Destroy)(bm->oset);
79 VG_(free)(bm);
sewardjaf44c822007-11-25 14:01:38 +000080}
81
82/**
bart36556122008-03-13 19:24:30 +000083 * Record an access of type access_type at addresses a .. a + size - 1 in
sewardjaf44c822007-11-25 14:01:38 +000084 * bitmap bm.
85 */
barta79df6e2008-03-14 17:07:51 +000086static
sewardjaf44c822007-11-25 14:01:38 +000087void bm_access_range(struct bitmap* const bm,
bart9036dea2008-03-13 19:10:06 +000088 const Addr a1, const Addr a2,
bart0268dfa2008-03-11 20:10:21 +000089 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +000090{
bart3772a982008-03-15 08:11:03 +000091 Addr b, b_next;
bart36556122008-03-13 19:24:30 +000092
bart3772a982008-03-15 08:11:03 +000093 tl_assert(bm);
94 tl_assert(a1 < a2);
sewardjaf44c822007-11-25 14:01:38 +000095
bart3772a982008-03-15 08:11:03 +000096 for (b = a1; b < a2; b = b_next)
97 {
98 Addr b_start;
99 Addr b_end;
100 struct bitmap2* bm2;
101 SPLIT_ADDRESS(b);
bart36556122008-03-13 19:24:30 +0000102
bart3772a982008-03-15 08:11:03 +0000103 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
104 if (b_next > a2)
105 {
106 b_next = a2;
107 }
bart36556122008-03-13 19:24:30 +0000108
bart3772a982008-03-15 08:11:03 +0000109 bm2 = bm2_lookup_or_insert(bm, b1);
110 tl_assert(bm2);
bart36556122008-03-13 19:24:30 +0000111
bart3772a982008-03-15 08:11:03 +0000112 if ((bm2->addr << ADDR0_BITS) < a1)
113 b_start = a1;
114 else
115 if ((bm2->addr << ADDR0_BITS) < a2)
116 b_start = (bm2->addr << ADDR0_BITS);
bart36556122008-03-13 19:24:30 +0000117 else
bart3772a982008-03-15 08:11:03 +0000118 break;
119 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000120
bart3772a982008-03-15 08:11:03 +0000121 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
122 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
123 else
124 b_end = a2;
125 tl_assert(a1 <= b_end && b_end <= a2);
126 tl_assert(b_start < b_end);
127 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000128
bart0008f5b2008-03-22 17:07:39 +0000129 if (access_type == eLoad)
bart3772a982008-03-15 08:11:03 +0000130 {
bart0008f5b2008-03-22 17:07:39 +0000131 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
bart36556122008-03-13 19:24:30 +0000132 {
bart3772a982008-03-15 08:11:03 +0000133 bm0_set(bm2->bm1.bm0_r, b0);
sewardjaf44c822007-11-25 14:01:38 +0000134 }
bart0008f5b2008-03-22 17:07:39 +0000135 }
136 else
137 {
138 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
bart3772a982008-03-15 08:11:03 +0000139 {
140 bm0_set(bm2->bm1.bm0_w, b0);
141 }
142 }
143 }
sewardjaf44c822007-11-25 14:01:38 +0000144}
145
barta79df6e2008-03-14 17:07:51 +0000146static inline
147void bm_access_aligned_load(struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000148 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000149{
bart3772a982008-03-15 08:11:03 +0000150 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000151
bart3772a982008-03-15 08:11:03 +0000152 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
bartf8bc71d2008-03-15 11:42:34 +0000153 bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size);
barta79df6e2008-03-14 17:07:51 +0000154}
155
156static inline
157void bm_access_aligned_store(struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000158 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000159{
bart3772a982008-03-15 08:11:03 +0000160 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000161
bart3772a982008-03-15 08:11:03 +0000162 bm2 = bm2_lookup_or_insert(bm, a1 >> ADDR0_BITS);
bartf8bc71d2008-03-15 11:42:34 +0000163 bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size);
barta79df6e2008-03-14 17:07:51 +0000164}
165
bart36556122008-03-13 19:24:30 +0000166void bm_access_range_load(struct bitmap* const bm,
167 const Addr a1, const Addr a2)
168{
bart3772a982008-03-15 08:11:03 +0000169 bm_access_range(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000170}
171
barta79df6e2008-03-14 17:07:51 +0000172void bm_access_load_1(struct bitmap* const bm, const Addr a1)
173{
bartf8bc71d2008-03-15 11:42:34 +0000174 bm_access_aligned_load(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000175}
176
177void bm_access_load_2(struct bitmap* const bm, const Addr a1)
178{
bart3772a982008-03-15 08:11:03 +0000179 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000180 bm_access_aligned_load(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000181 else
182 bm_access_range(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000183}
184
185void bm_access_load_4(struct bitmap* const bm, const Addr a1)
186{
bart3772a982008-03-15 08:11:03 +0000187 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000188 bm_access_aligned_load(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000189 else
190 bm_access_range(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000191}
192
193void bm_access_load_8(struct bitmap* const bm, const Addr a1)
194{
bart3772a982008-03-15 08:11:03 +0000195 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000196 bm_access_aligned_load(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000197 else if ((a1 & 3) == 0)
198 {
bartf8bc71d2008-03-15 11:42:34 +0000199 bm_access_aligned_load(bm, a1 + 0, 4);
200 bm_access_aligned_load(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000201 }
202 else
203 bm_access_range(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000204}
205
206void bm_access_store_1(struct bitmap* const bm, const Addr a1)
207{
bartf8bc71d2008-03-15 11:42:34 +0000208 bm_access_aligned_store(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000209}
210
211void bm_access_store_2(struct bitmap* const bm, const Addr a1)
212{
bart3772a982008-03-15 08:11:03 +0000213 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000214 bm_access_aligned_store(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000215 else
216 bm_access_range(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000217}
218
219void bm_access_store_4(struct bitmap* const bm, const Addr a1)
220{
bart3772a982008-03-15 08:11:03 +0000221 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000222 bm_access_aligned_store(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000223 else
224 bm_access_range(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000225}
226
227void bm_access_store_8(struct bitmap* const bm, const Addr a1)
228{
bart3772a982008-03-15 08:11:03 +0000229 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000230 bm_access_aligned_store(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000231 else if ((a1 & 3) == 0)
232 {
bartf8bc71d2008-03-15 11:42:34 +0000233 bm_access_aligned_store(bm, a1 + 0, 4);
234 bm_access_aligned_store(bm, a1 + 4, 4);
bart3772a982008-03-15 08:11:03 +0000235 }
236 else
237 bm_access_range(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000238}
239
bart36556122008-03-13 19:24:30 +0000240void bm_access_range_store(struct bitmap* const bm,
241 const Addr a1, const Addr a2)
242{
bart3772a982008-03-15 08:11:03 +0000243 bm_access_range(bm, a1, a2, eStore);
bart36556122008-03-13 19:24:30 +0000244}
245
246Bool bm_has(const struct bitmap* const bm, const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000247 const BmAccessTypeT access_type)
248{
bart3772a982008-03-15 08:11:03 +0000249 Addr b;
250 for (b = a1; b < a2; b++)
251 {
252 if (! bm_has_1(bm, b, access_type))
253 {
254 return False;
255 }
256 }
257 return True;
sewardjaf44c822007-11-25 14:01:38 +0000258}
259
260Bool bm_has_any(const struct bitmap* const bm,
bart36556122008-03-13 19:24:30 +0000261 const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000262 const BmAccessTypeT access_type)
263{
bart3772a982008-03-15 08:11:03 +0000264 Addr b;
sewardjaf44c822007-11-25 14:01:38 +0000265
bart3772a982008-03-15 08:11:03 +0000266 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000267
bart3772a982008-03-15 08:11:03 +0000268 for (b = a1; b < a2; b++)
269 {
270 if (bm_has_1(bm, b, access_type))
271 {
272 return True;
273 }
274 }
275 return False;
sewardjaf44c822007-11-25 14:01:38 +0000276}
277
278/* Return a non-zero value if there is a read access, write access or both */
279/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
280UWord bm_has_any_access(const struct bitmap* const bm,
281 const Addr a1,
282 const Addr a2)
283{
bart3772a982008-03-15 08:11:03 +0000284 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000285
bart3772a982008-03-15 08:11:03 +0000286 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000287
bart3772a982008-03-15 08:11:03 +0000288 for (b = a1; b < a2; b = b_next)
289 {
bart11d0b502008-03-22 16:44:03 +0000290 struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000291
bart3772a982008-03-15 08:11:03 +0000292 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
293 if (b_next > a2)
294 {
295 b_next = a2;
296 }
sewardjaf44c822007-11-25 14:01:38 +0000297
bart3772a982008-03-15 08:11:03 +0000298 if (bm2)
299 {
300 Addr b_start;
301 Addr b_end;
302 UWord b0;
303 const struct bitmap1* const p1 = &bm2->bm1;
sewardjaf44c822007-11-25 14:01:38 +0000304
bart3772a982008-03-15 08:11:03 +0000305 if ((bm2->addr << ADDR0_BITS) < a1)
306 b_start = a1;
307 else
308 if ((bm2->addr << ADDR0_BITS) < a2)
309 b_start = (bm2->addr << ADDR0_BITS);
310 else
311 break;
312 tl_assert(a1 <= b_start && b_start <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000313
bart3772a982008-03-15 08:11:03 +0000314 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
315 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
316 else
317 b_end = a2;
318 tl_assert(a1 <= b_end && b_end <= a2);
319 tl_assert(b_start < b_end);
320 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
sewardjaf44c822007-11-25 14:01:38 +0000321
bart3772a982008-03-15 08:11:03 +0000322 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
323 {
324 const UWord mask
325 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
326 if (mask)
327 {
328 return mask;
329 }
sewardjaf44c822007-11-25 14:01:38 +0000330 }
bart3772a982008-03-15 08:11:03 +0000331 }
332 }
333 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000334}
335
336/**
337 * Report whether an access of type access_type at address a is recorded in
338 * bitmap bm.
339 * @return != 0 means true, and == 0 means false
340 */
341UWord bm_has_1(const struct bitmap* const bm,
342 const Addr a,
343 const BmAccessTypeT access_type)
344{
bart3772a982008-03-15 08:11:03 +0000345 struct bitmap2* p2;
346 struct bitmap1* p1;
347 UWord* p0;
348 const UWord a0 = a & ADDR0_MASK;
sewardjaf44c822007-11-25 14:01:38 +0000349
bart3772a982008-03-15 08:11:03 +0000350 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000351
bart11d0b502008-03-22 16:44:03 +0000352 p2 = bm2_lookup(bm, a >> ADDR0_BITS);
bart3772a982008-03-15 08:11:03 +0000353 if (p2)
354 {
355 p1 = &p2->bm1;
356 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
357 return bm0_is_set(p0, a0);
358 }
359 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000360}
361
362static __inline__
363void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
364{
bart3772a982008-03-15 08:11:03 +0000365 UWord idx;
366 UWord mask;
sewardjaf44c822007-11-25 14:01:38 +0000367
368#if 0
bart3772a982008-03-15 08:11:03 +0000369 /* Commented out the statements below because of performance reasons. */
370 tl_assert(a1);
371 tl_assert(a1 <= a2);
372 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
373 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
sewardjaf44c822007-11-25 14:01:38 +0000374#endif
375
bart3772a982008-03-15 08:11:03 +0000376 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
377 /* mask: a contiguous series of one bits. The first bit set is bit */
378 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
379 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
380 bm1->bm0_r[idx] &= ~mask;
381 bm1->bm0_w[idx] &= ~mask;
sewardjaf44c822007-11-25 14:01:38 +0000382}
383
384void bm_clear_all(const struct bitmap* const bm)
385{
bart3772a982008-03-15 08:11:03 +0000386 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000387
bart3772a982008-03-15 08:11:03 +0000388 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000389
bart3772a982008-03-15 08:11:03 +0000390 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
391 {
392 struct bitmap1* const bm1 = &bm2->bm1;
393 tl_assert(bm1);
394 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
395 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
396 }
sewardjaf44c822007-11-25 14:01:38 +0000397}
398
sewardjaf44c822007-11-25 14:01:38 +0000399void bm_clear(const struct bitmap* const bm,
400 const Addr a1,
401 const Addr a2)
402{
bart3772a982008-03-15 08:11:03 +0000403 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000404
bart3772a982008-03-15 08:11:03 +0000405 tl_assert(bm);
406 tl_assert(a1);
407 tl_assert(a1 <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000408
bart3772a982008-03-15 08:11:03 +0000409 for (b = a1; b < a2; b = b_next)
410 {
bart11d0b502008-03-22 16:44:03 +0000411 struct bitmap2* const p2 = bm2_lookup(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000412
bart3772a982008-03-15 08:11:03 +0000413 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
414 if (b_next > a2)
415 {
416 b_next = a2;
417 }
418
419 if (p2)
420 {
421 Addr c = b;
422 if (UWORD_LSB(c))
sewardjaf44c822007-11-25 14:01:38 +0000423 {
bart3772a982008-03-15 08:11:03 +0000424 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
425 if (c_next > b_next)
426 c_next = b_next;
427 bm1_clear(&p2->bm1, c, c_next);
428 c = c_next;
sewardjaf44c822007-11-25 14:01:38 +0000429 }
bart3772a982008-03-15 08:11:03 +0000430 if (UWORD_LSB(c) == 0)
sewardjaf44c822007-11-25 14:01:38 +0000431 {
bart3772a982008-03-15 08:11:03 +0000432 const Addr c_next = UWORD_MSB(b_next);
433 tl_assert(UWORD_LSB(c) == 0);
434 tl_assert(UWORD_LSB(c_next) == 0);
435 tl_assert(c_next <= b_next);
436 tl_assert(c <= c_next);
437 if (c_next > c)
438 {
439 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
440 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
441 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
442 c = c_next;
443 }
sewardjaf44c822007-11-25 14:01:38 +0000444 }
bart3772a982008-03-15 08:11:03 +0000445 if (c != b_next)
446 {
447 bm1_clear(&p2->bm1, c, b_next);
448 }
449 }
450 }
sewardjaf44c822007-11-25 14:01:38 +0000451}
sewardjaf44c822007-11-25 14:01:38 +0000452
bart36556122008-03-13 19:24:30 +0000453Bool bm_has_conflict_with(const struct bitmap* const bm,
454 const Addr a1, const Addr a2,
455 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000456{
bart3772a982008-03-15 08:11:03 +0000457 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000458
bart3772a982008-03-15 08:11:03 +0000459 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000460
bart3772a982008-03-15 08:11:03 +0000461 for (b = a1; b < a2; b = b_next)
462 {
bart11d0b502008-03-22 16:44:03 +0000463 struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
bart36556122008-03-13 19:24:30 +0000464
bart3772a982008-03-15 08:11:03 +0000465 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
466 if (b_next > a2)
467 {
468 b_next = a2;
469 }
bart36556122008-03-13 19:24:30 +0000470
bart3772a982008-03-15 08:11:03 +0000471 if (bm2)
472 {
473 Addr b_start;
474 Addr b_end;
475 UWord b0;
476 const struct bitmap1* const p1 = &bm2->bm1;
bart36556122008-03-13 19:24:30 +0000477
bart3772a982008-03-15 08:11:03 +0000478 if ((bm2->addr << ADDR0_BITS) < a1)
479 b_start = a1;
480 else
481 if ((bm2->addr << ADDR0_BITS) < a2)
482 b_start = (bm2->addr << ADDR0_BITS);
483 else
484 break;
485 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000486
bart3772a982008-03-15 08:11:03 +0000487 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
488 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
489 else
490 b_end = a2;
491 tl_assert(a1 <= b_end && b_end <= a2);
492 tl_assert(b_start < b_end);
493 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000494
bart3772a982008-03-15 08:11:03 +0000495 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
496 {
497 if (access_type == eLoad)
498 {
499 if (bm0_is_set(p1->bm0_w, b0))
500 {
501 return True;
502 }
503 }
504 else
505 {
506 tl_assert(access_type == eStore);
507 if (bm0_is_set(p1->bm0_r, b0)
508 | bm0_is_set(p1->bm0_w, b0))
509 {
510 return True;
511 }
512 }
sewardjaf44c822007-11-25 14:01:38 +0000513 }
bart3772a982008-03-15 08:11:03 +0000514 }
515 }
516 return False;
sewardjaf44c822007-11-25 14:01:38 +0000517}
518
barta79df6e2008-03-14 17:07:51 +0000519static inline
520Bool bm_aligned_load_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000521 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000522{
bart3772a982008-03-15 08:11:03 +0000523 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000524
bart11d0b502008-03-22 16:44:03 +0000525 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
barta79df6e2008-03-14 17:07:51 +0000526
bartf8bc71d2008-03-15 11:42:34 +0000527 return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size));
barta79df6e2008-03-14 17:07:51 +0000528}
529
530static inline
531Bool bm_aligned_store_has_conflict_with(const struct bitmap* const bm,
bartf8bc71d2008-03-15 11:42:34 +0000532 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000533{
bart3772a982008-03-15 08:11:03 +0000534 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000535
bart11d0b502008-03-22 16:44:03 +0000536 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
barta79df6e2008-03-14 17:07:51 +0000537
bart3772a982008-03-15 08:11:03 +0000538 if (bm2)
539 {
bartf8bc71d2008-03-15 11:42:34 +0000540 if (bm0_is_any_set(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size)
541 | bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size))
bart3772a982008-03-15 08:11:03 +0000542 {
543 return True;
544 }
545 }
546 return False;
barta79df6e2008-03-14 17:07:51 +0000547}
548
bart36556122008-03-13 19:24:30 +0000549Bool bm_load_has_conflict_with(const struct bitmap* const bm,
550 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000551{
bart3772a982008-03-15 08:11:03 +0000552 return bm_has_conflict_with(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000553}
554
barta79df6e2008-03-14 17:07:51 +0000555Bool bm_load_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
556{
bartf8bc71d2008-03-15 11:42:34 +0000557 return bm_aligned_load_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000558}
559
560Bool bm_load_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
561{
bart3772a982008-03-15 08:11:03 +0000562 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000563 return bm_aligned_load_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000564 else
565 return bm_has_conflict_with(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000566}
567
568Bool bm_load_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
569{
bart3772a982008-03-15 08:11:03 +0000570 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000571 return bm_aligned_load_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000572 else
573 return bm_has_conflict_with(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000574}
575
576Bool bm_load_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
577{
bart3772a982008-03-15 08:11:03 +0000578 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000579 return bm_aligned_load_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000580 else
581 return bm_has_conflict_with(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000582}
583
584Bool bm_store_1_has_conflict_with(const struct bitmap* const bm, const Addr a1)
585{
bartf8bc71d2008-03-15 11:42:34 +0000586 return bm_aligned_store_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000587}
588
589Bool bm_store_2_has_conflict_with(const struct bitmap* const bm, const Addr a1)
590{
bart3772a982008-03-15 08:11:03 +0000591 if ((a1 & 1) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000592 return bm_aligned_store_has_conflict_with(bm, a1, 2);
bart3772a982008-03-15 08:11:03 +0000593 else
594 return bm_has_conflict_with(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000595}
596
597Bool bm_store_4_has_conflict_with(const struct bitmap* const bm, const Addr a1)
598{
bart3772a982008-03-15 08:11:03 +0000599 if ((a1 & 3) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000600 return bm_aligned_store_has_conflict_with(bm, a1, 4);
bart3772a982008-03-15 08:11:03 +0000601 else
602 return bm_has_conflict_with(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000603}
604
605Bool bm_store_8_has_conflict_with(const struct bitmap* const bm, const Addr a1)
606{
bart3772a982008-03-15 08:11:03 +0000607 if ((a1 & 7) == 0)
bartf8bc71d2008-03-15 11:42:34 +0000608 return bm_aligned_store_has_conflict_with(bm, a1, 8);
bart3772a982008-03-15 08:11:03 +0000609 else
610 return bm_has_conflict_with(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000611}
612
bart36556122008-03-13 19:24:30 +0000613Bool bm_store_has_conflict_with(const struct bitmap* const bm,
614 const Addr a1, const Addr a2)
615{
bart3772a982008-03-15 08:11:03 +0000616 return bm_has_conflict_with(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000617}
618
619void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
620{
bart3772a982008-03-15 08:11:03 +0000621 OSet* const tmp = bm1->oset;
622 bm1->oset = bm2->oset;
623 bm2->oset = tmp;
sewardjaf44c822007-11-25 14:01:38 +0000624}
625
626void bm_merge2(struct bitmap* const lhs,
627 const struct bitmap* const rhs)
628{
bart3772a982008-03-15 08:11:03 +0000629 struct bitmap2* bm2l;
630 const struct bitmap2* bm2r;
sewardjaf44c822007-11-25 14:01:38 +0000631
bart3772a982008-03-15 08:11:03 +0000632 // First step: allocate any missing bitmaps in *lhs.
633 VG_(OSetGen_ResetIter)(rhs->oset);
634 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
635 {
636 bm2_lookup_or_insert(lhs, bm2r->addr);
637 }
sewardjaf44c822007-11-25 14:01:38 +0000638
bart3772a982008-03-15 08:11:03 +0000639 VG_(OSetGen_ResetIter)(lhs->oset);
640 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000641
bart3772a982008-03-15 08:11:03 +0000642 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
643 {
644 do
645 {
646 bm2l = VG_(OSetGen_Next)(lhs->oset);
647 } while (bm2l->addr < bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000648
bart3772a982008-03-15 08:11:03 +0000649 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000650
bart3772a982008-03-15 08:11:03 +0000651 bm2_merge(bm2l, bm2r);
652 }
sewardjaf44c822007-11-25 14:01:38 +0000653}
654
655/**
656 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
657 * @param lhs First bitmap.
658 * @param rhs Bitmap to be compared with lhs.
659 * @return !=0 if there are data races, == 0 if there are none.
660 */
661int bm_has_races(const struct bitmap* const lhs,
662 const struct bitmap* const rhs)
663{
bart3772a982008-03-15 08:11:03 +0000664 VG_(OSetGen_ResetIter)(lhs->oset);
665 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000666
bart3772a982008-03-15 08:11:03 +0000667 for (;;)
668 {
669 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
670 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
671 const struct bitmap1* bm1l;
672 const struct bitmap1* bm1r;
673 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000674
bart3772a982008-03-15 08:11:03 +0000675 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
676 {
677 if (bm2l->addr < bm2r->addr)
678 bm2l = VG_(OSetGen_Next)(lhs->oset);
679 else
680 bm2r = VG_(OSetGen_Next)(rhs->oset);
681 }
682 if (bm2l == 0 || bm2r == 0)
683 break;
684
685 bm1l = &bm2l->bm1;
686 bm1r = &bm2r->bm1;
687
688 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
689 {
690 unsigned b;
691 for (b = 0; b < BITS_PER_UWORD; b++)
sewardjaf44c822007-11-25 14:01:38 +0000692 {
bart3772a982008-03-15 08:11:03 +0000693 UWord const access
694 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
695 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
696 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
697 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
698 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
699 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
700 {
701 return 1;
702 }
sewardjaf44c822007-11-25 14:01:38 +0000703 }
bart3772a982008-03-15 08:11:03 +0000704 }
705 }
706 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000707}
708
sewardjaf44c822007-11-25 14:01:38 +0000709void bm_print(const struct bitmap* const bm)
710{
bart3772a982008-03-15 08:11:03 +0000711 struct bitmap2* bm2;
sewardjaf44c822007-11-25 14:01:38 +0000712
bart3772a982008-03-15 08:11:03 +0000713 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000714
bart3772a982008-03-15 08:11:03 +0000715 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
716 {
717 const struct bitmap1* const bm1 = &bm2->bm1;
bart0008f5b2008-03-22 17:07:39 +0000718 unsigned b;
719 for (b = 0; b < ADDR0_COUNT; b++)
bart3772a982008-03-15 08:11:03 +0000720 {
bart0008f5b2008-03-22 17:07:39 +0000721 const Addr a = (bm2->addr << ADDR0_BITS) | b;
722 const Bool r = bm0_is_set(bm1->bm0_r, b) != 0;
723 const Bool w = bm0_is_set(bm1->bm0_w, b) != 0;
724 if (r || w)
sewardjaf44c822007-11-25 14:01:38 +0000725 {
bart0008f5b2008-03-22 17:07:39 +0000726 VG_(printf)("0x%08lx %c %c\n",
727 a,
728 w ? 'W' : ' ',
729 r ? 'R' : ' ');
sewardjaf44c822007-11-25 14:01:38 +0000730 }
bart3772a982008-03-15 08:11:03 +0000731 }
732 }
sewardjaf44c822007-11-25 14:01:38 +0000733}
734
735ULong bm_get_bitmap_creation_count(void)
736{
bart3772a982008-03-15 08:11:03 +0000737 return s_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000738}
739
740ULong bm_get_bitmap2_creation_count(void)
741{
bart3772a982008-03-15 08:11:03 +0000742 return s_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000743}
744
745static void bm2_merge(struct bitmap2* const bm2l,
746 const struct bitmap2* const bm2r)
747{
bart3772a982008-03-15 08:11:03 +0000748 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000749
bart33e56c92008-03-24 06:41:30 +0000750 tl_assert(bm2l);
751 tl_assert(bm2r);
bart3772a982008-03-15 08:11:03 +0000752 tl_assert(bm2l->addr == bm2r->addr);
sewardjaf44c822007-11-25 14:01:38 +0000753
bart3772a982008-03-15 08:11:03 +0000754 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
755 {
756 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
757 }
758 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
759 {
760 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
761 }
sewardjaf44c822007-11-25 14:01:38 +0000762}
763
764#if 0
765
766/* Unit test */
767static
768struct { Addr address; SizeT size; BmAccessTypeT access_type; }
bart3772a982008-03-15 08:11:03 +0000769 s_args[] = {
bart0008f5b2008-03-22 17:07:39 +0000770 { 0 + ADDR0_COUNT, 1, eLoad },
771 { 666 + ADDR0_COUNT, 4, eLoad },
772 { 667 + ADDR0_COUNT, 2, eStore },
bart33e56c92008-03-24 06:41:30 +0000773 { -2 + 2*ADDR0_COUNT, 1, eStore },
bart0008f5b2008-03-22 17:07:39 +0000774 { 0x0001ffffUL, 1, eLoad },
775 { 0x0002ffffUL, 1, eLoad },
776 { 0x00ffffffUL, 1, eLoad },
777 { 0xffffffffUL, 1, eStore },
bart3772a982008-03-15 08:11:03 +0000778 };
sewardjaf44c822007-11-25 14:01:38 +0000779
780void bm_test(void)
781{
bart3772a982008-03-15 08:11:03 +0000782 struct bitmap* bm;
783 struct bitmap* bm2;
bart0008f5b2008-03-22 17:07:39 +0000784 unsigned i, j;
sewardjaf44c822007-11-25 14:01:38 +0000785
bart3772a982008-03-15 08:11:03 +0000786 VG_(printf)("Start of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000787
bart3772a982008-03-15 08:11:03 +0000788 bm = bm_new();
sewardjaf44c822007-11-25 14:01:38 +0000789
bart3772a982008-03-15 08:11:03 +0000790 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
791 {
792 bm_access_range(bm,
793 s_args[i].address,
794 s_args[i].address + s_args[i].size,
795 s_args[i].access_type);
796 }
sewardjaf44c822007-11-25 14:01:38 +0000797
bart3772a982008-03-15 08:11:03 +0000798 VG_(printf)("Map contents -- should contain 10 addresses:\n");
799 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000800
bart3772a982008-03-15 08:11:03 +0000801 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
802 {
803 for (j = 0; j < s_args[i].size; j++)
804 {
805 tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
806 }
807 }
sewardjaf44c822007-11-25 14:01:38 +0000808
bart3772a982008-03-15 08:11:03 +0000809 VG_(printf)("Merge result:\n");
bart0008f5b2008-03-22 17:07:39 +0000810 bm2 = bm_new();
811 bm_merge2(bm2, bm);
812 bm_merge2(bm2, bm);
bart3772a982008-03-15 08:11:03 +0000813 bm_print(bm);
sewardjaf44c822007-11-25 14:01:38 +0000814
bart0008f5b2008-03-22 17:07:39 +0000815 VG_(printf)("Deleting bitmap bm\n");
bart3772a982008-03-15 08:11:03 +0000816 bm_delete(bm);
bart0008f5b2008-03-22 17:07:39 +0000817 VG_(printf)("Deleting bitmap bm2\n");
bart3772a982008-03-15 08:11:03 +0000818 bm_delete(bm2);
sewardjaf44c822007-11-25 14:01:38 +0000819
bart3772a982008-03-15 08:11:03 +0000820 VG_(printf)("End of DRD BM unit test.\n");
sewardjaf44c822007-11-25 14:01:38 +0000821}
822#endif