From 6a18a8fb507aadde7ffed4b56ea12875c6b30475 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Thu, 22 Jun 2023 20:03:00 +0100 Subject: [PATCH 1/2] [Threading][TSan] Fix TSan errors from lazy init on Linux. Move the TSan functionality from Concurrency into Threading. Use it in the Linux ulock implementation so that TSan knows about ulock and will tolerate the newer swift_once implementation that uses it. This should also slightly improve the performance of Concurrency, since the tsan tests will be inlined rather than it always doing a subroutine call. rdar://110665213 --- cmake/modules/AddSwiftUnittests.cmake | 3 +- include/swift/Threading/Impl/Linux/ulock.h | 29 +++-- include/swift/Threading/ThreadSanitizer.h | 120 ++++++++++++++++++ lib/Threading/CMakeLists.txt | 3 +- lib/Threading/Linux.cpp | 3 +- lib/Threading/ThreadSanitizer.cpp | 61 +++++++++ stdlib/public/Concurrency/CMakeLists.txt | 1 - stdlib/public/Concurrency/TaskPrivate.h | 27 ++-- stdlib/public/Concurrency/ThreadSanitizer.cpp | 50 -------- stdlib/public/Threading/CMakeLists.txt | 1 + stdlib/public/runtime/CMakeLists.txt | 7 + test/Sanitizers/tsan/once.swift | 55 ++++++++ 12 files changed, 287 insertions(+), 73 deletions(-) create mode 100644 include/swift/Threading/ThreadSanitizer.h create mode 100644 lib/Threading/ThreadSanitizer.cpp delete mode 100644 stdlib/public/Concurrency/ThreadSanitizer.cpp create mode 100644 test/Sanitizers/tsan/once.swift diff --git a/cmake/modules/AddSwiftUnittests.cmake b/cmake/modules/AddSwiftUnittests.cmake index b0ed92b913f8f..e7a98367337e9 100644 --- a/cmake/modules/AddSwiftUnittests.cmake +++ b/cmake/modules/AddSwiftUnittests.cmake @@ -58,7 +58,8 @@ function(add_swift_unittest test_dirname) string(TOUPPER "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_THREADING_PACKAGE}" _threading_package) target_compile_definitions("${test_dirname}" PRIVATE - "SWIFT_THREADING_${_threading_package}") + "SWIFT_THREADING_${_threading_package}" + "SWIFT_THREADING_STATIC") if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) if(SWIFT_USE_LINKER) diff --git a/include/swift/Threading/Impl/Linux/ulock.h b/include/swift/Threading/Impl/Linux/ulock.h index a9020965ec5d4..af04e74aa08ef 100644 --- a/include/swift/Threading/Impl/Linux/ulock.h +++ b/include/swift/Threading/Impl/Linux/ulock.h @@ -34,6 +34,8 @@ #include #include +#include "swift/Threading/ThreadSanitizer.h" + namespace swift { namespace threading_impl { namespace linux { @@ -59,31 +61,38 @@ inline void ulock_lock(ulock_t *lock) { const ulock_t tid = ulock_get_tid(); do { ulock_t zero = 0; - if (ulock_fastpath(__atomic_compare_exchange_n( - lock, &zero, tid, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))) - return; - + if (ulock_fastpath(__atomic_compare_exchange_n(lock, &zero, tid, + true, __ATOMIC_ACQUIRE, + __ATOMIC_RELAXED))) + break; } while (ulock_futex(lock, FUTEX_LOCK_PI) != 0); + + tsan::acquire(lock); } inline bool ulock_trylock(ulock_t *lock) { ulock_t zero = 0; if (ulock_fastpath(__atomic_compare_exchange_n(lock, &zero, ulock_get_tid(), true, __ATOMIC_ACQUIRE, - __ATOMIC_RELAXED))) + __ATOMIC_RELAXED)) + || ulock_futex(lock, FUTEX_TRYLOCK_PI) == 0) { + tsan::acquire(lock); return true; + } - return ulock_futex(lock, FUTEX_TRYLOCK_PI) == 0; + return false; } inline void ulock_unlock(ulock_t *lock) { + tsan::release(lock); + const ulock_t tid = ulock_get_tid(); do { ulock_t expected = tid; - if (ulock_fastpath(__atomic_compare_exchange_n( - lock, &expected, 0, true, __ATOMIC_RELEASE, __ATOMIC_RELAXED))) - return; - + if (ulock_fastpath(__atomic_compare_exchange_n(lock, &expected, 0, + true, __ATOMIC_RELEASE, + __ATOMIC_RELAXED))) + break; } while (ulock_futex(lock, FUTEX_UNLOCK_PI) != 0); } diff --git a/include/swift/Threading/ThreadSanitizer.h b/include/swift/Threading/ThreadSanitizer.h new file mode 100644 index 0000000000000..0a6a8028ea183 --- /dev/null +++ b/include/swift/Threading/ThreadSanitizer.h @@ -0,0 +1,120 @@ +//===--- ThreadSanitizer.h - Thread Sanitizer support --------- -*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2023 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Helper functions for code that needs to integrate with the thread +// sanitizer. In particular, TSan can't see inside the runtime libraries, +// so we occasionally need to give it a hint that we're doing synchronization +// in order to avoid false positives. +// +//===----------------------------------------------------------------------===// + +#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() + +#define SWIFT_THREADING_TSAN_SUPPORT 0 + +namespace tsan { + +inline bool enabled() { return false; } +template T *acquire(T *ptr) { return ptr; } +template T *release(T *ptr) { return ptr; } + +} // namespace tsan +#else + +#define SWIFT_THREADING_TSAN_SUPPORT 1 + +// If we're static linking to libswiftThreading.a, these symbols can come +// from there. If, on the other hand, we're dynamically linked, we want +// to get them from libswiftCore.dylib instead. +#if SWIFT_THREADING_STATIC +#define SWIFT_THREADING_EXPORT extern "C" +#else +#define SWIFT_THREADING_EXPORT SWIFT_RUNTIME_EXPORT +#endif + +namespace threading_impl { + +SWIFT_THREADING_EXPORT bool _swift_tsan_enabled; +SWIFT_THREADING_EXPORT void (*_swift_tsan_acquire)(const void *ptr); +SWIFT_THREADING_EXPORT void (*_swift_tsan_release)(const void *ptr); + +} // namespace threading_impl + +namespace tsan { + +/// Returns true if TSan is enabled +inline bool enabled() { + return threading_impl::_swift_tsan_enabled; +} + +/// Inform TSan about a synchronization operation. +/// +/// This is used when TSan cannot see the synchronization operation, for +/// example, if it is using a custom primitive for which TSan doesn't have +/// a built-in interceptor. This does not necessarily mean a lock or a C(++) +/// atomic operation - it could be any kind of synchronization mechanism. +/// +/// An acquire-release pair using the same address establishes an ordering +/// constraint in TSan's happens-before graph, which TSan uses to determine +/// whether two memory accesses from different threads have a well-defined +/// order. +/// +/// For instance, in +/// +/// Thread 1 Thread 2 +/// +/// access to y +/// tsan::release(x) +/// lock given away +/// +/// --> sync point --> +/// +/// lock taken +/// tsan::acquire(x) +/// access to y +/// +/// the access to y from Thread 2 is safe relative to the preceding access to +/// y on Thread 1 because it is preceded by an acquire of x that was itself +/// preceded by a release of x. +template +T *acquire(T *ptr) { + if (threading_impl::_swift_tsan_acquire) { + threading_impl::_swift_tsan_acquire(ptr); + } + return ptr; +} + +/// Inform TSan about a synchronization operation. +/// +/// This is the counterpart to tsan::acquire. +template +T *release(T *ptr) { + if (threading_impl::_swift_tsan_release) { + threading_impl::_swift_tsan_release(ptr); + } + return ptr; +} + +} // namespace tsan + +#endif + +} // namespace swift + +#endif diff --git a/lib/Threading/CMakeLists.txt b/lib/Threading/CMakeLists.txt index 029a52b68e1e3..4e0e6aed05e3b 100644 --- a/lib/Threading/CMakeLists.txt +++ b/lib/Threading/CMakeLists.txt @@ -10,4 +10,5 @@ add_swift_host_library(swiftThreading STATIC Linux.cpp Pthreads.cpp Win32.cpp - Errors.cpp) + Errors.cpp + ThreadSanitizer.cpp) diff --git a/lib/Threading/Linux.cpp b/lib/Threading/Linux.cpp index 811f470ba0832..93963a7c30ad2 100644 --- a/lib/Threading/Linux.cpp +++ b/lib/Threading/Linux.cpp @@ -18,6 +18,7 @@ #include "swift/Threading/Impl.h" #include "swift/Threading/Errors.h" +#include "swift/Threading/ThreadSanitizer.h" namespace { @@ -61,7 +62,7 @@ void swift::threading_impl::once_slow(once_t &predicate, void (*fn)(void *), #endif if (predicate.flag.load(std::memory_order_acquire) == 0) { fn(context); - predicate.flag.store(-1, std::memory_order_release); + predicate.flag.store(tsan::enabled() ? 1 : -1, std::memory_order_release); } #if defined(__LP64__) || defined(_LP64) linux::ulock_unlock(&predicate.lock); diff --git a/lib/Threading/ThreadSanitizer.cpp b/lib/Threading/ThreadSanitizer.cpp new file mode 100644 index 0000000000000..a103c161dce91 --- /dev/null +++ b/lib/Threading/ThreadSanitizer.cpp @@ -0,0 +1,61 @@ +//===--- ThreadSanitizer.cpp - Thread Sanitizer support -------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2023 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Helper functions for code that needs to integrate with the thread +// sanitizer. In particular, TSan can't see inside the runtime libraries, +// so we occasionally need to give it a hint that we're doing synchronization +// in order to avoid false positives. +// +//===----------------------------------------------------------------------===// + +#include "swift/Threading/ThreadSanitizer.h" + +#if SWIFT_THREADING_TSAN_SUPPORT + +#include "swift/shims/Visibility.h" + +#include + +namespace swift { +namespace threading_impl { + +SWIFT_THREADING_EXPORT bool _swift_tsan_enabled = false; +SWIFT_THREADING_EXPORT void (*_swift_tsan_acquire)(const void *) = nullptr; +SWIFT_THREADING_EXPORT void (*_swift_tsan_release)(const void *) = nullptr; + +#if __has_include() +#include + +// The TSan library code will call this function when it starts up +extern "C" SWIFT_ATTRIBUTE_FOR_EXPORTS +void __tsan_on_initialize() { + _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; 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) { + next_init(); + } +} +#endif // __has_include() + +} // namespace threading_impl +} // namespace swift + +#endif // SWIFT_THREADING_TSAN_SUPPORT diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index 7060ece89d636..0ac762e1cff1d 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -120,7 +120,6 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I TaskLocal.cpp TaskLocal.swift TaskSleep.swift - ThreadSanitizer.cpp ThreadingError.cpp TracingSignpost.cpp AsyncStreamBuffer.swift diff --git a/stdlib/public/Concurrency/TaskPrivate.h b/stdlib/public/Concurrency/TaskPrivate.h index 450fa2a7111d6..414bf3dc75c11 100644 --- a/stdlib/public/Concurrency/TaskPrivate.h +++ b/stdlib/public/Concurrency/TaskPrivate.h @@ -29,6 +29,7 @@ #include "swift/Runtime/Exclusivity.h" #include "swift/Runtime/HeapObject.h" #include "swift/Threading/Thread.h" +#include "swift/Threading/ThreadSanitizer.h" #include #include @@ -99,15 +100,23 @@ void _swift_taskGroup_cancelAllChildren(TaskGroup *group); /// should generally use a higher-level function. void _swift_taskGroup_detachChild(TaskGroup *group, AsyncTask *child); -/// release() establishes a happens-before relation with a preceding acquire() -/// on the same address. -void _swift_tsan_acquire(void *addr); -void _swift_tsan_release(void *addr); -/// Technically, this consume relies on implicit HW address dependency ordering -/// and is paired with a corresponding release. Since TSAN doesn't know how to -/// reason about this, we tell TSAN it's an acquire instead. See also -/// SWIFT_MEMORY_ORDER_CONSUME definition. -#define _swift_tsan_consume _swift_tsan_acquire +/// Tell TSan about an acquiring load +inline void _swift_tsan_acquire(void *addr) { + swift::tsan::acquire(addr); +} +/// Tell TSan about a releasing store +inline void _swift_tsan_release(void *addr) { + swift::tsan::release(addr); +} +/// Tell TSan about a consuming load +inline void _swift_tsan_consume(void *addr) { + // TSan doesn't support consume, so pretend it's an acquire. + // + // Note that that means that TSan won't generate errors for non-dependent + // reads, so this isn't entirely safe if you're relying solely on TSan to + // spot bugs. + swift::tsan::acquire(addr); +} /// Special values used with DispatchQueueIndex to indicate the global and main /// executors. diff --git a/stdlib/public/Concurrency/ThreadSanitizer.cpp b/stdlib/public/Concurrency/ThreadSanitizer.cpp deleted file mode 100644 index c9d1d5027732b..0000000000000 --- a/stdlib/public/Concurrency/ThreadSanitizer.cpp +++ /dev/null @@ -1,50 +0,0 @@ -//===--- ThreadSanitizer.cpp - Thread Sanitizer support -------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Thread Sanitizer support for the Swift Task runtime. -// -//===----------------------------------------------------------------------===// - -#include "TaskPrivate.h" - -// Thread Sanitizer is not supported on Windows or WASI. -#if defined(_WIN32) || defined(__wasi__) || !__has_include() -void swift::_swift_tsan_acquire(void *addr) {} -void swift::_swift_tsan_release(void *addr) {} -#else -#include - -namespace { -using TSanFunc = void(void *); -TSanFunc *tsan_acquire, *tsan_release; -} // anonymous namespace - -void swift::_swift_tsan_acquire(void *addr) { - if (tsan_acquire) { - tsan_acquire(addr); - SWIFT_TASK_DEBUG_LOG("tsan_acquire on %p", addr); - } -} - -void swift::_swift_tsan_release(void *addr) { - if (tsan_release) { - tsan_release(addr); - SWIFT_TASK_DEBUG_LOG("tsan_release on %p", addr); - } -} - -SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(c) -void __tsan_on_initialize() { - tsan_acquire = (TSanFunc *)dlsym(RTLD_DEFAULT, "__tsan_acquire"); - tsan_release = (TSanFunc *)dlsym(RTLD_DEFAULT, "__tsan_release"); -} -#endif diff --git a/stdlib/public/Threading/CMakeLists.txt b/stdlib/public/Threading/CMakeLists.txt index 007289ed3fac7..96ea52d1d8f7e 100644 --- a/stdlib/public/Threading/CMakeLists.txt +++ b/stdlib/public/Threading/CMakeLists.txt @@ -4,6 +4,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules") include(AddSwiftStdlib) +# This should *not* include ThreadSanitizer.cpp, as that is part of libswiftCore add_swift_target_library(swiftThreading OBJECT_LIBRARY "${SWIFT_SOURCE_DIR}/lib/Threading/C11.cpp" "${SWIFT_SOURCE_DIR}/lib/Threading/Linux.cpp" diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index 379f72b010a72..c715b7678caaf 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -79,6 +79,12 @@ set(swift_runtime_sources AccessibleFunction.cpp Win32.cpp) +# We pull this in separately here because other dylibs will need it, but only +# will have the __tsan_on_initialize called, and on Darwin, RTLD_NEXT can't be +# used to call subsequence dylibs' copies of that. +set(swift_runtime_threading_sources + ${SWIFT_SOURCE_DIR}/lib/Threading/ThreadSanitizer.cpp) + set(swift_runtime_backtracing_sources Backtrace.cpp CrashHandlerMacOS.cpp @@ -130,6 +136,7 @@ add_swift_target_library(swiftRuntime OBJECT_LIBRARY ${swift_runtime_sources} ${swift_runtime_objc_sources} ${swift_runtime_leaks_sources} + ${swift_runtime_threading_sources} C_COMPILE_FLAGS ${swift_runtime_library_compile_flags} LINK_FLAGS ${swift_runtime_linker_flags} diff --git a/test/Sanitizers/tsan/once.swift b/test/Sanitizers/tsan/once.swift new file mode 100644 index 0000000000000..f3bcc562403f5 --- /dev/null +++ b/test/Sanitizers/tsan/once.swift @@ -0,0 +1,55 @@ +// RUN: %target-swiftc_driver %s -Xfrontend -parse-as-library -g -sanitize=thread %import-libdispatch -o %t_tsan-binary +// RUN: %target-codesign %t_tsan-binary +// RUN: env %env-TSAN_OPTIONS=abort_on_error=0 %target-run %t_tsan-binary 2>&1 | %FileCheck %s --implicit-check-not='ThreadSanitizer' +// REQUIRES: executable_test +// REQUIRES: tsan_runtime + +// rdar://101876380 +// UNSUPPORTED: OS=ios + +// FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs +// don't support TSan. +// UNSUPPORTED: remote_run + +// Test that we do not report a race on initialization; Swift doesn't initialize +// globals at start-up, but rather uses `swift_once()`. This is thread safe, but +// on some platforms TSan wasn't seeing the synchronization, so would report +// a false positive. + +import Dispatch + +var count = 0 + +// This initialization will be done via a call to `swift_once()`. Prior to +// the fix for rdar://110665213, the addition to `count` would trigger a +// TSan message on Linux because the sanitizer couldn't see the lock we're +// using to make `swift_once()` thread safe. +let foo = { + count += 1 + return count +}() + +@main +struct Main { + static func main() { + let q = DispatchQueue(label: "q", attributes: .concurrent) + let finished = DispatchSemaphore(value: 0) + let count = 100 + + for _ in 0.. Date: Fri, 23 Jun 2023 16:03:26 +0100 Subject: [PATCH 2/2] [Freestanding] Remove uses of stat() and dlsym(). We shouldn't be using stat() or dlsym() in the freestanding runtime. rdar://111214571 rdar://106555012 --- CMakeLists.txt | 5 ++++ cmake/modules/AddSwiftUnittests.cmake | 9 ++++++- include/swift/Threading/ThreadSanitizer.h | 6 ++++- lib/Threading/ThreadSanitizer.cpp | 6 ++--- stdlib/cmake/modules/AddSwiftStdlib.cmake | 10 ++++++++ stdlib/cmake/modules/StdlibOptions.cmake | 10 +++++++- stdlib/public/runtime/Paths.cpp | 24 +++++++++++++++++++ utils/build-presets.ini | 2 ++ utils/build-script-impl | 4 ++++ utils/check_freestanding_dependencies.py | 1 - .../products/minimalstdlib.py | 2 ++ 11 files changed, 71 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c5626cbe50b4..342f60855e32a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -651,6 +651,11 @@ option(SWIFT_THREADING_PACKAGE Valid package names are 'pthreads', 'darwin', 'linux', 'win32', 'c11', 'none' or the empty string for the SDK default.") +option(SWIFT_THREADING_HAS_DLSYM + "Enable the use of the dlsym() function. This gets used to provide TSan + support on some platforms." + TRUE) + option(SWIFT_ENABLE_MACCATALYST "Build the Standard Library and overlays with MacCatalyst support" FALSE) diff --git a/cmake/modules/AddSwiftUnittests.cmake b/cmake/modules/AddSwiftUnittests.cmake index e7a98367337e9..a4573981c225c 100644 --- a/cmake/modules/AddSwiftUnittests.cmake +++ b/cmake/modules/AddSwiftUnittests.cmake @@ -49,12 +49,19 @@ function(add_swift_unittest test_dirname) endif() # some headers switch their inline implementations based on - # SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY and + # SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY, SWIFT_STDLIB_HAS_DLSYM and # SWIFT_THREADING_PACKAGE definitions if(SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY) target_compile_definitions("${test_dirname}" PRIVATE SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY) endif() + if(SWIFT_STDLIB_HAS_DLSYM) + target_compile_definitions("${test_dirname}" PRIVATE + "SWIFT_STDLIB_HAS_DLSYM=1") + else() + target_compile_definitions("${test_dirname}" PRIVATE + "SWIFT_STDLIB_HAS_DLSYM=0") + endif() string(TOUPPER "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_THREADING_PACKAGE}" _threading_package) target_compile_definitions("${test_dirname}" PRIVATE diff --git a/include/swift/Threading/ThreadSanitizer.h b/include/swift/Threading/ThreadSanitizer.h index 0a6a8028ea183..a50a554f08c40 100644 --- a/include/swift/Threading/ThreadSanitizer.h +++ b/include/swift/Threading/ThreadSanitizer.h @@ -24,7 +24,10 @@ namespace swift { -#if defined(_WIN32) || defined(__wasi__) || !__has_include() +#if SWIFT_THREADING_NONE \ + || defined(_WIN32) || defined(__wasi__) \ + || !__has_include() \ + || (defined(SWIFT_STDLIB_HAS_DLSYM) && !SWIFT_STDLIB_HAS_DLSYM) #define SWIFT_THREADING_TSAN_SUPPORT 0 @@ -35,6 +38,7 @@ template T *acquire(T *ptr) { return ptr; } template T *release(T *ptr) { return ptr; } } // namespace tsan + #else #define SWIFT_THREADING_TSAN_SUPPORT 1 diff --git a/lib/Threading/ThreadSanitizer.cpp b/lib/Threading/ThreadSanitizer.cpp index a103c161dce91..36a64b166e799 100644 --- a/lib/Threading/ThreadSanitizer.cpp +++ b/lib/Threading/ThreadSanitizer.cpp @@ -23,6 +23,8 @@ #include "swift/shims/Visibility.h" +#include + #include namespace swift { @@ -32,9 +34,6 @@ SWIFT_THREADING_EXPORT bool _swift_tsan_enabled = false; SWIFT_THREADING_EXPORT void (*_swift_tsan_acquire)(const void *) = nullptr; SWIFT_THREADING_EXPORT void (*_swift_tsan_release)(const void *) = nullptr; -#if __has_include() -#include - // The TSan library code will call this function when it starts up extern "C" SWIFT_ATTRIBUTE_FOR_EXPORTS void __tsan_on_initialize() { @@ -53,7 +52,6 @@ void __tsan_on_initialize() { next_init(); } } -#endif // __has_include() } // namespace threading_impl } // namespace swift diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index 9fc316537a211..735587543f954 100644 --- a/stdlib/cmake/modules/AddSwiftStdlib.cmake +++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake @@ -352,6 +352,16 @@ function(_add_target_variant_c_compile_flags) list(APPEND result "-DSWIFT_STDLIB_HAS_DLADDR") endif() + if(SWIFT_STDLIB_HAS_DLSYM) + list(APPEND result "-DSWIFT_STDLIB_HAS_DLSYM=1") + else() + list(APPEND result "-DSWIFT_STDLIB_HAS_DLSYM=0") + endif() + + if(SWIFT_STDLIB_HAS_FILESYSTEM) + list(APPEND result "-DSWIFT_STDLIB_HAS_FILESYSTEM") + endif() + if(SWIFT_RUNTIME_STATIC_IMAGE_INSPECTION) list(APPEND result "-DSWIFT_RUNTIME_STATIC_IMAGE_INSPECTION") endif() diff --git a/stdlib/cmake/modules/StdlibOptions.cmake b/stdlib/cmake/modules/StdlibOptions.cmake index 1116df016a8cb..5fce862ee273d 100644 --- a/stdlib/cmake/modules/StdlibOptions.cmake +++ b/stdlib/cmake/modules/StdlibOptions.cmake @@ -135,7 +135,15 @@ option(SWIFT_STDLIB_BUILD_PRIVATE TRUE) option(SWIFT_STDLIB_HAS_DLADDR - "Build stdlib assuming the runtime environment runtime environment provides dladdr API." + "Build stdlib assuming the runtime environment provides the dladdr API." + TRUE) + +option(SWIFT_STDLIB_HAS_DLSYM + "Build stdlib assuming the runtime environment provides the dlsym API." + TRUE) + +option(SWIFT_STDLIB_HAS_FILESYSTEM + "Build stdlib assuming the runtime environment has a filesystem." TRUE) option(SWIFT_RUNTIME_STATIC_IMAGE_INSPECTION diff --git a/stdlib/public/runtime/Paths.cpp b/stdlib/public/runtime/Paths.cpp index 5ea45bd9fa166..bba1b6e2db7e4 100644 --- a/stdlib/public/runtime/Paths.cpp +++ b/stdlib/public/runtime/Paths.cpp @@ -53,6 +53,28 @@ #include #include +#if !SWIFT_STDLIB_HAS_FILESYSTEM + +SWIFT_RUNTIME_EXPORT +const char * +swift_getRuntimeLibraryPath() { + return nullptr; +} + +SWIFT_RUNTIME_EXPORT +const char * +swift_getRootPath() { + return nullptr; +} + +SWIFT_RUNTIME_EXPORT +char * +swift_copyAuxiliaryExecutablePath(const char *name) { + return nullptr; +} + +#else // SWIFT_STDLIB_HAS_FILESYSTEM + namespace { swift::once_t runtimePathToken; @@ -578,3 +600,5 @@ bool _swift_exists(const char *path) } } + +#endif // SWIFT_STDLIB_HAS_FILESYSTEM diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 90625072a977a..5e67ab8df4ef3 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -2596,6 +2596,8 @@ swift-enable-reflection=0 swift-stdlib-reflection-metadata=debugger-only swift-stdlib-stable-abi=0 swift-stdlib-has-dladdr=0 +swift-stdlib-has-dlsym=0 +swift-stdlib-has-filesystem=0 swift-stdlib-supports-backtrace-reporting=0 swift-stdlib-has-darwin-libmalloc=0 swift-stdlib-has-asl=0 diff --git a/utils/build-script-impl b/utils/build-script-impl index 969eb64405eba..14b18a549d414 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -207,6 +207,8 @@ KNOWN_SETTINGS=( swift-enable-reflection "1" "whether to support reflection and mirrors" swift-stdlib-reflection-metadata "enabled" "whether to build stdlib with runtime metadata (valid options are 'enabled', 'disabled' and 'debugger-only')" swift-stdlib-has-dladdr "1" "whether to build stdlib assuming the runtime environment provides dladdr API" + swift-stdlib-has-dlsym "1" "whether to build stdlib assuming the runtime environment provides the dlsym API" + swift-stdlib-has-filesystem "1" "whether to build stdlib assuming the runtime environment provides a filesystem" swift-stdlib-supports-backtrace-reporting "" "whether to build stdlib assuming the runtime environment provides the backtrace(3) API, if not set defaults to true on all platforms except for Cygwin, Haiku and wasm" swift-runtime-static-image-inspection "0" "whether to build stdlib assuming the runtime environment only supports a single runtime image with Swift code" swift-threading-package "" "override the threading package for the host build; this is either a single package or a semicolon-separated list of sdk:package pairs. Valid packages are empty string (no override), 'pthreads', 'darwin', 'linux', 'win32', 'c11', 'none'" @@ -1828,6 +1830,8 @@ for host in "${ALL_HOSTS[@]}"; do -DSWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY:BOOL=$(true_false "${SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY}") -DSWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS:BOOL=$(true_false "${SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS}") -DSWIFT_STDLIB_HAS_DLADDR:BOOL=$(true_false "${SWIFT_STDLIB_HAS_DLADDR}") + -DSWIFT_STDLIB_HAS_DLSYM:BOOL=$(true_false "${SWIFT_STDLIB_HAS_DLSYM}") + -DSWIFT_STDLIB_HAS_FILESYSTEM:BOOL=$(true_false "${SWIFT_STDLIB_HAS_FILESYSTEM}") -DSWIFT_RUNTIME_STATIC_IMAGE_INSPECTION:BOOL=$(true_false "${SWIFT_RUNTIME_STATIC_IMAGE_INSPECTION}") -DSWIFT_STDLIB_OS_VERSIONING:BOOL=$(true_false "${SWIFT_STDLIB_OS_VERSIONING}") -DSWIFT_STDLIB_HAS_COMMANDLINE:BOOL=$(true_false "${SWIFT_STDLIB_HAS_COMMANDLINE}") diff --git a/utils/check_freestanding_dependencies.py b/utils/check_freestanding_dependencies.py index 4c048d283c852..cd87c651e7591 100755 --- a/utils/check_freestanding_dependencies.py +++ b/utils/check_freestanding_dependencies.py @@ -49,7 +49,6 @@ "_posix_memalign", "_putc", "_read", "_realloc", "_snprintf", "_strchr", "_strcmp", "_strdup", "_strlen", "_strncmp", "_strtod", "_strtof", "_strtol", "_strtold", "_vprintf", "_vsnprintf", "_write", - "_stat", "_stat$INODE64", ] + cxx_dependencies + math_dependencies vendor_apple_specific_dependencies = [ "___stack_chk_fail", "___stack_chk_guard", diff --git a/utils/swift_build_support/swift_build_support/products/minimalstdlib.py b/utils/swift_build_support/swift_build_support/products/minimalstdlib.py index 1264f1a434d0e..929a1305316d6 100644 --- a/utils/swift_build_support/swift_build_support/products/minimalstdlib.py +++ b/utils/swift_build_support/swift_build_support/products/minimalstdlib.py @@ -139,7 +139,9 @@ def build(self, host_target): self.cmake_options.define( 'SWIFT_STDLIB_HAS_DARWIN_LIBMALLOC:BOOL', 'FALSE') self.cmake_options.define('SWIFT_STDLIB_HAS_DLADDR:BOOL', 'FALSE') + self.cmake_options.define('SWIFT_STDLIB_HAS_DLSYM:BOOL', 'FALSE') self.cmake_options.define('SWIFT_STDLIB_HAS_ENVIRON:BOOL', 'FALSE') + self.cmake_options.define('SWIFT_STDLIB_HAS_FILESYSTEM:BOOL', 'FALSE') self.cmake_options.define('SWIFT_STDLIB_HAS_LOCALE:BOOL', 'FALSE') self.cmake_options.define('SWIFT_STDLIB_HAS_STDIN:BOOL', 'FALSE') self.cmake_options.define(