llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-compiler-rt-sanitizer Author: Naveen Seth Hanig (naveen-seth) <details> <summary>Changes</summary> This introduces a lightweight ThreadSanitizer submode that focuses exclusively on lock correctness validation, enabled by `-fsanitize=thread-deadlock`. The motivation behind this is to allow lock-order inversion and mutex misuse detection without enabling data-race detection. This is useful for: - Programs that exceed regular TSan's shadow memory address space constraints - Combining with other sanitizers incompatible with TSan because of the shadow memory mappings. (This works with MSan.) - Platforms where regular TSan is not supported - Users who are only interested in lock-correctness but not in data-races. This is implemented as a separate standalone runtime, as the regular TSan runtime intertwines its lock tracking with SyncVar objects in shadow memory. A follow up patch will remove the old tsan/dd, which was never wired to the compiler and is effectively unmaintained/dead code. This follows the RFC: https://discourse.llvm.org/t/rfc-add-update-tsan-submode-for-lock-correctness-validation-only/91319?u=naveen-seth --- Patch is 55.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/212748.diff 25 Files Affected: - (modified) clang/include/clang/Basic/Sanitizers.def (+3) - (modified) clang/include/clang/Driver/SanitizerArgs.h (+3) - (modified) clang/lib/CodeGen/BackendUtil.cpp (+9) - (modified) clang/lib/Driver/SanitizerArgs.cpp (+3-1) - (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+4) - (modified) clang/lib/Driver/ToolChains/Linux.cpp (+1) - (modified) compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake (+1) - (modified) compiler-rt/cmake/config-ix.cmake (+9-1) - (modified) compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h (+3) - (added) compiler-rt/lib/tsan_deadlock/CMakeLists.txt (+76) - (added) compiler-rt/lib/tsan_deadlock/tsan_deadlock_interceptors.cpp (+398) - (added) compiler-rt/lib/tsan_deadlock/tsan_deadlock_interface.cpp (+36) - (added) compiler-rt/lib/tsan_deadlock/tsan_deadlock_rtl.cpp (+339) - (added) compiler-rt/lib/tsan_deadlock/tsan_deadlock_rtl.h (+102) - (added) compiler-rt/test/tsan_deadlock/CMakeLists.txt (+29) - (added) compiler-rt/test/tsan_deadlock/lit.cfg.py (+47) - (added) compiler-rt/test/tsan_deadlock/lit.site.cfg.py.in (+12) - (added) compiler-rt/test/tsan_deadlock/mutex_bad_unlock.cpp (+26) - (added) compiler-rt/test/tsan_deadlock/mutex_cycle2.cpp (+31) - (added) compiler-rt/test/tsan_deadlock/mutex_cycle_long.c (+44) - (added) compiler-rt/test/tsan_deadlock/mutex_destroy_locked.cpp (+20) - (added) compiler-rt/test/tsan_deadlock/mutex_destroy_locked2.cpp (+27) - (added) compiler-rt/test/tsan_deadlock/mutex_double_lock.cpp (+17) - (modified) llvm/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h (+15-1) - (modified) llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp (+12-7) ``````````diff diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index da85431625026..fcb43dc31fcdc 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -79,6 +79,9 @@ SANITIZER("type", Type) // ThreadSanitizer SANITIZER("thread", Thread) +// DeadlockSanitizer (ThreadSanitizer, with only the deadlock detection.) +SANITIZER("thread-deadlock", ThreadDeadlock) + // Numerical stability sanitizer. SANITIZER("numerical", NumericalStability) diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 6a01b3e36d44c..7b7f738d91131 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -104,6 +104,9 @@ class SanitizerArgs { } bool needsTysanRt() const { return Sanitizers.has(SanitizerKind::Type); } bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); } + bool needsDeadlockRt() const { + return Sanitizers.has(SanitizerKind::ThreadDeadlock); + } bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); } bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); } bool needsLsanRt() const { diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 2b755fa916e55..ce9740554a348 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -741,6 +741,15 @@ static void addSanitizers(const Triple &TargetTriple, MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } + if (LangOpts.Sanitize.has(SanitizerKind::ThreadDeadlock)) { + MPM.addPass(ModuleThreadSanitizerPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass( + ThreadSanitizerOptions{/*InstrumentMemoryAccesses=*/false, + /*InstrumentAtomics=*/false, + /*InstrumentMemIntrinsics=*/false, + /*AlwaysInstrumentFuncEntryExit=*/true}))); + } + if (LangOpts.Sanitize.has(SanitizerKind::Type)) MPM.addPass(TypeSanitizerPass()); diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index c77ba78122a81..3c3bc84eacd3f 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -40,7 +40,8 @@ static const SanitizerMask NotAllowedWithExecuteOnly = SanitizerKind::Function | SanitizerKind::KCFI; static const SanitizerMask NeedsUnwindTables = SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type | - SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow | + SanitizerKind::Thread | SanitizerKind::ThreadDeadlock | + SanitizerKind::Memory | SanitizerKind::DataFlow | SanitizerKind::NumericalStability; static const SanitizerMask SupportsCoverage = SanitizerKind::Address | SanitizerKind::HWAddress | @@ -707,6 +708,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, SanitizerKind::Memory | SanitizerKind::Leak | SanitizerKind::Thread), std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory), + std::make_pair(SanitizerKind::Thread, SanitizerKind::ThreadDeadlock), std::make_pair(SanitizerKind::Leak, SanitizerKind::Thread | SanitizerKind::Memory), std::make_pair(SanitizerKind::KernelAddress, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 08c06951cf220..d7acfacd17b05 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1655,6 +1655,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, } if (SanArgs.needsTsanRt()) SharedRuntimes.push_back("tsan"); + if (SanArgs.needsDeadlockRt()) + SharedRuntimes.push_back("tsan_deadlock"); if (SanArgs.needsTysanRt()) SharedRuntimes.push_back("tysan"); if (SanArgs.needsHwasanRt()) { @@ -1729,6 +1731,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("tsan_cxx"); } + if (!SanArgs.needsSharedRt() && SanArgs.needsDeadlockRt()) + StaticRuntimes.push_back("tsan_deadlock"); if (!SanArgs.needsSharedRt() && SanArgs.needsTysanRt()) StaticRuntimes.push_back("tysan"); if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) { diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 6dca14d8bf0a8..ab9257362cea1 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -1001,6 +1001,7 @@ Linux::getSupportedSanitizers(BoundArch BA, if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ || IsLoongArch64 || IsRISCV64) Res |= SanitizerKind::Thread; + Res |= SanitizerKind::ThreadDeadlock; if (IsX86_64 || IsAArch64 || IsSystemZ || IsHexagon) Res |= SanitizerKind::Type; if (IsX86_64 || IsSystemZ || IsPowerPC64) diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index 9c9874d94a1f2..5eebb98cda68a 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -52,6 +52,7 @@ set(ALL_ASAN_ABI_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM64_32}) set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${LOONGARCH64} ${S390X}) set(ALL_RTSAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${HEXAGON}) +set(ALL_TSAN_DEADLOCK_SUPPORTED_ARCH ${ALL_SANITIZER_COMMON_SUPPORTED_ARCH}) if(ANDROID) set(OS_NAME "Android") diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 083f1c98d0f16..d0ef92ed6d446 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -476,6 +476,7 @@ if(APPLE) set(SANITIZER_COMMON_SUPPORTED_OS osx) set(PROFILE_SUPPORTED_OS osx) set(TSAN_SUPPORTED_OS osx) + set(TSAN_DEADLOCK_SUPPORTED_OS osx) set(TYSAN_SUPPORTED_OS osx) set(XRAY_SUPPORTED_OS osx) set(FUZZER_SUPPORTED_OS osx) @@ -575,6 +576,7 @@ if(APPLE) list(APPEND SANITIZER_COMMON_SUPPORTED_OS ${platform}sim) list(APPEND PROFILE_SUPPORTED_OS ${platform}sim) list(APPEND TSAN_SUPPORTED_OS ${platform}sim) + list(APPEND TSAN_DEADLOCK_SUPPORTED_OS ${platform}sim) list(APPEND FUZZER_SUPPORTED_OS ${platform}sim) list(APPEND ORC_SUPPORTED_OS ${platform}sim) list(APPEND UBSAN_SUPPORTED_OS ${platform}sim) @@ -608,6 +610,7 @@ if(APPLE) list_intersect(DARWIN_${platform}_TSAN_ARCHS DARWIN_${platform}_ARCHS ALL_TSAN_SUPPORTED_ARCH) if(DARWIN_${platform}_TSAN_ARCHS) list(APPEND TSAN_SUPPORTED_OS ${platform}) + list(APPEND TSAN_DEADLOCK_SUPPORTED_OS ${platform}) endif() list(APPEND FUZZER_SUPPORTED_OS ${platform}) list(APPEND ORC_SUPPORTED_OS ${platform}) @@ -677,6 +680,9 @@ if(APPLE) list_intersect(TSAN_SUPPORTED_ARCH ALL_TSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) + list_intersect(TSAN_DEADLOCK_SUPPORTED_ARCH + ALL_TSAN_DEADLOCK_SUPPORTED_ARCH + SANITIZER_COMMON_SUPPORTED_ARCH) list_intersect(UBSAN_SUPPORTED_ARCH ALL_UBSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) @@ -726,6 +732,7 @@ else() filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH}) filter_available_targets(CTX_PROFILE_SUPPORTED_ARCH ${ALL_CTX_PROFILE_SUPPORTED_ARCH}) filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH}) + filter_available_targets(TSAN_DEADLOCK_SUPPORTED_ARCH ${ALL_TSAN_DEADLOCK_SUPPORTED_ARCH}) filter_available_targets(TYSAN_SUPPORTED_ARCH ${ALL_TYSAN_SUPPORTED_ARCH}) filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH}) filter_available_targets(SAFESTACK_SUPPORTED_ARCH @@ -765,7 +772,7 @@ if(COMPILER_RT_SUPPORTED_ARCH) endif() message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}") -set(ALL_SANITIZERS asan;rtsan;dfsan;msan;hwasan;tsan;tysan;safestack;cfi;scudo_standalone;ubsan_minimal;gwp_asan;nsan;asan_abi) +set(ALL_SANITIZERS asan;rtsan;dfsan;msan;hwasan;tsan;tsan_deadlock;tysan;safestack;cfi;scudo_standalone;ubsan_minimal;gwp_asan;nsan;asan_abi) set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING "sanitizers to build if supported on the target (all;${ALL_SANITIZERS})") list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}") @@ -879,6 +886,7 @@ if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH) else() set(COMPILER_RT_HAS_TSAN FALSE) endif() +set(COMPILER_RT_HAS_TSAN_DEADLOCK ${COMPILER_RT_HAS_TSAN}) if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS") set(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME TRUE) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h index c694897b6556b..8d30a4e2f044c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -500,5 +500,8 @@ using namespace __sanitizer; namespace __memprof { using namespace __sanitizer; } +namespace __tsan_deadlock { +using namespace __sanitizer; +} #endif // SANITIZER_DEFS_H diff --git a/compiler-rt/lib/tsan_deadlock/CMakeLists.txt b/compiler-rt/lib/tsan_deadlock/CMakeLists.txt new file mode 100644 index 0000000000000..74fc0f8bdb1cb --- /dev/null +++ b/compiler-rt/lib/tsan_deadlock/CMakeLists.txt @@ -0,0 +1,76 @@ +# Build for the DeadlockSanitizer runtime support library. + +include_directories(..) + +set(TSAN_DEADLOCK_SOURCES + tsan_deadlock_rtl.cpp + tsan_deadlock_interceptors.cpp + tsan_deadlock_interface.cpp) + +set(TSAN_DEADLOCK_HEADERS + tsan_deadlock_rtl.h) + +set(TSAN_DEADLOCK_CFLAGS ${SANITIZER_COMMON_CFLAGS}) +append_rtti_flag(OFF TSAN_DEADLOCK_CFLAGS) + +set(TSAN_DEADLOCK_DYNAMIC_LINK_LIBS + ${COMPILER_RT_UNWINDER_LINK_LIBS} + ${SANITIZER_CXX_ABI_LIBRARIES} + ${SANITIZER_COMMON_LINK_LIBS}) + +append_list_if(COMPILER_RT_HAS_LIBDL dl TSAN_DEADLOCK_DYNAMIC_LINK_LIBS) +append_list_if(COMPILER_RT_HAS_LIBM m TSAN_DEADLOCK_DYNAMIC_LINK_LIBS) +append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread TSAN_DEADLOCK_DYNAMIC_LINK_LIBS) + +add_compiler_rt_component(tsan_deadlock) + +if(APPLE) + add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) + + add_compiler_rt_runtime(clang_rt.tsan_deadlock + SHARED + OS ${TSAN_DEADLOCK_SUPPORTED_OS} + ARCHS ${TSAN_DEADLOCK_SUPPORTED_ARCH} + SOURCES ${TSAN_DEADLOCK_SOURCES} + ADDITIONAL_HEADERS ${TSAN_DEADLOCK_HEADERS} + OBJECT_LIBS RTInterception + RTSanitizerCommon + RTSanitizerCommonLibc + RTSanitizerCommonCoverage + RTSanitizerCommonSymbolizer + CFLAGS ${TSAN_DEADLOCK_CFLAGS} + LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} + LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS} + PARENT_TARGET tsan_deadlock) +else() + foreach(arch ${TSAN_DEADLOCK_SUPPORTED_ARCH}) + add_compiler_rt_runtime(clang_rt.tsan_deadlock + STATIC + ARCHS ${arch} + SOURCES ${TSAN_DEADLOCK_SOURCES} + $<TARGET_OBJECTS:RTInterception.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonSymbolizerInternal.${arch}> + ADDITIONAL_HEADERS ${TSAN_DEADLOCK_HEADERS} + CFLAGS ${TSAN_DEADLOCK_CFLAGS} + PARENT_TARGET tsan_deadlock) + add_compiler_rt_runtime(clang_rt.tsan_deadlock + SHARED + ARCHS ${arch} + SOURCES ${TSAN_DEADLOCK_SOURCES} + $<TARGET_OBJECTS:RTInterception.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonSymbolizerInternal.${arch}> + ADDITIONAL_HEADERS ${TSAN_DEADLOCK_HEADERS} + CFLAGS ${TSAN_DEADLOCK_CFLAGS} + LINK_LIBS ${TSAN_DEADLOCK_DYNAMIC_LINK_LIBS} + LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} + PARENT_TARGET tsan_deadlock) + endforeach() +endif() diff --git a/compiler-rt/lib/tsan_deadlock/tsan_deadlock_interceptors.cpp b/compiler-rt/lib/tsan_deadlock/tsan_deadlock_interceptors.cpp new file mode 100644 index 0000000000000..51ed3a22e2d9d --- /dev/null +++ b/compiler-rt/lib/tsan_deadlock/tsan_deadlock_interceptors.cpp @@ -0,0 +1,398 @@ +//===-- tsan_deadlock_interceptors.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of DeadlockSanitizer. +// +//===----------------------------------------------------------------------===// + +#include <pthread.h> + +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_allocator_internal.h" +#include "sanitizer_common/sanitizer_errno.h" +#include "sanitizer_common/sanitizer_glibc_version.h" +#include "sanitizer_common/sanitizer_stacktrace.h" +#include "tsan_deadlock_rtl.h" + +using namespace __tsan_deadlock; + +__attribute__((tls_model("initial-exec"))) static __thread volatile int initing; +static bool inited; + +static bool InitThread() { + if (initing) + return false; + if (cur_thread()) + return true; + initing = true; + if (!inited) { + inited = true; + Initialize(); + } + ThreadInit(&thr_tls); + initing = false; + return true; +} + +struct ThreadArg { + void *(*fn)(void *); + void *arg; +}; + +static void *ThreadTrampoline(void *arg) { + ThreadArg *targ = static_cast<ThreadArg *>(arg); + void *(*fn)(void *) = targ->fn; + void *fn_arg = targ->arg; + InternalFree(targ); + ThreadInit(&thr_tls); + void *retval = fn(fn_arg); + // Also called from the pthread_exit interceptor; guard with is_inited to + // stay idempotent. + if (thr_tls.is_inited) + ThreadDestroy(&thr_tls); + return retval; +} + +INTERCEPTOR(int, pthread_create, pthread_t *th, const pthread_attr_t *attr, + void *(*fn)(void *), void *arg) { + InitThread(); + ThreadArg *targ = static_cast<ThreadArg *>(InternalAlloc(sizeof(ThreadArg))); + targ->fn = fn; + targ->arg = arg; + return REAL(pthread_create)(th, attr, ThreadTrampoline, targ); +} + +INTERCEPTOR(int, pthread_join, pthread_t t, void **retval) { + InitThread(); + return REAL(pthread_join)(t, retval); +} + +INTERCEPTOR(void, pthread_exit, void *retval) { + if (thr_tls.is_inited) + ThreadDestroy(&thr_tls); + REAL(pthread_exit)(retval); +} + +INTERCEPTOR(int, pthread_mutex_init, pthread_mutex_t *m, + const pthread_mutexattr_t *attr) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_mutex_init)(m, attr); + if (res == 0) { + bool reentrant = false; + if (attr) { + int type = 0; + if (pthread_mutexattr_gettype(attr, &type) == 0) + reentrant = (type == PTHREAD_MUTEX_RECURSIVE); + } + MutexInit(cur_thread(), (uptr)m, reentrant, pc); + } + return res; +} + +INTERCEPTOR(int, pthread_mutex_destroy, pthread_mutex_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_mutex_destroy)(m); + if (res == 0 || res == errno_EBUSY) + MutexDestroy(cur_thread(), (uptr)m, pc); + return res; +} + +INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + MutexBeforeLock(cur_thread(), (uptr)m, true, pc); + int res = REAL(pthread_mutex_lock)(m); + MutexAfterLock(cur_thread(), (uptr)m, true, false, pc); + return res; +} + +INTERCEPTOR(int, pthread_mutex_trylock, pthread_mutex_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_mutex_trylock)(m); + if (res == 0) + MutexAfterLock(cur_thread(), (uptr)m, true, true, pc); + return res; +} + +INTERCEPTOR(int, pthread_mutex_timedlock, pthread_mutex_t *m, + const struct timespec *abstime) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_mutex_timedlock)(m, abstime); + if (res == 0) + MutexAfterLock(cur_thread(), (uptr)m, true, true, pc); + return res; +} + +INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + MutexBeforeUnlock(cur_thread(), (uptr)m, true, pc); + return REAL(pthread_mutex_unlock)(m); +} + +INTERCEPTOR(int, pthread_spin_init, pthread_spinlock_t *m, int pshared) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_spin_init)(m, pshared); + if (res == 0) + MutexInit(cur_thread(), (uptr)m, false, pc); + return res; +} + +INTERCEPTOR(int, pthread_spin_destroy, pthread_spinlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_spin_destroy)(m); + if (res == 0) + MutexDestroy(cur_thread(), (uptr)m, pc); + return res; +} + +INTERCEPTOR(int, pthread_spin_lock, pthread_spinlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + MutexBeforeLock(cur_thread(), (uptr)m, true, pc); + int res = REAL(pthread_spin_lock)(m); + MutexAfterLock(cur_thread(), (uptr)m, true, false, pc); + return res; +} + +INTERCEPTOR(int, pthread_spin_trylock, pthread_spinlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_spin_trylock)(m); + if (res == 0) + MutexAfterLock(cur_thread(), (uptr)m, true, true, pc); + return res; +} + +INTERCEPTOR(int, pthread_spin_unlock, pthread_spinlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + MutexBeforeUnlock(cur_thread(), (uptr)m, true, pc); + return REAL(pthread_spin_unlock)(m); +} + +INTERCEPTOR(int, pthread_rwlock_init, pthread_rwlock_t *m, + const pthread_rwlockattr_t *attr) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_rwlock_init)(m, attr); + if (res == 0) + MutexInit(cur_thread(), (uptr)m, false, pc); + return res; +} + +INTERCEPTOR(int, pthread_rwlock_destroy, pthread_rwlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + MutexDestroy(cur_thread(), (uptr)m, pc); + return REAL(pthread_rwlock_destroy)(m); +} + +INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + MutexBeforeLock(cur_thread(), (uptr)m, false, pc); + int res = REAL(pthread_rwlock_rdlock)(m); + MutexAfterLock(cur_thread(), (uptr)m, false, false, pc); + return res; +} + +INTERCEPTOR(int, pthread_rwlock_tryrdlock, pthread_rwlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_rwlock_tryrdlock)(m); + if (res == 0) + MutexAfterLock(cur_thread(), (uptr)m, false, true, pc); + return res; +} + +INTERCEPTOR(int, pthread_rwlock_timedrdlock, pthread_rwlock_t *m, + const timespec *abstime) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_rwlock_timedrdlock)(m, abstime); + if (res == 0) + MutexAfterLock(cur_thread(), (uptr)m, false, true, pc); + return res; +} + +INTERCEPTOR(int, pthread_rwlock_wrlock, pthread_rwlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + MutexBeforeLock(cur_thread(), (uptr)m, true, pc); + int res = REAL(pthread_rwlock_wrlock)(m); + MutexAfterLock(cur_thread(), (uptr)m, true, false, pc); + return res; +} + +INTERCEPTOR(int, pthread_rwlock_trywrlock, pthread_rwlock_t *m) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_rwlock_trywrlock)(m); + if (res == 0) + MutexAfterLock(cur_thread(), (uptr)m, true, true, pc); + return res; +} + +INTERCEPTOR(int, pthread_rwlock_timedwrlock, pthread_rwlock_t *m, + const timespec *abstime) { + uptr pc = GET_CURRENT_PC(); + InitThread(); + int res = REAL(pthread_rwlock_timedwrlock)(m, abstime); + if (res == 0... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/212748 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
