Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tsanv3 #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class MUTEX ThreadRegistry {
return threads_.empty() ? nullptr : threads_[tid];
}

u32 NumThreadsLocked() const { return threads_.size(); }

u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);

typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
Expand Down
1 change: 0 additions & 1 deletion compiler-rt/lib/tsan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ set(TSAN_HEADERS
rtl/tsan_symbolize.h
rtl/tsan_sync.h
rtl/tsan_trace.h
rtl/tsan_update_shadow_word.inc
rtl/tsan_vector_clock.h
)

Expand Down
12 changes: 9 additions & 3 deletions compiler-rt/lib/tsan/check_analyze.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,27 @@ check() {
fi
}

# All hot functions must contain no PUSH/POP
# and no CALLs (everything is tail-called).
for f in write1 write2 write4 write8; do
check $f rsp 1
check $f push 2
check $f push 0
check $f pop 0
check $f call 0
done

for f in read1 read2 read4 read8; do
check $f rsp 1
check $f push 3
check $f push 0
check $f pop 0
check $f call 0
done

for f in func_entry func_exit; do
check $f rsp 0
check $f push 0
check $f pop 0
check $f call 1 # TraceSwitch()
check $f call 0
done

echo LGTM
1 change: 1 addition & 0 deletions compiler-rt/lib/tsan/go/build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type ^
..\rtl\tsan_suppressions.cpp ^
..\rtl\tsan_sync.cpp ^
..\rtl\tsan_stack_trace.cpp ^
..\rtl\tsan_vector_clock.cpp ^
..\..\sanitizer_common\sanitizer_allocator.cpp ^
..\..\sanitizer_common\sanitizer_common.cpp ^
..\..\sanitizer_common\sanitizer_flags.cpp ^
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/tsan/go/buildgo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ SRCS="
../rtl/tsan_stack_trace.cpp
../rtl/tsan_suppressions.cpp
../rtl/tsan_sync.cpp
../rtl/tsan_vector_clock.cpp
../../sanitizer_common/sanitizer_allocator.cpp
../../sanitizer_common/sanitizer_common.cpp
../../sanitizer_common/sanitizer_common_libcdep.cpp
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/lib/tsan/go/tsan_go.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ void __tsan_malloc(ThreadState *thr, uptr pc, uptr p, uptr sz) {
}

void __tsan_free(uptr p, uptr sz) {
ctx->metamap.FreeRange(get_cur_proc(), p, sz);
ctx->metamap.FreeRange(get_cur_proc(), p, sz, false);
}

void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
Expand Down
23 changes: 19 additions & 4 deletions compiler-rt/lib/tsan/rtl/tsan_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ enum class Epoch : u16 {};
constexpr uptr kEpochBits = 14;
constexpr Epoch kEpochZero = static_cast<Epoch>(0);
constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);

inline Epoch EpochInc(Epoch epoch) {
return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
}

inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }

const int kClkBits = 42;
const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
Expand Down Expand Up @@ -107,7 +114,7 @@ const uptr kShadowCnt = 4;
const uptr kShadowCell = 8;

// Single shadow value.
typedef u64 RawShadow;
enum class RawShadow : u32 {};
const uptr kShadowSize = sizeof(RawShadow);

// Shadow memory is kShadowMultiplier times larger than user memory.
Expand Down Expand Up @@ -184,10 +191,13 @@ MD5Hash md5_hash(const void *data, uptr size);
struct Processor;
struct ThreadState;
class ThreadContext;
struct TidSlot;
struct Context;
struct ReportStack;
class ReportDesc;
class RegionAlloc;
struct Trace;
struct TracePart;

typedef uptr AccessType;

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

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

enum MutexType {
MutexTypeTrace = MutexLastCommon,
MutexTypeReport,
enum {
MutexTypeReport = MutexLastCommon,
MutexTypeSyncVar,
MutexTypeAnnotations,
MutexTypeAtExit,
MutexTypeFired,
MutexTypeRacy,
MutexTypeGlobalProc,
MutexTypeInternalAlloc,
MutexTypeTrace,
MutexTypeSlot,
MutexTypeSlots,
MutexTypeMultiSlot,
};

} // namespace __tsan
Expand Down
9 changes: 9 additions & 0 deletions compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ class DenseSlabAlloc {
return atomic_load_relaxed(&fillpos_) * kL2Size * sizeof(T);
}

template <typename Func>
void ForEach(Func func) {
SpinMutexLock lock(&mtx_);
uptr fillpos = atomic_load_relaxed(&fillpos_);
for (uptr l1 = 0; l1 < fillpos; l1++) {
for (IndexT l2 = l1 == 0 ? 1 : 0; l2 < kL2Size; l2++) func(&map_[l1][l2]);
}
}

