Skip to content

Commit ab02680

Browse files
committed
tsan: fix a bug in trace part switching
Callers of TraceSwitchPart expect that TraceAcquire will always succeed after the call. It's possible that TryTraceFunc/TraceMutexLock in TraceSwitchPart that restore the current stack/mutexset filled the trace part exactly up to the TracePart::kAlignment gap and the next TraceAcquire won't succeed. Skip the alignment gap after writing initial stack/mutexset to avoid that. Reviewed By: melver Differential Revision: https://reviews.llvm.org/D129777
1 parent 58fec78 commit ab02680

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,15 @@ void TraceSwitchPartImpl(ThreadState* thr) {
951951
TraceMutexLock(thr, d.write ? EventType::kLock : EventType::kRLock, 0,
952952
d.addr, d.stack_id);
953953
}
954+
// Callers of TraceSwitchPart expect that TraceAcquire will always succeed
955+
// after the call. It's possible that TryTraceFunc/TraceMutexLock above
956+
// filled the trace part exactly up to the TracePart::kAlignment gap
957+
// and the next TraceAcquire won't succeed. Skip the gap to avoid that.
958+
EventFunc *ev;
959+
if (!TraceAcquire(thr, &ev)) {
960+
CHECK(TraceSkipGap(thr));
961+
CHECK(TraceAcquire(thr, &ev));
962+
}
954963
{
955964
Lock lock(&ctx->slot_mtx);
956965
// There is a small chance that the slot may be not queued at this point.

compiler-rt/lib/tsan/tests/unit/tsan_trace_test.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,18 @@ TRACE_TEST(Trace, MultiPart) {
243243
CHECK_EQ(mset.Get(1).count, 1);
244244
}
245245

246+
TRACE_TEST(Trace, DeepSwitch) {
247+
ThreadArray<1> thr;
248+
for (int i = 0; i < 2000; i++) {
249+
FuncEntry(thr, 0x1000);
250+
const uptr kEvents = sizeof(TracePart) / sizeof(Event);
251+
for (uptr i = 0; i < kEvents; i++) {
252+
TraceMutexLock(thr, EventType::kLock, 0x4000, 0x5000, 0x6000);
253+
TraceMutexUnlock(thr, 0x5000);
254+
}
255+
}
256+
}
257+
246258
void CheckTraceState(uptr count, uptr finished, uptr excess, uptr recycle) {
247259
Lock l(&ctx->slot_mtx);
248260
Printf("CheckTraceState(%zu/%zu, %zu/%zu, %zu/%zu, %zu/%zu)\n",

0 commit comments

Comments
 (0)