blob: 85cacd5078a02bd525b72b5f6c4ed3d1b2fa445d [file] [log] [blame]
bartbedfd232009-03-26 19:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardjaf44c822007-11-25 14:01:38 +00002/*
bart86562bd2009-02-16 19:43:56 +00003 This file is part of drd, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00004
bart86562bd2009-02-16 19:43:56 +00005 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
sewardjaf44c822007-11-25 14:01:38 +00006
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
bart39934d62009-02-15 16:18:03 +000026#include "drd_basics.h" /* DRD_() */
sewardjaf44c822007-11-25 14:01:38 +000027#include "drd_bitmap.h"
28#include "drd_error.h"
29#include "drd_suppression.h"
bart39934d62009-02-15 16:18:03 +000030#include "pub_drd_bitmap.h"
31#include "pub_tool_basics.h" /* Addr, SizeT */
32#include "pub_tool_debuginfo.h" /* VG_(get_objname)() */
33#include "pub_tool_libcassert.h" /* tl_assert() */
34#include "pub_tool_libcbase.h" /* VG_(memset) */
35#include "pub_tool_libcprint.h" /* VG_(printf) */
36#include "pub_tool_machine.h" /* VG_(get_IP)() */
37#include "pub_tool_mallocfree.h" /* VG_(malloc), VG_(free) */
sewardjaf44c822007-11-25 14:01:38 +000038
39
bartf647d342008-03-24 19:12:12 +000040/* Forward declarations. */
sewardjaf44c822007-11-25 14:01:38 +000041
bartf647d342008-03-24 19:12:12 +000042struct bitmap2;
sewardjaf44c822007-11-25 14:01:38 +000043
44
bartf647d342008-03-24 19:12:12 +000045/* Local function declarations. */
sewardjaf44c822007-11-25 14:01:38 +000046
47static void bm2_merge(struct bitmap2* const bm2l,
48 const struct bitmap2* const bm2r);
49
50
bart99edb292009-02-15 15:59:20 +000051/* Local variables. */
bartf647d342008-03-24 19:12:12 +000052
53static ULong s_bitmap_creation_count;
54
55
56/* Function definitions. */
sewardjaf44c822007-11-25 14:01:38 +000057
bart99edb292009-02-15 15:59:20 +000058struct bitmap* DRD_(bm_new)()
sewardjaf44c822007-11-25 14:01:38 +000059{
bartbedfd232009-03-26 19:07:15 +000060 unsigned i;
61 struct bitmap* bm;
sewardjaf44c822007-11-25 14:01:38 +000062
bartbedfd232009-03-26 19:07:15 +000063 /* If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD */
64 /* in drd_bitmap.h. */
65 tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD);
sewardjaf44c822007-11-25 14:01:38 +000066
bartbedfd232009-03-26 19:07:15 +000067 bm = VG_(malloc)("drd.bitmap.bn.1", sizeof(*bm));
68 tl_assert(bm);
69 /* Cache initialization. a1 is initialized with a value that never can */
70 /* match any valid address: the upper ADDR0_BITS bits of a1 are always */
71 /* zero for a valid cache entry. */
72 for (i = 0; i < N_CACHE_ELEM; i++)
73 {
74 bm->cache[i].a1 = ~(UWord)1;
75 bm->cache[i].bm2 = 0;
76 }
77 bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.bitmap.bn.2",
78 VG_(free));
sewardjaf44c822007-11-25 14:01:38 +000079
bartbedfd232009-03-26 19:07:15 +000080 s_bitmap_creation_count++;
sewardjaf44c822007-11-25 14:01:38 +000081
bartbedfd232009-03-26 19:07:15 +000082 return bm;
sewardjaf44c822007-11-25 14:01:38 +000083}
84
bart99edb292009-02-15 15:59:20 +000085void DRD_(bm_delete)(struct bitmap* const bm)
sewardjaf44c822007-11-25 14:01:38 +000086{
bartbedfd232009-03-26 19:07:15 +000087 struct bitmap2* bm2;
88 struct bitmap2ref* bm2ref;
bartf647d342008-03-24 19:12:12 +000089
bartbedfd232009-03-26 19:07:15 +000090 tl_assert(bm);
bartf647d342008-03-24 19:12:12 +000091
bartbedfd232009-03-26 19:07:15 +000092 VG_(OSetGen_ResetIter)(bm->oset);
93 for ( ; (bm2ref = VG_(OSetGen_Next)(bm->oset)) != 0; )
94 {
95 bm2 = bm2ref->bm2;
96 tl_assert(bm2->refcnt >= 1);
97 if (--bm2->refcnt == 0)
98 {
99 VG_(free)(bm2);
100 }
101 }
bartf647d342008-03-24 19:12:12 +0000102
bartbedfd232009-03-26 19:07:15 +0000103 VG_(OSetGen_Destroy)(bm->oset);
104 VG_(free)(bm);
sewardjaf44c822007-11-25 14:01:38 +0000105}
106
107/**
bart36556122008-03-13 19:24:30 +0000108 * Record an access of type access_type at addresses a .. a + size - 1 in
sewardjaf44c822007-11-25 14:01:38 +0000109 * bitmap bm.
110 */
bart99edb292009-02-15 15:59:20 +0000111void DRD_(bm_access_range)(struct bitmap* const bm,
112 const Addr a1, const Addr a2,
113 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000114{
bartbedfd232009-03-26 19:07:15 +0000115 Addr b, b_next;
bart36556122008-03-13 19:24:30 +0000116
bartbedfd232009-03-26 19:07:15 +0000117 tl_assert(bm);
118 tl_assert(a1 < a2);
119 /* The current implementation of bm_access_range does not work for the */
120 /* ADDR0_COUNT highest addresses in the address range. At least on Linux */
121 /* this is not a problem since the upper part of the address space is */
122 /* reserved for the kernel. */
123 tl_assert(a2 + ADDR0_COUNT > a2);
sewardjaf44c822007-11-25 14:01:38 +0000124
bartbedfd232009-03-26 19:07:15 +0000125 for (b = a1; b < a2; b = b_next)
126 {
127 Addr b_start;
128 Addr b_end;
129 struct bitmap2* bm2;
130 SPLIT_ADDRESS(b);
bart36556122008-03-13 19:24:30 +0000131
bartbedfd232009-03-26 19:07:15 +0000132 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
133 if (b_next > a2)
134 {
135 b_next = a2;
136 }
bart36556122008-03-13 19:24:30 +0000137
bartbedfd232009-03-26 19:07:15 +0000138 bm2 = bm2_lookup_or_insert_exclusive(bm, b1);
139 tl_assert(bm2);
bart36556122008-03-13 19:24:30 +0000140
bartbedfd232009-03-26 19:07:15 +0000141 if ((bm2->addr << ADDR0_BITS) < a1)
142 b_start = a1;
bart36556122008-03-13 19:24:30 +0000143 else
bartbedfd232009-03-26 19:07:15 +0000144 if ((bm2->addr << ADDR0_BITS) < a2)
145 b_start = (bm2->addr << ADDR0_BITS);
146 else
147 break;
148 tl_assert(a1 <= b_start && b_start <= a2);
bart36556122008-03-13 19:24:30 +0000149
bartbedfd232009-03-26 19:07:15 +0000150 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
151 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
152 else
153 b_end = a2;
154 tl_assert(a1 <= b_end && b_end <= a2);
155 tl_assert(b_start < b_end);
156 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
bart36556122008-03-13 19:24:30 +0000157
bartbedfd232009-03-26 19:07:15 +0000158 if (access_type == eLoad)
bart36556122008-03-13 19:24:30 +0000159 {
bartbedfd232009-03-26 19:07:15 +0000160 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
161 {
162 bm0_set(bm2->bm1.bm0_r, b0);
163 }
sewardjaf44c822007-11-25 14:01:38 +0000164 }
bartbedfd232009-03-26 19:07:15 +0000165 else
bart3772a982008-03-15 08:11:03 +0000166 {
bartbedfd232009-03-26 19:07:15 +0000167 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
168 {
169 bm0_set(bm2->bm1.bm0_w, b0);
170 }
bart3772a982008-03-15 08:11:03 +0000171 }
bartbedfd232009-03-26 19:07:15 +0000172 }
sewardjaf44c822007-11-25 14:01:38 +0000173}
174
bart99edb292009-02-15 15:59:20 +0000175void DRD_(bm_access_range_load)(struct bitmap* const bm,
176 const Addr a1, const Addr a2)
bart36556122008-03-13 19:24:30 +0000177{
bartbedfd232009-03-26 19:07:15 +0000178 DRD_(bm_access_range)(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000179}
180
bart99edb292009-02-15 15:59:20 +0000181void DRD_(bm_access_load_1)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000182{
bartbedfd232009-03-26 19:07:15 +0000183 bm_access_aligned_load(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000184}
185
bart99edb292009-02-15 15:59:20 +0000186void DRD_(bm_access_load_2)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000187{
bartbedfd232009-03-26 19:07:15 +0000188 if ((a1 & 1) == 0)
189 bm_access_aligned_load(bm, a1, 2);
190 else
191 DRD_(bm_access_range)(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000192}
193
bart99edb292009-02-15 15:59:20 +0000194void DRD_(bm_access_load_4)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000195{
bartbedfd232009-03-26 19:07:15 +0000196 if ((a1 & 3) == 0)
197 bm_access_aligned_load(bm, a1, 4);
198 else
199 DRD_(bm_access_range)(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000200}
201
bart99edb292009-02-15 15:59:20 +0000202void DRD_(bm_access_load_8)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000203{
bartbedfd232009-03-26 19:07:15 +0000204 if ((a1 & 7) == 0)
205 bm_access_aligned_load(bm, a1, 8);
206 else if ((a1 & 3) == 0)
207 {
208 bm_access_aligned_load(bm, a1 + 0, 4);
209 bm_access_aligned_load(bm, a1 + 4, 4);
210 }
211 else
212 DRD_(bm_access_range)(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000213}
214
bart99edb292009-02-15 15:59:20 +0000215void DRD_(bm_access_range_store)(struct bitmap* const bm,
216 const Addr a1, const Addr a2)
bartf5acbbc2008-05-10 08:22:20 +0000217{
bartbedfd232009-03-26 19:07:15 +0000218 DRD_(bm_access_range)(bm, a1, a2, eStore);
bartf5acbbc2008-05-10 08:22:20 +0000219}
220
bart99edb292009-02-15 15:59:20 +0000221void DRD_(bm_access_store_1)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000222{
bartbedfd232009-03-26 19:07:15 +0000223 bm_access_aligned_store(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000224}
225
bart99edb292009-02-15 15:59:20 +0000226void DRD_(bm_access_store_2)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000227{
bartbedfd232009-03-26 19:07:15 +0000228 if ((a1 & 1) == 0)
229 bm_access_aligned_store(bm, a1, 2);
230 else
231 DRD_(bm_access_range)(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000232}
233
bart99edb292009-02-15 15:59:20 +0000234void DRD_(bm_access_store_4)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000235{
bartbedfd232009-03-26 19:07:15 +0000236 if ((a1 & 3) == 0)
237 bm_access_aligned_store(bm, a1, 4);
238 else
239 DRD_(bm_access_range)(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000240}
241
bart99edb292009-02-15 15:59:20 +0000242void DRD_(bm_access_store_8)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000243{
bartbedfd232009-03-26 19:07:15 +0000244 if ((a1 & 7) == 0)
245 bm_access_aligned_store(bm, a1, 8);
246 else if ((a1 & 3) == 0)
247 {
248 bm_access_aligned_store(bm, a1 + 0, 4);
249 bm_access_aligned_store(bm, a1 + 4, 4);
250 }
251 else
252 DRD_(bm_access_range)(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000253}
254
bart99edb292009-02-15 15:59:20 +0000255Bool DRD_(bm_has)(struct bitmap* const bm, const Addr a1, const Addr a2,
256 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000257{
bartbedfd232009-03-26 19:07:15 +0000258 Addr b;
259 for (b = a1; b < a2; b++)
260 {
261 if (! DRD_(bm_has_1)(bm, b, access_type))
262 {
263 return False;
264 }
265 }
266 return True;
sewardjaf44c822007-11-25 14:01:38 +0000267}
268
bart99edb292009-02-15 15:59:20 +0000269Bool
270DRD_(bm_has_any_load)(struct bitmap* const bm, const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000271{
bartbedfd232009-03-26 19:07:15 +0000272 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000273
bartbedfd232009-03-26 19:07:15 +0000274 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000275
bartbedfd232009-03-26 19:07:15 +0000276 for (b = a1; b < a2; b = b_next)
277 {
278 const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
bartd4907072008-03-30 18:41:07 +0000279
bartbedfd232009-03-26 19:07:15 +0000280 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
281 if (b_next > a2)
bartd4907072008-03-30 18:41:07 +0000282 {
bartbedfd232009-03-26 19:07:15 +0000283 b_next = a2;
bartd4907072008-03-30 18:41:07 +0000284 }
bartbedfd232009-03-26 19:07:15 +0000285
286 if (bm2)
287 {
288 Addr b_start;
289 Addr b_end;
290 UWord b0;
291 const struct bitmap1* const p1 = &bm2->bm1;
292
293 if ((bm2->addr << ADDR0_BITS) < a1)
294 b_start = a1;
295 else
296 if ((bm2->addr << ADDR0_BITS) < a2)
297 b_start = (bm2->addr << ADDR0_BITS);
298 else
299 break;
300 tl_assert(a1 <= b_start && b_start <= a2);
301
302 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
303 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
304 else
305 b_end = a2;
306 tl_assert(a1 <= b_end && b_end <= a2);
307 tl_assert(b_start < b_end);
308 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
309
310 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
311 {
312 if (bm0_is_set(p1->bm0_r, b0))
313 {
314 return True;
315 }
316 }
317 }
318 }
319 return 0;
bartd4907072008-03-30 18:41:07 +0000320}
321
bart99edb292009-02-15 15:59:20 +0000322Bool DRD_(bm_has_any_store)(struct bitmap* const bm,
323 const Addr a1, const Addr a2)
bartd4907072008-03-30 18:41:07 +0000324{
bartbedfd232009-03-26 19:07:15 +0000325 Addr b, b_next;
bartd4907072008-03-30 18:41:07 +0000326
bartbedfd232009-03-26 19:07:15 +0000327 tl_assert(bm);
bartd4907072008-03-30 18:41:07 +0000328
bartbedfd232009-03-26 19:07:15 +0000329 for (b = a1; b < a2; b = b_next)
330 {
331 const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
bartd4907072008-03-30 18:41:07 +0000332
bartbedfd232009-03-26 19:07:15 +0000333 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
334 if (b_next > a2)
bartd4907072008-03-30 18:41:07 +0000335 {
bartbedfd232009-03-26 19:07:15 +0000336 b_next = a2;
bartd4907072008-03-30 18:41:07 +0000337 }
bartbedfd232009-03-26 19:07:15 +0000338
339 if (bm2)
340 {
341 Addr b_start;
342 Addr b_end;
343 UWord b0;
344 const struct bitmap1* const p1 = &bm2->bm1;
345
346 if ((bm2->addr << ADDR0_BITS) < a1)
347 b_start = a1;
348 else
349 if ((bm2->addr << ADDR0_BITS) < a2)
350 b_start = (bm2->addr << ADDR0_BITS);
351 else
352 break;
353 tl_assert(a1 <= b_start && b_start <= a2);
354
355 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
356 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
357 else
358 b_end = a2;
359 tl_assert(a1 <= b_end && b_end <= a2);
360 tl_assert(b_start < b_end);
361 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
362
363 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
364 {
365 if (bm0_is_set(p1->bm0_w, b0))
366 {
367 return True;
368 }
369 }
370 }
371 }
372 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000373}
374
bartc2c81db2008-05-10 11:19:10 +0000375/* Return True if there is a read access, write access or both */
376/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
bart99edb292009-02-15 15:59:20 +0000377Bool DRD_(bm_has_any_access)(struct bitmap* const bm,
378 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000379{
bartbedfd232009-03-26 19:07:15 +0000380 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000381
bartbedfd232009-03-26 19:07:15 +0000382 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000383
bartbedfd232009-03-26 19:07:15 +0000384 for (b = a1; b < a2; b = b_next)
385 {
386 const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000387
bartbedfd232009-03-26 19:07:15 +0000388 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
389 if (b_next > a2)
bart3772a982008-03-15 08:11:03 +0000390 {
bartbedfd232009-03-26 19:07:15 +0000391 b_next = a2;
sewardjaf44c822007-11-25 14:01:38 +0000392 }
bartbedfd232009-03-26 19:07:15 +0000393
394 if (bm2)
395 {
396 Addr b_start;
397 Addr b_end;
398 UWord b0;
399 const struct bitmap1* const p1 = &bm2->bm1;
400
401 if ((bm2->addr << ADDR0_BITS) < a1)
402 b_start = a1;
403 else
404 if ((bm2->addr << ADDR0_BITS) < a2)
405 b_start = (bm2->addr << ADDR0_BITS);
406 else
407 break;
408 tl_assert(a1 <= b_start && b_start <= a2);
409
410 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
411 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
412 else
413 b_end = a2;
414 tl_assert(a1 <= b_end && b_end <= a2);
415 tl_assert(b_start < b_end);
416 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
417
418 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
419 {
420 if (bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0))
421 {
422 return True;
423 }
424 }
425 }
426 }
427 return False;
sewardjaf44c822007-11-25 14:01:38 +0000428}
429
bart99edb292009-02-15 15:59:20 +0000430/**
431 * Report whether an access of type access_type at address a is recorded in
432 * bitmap bm.
sewardjaf44c822007-11-25 14:01:38 +0000433 */
bart99edb292009-02-15 15:59:20 +0000434Bool DRD_(bm_has_1)(struct bitmap* const bm,
435 const Addr a, const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000436{
bartbedfd232009-03-26 19:07:15 +0000437 const struct bitmap2* p2;
438 const struct bitmap1* p1;
439 const UWord* p0;
440 const UWord a0 = a & ADDR0_MASK;
sewardjaf44c822007-11-25 14:01:38 +0000441
bartbedfd232009-03-26 19:07:15 +0000442 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000443
bartbedfd232009-03-26 19:07:15 +0000444 p2 = bm2_lookup(bm, a >> ADDR0_BITS);
445 if (p2)
446 {
447 p1 = &p2->bm1;
448 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
449 return bm0_is_set(p0, a0) ? True : False;
450 }
451 return False;
sewardjaf44c822007-11-25 14:01:38 +0000452}
453
bart99edb292009-02-15 15:59:20 +0000454void DRD_(bm_clear)(struct bitmap* const bm, const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000455{
bartbedfd232009-03-26 19:07:15 +0000456 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000457
bartbedfd232009-03-26 19:07:15 +0000458 tl_assert(bm);
459 tl_assert(a1);
460 tl_assert(a1 <= a2);
sewardjaf44c822007-11-25 14:01:38 +0000461
bartbedfd232009-03-26 19:07:15 +0000462 for (b = a1; b < a2; b = b_next)
463 {
464 struct bitmap2* const p2 = bm2_lookup_exclusive(bm, b >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +0000465
bartbedfd232009-03-26 19:07:15 +0000466 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
467 if (b_next > a2)
sewardjaf44c822007-11-25 14:01:38 +0000468 {
bartbedfd232009-03-26 19:07:15 +0000469 b_next = a2;
sewardjaf44c822007-11-25 14:01:38 +0000470 }
bartbedfd232009-03-26 19:07:15 +0000471
472 if (p2)
sewardjaf44c822007-11-25 14:01:38 +0000473 {
bartbedfd232009-03-26 19:07:15 +0000474 Addr c = b;
475 /* If the first address in the bitmap that must be cleared does not */
476 /* start on an UWord boundary, start clearing the first addresses. */
477 if (UWORD_LSB(c))
478 {
479 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
480 if (c_next > b_next)
481 c_next = b_next;
482 bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, c_next - c);
483 bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, c_next - c);
484 c = c_next;
485 }
486 /* If some UWords have to be cleared entirely, do this now. */
487 if (UWORD_LSB(c) == 0)
488 {
489 const Addr c_next = UWORD_MSB(b_next);
490 tl_assert(UWORD_LSB(c) == 0);
491 tl_assert(UWORD_LSB(c_next) == 0);
492 tl_assert(c_next <= b_next);
493 tl_assert(c <= c_next);
494 if (c_next > c)
495 {
496 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
497 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
498 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
499 c = c_next;
500 }
501 }
502 /* If the last address in the bitmap that must be cleared does not */
503 /* fall on an UWord boundary, clear the last addresses. */
504 /* tl_assert(c <= b_next); */
505 bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, b_next - c);
506 bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, b_next - c);
sewardjaf44c822007-11-25 14:01:38 +0000507 }
bartbedfd232009-03-26 19:07:15 +0000508 }
sewardjaf44c822007-11-25 14:01:38 +0000509}
sewardjaf44c822007-11-25 14:01:38 +0000510
bart99edb292009-02-15 15:59:20 +0000511/**
512 * Clear all references to loads in bitmap bm starting at address a1 and
513 * up to but not including address a2.
bart9c4224c2008-03-29 14:40:08 +0000514 */
bart99edb292009-02-15 15:59:20 +0000515void DRD_(bm_clear_load)(struct bitmap* const bm, const Addr a1, const Addr a2)
bart9c4224c2008-03-29 14:40:08 +0000516{
bartbedfd232009-03-26 19:07:15 +0000517 Addr a;
bart9c4224c2008-03-29 14:40:08 +0000518
bartbedfd232009-03-26 19:07:15 +0000519 for (a = a1; a < a2; a++)
520 {
521 struct bitmap2* const p2 = bm2_lookup_exclusive(bm, a >> ADDR0_BITS);
522 if (p2)
523 {
524 bm0_clear(p2->bm1.bm0_r, a & ADDR0_MASK);
525 }
526 }
bart9c4224c2008-03-29 14:40:08 +0000527}
528
bart99edb292009-02-15 15:59:20 +0000529/**
530 * Clear all references to stores in bitmap bm starting at address a1 and
531 * up to but not including address a2.
bart9c4224c2008-03-29 14:40:08 +0000532 */
bart99edb292009-02-15 15:59:20 +0000533void DRD_(bm_clear_store)(struct bitmap* const bm,
534 const Addr a1, const Addr a2)
bart9c4224c2008-03-29 14:40:08 +0000535{
bartbedfd232009-03-26 19:07:15 +0000536 Addr a;
bart9c4224c2008-03-29 14:40:08 +0000537
bartbedfd232009-03-26 19:07:15 +0000538 for (a = a1; a < a2; a++)
539 {
540 struct bitmap2* const p2 = bm2_lookup_exclusive(bm, a >> ADDR0_BITS);
541 if (p2)
542 {
543 bm0_clear(p2->bm1.bm0_w, a & ADDR0_MASK);
544 }
545 }
bart9c4224c2008-03-29 14:40:08 +0000546}
547
bart99edb292009-02-15 15:59:20 +0000548/**
549 * Clear bitmap bm starting at address a1 and up to but not including address
550 * a2. Return True if and only if any of the addresses was set before
551 * clearing.
bart8bf2f8b2008-03-30 17:56:43 +0000552 */
bart99edb292009-02-15 15:59:20 +0000553Bool DRD_(bm_test_and_clear)(struct bitmap* const bm,
554 const Addr a1, const Addr a2)
bart8bf2f8b2008-03-30 17:56:43 +0000555{
bartbedfd232009-03-26 19:07:15 +0000556 Bool result;
bart8bf2f8b2008-03-30 17:56:43 +0000557
bartbedfd232009-03-26 19:07:15 +0000558 result = DRD_(bm_has_any_access)(bm, a1, a2) != 0;
559 DRD_(bm_clear)(bm, a1, a2);
560 return result;
bart8bf2f8b2008-03-30 17:56:43 +0000561}
562
bart99edb292009-02-15 15:59:20 +0000563Bool DRD_(bm_has_conflict_with)(struct bitmap* const bm,
564 const Addr a1, const Addr a2,
565 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000566{
bartbedfd232009-03-26 19:07:15 +0000567 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000568
bartbedfd232009-03-26 19:07:15 +0000569 tl_assert(bm);
sewardjaf44c822007-11-25 14:01:38 +0000570
bartbedfd232009-03-26 19:07:15 +0000571 for (b = a1; b < a2; b = b_next)
572 {
573 const struct bitmap2* bm2 = bm2_lookup(bm, b >> ADDR0_BITS);
bart36556122008-03-13 19:24:30 +0000574
bartbedfd232009-03-26 19:07:15 +0000575 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
576 if (b_next > a2)
bart3772a982008-03-15 08:11:03 +0000577 {
bartbedfd232009-03-26 19:07:15 +0000578 b_next = a2;
sewardjaf44c822007-11-25 14:01:38 +0000579 }
bartbedfd232009-03-26 19:07:15 +0000580
581 if (bm2)
582 {
583 Addr b_start;
584 Addr b_end;
585 UWord b0;
586 const struct bitmap1* const p1 = &bm2->bm1;
587
588 if ((bm2->addr << ADDR0_BITS) < a1)
589 b_start = a1;
590 else
591 if ((bm2->addr << ADDR0_BITS) < a2)
592 b_start = (bm2->addr << ADDR0_BITS);
593 else
594 break;
595 tl_assert(a1 <= b_start && b_start <= a2);
596
597 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
598 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
599 else
600 b_end = a2;
601 tl_assert(a1 <= b_end && b_end <= a2);
602 tl_assert(b_start < b_end);
603 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
604
605 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
606 {
607 if (access_type == eLoad)
608 {
609 if (bm0_is_set(p1->bm0_w, b0))
610 {
611 return True;
612 }
613 }
614 else
615 {
616 tl_assert(access_type == eStore);
617 if (bm0_is_set(p1->bm0_r, b0)
618 | bm0_is_set(p1->bm0_w, b0))
619 {
620 return True;
621 }
622 }
623 }
624 }
625 }
626 return False;
sewardjaf44c822007-11-25 14:01:38 +0000627}
628
bart99edb292009-02-15 15:59:20 +0000629Bool DRD_(bm_load_has_conflict_with)(struct bitmap* const bm,
630 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000631{
bartbedfd232009-03-26 19:07:15 +0000632 return DRD_(bm_has_conflict_with)(bm, a1, a2, eLoad);
bart36556122008-03-13 19:24:30 +0000633}
634
bart99edb292009-02-15 15:59:20 +0000635Bool DRD_(bm_load_1_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000636{
bartbedfd232009-03-26 19:07:15 +0000637 return bm_aligned_load_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000638}
639
bart99edb292009-02-15 15:59:20 +0000640Bool DRD_(bm_load_2_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000641{
bartbedfd232009-03-26 19:07:15 +0000642 if ((a1 & 1) == 0)
643 return bm_aligned_load_has_conflict_with(bm, a1, 2);
644 else
645 return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eLoad);
barta79df6e2008-03-14 17:07:51 +0000646}
647
bart99edb292009-02-15 15:59:20 +0000648Bool DRD_(bm_load_4_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000649{
bartbedfd232009-03-26 19:07:15 +0000650 if ((a1 & 3) == 0)
651 return bm_aligned_load_has_conflict_with(bm, a1, 4);
652 else
653 return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eLoad);
barta79df6e2008-03-14 17:07:51 +0000654}
655
bart99edb292009-02-15 15:59:20 +0000656Bool DRD_(bm_load_8_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000657{
bartbedfd232009-03-26 19:07:15 +0000658 if ((a1 & 7) == 0)
659 return bm_aligned_load_has_conflict_with(bm, a1, 8);
660 else
661 return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eLoad);
barta79df6e2008-03-14 17:07:51 +0000662}
663
bart99edb292009-02-15 15:59:20 +0000664Bool DRD_(bm_store_1_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000665{
bartbedfd232009-03-26 19:07:15 +0000666 return bm_aligned_store_has_conflict_with(bm, a1, 1);
barta79df6e2008-03-14 17:07:51 +0000667}
668
bart99edb292009-02-15 15:59:20 +0000669Bool DRD_(bm_store_2_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000670{
bartbedfd232009-03-26 19:07:15 +0000671 if ((a1 & 1) == 0)
672 return bm_aligned_store_has_conflict_with(bm, a1, 2);
673 else
674 return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eStore);
barta79df6e2008-03-14 17:07:51 +0000675}
676
bart99edb292009-02-15 15:59:20 +0000677Bool DRD_(bm_store_4_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000678{
bartbedfd232009-03-26 19:07:15 +0000679 if ((a1 & 3) == 0)
680 return bm_aligned_store_has_conflict_with(bm, a1, 4);
681 else
682 return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eStore);
barta79df6e2008-03-14 17:07:51 +0000683}
684
bart99edb292009-02-15 15:59:20 +0000685Bool DRD_(bm_store_8_has_conflict_with)(struct bitmap* const bm, const Addr a1)
barta79df6e2008-03-14 17:07:51 +0000686{
bartbedfd232009-03-26 19:07:15 +0000687 if ((a1 & 7) == 0)
688 return bm_aligned_store_has_conflict_with(bm, a1, 8);
689 else
690 return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eStore);
barta79df6e2008-03-14 17:07:51 +0000691}
692
bart99edb292009-02-15 15:59:20 +0000693Bool DRD_(bm_store_has_conflict_with)(struct bitmap* const bm,
694 const Addr a1, const Addr a2)
bart36556122008-03-13 19:24:30 +0000695{
bartbedfd232009-03-26 19:07:15 +0000696 return DRD_(bm_has_conflict_with)(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000697}
698
bart99edb292009-02-15 15:59:20 +0000699/**
700 * Return True if the two bitmaps *lhs and *rhs are identical, and false
701 * if not.
bart7cd7d7f2008-04-14 16:10:01 +0000702 */
bart99edb292009-02-15 15:59:20 +0000703Bool DRD_(bm_equal)(struct bitmap* const lhs, struct bitmap* const rhs)
bart7cd7d7f2008-04-14 16:10:01 +0000704{
bartbedfd232009-03-26 19:07:15 +0000705 struct bitmap2* bm2l;
706 struct bitmap2ref* bm2l_ref;
707 struct bitmap2* bm2r;
708 const struct bitmap2ref* bm2r_ref;
bart7cd7d7f2008-04-14 16:10:01 +0000709
bartbedfd232009-03-26 19:07:15 +0000710 /* It's not possible to have two independent iterators over the same OSet, */
711 /* so complain if lhs == rhs. */
712 tl_assert(lhs != rhs);
barta3f61092008-05-04 07:46:20 +0000713
bartbedfd232009-03-26 19:07:15 +0000714 VG_(OSetGen_ResetIter)(lhs->oset);
715 VG_(OSetGen_ResetIter)(rhs->oset);
bart7cd7d7f2008-04-14 16:10:01 +0000716
bartbedfd232009-03-26 19:07:15 +0000717 for ( ; (bm2l_ref = VG_(OSetGen_Next)(lhs->oset)) != 0; )
718 {
719 while (bm2l_ref
720 && (bm2l = bm2l_ref->bm2)
721 && bm2l
722 && ! DRD_(bm_has_any_access)(lhs,
723 bm2l->addr << ADDR0_BITS,
724 (bm2l->addr + 1) << ADDR0_BITS))
725 {
726 bm2l_ref = VG_(OSetGen_Next)(lhs->oset);
727 }
728 if (bm2l_ref == 0)
729 break;
730 tl_assert(bm2l);
barta3f61092008-05-04 07:46:20 +0000731#if 0
bartbedfd232009-03-26 19:07:15 +0000732 VG_(message)(Vg_DebugMsg, "bm_equal: at 0x%lx", bm2l->addr << ADDR0_BITS);
barta3f61092008-05-04 07:46:20 +0000733#endif
734
bartbedfd232009-03-26 19:07:15 +0000735 bm2r_ref = VG_(OSetGen_Next)(rhs->oset);
736 if (bm2r_ref == 0)
737 {
barta3f61092008-05-04 07:46:20 +0000738#if 0
bartbedfd232009-03-26 19:07:15 +0000739 VG_(message)(Vg_DebugMsg, "bm_equal: no match found");
barta3f61092008-05-04 07:46:20 +0000740#endif
bartbedfd232009-03-26 19:07:15 +0000741 return False;
742 }
743 bm2r = bm2r_ref->bm2;
744 tl_assert(bm2r);
745 tl_assert(DRD_(bm_has_any_access)(rhs,
746 bm2r->addr << ADDR0_BITS,
747 (bm2r->addr + 1) << ADDR0_BITS));
barta3f61092008-05-04 07:46:20 +0000748
bartbedfd232009-03-26 19:07:15 +0000749 if (bm2l != bm2r
750 && (bm2l->addr != bm2r->addr
751 || VG_(memcmp)(&bm2l->bm1, &bm2r->bm1, sizeof(bm2l->bm1)) != 0))
752 {
barta3f61092008-05-04 07:46:20 +0000753#if 0
bartbedfd232009-03-26 19:07:15 +0000754 VG_(message)(Vg_DebugMsg, "bm_equal: rhs 0x%lx -- returning false",
755 bm2r->addr << ADDR0_BITS);
756#endif
757 return False;
758 }
759 }
760 bm2r = VG_(OSetGen_Next)(rhs->oset);
761 if (bm2r)
762 {
763 tl_assert(DRD_(bm_has_any_access)(rhs,
764 bm2r->addr << ADDR0_BITS,
765 (bm2r->addr + 1) << ADDR0_BITS));
766#if 0
767 VG_(message)(Vg_DebugMsg,
768 "bm_equal: remaining rhs 0x%lx -- returning false",
barta3f61092008-05-04 07:46:20 +0000769 bm2r->addr << ADDR0_BITS);
770#endif
bart7cd7d7f2008-04-14 16:10:01 +0000771 return False;
bartbedfd232009-03-26 19:07:15 +0000772 }
773 return True;
bart7cd7d7f2008-04-14 16:10:01 +0000774}
775
bart99edb292009-02-15 15:59:20 +0000776void DRD_(bm_swap)(struct bitmap* const bm1, struct bitmap* const bm2)
sewardjaf44c822007-11-25 14:01:38 +0000777{
bartbedfd232009-03-26 19:07:15 +0000778 OSet* const tmp = bm1->oset;
779 bm1->oset = bm2->oset;
780 bm2->oset = tmp;
sewardjaf44c822007-11-25 14:01:38 +0000781}
782
bartf647d342008-03-24 19:12:12 +0000783/** Merge bitmaps *lhs and *rhs into *lhs. */
bart99edb292009-02-15 15:59:20 +0000784void DRD_(bm_merge2)(struct bitmap* const lhs,
785 struct bitmap* const rhs)
sewardjaf44c822007-11-25 14:01:38 +0000786{
bartbedfd232009-03-26 19:07:15 +0000787 struct bitmap2* bm2l;
788 struct bitmap2ref* bm2l_ref;
789 struct bitmap2* bm2r;
790 const struct bitmap2ref* bm2r_ref;
sewardjaf44c822007-11-25 14:01:38 +0000791
bartbedfd232009-03-26 19:07:15 +0000792 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000793
bartbedfd232009-03-26 19:07:15 +0000794 for ( ; (bm2r_ref = VG_(OSetGen_Next)(rhs->oset)) != 0; )
795 {
796 bm2r = bm2r_ref->bm2;
797 bm2l_ref = VG_(OSetGen_Lookup)(lhs->oset, &bm2r->addr);
798 if (bm2l_ref)
bartf647d342008-03-24 19:12:12 +0000799 {
bartbedfd232009-03-26 19:07:15 +0000800 bm2l = bm2l_ref->bm2;
801 if (bm2l != bm2r)
802 {
803 if (bm2l->refcnt > 1)
804 bm2l = bm2_make_exclusive(lhs, bm2l_ref);
805 bm2_merge(bm2l, bm2r);
806 }
bartf647d342008-03-24 19:12:12 +0000807 }
bartbedfd232009-03-26 19:07:15 +0000808 else
809 {
810 bm2_insert_addref(lhs, bm2r);
811 }
812 }
sewardjaf44c822007-11-25 14:01:38 +0000813}
814
815/**
816 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
817 * @param lhs First bitmap.
818 * @param rhs Bitmap to be compared with lhs.
819 * @return !=0 if there are data races, == 0 if there are none.
820 */
bart99edb292009-02-15 15:59:20 +0000821int DRD_(bm_has_races)(struct bitmap* const lhs, struct bitmap* const rhs)
sewardjaf44c822007-11-25 14:01:38 +0000822{
bartbedfd232009-03-26 19:07:15 +0000823 VG_(OSetGen_ResetIter)(lhs->oset);
824 VG_(OSetGen_ResetIter)(rhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000825
bartbedfd232009-03-26 19:07:15 +0000826 for (;;)
827 {
828 const struct bitmap2ref* bm2l_ref;
829 const struct bitmap2ref* bm2r_ref;
830 const struct bitmap2* bm2l;
831 const struct bitmap2* bm2r;
832 const struct bitmap1* bm1l;
833 const struct bitmap1* bm1r;
834 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000835
bartbedfd232009-03-26 19:07:15 +0000836 bm2l_ref = VG_(OSetGen_Next)(lhs->oset);
837 bm2l = bm2l_ref->bm2;
838 bm2r_ref = VG_(OSetGen_Next)(rhs->oset);
839 bm2r = bm2r_ref->bm2;
840 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
sewardjaf44c822007-11-25 14:01:38 +0000841 {
bartbedfd232009-03-26 19:07:15 +0000842 if (bm2l->addr < bm2r->addr)
843 bm2l = (bm2l_ref = VG_(OSetGen_Next)(lhs->oset))->bm2;
844 else
845 bm2r = (bm2r_ref = VG_(OSetGen_Next)(rhs->oset))->bm2;
sewardjaf44c822007-11-25 14:01:38 +0000846 }
bartbedfd232009-03-26 19:07:15 +0000847 if (bm2l == 0 || bm2r == 0)
848 break;
849
850 bm1l = &bm2l->bm1;
851 bm1r = &bm2r->bm1;
852
853 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
854 {
855 unsigned b;
856 for (b = 0; b < BITS_PER_UWORD; b++)
857 {
858 UWord const access_mask
859 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
860 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
861 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
862 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
863 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
864 if (HAS_RACE(access_mask) && ! DRD_(is_suppressed)(a, a + 1))
865 {
866 return 1;
867 }
868 }
869 }
870 }
871 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000872}
873
bart99edb292009-02-15 15:59:20 +0000874void DRD_(bm_print)(struct bitmap* const bm)
sewardjaf44c822007-11-25 14:01:38 +0000875{
bartbedfd232009-03-26 19:07:15 +0000876 struct bitmap2* bm2;
877 struct bitmap2ref* bm2ref;
sewardjaf44c822007-11-25 14:01:38 +0000878
bartbedfd232009-03-26 19:07:15 +0000879 VG_(OSetGen_ResetIter)(bm->oset);
sewardjaf44c822007-11-25 14:01:38 +0000880
bartbedfd232009-03-26 19:07:15 +0000881 for ( ; (bm2ref = VG_(OSetGen_Next)(bm->oset)) != 0; )
882 {
883 const struct bitmap1* bm1;
884 unsigned b;
bartf647d342008-03-24 19:12:12 +0000885
bartbedfd232009-03-26 19:07:15 +0000886 bm2 = bm2ref->bm2;
887 bm1 = &bm2->bm1;
888 for (b = 0; b < ADDR0_COUNT; b++)
sewardjaf44c822007-11-25 14:01:38 +0000889 {
bartbedfd232009-03-26 19:07:15 +0000890 const Addr a = (bm2->addr << ADDR0_BITS) | b;
891 const Bool r = bm0_is_set(bm1->bm0_r, b) != 0;
892 const Bool w = bm0_is_set(bm1->bm0_w, b) != 0;
893 if (r || w)
894 {
895 VG_(printf)("0x%08lx %c %c\n",
896 a,
897 w ? 'W' : ' ',
898 r ? 'R' : ' ');
899 }
sewardjaf44c822007-11-25 14:01:38 +0000900 }
bartbedfd232009-03-26 19:07:15 +0000901 }
sewardjaf44c822007-11-25 14:01:38 +0000902}
903
bart99edb292009-02-15 15:59:20 +0000904ULong DRD_(bm_get_bitmap_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +0000905{
bartbedfd232009-03-26 19:07:15 +0000906 return s_bitmap_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000907}
908
bart99edb292009-02-15 15:59:20 +0000909ULong DRD_(bm_get_bitmap2_node_creation_count)(void)
bart588d90f2008-04-06 13:05:58 +0000910{
bartbedfd232009-03-26 19:07:15 +0000911 return s_bitmap2_node_creation_count;
bart588d90f2008-04-06 13:05:58 +0000912}
913
bart99edb292009-02-15 15:59:20 +0000914ULong DRD_(bm_get_bitmap2_creation_count)(void)
sewardjaf44c822007-11-25 14:01:38 +0000915{
bartbedfd232009-03-26 19:07:15 +0000916 return s_bitmap2_creation_count;
sewardjaf44c822007-11-25 14:01:38 +0000917}
918
bartf647d342008-03-24 19:12:12 +0000919/** Allocate and initialize a second level bitmap. */
920static struct bitmap2* bm2_new(const UWord a1)
921{
bartbedfd232009-03-26 19:07:15 +0000922 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000923
bartbedfd232009-03-26 19:07:15 +0000924 bm2 = VG_(malloc)("drd.bitmap.bm2n.1", sizeof(*bm2));
925 bm2->addr = a1;
926 bm2->refcnt = 1;
bartf647d342008-03-24 19:12:12 +0000927
bartbedfd232009-03-26 19:07:15 +0000928 s_bitmap2_creation_count++;
bartf647d342008-03-24 19:12:12 +0000929
bartbedfd232009-03-26 19:07:15 +0000930 return bm2;
bartf647d342008-03-24 19:12:12 +0000931}
932
933/** Make a copy of a shared second level bitmap such that the copy can be
934 * modified.
935 *
936 * @param a1 client address shifted right by ADDR0_BITS.
937 * @param bm bitmap pointer.
938 */
bart99edb292009-02-15 15:59:20 +0000939static struct bitmap2* bm2_make_exclusive(struct bitmap* const bm,
940 struct bitmap2ref* const bm2ref)
bartf647d342008-03-24 19:12:12 +0000941{
bartbedfd232009-03-26 19:07:15 +0000942 UWord a1;
943 struct bitmap2* bm2;
944 struct bitmap2* bm2_copy;
bartf647d342008-03-24 19:12:12 +0000945
bartbedfd232009-03-26 19:07:15 +0000946 tl_assert(bm);
947 tl_assert(bm2ref);
948 bm2 = bm2ref->bm2;
949 tl_assert(bm2);
950 tl_assert(bm2->refcnt > 1);
951 bm2->refcnt--;
952 tl_assert(bm2->refcnt >= 1);
953 a1 = bm2->addr;
954 bm2_copy = bm2_new(a1);
955 tl_assert(bm2_copy);
956 tl_assert(bm2_copy->addr == a1);
957 tl_assert(bm2_copy->refcnt == 1);
958 VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1));
959 bm2ref->bm2 = bm2_copy;
bartf647d342008-03-24 19:12:12 +0000960
bartbedfd232009-03-26 19:07:15 +0000961 bm_update_cache(bm, a1, bm2_copy);
bartf647d342008-03-24 19:12:12 +0000962
bartbedfd232009-03-26 19:07:15 +0000963 return bm2_copy;
bartf647d342008-03-24 19:12:12 +0000964}
965
sewardjaf44c822007-11-25 14:01:38 +0000966static void bm2_merge(struct bitmap2* const bm2l,
967 const struct bitmap2* const bm2r)
968{
bartbedfd232009-03-26 19:07:15 +0000969 unsigned k;
sewardjaf44c822007-11-25 14:01:38 +0000970
bartbedfd232009-03-26 19:07:15 +0000971 tl_assert(bm2l);
972 tl_assert(bm2r);
973 tl_assert(bm2l->addr == bm2r->addr);
974 tl_assert(bm2l->refcnt == 1);
sewardjaf44c822007-11-25 14:01:38 +0000975
bartbedfd232009-03-26 19:07:15 +0000976 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
977 {
978 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
979 }
980 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
981 {
982 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
983 }
sewardjaf44c822007-11-25 14:01:38 +0000984}