blob: 61aca8526744adf56098c85fb3bb5390ffa42650 [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/**
77 * Record an access of type access_type at addresses a in bitmap bm.
78 */
79static
80__inline__
81void bm_access_1(struct bitmap* const bm,
82 const Addr a,
83 const BmAccessTypeT access_type)
84{
85 struct bitmap2* p2;
86 struct bitmap1* p1;
87 UWord* p0;
88 SPLIT_ADDRESS(a);
89
90 tl_assert(bm);
91
92 p2 = bm2_lookup_or_insert(bm, a1);
93 p1 = &p2->bm1;
94 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
95 bm0_set(p0, a0);
96}
97
98static
99void bm_access_4_nonaligned(struct bitmap* const bm,
100 const Addr a,
101 const BmAccessTypeT access_type)
102{
103 bm_access_1(bm, a + 0, access_type);
104 bm_access_1(bm, a + 1, access_type);
105 bm_access_1(bm, a + 2, access_type);
106 bm_access_1(bm, a + 3, access_type);
107}
108
109static
110__inline__
111void bm_access_4_aligned(struct bitmap* const bm,
112 const Addr a,
113 const BmAccessTypeT access_type)
114{
115 struct bitmap2* p2;
116 struct bitmap1* p1;
117 UWord* p0;
118 SPLIT_ADDRESS(a);
119
120 tl_assert(bm);
121
122 p2 = bm2_lookup_or_insert(bm, a1);
123 p1 = &p2->bm1;
124 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
125 bm0_set(p0, a0+0);
126 bm0_set(p0, a0+1);
127 bm0_set(p0, a0+2);
128 bm0_set(p0, a0+3);
129}
130
131/**
132 * Record an access of type access_type at addresses a .. a + 3 in bitmap bm.
133 */
134void bm_access_4(struct bitmap* const bm,
135 const Addr a,
136 const BmAccessTypeT access_type)
137{
138 tl_assert(bm);
139 if ((a & 3) != 0)
140 {
141 bm_access_4_nonaligned(bm, a, access_type);
142 }
143 else
144 {
145 bm_access_4_aligned(bm, a, access_type);
146 }
147}
148
149/**
bart9036dea2008-03-13 19:10:06 +0000150 * Record an access of type access_type at addresses a1 .. a2 - 1 in
sewardjaf44c822007-11-25 14:01:38 +0000151 * bitmap bm.
152 */
153void bm_access_range(struct bitmap* const bm,
bart9036dea2008-03-13 19:10:06 +0000154 const Addr a1, const Addr a2,
bart0268dfa2008-03-11 20:10:21 +0000155 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000156{
157 tl_assert(bm);
bart9036dea2008-03-13 19:10:06 +0000158 tl_assert(a1 < a2);
sewardjaf44c822007-11-25 14:01:38 +0000159
bart9036dea2008-03-13 19:10:06 +0000160 if (a2 - a1 == 4)
161 bm_access_4(bm, a1, access_type);
162 else if (a2 - a1 == 1)
163 bm_access_1(bm, a1, access_type);
sewardjaf44c822007-11-25 14:01:38 +0000164 else
165 {
166 Addr b;
bart9036dea2008-03-13 19:10:06 +0000167 for (b = a1; b != a2; b++)
sewardjaf44c822007-11-25 14:01:38 +0000168 {
169 bm_access_1(bm, b, access_type);
170 }
171 }
172}
173
174Bool bm_has(const struct bitmap* const bm,
175 const Addr a1,
176 const Addr a2,
177 const BmAccessTypeT access_type)
178{
179 Addr b;
180 for (b = a1; b < a2; b++)
181 {
182 if (! bm_has_1(bm, b, access_type))
183 {
184 return False;
185 }
186 }
187 return True;
188}
189
190Bool bm_has_any(const struct bitmap* const bm,
191 const Addr a1,
192 const Addr a2,
193 const BmAccessTypeT access_type)
194{
195 Addr b;
196
197 tl_assert(bm);
198
199 for (b = a1; b < a2; b++)
200 {
201 if (bm_has_1(bm, b, access_type))
202 {
203 return True;
204 }
205 }
206 return False;
207}
208
209/* Return a non-zero value if there is a read access, write access or both */
210/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
211UWord bm_has_any_access(const struct bitmap* const bm,
212 const Addr a1,
213 const Addr a2)
214{
215 Addr b, b_next;
216
217 tl_assert(bm);
218
219 for (b = a1; b < a2; b = b_next)
220 {
221 struct bitmap2* bm2 = bm_lookup(bm, b);
222
223 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
224 if (b_next > a2)
225 {
226 b_next = a2;
227 }
228
229 if (bm2)
230 {
231 Addr b_start;
232 Addr b_end;
233 UWord b0;
234
235 if ((bm2->addr << ADDR0_BITS) < a1)
236 b_start = a1;
237 else
238 if ((bm2->addr << ADDR0_BITS) < a2)
239 b_start = (bm2->addr << ADDR0_BITS);
240 else
241 break;
242 tl_assert(a1 <= b_start && b_start <= a2);
243
244 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
245 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
246 else
247 b_end = a2;
248#if 0
249 VG_(message)(Vg_DebugMsg,
250 "in 0x%lx 0x%lx / cur 0x%lx 0x%lx / out 0x%lx 0x%lx",
251 a1, a2,
252 (bm2->addr << ADDR0_BITS),
253 (bm2->addr << ADDR0_BITS) + ADDR0_COUNT,
254 b_start, b_end);
255#endif
256 tl_assert(a1 <= b_end && b_end <= a2);
257 tl_assert(b_start < b_end);
258 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
259
260 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end - 1) & ADDR0_MASK); b0++)
261 {
262 const struct bitmap1* const p1 = &bm2->bm1;
263 const UWord mask
264 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
265 if (mask)
266 {
267 return mask;
268 }
269 }
270 }
271 }
272 return 0;
273}
274
275/**
276 * Report whether an access of type access_type at address a is recorded in
277 * bitmap bm.
278 * @return != 0 means true, and == 0 means false
279 */
280UWord bm_has_1(const struct bitmap* const bm,
281 const Addr a,
282 const BmAccessTypeT access_type)
283{
284 struct bitmap2* p2;
285 struct bitmap1* p1;
286 UWord* p0;
287 const UWord a0 = a & ADDR0_MASK;
288
289 tl_assert(bm);
290
291 p2 = bm_lookup(bm, a);
292 if (p2)
293 {
294 p1 = &p2->bm1;
295 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
296 return bm0_is_set(p0, a0);
297 }
298 return 0;
299}
300
301static __inline__
302void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
303{
304 UWord idx;
305 UWord mask;
306
307#if 0
308 // Commented out the assert statements below because of performance reasons.
309 tl_assert(a1);
310 tl_assert(a1 <= a2);
311 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
312 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
313#endif
314
315 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
316 /* mask: a contiguous series of one bits. The first bit set is bit */
317 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
318 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
319 bm1->bm0_r[idx] &= ~mask;
320 bm1->bm0_w[idx] &= ~mask;
321}
322
323void bm_clear_all(const struct bitmap* const bm)
324{
325 struct bitmap2* bm2;
326
327 VG_(OSetGen_ResetIter)(bm->oset);
328
329 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
330 {
331 struct bitmap1* const bm1 = &bm2->bm1;
332 tl_assert(bm1);
333 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
334 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
335 }
336}
337
sewardjaf44c822007-11-25 14:01:38 +0000338// New and fast implementation.
339void bm_clear(const struct bitmap* const bm,
340 const Addr a1,
341 const Addr a2)
342{
343 Addr b, b_next;
344
345 tl_assert(bm);
346 tl_assert(a1);
347 tl_assert(a1 <= a2);
348
349 for (b = a1; b < a2; b = b_next)
350 {
351 struct bitmap2* const p2 = bm_lookup(bm, b);
352
353 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
354 if (b_next > a2)
355 {
356 b_next = a2;
357 }
358
359 if (p2)
360 {
361 Addr c = b;
362 if (UWORD_LSB(c))
363 {
364 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
365 if (c_next > b_next)
366 c_next = b_next;
367 bm1_clear(&p2->bm1, c, c_next);
368 c = c_next;
369 }
370 if (UWORD_LSB(c) == 0)
371 {
372 const Addr c_next = UWORD_MSB(b_next);
373 tl_assert(UWORD_LSB(c) == 0);
374 tl_assert(UWORD_LSB(c_next) == 0);
375 tl_assert(c_next <= b_next);
376 tl_assert(c <= c_next);
377 if (c_next > c)
378 {
379 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
380 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
381 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
382 c = c_next;
383 }
384 }
385 if (c != b_next)
386 {
387 bm1_clear(&p2->bm1, c, b_next);
388 }
389 }
390 }
391}
sewardjaf44c822007-11-25 14:01:38 +0000392
393static
394__inline__
395UWord bm_has_conflict_with_1(const struct bitmap* const bm,
396 const Addr a,
397 const BmAccessTypeT access_type)
398{
399 struct bitmap2* p2;
400 const UWord a0 = a & ADDR0_MASK;
401
402 tl_assert(bm);
403
404 p2 = bm_lookup(bm, a);
405 if (p2)
406 {
407 if (access_type == eLoad)
408 {
409 return bm0_is_set(p2->bm1.bm0_w, a0);
410 }
411 else
412 {
413 tl_assert(access_type == eStore);
414 return (bm0_is_set(p2->bm1.bm0_r, a0)
415 | bm0_is_set(p2->bm1.bm0_w, a0));
416 }
417 }
418 return False;
419}
420
421/**
422 * Return true if the access to [a,a+size[ of type access_type conflicts with
423 * any access stored in bitmap bm.
424 */
425Bool bm_has_conflict_with(const struct bitmap* const bm,
426 const Addr a1,
427 const Addr a2,
428 const BmAccessTypeT access_type)
429{
430 Addr b;
431 for (b = a1; b != a2; b++)
432 {
433 if (bm_has_conflict_with_1(bm, b, access_type))
434 {
435 return True;
436 }
437 }
438 return False;
439}
440
441void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
442{
443 OSet* const tmp = bm1->oset;
444 bm1->oset = bm2->oset;
445 bm2->oset = tmp;
446}
447
448void bm_merge2(struct bitmap* const lhs,
449 const struct bitmap* const rhs)
450{
451 struct bitmap2* bm2l;
452 const struct bitmap2* bm2r;
453
454 // First step: allocate any missing bitmaps in *lhs.
455 VG_(OSetGen_ResetIter)(rhs->oset);
456 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
457 {
458 bm2_lookup_or_insert(lhs, bm2r->addr);
459 }
460
461 VG_(OSetGen_ResetIter)(lhs->oset);
462 VG_(OSetGen_ResetIter)(rhs->oset);
463
464 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
465 {
466 do
467 {
468 bm2l = VG_(OSetGen_Next)(lhs->oset);
469 //VG_(message)(Vg_DebugMsg, "0x%x 0x%x", bm2l->addr, bm2r->addr);
470 } while (bm2l->addr < bm2r->addr);
471
472 tl_assert(bm2l->addr == bm2r->addr);
473
474 bm2_merge(bm2l, bm2r);
475 }
476}
477
478/**
479 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
480 * @param lhs First bitmap.
481 * @param rhs Bitmap to be compared with lhs.
482 * @return !=0 if there are data races, == 0 if there are none.
483 */
484int bm_has_races(const struct bitmap* const lhs,
485 const struct bitmap* const rhs)
486{
487 VG_(OSetGen_ResetIter)(lhs->oset);
488 VG_(OSetGen_ResetIter)(rhs->oset);
489
490 for (;;)
491 {
492 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
493 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
494 const struct bitmap1* bm1l;
495 const struct bitmap1* bm1r;
496 unsigned k;
497
498 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
499 {
500 if (bm2l->addr < bm2r->addr)
501 bm2l = VG_(OSetGen_Next)(lhs->oset);
502 else
503 bm2r = VG_(OSetGen_Next)(rhs->oset);
504 }
505 if (bm2l == 0 || bm2r == 0)
506 break;
507
508 bm1l = &bm2l->bm1;
509 bm1r = &bm2r->bm1;
510
511 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
512 {
513 unsigned b;
514 for (b = 0; b < BITS_PER_UWORD; b++)
515 {
516 UWord const access
517 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
518 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
519 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
520 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
521 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
522 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
523 {
524 return 1;
525 }
526 }
527 }
528 }
529 return 0;
530}
531
sewardjaf44c822007-11-25 14:01:38 +0000532void bm_print(const struct bitmap* const bm)
533{
534 struct bitmap2* bm2;
535
536 VG_(OSetGen_ResetIter)(bm->oset);
537
538 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
539 {
540 const struct bitmap1* const bm1 = &bm2->bm1;
541 unsigned k;
542 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
543 {
544 unsigned b;
545 for (b = 0; b < BITS_PER_UWORD; b++)
546 {
547 int const r = bm1->bm0_r[k] & bm0_mask(b);
548 int const w = bm1->bm0_w[k] & bm0_mask(b);
549 Addr const a = MAKE_ADDRESS(bm2->addr, k * BITS_PER_UWORD | b);
550 if (r || w)
551 {
552 VG_(printf)("0x%08lx %c %c\n",
553 (Addr)(a),
554 w ? 'W' : ' ', r ? 'R' : ' ');
555 }
556 }
557 }
558 }
559}
560
561ULong bm_get_bitmap_creation_count(void)
562{
563 return s_bitmap_creation_count;
564}
565
566ULong bm_get_bitmap2_creation_count(void)
567{
568 return s_bitmap2_creation_count;
569}
570
571static void bm2_merge(struct bitmap2* const bm2l,
572 const struct bitmap2* const bm2r)
573{
574 unsigned k;
575
576 tl_assert(bm2l->addr == bm2r->addr);
577
578 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
579 {
580 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
581 }
582 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
583 {
584 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
585 }
586}
587
588#if 0
589
590/* Unit test */
591static
592struct { Addr address; SizeT size; BmAccessTypeT access_type; }
593 s_args[] = {
594 { 0, 1, eLoad },
595 { 666, 4, eLoad },
596 { 667, 2, eStore },
597 { 1024, 1, eStore },
598 { 0x0000ffff, 1, eLoad },
599 { 0x0001ffff, 1, eLoad },
600 { 0x00ffffff, 1, eLoad },
601 { 0xffffffff, 1, eStore },
602 };
603
604void bm_test(void)
605{
606 struct bitmap* bm;
607 struct bitmap* bm2;
608 int i, j;
609
610 VG_(printf)("Start of DRD BM unit test.\n");
611
612 bm = bm_new();
613
614 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
615 {
bart9036dea2008-03-13 19:10:06 +0000616 bm_access_range(bm,
617 s_args[i].address,
618 s_args[i].address + s_args[i].size,
619 s_args[i].access_type);
sewardjaf44c822007-11-25 14:01:38 +0000620 }
621
622 VG_(printf)("Map contents -- should contain 10 addresses:\n");
623 bm_print(bm);
624
625 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
626 {
627 for (j = 0; j < s_args[i].size; j++)
628 {
629 tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
630 }
631 }
632
633 VG_(printf)("Merge result:\n");
634 bm2 = bm_merge(bm, bm);
635 bm_print(bm);
636
637 bm_delete(bm);
638 bm_delete(bm2);
639
640 VG_(printf)("End of DRD BM unit test.\n");
641}
642#endif
643
644
645/*
646 * Local variables:
647 * c-basic-offset: 3
648 * End:
649 */