]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- tsan_update_shadow_word_inl.h ---------------------------*- C++ -*-===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file is a part of ThreadSanitizer (TSan), a race detector. | |
11 | // | |
12 | // Body of the hottest inner loop. | |
13 | // If we wrap this body into a function, compilers (both gcc and clang) | |
14 | // produce sligtly less efficient code. | |
15 | //===----------------------------------------------------------------------===// | |
16 | do { | |
17 | StatInc(thr, StatShadowProcessed); | |
18 | const unsigned kAccessSize = 1 << kAccessSizeLog; | |
92a42be0 | 19 | u64 *sp = &shadow_mem[idx]; |
1a4d82fc JJ |
20 | old = LoadShadow(sp); |
21 | if (old.IsZero()) { | |
22 | StatInc(thr, StatShadowZero); | |
23 | if (store_word) | |
24 | StoreIfNotYetStored(sp, &store_word); | |
25 | // The above StoreIfNotYetStored could be done unconditionally | |
26 | // and it even shows 4% gain on synthetic benchmarks (r4307). | |
27 | break; | |
28 | } | |
29 | // is the memory access equal to the previous? | |
30 | if (Shadow::Addr0AndSizeAreEqual(cur, old)) { | |
31 | StatInc(thr, StatShadowSameSize); | |
32 | // same thread? | |
33 | if (Shadow::TidsAreEqual(old, cur)) { | |
34 | StatInc(thr, StatShadowSameThread); | |
1a4d82fc JJ |
35 | if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic)) |
36 | StoreIfNotYetStored(sp, &store_word); | |
37 | break; | |
38 | } | |
39 | StatInc(thr, StatShadowAnotherThread); | |
40 | if (HappensBefore(old, thr)) { | |
92a42be0 SL |
41 | if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic)) |
42 | StoreIfNotYetStored(sp, &store_word); | |
1a4d82fc JJ |
43 | break; |
44 | } | |
45 | if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic)) | |
46 | break; | |
47 | goto RACE; | |
48 | } | |
49 | // Do the memory access intersect? | |
50 | if (Shadow::TwoRangesIntersect(old, cur, kAccessSize)) { | |
51 | StatInc(thr, StatShadowIntersect); | |
52 | if (Shadow::TidsAreEqual(old, cur)) { | |
53 | StatInc(thr, StatShadowSameThread); | |
54 | break; | |
55 | } | |
56 | StatInc(thr, StatShadowAnotherThread); | |
57 | if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic)) | |
58 | break; | |
59 | if (HappensBefore(old, thr)) | |
60 | break; | |
61 | goto RACE; | |
62 | } | |
63 | // The accesses do not intersect. | |
64 | StatInc(thr, StatShadowNotIntersect); | |
65 | break; | |
66 | } while (0); |