blob: a860cf4e021313c502d2b00db15d0d91059b6bf0 [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;
bart588d90f2008-04-06 13:05:58 +000081static ULong s_node_creation_count;
sewardjaf44c822007-11-25 14:01:38 +000082
83
bart0008f5b2008-03-22 17:07:39 +000084
85/*********************************************************************/
86/* Functions for manipulating a struct bitmap1. */
87/*********************************************************************/
88
89
sewardjaf44c822007-11-25 14:01:38 +000090/* Lowest level, corresponding to the lowest ADDR0_BITS of an address. */
91struct bitmap1
92{
93 UWord bm0_r[BITMAP1_UWORD_COUNT];
94 UWord bm0_w[BITMAP1_UWORD_COUNT];
95};
96
97static __inline__ UWord bm0_mask(const Addr a)
98{
barta79df6e2008-03-14 17:07:51 +000099 return ((UWord)1 << UWORD_LSB(a));
sewardjaf44c822007-11-25 14:01:38 +0000100}
101
102static __inline__ void bm0_set(UWord* bm0, const Addr a)
103{
104 //tl_assert(a < ADDR0_COUNT);
barta79df6e2008-03-14 17:07:51 +0000105 bm0[a >> BITS_PER_BITS_PER_UWORD] |= (UWord)1 << UWORD_LSB(a);
106}
107
bartf8bc71d2008-03-15 11:42:34 +0000108/** Set all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */
109static __inline__ void bm0_set_range(UWord* bm0,
110 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000111{
112#if 0
113 tl_assert(a1 < ADDR0_COUNT);
bartf8bc71d2008-03-15 11:42:34 +0000114 tl_assert(size > 0);
115 tl_assert(a1 + size <= ADDR0_COUNT);
116 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
barta79df6e2008-03-14 17:07:51 +0000117#endif
118 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
bartf8bc71d2008-03-15 11:42:34 +0000119 |= (((UWord)1 << size) - 1) << UWORD_LSB(a1);
sewardjaf44c822007-11-25 14:01:38 +0000120}
121
122static __inline__ void bm0_clear(UWord* bm0, const Addr a)
123{
124 //tl_assert(a < ADDR0_COUNT);
barta79df6e2008-03-14 17:07:51 +0000125 bm0[a >> BITS_PER_BITS_PER_UWORD] &= ~((UWord)1 << UWORD_LSB(a));
sewardjaf44c822007-11-25 14:01:38 +0000126}
127
bart5955f332008-03-25 17:19:20 +0000128/** Clear all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */
129static __inline__ void bm0_clear_range(UWord* bm0,
130 const Addr a1, const SizeT size)
131{
132#if 0
133 tl_assert(a1 < ADDR0_COUNT);
134 tl_assert(size > 0);
135 tl_assert(a1 + size <= ADDR0_COUNT);
136 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
137#endif
138 bm0[a1 >> BITS_PER_BITS_PER_UWORD]
139 &= ~(((UWord)1 << size) - 1) << UWORD_LSB(a1);
140}
141
sewardjaf44c822007-11-25 14:01:38 +0000142static __inline__ UWord bm0_is_set(const UWord* bm0, const Addr a)
143{
144 //tl_assert(a < ADDR0_COUNT);
barta79df6e2008-03-14 17:07:51 +0000145 return (bm0[a >> BITS_PER_BITS_PER_UWORD] & ((UWord)1 << UWORD_LSB(a)));
sewardjaf44c822007-11-25 14:01:38 +0000146}
147
bartf8bc71d2008-03-15 11:42:34 +0000148/** Return true if any of the bits [ a1 .. a1+size [ are set in bm0. */
barta79df6e2008-03-14 17:07:51 +0000149static __inline__ UWord bm0_is_any_set(const UWord* bm0,
bartf8bc71d2008-03-15 11:42:34 +0000150 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000151{
152#if 0
153 tl_assert(a1 < ADDR0_COUNT);
bartf8bc71d2008-03-15 11:42:34 +0000154 tl_assert(size > 0);
155 tl_assert(a1 + size <= ADDR0_COUNT);
156 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
barta79df6e2008-03-14 17:07:51 +0000157#endif
158 return (bm0[a1 >> BITS_PER_BITS_PER_UWORD]
bartf8bc71d2008-03-15 11:42:34 +0000159 & ((((UWord)1 << size) - 1) << UWORD_LSB(a1)));
barta79df6e2008-03-14 17:07:51 +0000160}
sewardjaf44c822007-11-25 14:01:38 +0000161
bartadbdf142008-03-19 17:00:12 +0000162
bart0008f5b2008-03-22 17:07:39 +0000163
164/*********************************************************************/
165/* Functions for manipulating a struct bitmap. */
bartadbdf142008-03-19 17:00:12 +0000166/*********************************************************************/
167
168
bart33e56c92008-03-24 06:41:30 +0000169/* Second level bitmap. */
sewardjaf44c822007-11-25 14:01:38 +0000170struct bitmap2
171{
bart33e56c92008-03-24 06:41:30 +0000172 Addr addr; ///< address >> ADDR0_BITS
bartf647d342008-03-24 19:12:12 +0000173 int refcnt;
sewardjaf44c822007-11-25 14:01:38 +0000174 struct bitmap1 bm1;
175};
176
bartf647d342008-03-24 19:12:12 +0000177/* One node of bitmap::oset. */
178struct bitmap2ref
179{
180 Addr addr; ///< address >> ADDR0_BITS
181 struct bitmap2* bm2;
182};
183
bart33e56c92008-03-24 06:41:30 +0000184struct bm_cache_elem
185{
186 Addr a1;
187 struct bitmap2* bm2;
188};
189
190#define N_CACHE_ELEM 4
191
sewardjaf44c822007-11-25 14:01:38 +0000192/* Complete bitmap. */
193struct bitmap
194{
bart33e56c92008-03-24 06:41:30 +0000195 struct bm_cache_elem cache[N_CACHE_ELEM];
196 OSet* oset;
sewardjaf44c822007-11-25 14:01:38 +0000197};
198
bart33e56c92008-03-24 06:41:30 +0000199
bartf647d342008-03-24 19:12:12 +0000200static struct bitmap2* bm2_new(const UWord a1);
201static struct bitmap2* bm2_make_exclusive(struct bitmap* const bm,
202 struct bitmap2ref* const bm2ref);
203
204
bartf647d342008-03-24 19:12:12 +0000205static __inline__
bartf29205e2008-03-25 18:51:06 +0000206Bool bm_cache_lookup(const struct bitmap* const bm, const UWord a1,
207 struct bitmap2** bm2)
bart33e56c92008-03-24 06:41:30 +0000208{
209 tl_assert(bm);
bartf29205e2008-03-25 18:51:06 +0000210 tl_assert(bm2);
bart33e56c92008-03-24 06:41:30 +0000211
212#if N_CACHE_ELEM > 8
213#error Please update the code below.
214#endif
215#if N_CACHE_ELEM >= 1
216 if (a1 == bm->cache[0].a1)
bartf29205e2008-03-25 18:51:06 +0000217 {
218 *bm2 = bm->cache[0].bm2;
219 return True;
220 }
bart33e56c92008-03-24 06:41:30 +0000221#endif
222#if N_CACHE_ELEM >= 2
223 if (a1 == bm->cache[1].a1)
bartf29205e2008-03-25 18:51:06 +0000224 {
225 *bm2 = bm->cache[1].bm2;
226 return True;
227 }
bart33e56c92008-03-24 06:41:30 +0000228#endif
229#if N_CACHE_ELEM >= 3
230 if (a1 == bm->cache[2].a1)
bartf29205e2008-03-25 18:51:06 +0000231 {
232 *bm2 = bm->cache[2].bm2;
233 return True;
234 }
bart33e56c92008-03-24 06:41:30 +0000235#endif
236#if N_CACHE_ELEM >= 4
237 if (a1 == bm->cache[3].a1)
bartf29205e2008-03-25 18:51:06 +0000238 {
239 *bm2 = bm->cache[3].bm2;
240 return True;
241 }
bart33e56c92008-03-24 06:41:30 +0000242#endif
243#if N_CACHE_ELEM >= 5
244 if (a1 == bm->cache[4].a1)
bartf29205e2008-03-25 18:51:06 +0000245 {
246 *bm2 = bm->cache[4].bm2;
247 return True;
248 }
bart33e56c92008-03-24 06:41:30 +0000249#endif
250#if N_CACHE_ELEM >= 6
251 if (a1 == bm->cache[5].a1)
bartf29205e2008-03-25 18:51:06 +0000252 {
253 *bm2 = bm->cache[5].bm2;
254 return True;
255 }
bart33e56c92008-03-24 06:41:30 +0000256#endif
257#if N_CACHE_ELEM >= 7
258 if (a1 == bm->cache[6].a1)
bartf29205e2008-03-25 18:51:06 +0000259 {
260 *bm2 = bm->cache[6].bm2;
261 return True;
262 }
bart33e56c92008-03-24 06:41:30 +0000263#endif
264#if N_CACHE_ELEM >= 8
265 if (a1 == bm->cache[7].a1)
bartf29205e2008-03-25 18:51:06 +0000266 {
267 *bm2 = bm->cache[7].bm2;
268 return True;
269 }
bart33e56c92008-03-24 06:41:30 +0000270#endif
bartf29205e2008-03-25 18:51:06 +0000271 *bm2 = 0;
272 return False;
bart33e56c92008-03-24 06:41:30 +0000273}
274
275static __inline__
276void bm_update_cache(struct bitmap* const bm,
277 const UWord a1,
278 struct bitmap2* const bm2)
279{
280 tl_assert(bm);
281
282#if N_CACHE_ELEM > 8
283#error Please update the code below.
284#endif
285#if N_CACHE_ELEM >= 8
286 bm->cache[7] = bm->cache[6];
287#endif
288#if N_CACHE_ELEM >= 7
289 bm->cache[6] = bm->cache[5];
290#endif
291#if N_CACHE_ELEM >= 6
292 bm->cache[5] = bm->cache[4];
293#endif
294#if N_CACHE_ELEM >= 5
295 bm->cache[4] = bm->cache[3];
296#endif
297#if N_CACHE_ELEM >= 4
298 bm->cache[3] = bm->cache[2];
299#endif
300#if N_CACHE_ELEM >= 3
301 bm->cache[2] = bm->cache[1];
302#endif
303#if N_CACHE_ELEM >= 2
304 bm->cache[1] = bm->cache[0];
305#endif
306 bm->cache[0].a1 = a1;
307 bm->cache[0].bm2 = bm2;
308}
309
bartf647d342008-03-24 19:12:12 +0000310/** Look up the address a1 in bitmap bm and return a pointer to a potentially
311 * shared second level bitmap. The bitmap where the returned pointer points
312 * at may not be modified by the caller.
313 *
bart0008f5b2008-03-22 17:07:39 +0000314 * @param a1 client address shifted right by ADDR0_BITS.
315 * @param bm bitmap pointer.
316 */
sewardjaf44c822007-11-25 14:01:38 +0000317static __inline__
bartf647d342008-03-24 19:12:12 +0000318const struct bitmap2* bm2_lookup(const struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000319{
bartf29205e2008-03-25 18:51:06 +0000320 struct bitmap2* bm2;
bartf647d342008-03-24 19:12:12 +0000321 struct bitmap2ref* bm2ref;
322
323 tl_assert(bm);
bartf29205e2008-03-25 18:51:06 +0000324 if (! bm_cache_lookup(bm, a1, &bm2))
barta79df6e2008-03-14 17:07:51 +0000325 {
bartf29205e2008-03-25 18:51:06 +0000326 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
327 if (bm2ref)
328 {
329 bm2 = bm2ref->bm2;
330 }
bartf647d342008-03-24 19:12:12 +0000331 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000332 }
bartf29205e2008-03-25 18:51:06 +0000333 return bm2;
bartf647d342008-03-24 19:12:12 +0000334}
335
336/** Look up the address a1 in bitmap bm and return a pointer to a second
337 * level bitmap that is not shared and hence may be modified.
338 *
339 * @param a1 client address shifted right by ADDR0_BITS.
340 * @param bm bitmap pointer.
341 */
342static __inline__
343struct bitmap2*
344bm2_lookup_exclusive(const struct bitmap* const bm, const UWord a1)
345{
346 struct bitmap2ref* bm2ref;
347 struct bitmap2* bm2;
348
349 bm2ref = 0;
bartf29205e2008-03-25 18:51:06 +0000350 if (bm_cache_lookup(bm, a1, &bm2))
bartf647d342008-03-24 19:12:12 +0000351 {
bartf29205e2008-03-25 18:51:06 +0000352 if (bm2 == 0)
353 return 0;
bartf647d342008-03-24 19:12:12 +0000354 if (bm2->refcnt > 1)
bart33e56c92008-03-24 06:41:30 +0000355 {
bartf647d342008-03-24 19:12:12 +0000356 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bart33e56c92008-03-24 06:41:30 +0000357 }
barta79df6e2008-03-14 17:07:51 +0000358 }
bartf647d342008-03-24 19:12:12 +0000359 else
360 {
361 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bartf29205e2008-03-25 18:51:06 +0000362 if (bm2ref == 0)
bartf647d342008-03-24 19:12:12 +0000363 return 0;
bartf29205e2008-03-25 18:51:06 +0000364 bm2 = bm2ref->bm2;
bartf647d342008-03-24 19:12:12 +0000365 }
366
367 tl_assert(bm2);
368
369 if (bm2->refcnt > 1)
370 {
371 tl_assert(bm2ref);
372 bm2 = bm2_make_exclusive(*(struct bitmap**)&bm, bm2ref);
373 }
374
bart33e56c92008-03-24 06:41:30 +0000375 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000376}
377
bartf647d342008-03-24 19:12:12 +0000378/** Look up the address a1 in bitmap bm. The returned second level bitmap has
379 * reference count one and hence may be modified.
380 *
381 * @param a1 client address shifted right by ADDR0_BITS.
382 * @param bm bitmap pointer.
383 */
sewardjaf44c822007-11-25 14:01:38 +0000384static __inline__
bart0008f5b2008-03-22 17:07:39 +0000385struct bitmap2* bm2_insert(const struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000386{
bartf647d342008-03-24 19:12:12 +0000387 struct bitmap2ref* bm2ref;
bart33e56c92008-03-24 06:41:30 +0000388 struct bitmap2* bm2;
389
bart588d90f2008-04-06 13:05:58 +0000390 s_node_creation_count++;
bartf647d342008-03-24 19:12:12 +0000391 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
392 bm2ref->addr = a1;
393 bm2 = bm2_new(a1);
394 bm2ref->bm2 = bm2;
bart0008f5b2008-03-22 17:07:39 +0000395 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
bartf647d342008-03-24 19:12:12 +0000396 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000397
bart33e56c92008-03-24 06:41:30 +0000398 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000399
400 return bm2;
401}
402
403/** Insert a new node in bitmap bm that points to the second level bitmap
404 * *bm2. This means that *bm2 becomes shared over two or more bitmaps.
405 */
406static __inline__
407struct bitmap2* bm2_insert_addref(const struct bitmap* const bm,
408 struct bitmap2* const bm2)
409{
410 struct bitmap2ref* bm2ref;
411
412 tl_assert(bm);
413 //tl_assert(VG_(OSetGen_Lookup)(bm->oset, &bm2->addr) == 0);
bart588d90f2008-04-06 13:05:58 +0000414
415 s_node_creation_count++;
bartf647d342008-03-24 19:12:12 +0000416 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
417 bm2ref->addr = bm2->addr;
418 bm2ref->bm2 = bm2;
419 bm2->refcnt++;
420 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000421
bartf647d342008-03-24 19:12:12 +0000422 bm_update_cache(*(struct bitmap**)&bm, bm2->addr, bm2);
423
bart0008f5b2008-03-22 17:07:39 +0000424 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000425}
426
bart0008f5b2008-03-22 17:07:39 +0000427/** Look up the address a1 in bitmap bm, and insert it if not found.
bartf647d342008-03-24 19:12:12 +0000428 * The returned second level bitmap may not be modified.
bart0008f5b2008-03-22 17:07:39 +0000429 *
430 * @param a1 client address shifted right by ADDR0_BITS.
431 * @param bm bitmap pointer.
432 */
sewardjaf44c822007-11-25 14:01:38 +0000433static __inline__
434struct bitmap2* bm2_lookup_or_insert(const struct bitmap* const bm,
435 const UWord a1)
436{
bartf647d342008-03-24 19:12:12 +0000437 struct bitmap2ref* bm2ref;
bart0008f5b2008-03-22 17:07:39 +0000438 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000439
bartf647d342008-03-24 19:12:12 +0000440 tl_assert(bm);
bart567614d2008-03-25 19:16:20 +0000441 if (bm_cache_lookup(bm, a1, &bm2))
442 {
443 if (bm2 == 0)
444 {
445 bm2 = bm2_insert(bm, a1);
446 }
447 }
448 else
barta79df6e2008-03-14 17:07:51 +0000449 {
bartf647d342008-03-24 19:12:12 +0000450 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
451 if (bm2ref)
452 {
453 bm2 = bm2ref->bm2;
454 }
455 else
bart33e56c92008-03-24 06:41:30 +0000456 {
457 bm2 = bm2_insert(bm, a1);
458 }
459 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
barta79df6e2008-03-14 17:07:51 +0000460 }
bart0008f5b2008-03-22 17:07:39 +0000461 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000462}
463
bartf647d342008-03-24 19:12:12 +0000464/** Look up the address a1 in bitmap bm, and insert it if not found.
465 * The returned second level bitmap may be modified.
466 *
467 * @param a1 client address shifted right by ADDR0_BITS.
468 * @param bm bitmap pointer.
469 */
470static __inline__
471struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
472 const UWord a1)
473{
474 struct bitmap2* bm2;
475
476 tl_assert(bm);
477 bm2 = (struct bitmap2*)bm2_lookup_or_insert(bm, a1);
478 tl_assert(bm2);
479 if (bm2->refcnt > 1)
480 {
481 struct bitmap2ref* bm2ref;
482 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
483 bm2 = bm2_make_exclusive(bm, bm2ref);
484 }
485 return bm2;
486}
487
sewardjaf44c822007-11-25 14:01:38 +0000488
bart33e56c92008-03-24 06:41:30 +0000489#endif /* __DRD_BITMAP_H */