#pragma once #include "defaults.h" extern "C" { // sanitizers API #if defined(_asan_enabled_) void __lsan_ignore_object(const void* p); #endif #if defined(_msan_enabled_) void __msan_unpoison(const volatile void* a, size_t size); void __msan_poison(const volatile void* a, size_t size); void __msan_check_mem_is_initialized(const volatile void* x, size_t size); #endif #if defined(_tsan_enabled_) void __tsan_acquire(void* a); void __tsan_release(void* a); #endif } // sanitizers API namespace NSan { class TFiberContext { public: TFiberContext() noexcept; TFiberContext(const void* stack, size_t len, const char* contName) noexcept; ~TFiberContext() noexcept; void BeforeFinish() noexcept; void BeforeSwitch(TFiberContext* old) noexcept; void AfterSwitch() noexcept; static void AfterStart() noexcept; private: void* Token_; const void* Stack_; size_t Len_; const bool IsMainFiber_; #if defined(_tsan_enabled_) void* const CurrentTSanFiberContext_; #endif }; // Returns plain if no sanitizer enabled or sanitized otherwise // Ment to be used in test code for constants (timeouts, etc) template <typename T> inline constexpr static T PlainOrUnderSanitizer(T plain, T sanitized) noexcept { #if defined(_tsan_enabled_) || defined(_msan_enabled_) || defined(_asan_enabled_) Y_UNUSED(plain); return sanitized; #else Y_UNUSED(sanitized); return plain; #endif } // Determines if asan present inline constexpr static bool ASanIsOn() noexcept { #if defined(_asan_enabled_) return true; #else return false; #endif } // Determines if tsan present inline constexpr static bool TSanIsOn() noexcept { #if defined(_tsan_enabled_) return true; #else return false; #endif } // Determines if msan present inline constexpr static bool MSanIsOn() noexcept { #if defined(_msan_enabled_) return true; #else return false; #endif } // Make memory region fully initialized (without changing its contents). inline static void Unpoison(const volatile void* a, size_t size) noexcept { #if defined(_msan_enabled_) __msan_unpoison(a, size); #else Y_UNUSED(a); Y_UNUSED(size); #endif } // Make memory region fully uninitialized (without changing its contents). // This is a legacy interface that does not update origin information. Use __msan_allocated_memory() instead. inline static void Poison(const volatile void* a, size_t size) noexcept { #if defined(_msan_enabled_) __msan_poison(a, size); #else Y_UNUSED(a); Y_UNUSED(size); #endif } // Checks that memory range is fully initialized, and reports an error if it is not. inline static void CheckMemIsInitialized(const volatile void* a, size_t size) noexcept { #if defined(_msan_enabled_) __msan_check_mem_is_initialized(a, size); #else Y_UNUSED(a); Y_UNUSED(size); #endif } inline static void MarkAsIntentionallyLeaked(const void* ptr) noexcept { #if defined(_asan_enabled_) __lsan_ignore_object(ptr); #else Y_UNUSED(ptr); #endif } #if defined(_tsan_enabled_) // defined in .cpp to avoid exposing problematic C-linkage version of AnnotateBenignRaceSized(...) void AnnotateBenignRaceSized(const char* file, int line, const volatile void* address, size_t size, const char* description) noexcept; #else inline static void AnnotateBenignRaceSized(const char* file, int line, const volatile void* address, size_t size, const char* description) noexcept { Y_UNUSED(file); Y_UNUSED(line); Y_UNUSED(address); Y_UNUSED(size); Y_UNUSED(description); } #endif inline static void Acquire(void* a) { #if defined(_tsan_enabled_) __tsan_acquire(a); #else Y_UNUSED(a); #endif } inline static void Release(void* a) { #if defined(_tsan_enabled_) __tsan_release(a); #else Y_UNUSED(a); #endif } }