blob: d09ae47d3a7efb5fdb85519b6b8c37bea57b7fea [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;
221#if 0
222 VG_(message)(Vg_DebugMsg,
223 "in 0x%lx 0x%lx / cur 0x%lx 0x%lx / out 0x%lx 0x%lx",
224 a1, a2,
225 (bm2->addr << ADDR0_BITS),
226 (bm2->addr << ADDR0_BITS) + ADDR0_COUNT,
227 b_start, b_end);
228#endif
229 tl_assert(a1 <= b_end && b_end <= a2);
230 tl_assert(b_start < b_end);
231 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
232
bart36556122008-03-13 19:24:30 +0000233 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
sewardjaf44c822007-11-25 14:01:38 +0000234 {
sewardjaf44c822007-11-25 14:01:38 +0000235 const UWord mask
236 = bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0);
237 if (mask)
238 {
239 return mask;
240 }
241 }
242 }
243 }
244 return 0;
245}
246
247/**
248 * Report whether an access of type access_type at address a is recorded in
249 * bitmap bm.
250 * @return != 0 means true, and == 0 means false
251 */
252UWord bm_has_1(const struct bitmap* const bm,
253 const Addr a,
254 const BmAccessTypeT access_type)
255{
256 struct bitmap2* p2;
257 struct bitmap1* p1;
258 UWord* p0;
259 const UWord a0 = a & ADDR0_MASK;
260
261 tl_assert(bm);
262
263 p2 = bm_lookup(bm, a);
264 if (p2)
265 {
266 p1 = &p2->bm1;
267 p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
268 return bm0_is_set(p0, a0);
269 }
270 return 0;
271}
272
273static __inline__
274void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
275{
276 UWord idx;
277 UWord mask;
278
279#if 0
280 // Commented out the assert statements below because of performance reasons.
281 tl_assert(a1);
282 tl_assert(a1 <= a2);
283 tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
284 || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
285#endif
286
287 idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
288 /* mask: a contiguous series of one bits. The first bit set is bit */
289 /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
290 mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
291 bm1->bm0_r[idx] &= ~mask;
292 bm1->bm0_w[idx] &= ~mask;
293}
294
295void bm_clear_all(const struct bitmap* const bm)
296{
297 struct bitmap2* bm2;
298
299 VG_(OSetGen_ResetIter)(bm->oset);
300
301 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
302 {
303 struct bitmap1* const bm1 = &bm2->bm1;
304 tl_assert(bm1);
305 VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
306 VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
307 }
308}
309
sewardjaf44c822007-11-25 14:01:38 +0000310void bm_clear(const struct bitmap* const bm,
311 const Addr a1,
312 const Addr a2)
313{
314 Addr b, b_next;
315
316 tl_assert(bm);
317 tl_assert(a1);
318 tl_assert(a1 <= a2);
319
320 for (b = a1; b < a2; b = b_next)
321 {
322 struct bitmap2* const p2 = bm_lookup(bm, b);
323
324 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
325 if (b_next > a2)
326 {
327 b_next = a2;
328 }
329
330 if (p2)
331 {
332 Addr c = b;
333 if (UWORD_LSB(c))
334 {
335 Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
336 if (c_next > b_next)
337 c_next = b_next;
338 bm1_clear(&p2->bm1, c, c_next);
339 c = c_next;
340 }
341 if (UWORD_LSB(c) == 0)
342 {
343 const Addr c_next = UWORD_MSB(b_next);
344 tl_assert(UWORD_LSB(c) == 0);
345 tl_assert(UWORD_LSB(c_next) == 0);
346 tl_assert(c_next <= b_next);
347 tl_assert(c <= c_next);
348 if (c_next > c)
349 {
350 UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
351 VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8);
352 VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8);
353 c = c_next;
354 }
355 }
356 if (c != b_next)
357 {
358 bm1_clear(&p2->bm1, c, b_next);
359 }
360 }
361 }
362}
sewardjaf44c822007-11-25 14:01:38 +0000363
bart36556122008-03-13 19:24:30 +0000364inline
365Bool bm_has_conflict_with(const struct bitmap* const bm,
366 const Addr a1, const Addr a2,
367 const BmAccessTypeT access_type)
sewardjaf44c822007-11-25 14:01:38 +0000368{
bart36556122008-03-13 19:24:30 +0000369 Addr b, b_next;
sewardjaf44c822007-11-25 14:01:38 +0000370
371 tl_assert(bm);
372
bart36556122008-03-13 19:24:30 +0000373 for (b = a1; b < a2; b = b_next)
sewardjaf44c822007-11-25 14:01:38 +0000374 {
bart36556122008-03-13 19:24:30 +0000375 struct bitmap2* bm2 = bm_lookup(bm, b);
376
377 b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT;
378 if (b_next > a2)
sewardjaf44c822007-11-25 14:01:38 +0000379 {
bart36556122008-03-13 19:24:30 +0000380 b_next = a2;
sewardjaf44c822007-11-25 14:01:38 +0000381 }
bart36556122008-03-13 19:24:30 +0000382
383 if (bm2)
sewardjaf44c822007-11-25 14:01:38 +0000384 {
bart36556122008-03-13 19:24:30 +0000385 Addr b_start;
386 Addr b_end;
387 UWord b0;
388 const struct bitmap1* const p1 = &bm2->bm1;
389
390 if ((bm2->addr << ADDR0_BITS) < a1)
391 b_start = a1;
392 else
393 if ((bm2->addr << ADDR0_BITS) < a2)
394 b_start = (bm2->addr << ADDR0_BITS);
395 else
396 break;
397 tl_assert(a1 <= b_start && b_start <= a2);
398
399 if ((bm2->addr << ADDR0_BITS) + ADDR0_COUNT < a2)
400 b_end = (bm2->addr << ADDR0_BITS) + ADDR0_COUNT;
401 else
402 b_end = a2;
403 tl_assert(a1 <= b_end && b_end <= a2);
404 tl_assert(b_start < b_end);
405 tl_assert((b_start & ADDR0_MASK) <= ((b_end - 1) & ADDR0_MASK));
406
407 for (b0 = b_start & ADDR0_MASK; b0 <= ((b_end-1) & ADDR0_MASK); b0++)
408 {
409 if (access_type == eLoad)
410 {
411 if (bm0_is_set(p1->bm0_w, b0))
412 {
413 return True;
414 }
415 }
416 else
417 {
418 tl_assert(access_type == eStore);
419 if (bm0_is_set(p1->bm0_r, b0)
420 | bm0_is_set(p1->bm0_w, b0))
421 {
422 return True;
423 }
424 }
425 }
sewardjaf44c822007-11-25 14:01:38 +0000426 }
427 }
428 return False;
429}
430
bart36556122008-03-13 19:24:30 +0000431Bool bm_load_has_conflict_with(const struct bitmap* const bm,
432 const Addr a1, const Addr a2)
sewardjaf44c822007-11-25 14:01:38 +0000433{
bart36556122008-03-13 19:24:30 +0000434 return bm_has_conflict_with(bm, a1, a2, eLoad);
435}
436
437Bool bm_store_has_conflict_with(const struct bitmap* const bm,
438 const Addr a1, const Addr a2)
439{
440 return bm_has_conflict_with(bm, a1, a2, eStore);
sewardjaf44c822007-11-25 14:01:38 +0000441}
442
443void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2)
444{
445 OSet* const tmp = bm1->oset;
446 bm1->oset = bm2->oset;
447 bm2->oset = tmp;
448}
449
450void bm_merge2(struct bitmap* const lhs,
451 const struct bitmap* const rhs)
452{
453 struct bitmap2* bm2l;
454 const struct bitmap2* bm2r;
455
456 // First step: allocate any missing bitmaps in *lhs.
457 VG_(OSetGen_ResetIter)(rhs->oset);
458 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
459 {
460 bm2_lookup_or_insert(lhs, bm2r->addr);
461 }
462
463 VG_(OSetGen_ResetIter)(lhs->oset);
464 VG_(OSetGen_ResetIter)(rhs->oset);
465
466 for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
467 {
468 do
469 {
470 bm2l = VG_(OSetGen_Next)(lhs->oset);
sewardjaf44c822007-11-25 14:01:38 +0000471 } while (bm2l->addr < bm2r->addr);
472
473 tl_assert(bm2l->addr == bm2r->addr);
474
475 bm2_merge(bm2l, bm2r);
476 }
477}
478
479/**
480 * Report whether there are any RW / WR / WW patterns in lhs and rhs.
481 * @param lhs First bitmap.
482 * @param rhs Bitmap to be compared with lhs.
483 * @return !=0 if there are data races, == 0 if there are none.
484 */
485int bm_has_races(const struct bitmap* const lhs,
486 const struct bitmap* const rhs)
487{
488 VG_(OSetGen_ResetIter)(lhs->oset);
489 VG_(OSetGen_ResetIter)(rhs->oset);
490
491 for (;;)
492 {
493 const struct bitmap2* bm2l = VG_(OSetGen_Next)(lhs->oset);
494 const struct bitmap2* bm2r = VG_(OSetGen_Next)(rhs->oset);
495 const struct bitmap1* bm1l;
496 const struct bitmap1* bm1r;
497 unsigned k;
498
499 while (bm2l && bm2r && bm2l->addr != bm2r->addr)
500 {
501 if (bm2l->addr < bm2r->addr)
502 bm2l = VG_(OSetGen_Next)(lhs->oset);
503 else
504 bm2r = VG_(OSetGen_Next)(rhs->oset);
505 }
506 if (bm2l == 0 || bm2r == 0)
507 break;
508
509 bm1l = &bm2l->bm1;
510 bm1r = &bm2r->bm1;
511
512 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
513 {
514 unsigned b;
515 for (b = 0; b < BITS_PER_UWORD; b++)
516 {
517 UWord const access
518 = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
519 | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
520 | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
521 | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
522 Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
523 if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
524 {
525 return 1;
526 }
527 }
528 }
529 }
530 return 0;
531}
532
sewardjaf44c822007-11-25 14:01:38 +0000533void bm_print(const struct bitmap* const bm)
534{
535 struct bitmap2* bm2;
536
537 VG_(OSetGen_ResetIter)(bm->oset);
538
539 for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
540 {
541 const struct bitmap1* const bm1 = &bm2->bm1;
542 unsigned k;
543 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
544 {
545 unsigned b;
546 for (b = 0; b < BITS_PER_UWORD; b++)
547 {
548 int const r = bm1->bm0_r[k] & bm0_mask(b);
549 int const w = bm1->bm0_w[k] & bm0_mask(b);
550 Addr const a = MAKE_ADDRESS(bm2->addr, k * BITS_PER_UWORD | b);
551 if (r || w)
552 {
553 VG_(printf)("0x%08lx %c %c\n",
554 (Addr)(a),
555 w ? 'W' : ' ', r ? 'R' : ' ');
556 }
557 }
558 }
559 }
560}
561
562ULong bm_get_bitmap_creation_count(void)
563{
564 return s_bitmap_creation_count;
565}
566
567ULong bm_get_bitmap2_creation_count(void)
568{
569 return s_bitmap2_creation_count;
570}
571
572static void bm2_merge(struct bitmap2* const bm2l,
573 const struct bitmap2* const bm2r)
574{
575 unsigned k;
576
577 tl_assert(bm2l->addr == bm2r->addr);
578
579 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
580 {
581 bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
582 }
583 for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
584 {
585 bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
586 }
587}
588
589#if 0
590
591/* Unit test */
592static
593struct { Addr address; SizeT size; BmAccessTypeT access_type; }
594 s_args[] = {
595 { 0, 1, eLoad },
596 { 666, 4, eLoad },
597 { 667, 2, eStore },
598 { 1024, 1, eStore },
599 { 0x0000ffff, 1, eLoad },
600 { 0x0001ffff, 1, eLoad },
601 { 0x00ffffff, 1, eLoad },
602 { 0xffffffff, 1, eStore },
603 };
604
605void bm_test(void)
606{
607 struct bitmap* bm;
608 struct bitmap* bm2;
609 int i, j;
610
611 VG_(printf)("Start of DRD BM unit test.\n");
612
613 bm = bm_new();
614
615 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
616 {
bart9036dea2008-03-13 19:10:06 +0000617 bm_access_range(bm,
618 s_args[i].address,
619 s_args[i].address + s_args[i].size,
620 s_args[i].access_type);
sewardjaf44c822007-11-25 14:01:38 +0000621 }
622
623 VG_(printf)("Map contents -- should contain 10 addresses:\n");
624 bm_print(bm);
625
626 for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
627 {
628 for (j = 0; j < s_args[i].size; j++)
629 {
630 tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
631 }
632 }
633
634 VG_(printf)("Merge result:\n");
635 bm2 = bm_merge(bm, bm);
636 bm_print(bm);
637
638 bm_delete(bm);
639 bm_delete(bm2);
640
641 VG_(printf)("End of DRD BM unit test.\n");
642}
643#endif
644
645
646/*
647 * Local variables:
648 * c-basic-offset: 3
649 * End:
650 */