[Threading][TSan] Move ThreadSanitizer.cpp into the main runtime.

On Darwin, `RTLD_NEXT` doesn't do what we need it to here, with the
result that if `libswiftCore`'s TSan initializer gets found first,
then `libswift_Concurrency` won't have its initializer called at all,
in spite of us using `RTLD_NEXT` to find the next definition.

Fix this by centralising the initializer in `libswiftCore` instead.

rdar://110665213
This commit is contained in:
Alastair Houghton
2023-06-19 15:20:17 +01:00
parent ee5efff5b1
commit 8ed8a28478
5 changed files with 28 additions and 20 deletions

View File

@@ -20,6 +20,8 @@
#ifndef SWIFT_THREADING_THREAD_SANITIZER_H
#define SWIFT_THREADING_THREAD_SANITIZER_H
#include "swift/shims/Visibility.h"
namespace swift {
#if defined(_WIN32) || defined(__wasi__) || !__has_include(<dlfcn.h>)
@@ -34,9 +36,9 @@ template <typename T> T *release(T *ptr) { return ptr; }
namespace threading_impl {
extern bool tsan_enabled;
extern void (*tsan_acquire)(const void *ptr);
extern void (*tsan_release)(const void *ptr);
SWIFT_RUNTIME_EXPORT bool _swift_tsan_enabled;
SWIFT_RUNTIME_EXPORT void (*_swift_tsan_acquire)(const void *ptr);
SWIFT_RUNTIME_EXPORT void (*_swift_tsan_release)(const void *ptr);
} // namespace threading_impl
@@ -44,7 +46,7 @@ namespace tsan {
/// Returns true if TSan is enabled
inline bool enabled() {
return threading_impl::tsan_enabled;
return threading_impl::_swift_tsan_enabled;
}
/// Indicate to TSan that an acquiring load has occurred on the current
@@ -54,8 +56,8 @@ inline bool enabled() {
/// `acquire()`.
template <typename T>
T *acquire(T *ptr) {
if (threading_impl::tsan_acquire) {
threading_impl::tsan_acquire(ptr);
if (threading_impl::_swift_tsan_acquire) {
threading_impl::_swift_tsan_acquire(ptr);
}
return ptr;
}
@@ -66,8 +68,8 @@ T *acquire(T *ptr) {
/// see all writes that happened before the `release()`.
template <typename T>
T *release(T *ptr) {
if (threading_impl::tsan_release) {
threading_impl::tsan_release(ptr);
if (threading_impl::_swift_tsan_release) {
threading_impl::_swift_tsan_release(ptr);
}
return ptr;
}

View File

@@ -10,5 +10,4 @@ add_swift_host_library(swiftThreading STATIC
Linux.cpp
Pthreads.cpp
Win32.cpp
Errors.cpp
ThreadSanitizer.cpp)
Errors.cpp)

View File

@@ -9,5 +9,4 @@ add_swift_target_library(swiftThreading OBJECT_LIBRARY
"${SWIFT_SOURCE_DIR}/lib/Threading/Linux.cpp"
"${SWIFT_SOURCE_DIR}/lib/Threading/Pthreads.cpp"
"${SWIFT_SOURCE_DIR}/lib/Threading/Win32.cpp"
"${SWIFT_SOURCE_DIR}/lib/Threading/ThreadSanitizer.cpp"
INSTALL_IN_COMPONENT never_install)

View File

@@ -76,6 +76,7 @@ set(swift_runtime_sources
SwiftDtoa.cpp
SwiftTLSContext.cpp
ThreadingError.cpp
ThreadSanitizer.cpp
Tracing.cpp
AccessibleFunction.cpp
Win32.cpp)

View File

@@ -20,28 +20,35 @@
#include "swift/Threading/ThreadSanitizer.h"
#include "swift/shims/Visibility.h"
#include <cstdio>
namespace swift {
namespace threading_impl {
bool tsan_enabled = false;
void (*tsan_acquire)(const void *) = nullptr;
void (*tsan_release)(const void *) = nullptr;
SWIFT_RUNTIME_EXPORT bool _swift_tsan_enabled = false;
SWIFT_RUNTIME_EXPORT void (*_swift_tsan_acquire)(const void *) = nullptr;
SWIFT_RUNTIME_EXPORT void (*_swift_tsan_release)(const void *) = nullptr;
#if __has_include(<dlfcn.h>)
#include <dlfcn.h>
// The TSan library code will call this function when it starts up
extern "C" SWIFT_ATTRIBUTE_FOR_EXPORTS
SWIFT_RUNTIME_EXPORT
void __tsan_on_initialize() {
tsan_enabled = true;
tsan_acquire = (void (*)(const void *))dlsym(RTLD_DEFAULT, "__tsan_acquire");
tsan_release = (void (*)(const void *))dlsym(RTLD_DEFAULT, "__tsan_release");
_swift_tsan_enabled = true;
_swift_tsan_acquire = (void (*)(const void *))dlsym(RTLD_DEFAULT,
"__tsan_acquire");
_swift_tsan_release = (void (*)(const void *))dlsym(RTLD_DEFAULT,
"__tsan_release");
// Always call through to the next image
// Always call through to the next image; this won't work on macOS, but it's
// important on Linux to allow others to hook into the thread sanitizer if
// they wish.
void (*next_init)(void);
next_init = (void (*)(void))dlsym(RTLD_NEXT, "__tsan_on_initialize");
if (next_init)
if (next_init) {
next_init();
}
}
#endif