blob: 23ef6372c3bdefa57946000c20bae7c82530775f [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
30#include "pub_tool_oset.h"
31
32
33/*
34 Bitmap representation. A bitmap is a data structure in which two bits are
35 reserved per 32 bit address: one bit that indicates that the data at the
36 specified address has been read, and one bit that indicates that the data has
37 been written to.
38*/
39
40
41/* Macro definitions. */
42
bartf587d042008-03-15 14:30:20 +000043#define ADDR0_BITS 16
sewardjaf44c822007-11-25 14:01:38 +000044
barta79df6e2008-03-14 17:07:51 +000045#define ADDR0_COUNT ((UWord)1 << ADDR0_BITS)
sewardjaf44c822007-11-25 14:01:38 +000046
47#define ADDR0_MASK (ADDR0_COUNT - 1)
48
bart0268dfa2008-03-11 20:10:21 +000049#define SPLIT_ADDRESS(a) \
50 UWord a##0 = ((a) & ADDR0_MASK); \
sewardjaf44c822007-11-25 14:01:38 +000051 UWord a##1 = ((a) >> ADDR0_BITS);
52
53// Assumption: sizeof(Addr) == sizeof(UWord).
bart0268dfa2008-03-11 20:10:21 +000054#define MAKE_ADDRESS(a1, a0) \
sewardjaf44c822007-11-25 14:01:38 +000055 (Addr)(((UWord)(a1) << (ADDR0_BITS)) | ((UWord)(a0)))
56
57#define BITS_PER_UWORD (8UL*sizeof(UWord))
58#if defined(VGA_x86) || defined(VGA_ppc32)
59#define BITS_PER_BITS_PER_UWORD 5
60#elif defined(VGA_amd64) || defined(VGA_ppc64)
61#define BITS_PER_BITS_PER_UWORD 6
62#else
63#error Unknown platform.
64#endif
65
66#define BITMAP1_UWORD_COUNT (ADDR0_COUNT >> BITS_PER_BITS_PER_UWORD)
67
68/* Highest bits of an address that fit into the same UWord of bm0[]. */
69#define UWORD_MSB(a) ((a) & ~(BITS_PER_UWORD - 1))
70
71/* Lowest bits of an address that fit into the same UWord of bm0[]. */
72#define UWORD_LSB(a) ((a) & (BITS_PER_UWORD - 1))
73
74/* Highest address that fits in the same UWord as a. */
75#define UWORD_HIGHEST_ADDRESS(a) ((a) | (BITS_PER_UWORD - 1))
76
77
bart33e56c92008-03-24 06:41:30 +000078/* Local variables. */
sewardjaf44c822007-11-25 14:01:38 +000079
80static ULong s_bitmap2_creation_count;
81
82
bart0008f5b2008-03-22 17:07:39 +000083
84/*********************************************************************/
85/* Functions for manipulating a struct bitmap1. */
86/*********************************************************************/
87
88
sewardjaf44c822007-11-25 14:01:38 +000089/* Lowest level, corresponding to the lowest ADDR0_BITS of an address. */
90struct bitmap1
91{
92 UWord bm0_r[BITMAP1_UWORD_COUNT];
93 UWord bm0_w[BITMAP1_UWORD_COUNT];
94};
95
96static __inline__ UWord bm0_mask(const Addr a)
97{
barta79df6e2008-03-14 17:07:51 +000098 return ((UWord)1 << UWORD_LSB(a));
sewardjaf44c822007-11-25 14:01:38 +000099}
100
101static __inline__ void bm0_set(UWord* bm0, const Addr a)
102{
103 //tl_assert(a < ADDR0_COUNT);
barta79df6e2008-03-14 17:07:51 +0000104 bm0[a >> BITS_PER_BITS_PER_UWORD] |= (UWord)1 << UWORD_LSB(a);
105}
106
bartf8bc71d2008-03-15 11:42:34 +0000107/** Set all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */
108static __inline__ void bm0_set_range(UWord* bm0,
109 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000110{
111#if 0
112 tl_assert(a1 < ADDR0_COUNT);
bartf8bc71d2008-03-15 11:42:34 +0000113 tl_assert(size > 0);
114 tl_assert(a1 + size <= ADDR0_COUNT);
115 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
barta79df6e2008-03-14 17:07:51 +0000116#endif
117 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
bartf8bc71d2008-03-15 11:42:34 +0000118 |= (((UWord)1 << size) - 1) << UWORD_LSB(a1);
sewardjaf44c822007-11-25 14:01:38 +0000119}
120
121static __inline__ void bm0_clear(UWord* bm0, const Addr a)
122{
123 //tl_assert(a < ADDR0_COUNT);
barta79df6e2008-03-14 17:07:51 +0000124 bm0[a >> BITS_PER_BITS_PER_UWORD] &= ~((UWord)1 << UWORD_LSB(a));
sewardjaf44c822007-11-25 14:01:38 +0000125}
126
bart5955f332008-03-25 17:19:20 +0000127/** Clear all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */
128static __inline__ void bm0_clear_range(UWord* bm0,
129 const Addr a1, const SizeT size)
130{
131#if 0
132 tl_assert(a1 < ADDR0_COUNT);
133 tl_assert(size > 0);
134 tl_assert(a1 + size <= ADDR0_COUNT);
135 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
136#endif
137 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
138 &= ~(((UWord)1 << size) - 1) << UWORD_LSB(a1);
139}
140
sewardjaf44c822007-11-25 14:01:38 +0000141static __inline__ UWord bm0_is_set(const UWord* bm0, const Addr a)
142{
143 //tl_assert(a < ADDR0_COUNT);
barta79df6e2008-03-14 17:07:51 +0000144 return (bm0[a >> BITS_PER_BITS_PER_UWORD] & ((UWord)1 << UWORD_LSB(a)));
sewardjaf44c822007-11-25 14:01:38 +0000145}
146
bartf8bc71d2008-03-15 11:42:34 +0000147/** Return true if any of the bits [ a1 .. a1+size [ are set in bm0. */
barta79df6e2008-03-14 17:07:51 +0000148static __inline__ UWord bm0_is_any_set(const UWord* bm0,
bartf8bc71d2008-03-15 11:42:34 +0000149 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000150{
151#if 0
152 tl_assert(a1 < ADDR0_COUNT);
bartf8bc71d2008-03-15 11:42:34 +0000153 tl_assert(size > 0);
154 tl_assert(a1 + size <= ADDR0_COUNT);
155 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
barta79df6e2008-03-14 17:07:51 +0000156#endif
157 return (bm0[a1 >> BITS_PER_BITS_PER_UWORD]
bartf8bc71d2008-03-15 11:42:34 +0000158 & ((((UWord)1 << size) - 1) << UWORD_LSB(a1)));
barta79df6e2008-03-14 17:07:51 +0000159}
sewardjaf44c822007-11-25 14:01:38 +0000160
bartadbdf142008-03-19 17:00:12 +0000161
bart0008f5b2008-03-22 17:07:39 +0000162
163/*********************************************************************/
164/* Functions for manipulating a struct bitmap. */
bartadbdf142008-03-19 17:00:12 +0000165/*********************************************************************/
166
167
bart33e56c92008-03-24 06:41:30 +0000168/* Second level bitmap. */
sewardjaf44c822007-11-25 14:01:38 +0000169struct bitmap2
170{
bart33e56c92008-03-24 06:41:30 +0000171 Addr addr; ///< address >> ADDR0_BITS
bartf647d342008-03-24 19:12:12 +0000172 int refcnt;
sewardjaf44c822007-11-25 14:01:38 +0000173 struct bitmap1 bm1;
174};
175
bartf647d342008-03-24 19:12:12 +0000176/* One node of bitmap::oset. */
177struct bitmap2ref
178{
179 Addr addr; ///< address >> ADDR0_BITS
180 struct bitmap2* bm2;
181};
182
bart33e56c92008-03-24 06:41:30 +0000183struct bm_cache_elem
184{
185 Addr a1;
186 struct bitmap2* bm2;
187};
188
189#define N_CACHE_ELEM 4
190
sewardjaf44c822007-11-25 14:01:38 +0000191/* Complete bitmap. */
192struct bitmap
193{
bart33e56c92008-03-24 06:41:30 +0000194 struct bm_cache_elem cache[N_CACHE_ELEM];
195 OSet* oset;
sewardjaf44c822007-11-25 14:01:38 +0000196};
197
bart33e56c92008-03-24 06:41:30 +0000198
bartf647d342008-03-24 19:12:12 +0000199static struct bitmap2* bm2_new(const UWord a1);
200static struct bitmap2* bm2_make_exclusive(struct bitmap* const bm,
201 struct bitmap2ref* const bm2ref);
202
203
bartf647d342008-03-24 19:12:12 +0000204static __inline__
bartf29205e2008-03-25 18:51:06 +0000205Bool bm_cache_lookup(const struct bitmap* const bm, const UWord a1,
206 struct bitmap2** bm2)
bart33e56c92008-03-24 06:41:30 +0000207{
208 tl_assert(bm);
bartf29205e2008-03-25 18:51:06 +0000209 tl_assert(bm2);
bart33e56c92008-03-24 06:41:30 +0000210
211#if N_CACHE_ELEM > 8
212#error Please update the code below.
213#endif
214#if N_CACHE_ELEM >= 1
215 if (a1 == bm->cache[0].a1)
bartf29205e2008-03-25 18:51:06 +0000216 {
217 *bm2 = bm->cache[0].bm2;
218 return True;
219 }
bart33e56c92008-03-24 06:41:30 +0000220#endif
221#if N_CACHE_ELEM >= 2
222 if (a1 == bm->cache[1].a1)
bartf29205e2008-03-25 18:51:06 +0000223 {
224 *bm2 = bm->cache[1].bm2;
225 return True;
226 }
bart33e56c92008-03-24 06:41:30 +0000227#endif
228#if N_CACHE_ELEM >= 3
229 if (a1 == bm->cache[2].a1)
bartf29205e2008-03-25 18:51:06 +0000230 {
231 *bm2 = bm->cache[2].bm2;
232 return True;
233 }
bart33e56c92008-03-24 06:41:30 +0000234#endif
235#if N_CACHE_ELEM >= 4
236 if (a1 == bm->cache[3].a1)
bartf29205e2008-03-25 18:51:06 +0000237 {
238 *bm2 = bm->cache[3].bm2;
239 return True;
240 }
bart33e56c92008-03-24 06:41:30 +0000241#endif
242#if N_CACHE_ELEM >= 5
243 if (a1 == bm->cache[4].a1)
bartf29205e2008-03-25 18:51:06 +0000244 {
245 *bm2 = bm->cache[4].bm2;
246 return True;
247 }
bart33e56c92008-03-24 06:41:30 +0000248#endif
249#if N_CACHE_ELEM >= 6
250 if (a1 == bm->cache[5].a1)
bartf29205e2008-03-25 18:51:06 +0000251 {
252 *bm2 = bm->cache[5].bm2;
253 return True;
254 }
bart33e56c92008-03-24 06:41:30 +0000255#endif
256#if N_CACHE_ELEM >= 7
257 if (a1 == bm->cache[6].a1)
bartf29205e2008-03-25 18:51:06 +0000258 {
259 *bm2 = bm->cache[6].bm2;
260 return True;
261 }
bart33e56c92008-03-24 06:41:30 +0000262#endif
263#if N_CACHE_ELEM >= 8
264 if (a1 == bm->cache[7].a1)
bartf29205e2008-03-25 18:51:06 +0000265 {
266 *bm2 = bm->cache[7].bm2;
267 return True;
268 }
bart33e56c92008-03-24 06:41:30 +0000269#endif
bartf29205e2008-03-25 18:51:06 +0000270 *bm2 = 0;
271 return False;
bart33e56c92008-03-24 06:41:30 +0000272}
273
274static __inline__
275void bm_update_cache(struct bitmap* const bm,
276 const UWord a1,
277 struct bitmap2* const bm2)
278{
279 tl_assert(bm);
280
281#if N_CACHE_ELEM > 8
282#error Please update the code below.
283#endif
284#if N_CACHE_ELEM >= 8
285 bm->cache[7] = bm->cache[6];
286#endif
287#if N_CACHE_ELEM >= 7
288 bm->cache[6] = bm->cache[5];
289#endif
290#if N_CACHE_ELEM >= 6
291 bm->cache[5] = bm->cache[4];
292#endif
293#if N_CACHE_ELEM >= 5
294 bm->cache[4] = bm->cache[3];
295#endif
296#if N_CACHE_ELEM >= 4
297 bm->cache[3] = bm->cache[2];
298#endif
299#if N_CACHE_ELEM >= 3
300 bm->cache[2] = bm->cache[1];
301#endif
302#if N_CACHE_ELEM >= 2
303 bm->cache[1] = bm->cache[0];
304#endif
305 bm->cache[0].a1 = a1;
306 bm->cache[0].bm2 = bm2;
307}
308
bartf647d342008-03-24 19:12:12 +0000309/** Look up the address a1 in bitmap bm and return a pointer to a potentially
310 * shared second level bitmap. The bitmap where the returned pointer points
311 * at may not be modified by the caller.
312 *
bart0008f5b2008-03-22 17:07:39 +0000313 * @param a1 client address shifted right by ADDR0_BITS.
314 * @param bm bitmap pointer.
315 */
sewardjaf44c822007-11-25 14:01:38 +0000316static __inline__
bartf647d342008-03-24 19:12:12 +0000317const struct bitmap2* bm2_lookup(const struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000318{
bartf29205e2008-03-25 18:51:06 +0000319 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000320 struct bitmap2ref* bm2ref;
321
322 tl_assert(bm);
bartf29205e2008-03-25 18:51:06 +0000323 if (! bm_cache_lookup(bm, a1, &bm2))
barta79df6e2008-03-14 17:07:51 +0000324 {
bartf29205e2008-03-25 18:51:06 +0000325 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
326 if (bm2ref)
327 {
328 bm2 = bm2ref->bm2;
329 }
bartf647d342008-03-24 19:12:12 +0000330 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000331 }
bartf29205e2008-03-25 18:51:06 +0000332 return bm2;
bartf647d342008-03-24 19:12:12 +0000333}
334
335/** Look up the address a1 in bitmap bm and return a pointer to a second
336 * level bitmap that is not shared and hence may be modified.
337 *
338 * @param a1 client address shifted right by ADDR0_BITS.
339 * @param bm bitmap pointer.
340 */
341static __inline__
342struct bitmap2*
343bm2_lookup_exclusive(const struct bitmap* const bm, const UWord a1)
344{
345 struct bitmap2ref* bm2ref;
346 struct bitmap2* bm2;
347
348 bm2ref = 0;
bartf29205e2008-03-25 18:51:06 +0000349 if (bm_cache_lookup(bm, a1, &bm2))
bartf647d342008-03-24 19:12:12 +0000350 {
bartf29205e2008-03-25 18:51:06 +0000351 if (bm2 == 0)
352 return 0;
bartf647d342008-03-24 19:12:12 +0000353 if (bm2->refcnt > 1)
bart33e56c92008-03-24 06:41:30 +0000354 {
bartf647d342008-03-24 19:12:12 +0000355 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bart33e56c92008-03-24 06:41:30 +0000356 }
barta79df6e2008-03-14 17:07:51 +0000357 }
bartf647d342008-03-24 19:12:12 +0000358 else
359 {
360 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bartf29205e2008-03-25 18:51:06 +0000361 if (bm2ref == 0)
bartf647d342008-03-24 19:12:12 +0000362 return 0;
bartf29205e2008-03-25 18:51:06 +0000363 bm2 = bm2ref->bm2;
bartf647d342008-03-24 19:12:12 +0000364 }
365
366 tl_assert(bm2);
367
368 if (bm2->refcnt > 1)
369 {
370 tl_assert(bm2ref);
371 bm2 = bm2_make_exclusive(*(struct bitmap**)&bm, bm2ref);
372 }
373
bart33e56c92008-03-24 06:41:30 +0000374 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000375}
376
bartf647d342008-03-24 19:12:12 +0000377/** Look up the address a1 in bitmap bm. The returned second level bitmap has
378 * reference count one and hence may be modified.
379 *
380 * @param a1 client address shifted right by ADDR0_BITS.
381 * @param bm bitmap pointer.
382 */
sewardjaf44c822007-11-25 14:01:38 +0000383static __inline__
bart0008f5b2008-03-22 17:07:39 +0000384struct bitmap2* bm2_insert(const struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000385{
bartf647d342008-03-24 19:12:12 +0000386 struct bitmap2ref* bm2ref;
bart33e56c92008-03-24 06:41:30 +0000387 struct bitmap2* bm2;
388
bartf647d342008-03-24 19:12:12 +0000389 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
390 bm2ref->addr = a1;
391 bm2 = bm2_new(a1);
392 bm2ref->bm2 = bm2;
bart0008f5b2008-03-22 17:07:39 +0000393 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
bartf647d342008-03-24 19:12:12 +0000394 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000395
bart33e56c92008-03-24 06:41:30 +0000396 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000397
398 return bm2;
399}
400
401/** Insert a new node in bitmap bm that points to the second level bitmap
402 * *bm2. This means that *bm2 becomes shared over two or more bitmaps.
403 */
404static __inline__
405struct bitmap2* bm2_insert_addref(const struct bitmap* const bm,
406 struct bitmap2* const bm2)
407{
408 struct bitmap2ref* bm2ref;
409
410 tl_assert(bm);
411 //tl_assert(VG_(OSetGen_Lookup)(bm->oset, &bm2->addr) == 0);
412 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
413 bm2ref->addr = bm2->addr;
414 bm2ref->bm2 = bm2;
415 bm2->refcnt++;
416 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000417
bartf647d342008-03-24 19:12:12 +0000418 bm_update_cache(*(struct bitmap**)&bm, bm2->addr, bm2);
419
bart0008f5b2008-03-22 17:07:39 +0000420 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000421}
422
bart0008f5b2008-03-22 17:07:39 +0000423/** Look up the address a1 in bitmap bm, and insert it if not found.
bartf647d342008-03-24 19:12:12 +0000424 * The returned second level bitmap may not be modified.
bart0008f5b2008-03-22 17:07:39 +0000425 *
426 * @param a1 client address shifted right by ADDR0_BITS.
427 * @param bm bitmap pointer.
428 */
sewardjaf44c822007-11-25 14:01:38 +0000429static __inline__
430struct bitmap2* bm2_lookup_or_insert(const struct bitmap* const bm,
431 const UWord a1)
432{
bartf647d342008-03-24 19:12:12 +0000433 struct bitmap2ref* bm2ref;
bart0008f5b2008-03-22 17:07:39 +0000434 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000435
bartf647d342008-03-24 19:12:12 +0000436 tl_assert(bm);
bart567614d2008-03-25 19:16:20 +0000437 if (bm_cache_lookup(bm, a1, &bm2))
438 {
439 if (bm2 == 0)
440 {
441 bm2 = bm2_insert(bm, a1);
442 }
443 }
444 else
barta79df6e2008-03-14 17:07:51 +0000445 {
bartf647d342008-03-24 19:12:12 +0000446 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
447 if (bm2ref)
448 {
449 bm2 = bm2ref->bm2;
450 }
451 else
bart33e56c92008-03-24 06:41:30 +0000452 {
453 bm2 = bm2_insert(bm, a1);
454 }
455 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
barta79df6e2008-03-14 17:07:51 +0000456 }
bart0008f5b2008-03-22 17:07:39 +0000457 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000458}
459
bartf647d342008-03-24 19:12:12 +0000460/** Look up the address a1 in bitmap bm, and insert it if not found.
461 * The returned second level bitmap may be modified.
462 *
463 * @param a1 client address shifted right by ADDR0_BITS.
464 * @param bm bitmap pointer.
465 */
466static __inline__
467struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
468 const UWord a1)
469{
470 struct bitmap2* bm2;
471
472 tl_assert(bm);
473 bm2 = (struct bitmap2*)bm2_lookup_or_insert(bm, a1);
474 tl_assert(bm2);
475 if (bm2->refcnt > 1)
476 {
477 struct bitmap2ref* bm2ref;
478 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
479 bm2 = bm2_make_exclusive(bm, bm2ref);
480 }
481 return bm2;
482}
483
sewardjaf44c822007-11-25 14:01:38 +0000484
bart33e56c92008-03-24 06:41:30 +0000485#endif /* __DRD_BITMAP_H */