blob: 94818307f7b6e7f42ac1e96fb949b360fd2595b5 [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
26#include "pub_tool_basics.h" // Addr, SizeT
27#include "pub_tool_debuginfo.h" // VG_(get_objname)()
28#include "pub_tool_libcassert.h" // tl_assert()
29#include "pub_tool_libcbase.h" // VG_(memset)
30#include "pub_tool_libcprint.h" // VG_(printf)
31#include "pub_tool_machine.h" // VG_(get_IP)()
32#include "pub_tool_mallocfree.h" // VG_(malloc), VG_(free)
33#include "pub_drd_bitmap.h"
34#include "drd_bitmap.h"
35#include "drd_error.h"
36#include "drd_suppression.h"
37
38
39// Local constants.
40
41static ULong s_bitmap_creation_count;
42
43
44// Local function declarations.
45
46static void bm2_merge(struct bitmap2* const bm2l,
47 const struct bitmap2* const bm2r);
48
49
50// Function definitions.
51
52struct bitmap* bm_new()
53{
54 struct bitmap* bm;
55
56 // If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD
57 // in drd_bitmap.h.
58 tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD);
59
60 bm = VG_(malloc)(sizeof(*bm));
61 tl_assert(bm);
62 bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
63
64 s_bitmap_creation_count++;
65
66 return bm;
67}
68
69void bm_delete(struct bitmap* const bm)
70{
71 tl_assert(bm);
72 VG_(OSetGen_Destroy)(bm->oset);
73 VG_(free)(bm);
74}
75
76/**
bart36556122008-03-13 19:24:30 +000077 * Record an access of type access_type at addresses a .. a + size - 1 in
sewardjaf44c822007-11-25 14:01:38 +000078 * bitmap bm.
79 */
bart36556122008-03-13 19:24:30 +000080static inline
sewardjaf44c822007-11-25 14:01:38 +000081void bm_access_range(struct bitmap* const bm,
bart9036dea2008-03-13 19:10:06 +000082 const Addr a1, const Addr a2,
bart0268dfa2008-03-11 20:10:21 +000083 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +000084{
bart36556122008-03-13 19:24:30 +000085 Addr b, b_next;
86
sewardjaf44c822007-11-25 14:01:38 +000087 tl_assert(bm);
bart9036dea2008-03-13 19:10:06 +000088 tl_assert(a1 < a2);
sewardjaf44c822007-11-25 14:01:38 +000089
bart36556122008-03-13 19:24:30 +000090 for (b = a1; b < a2; b = b_next)
sewardjaf44c822007-11-25 14:01:38 +000091 {
bart36556122008-03-13 19:24:30 +000092 Addr b_start;
93 Addr b_end;
94 struct bitmap2* bm2;
95 SPLIT_ADDRESS(b);
96
97 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
98 if (b_next > a2)
sewardjaf44c822007-11-25 14:01:38 +000099 {
bart36556122008-03-13 19:24:30 +0000100 b_next = a2;
101 }
102
103 bm2 = bm2_lookup_or_insert(bm, b1);
104 tl_assert(bm2);
105
106 if ((bm2->addr << ADDR0_BITS) < a1)
107 b_start = a1;
108 else
109 if ((bm2->addr << ADDR0_BITS) < a2)
110 b_start = (bm2->addr << ADDR0_BITS);
111 else
112 break;
113 tl_assert(a1 <= b_start && b_start <= a2);
114
115 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
116 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
117 else
118 b_end = a2;
119 tl_assert(a1 <= b_end && b_end <= a2);
120 tl_assert(b_start < b_end);
121 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
122
123 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
124 {
125 if (access_type == eLoad)
126 {
127 bm0_set(bm2->bm1.bm0_r, b0);
128 }
129 else
130 {
131 bm0_set(bm2->bm1.bm0_w, b0);
132 }
sewardjaf44c822007-11-25 14:01:38 +0000133 }
134 }
135}
136
bart36556122008-03-13 19:24:30 +0000137void bm_access_range_load(struct bitmap* const bm,
138 const Addr a1, const Addr a2)
139{
140 bm_access_range(bm, a1, a2, eLoad);
141}
142
143void bm_access_range_store(struct bitmap* const bm,
144 const Addr a1, const Addr a2)
145{
146 bm_access_range(bm, a1, a2, eStore);
147}
148
149Bool bm_has(const struct bitmap* const bm, const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000150 const BmAccessTypeT access_type)
151{
152 Addr b;
153 for (b = a1; b < a2; b++)
154 {
155 if (! bm_has_1(bm, b, access_type))
156 {
157 return False;
158 }
159 }
160 return True;
161}
162
163Bool bm_has_any(const struct bitmap* const bm,
bart36556122008-03-13 19:24:30 +0000164 const Addr a1, const Addr a2,
sewardjaf44c822007-11-25 14:01:38 +0000165 const BmAccessTypeT access_type)
166{
167 Addr b;
168
169 tl_assert(bm);
170
171 for (b = a1; b < a2; b++)
172 {
173 if (bm_has_1(bm, b, access_type))
174 {
175 return True;
176 }
177 }
178 return False;
179}
180
181/* Return a non-zero value if there is a read access, write access or both */
182/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
183UWord bm_has_any_access(const struct bitmap* const bm,
184 const Addr a1,
185 const Addr a2)
186{
187 Addr b, b_next;
188
189 tl_assert(bm);
190
191 for (b = a1; b < a2; b = b_next)
192 {
193 struct bitmap2* bm2 = bm_lookup(bm, b);
194
195 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
196 if (b_next > a2)
197 {
198 b_next = a2;
199 }
200
201 if (bm2)
202 {
203 Addr b_start;
204 Addr b_end;
205 UWord b0;
bart36556122008-03-13 19:24:30 +0000206 const struct bitmap1* const p1 = &bm2->bm1;
sewardjaf44c822007-11-25 14:01:38 +0000207
208 if ((bm2->addr << ADDR0_BITS) < a1)
209 b_start = a1;
210 else
211 if ((bm2->addr << ADDR0_BITS) < a2)
212 b_start = (bm2->addr << ADDR0_BITS);
213 else
214 break;
215 tl_assert(a1 <= b_start && b_start <= a2);
216
217 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
218 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
219 else
220 b_end = a2;
sewardjaf44c822007-11-25 14:01:38 +0000221 tl_assert(a1 <= b_end && b_end <= a2);
222 tl_assert(b_start < b_end);
223 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
224
bart36556122008-03-13 19:24:30 +0000225 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
sewardjaf44c822007-11-25 14:01:38 +0000226 {
sewardjaf44c822007-11-25 14:01:38 +0000227 const UWord mask
228 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
229 if (mask)
230 {
231 return mask;
232 }
233 }
234 }
235 }
236 return 0;
237}
238
239/**
240 * Report whether an access of type access_type at address a is recorded in
241 * bitmap bm.
242 * @return != 0 means true, and == 0 means false
243 */
244UWord bm_has_1(const struct bitmap* const bm,
245 const Addr a,
246 const BmAccessTypeT access_type)
247{
248 struct bitmap2* p2;
249 struct bitmap1* p1;
250 UWord* p0;
251 const UWord a0 = a & ADDR0_MASK;
252
253 tl_assert(bm);
254
255 p2 = bm_lookup(bm, a);
256 if (p2)
257 {
258 p1 = &p2->bm1;
259 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
260 return bm0_is_set(p0, a0);
261 }
262 return 0;
263}
264
265static __inline__
266void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
267{
268 UWord idx;
269 UWord mask;
270
271#if 0
272 // Commented out the assert statements below because of performance reasons.
273 tl_assert(a1);
274 tl_assert(a1 <= a2);
275 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
276 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
277#endif
278
279 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
280 /* mask: a contiguous series of one bits. The first bit set is bit */
281 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
282 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
283 bm1->bm0_r[idx] &= ~mask;
284 bm1->bm0_w[idx] &= ~mask;
285}
286
287void bm_clear_all(const struct bitmap* const bm)
288{
289 struct bitmap2* bm2;
290
291 VG_(OSetGen_ResetIter)(bm->oset);
292
293 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
294 {
295 struct bitmap1* const bm1 = &bm2->bm1;
296 tl_assert(bm1);
297 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
298 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
299 }
300}
301
sewardjaf44c822007-11-25 14:01:38 +0000302void bm_clear(const struct bitmap* const bm,
303 const Addr a1,
304 const Addr a2)
305{
306 Addr b, b_next;
307
308 tl_assert(bm);
309 tl_assert(a1);
310 tl_assert(a1 <= a2);
311
312 for (b = a1; b < a2; b = b_next)
313 {
314 struct bitmap2* const p2 = bm_lookup(bm, b);
315
316 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
317 if (b_next > a2)
318 {
319 b_next = a2;
320 }
321
322 if (p2)
323 {
324 Addr c = b;
325 if (UWORD_LSB(c))
326 {
327 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
328 if (c_next > b_next)
329 c_next = b_next;
330 bm1_clear(&p2->bm1, c, c_next);
331 c = c_next;
332 }
333 if (UWORD_LSB(c) == 0)
334 {
335 const Addr c_next = UWORD_MSB(b_next);
336 tl_assert(UWORD_LSB(c) == 0);
337 tl_assert(UWORD_LSB(c_next) == 0);
338 tl_assert(c_next <= b_next);
339 tl_assert(c <= c_next);
340 if (c_next > c)
341 {
342 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
343 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
344 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
345 c = c_next;
346 }
347 }
348 if (c != b_next)
349 {
350 bm1_clear(&p2->bm1, c, b_next);
351 }
352 }
353 }
354}
sewardjaf44c822007-11-25 14:01:38 +0000355
bart36556122008-03-13 19:24:30 +0000356inline
357Bool bm_has_conflict_with(const struct bitmap* const bm,
358 const Addr a1, const Addr a2,
359 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000360{
bart36556122008-03-13 19:24:30 +0000361 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000362
363 tl_assert(bm);
364
bart36556122008-03-13 19:24:30 +0000365 for (b = a1; b < a2; b = b_next)
sewardjaf44c822007-11-25 14:01:38 +0000366 {
bart36556122008-03-13 19:24:30 +0000367 struct bitmap2* bm2 = bm_lookup(bm, b);
368
369 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
370 if (b_next > a2)
sewardjaf44c822007-11-25 14:01:38 +0000371 {
bart36556122008-03-13 19:24:30 +0000372 b_next = a2;
sewardjaf44c822007-11-25 14:01:38 +0000373 }
bart36556122008-03-13 19:24:30 +0000374
375 if (bm2)
sewardjaf44c822007-11-25 14:01:38 +0000376 {
bart36556122008-03-13 19:24:30 +0000377 Addr b_start;
378 Addr b_end;
379 UWord b0;
380 const struct bitmap1* const p1 = &bm2->bm1;
381
382 if ((bm2->addr << ADDR0_BITS) < a1)
383 b_start = a1;
384 else
385 if ((bm2->addr << ADDR0_BITS) < a2)
386 b_start = (bm2->addr << ADDR0_BITS);
387 else
388 break;
389 tl_assert(a1 <= b_start && b_start <= a2);
390
391 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
392 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
393 else
394 b_end = a2;
395 tl_assert(a1 <= b_end && b_end <= a2);
396 tl_assert(b_start < b_end);
397 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
398
399 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
400 {
401 if (access_type == eLoad)
402 {
403 if (bm0_is_set(p1->bm0_w, b0))
404 {
405 return True;
406 }
407 }
408 else
409 {
410 tl_assert(access_type == eStore);
411 if (bm0_is_set(p1->bm0_r, b0)
412 | bm0_is_set(p1->bm0_w, b0))
413 {
414 return True;
415 }
416 }
417 }
sewardjaf44c822007-11-25 14:01:38 +0000418 }
419 }
420 return False;
421}
422
bart36556122008-03-13 19:24:30 +0000423Bool bm_load_has_conflict_with(const struct bitmap* const bm,
424 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000425{
bart36556122008-03-13 19:24:30 +0000426 return bm_has_conflict_with(bm, a1, a2, eLoad);
427}
428
429Bool bm_store_has_conflict_with(const struct bitmap* const bm,
430 const Addr a1, const Addr a2)
431{
432 return bm_has_conflict_with(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000433}
434
435void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
436{
437 OSet* const tmp = bm1->oset;
438 bm1->oset = bm2->oset;
439 bm2->oset = tmp;
440}
441
442void bm_merge2(struct bitmap* const lhs,
443 const struct bitmap* const rhs)
444{
445 struct bitmap2* bm2l;
446 const struct bitmap2* bm2r;
447
448 // First step: allocate any missing bitmaps in *lhs.
449 VG_(OSetGen_ResetIter)(rhs->oset);
450 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
451 {
452 bm2_lookup_or_insert(lhs, bm2r->addr);
453 }
454
455 VG_(OSetGen_ResetIter)(lhs->oset);
456 VG_(OSetGen_ResetIter)(rhs->oset);
457
458 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
459 {
460 do
461 {
462 bm2l = VG_(OSetGen_Next)(lhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000463 } while (bm2l->addr < bm2r->addr);
464
465 tl_assert(bm2l->addr == bm2r->addr);
466
467 bm2_merge(bm2l, bm2r);
468 }
469}
470
471/**
472 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
473 * @param lhs First bitmap.
474 * @param rhs Bitmap to be compared with lhs.
475 * @return !=0 if there are data races, == 0 if there are none.
476 */
477int bm_has_races(const struct bitmap* const lhs,
478 const struct bitmap* const rhs)
479{
480 VG_(OSetGen_ResetIter)(lhs->oset);
481 VG_(OSetGen_ResetIter)(rhs->oset);
482
483 for (;;)
484 {
485 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
486 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
487 const struct bitmap1* bm1l;
488 const struct bitmap1* bm1r;
489 unsigned k;
490
491 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
492 {
493 if (bm2l->addr < bm2r->addr)
494 bm2l = VG_(OSetGen_Next)(lhs->oset);
495 else
496 bm2r = VG_(OSetGen_Next)(rhs->oset);
497 }
498 if (bm2l == 0 || bm2r == 0)
499 break;
500
501 bm1l = &bm2l->bm1;
502 bm1r = &bm2r->bm1;
503
504 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
505 {
506 unsigned b;
507 for (b = 0; b < BITS_PER_UWORD; b++)
508 {
509 UWord const access
510 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
511 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
512 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
513 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
514 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
515 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
516 {
517 return 1;
518 }
519 }
520 }
521 }
522 return 0;
523}
524
sewardjaf44c822007-11-25 14:01:38 +0000525void bm_print(const struct bitmap* const bm)
526{
527 struct bitmap2* bm2;
528
529 VG_(OSetGen_ResetIter)(bm->oset);
530
531 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
532 {
533 const struct bitmap1* const bm1 = &bm2->bm1;
534 unsigned k;
535 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
536 {
537 unsigned b;
538 for (b = 0; b < BITS_PER_UWORD; b++)
539 {
540 int const r = bm1->bm0_r[k] & bm0_mask(b);
541 int const w = bm1->bm0_w[k] & bm0_mask(b);
542 Addr const a = MAKE_ADDRESS(bm2->addr, k * BITS_PER_UWORD | b);
543 if (r || w)
544 {
545 VG_(printf)("0x%08lx %c %c\n",
546 (Addr)(a),
547 w ? 'W' : ' ', r ? 'R' : ' ');
548 }
549 }
550 }
551 }
552}
553
554ULong bm_get_bitmap_creation_count(void)
555{
556 return s_bitmap_creation_count;
557}
558
559ULong bm_get_bitmap2_creation_count(void)
560{
561 return s_bitmap2_creation_count;
562}
563
564static void bm2_merge(struct bitmap2* const bm2l,
565 const struct bitmap2* const bm2r)
566{
567 unsigned k;
568
569 tl_assert(bm2l->addr == bm2r->addr);
570
571 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
572 {
573 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
574 }
575 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
576 {
577 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
578 }
579}
580
581#if 0
582
583/* Unit test */
584static
585struct { Addr address; SizeT size; BmAccessTypeT access_type; }
586 s_args[] = {
587 { 0, 1, eLoad },
588 { 666, 4, eLoad },
589 { 667, 2, eStore },
590 { 1024, 1, eStore },
591 { 0x0000ffff, 1, eLoad },
592 { 0x0001ffff, 1, eLoad },
593 { 0x00ffffff, 1, eLoad },
594 { 0xffffffff, 1, eStore },
595 };
596
597void bm_test(void)
598{
599 struct bitmap* bm;
600 struct bitmap* bm2;
601 int i, j;
602
603 VG_(printf)("Start of DRD BM unit test.\n");
604
605 bm = bm_new();
606
607 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
608 {
bart9036dea2008-03-13 19:10:06 +0000609 bm_access_range(bm,
610 s_args[i].address,
611 s_args[i].address + s_args[i].size,
612 s_args[i].access_type);
sewardjaf44c822007-11-25 14:01:38 +0000613 }
614
615 VG_(printf)("Map contents -- should contain 10 addresses:\n");
616 bm_print(bm);
617
618 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
619 {
620 for (j = 0; j < s_args[i].size; j++)
621 {
622 tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
623 }
624 }
625
626 VG_(printf)("Merge result:\n");
627 bm2 = bm_merge(bm, bm);
628 bm_print(bm);
629
630 bm_delete(bm);
631 bm_delete(bm2);
632
633 VG_(printf)("End of DRD BM unit test.\n");
634}
635#endif
636
637
638/*
639 * Local variables:
640 * c-basic-offset: 3
641 * End:
642 */