blob: dc98f46bea48afe5d680ceda1b1913f6315ef8a4 [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
bart33e56c92008-03-24 06:41:30 +000026#ifndef __DRD_BITMAP_H
27#define __DRD_BITMAP_H
sewardjaf44c822007-11-25 14:01:38 +000028
29
bart82a0c5d2009-02-14 14:49:23 +000030#include "pub_tool_basics.h"
sewardjaf44c822007-11-25 14:01:38 +000031#include "pub_tool_oset.h"
bartd59bb0f2008-06-08 08:08:31 +000032#include "pub_tool_libcbase.h"
sewardjaf44c822007-11-25 14:01:38 +000033
34
35/*
36 Bitmap representation. A bitmap is a data structure in which two bits are
37 reserved per 32 bit address: one bit that indicates that the data at the
38 specified address has been read, and one bit that indicates that the data has
39 been written to.
40*/
41
42
43/* Macro definitions. */
44
bart8b4b2ee2008-06-11 13:17:56 +000045#define ADDR0_BITS 14
sewardjaf44c822007-11-25 14:01:38 +000046
barta79df6e2008-03-14 17:07:51 +000047#define ADDR0_COUNT ((UWord)1 << ADDR0_BITS)
sewardjaf44c822007-11-25 14:01:38 +000048
49#define ADDR0_MASK (ADDR0_COUNT - 1)
50
bart0268dfa2008-03-11 20:10:21 +000051#define SPLIT_ADDRESS(a) \
52 UWord a##0 = ((a) & ADDR0_MASK); \
sewardjaf44c822007-11-25 14:01:38 +000053 UWord a##1 = ((a) >> ADDR0_BITS);
54
55// Assumption: sizeof(Addr) == sizeof(UWord).
bart0268dfa2008-03-11 20:10:21 +000056#define MAKE_ADDRESS(a1, a0) \
sewardjaf44c822007-11-25 14:01:38 +000057 (Addr)(((UWord)(a1) << (ADDR0_BITS)) | ((UWord)(a0)))
58
59#define BITS_PER_UWORD (8UL*sizeof(UWord))
60#if defined(VGA_x86) || defined(VGA_ppc32)
61#define BITS_PER_BITS_PER_UWORD 5
62#elif defined(VGA_amd64) || defined(VGA_ppc64)
63#define BITS_PER_BITS_PER_UWORD 6
64#else
65#error Unknown platform.
66#endif
67
68#define BITMAP1_UWORD_COUNT (ADDR0_COUNT >> BITS_PER_BITS_PER_UWORD)
69
70/* Highest bits of an address that fit into the same UWord of bm0[]. */
71#define UWORD_MSB(a) ((a) & ~(BITS_PER_UWORD - 1))
72
73/* Lowest bits of an address that fit into the same UWord of bm0[]. */
74#define UWORD_LSB(a) ((a) & (BITS_PER_UWORD - 1))
75
76/* Highest address that fits in the same UWord as a. */
77#define UWORD_HIGHEST_ADDRESS(a) ((a) | (BITS_PER_UWORD - 1))
78
79
bart33e56c92008-03-24 06:41:30 +000080/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000081
82static ULong s_bitmap2_creation_count;
bart3c9989f2008-06-11 19:17:01 +000083static ULong s_bitmap2_node_creation_count;
sewardjaf44c822007-11-25 14:01:38 +000084
85
bart0008f5b2008-03-22 17:07:39 +000086
87/*********************************************************************/
88/* Functions for manipulating a struct bitmap1. */
89/*********************************************************************/
90
91
sewardjaf44c822007-11-25 14:01:38 +000092/* Lowest level, corresponding to the lowest ADDR0_BITS of an address. */
93struct bitmap1
94{
95 UWord bm0_r[BITMAP1_UWORD_COUNT];
96 UWord bm0_w[BITMAP1_UWORD_COUNT];
97};
98
99static __inline__ UWord bm0_mask(const Addr a)
100{
barta79df6e2008-03-14 17:07:51 +0000101 return ((UWord)1 << UWORD_LSB(a));
sewardjaf44c822007-11-25 14:01:38 +0000102}
103
104static __inline__ void bm0_set(UWord* bm0, const Addr a)
105{
bart3c9989f2008-06-11 19:17:01 +0000106#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
107 tl_assert(a < ADDR0_COUNT);
108#endif
barta79df6e2008-03-14 17:07:51 +0000109 bm0[a >> BITS_PER_BITS_PER_UWORD] |= (UWord)1 << UWORD_LSB(a);
110}
111
bartf8bc71d2008-03-15 11:42:34 +0000112/** Set all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */
113static __inline__ void bm0_set_range(UWord* bm0,
114 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000115{
bart8b4b2ee2008-06-11 13:17:56 +0000116#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
barta79df6e2008-03-14 17:07:51 +0000117 tl_assert(a1 < ADDR0_COUNT);
bartf8bc71d2008-03-15 11:42:34 +0000118 tl_assert(size > 0);
119 tl_assert(a1 + size <= ADDR0_COUNT);
120 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
barta79df6e2008-03-14 17:07:51 +0000121#endif
122 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
bartf8bc71d2008-03-15 11:42:34 +0000123 |= (((UWord)1 << size) - 1) << UWORD_LSB(a1);
sewardjaf44c822007-11-25 14:01:38 +0000124}
125
126static __inline__ void bm0_clear(UWord* bm0, const Addr a)
127{
bart3c9989f2008-06-11 19:17:01 +0000128#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
129 tl_assert(a < ADDR0_COUNT);
130#endif
barta79df6e2008-03-14 17:07:51 +0000131 bm0[a >> BITS_PER_BITS_PER_UWORD] &= ~((UWord)1 << UWORD_LSB(a));
sewardjaf44c822007-11-25 14:01:38 +0000132}
133
bart5955f332008-03-25 17:19:20 +0000134/** Clear all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */
135static __inline__ void bm0_clear_range(UWord* bm0,
136 const Addr a1, const SizeT size)
137{
bart8b4b2ee2008-06-11 13:17:56 +0000138#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart5955f332008-03-25 17:19:20 +0000139 tl_assert(a1 < ADDR0_COUNT);
140 tl_assert(size > 0);
141 tl_assert(a1 + size <= ADDR0_COUNT);
142 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
143#endif
144 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
145 &= ~(((UWord)1 << size) - 1) << UWORD_LSB(a1);
146}
147
sewardjaf44c822007-11-25 14:01:38 +0000148static __inline__ UWord bm0_is_set(const UWord* bm0, const Addr a)
149{
bart3c9989f2008-06-11 19:17:01 +0000150#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
151 tl_assert(a < ADDR0_COUNT);
152#endif
barta79df6e2008-03-14 17:07:51 +0000153 return (bm0[a >> BITS_PER_BITS_PER_UWORD] & ((UWord)1 << UWORD_LSB(a)));
sewardjaf44c822007-11-25 14:01:38 +0000154}
155
bartf8bc71d2008-03-15 11:42:34 +0000156/** Return true if any of the bits [ a1 .. a1+size [ are set in bm0. */
barta79df6e2008-03-14 17:07:51 +0000157static __inline__ UWord bm0_is_any_set(const UWord* bm0,
bartf8bc71d2008-03-15 11:42:34 +0000158 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000159{
bart8b4b2ee2008-06-11 13:17:56 +0000160#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
barta79df6e2008-03-14 17:07:51 +0000161 tl_assert(a1 < ADDR0_COUNT);
bartf8bc71d2008-03-15 11:42:34 +0000162 tl_assert(size > 0);
163 tl_assert(a1 + size <= ADDR0_COUNT);
164 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
barta79df6e2008-03-14 17:07:51 +0000165#endif
166 return (bm0[a1 >> BITS_PER_BITS_PER_UWORD]
bartf8bc71d2008-03-15 11:42:34 +0000167 & ((((UWord)1 << size) - 1) << UWORD_LSB(a1)));
barta79df6e2008-03-14 17:07:51 +0000168}
sewardjaf44c822007-11-25 14:01:38 +0000169
bartadbdf142008-03-19 17:00:12 +0000170
bart0008f5b2008-03-22 17:07:39 +0000171
172/*********************************************************************/
173/* Functions for manipulating a struct bitmap. */
bartadbdf142008-03-19 17:00:12 +0000174/*********************************************************************/
175
176
bart33e56c92008-03-24 06:41:30 +0000177/* Second level bitmap. */
sewardjaf44c822007-11-25 14:01:38 +0000178struct bitmap2
179{
bart33e56c92008-03-24 06:41:30 +0000180 Addr addr; ///< address >> ADDR0_BITS
bartf647d342008-03-24 19:12:12 +0000181 int refcnt;
sewardjaf44c822007-11-25 14:01:38 +0000182 struct bitmap1 bm1;
183};
184
bartf647d342008-03-24 19:12:12 +0000185/* One node of bitmap::oset. */
186struct bitmap2ref
187{
188 Addr addr; ///< address >> ADDR0_BITS
189 struct bitmap2* bm2;
190};
191
bart33e56c92008-03-24 06:41:30 +0000192struct bm_cache_elem
193{
194 Addr a1;
195 struct bitmap2* bm2;
196};
197
198#define N_CACHE_ELEM 4
199
sewardjaf44c822007-11-25 14:01:38 +0000200/* Complete bitmap. */
201struct bitmap
202{
bart33e56c92008-03-24 06:41:30 +0000203 struct bm_cache_elem cache[N_CACHE_ELEM];
204 OSet* oset;
sewardjaf44c822007-11-25 14:01:38 +0000205};
206
bart33e56c92008-03-24 06:41:30 +0000207
bartf647d342008-03-24 19:12:12 +0000208static struct bitmap2* bm2_new(const UWord a1);
209static struct bitmap2* bm2_make_exclusive(struct bitmap* const bm,
210 struct bitmap2ref* const bm2ref);
211
bart7e81a172008-06-09 19:50:51 +0000212/** Rotate elements cache[0..n-1] such that the element at position n-1 is
213 * moved to position 0. This allows to speed up future cache lookups.
214 */
215static __inline__
216void bm_cache_rotate(struct bm_cache_elem cache[], const int n)
217{
bart45af5ea2008-06-12 06:04:59 +0000218#if 0
bart7e81a172008-06-09 19:50:51 +0000219 struct bm_cache_elem t;
220
bartea2fa4c2008-06-10 06:32:49 +0000221 tl_assert(2 <= n && n <= 8);
bartea2fa4c2008-06-10 06:32:49 +0000222
bart7e81a172008-06-09 19:50:51 +0000223 t = cache[0];
224 if (n > 1)
225 cache[0] = cache[1];
226 if (n > 2)
227 cache[1] = cache[2];
228 if (n > 3)
229 cache[2] = cache[3];
230 if (n > 4)
231 cache[3] = cache[4];
232 if (n > 5)
233 cache[4] = cache[5];
234 if (n > 6)
235 cache[5] = cache[6];
236 if (n > 7)
237 cache[6] = cache[7];
238 cache[n - 1] = t;
bartea2fa4c2008-06-10 06:32:49 +0000239#endif
bart7e81a172008-06-09 19:50:51 +0000240}
bartf647d342008-03-24 19:12:12 +0000241
bartf647d342008-03-24 19:12:12 +0000242static __inline__
bart7e81a172008-06-09 19:50:51 +0000243Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1,
bartf29205e2008-03-25 18:51:06 +0000244 struct bitmap2** bm2)
bart33e56c92008-03-24 06:41:30 +0000245{
bart8b4b2ee2008-06-11 13:17:56 +0000246#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart33e56c92008-03-24 06:41:30 +0000247 tl_assert(bm);
bartf29205e2008-03-25 18:51:06 +0000248 tl_assert(bm2);
bart7e81a172008-06-09 19:50:51 +0000249#endif
bart33e56c92008-03-24 06:41:30 +0000250
251#if N_CACHE_ELEM > 8
252#error Please update the code below.
253#endif
254#if N_CACHE_ELEM >= 1
255 if (a1 == bm->cache[0].a1)
bartf29205e2008-03-25 18:51:06 +0000256 {
257 *bm2 = bm->cache[0].bm2;
258 return True;
259 }
bart33e56c92008-03-24 06:41:30 +0000260#endif
261#if N_CACHE_ELEM >= 2
262 if (a1 == bm->cache[1].a1)
bartf29205e2008-03-25 18:51:06 +0000263 {
264 *bm2 = bm->cache[1].bm2;
265 return True;
266 }
bart33e56c92008-03-24 06:41:30 +0000267#endif
268#if N_CACHE_ELEM >= 3
269 if (a1 == bm->cache[2].a1)
bartf29205e2008-03-25 18:51:06 +0000270 {
271 *bm2 = bm->cache[2].bm2;
bart7e81a172008-06-09 19:50:51 +0000272 bm_cache_rotate(bm->cache, 3);
bartf29205e2008-03-25 18:51:06 +0000273 return True;
274 }
bart33e56c92008-03-24 06:41:30 +0000275#endif
276#if N_CACHE_ELEM >= 4
277 if (a1 == bm->cache[3].a1)
bartf29205e2008-03-25 18:51:06 +0000278 {
279 *bm2 = bm->cache[3].bm2;
bart7e81a172008-06-09 19:50:51 +0000280 bm_cache_rotate(bm->cache, 4);
bartf29205e2008-03-25 18:51:06 +0000281 return True;
282 }
bart33e56c92008-03-24 06:41:30 +0000283#endif
284#if N_CACHE_ELEM >= 5
285 if (a1 == bm->cache[4].a1)
bartf29205e2008-03-25 18:51:06 +0000286 {
287 *bm2 = bm->cache[4].bm2;
bart7e81a172008-06-09 19:50:51 +0000288 bm_cache_rotate(bm->cache, 5);
bartf29205e2008-03-25 18:51:06 +0000289 return True;
290 }
bart33e56c92008-03-24 06:41:30 +0000291#endif
292#if N_CACHE_ELEM >= 6
293 if (a1 == bm->cache[5].a1)
bartf29205e2008-03-25 18:51:06 +0000294 {
295 *bm2 = bm->cache[5].bm2;
bart7e81a172008-06-09 19:50:51 +0000296 bm_cache_rotate(bm->cache, 6);
bartf29205e2008-03-25 18:51:06 +0000297 return True;
298 }
bart33e56c92008-03-24 06:41:30 +0000299#endif
300#if N_CACHE_ELEM >= 7
301 if (a1 == bm->cache[6].a1)
bartf29205e2008-03-25 18:51:06 +0000302 {
303 *bm2 = bm->cache[6].bm2;
bart7e81a172008-06-09 19:50:51 +0000304 bm_cache_rotate(bm->cache, 7);
bartf29205e2008-03-25 18:51:06 +0000305 return True;
306 }
bart33e56c92008-03-24 06:41:30 +0000307#endif
308#if N_CACHE_ELEM >= 8
309 if (a1 == bm->cache[7].a1)
bartf29205e2008-03-25 18:51:06 +0000310 {
311 *bm2 = bm->cache[7].bm2;
bart7e81a172008-06-09 19:50:51 +0000312 bm_cache_rotate(bm->cache, 8);
bartf29205e2008-03-25 18:51:06 +0000313 return True;
314 }
bart33e56c92008-03-24 06:41:30 +0000315#endif
bartf29205e2008-03-25 18:51:06 +0000316 *bm2 = 0;
317 return False;
bart33e56c92008-03-24 06:41:30 +0000318}
319
320static __inline__
321void bm_update_cache(struct bitmap* const bm,
322 const UWord a1,
323 struct bitmap2* const bm2)
324{
bart3c9989f2008-06-11 19:17:01 +0000325#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bart33e56c92008-03-24 06:41:30 +0000326 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000327#endif
bart33e56c92008-03-24 06:41:30 +0000328
329#if N_CACHE_ELEM > 8
330#error Please update the code below.
331#endif
332#if N_CACHE_ELEM >= 8
333 bm->cache[7] = bm->cache[6];
334#endif
335#if N_CACHE_ELEM >= 7
336 bm->cache[6] = bm->cache[5];
337#endif
338#if N_CACHE_ELEM >= 6
339 bm->cache[5] = bm->cache[4];
340#endif
341#if N_CACHE_ELEM >= 5
342 bm->cache[4] = bm->cache[3];
343#endif
344#if N_CACHE_ELEM >= 4
345 bm->cache[3] = bm->cache[2];
346#endif
347#if N_CACHE_ELEM >= 3
348 bm->cache[2] = bm->cache[1];
349#endif
350#if N_CACHE_ELEM >= 2
351 bm->cache[1] = bm->cache[0];
352#endif
353 bm->cache[0].a1 = a1;
354 bm->cache[0].bm2 = bm2;
355}
356
bartf647d342008-03-24 19:12:12 +0000357/** Look up the address a1 in bitmap bm and return a pointer to a potentially
358 * shared second level bitmap. The bitmap where the returned pointer points
359 * at may not be modified by the caller.
360 *
bart0008f5b2008-03-22 17:07:39 +0000361 * @param a1 client address shifted right by ADDR0_BITS.
362 * @param bm bitmap pointer.
363 */
sewardjaf44c822007-11-25 14:01:38 +0000364static __inline__
bart7e81a172008-06-09 19:50:51 +0000365const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000366{
bartf29205e2008-03-25 18:51:06 +0000367 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000368 struct bitmap2ref* bm2ref;
369
bart3c9989f2008-06-11 19:17:01 +0000370#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartf647d342008-03-24 19:12:12 +0000371 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000372#endif
bartf29205e2008-03-25 18:51:06 +0000373 if (! bm_cache_lookup(bm, a1, &bm2))
barta79df6e2008-03-14 17:07:51 +0000374 {
bartf29205e2008-03-25 18:51:06 +0000375 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
376 if (bm2ref)
377 {
378 bm2 = bm2ref->bm2;
379 }
bartf647d342008-03-24 19:12:12 +0000380 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000381 }
bartf29205e2008-03-25 18:51:06 +0000382 return bm2;
bartf647d342008-03-24 19:12:12 +0000383}
384
385/** Look up the address a1 in bitmap bm and return a pointer to a second
386 * level bitmap that is not shared and hence may be modified.
387 *
388 * @param a1 client address shifted right by ADDR0_BITS.
389 * @param bm bitmap pointer.
390 */
391static __inline__
392struct bitmap2*
bart7e81a172008-06-09 19:50:51 +0000393bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1)
bartf647d342008-03-24 19:12:12 +0000394{
395 struct bitmap2ref* bm2ref;
396 struct bitmap2* bm2;
397
398 bm2ref = 0;
bartf29205e2008-03-25 18:51:06 +0000399 if (bm_cache_lookup(bm, a1, &bm2))
bartf647d342008-03-24 19:12:12 +0000400 {
bartf29205e2008-03-25 18:51:06 +0000401 if (bm2 == 0)
402 return 0;
bartf647d342008-03-24 19:12:12 +0000403 if (bm2->refcnt > 1)
bart33e56c92008-03-24 06:41:30 +0000404 {
bartf647d342008-03-24 19:12:12 +0000405 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bart33e56c92008-03-24 06:41:30 +0000406 }
barta79df6e2008-03-14 17:07:51 +0000407 }
bartf647d342008-03-24 19:12:12 +0000408 else
409 {
410 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bartf29205e2008-03-25 18:51:06 +0000411 if (bm2ref == 0)
bartf647d342008-03-24 19:12:12 +0000412 return 0;
bartf29205e2008-03-25 18:51:06 +0000413 bm2 = bm2ref->bm2;
bartf647d342008-03-24 19:12:12 +0000414 }
415
bart3c9989f2008-06-11 19:17:01 +0000416#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartf647d342008-03-24 19:12:12 +0000417 tl_assert(bm2);
bart3c9989f2008-06-11 19:17:01 +0000418#endif
bartf647d342008-03-24 19:12:12 +0000419
420 if (bm2->refcnt > 1)
421 {
bart3c9989f2008-06-11 19:17:01 +0000422#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartf647d342008-03-24 19:12:12 +0000423 tl_assert(bm2ref);
bart3c9989f2008-06-11 19:17:01 +0000424#endif
bartf647d342008-03-24 19:12:12 +0000425 bm2 = bm2_make_exclusive(*(struct bitmap**)&bm, bm2ref);
426 }
427
bart33e56c92008-03-24 06:41:30 +0000428 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000429}
430
bartf647d342008-03-24 19:12:12 +0000431/** Look up the address a1 in bitmap bm. The returned second level bitmap has
432 * reference count one and hence may be modified.
433 *
434 * @param a1 client address shifted right by ADDR0_BITS.
435 * @param bm bitmap pointer.
436 */
sewardjaf44c822007-11-25 14:01:38 +0000437static __inline__
bart7e81a172008-06-09 19:50:51 +0000438struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000439{
bartf647d342008-03-24 19:12:12 +0000440 struct bitmap2ref* bm2ref;
bart33e56c92008-03-24 06:41:30 +0000441 struct bitmap2* bm2;
442
bart3c9989f2008-06-11 19:17:01 +0000443 s_bitmap2_node_creation_count++;
bartf647d342008-03-24 19:12:12 +0000444 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
445 bm2ref->addr = a1;
446 bm2 = bm2_new(a1);
447 bm2ref->bm2 = bm2;
bart0008f5b2008-03-22 17:07:39 +0000448 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
bartf647d342008-03-24 19:12:12 +0000449 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000450
bart33e56c92008-03-24 06:41:30 +0000451 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000452
453 return bm2;
454}
455
456/** Insert a new node in bitmap bm that points to the second level bitmap
457 * *bm2. This means that *bm2 becomes shared over two or more bitmaps.
458 */
459static __inline__
bart7e81a172008-06-09 19:50:51 +0000460struct bitmap2* bm2_insert_addref(struct bitmap* const bm,
bartf647d342008-03-24 19:12:12 +0000461 struct bitmap2* const bm2)
462{
463 struct bitmap2ref* bm2ref;
464
bart3c9989f2008-06-11 19:17:01 +0000465#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartf647d342008-03-24 19:12:12 +0000466 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000467 tl_assert(VG_(OSetGen_Lookup)(bm->oset, &bm2->addr) == 0);
468#endif
bart588d90f2008-04-06 13:05:58 +0000469
bart3c9989f2008-06-11 19:17:01 +0000470 s_bitmap2_node_creation_count++;
bartf647d342008-03-24 19:12:12 +0000471 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
472 bm2ref->addr = bm2->addr;
473 bm2ref->bm2 = bm2;
474 bm2->refcnt++;
475 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000476
bartf647d342008-03-24 19:12:12 +0000477 bm_update_cache(*(struct bitmap**)&bm, bm2->addr, bm2);
478
bart0008f5b2008-03-22 17:07:39 +0000479 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000480}
481
bart0008f5b2008-03-22 17:07:39 +0000482/** Look up the address a1 in bitmap bm, and insert it if not found.
bartf647d342008-03-24 19:12:12 +0000483 * The returned second level bitmap may not be modified.
bart0008f5b2008-03-22 17:07:39 +0000484 *
485 * @param a1 client address shifted right by ADDR0_BITS.
486 * @param bm bitmap pointer.
487 */
sewardjaf44c822007-11-25 14:01:38 +0000488static __inline__
bart7e81a172008-06-09 19:50:51 +0000489struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000490{
bartf647d342008-03-24 19:12:12 +0000491 struct bitmap2ref* bm2ref;
bart0008f5b2008-03-22 17:07:39 +0000492 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000493
bart3c9989f2008-06-11 19:17:01 +0000494#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartf647d342008-03-24 19:12:12 +0000495 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000496#endif
bart567614d2008-03-25 19:16:20 +0000497 if (bm_cache_lookup(bm, a1, &bm2))
498 {
499 if (bm2 == 0)
500 {
501 bm2 = bm2_insert(bm, a1);
502 }
503 }
504 else
barta79df6e2008-03-14 17:07:51 +0000505 {
bartf647d342008-03-24 19:12:12 +0000506 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
507 if (bm2ref)
508 {
509 bm2 = bm2ref->bm2;
510 }
511 else
bart33e56c92008-03-24 06:41:30 +0000512 {
513 bm2 = bm2_insert(bm, a1);
514 }
515 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
barta79df6e2008-03-14 17:07:51 +0000516 }
bart0008f5b2008-03-22 17:07:39 +0000517 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000518}
519
bartf647d342008-03-24 19:12:12 +0000520/** Look up the address a1 in bitmap bm, and insert it if not found.
521 * The returned second level bitmap may be modified.
522 *
523 * @param a1 client address shifted right by ADDR0_BITS.
524 * @param bm bitmap pointer.
525 */
526static __inline__
527struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
528 const UWord a1)
529{
530 struct bitmap2* bm2;
531
bart3c9989f2008-06-11 19:17:01 +0000532#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartf647d342008-03-24 19:12:12 +0000533 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000534#endif
bartf647d342008-03-24 19:12:12 +0000535 bm2 = (struct bitmap2*)bm2_lookup_or_insert(bm, a1);
bart3c9989f2008-06-11 19:17:01 +0000536#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartf647d342008-03-24 19:12:12 +0000537 tl_assert(bm2);
bart3c9989f2008-06-11 19:17:01 +0000538#endif
bartf647d342008-03-24 19:12:12 +0000539 if (bm2->refcnt > 1)
540 {
541 struct bitmap2ref* bm2ref;
542 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
543 bm2 = bm2_make_exclusive(bm, bm2ref);
544 }
545 return bm2;
546}
547
bartd59bb0f2008-06-08 08:08:31 +0000548static __inline__
549void bm_access_aligned_load(struct bitmap* const bm,
550 const Addr a1, const SizeT size)
551{
552 struct bitmap2* bm2;
553
554 bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS);
555 bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size);
556}
557
558static __inline__
559void bm_access_aligned_store(struct bitmap* const bm,
560 const Addr a1, const SizeT size)
561{
562 struct bitmap2* bm2;
563
564 bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS);
565 bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size);
566}
567
568static __inline__
bart7e81a172008-06-09 19:50:51 +0000569Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm,
bartd59bb0f2008-06-08 08:08:31 +0000570 const Addr a1, const SizeT size)
571{
572 const struct bitmap2* bm2;
573
574 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
575
576 return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size));
577}
578
579static __inline__
bart7e81a172008-06-09 19:50:51 +0000580Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm,
bartd59bb0f2008-06-08 08:08:31 +0000581 const Addr a1, const SizeT size)
582{
583 const struct bitmap2* bm2;
584
585 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
586
587 if (bm2)
588 {
589 if (bm0_is_any_set(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size)
590 | bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size))
591 {
592 return True;
593 }
594 }
595 return False;
596}
sewardjaf44c822007-11-25 14:01:38 +0000597
bart33e56c92008-03-24 06:41:30 +0000598#endif /* __DRD_BITMAP_H */