Skip to content

Commit 66d4ce7

Browse files
committed
tsan: new runtime (v3)
This change switches tsan to the new runtime which features: - 2x smaller shadow memory (2x of app memory) - faster fully vectorized race detection - small fixed-size vector clocks (512b) - fast vectorized vector clock operations - unlimited number of alive threads/goroutimes Depends on D112602. Reviewed By: melver Differential Revision: https://reviews.llvm.org/D112603
1 parent 71a7c55 commit 66d4ce7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2284
-2133
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class MUTEX ThreadRegistry {
104104
return threads_.empty() ? nullptr : threads_[tid];
105105
}
106106

107+
u32 NumThreadsLocked() const { return threads_.size(); }
108+
107109
u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);
108110

109111
typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);

compiler-rt/lib/tsan/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ set(TSAN_HEADERS
119119
rtl/tsan_symbolize.h
120120
rtl/tsan_sync.h
121121
rtl/tsan_trace.h
122-
rtl/tsan_update_shadow_word.inc
123122
rtl/tsan_vector_clock.h
124123
)
125124

compiler-rt/lib/tsan/check_analyze.sh

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,27 @@ check() {
3434
fi
3535
}
3636

37+
# All hot functions must contain no PUSH/POP
38+
# and no CALLs (everything is tail-called).
3739
for f in write1 write2 write4 write8; do
3840
check $f rsp 1
39-
check $f push 2
41+
check $f push 0
42+
check $f pop 0
43+
check $f call 0
4044
done
4145

4246
for f in read1 read2 read4 read8; do
4347
check $f rsp 1
44-
check $f push 3
48+
check $f push 0
49+
check $f pop 0
50+
check $f call 0
4551
done
4652

4753
for f in func_entry func_exit; do
4854
check $f rsp 0
4955
check $f push 0
5056
check $f pop 0
51-
check $f call 1 # TraceSwitch()
57+
check $f call 0
5258
done
5359

5460
echo LGTM

compiler-rt/lib/tsan/go/build.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type ^
1414
..\rtl\tsan_suppressions.cpp ^
1515
..\rtl\tsan_sync.cpp ^
1616
..\rtl\tsan_stack_trace.cpp ^
17+
..\rtl\tsan_vector_clock.cpp ^
1718
..\..\sanitizer_common\sanitizer_allocator.cpp ^
1819
..\..\sanitizer_common\sanitizer_common.cpp ^
1920
..\..\sanitizer_common\sanitizer_flags.cpp ^

compiler-rt/lib/tsan/go/buildgo.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ SRCS="
1919
../rtl/tsan_stack_trace.cpp
2020
../rtl/tsan_suppressions.cpp
2121
../rtl/tsan_sync.cpp
22+
../rtl/tsan_vector_clock.cpp
2223
../../sanitizer_common/sanitizer_allocator.cpp
2324
../../sanitizer_common/sanitizer_common.cpp
2425
../../sanitizer_common/sanitizer_common_libcdep.cpp

compiler-rt/lib/tsan/go/tsan_go.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ void __tsan_malloc(ThreadState *thr, uptr pc, uptr p, uptr sz) {
214214
}
215215

216216
void __tsan_free(uptr p, uptr sz) {
217-
ctx->metamap.FreeRange(get_cur_proc(), p, sz);
217+
ctx->metamap.FreeRange(get_cur_proc(), p, sz, false);
218218
}
219219

220220
void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {

compiler-rt/lib/tsan/rtl/tsan_defs.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ enum class Epoch : u16 {};
6363
constexpr uptr kEpochBits = 14;
6464
constexpr Epoch kEpochZero = static_cast<Epoch>(0);
6565
constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
66+
constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);
67+
68+
inline Epoch EpochInc(Epoch epoch) {
69+
return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
70+
}
71+
72+
inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }
6673

6774
const int kClkBits = 42;
6875
const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
@@ -107,7 +114,7 @@ const uptr kShadowCnt = 4;
107114
const uptr kShadowCell = 8;
108115

109116
// Single shadow value.
110-
typedef u64 RawShadow;
117+
enum class RawShadow : u32 {};
111118
const uptr kShadowSize = sizeof(RawShadow);
112119

