blob: 3ed3f9a71fdd200a7ebe3eeef91039ee902f061c [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
127static __inline__ UWord bm0_is_set(const UWord* bm0, const Addr a)
128{
129 //tl_assert(a < ADDR0_COUNT);
barta79df6e2008-03-14 17:07:51 +0000130 return (bm0[a >> BITS_PER_BITS_PER_UWORD] & ((UWord)1 << UWORD_LSB(a)));
sewardjaf44c822007-11-25 14:01:38 +0000131}
132
bartf8bc71d2008-03-15 11:42:34 +0000133/** Return true if any of the bits [ a1 .. a1+size [ are set in bm0. */
barta79df6e2008-03-14 17:07:51 +0000134static __inline__ UWord bm0_is_any_set(const UWord* bm0,
bartf8bc71d2008-03-15 11:42:34 +0000135 const Addr a1, const SizeT size)
barta79df6e2008-03-14 17:07:51 +0000136{
137#if 0
138 tl_assert(a1 < ADDR0_COUNT);
bartf8bc71d2008-03-15 11:42:34 +0000139 tl_assert(size > 0);
140 tl_assert(a1 + size <= ADDR0_COUNT);
141 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
barta79df6e2008-03-14 17:07:51 +0000142#endif
143 return (bm0[a1 >> BITS_PER_BITS_PER_UWORD]
bartf8bc71d2008-03-15 11:42:34 +0000144 & ((((UWord)1 << size) - 1) << UWORD_LSB(a1)));
barta79df6e2008-03-14 17:07:51 +0000145}
sewardjaf44c822007-11-25 14:01:38 +0000146
bartadbdf142008-03-19 17:00:12 +0000147
bart0008f5b2008-03-22 17:07:39 +0000148
149/*********************************************************************/
150/* Functions for manipulating a struct bitmap. */
bartadbdf142008-03-19 17:00:12 +0000151/*********************************************************************/
152
153
bart33e56c92008-03-24 06:41:30 +0000154/* Second level bitmap. */
sewardjaf44c822007-11-25 14:01:38 +0000155struct bitmap2
156{
bart33e56c92008-03-24 06:41:30 +0000157 Addr addr; ///< address >> ADDR0_BITS
bartf647d342008-03-24 19:12:12 +0000158 int refcnt;
sewardjaf44c822007-11-25 14:01:38 +0000159 struct bitmap1 bm1;
160};
161
bartf647d342008-03-24 19:12:12 +0000162/* One node of bitmap::oset. */
163struct bitmap2ref
164{
165 Addr addr; ///< address >> ADDR0_BITS
166 struct bitmap2* bm2;
167};
168
bart33e56c92008-03-24 06:41:30 +0000169struct bm_cache_elem
170{
171 Addr a1;
172 struct bitmap2* bm2;
173};
174
175#define N_CACHE_ELEM 4
176
sewardjaf44c822007-11-25 14:01:38 +0000177/* Complete bitmap. */
178struct bitmap
179{
bart33e56c92008-03-24 06:41:30 +0000180 struct bm_cache_elem cache[N_CACHE_ELEM];
181 OSet* oset;
sewardjaf44c822007-11-25 14:01:38 +0000182};
183
bart33e56c92008-03-24 06:41:30 +0000184
bartf647d342008-03-24 19:12:12 +0000185static struct bitmap2* bm2_new(const UWord a1);
186static struct bitmap2* bm2_make_exclusive(struct bitmap* const bm,
187 struct bitmap2ref* const bm2ref);
188
189
190#if 0
191/** Bitmap invariant check.
192 *
193 * @return 1 if the invariant is satisfied, 0 if not.
194 */
195static __inline__
196int bm_check(const struct bitmap* const bm)
197{
198 struct bitmap2_ref* bm2ref;
199
200 tl_assert(bm);
201
202 return (bm->cache[0].a1 == 0
203 && bm->cache[1].a1 == 0
204 || ((bm2ref = VG_(OSetGen_Lookup)(bm->oset, &bm->last_lookup_a1))
205 && bm2ref->bm2
206 && bm->last_lookup_a1 == bm2ref->bm2->addr
207 && bm2ref->bm2->refcnt >= 1)
208 );
209}
210#endif
211
bart33e56c92008-03-24 06:41:30 +0000212static __inline__
213struct bitmap2* bm_cache_lookup(const struct bitmap* const bm, const UWord a1)
214{
215 tl_assert(bm);
216
217#if N_CACHE_ELEM > 8
218#error Please update the code below.
219#endif
220#if N_CACHE_ELEM >= 1
221 if (a1 == bm->cache[0].a1)
222 return bm->cache[0].bm2;
223#endif
224#if N_CACHE_ELEM >= 2
225 if (a1 == bm->cache[1].a1)
226 return bm->cache[1].bm2;
227#endif
228#if N_CACHE_ELEM >= 3
229 if (a1 == bm->cache[2].a1)
230 return bm->cache[2].bm2;
231#endif
232#if N_CACHE_ELEM >= 4
233 if (a1 == bm->cache[3].a1)
234 return bm->cache[3].bm2;
235#endif
236#if N_CACHE_ELEM >= 5
237 if (a1 == bm->cache[4].a1)
238 return bm->cache[4].bm2;
239#endif
240#if N_CACHE_ELEM >= 6
241 if (a1 == bm->cache[5].a1)
242 return bm->cache[5].bm2;
243#endif
244#if N_CACHE_ELEM >= 7
245 if (a1 == bm->cache[6].a1)
246 return bm->cache[6].bm2;
247#endif
248#if N_CACHE_ELEM >= 8
249 if (a1 == bm->cache[7].a1)
250 return bm->cache[7].bm2;
251#endif
252 return 0;
253}
254
255static __inline__
256void bm_update_cache(struct bitmap* const bm,
257 const UWord a1,
258 struct bitmap2* const bm2)
259{
260 tl_assert(bm);
261
262#if N_CACHE_ELEM > 8
263#error Please update the code below.
264#endif
265#if N_CACHE_ELEM >= 8
266 bm->cache[7] = bm->cache[6];
267#endif
268#if N_CACHE_ELEM >= 7
269 bm->cache[6] = bm->cache[5];
270#endif
271#if N_CACHE_ELEM >= 6
272 bm->cache[5] = bm->cache[4];
273#endif
274#if N_CACHE_ELEM >= 5
275 bm->cache[4] = bm->cache[3];
276#endif
277#if N_CACHE_ELEM >= 4
278 bm->cache[3] = bm->cache[2];
279#endif
280#if N_CACHE_ELEM >= 3
281 bm->cache[2] = bm->cache[1];
282#endif
283#if N_CACHE_ELEM >= 2
284 bm->cache[1] = bm->cache[0];
285#endif
286 bm->cache[0].a1 = a1;
287 bm->cache[0].bm2 = bm2;
288}
289
bartf647d342008-03-24 19:12:12 +0000290/** Look up the address a1 in bitmap bm and return a pointer to a potentially
291 * shared second level bitmap. The bitmap where the returned pointer points
292 * at may not be modified by the caller.
293 *
bart0008f5b2008-03-22 17:07:39 +0000294 * @param a1 client address shifted right by ADDR0_BITS.
295 * @param bm bitmap pointer.
296 */
sewardjaf44c822007-11-25 14:01:38 +0000297static __inline__
bartf647d342008-03-24 19:12:12 +0000298const struct bitmap2* bm2_lookup(const struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000299{
bartf647d342008-03-24 19:12:12 +0000300 struct bitmap2ref* bm2ref;
301
302 tl_assert(bm);
303 if (a1 == bm->cache[0].a1)
barta79df6e2008-03-14 17:07:51 +0000304 {
bartf647d342008-03-24 19:12:12 +0000305 return bm->cache[0].bm2;
306 }
307 if (a1 == bm->cache[1].a1)
308 {
309 return bm->cache[1].bm2;
310 }
311 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
312 if (bm2ref)
313 {
314 struct bitmap2* const bm2 = bm2ref->bm2;
315 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
316 return bm2;
317 }
318 return 0;
319}
320
321/** Look up the address a1 in bitmap bm and return a pointer to a second
322 * level bitmap that is not shared and hence may be modified.
323 *
324 * @param a1 client address shifted right by ADDR0_BITS.
325 * @param bm bitmap pointer.
326 */
327static __inline__
328struct bitmap2*
329bm2_lookup_exclusive(const struct bitmap* const bm, const UWord a1)
330{
331 struct bitmap2ref* bm2ref;
332 struct bitmap2* bm2;
333
334 bm2ref = 0;
335 bm2 = bm_cache_lookup(bm, a1);
336 if (bm2)
337 {
338 if (bm2->refcnt > 1)
bart33e56c92008-03-24 06:41:30 +0000339 {
bartf647d342008-03-24 19:12:12 +0000340 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
bart33e56c92008-03-24 06:41:30 +0000341 }
barta79df6e2008-03-14 17:07:51 +0000342 }
bartf647d342008-03-24 19:12:12 +0000343 else
344 {
345 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
346 if (bm2ref)
347 {
348 bm2 = bm2ref->bm2;
349 }
350 else
351 {
352 return 0;
353 }
354 }
355
356 tl_assert(bm2);
357
358 if (bm2->refcnt > 1)
359 {
360 tl_assert(bm2ref);
361 bm2 = bm2_make_exclusive(*(struct bitmap**)&bm, bm2ref);
362 }
363
bart33e56c92008-03-24 06:41:30 +0000364 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000365}
366
bartf647d342008-03-24 19:12:12 +0000367/** Look up the address a1 in bitmap bm. The returned second level bitmap has
368 * reference count one and hence may be modified.
369 *
370 * @param a1 client address shifted right by ADDR0_BITS.
371 * @param bm bitmap pointer.
372 */
sewardjaf44c822007-11-25 14:01:38 +0000373static __inline__
bart0008f5b2008-03-22 17:07:39 +0000374struct bitmap2* bm2_insert(const struct bitmap* const bm, const UWord a1)
sewardjaf44c822007-11-25 14:01:38 +0000375{
bartf647d342008-03-24 19:12:12 +0000376 struct bitmap2ref* bm2ref;
bart33e56c92008-03-24 06:41:30 +0000377 struct bitmap2* bm2;
378
bartf647d342008-03-24 19:12:12 +0000379 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
380 bm2ref->addr = a1;
381 bm2 = bm2_new(a1);
382 bm2ref->bm2 = bm2;
bart0008f5b2008-03-22 17:07:39 +0000383 VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
bartf647d342008-03-24 19:12:12 +0000384 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000385
bart33e56c92008-03-24 06:41:30 +0000386 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
bartf647d342008-03-24 19:12:12 +0000387
388 return bm2;
389}
390
391/** Insert a new node in bitmap bm that points to the second level bitmap
392 * *bm2. This means that *bm2 becomes shared over two or more bitmaps.
393 */
394static __inline__
395struct bitmap2* bm2_insert_addref(const struct bitmap* const bm,
396 struct bitmap2* const bm2)
397{
398 struct bitmap2ref* bm2ref;
399
400 tl_assert(bm);
401 //tl_assert(VG_(OSetGen_Lookup)(bm->oset, &bm2->addr) == 0);
402 bm2ref = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2ref));
403 bm2ref->addr = bm2->addr;
404 bm2ref->bm2 = bm2;
405 bm2->refcnt++;
406 VG_(OSetGen_Insert)(bm->oset, bm2ref);
barta79df6e2008-03-14 17:07:51 +0000407
bartf647d342008-03-24 19:12:12 +0000408 bm_update_cache(*(struct bitmap**)&bm, bm2->addr, bm2);
409
bart0008f5b2008-03-22 17:07:39 +0000410 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000411}
412
bart0008f5b2008-03-22 17:07:39 +0000413/** Look up the address a1 in bitmap bm, and insert it if not found.
bartf647d342008-03-24 19:12:12 +0000414 * The returned second level bitmap may not be modified.
bart0008f5b2008-03-22 17:07:39 +0000415 *
416 * @param a1 client address shifted right by ADDR0_BITS.
417 * @param bm bitmap pointer.
418 */
sewardjaf44c822007-11-25 14:01:38 +0000419static __inline__
420struct bitmap2* bm2_lookup_or_insert(const struct bitmap* const bm,
421 const UWord a1)
422{
bartf647d342008-03-24 19:12:12 +0000423 struct bitmap2ref* bm2ref;
bart0008f5b2008-03-22 17:07:39 +0000424 struct bitmap2* bm2;
barta79df6e2008-03-14 17:07:51 +0000425
bartf647d342008-03-24 19:12:12 +0000426 tl_assert(bm);
bart33e56c92008-03-24 06:41:30 +0000427 bm2 = bm_cache_lookup(bm, a1);
bart0008f5b2008-03-22 17:07:39 +0000428 if (bm2 == 0)
barta79df6e2008-03-14 17:07:51 +0000429 {
bartf647d342008-03-24 19:12:12 +0000430 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
431 if (bm2ref)
432 {
433 bm2 = bm2ref->bm2;
434 }
435 else
bart33e56c92008-03-24 06:41:30 +0000436 {
437 bm2 = bm2_insert(bm, a1);
438 }
439 bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
barta79df6e2008-03-14 17:07:51 +0000440 }
bart0008f5b2008-03-22 17:07:39 +0000441 return bm2;
sewardjaf44c822007-11-25 14:01:38 +0000442}
443
bartf647d342008-03-24 19:12:12 +0000444/** Look up the address a1 in bitmap bm, and insert it if not found.
445 * The returned second level bitmap may be modified.
446 *
447 * @param a1 client address shifted right by ADDR0_BITS.
448 * @param bm bitmap pointer.
449 */
450static __inline__
451struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
452 const UWord a1)
453{
454 struct bitmap2* bm2;
455
456 tl_assert(bm);
457 bm2 = (struct bitmap2*)bm2_lookup_or_insert(bm, a1);
458 tl_assert(bm2);
459 if (bm2->refcnt > 1)
460 {
461 struct bitmap2ref* bm2ref;
462 bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
463 bm2 = bm2_make_exclusive(bm, bm2ref);
464 }
465 return bm2;
466}
467
sewardjaf44c822007-11-25 14:01:38 +0000468
bart33e56c92008-03-24 06:41:30 +0000469#endif /* __DRD_BITMAP_H */