blob: 84f1eb514b5a79c2d59b406e436ea2093413cef9 [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
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
bartbedfd232009-03-26 19:07:15 +000051#define SPLIT_ADDRESS(a) \
52 UWord a##0 = ((a) & ADDR0_MASK); \
53 UWord a##1 = ((a) >> ADDR0_BITS);
sewardjaf44c822007-11-25 14:01:38 +000054
55// Assumption: sizeof(Addr) == sizeof(UWord).
bartbedfd232009-03-26 19:07:15 +000056#define MAKE_ADDRESS(a1, a0) \
57 (Addr)(((UWord)(a1) << (ADDR0_BITS)) | ((UWord)(a0)))
sewardjaf44c822007-11-25 14:01:38 +000058
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{
bartbedfd232009-03-26 19:07:15 +000095 UWord bm0_r[BITMAP1_UWORD_COUNT];
96 UWord bm0_w[BITMAP1_UWORD_COUNT];
sewardjaf44c822007-11-25 14:01:38 +000097};
98
99static __inline__ UWord bm0_mask(const Addr a)
100{
bartbedfd232009-03-26 19:07:15 +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
bartbedfd232009-03-26 19:07:15 +0000107 tl_assert(a < ADDR0_COUNT);
bart3c9989f2008-06-11 19:17:01 +0000108#endif
bartbedfd232009-03-26 19:07:15 +0000109 bm0[a >> BITS_PER_BITS_PER_UWORD] |= (UWord)1 << UWORD_LSB(a);
barta79df6e2008-03-14 17:07:51 +0000110}
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
bartbedfd232009-03-26 19:07:15 +0000117 tl_assert(a1 < ADDR0_COUNT);
118 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
bartbedfd232009-03-26 19:07:15 +0000122 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
123 |= (((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
bartbedfd232009-03-26 19:07:15 +0000129 tl_assert(a < ADDR0_COUNT);
bart3c9989f2008-06-11 19:17:01 +0000130#endif
bartbedfd232009-03-26 19:07:15 +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
bartbedfd232009-03-26 19:07:15 +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));
bart5955f332008-03-25 17:19:20 +0000143#endif
bartbedfd232009-03-26 19:07:15 +0000144 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
145 &= ~(((UWord)1 << size) - 1) << UWORD_LSB(a1);
bart5955f332008-03-25 17:19:20 +0000146}
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
bartbedfd232009-03-26 19:07:15 +0000151 tl_assert(a < ADDR0_COUNT);
bart3c9989f2008-06-11 19:17:01 +0000152#endif
bartbedfd232009-03-26 19:07:15 +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
bartbedfd232009-03-26 19:07:15 +0000161 tl_assert(a1 < ADDR0_COUNT);
162 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
bartbedfd232009-03-26 19:07:15 +0000166 return (bm0[a1 >> BITS_PER_BITS_PER_UWORD]
167 & ((((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{
bartbedfd232009-03-26 19:07:15 +0000180 Addr addr; ///< address >> ADDR0_BITS
181 int refcnt;
182 struct bitmap1 bm1;
sewardjaf44c822007-11-25 14:01:38 +0000183};
184
bartf647d342008-03-24 19:12:12 +0000185/* One node of bitmap::oset. */
186struct bitmap2ref
187{
bartbedfd232009-03-26 19:07:15 +0000188 Addr addr; ///< address >> ADDR0_BITS
189 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000190};
191
bart33e56c92008-03-24 06:41:30 +0000192struct bm_cache_elem
193{
bartbedfd232009-03-26 19:07:15 +0000194 Addr a1;
195 struct bitmap2* bm2;
bart33e56c92008-03-24 06:41:30 +0000196};
197
198#define N_CACHE_ELEM 4
199
sewardjaf44c822007-11-25 14:01:38 +0000200/* Complete bitmap. */
201struct bitmap
202{
bartbedfd232009-03-26 19:07:15 +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
bartbedfd232009-03-26 19:07:15 +0000219 struct bm_cache_elem t;
bart7e81a172008-06-09 19:50:51 +0000220
bartbedfd232009-03-26 19:07:15 +0000221 tl_assert(2 <= n && n <= 8);
bartea2fa4c2008-06-10 06:32:49 +0000222
bartbedfd232009-03-26 19:07:15 +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
bartbedfd232009-03-26 19:07:15 +0000247 tl_assert(bm);
248 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
bartbedfd232009-03-26 19:07:15 +0000255 if (a1 == bm->cache[0].a1)
256 {
257 *bm2 = bm->cache[0].bm2;
258 return True;
259 }
bart33e56c92008-03-24 06:41:30 +0000260#endif
261#if N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000262 if (a1 == bm->cache[1].a1)
263 {
264 *bm2 = bm->cache[1].bm2;
265 return True;
266 }
bart33e56c92008-03-24 06:41:30 +0000267#endif
268#if N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000269 if (a1 == bm->cache[2].a1)
270 {
271 *bm2 = bm->cache[2].bm2;
272 bm_cache_rotate(bm->cache, 3);
273 return True;
274 }
bart33e56c92008-03-24 06:41:30 +0000275#endif
276#if N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000277 if (a1 == bm->cache[3].a1)
278 {
279 *bm2 = bm->cache[3].bm2;
280 bm_cache_rotate(bm->cache, 4);
281 return True;
282 }
bart33e56c92008-03-24 06:41:30 +0000283#endif
284#if N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000285 if (a1 == bm->cache[4].a1)
286 {
287 *bm2 = bm->cache[4].bm2;
288 bm_cache_rotate(bm->cache, 5);
289 return True;
290 }
bart33e56c92008-03-24 06:41:30 +0000291#endif
292#if N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000293 if (a1 == bm->cache[5].a1)
294 {
295 *bm2 = bm->cache[5].bm2;
296 bm_cache_rotate(bm->cache, 6);
297 return True;
298 }
bart33e56c92008-03-24 06:41:30 +0000299#endif
300#if N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000301 if (a1 == bm->cache[6].a1)
302 {
303 *bm2 = bm->cache[6].bm2;
304 bm_cache_rotate(bm->cache, 7);
305 return True;
306 }
bart33e56c92008-03-24 06:41:30 +0000307#endif
308#if N_CACHE_ELEM >= 8
bartbedfd232009-03-26 19:07:15 +0000309 if (a1 == bm->cache[7].a1)
310 {
311 *bm2 = bm->cache[7].bm2;
312 bm_cache_rotate(bm->cache, 8);
313 return True;
314 }
bart33e56c92008-03-24 06:41:30 +0000315#endif
bartbedfd232009-03-26 19:07:15 +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
bartbedfd232009-03-26 19:07:15 +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
bartbedfd232009-03-26 19:07:15 +0000333 bm->cache[7] = bm->cache[6];
bart33e56c92008-03-24 06:41:30 +0000334#endif
335#if N_CACHE_ELEM >= 7
bartbedfd232009-03-26 19:07:15 +0000336 bm->cache[6] = bm->cache[5];
bart33e56c92008-03-24 06:41:30 +0000337#endif
338#if N_CACHE_ELEM >= 6
bartbedfd232009-03-26 19:07:15 +0000339 bm->cache[5] = bm->cache[4];
bart33e56c92008-03-24 06:41:30 +0000340#endif
341#if N_CACHE_ELEM >= 5
bartbedfd232009-03-26 19:07:15 +0000342 bm->cache[4] = bm->cache[3];
bart33e56c92008-03-24 06:41:30 +0000343#endif
344#if N_CACHE_ELEM >= 4
bartbedfd232009-03-26 19:07:15 +0000345 bm->cache[3] = bm->cache[2];
bart33e56c92008-03-24 06:41:30 +0000346#endif
347#if N_CACHE_ELEM >= 3
bartbedfd232009-03-26 19:07:15 +0000348 bm->cache[2] = bm->cache[1];
bart33e56c92008-03-24 06:41:30 +0000349#endif
350#if N_CACHE_ELEM >= 2
bartbedfd232009-03-26 19:07:15 +0000351 bm->cache[1] = bm->cache[0];
bart33e56c92008-03-24 06:41:30 +0000352#endif
bartbedfd232009-03-26 19:07:15 +0000353 bm->cache[0].a1 = a1;
354 bm->cache[0].bm2 = bm2;
bart33e56c92008-03-24 06:41:30 +0000355}
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{
bartbedfd232009-03-26 19:07:15 +0000367 struct bitmap2* bm2;
368 struct bitmap2ref* bm2ref;
bartf647d342008-03-24 19:12:12 +0000369
bart3c9989f2008-06-11 19:17:01 +0000370#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000371 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000372#endif
bartbedfd232009-03-26 19:07:15 +0000373 if (! bm_cache_lookup(bm, a1, &bm2))
374 {
375 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
376 if (bm2ref)
377 {
378 bm2 = bm2ref->bm2;
379 }
380 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
381 }
382 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{
bartbedfd232009-03-26 19:07:15 +0000395 struct bitmap2ref* bm2ref;
396 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000397
bartbedfd232009-03-26 19:07:15 +0000398 bm2ref = 0;
399 if (bm_cache_lookup(bm, a1, &bm2))
400 {
401 if (bm2 == 0)
402 return 0;
403 if (bm2->refcnt > 1)
404 {
405 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
406 }
407 }
408 else
409 {
bartf647d342008-03-24 19:12:12 +0000410 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bartbedfd232009-03-26 19:07:15 +0000411 if (bm2ref == 0)
412 return 0;
413 bm2 = bm2ref->bm2;
414 }
bartf647d342008-03-24 19:12:12 +0000415
bart3c9989f2008-06-11 19:17:01 +0000416#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000417 tl_assert(bm2);
bart3c9989f2008-06-11 19:17:01 +0000418#endif
bartf647d342008-03-24 19:12:12 +0000419
bartbedfd232009-03-26 19:07:15 +0000420 if (bm2->refcnt > 1)
421 {
bart3c9989f2008-06-11 19:17:01 +0000422#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000423 tl_assert(bm2ref);
bart3c9989f2008-06-11 19:17:01 +0000424#endif
bartbedfd232009-03-26 19:07:15 +0000425 bm2 = bm2_make_exclusive(*(struct bitmap**)&bm, bm2ref);
426 }
bartf647d342008-03-24 19:12:12 +0000427
bartbedfd232009-03-26 19:07:15 +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{
bartbedfd232009-03-26 19:07:15 +0000440 struct bitmap2ref* bm2ref;
441 struct bitmap2* bm2;
bart33e56c92008-03-24 06:41:30 +0000442
bartbedfd232009-03-26 19:07:15 +0000443 s_bitmap2_node_creation_count++;
444 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
445 bm2ref->addr = a1;
446 bm2 = bm2_new(a1);
447 bm2ref->bm2 = bm2;
448 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
449 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000450
bartbedfd232009-03-26 19:07:15 +0000451 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000452
bartbedfd232009-03-26 19:07:15 +0000453 return bm2;
bartf647d342008-03-24 19:12:12 +0000454}
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{
bartbedfd232009-03-26 19:07:15 +0000463 struct bitmap2ref* bm2ref;
bartf647d342008-03-24 19:12:12 +0000464
bart3c9989f2008-06-11 19:17:01 +0000465#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000466 tl_assert(bm);
467 tl_assert(VG_(OSetGen_Lookup)(bm->oset, &bm2->addr) == 0);
bart3c9989f2008-06-11 19:17:01 +0000468#endif
bart588d90f2008-04-06 13:05:58 +0000469
bartbedfd232009-03-26 19:07:15 +0000470 s_bitmap2_node_creation_count++;
471 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
bartbedfd232009-03-26 19:07:15 +0000477 bm_update_cache(*(struct bitmap**)&bm, bm2->addr, bm2);
bartf647d342008-03-24 19:12:12 +0000478
bartbedfd232009-03-26 19:07:15 +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{
bartbedfd232009-03-26 19:07:15 +0000491 struct bitmap2ref* bm2ref;
492 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000493
bart3c9989f2008-06-11 19:17:01 +0000494#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000495 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000496#endif
bartbedfd232009-03-26 19:07:15 +0000497 if (bm_cache_lookup(bm, a1, &bm2))
498 {
499 if (bm2 == 0)
500 {
501 bm2 = bm2_insert(bm, a1);
502 }
503 }
504 else
505 {
506 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
507 if (bm2ref)
508 {
509 bm2 = bm2ref->bm2;
510 }
511 else
512 {
513 bm2 = bm2_insert(bm, a1);
514 }
515 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
516 }
517 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{
bartbedfd232009-03-26 19:07:15 +0000530 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000531
bart3c9989f2008-06-11 19:17:01 +0000532#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000533 tl_assert(bm);
bart3c9989f2008-06-11 19:17:01 +0000534#endif
bartbedfd232009-03-26 19:07:15 +0000535 bm2 = (struct bitmap2*)bm2_lookup_or_insert(bm, a1);
bart3c9989f2008-06-11 19:17:01 +0000536#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000537 tl_assert(bm2);
bart3c9989f2008-06-11 19:17:01 +0000538#endif
bartbedfd232009-03-26 19:07:15 +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;
bartf647d342008-03-24 19:12:12 +0000546}
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{
bartbedfd232009-03-26 19:07:15 +0000552 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000553
bartbedfd232009-03-26 19:07:15 +0000554 bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS);
555 bm0_set_range(bm2->bm1.bm0_r, a1 & ADDR0_MASK, size);
bartd59bb0f2008-06-08 08:08:31 +0000556}
557
558static __inline__
559void bm_access_aligned_store(struct bitmap* const bm,
560 const Addr a1, const SizeT size)
561{
bartbedfd232009-03-26 19:07:15 +0000562 struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000563
bartbedfd232009-03-26 19:07:15 +0000564 bm2 = bm2_lookup_or_insert_exclusive(bm, a1 >> ADDR0_BITS);
565 bm0_set_range(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size);
bartd59bb0f2008-06-08 08:08:31 +0000566}
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{
bartbedfd232009-03-26 19:07:15 +0000572 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000573
bartbedfd232009-03-26 19:07:15 +0000574 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
bartd59bb0f2008-06-08 08:08:31 +0000575
bartbedfd232009-03-26 19:07:15 +0000576 return (bm2 && bm0_is_any_set(bm2->bm1.bm0_w, a1 & ADDR0_MASK, size));
bartd59bb0f2008-06-08 08:08:31 +0000577}
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{
bartbedfd232009-03-26 19:07:15 +0000583 const struct bitmap2* bm2;
bartd59bb0f2008-06-08 08:08:31 +0000584
bartbedfd232009-03-26 19:07:15 +0000585 bm2 = bm2_lookup(bm, a1 >> ADDR0_BITS);
bartd59bb0f2008-06-08 08:08:31 +0000586
bartbedfd232009-03-26 19:07:15 +0000587 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;
bartd59bb0f2008-06-08 08:08:31 +0000596}
sewardjaf44c822007-11-25 14:01:38 +0000597
bart33e56c92008-03-24 06:41:30 +0000598#endif /* __DRD_BITMAP_H */