113120
// Shadow memory is kShadowMultiplier times larger than user memory.
@@ -184,10 +191,13 @@ MD5Hash md5_hash(const void *data, uptr size);
184191
struct Processor;
185192
struct ThreadState;
186193
class ThreadContext;
194+
struct TidSlot;
187195
struct Context;
188196
struct ReportStack;
189197
class ReportDesc;
190198
class RegionAlloc;
199+
struct Trace;
200+
struct TracePart;
191201

192202
typedef uptr AccessType;
193203

@@ -198,6 +208,8 @@ enum : AccessType {
198208
kAccessVptr = 1 << 2, // read or write of an object virtual table pointer
199209
kAccessFree = 1 << 3, // synthetic memory access during memory freeing
200210
kAccessExternalPC = 1 << 4, // access PC can have kExternalPCBit set
211+
kAccessCheckOnly = 1 << 5, // check for races, but don't store
212+
kAccessNoRodata = 1 << 6, // don't check for .rodata marker
201213
};
202214

203215
// Descriptor of user's memory block.
@@ -219,16 +231,19 @@ enum ExternalTag : uptr {
219231
// as 16-bit values, see tsan_defs.h.
220232
};
221233

222-
enum MutexType {
223-
MutexTypeTrace = MutexLastCommon,
224-
MutexTypeReport,
234+
enum {
235+
MutexTypeReport = MutexLastCommon,
225236
MutexTypeSyncVar,
226237
MutexTypeAnnotations,
227238
MutexTypeAtExit,
228239
MutexTypeFired,
229240
MutexTypeRacy,
230241
MutexTypeGlobalProc,
231242
MutexTypeInternalAlloc,
243+
MutexTypeTrace,
244+
MutexTypeSlot,
245+
MutexTypeSlots,
246+
MutexTypeMultiSlot,
232247
};
233248

234249
} // namespace __tsan

compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ class DenseSlabAlloc {
104104
return atomic_load_relaxed(&fillpos_) * kL2Size * sizeof(T);
105105
}
106106

107+
template <typename Func>
108+
void ForEach(Func func) {
109+
SpinMutexLock lock(&mtx_);
110+
uptr fillpos = atomic_load_relaxed(&fillpos_);
111+
for (uptr l1 = 0; l1 < fillpos; l1++) {
112+
for (IndexT l2 = l1 == 0 ? 1 : 0; l2 < kL2Size; l2++) func(&map_[l1][l2]);
113+
}
114+
}
115+
107116
private:
108117
T *map_[kL1Size];
109118
SpinMutex mtx_;

compiler-rt/lib/tsan/rtl/tsan_flags.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,6 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
110110

111111
if (common_flags()->help) parser.PrintFlagDescriptions();
112112

113-
if (f->history_size < 0 || f->history_size > 7) {
114-
Printf("ThreadSanitizer: incorrect value for history_size"
115-
" (must be [0..7])\n");
116-
Die();
117-
}
118-
119113
if (f->io_sync < 0 || f->io_sync > 2) {
120114
Printf("ThreadSanitizer: incorrect value for io_sync"
121115
" (must be [0..2])\n");

compiler-rt/lib/tsan/rtl/tsan_flags.inc

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,10 @@ TSAN_FLAG(bool, stop_on_start, false,
5959
"Stops on start until __tsan_resume() is called (for debugging).")
6060
TSAN_FLAG(bool, running_on_valgrind, false,
6161
"Controls whether RunningOnValgrind() returns true or false.")
62-
// There are a lot of goroutines in Go, so we use smaller history.
6362
TSAN_FLAG(
64-
int, history_size, SANITIZER_GO ? 1 : 3,
65-
"Per-thread history size, controls how many previous memory accesses "
66-
"are remembered per thread. Possible values are [0..7]. "
67-
"history_size=0 amounts to 32K memory accesses. Each next value doubles "
68-
"the amount of memory accesses, up to history_size=7 that amounts to "
69-
"4M memory accesses. The default value is 2 (128K memory accesses).")
63+
uptr, history_size, 0,
64+
"Per-thread history size,"
65+
" controls how many extra previous memory accesses are remembered per thread.")
7066
TSAN_FLAG(int, io_sync, 1,
7167
"Controls level of synchronization implied by IO operations. "
7268
"0 - no synchronization "

0 commit comments

Comments
 (0)