private:
T *map_[kL1Size];
SpinMutex mtx_;
Expand Down
6 changes: 0 additions & 6 deletions compiler-rt/lib/tsan/rtl/tsan_flags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,6 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {

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

if (f->history_size < 0 || f->history_size > 7) {
Printf("ThreadSanitizer: incorrect value for history_size"
" (must be [0..7])\n");
Die();
}

if (f->io_sync < 0 || f->io_sync > 2) {
Printf("ThreadSanitizer: incorrect value for io_sync"
" (must be [0..2])\n");
Expand Down
10 changes: 3 additions & 7 deletions compiler-rt/lib/tsan/rtl/tsan_flags.inc
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,10 @@ TSAN_FLAG(bool, stop_on_start, false,
"Stops on start until __tsan_resume() is called (for debugging).")
TSAN_FLAG(bool, running_on_valgrind, false,
"Controls whether RunningOnValgrind() returns true or false.")
// There are a lot of goroutines in Go, so we use smaller history.
TSAN_FLAG(
int, history_size, SANITIZER_GO ? 1 : 3,
"Per-thread history size, controls how many previous memory accesses "
"are remembered per thread. Possible values are [0..7]. "
"history_size=0 amounts to 32K memory accesses. Each next value doubles "
"the amount of memory accesses, up to history_size=7 that amounts to "
"4M memory accesses. The default value is 2 (128K memory accesses).")
uptr, history_size, 0,
"Per-thread history size,"
" controls how many extra previous memory accesses are remembered per thread.")
TSAN_FLAG(int, io_sync, 1,
"Controls level of synchronization implied by IO operations. "
"0 - no synchronization "
Expand Down
3 changes: 2 additions & 1 deletion compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1981,6 +1981,7 @@ static void ReportErrnoSpoiling(ThreadState *thr, uptr pc) {
static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
int sig, __sanitizer_siginfo *info,
void *uctx) {
CHECK(thr->slot);
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
if (acquire)
Acquire(thr, 0, (uptr)&sigactions[sig]);
Expand Down Expand Up @@ -2268,7 +2269,7 @@ struct dl_iterate_phdr_data {
};

static bool IsAppNotRodata(uptr addr) {
return IsAppMem(addr) && *MemToShadow(addr) != kShadowRodata;
return IsAppMem(addr) && *MemToShadow(addr) != Shadow::kRodata;
}

static int dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
Expand Down
87 changes: 46 additions & 41 deletions compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,9 @@ static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) {
T v = NoTsanAtomicLoad(a, mo);
SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a);
if (s) {
ReadLock l(&s->mtx);
AcquireImpl(thr, pc, &s->clock);
SlotLocker locker(thr);
ReadLock lock(&s->mtx);
thr->clock.Acquire(s->clock);
// Re-read under sync mutex because we need a consistent snapshot
// of the value and the clock we acquire.
v = NoTsanAtomicLoad(a, mo);
Expand Down Expand Up @@ -270,33 +271,36 @@ static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
NoTsanAtomicStore(a, v, mo);
return;
}
__sync_synchronize();
SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
Lock l(&s->mtx);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
ReleaseStoreImpl(thr, pc, &s->clock);
NoTsanAtomicStore(a, v, mo);
SlotLocker locker(thr);
{
auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
Lock lock(&s->mtx);
thr->clock.ReleaseStore(&s->clock);
NoTsanAtomicStore(a, v, mo);
}
IncrementEpoch(thr);
}

template <typename T, T (*F)(volatile T *v, T op)>
static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
if (LIKELY(mo == mo_relaxed))
return F(a, v);
SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
Lock l(&s->mtx);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
if (IsAcqRelOrder(mo))
AcquireReleaseImpl(thr, pc, &s->clock);
else if (IsReleaseOrder(mo))
ReleaseImpl(thr, pc, &s->clock);
else if (IsAcquireOrder(mo))
AcquireImpl(thr, pc, &s->clock);
return F(a, v);
SlotLocker locker(thr);
{
auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
RWLock lock(&s->mtx, IsReleaseOrder(mo));
if (IsAcqRelOrder(mo))
thr->clock.ReleaseAcquire(&s->clock);
else if (IsReleaseOrder(mo))
thr->clock.Release(&s->clock);
else if (IsAcquireOrder(mo))
thr->clock.Acquire(s->clock);
v = F(a, v);
}
if (IsReleaseOrder(mo))
IncrementEpoch(thr);
return v;
}

template<typename T>
Expand Down Expand Up @@ -416,27 +420,28 @@ static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,
*c = pr;
return false;
}

SlotLocker locker(thr);
bool release = IsReleaseOrder(mo);
SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
RWLock l(&s->mtx, release);
T cc = *c;
T pr = func_cas(a, cc, v);
bool success = pr == cc;
if (!success) {
*c = pr;
mo = fmo;
bool success;
{
auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
RWLock lock(&s->mtx, release);
T cc = *c;
T pr = func_cas(a, cc, v);
success = pr == cc;
if (!success) {
*c = pr;
mo = fmo;
}
if (success && IsAcqRelOrder(mo))
thr->clock.ReleaseAcquire(&s->clock);
else if (success && IsReleaseOrder(mo))
thr->clock.Release(&s->clock);
else if (IsAcquireOrder(mo))
thr->clock.Acquire(s->clock);
}
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);

if (success && IsAcqRelOrder(mo))
AcquireReleaseImpl(thr, pc, &s->clock);
else if (success && IsReleaseOrder(mo))
ReleaseImpl(thr, pc, &s->clock);
else if (IsAcquireOrder(mo))
AcquireImpl(thr, pc, &s->clock);
if (success && release)
IncrementEpoch(thr);
return success;
}

Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void __tsan_java_free(jptr ptr, jptr size) {
DCHECK_GE(ptr, jctx->heap_begin);
DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);

ctx->metamap.FreeRange(thr->proc(), ptr, size);
ctx->metamap.FreeRange(thr->proc(), ptr, size, false);
}

void __tsan_java_move(jptr src, jptr dst, jptr size) {
Expand All @@ -133,7 +133,7 @@ void __tsan_java_move(jptr src, jptr dst, jptr size) {
// support that anymore as it contains addresses of accesses.
RawShadow *d = MemToShadow(dst);
RawShadow *dend = MemToShadow(dst + size);
internal_memset(d, 0, (dend - d) * sizeof(*d));
ShadowSet(d, dend, Shadow::kEmpty);
}

jptr __tsan_java_find(jptr *from_ptr, jptr to) {
Expand Down
Loading