mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Threading] Create new threading library and use it.
Moved all the threading code to one place. Added explicit support for Darwin, Linux, Pthreads, C11 threads and Win32 threads, including new implementations of Once for Linux, Pthreads, C11 and Win32. rdar://90776105
This commit is contained in:
@@ -126,12 +126,13 @@ option(SWIFT_STDLIB_ENABLE_UNICODE_DATA
|
||||
|
||||
include(Threading)
|
||||
|
||||
threading_package_default(SWIFT_STDLIB_THREADING_PACKAGE_default)
|
||||
threading_package_default("${SWIFT_HOST_VARIANT_SDK}"
|
||||
SWIFT_THREADING_PACKAGE_default)
|
||||
|
||||
set(SWIFT_STDLIB_THREADING_PACKAGE "${SWIFT_STDLIB_THREADING_PACKAGE_default}"
|
||||
set(SWIFT_THREADING_PACKAGE "${SWIFT_THREADING_PACKAGE_default}"
|
||||
CACHE STRING
|
||||
"The threading package to use. Must be one of 'none', 'pthreads',
|
||||
'darwin', 'win32', 'c11'.")
|
||||
'darwin', 'linux', 'win32', 'c11'.")
|
||||
|
||||
option(SWIFT_BUILD_DYNAMIC_SDK_OVERLAY
|
||||
"Build dynamic variants of the Swift SDK overlay"
|
||||
@@ -1046,7 +1047,7 @@ if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_SDK_OVERLAY)
|
||||
message(STATUS " Leak Detection Checker Entrypoints: ${SWIFT_RUNTIME_ENABLE_LEAK_CHECKER}")
|
||||
message(STATUS "")
|
||||
|
||||
message(STATUS "Threading Package: ${SWIFT_STDLIB_THREADING_PACKAGE}")
|
||||
message(STATUS "Threading Package: ${SWIFT_THREADING_PACKAGE}")
|
||||
message(STATUS "Differentiable Programming Support: ${SWIFT_ENABLE_EXPERIMENTAL_DIFFERENTIABLE_PROGRAMMING}")
|
||||
message(STATUS "Concurrency Support: ${SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY}")
|
||||
message(STATUS "Distributed Support: ${SWIFT_ENABLE_EXPERIMENTAL_DISTRIBUTED}")
|
||||
|
||||
@@ -4,6 +4,7 @@ include(SwiftXcodeSupport)
|
||||
include(SwiftWindowsSupport)
|
||||
include(SwiftAndroidSupport)
|
||||
include(SwiftCXXUtils)
|
||||
include(Threading)
|
||||
|
||||
function(_swift_gyb_target_sources target scope)
|
||||
file(GLOB GYB_UNICODE_DATA ${SWIFT_SOURCE_DIR}/utils/UnicodeData/*)
|
||||
@@ -308,6 +309,10 @@ function(_add_host_variant_c_compile_flags target)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS>)
|
||||
endif()
|
||||
|
||||
threading_package_name("${SWIFT_HOST_VARIANT_SDK}" _threading_package)
|
||||
target_compile_definitions(${target} PRIVATE
|
||||
"SWIFT_THREADING_${_threading_package}")
|
||||
|
||||
if(SWIFT_ANALYZE_CODE_COVERAGE)
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fprofile-instr-generate -fcoverage-mapping>)
|
||||
|
||||
@@ -49,14 +49,14 @@ function(add_swift_unittest test_dirname)
|
||||
|
||||
# some headers switch their inline implementations based on
|
||||
# SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY and
|
||||
# SWIFT_STDLIB_THREADING_PACKAGE definitions
|
||||
# SWIFT_THREADING_PACKAGE definitions
|
||||
if(SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY)
|
||||
target_compile_definitions("${test_dirname}" PRIVATE
|
||||
SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY)
|
||||
endif()
|
||||
threading_package_name(_threading_package)
|
||||
threading_package_name("${SWIFT_HOST_VARIANT_SDK}" _threading_package)
|
||||
target_compile_definitions("${test_dirname}" PRIVATE
|
||||
"SWIFT_STDLIB_THREADING_${_threading_package}")
|
||||
"SWIFT_THREADING_${_threading_package}")
|
||||
|
||||
if(NOT SWIFT_COMPILER_IS_MSVC_LIKE)
|
||||
if(SWIFT_USE_LINKER)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# Get the default threading package for the platform
|
||||
function(threading_package_default out_var)
|
||||
if("${SWIFT_HOST_VARIANT_SDK}" IN_LIST SWIFT_DARWIN_PLATFORMS)
|
||||
function(threading_package_default sdk out_var)
|
||||
if(sdk IN_LIST SWIFT_DARWIN_PLATFORMS)
|
||||
set("${out_var}" "darwin" PARENT_SCOPE)
|
||||
elseif("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "WINDOWS")
|
||||
elseif(sdk STREQUAL "LINUX")
|
||||
set("${out_var}" "linux" PARENT_SCOPE)
|
||||
elseif(sdk STREQUAL "WINDOWS")
|
||||
set("${out_var}" "win32" PARENT_SCOPE)
|
||||
elseif("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "WASI")
|
||||
elseif(sdk STREQUAL "WASI")
|
||||
set("${out_var}" "none" PARENT_SCOPE)
|
||||
else()
|
||||
set("${out_var}" "pthreads" PARENT_SCOPE)
|
||||
@@ -14,11 +16,11 @@ endfunction()
|
||||
# Given the threading package, find the name for the preprocessor
|
||||
# define that we need to make. Also deals with the default platform
|
||||
# setting.
|
||||
function(threading_package_name out_var)
|
||||
function(threading_package_name sdk out_var)
|
||||
precondition(SWIFT_HOST_VARIANT_SDK)
|
||||
precondition(SWIFT_DARWIN_PLATFORMS)
|
||||
|
||||
string(TOUPPER "${SWIFT_STDLIB_THREADING_PACKAGE}" package)
|
||||
string(TOUPPER "${SWIFT_THREADING_PACKAGE}" package)
|
||||
if(package STREQUAL "")
|
||||
threading_package_default(package)
|
||||
string(TOUPPER "${package}" package)
|
||||
|
||||
@@ -162,4 +162,20 @@
|
||||
#define SWIFT_ASM_LABEL_WITH_PREFIX(STRING) \
|
||||
SWIFT_ASM_LABEL_RAW(SWIFT_SYMBOL_PREFIX_STRING STRING)
|
||||
|
||||
// SWIFT_FORMAT(fmt,first) marks a function as taking a format string argument
|
||||
// at argument `fmt`, with the first argument for the format string as `first`.
|
||||
#if __has_attribute(format)
|
||||
#define SWIFT_FORMAT(fmt,first) __attribute__((format(printf, fmt, first)))
|
||||
#else
|
||||
#define SWIFT_FORMAT(fmt,first)
|
||||
#endif
|
||||
|
||||
// SWIFT_VFORMAT(fmt) marks a function as taking a format string argument at
|
||||
// argument `fmt`, with the arguments in a `va_list`.
|
||||
#if __has_attribute(format)
|
||||
#define SWIFT_VFORMAT(fmt) __attribute__((format(printf, fmt, 0)))
|
||||
#else
|
||||
#define SWIFT_VFORMAT(fmt)
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_BASIC_COMPILER_H
|
||||
|
||||
@@ -15,47 +15,18 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_NONE
|
||||
// No dependencies on single-threaded environments.
|
||||
#elif SWIFT_STDLIB_THREADING_DARWIN
|
||||
#include <dispatch/dispatch.h>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#include "swift/Basic/Malloc.h"
|
||||
#include "swift/Basic/type_traits.h"
|
||||
#include "swift/Threading/Once.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_NONE
|
||||
using OnceToken_t = bool;
|
||||
# define SWIFT_ONCE_F(TOKEN, FUNC, CONTEXT) \
|
||||
do { if (!TOKEN) { TOKEN = true; (FUNC)(CONTEXT); } } while (0)
|
||||
#elif SWIFT_STDLIB_THREADING_DARWIN
|
||||
using OnceToken_t = ::dispatch_once_t;
|
||||
# define SWIFT_ONCE_F(TOKEN, FUNC, CONTEXT) \
|
||||
::dispatch_once_f(&TOKEN, CONTEXT, FUNC)
|
||||
#elif defined(__CYGWIN__)
|
||||
// _swift_once_f() is declared in Private.h.
|
||||
// This prototype is copied instead including the header file.
|
||||
void _swift_once_f(uintptr_t *predicate, void *context,
|
||||
void (*function)(void *));
|
||||
using OnceToken_t = unsigned long;
|
||||
# define SWIFT_ONCE_F(TOKEN, FUNC, CONTEXT) \
|
||||
_swift_once_f(&TOKEN, CONTEXT, FUNC)
|
||||
#else
|
||||
using OnceToken_t = std::once_flag;
|
||||
# define SWIFT_ONCE_F(TOKEN, FUNC, CONTEXT) \
|
||||
::std::call_once(TOKEN, FUNC, CONTEXT)
|
||||
#endif
|
||||
|
||||
/// A template for lazily-constructed, zero-initialized, leaked-on-exit
|
||||
/// global objects.
|
||||
template <class T> class Lazy {
|
||||
alignas(T) char Value[sizeof(T)] = { 0 };
|
||||
|
||||
OnceToken_t OnceToken = {};
|
||||
swift::once_t OnceToken = {};
|
||||
|
||||
static void defaultInitCallback(void *ValueAddr) {
|
||||
::new (ValueAddr) T();
|
||||
@@ -87,7 +58,7 @@ template <typename T> inline T &Lazy<T>::get(void (*initCallback)(void*)) {
|
||||
static_assert(std::is_literal_type<Lazy<T>>::value,
|
||||
"Lazy<T> must be a literal type");
|
||||
|
||||
SWIFT_ONCE_F(OnceToken, initCallback, &Value);
|
||||
swift::once(OnceToken, initCallback, &Value);
|
||||
return unsafeGetAlreadyInitialized();
|
||||
}
|
||||
|
||||
@@ -103,7 +74,7 @@ template <typename Arg1> inline T &Lazy<T>::getWithInit(Arg1 &&arg1) {
|
||||
}
|
||||
} data{&Value, static_cast<Arg1&&>(arg1)};
|
||||
|
||||
SWIFT_ONCE_F(OnceToken, &Data::init, &data);
|
||||
swift::once(OnceToken, &Data::init, &data);
|
||||
return unsafeGetAlreadyInitialized();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "swift/Runtime/Heap.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace swift {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "Atomic.h"
|
||||
#include "Debug.h"
|
||||
#include "Mutex.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__HAIKU__)
|
||||
#include <stdio.h>
|
||||
@@ -624,7 +624,7 @@ using llvm::hash_value;
|
||||
/// process. It has no destructor, to avoid generating useless global destructor
|
||||
/// calls. The memory it allocates can be freed by calling clear() with no
|
||||
/// outstanding readers, but this won't destroy the static mutex it uses.
|
||||
template <class ElemTy, class MutexTy = StaticMutex>
|
||||
template <class ElemTy, class MutexTy = LazyMutex>
|
||||
struct ConcurrentReadableHashMap {
|
||||
// We don't call destructors. Make sure the elements will put up with this.
|
||||
static_assert(std::is_trivially_destructible<ElemTy>::value,
|
||||
@@ -1171,7 +1171,7 @@ template <class ElemTy> struct HashMapElementWrapper {
|
||||
/// by allocating them separately and storing pointers to them. The elements of
|
||||
/// the hash table are instances of HashMapElementWrapper. A new getOrInsert
|
||||
/// method is provided that directly returns the stable element pointer.
|
||||
template <class ElemTy, class Allocator, class MutexTy = StaticMutex>
|
||||
template <class ElemTy, class Allocator, class MutexTy = LazyMutex>
|
||||
struct StableAddressConcurrentReadableHashMap
|
||||
: public ConcurrentReadableHashMap<HashMapElementWrapper<ElemTy>, MutexTy> {
|
||||
// Implicitly trivial destructor.
|
||||
|
||||
@@ -232,22 +232,6 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
|
||||
// so changing this value is not sufficient.
|
||||
#define SWIFT_DEFAULT_LLVM_CC llvm::CallingConv::C
|
||||
|
||||
// SWIFT_FORMAT(fmt,first) marks a function as taking a format string argument
|
||||
// at argument `fmt`, with the first argument for the format string as `first`.
|
||||
#if __has_attribute(format)
|
||||
#define SWIFT_FORMAT(fmt,first) __attribute__((format(printf, fmt, first)))
|
||||
#else
|
||||
#define SWIFT_FORMAT(fmt,first)
|
||||
#endif
|
||||
|
||||
// SWIFT_VFORMAT(fmt) marks a function as taking a format string argument at
|
||||
// argument `fmt`, with the arguments in a `va_list`.
|
||||
#if __has_attribute(format)
|
||||
#define SWIFT_VFORMAT(fmt) __attribute__((format(printf, fmt, 0)))
|
||||
#else
|
||||
#define SWIFT_VFORMAT(fmt)
|
||||
#endif
|
||||
|
||||
/// Should we use absolute function pointers instead of relative ones?
|
||||
/// WebAssembly target uses it by default.
|
||||
#ifndef SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../Basic/Lazy.h"
|
||||
#include "swift/Threading/Once.h"
|
||||
|
||||
namespace swift {
|
||||
namespace runtime {
|
||||
@@ -22,7 +22,7 @@ namespace environment {
|
||||
|
||||
void initialize(void *);
|
||||
|
||||
extern OnceToken_t initializeToken;
|
||||
extern swift::once_t initializeToken;
|
||||
|
||||
// Declare backing variables.
|
||||
#define VARIABLE(name, type, defaultValue, help) extern type name ## _variable;
|
||||
@@ -31,7 +31,7 @@ extern OnceToken_t initializeToken;
|
||||
// Define getter functions.
|
||||
#define VARIABLE(name, type, defaultValue, help) \
|
||||
inline type name() { \
|
||||
SWIFT_ONCE_F(initializeToken, initialize, nullptr); \
|
||||
swift::once(initializeToken, initialize, nullptr); \
|
||||
return name ## _variable; \
|
||||
}
|
||||
#include "../../../stdlib/public/runtime/EnvironmentVariables.def"
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
//===--- MutexC11.h - Supports Mutex.h using C11 threading ------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex, Read/Write lock, and Scoped lock implementations
|
||||
// using C11 threading primtives.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_C11_H
|
||||
#define SWIFT_RUNTIME_MUTEX_C11_H
|
||||
|
||||
#include <threads.h>
|
||||
|
||||
namespace swift {
|
||||
|
||||
namespace c11threads {
|
||||
class rwlock;
|
||||
|
||||
static void fatalError(int errcode);
|
||||
static inline void handleError(int errcode) {
|
||||
if (SWIFT_LIKELY(errcode == thrd_success))
|
||||
return;
|
||||
|
||||
fatalError(errcode);
|
||||
}
|
||||
}
|
||||
|
||||
typedef ::mtx_t MutexHandle;
|
||||
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 0
|
||||
|
||||
/// C11 low-level implementation that supports Mutex
|
||||
/// found in Mutex.h
|
||||
///
|
||||
/// See Mutex
|
||||
class MutexPlatformHelper {
|
||||
public:
|
||||
static MutexHandle staticInit() {
|
||||
::mtx_t mutex;
|
||||
::mtx_init(&mutex, ::mtx_plain);
|
||||
return mutex;
|
||||
}
|
||||
|
||||
static void init(MutexHandle &mutex, bool checked = false) {
|
||||
// C11 mutexes can't be checked
|
||||
c11threads::handleError(::mtx_init(&mutex, ::mtx_plain));
|
||||
}
|
||||
static void destroy(MutexHandle &mutex) {
|
||||
::mtx_destroy(&mutex);
|
||||
}
|
||||
static void lock(MutexHandle &mutex) {
|
||||
c11threads::handleError(::mtx_lock(&mutex));
|
||||
}
|
||||
static void unlock(MutexHandle &mutex) {
|
||||
c11threads::handleError(::mtx_unlock(&mutex));
|
||||
}
|
||||
static bool try_lock(MutexHandle &mutex) {
|
||||
int err = ::mtx_trylock(&mutex);
|
||||
switch (err) {
|
||||
case thrd_success:
|
||||
return true;
|
||||
case thrd_busy:
|
||||
return false;
|
||||
default:
|
||||
c11threads::handleError(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Skip error checking for the unsafe versions.
|
||||
static void unsafeLock(MutexHandle &mutex) {
|
||||
(void)::mtx_lock(&mutex);
|
||||
}
|
||||
static void unsafeUnlock(MutexHandle &mutex) {
|
||||
(void)::mtx_unlock(&mutex);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,115 +0,0 @@
|
||||
//===--- MutexPThread.h - Supports Mutex.h using PThreads -------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex, Read/Write lock, and Scoped lock implementations
|
||||
// using PThreads.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_PHTREAD_H
|
||||
#define SWIFT_RUNTIME_MUTEX_PHTREAD_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <os/lock.h>
|
||||
#define HAS_OS_UNFAIR_LOCK 1
|
||||
#endif
|
||||
|
||||
namespace swift {
|
||||
|
||||
#if HAS_OS_UNFAIR_LOCK
|
||||
typedef os_unfair_lock MutexHandle;
|
||||
#else
|
||||
typedef pthread_mutex_t MutexHandle;
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__HAIKU__) || defined(__wasi__)
|
||||
// At the moment CYGWIN pthreads implementation doesn't support the use of
|
||||
// constexpr for static allocation versions. The way they define things
|
||||
// results in a reinterpret_cast which violates constexpr.
|
||||
// WASI currently doesn't support threading/locking at all.
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 0
|
||||
#else
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1
|
||||
#endif
|
||||
|
||||
/// PThread low-level implementation that supports Mutex
|
||||
/// found in Mutex.h
|
||||
///
|
||||
/// See Mutex
|
||||
struct MutexPlatformHelper {
|
||||
#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
|
||||
static constexpr
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
MutexHandle
|
||||
staticInit() {
|
||||
#if HAS_OS_UNFAIR_LOCK
|
||||
return OS_UNFAIR_LOCK_INIT;
|
||||
#else
|
||||
return PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init(MutexHandle &mutex, bool checked = false);
|
||||
static void destroy(MutexHandle &mutex);
|
||||
static void lock(MutexHandle &mutex);
|
||||
static void unlock(MutexHandle &mutex);
|
||||
static bool try_lock(MutexHandle &mutex);
|
||||
|
||||
#if HAS_OS_UNFAIR_LOCK
|
||||
// os_unfair_lock always checks for errors, so just call through.
|
||||
static void unsafeLock(MutexHandle &mutex) {
|
||||
lock(mutex);
|
||||
}
|
||||
static void unsafeUnlock(MutexHandle &mutex) {
|
||||
unlock(mutex);
|
||||
}
|
||||
#else
|
||||
// Skip error checking for the unsafe versions.
|
||||
static void unsafeLock(MutexHandle &mutex) {
|
||||
(void)pthread_mutex_lock(&mutex);
|
||||
}
|
||||
static void unsafeUnlock(MutexHandle &mutex) {
|
||||
(void)pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if HAS_OS_UNFAIR_LOCK
|
||||
|
||||
inline void MutexPlatformHelper::init(os_unfair_lock &lock, bool checked) {
|
||||
(void)checked; // Unfair locks are always checked.
|
||||
lock = OS_UNFAIR_LOCK_INIT;
|
||||
}
|
||||
|
||||
inline void MutexPlatformHelper::destroy(os_unfair_lock &lock) {}
|
||||
|
||||
inline void MutexPlatformHelper::lock(os_unfair_lock &lock) {
|
||||
os_unfair_lock_lock(&lock);
|
||||
}
|
||||
|
||||
inline void MutexPlatformHelper::unlock(os_unfair_lock &lock) {
|
||||
os_unfair_lock_unlock(&lock);
|
||||
}
|
||||
|
||||
inline bool MutexPlatformHelper::try_lock(os_unfair_lock &lock) {
|
||||
return os_unfair_lock_trylock(&lock);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,41 +0,0 @@
|
||||
//===--- MutexSingleThreaded.h - --------------------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// No-op implementation of locks for single-threaded environments.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_H
|
||||
#define SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_H
|
||||
|
||||
#include "swift/Runtime/Debug.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
typedef void* MutexHandle;
|
||||
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1
|
||||
|
||||
struct MutexPlatformHelper {
|
||||
static constexpr MutexHandle staticInit() { return nullptr; }
|
||||
static void init(MutexHandle &mutex, bool checked = false) {}
|
||||
static void destroy(MutexHandle &mutex) {}
|
||||
static void lock(MutexHandle &mutex) {}
|
||||
static void unlock(MutexHandle &mutex) {}
|
||||
static bool try_lock(MutexHandle &mutex) { return true; }
|
||||
static void unsafeLock(MutexHandle &mutex) {}
|
||||
static void unsafeUnlock(MutexHandle &mutex) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,51 +0,0 @@
|
||||
//===--- MutexWin32.h - -----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex and Read/Write lock implementations using Windows Slim
|
||||
// Reader/Writer Locks and Conditional Variables.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_WIN32_H
|
||||
#define SWIFT_RUNTIME_MUTEX_WIN32_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
namespace swift {
|
||||
|
||||
typedef SRWLOCK MutexHandle;
|
||||
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1
|
||||
|
||||
struct MutexPlatformHelper {
|
||||
static constexpr MutexHandle staticInit() { return SRWLOCK_INIT; }
|
||||
static void init(MutexHandle &mutex, bool checked = false) {
|
||||
InitializeSRWLock(&mutex);
|
||||
}
|
||||
static void destroy(MutexHandle &mutex) {}
|
||||
static void lock(MutexHandle &mutex) { AcquireSRWLockExclusive(&mutex); }
|
||||
static void unlock(MutexHandle &mutex) { ReleaseSRWLockExclusive(&mutex); }
|
||||
static bool try_lock(MutexHandle &mutex) {
|
||||
return TryAcquireSRWLockExclusive(&mutex) != 0;
|
||||
}
|
||||
// The unsafe versions don't do error checking.
|
||||
static void unsafeLock(MutexHandle &mutex) {
|
||||
AcquireSRWLockExclusive(&mutex);
|
||||
}
|
||||
static void unsafeUnlock(MutexHandle &mutex) {
|
||||
ReleaseSRWLockExclusive(&mutex);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,40 +17,18 @@
|
||||
#ifndef SWIFT_RUNTIME_ONCE_H
|
||||
#define SWIFT_RUNTIME_ONCE_H
|
||||
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_DARWIN
|
||||
#include <dispatch/dispatch.h>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
#include "swift/Threading/Once.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
|
||||
typedef bool swift_once_t;
|
||||
|
||||
#elif SWIFT_STDLIB_THREADING_DARWIN
|
||||
|
||||
// On OS X and iOS, swift_once_t is really a dispatch_once_t.
|
||||
typedef dispatch_once_t swift_once_t;
|
||||
|
||||
#elif defined(__CYGWIN__)
|
||||
|
||||
// On Cygwin, std::once_flag can not be used because it is larger than the
|
||||
// platform word.
|
||||
typedef uintptr_t swift_once_t;
|
||||
#else
|
||||
|
||||
// On other platforms swift_once_t is std::once_flag
|
||||
typedef std::once_flag swift_once_t;
|
||||
|
||||
#endif
|
||||
typedef swift::once_t swift_once_t;
|
||||
|
||||
/// Runs the given function with the given context argument exactly once.
|
||||
/// The predicate argument must point to a global or static variable of static
|
||||
/// extent of type swift_once_t.
|
||||
///
|
||||
/// Within the runtime, you should be using swift::once, which will be faster;
|
||||
/// this is exposed so that the compiler can generate calls to it.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_once(swift_once_t *predicate, void (*fn)(void *), void *context);
|
||||
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
//===--- ThreadLocal.h - Thread-local storage -------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Declarations and macros for working with thread-local storage in the
|
||||
// Swift runtime.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_THREADLOCAL_H
|
||||
#define SWIFT_RUNTIME_THREADLOCAL_H
|
||||
|
||||
#include <type_traits>
|
||||
#include "ThreadLocalStorage.h"
|
||||
#include "Once.h"
|
||||
|
||||
/// SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL - Does the current configuration
|
||||
/// allow the use of SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL?
|
||||
#if SWIFT_STDLIB_THREADING_NONE
|
||||
// We define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL to nothing in this
|
||||
// configuration and just use a global variable, so this is okay.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1
|
||||
#elif SWIFT_STDLIB_THREADING_DARWIN
|
||||
// The pthread TLS APIs work better than C++ TLS on Apple platforms.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0
|
||||
#elif __has_feature(tls)
|
||||
// If __has_feature reports that TLS is available, use it.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1
|
||||
#elif !defined(__clang__)
|
||||
// If we're not using Clang, assume that __has_feature is unreliable
|
||||
// and that we can safely use TLS.
|
||||
#else
|
||||
// Otherwise we can't use TLS and have to fall back on something else.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0
|
||||
#endif
|
||||
|
||||
/// SWIFT_RUNTIME_THREAD_LOCAL - Declare that something is a
|
||||
/// thread-local variable in the runtime.
|
||||
#if SWIFT_STDLIB_THREADING_NONE
|
||||
// In a single-threaded runtime, thread-locals are global.
|
||||
#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL
|
||||
#elif defined(__GNUC__)
|
||||
// In GCC-compatible compilers, we prefer __thread because it's understood
|
||||
// to guarantee a constant initializer, which permits more efficient access
|
||||
// patterns.
|
||||
#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL __thread
|
||||
#else
|
||||
// Otherwise, just fall back on the standard C++ feature.
|
||||
#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
// Implementation of SWIFT_RUNTIME_DECLARE_THREAD_LOCAL
|
||||
#if !SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
#include <pthread.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
namespace swift {
|
||||
// Validate a type stored in thread-local storage, using static asserts. Such
|
||||
// types must fit in a pointer and be trivially copyable/destructible.
|
||||
#define VALIDATE_THREAD_LOCAL_TYPE(T) \
|
||||
static_assert(sizeof(T) <= sizeof(void *), \
|
||||
"cannot store more than a pointer"); \
|
||||
static_assert(std::is_trivially_copyable<T>::value, \
|
||||
"ThreadLocal values must be trivially copyable"); \
|
||||
static_assert(std::is_trivially_destructible<T>::value, \
|
||||
"ThreadLocal cleanup is not supported, stored types must be " \
|
||||
"trivially destructible");
|
||||
|
||||
// A wrapper class for thread-local storage.
|
||||
//
|
||||
// - On platforms that report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
// above, an object of this type is declared with
|
||||
// SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL. This makes the object
|
||||
// itself thread-local, and no internal support is required.
|
||||
//
|
||||
// Note that this includes platforms that don't support threading,
|
||||
// for which SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL is empty;
|
||||
// thread-local declarations then create an ordinary global.
|
||||
//
|
||||
// - On platforms that don't report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL,
|
||||
// we have to simulate thread-local storage. Fortunately, all of
|
||||
// these platforms (at least for now) support pthread_getspecific
|
||||
// or similar.
|
||||
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
template <class T>
|
||||
class ThreadLocal {
|
||||
VALIDATE_THREAD_LOCAL_TYPE(T)
|
||||
|
||||
T value;
|
||||
|
||||
public:
|
||||
constexpr ThreadLocal() {}
|
||||
|
||||
T get() { return value; }
|
||||
|
||||
void set(T newValue) { value = newValue; }
|
||||
};
|
||||
#else
|
||||
// A wrapper around a __swift_thread_key_t that is lazily initialized using
|
||||
// dispatch_once.
|
||||
class ThreadLocalKey {
|
||||
// We rely on the zero-initialization of objects with static storage
|
||||
// duration.
|
||||
swift_once_t once;
|
||||
__swift_thread_key_t key;
|
||||
|
||||
public:
|
||||
__swift_thread_key_t getKey() {
|
||||
swift_once(&once, [](void *ctx) {
|
||||
SWIFT_THREAD_KEY_CREATE(reinterpret_cast<__swift_thread_key_t *>(ctx),
|
||||
nullptr);
|
||||
}, &key);
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
// A type representing a constant __swift_thread_key_t, for use on platforms
|
||||
// that provide reserved keys.
|
||||
template <__swift_thread_key_t constantKey>
|
||||
class ConstantThreadLocalKey {
|
||||
public:
|
||||
__swift_thread_key_t getKey() { return constantKey; }
|
||||
};
|
||||
|
||||
template <class T, class Key>
|
||||
class ThreadLocal {
|
||||
VALIDATE_THREAD_LOCAL_TYPE(T)
|
||||
|
||||
Key key;
|
||||
|
||||
public:
|
||||
constexpr ThreadLocal() {}
|
||||
|
||||
T get() {
|
||||
void *storedValue = SWIFT_THREAD_GETSPECIFIC(key.getKey());
|
||||
T value;
|
||||
memcpy(&value, &storedValue, sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
void set(T newValue) {
|
||||
void *storedValue;
|
||||
memcpy(&storedValue, &newValue, sizeof(T));
|
||||
SWIFT_THREAD_SETSPECIFIC(key.getKey(), storedValue);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
/// SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME) - Declare a variable
|
||||
/// to be a thread-local variable. The declaration must have static
|
||||
/// storage duration; it may be prefixed with "static".
|
||||
///
|
||||
/// Because of the fallback path, the default-initialization of the
|
||||
/// type must be equivalent to a bitwise zero-initialization, and the
|
||||
/// type must be small and trivially copyable and destructible.
|
||||
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
|
||||
SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL swift::ThreadLocal<TYPE> NAME
|
||||
#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
|
||||
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
|
||||
swift::ThreadLocal<TYPE, ConstantThreadLocalKey<KEY>> NAME
|
||||
#else
|
||||
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
|
||||
swift::ThreadLocal<TYPE, ThreadLocalKey> NAME
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,114 +0,0 @@
|
||||
//===--- ThreadLocalStorage.h - Thread-local storage interface. --*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_THREADLOCALSTORAGE_H
|
||||
#define SWIFT_RUNTIME_THREADLOCALSTORAGE_H
|
||||
|
||||
#include "swift/Runtime/Config.h"
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_DARWIN || SWIFT_STDLIB_THREADING_PTHREADS
|
||||
#include <pthread.h>
|
||||
#elif SWIFT_STDLIB_THREADING_C11
|
||||
#include <threads.h>
|
||||
#elif SWIFT_STDLIB_THREADING_WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
|
||||
// Depending on the target, we may be able to use dedicated TSD keys or
|
||||
// thread_local variables. When dedicated TSD keys aren't available,
|
||||
// wrap the target's API for thread-local data for things that don't want
|
||||
// to use thread_local.
|
||||
|
||||
// On Apple platforms, we have dedicated TSD keys.
|
||||
#if SWIFT_STDLIB_THREADING_DARWIN
|
||||
# define SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC 1
|
||||
// Use reserved TSD keys.
|
||||
# if __has_include(<pthread/tsd_private.h>)
|
||||
# include <pthread/tsd_private.h>
|
||||
# else
|
||||
// We still need to use the SPI for setting the destructor, so declare it here.
|
||||
extern "C" int pthread_key_init_np(int key, void (*destructor)(void *));
|
||||
#define SWIFT_THREAD_KEY_INIT pthread_key_init_np
|
||||
# endif
|
||||
|
||||
// If the keys are not available from the header, define them ourselves. The values match
|
||||
// what tsd_private.h provides.
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY0
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY0 100
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY1
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY1 101
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY2
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY2 102
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY3
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY3 103
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY4
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY4 104
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY5
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY5 105
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY6
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY6 106
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY7
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY7 107
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY8
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY8 108
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY9
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY9 109
|
||||
# endif
|
||||
|
||||
|
||||
# define SWIFT_RUNTIME_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY0
|
||||
# define SWIFT_STDLIB_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY1
|
||||
# define SWIFT_COMPATIBILITY_50_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY2
|
||||
# define SWIFT_CONCURRENCY_TASK_KEY __PTK_FRAMEWORK_SWIFT_KEY3
|
||||
# define SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY __PTK_FRAMEWORK_SWIFT_KEY4
|
||||
# define SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY \
|
||||
__PTK_FRAMEWORK_SWIFT_KEY5
|
||||
|
||||
#endif
|
||||
|
||||
// If the reserved key path didn't already provide get/setspecific macros,
|
||||
// wrap the platform's APIs.
|
||||
#ifndef SWIFT_THREAD_GETSPECIFIC
|
||||
|
||||
// Pick the right typedef for the key.
|
||||
#if SWIFT_STDLIB_THREADING_WIN32
|
||||
typedef DWORD __swift_thread_key_t;
|
||||
# define SWIFT_THREAD_KEY_CREATE _stdlib_thread_key_create
|
||||
# define SWIFT_THREAD_GETSPECIFIC FlsGetValue
|
||||
# define SWIFT_THREAD_SETSPECIFIC(key, value) (FlsSetValue(key, value) == FALSE)
|
||||
#elif SWIFT_STDLIB_THREADING_PTHREADS || SWIFT_STDLIB_THREADING_DARWIN
|
||||
typedef pthread_key_t __swift_thread_key_t;
|
||||
# define SWIFT_THREAD_KEY_CREATE pthread_key_create
|
||||
# define SWIFT_THREAD_GETSPECIFIC pthread_getspecific
|
||||
# define SWIFT_THREAD_SETSPECIFIC pthread_setspecific
|
||||
#elif SWIFT_STDLIB_THREADING_C11
|
||||
typedef tss_t __swift_thread_key_t;
|
||||
# define SWIFT_THREAD_KEY_CREATE tss_create
|
||||
# define SWIFT_THREAD_GETSPECIFIC tss_get
|
||||
# define SWIFT_THREAD_SETSPECIFIC tss_set
|
||||
#else
|
||||
typedef unsigned long __swift_thread_key_t;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_RUNTIME_THREADLOCALSTORAGE_H
|
||||
@@ -22,7 +22,7 @@
|
||||
// swift-corelibs-libdispatch has os/voucher_private.h but it doesn't work for
|
||||
// us yet, so only look for it on Apple platforms. We also don't need vouchers
|
||||
// in the single threaded concurrency runtime.
|
||||
#if __APPLE__ && !SWIFT_STDLIB_THREADING_NONE \
|
||||
#if __APPLE__ && !SWIFT_THREADING_NONE \
|
||||
&& __has_include(<os/voucher_private.h>)
|
||||
#define SWIFT_HAS_VOUCHER_HEADER 1
|
||||
#include <os/voucher_private.h>
|
||||
|
||||
35
include/swift/Threading/Errors.h
Normal file
35
include/swift/Threading/Errors.h
Normal file
@@ -0,0 +1,35 @@
|
||||
//==--- Errors.h - Threading implementation error handling ----- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Declares some support routines for error handling in the threading code
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_ERRORS_H
|
||||
#define SWIFT_THREADING_ERRORS_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "swift/Basic/Compiler.h"
|
||||
|
||||
namespace swift {
|
||||
namespace threading {
|
||||
|
||||
// Users of the threading library are expected to provide this function.
|
||||
SWIFT_ATTRIBUTE_NORETURN
|
||||
SWIFT_FORMAT(1, 2)
|
||||
void fatal(const char *msg, ...);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SWIFT_THREADING_ERRORS_H
|
||||
37
include/swift/Threading/Impl.h
Normal file
37
include/swift/Threading/Impl.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//===--- Impl.h - Threading abstraction implementation -------- -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Includes the relevant implementation file based on the selected threading
|
||||
// package.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_H
|
||||
#define SWIFT_THREADING_IMPL_H
|
||||
|
||||
#if SWIFT_THREADING_NONE
|
||||
#include "Impl/Nothreads.h"
|
||||
#elif SWIFT_THREADING_DARWIN
|
||||
#include "Impl/Darwin.h"
|
||||
#elif SWIFT_THREADING_LINUX
|
||||
#include "Impl/Linux.h"
|
||||
#elif SWIFT_THREADING_PTHREADS
|
||||
#include "Impl/Pthreads.h"
|
||||
#elif SWIFT_THREADING_C11
|
||||
#include "Impl/C11.h"
|
||||
#elif SWIFT_THREADING_WIN32
|
||||
#include "Impl/Win32.h"
|
||||
#else
|
||||
#error You need to implement Threading/Impl.h for your threading package.
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_H
|
||||
180
include/swift/Threading/Impl/C11.h
Normal file
180
include/swift/Threading/Impl/C11.h
Normal file
@@ -0,0 +1,180 @@
|
||||
//==--- C11.h - Threading abstraction implementation ----------- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for C11 threads
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_C11_H
|
||||
#define SWIFT_THREADING_IMPL_C11_H
|
||||
|
||||
#include <threads.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
namespace swift {
|
||||
namespace threading_impl {
|
||||
|
||||
#define SWIFT_C11THREADS_CHECK(expr) \
|
||||
do { \
|
||||
int res_ = (expr); \
|
||||
if (res_ != thrd_success) \
|
||||
swift::threading::fatal(#expr " failed with error %d\n", res_); \
|
||||
} while (0)
|
||||
|
||||
#define SWIFT_C11THREADS_RETURN_TRUE_OR_FALSE(expr) \
|
||||
do { \
|
||||
int res_ = (expr); \
|
||||
switch (res_) { \
|
||||
case thrd_success: \
|
||||
return true; \
|
||||
case thrd_busy: \
|
||||
return false; \
|
||||
default: \
|
||||
swift::threading::fatal(#expr " failed with error (%d)\n", res_); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
// .. Thread related things ..................................................
|
||||
|
||||
using thread_id = ::thrd_t;
|
||||
|
||||
inline thread_id thread_get_current() { return ::thrd_current(); }
|
||||
thread_id thread_get_main();
|
||||
bool thread_is_main();
|
||||
inline bool threads_same(thread_id a, thread_id b) {
|
||||
return ::thrd_equal(a, b);
|
||||
}
|
||||
|
||||
// .. Mutex support ..........................................................
|
||||
|
||||
using mutex_handle = ::mtx_t;
|
||||
|
||||
inline void mutex_init(mutex_handle &handle, bool checked=false) {
|
||||
SWIFT_C11THREADS_CHECK(::mtx_init(&handle), ::mtx_plain);
|
||||
}
|
||||
inline void mutex_destroy(mutex_handle &handle) {
|
||||
SWIFT_C11THREADS_CHECK(::mtx_destroy(&handle));
|
||||
}
|
||||
|
||||
inline void mutex_lock(mutex_handle &handle) {
|
||||
SWIFT_C11THREADS_CHECK(::mtx_lock(&handle));
|
||||
}
|
||||
inline void mutex_unlock(mutex_handle &handle) {
|
||||
SWIFT_C11THREADS_CHECK(::mtx_unlock(&handle));
|
||||
}
|
||||
inline bool mutex_try_lock(mutex_handle &handle) {
|
||||
SWIFT_C11THREADS_RETURN_TRUE_OR_FALSE(::mtx_trylock(&handle));
|
||||
}
|
||||
|
||||
inline void mutex_unsafe_lock(mutex_handle &handle) {
|
||||
(void)::mtx_lock(&handle);
|
||||
}
|
||||
inline void mutex_unsafe_unlock(mutex_handle &handle) {
|
||||
(void)::mtx_unlock(&handle);
|
||||
}
|
||||
|
||||
struct lazy_mutex_handle {
|
||||
::mtx_t mutex;
|
||||
::atomic_int once; // -1 = initialized, 0 = uninitialized, 1 = initializing
|
||||
};
|
||||
|
||||
inline constexpr lazy_mutex_handle lazy_mutex_initializer() {
|
||||
return (lazy_mutex_handle){0};
|
||||
}
|
||||
inline void lazy_mutex_init(lazy_mutex_handle &handle) {
|
||||
// Sadly, we can't use call_once() for this as it doesn't have a context
|
||||
if (::atomic_load_explicit(&handle.once, ::memory_order_acquire) < 0)
|
||||
return;
|
||||
|
||||
if (::atomic_compare_exchange_strong_explicit(&handle.once,
|
||||
&(int){ 0 },
|
||||
1,
|
||||
::memory_order_relaxed,
|
||||
::memory_order_relaxed)) {
|
||||
SWIFT_C11THREADS_CHECK(::mtx_init(&handle.mutex, ::mtx_plain));
|
||||
::atomic_store_explicit(&handle.once, -1, ::memory_order_release);
|
||||
return;
|
||||
}
|
||||
|
||||
while (::atomic_load_explicit(&handle.once, memory_order_acquire) >= 0) {
|
||||
// Just spin; ::mtx_init() is very likely to be fast
|
||||
}
|
||||
}
|
||||
|
||||
inline void lazy_mutex_destroy(lazy_mutex_handle &handle) {
|
||||
if (::atomic_load_explicit(&handle.once, ::memory_order_acquire) < 0)
|
||||
SWIFT_C11THREADS_CHECK(::mtx_destroy(&handle.mutex));
|
||||
}
|
||||
|
||||
inline void lazy_mutex_lock(lazy_mutex_handle &handle) {
|
||||
lazy_mutex_init(handle);
|
||||
SWIFT_C11THREADS_CHECK(::mtx_lock(&handle.mutex));
|
||||
}
|
||||
inline void lazy_mutex_unlock(lazy_mutex_handle &handle) {
|
||||
lazy_mutex_init(handle);
|
||||
SWIFT_C11THREADS_CHECK(::mtx_unlock(&handle.mutex));
|
||||
}
|
||||
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) {
|
||||
lazy_mutex_init(handle);
|
||||
SWIFT_C11THREADS_RETURN_TRUE_OR_FALSE(::mtx_trylock(&handle.mutex));
|
||||
}
|
||||
|
||||
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) {
|
||||
lazy_mutex_init(handle);
|
||||
(void)::mtx_lock(&handle.mutex);
|
||||
}
|
||||
inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) {
|
||||
lazy_mutex_init(handle);
|
||||
(void)::mtx_unlock(&handle.mutex);
|
||||
}
|
||||
|
||||
// .. Once ...................................................................
|
||||
|
||||
typedef ::atomic_int once_t;
|
||||
|
||||
void once_slow(once_t &predicate, void (*fn)(void *), void *context);
|
||||
|
||||
inline void once(once_t &predicate, void (*fn)(void *), void *context) {
|
||||
// Sadly we can't use call_once() for this (no context)
|
||||
if (::atomic_load_explicit(&predicate, ::memory_order_acquire) < 0)
|
||||
return;
|
||||
|
||||
once_slow(predicate, fn, context);
|
||||
}
|
||||
|
||||
// .. Thread local storage ...................................................
|
||||
|
||||
#if __cplusplus >= 201103L || __has_feature(cxx_thread_local)
|
||||
#define SWIFT_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
using tls_key = ::tss_t;
|
||||
using tls_dtor = void (*)(void *);
|
||||
|
||||
inline bool tls_alloc(tls_key &key, tls_dtor dtor) {
|
||||
return ::tss_create(&key, dtor) == thrd_success;
|
||||
}
|
||||
|
||||
inline void *tls_get(tls_key key) {
|
||||
return ::tss_get(key);
|
||||
}
|
||||
|
||||
inline void tls_set(tls_key key, void *ptr) {
|
||||
::tss_set(key, ptr);
|
||||
}
|
||||
|
||||
} // namespace threading_impl
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_C11_H
|
||||
177
include/swift/Threading/Impl/Darwin.h
Normal file
177
include/swift/Threading/Impl/Darwin.h
Normal file
@@ -0,0 +1,177 @@
|
||||
//==--- Darwin.h - Threading abstraction implementation -------- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for Apple platforms
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_DARWIN_H
|
||||
#define SWIFT_THREADING_IMPL_DARWIN_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <os/lock.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
|
||||
#include "swift/Threading/Errors.h"
|
||||
|
||||
namespace swift {
|
||||
namespace threading_impl {
|
||||
|
||||
// .. Thread related things ..................................................
|
||||
|
||||
using thread_id = ::pthread_t;
|
||||
|
||||
inline thread_id thread_get_current() { return ::pthread_self(); }
|
||||
|
||||
thread_id thread_get_main();
|
||||
bool thread_is_main();
|
||||
|
||||
inline bool threads_same(thread_id a, thread_id b) {
|
||||
return ::pthread_equal(a, b);
|
||||
}
|
||||
|
||||
// .. Mutex support ..........................................................
|
||||
|
||||
using mutex_handle = ::os_unfair_lock;
|
||||
|
||||
inline void mutex_init(mutex_handle &handle, bool checked=false) {
|
||||
handle = OS_UNFAIR_LOCK_INIT;
|
||||
}
|
||||
inline void mutex_destroy(mutex_handle &handle) { }
|
||||
|
||||
inline void mutex_lock(mutex_handle &handle) {
|
||||
::os_unfair_lock_lock(&handle);
|
||||
}
|
||||
inline void mutex_unlock(mutex_handle &handle) {
|
||||
::os_unfair_lock_unlock(&handle);
|
||||
}
|
||||
inline bool mutex_try_lock(mutex_handle &handle) {
|
||||
return ::os_unfair_lock_trylock(&handle);
|
||||
}
|
||||
|
||||
inline void mutex_unsafe_lock(mutex_handle &handle) {
|
||||
::os_unfair_lock_lock(&handle);
|
||||
}
|
||||
inline void mutex_unsafe_unlock(mutex_handle &handle) {
|
||||
::os_unfair_lock_unlock(&handle);
|
||||
}
|
||||
|
||||
using lazy_mutex_handle = ::os_unfair_lock;
|
||||
|
||||
// We don't need to be lazy here because Darwin has OS_UNFAIR_LOCK_INIT.
|
||||
inline constexpr lazy_mutex_handle lazy_mutex_initializer() {
|
||||
return OS_UNFAIR_LOCK_INIT;
|
||||
}
|
||||
inline void lazy_mutex_destroy(lazy_mutex_handle &handle) { }
|
||||
|
||||
inline void lazy_mutex_lock(lazy_mutex_handle &handle) {
|
||||
::os_unfair_lock_lock(&handle);
|
||||
}
|
||||
inline void lazy_mutex_unlock(lazy_mutex_handle &handle) {
|
||||
::os_unfair_lock_unlock(&handle);
|
||||
}
|
||||
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) {
|
||||
return ::os_unfair_lock_trylock(&handle);
|
||||
}
|
||||
|
||||
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) {
|
||||
::os_unfair_lock_lock(&handle);
|
||||
}
|
||||
inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) {
|
||||
::os_unfair_lock_unlock(&handle);
|
||||
}
|
||||
|
||||
// .. Once ...................................................................
|
||||
|
||||
using once_t = ::dispatch_once_t;
|
||||
|
||||
inline void once(once_t &predicate, void (*fn)(void *), void *context) {
|
||||
dispatch_once_f(&predicate, context, fn);
|
||||
}
|
||||
|
||||
// .. Thread local storage ...................................................
|
||||
|
||||
// On Darwin, we want to use the reserved keys
|
||||
#define SWIFT_THREADING_USE_RESERVED_TLS_KEYS 1
|
||||
|
||||
#if __has_include(<pthread/tsd_private.h>)
|
||||
#include <pthread/tsd_private.h>
|
||||
#else
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY0 100
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY1 101
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY2 102
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY3 103
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY4 104
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY5 105
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY6 106
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY7 107
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY8 108
|
||||
#define __PTK_FRAMEWORK_SWIFT_KEY9 109
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern int pthread_key_init_np(int, void (*)(void *));
|
||||
|
||||
inline bool _pthread_has_direct_tsd() { return false; }
|
||||
inline void *_pthread_getspecific_direct(pthread_key_t k) {
|
||||
return pthread_getspecific(k);
|
||||
}
|
||||
inline void _pthread_setspecific_direct(pthread_key_t k, void *v) {
|
||||
pthread_setspecific(k, v);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SWIFT_RUNTIME_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY0
|
||||
#define SWIFT_STDLIB_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY1
|
||||
#define SWIFT_COMPATIBILITY_50_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY2
|
||||
#define SWIFT_CONCURRENCY_TASK_KEY __PTK_FRAMEWORK_SWIFT_KEY3
|
||||
#define SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY __PTK_FRAMEWORK_SWIFT_KEY4
|
||||
#define SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY __PTK_FRAMEWORK_SWIFT_KEY5
|
||||
#define SWIFT_RESERVED_TLS_KEY_6 __PTK_FRAMEWORK_SWIFT_KEY6
|
||||
#define SWIFT_RESERVED_TLS_KEY_7 __PTK_FRAMEWORK_SWIFT_KEY7
|
||||
#define SWIFT_RESERVED_TLS_KEY_8 __PTK_FRAMEWORK_SWIFT_KEY8
|
||||
#define SWIFT_RESERVED_TLS_KEY_9 __PTK_FRAMEWORK_SWIFT_KEY9
|
||||
|
||||
#define SWIFT_TLS_DECLARE_DTOR(name) void name(void *)
|
||||
|
||||
using tls_key = pthread_key_t;
|
||||
using tls_dtor = void (*)(void *);
|
||||
|
||||
inline bool tls_init(tls_key key, tls_dtor dtor) {
|
||||
return pthread_key_init_np(key, dtor) == 0;
|
||||
}
|
||||
|
||||
inline bool tls_alloc(tls_key &key, tls_dtor dtor) {
|
||||
return pthread_key_create(&key, dtor) == 0;
|
||||
}
|
||||
|
||||
inline void *tls_get(tls_key key) {
|
||||
if (_pthread_has_direct_tsd())
|
||||
return _pthread_getspecific_direct(key);
|
||||
else
|
||||
return pthread_getspecific(key);
|
||||
}
|
||||
|
||||
inline void tls_set(tls_key key, void *value) {
|
||||
if (_pthread_has_direct_tsd())
|
||||
_pthread_setspecific_direct(key, value);
|
||||
else
|
||||
pthread_setspecific(key, value);
|
||||
}
|
||||
|
||||
} // namespace threading_impl
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_DARWIN_H
|
||||
168
include/swift/Threading/Impl/Linux.h
Normal file
168
include/swift/Threading/Impl/Linux.h
Normal file
@@ -0,0 +1,168 @@
|
||||
//==--- Pthreads.h - Threading abstraction implementation ------ -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for Linux
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_LINUX_H
|
||||
#define SWIFT_THREADING_IMPL_LINUX_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <atomic>
|
||||
#include "swift/Threading/Errors.h"
|
||||
|
||||
#include "Linux/ulock.h"
|
||||
|
||||
namespace swift {
|
||||
namespace threading_impl {
|
||||
|
||||
#define SWIFT_LINUXTHREADS_CHECK(expr) \
|
||||
do { \
|
||||
int res_ = (expr); \
|
||||
if (res_ != 0) \
|
||||
swift::threading::fatal(#expr " failed with error %d\n", res_); \
|
||||
} while (0)
|
||||
|
||||
#define SWIFT_PTHREADS_RETURN_TRUE_OR_FALSE(expr) \
|
||||
do { \
|
||||
int res_ = (expr); \
|
||||
switch (res_) { \
|
||||
case 0: \
|
||||
return true; \
|
||||
case EBUSY: \
|
||||
return false; \
|
||||
default: \
|
||||
swift::threading::fatal(#expr " failed with error (%d)\n", res_); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// .. Thread related things ..................................................
|
||||
|
||||
using thread_id = ::pthread_t;
|
||||
|
||||
inline thread_id thread_get_current() { return ::pthread_self(); }
|
||||
|
||||
thread_id thread_get_main();
|
||||
bool thread_is_main();
|
||||
|
||||
inline bool threads_same(thread_id a, thread_id b) {
|
||||
return ::pthread_equal(a, b);
|
||||
}
|
||||
|
||||
// .. Mutex support ..........................................................
|
||||
|
||||
using mutex_handle = ::pthread_mutex_t;
|
||||
|
||||
inline void mutex_init(mutex_handle &handle, bool checked=false) {
|
||||
if (!checked) {
|
||||
handle = PTHREAD_MUTEX_INITIALIZER;
|
||||
} else {
|
||||
::pthread_mutexattr_t attr;
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutexattr_init(&attr));
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutexattr_settype(&attr,
|
||||
PTHREAD_MUTEX_ERRORCHECK));
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutexattr_destroy(&attr));
|
||||
}
|
||||
}
|
||||
inline void mutex_destroy(mutex_handle &handle) {
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_destroy(&handle));
|
||||
}
|
||||
|
||||
inline void mutex_lock(mutex_handle &handle) {
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_lock(&handle));
|
||||
}
|
||||
inline void mutex_unlock(mutex_handle &handle) {
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_unlock(&handle));
|
||||
}
|
||||
inline bool mutex_try_lock(mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_RETURN_TRUE_OR_FALSE(::pthread_mutex_trylock(&handle));
|
||||
}
|
||||
|
||||
inline void mutex_unsafe_lock(mutex_handle &handle) {
|
||||
(void)::pthread_mutex_lock(&handle);
|
||||
}
|
||||
inline void mutex_unsafe_unlock(mutex_handle &handle) {
|
||||
(void)::pthread_mutex_unlock(&handle);
|
||||
}
|
||||
|
||||
using lazy_mutex_handle = ::pthread_mutex_t;
|
||||
|
||||
// We don't actually need to be lazy here because pthreads has
|
||||
// PTHREAD_MUTEX_INITIALIZER.
|
||||
inline constexpr lazy_mutex_handle lazy_mutex_initializer() {
|
||||
return PTHREAD_MUTEX_INITIALIZER;
|
||||
}
|
||||
inline void lazy_mutex_destroy(lazy_mutex_handle &handle) {
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_destroy(&handle));
|
||||
}
|
||||
|
||||
inline void lazy_mutex_lock(lazy_mutex_handle &handle) {
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_lock(&handle));
|
||||
}
|
||||
inline void lazy_mutex_unlock(lazy_mutex_handle &handle) {
|
||||
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_unlock(&handle));
|
||||
}
|
||||
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_RETURN_TRUE_OR_FALSE(::pthread_mutex_trylock(&handle));
|
||||
}
|
||||
|
||||
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) {
|
||||
(void)::pthread_mutex_lock(&handle);
|
||||
}
|
||||
inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) {
|
||||
(void)::pthread_mutex_unlock(&handle);
|
||||
}
|
||||
|
||||
// .. Once ...................................................................
|
||||
|
||||
struct once_t {
|
||||
std::atomic<std::int32_t> flag;
|
||||
linux::ulock_t lock;
|
||||
};
|
||||
|
||||
using once_t = std::atomic<int>;
|
||||
|
||||
inline void once(once_t &predicate, void (*fn)(void *), void *context) {
|
||||
// Sadly we can't use ::pthread_once() for this (no context)
|
||||
if (predicate.load(std::memory_order_acquire) < 0)
|
||||
return;
|
||||
|
||||
once_slow(predicate, fn, context);
|
||||
}
|
||||
|
||||
// .. Thread local storage ...................................................
|
||||
|
||||
#if __cplusplus >= 201103L || __has_feature(cxx_thread_local)
|
||||
#define SWIFT_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
using tls_key = pthread_key_t;
|
||||
using tls_dtor = void (*)(void *);
|
||||
|
||||
inline bool tls_alloc(tls_key &key, tls_dtor dtor) {
|
||||
return pthread_key_create(&key, dtor) == 0;
|
||||
}
|
||||
|
||||
inline void *tls_get(tls_key key) {
|
||||
return pthread_getspecific(key);
|
||||
}
|
||||
|
||||
inline void tls_set(tls_key key, void *value) {
|
||||
pthread_setspecific(key, value);
|
||||
}
|
||||
|
||||
} // namespace threading_impl
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_PTHREADS_H
|
||||
99
include/swift/Threading/Impl/Linux/ulock.h
Normal file
99
include/swift/Threading/Impl/Linux/ulock.h
Normal file
@@ -0,0 +1,99 @@
|
||||
//==--- ulock.h - 32-bit futex-based lock for Linux ------------ -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements a 32-bit futex-based locking primitive with priority inversion
|
||||
// support.
|
||||
//
|
||||
// This has comparable performance to pthread_mutex_t (on x86-64, it's slower
|
||||
// under contention, but not much different otherwise; other architectures may
|
||||
// vary), but it only takes up 32 bits instead of 40 *bytes*.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_LINUX_ULOCK_H
|
||||
#define SWIFT_THREADING_IMPL_LINUX_ULOCK_H
|
||||
|
||||
// This file is specific to Linux; we're just going to assume we can use
|
||||
// various GCC/Clang extensions here.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
namespace swift {
|
||||
namespace threading_impl {
|
||||
namespace linux {
|
||||
|
||||
typedef std::int32_t ulock_t;
|
||||
|
||||
#define ULOCK_INITIALIZER 0
|
||||
#define ulock_fastpath(x) __builtin_expect((x), true)
|
||||
|
||||
inline int ulock_get_tid(void) {
|
||||
static __thread int tid;
|
||||
if (tid == 0)
|
||||
tid = gettid();
|
||||
return tid;
|
||||
}
|
||||
|
||||
inline int ulock_futex(ulock_t *lock, int op) {
|
||||
return syscall(SYS_futex, lock, op | FUTEX_PRIVATE_FLAG,
|
||||
0, nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
} while (ulock_futex(lock, FUTEX_LOCK_PI) != 0);
|
||||
}
|
||||
|
||||
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)))
|
||||
return true;
|
||||
|
||||
return ulock_futex(lock, FUTEX_TRYLOCK_PI) == 0;
|
||||
}
|
||||
|
||||
inline void ulock_unlock(ulock_t *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;
|
||||
|
||||
} while (ulock_futex(lock, FUTEX_UNLOCK_PI) != 0);
|
||||
}
|
||||
|
||||
} // namespace linux
|
||||
} // namespace threading_impl
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_LINUX_ULOCK_H
|
||||
76
include/swift/Threading/Impl/Nothreads.h
Normal file
76
include/swift/Threading/Impl/Nothreads.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//==--- Nothreads.h - Threading abstraction implementation ----- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for platforms without threading
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_NOTHREADS_H
|
||||
#define SWIFT_THREADING_IMPL_NOTHREADS_H
|
||||
|
||||
namespace swift {
|
||||
namespace threading_impl {
|
||||
|
||||
// .. Thread related things ..................................................
|
||||
|
||||
using thread_id = unsigned;
|
||||
|
||||
inline thread_id thread_get_current() { return 0; }
|
||||
inline thread_id thread_get_main() { return 0; }
|
||||
inline bool thread_is_main() { return true; }
|
||||
inline bool threads_same(thread_id a, thread_id b) { return a == b; }
|
||||
|
||||
// .. Mutex support ..........................................................
|
||||
|
||||
using mutex_handle = unsigned;
|
||||
|
||||
inline void mutex_init(mutex_handle &handle, bool checked=false) {}
|
||||
inline void mutex_destroy(mutex_handle &handle) { }
|
||||
inline void mutex_lock(mutex_handle &handle) { }
|
||||
inline void mutex_unlock(mutex_handle &handle) { }
|
||||
inline bool mutex_try_lock(mutex_handle &handle) { return true; }
|
||||
|
||||
inline void mutex_unsafe_lock(mutex_handle &handle) { }
|
||||
inline void mutex_unsafe_unlock(mutex_handle &handle) { }
|
||||
|
||||
using lazy_mutex_handle = unsigned;
|
||||
|
||||
inline constexpr lazy_mutex_handle lazy_mutex_initializer() { return 0; }
|
||||
inline void lazy_mutex_destroy(lazy_mutex_handle &handle) { }
|
||||
inline void lazy_mutex_lock(lazy_mutex_handle &handle) { }
|
||||
inline void lazy_mutex_unlock(lazy_mutex_handle &handle) { }
|
||||
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) { return true; }
|
||||
|
||||
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) { }
|
||||
inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) { }
|
||||
|
||||
// .. Once ...................................................................
|
||||
|
||||
typedef bool once_t;
|
||||
|
||||
inline void once(once_t &predicate, void (*fn)(void *), void *ctx) {
|
||||
if (!predicate) {
|
||||
predicate = true;
|
||||
fn(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// .. Thread local storage ...................................................
|
||||
|
||||
// If we have no threads, we can use the simple version of TLS
|
||||
#define SWIFT_THREAD_LOCAL
|
||||
|
||||
} // namespace threading_impl
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_NOTHREADS_H
|
||||
162
include/swift/Threading/Impl/Pthreads.h
Normal file
162
include/swift/Threading/Impl/Pthreads.h
Normal file
@@ -0,0 +1,162 @@
|
||||
//==--- Pthreads.h - Threading abstraction implementation ------ -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for plain pthreads
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_PTHREADS_H
|
||||
#define SWIFT_THREADING_IMPL_PTHREADS_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include "swift/Threading/Errors.h"
|
||||
|
||||
namespace swift {
|
||||
namespace threading_impl {
|
||||
|
||||
#define SWIFT_PTHREADS_CHECK(expr) \
|
||||
do { \
|
||||
int res_ = (expr); \
|
||||
if (res_ != 0) \
|
||||
swift::threading::fatal(#expr " failed with error %d\n", res_); \
|
||||
} while (0)
|
||||
|
||||
#define SWIFT_PTHREADS_RETURN_TRUE_OR_FALSE(expr) \
|
||||
do { \
|
||||
int res_ = (expr); \
|
||||
switch (res_) { \
|
||||
case 0: \
|
||||
return true; \
|
||||
case EBUSY: \
|
||||
return false; \
|
||||
default: \
|
||||
swift::threading::fatal(#expr " failed with error (%d)\n", res_); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// .. Thread related things ..................................................
|
||||
|
||||
using thread_id = ::pthread_t;
|
||||
|
||||
inline thread_id thread_get_current() { return ::pthread_self(); }
|
||||
|
||||
thread_id thread_get_main();
|
||||
bool thread_is_main();
|
||||
|
||||
inline bool threads_same(thread_id a, thread_id b) {
|
||||
return ::pthread_equal(a, b);
|
||||
}
|
||||
|
||||
// .. Mutex support ..........................................................
|
||||
|
||||
using mutex_handle = ::pthread_mutex_t;
|
||||
|
||||
inline void mutex_init(mutex_handle &handle, bool checked=false) {
|
||||
if (!checked) {
|
||||
handle = PTHREAD_MUTEX_INITIALIZER;
|
||||
} else {
|
||||
::pthread_mutexattr_t attr;
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutexattr_init(&attr));
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutexattr_settype(&attr,
|
||||
PTHREAD_MUTEX_ERRORCHECK));
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutexattr_destroy(&attr));
|
||||
}
|
||||
}
|
||||
inline void mutex_destroy(mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutex_destroy(&handle));
|
||||
}
|
||||
|
||||
inline void mutex_lock(mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutex_lock(&handle));
|
||||
}
|
||||
inline void mutex_unlock(mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutex_unlock(&handle));
|
||||
}
|
||||
inline bool mutex_try_lock(mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_RETURN_TRUE_OR_FALSE(::pthread_mutex_trylock(&handle));
|
||||
}
|
||||
|
||||
inline void mutex_unsafe_lock(mutex_handle &handle) {
|
||||
(void)::pthread_mutex_lock(&handle);
|
||||
}
|
||||
inline void mutex_unsafe_unlock(mutex_handle &handle) {
|
||||
(void)::pthread_mutex_unlock(&handle);
|
||||
}
|
||||
|
||||
using lazy_mutex_handle = ::pthread_mutex_t;
|
||||
|
||||
// We don't actually need to be lazy here because pthreads has
|
||||
// PTHREAD_MUTEX_INITIALIZER.
|
||||
inline constexpr lazy_mutex_handle lazy_mutex_initializer() {
|
||||
return PTHREAD_MUTEX_INITIALIZER;
|
||||
}
|
||||
inline void lazy_mutex_destroy(lazy_mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutex_destroy(&handle));
|
||||
}
|
||||
|
||||
inline void lazy_mutex_lock(lazy_mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutex_lock(&handle));
|
||||
}
|
||||
inline void lazy_mutex_unlock(lazy_mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_CHECK(::pthread_mutex_unlock(&handle));
|
||||
}
|
||||
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) {
|
||||
SWIFT_PTHREADS_RETURN_TRUE_OR_FALSE(::pthread_mutex_trylock(&handle));
|
||||
}
|
||||
|
||||
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) {
|
||||
(void)::pthread_mutex_lock(&handle);
|
||||
}
|
||||
inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) {
|
||||
(void)::pthread_mutex_unlock(&handle);
|
||||
}
|
||||
|
||||
// .. Once ...................................................................
|
||||
|
||||
using once_t = std::atomic<std::int64_t>;
|
||||
|
||||
inline void once(once_t &predicate, void (*fn)(void *), void *context) {
|
||||
// Sadly we can't use ::pthread_once() for this (no context)
|
||||
if (predicate.load(std::memory_order_acquire) < 0)
|
||||
return;
|
||||
|
||||
once_slow(predicate, fn, context);
|
||||
}
|
||||
|
||||
// .. Thread local storage ...................................................
|
||||
|
||||
#if __cplusplus >= 201103L || __has_feature(cxx_thread_local)
|
||||
#define SWIFT_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
using tls_key = pthread_key_t;
|
||||
using tls_dtor = void (*)(void *);
|
||||
|
||||
inline bool tls_alloc(tls_key &key, tls_dtor dtor) {
|
||||
return pthread_key_create(&key, dtor) == 0;
|
||||
}
|
||||
|
||||
inline void *tls_get(tls_key key) {
|
||||
return pthread_getspecific(key);
|
||||
}
|
||||
|
||||
inline void tls_set(tls_key key, void *value) {
|
||||
pthread_setspecific(key, value);
|
||||
}
|
||||
|
||||
} // namespace threading_impl
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_PTHREADS_H
|
||||
127
include/swift/Threading/Impl/Win32.h
Normal file
127
include/swift/Threading/Impl/Win32.h
Normal file
@@ -0,0 +1,127 @@
|
||||
//==--- Win32.h - Threading abstraction implementation --------- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for Windows threads
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_IMPL_WIN32_H
|
||||
#define SWIFT_THREADING_IMPL_WIN32_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace swift {
|
||||
namespace threading_impl {
|
||||
|
||||
// .. Thread related things ..................................................
|
||||
|
||||
using thread_id = DWORD;
|
||||
|
||||
inline thread_id thread_get_current() { return ::GetCurrentThreadId(); }
|
||||
thread_id thread_get_main();
|
||||
bool thread_is_main();
|
||||
inline bool threads_same(thread_id a, thread_id b) { return a == b; }
|
||||
|
||||
// .. Mutex support ..........................................................
|
||||
|
||||
using mutex_handle = SRWLOCK;
|
||||
|
||||
inline void mutex_init(mutex_handle &handle, bool checked=false) {
|
||||
handle = SRWLOCK_INIT;
|
||||
}
|
||||
inline void mutex_destroy(mutex_handle &handle) { }
|
||||
|
||||
inline void mutex_lock(mutex_handle &handle) {
|
||||
AcquireSRWLockExclusive(&handle);
|
||||
}
|
||||
inline void mutex_unlock(mutex_handle &handle) {
|
||||
ReleaseSRWLockExclusive(&handle);
|
||||
}
|
||||
inline bool mutex_try_lock(mutex_handle &handle) {
|
||||
return !!TryAcquireSRWLockExclusive(&handle);
|
||||
}
|
||||
|
||||
inline void mutex_unsafe_lock(mutex_handle &handle) {
|
||||
AcquireSRWLockExclusive(&handle);
|
||||
}
|
||||
inline void mutex_unsafe_unlock(mutex_handle &handle) {
|
||||
ReleaseSRWLockExclusive(&handle);
|
||||
}
|
||||
|
||||
using lazy_mutex_handle = SRWLOCK;
|
||||
|
||||
// We don't need to be lazy here because Win32 has SRWLOCK_INIT.
|
||||
inline void lazy_mutex_init(lazy_mutex_handle &handle) {
|
||||
handle = SRWLOCK_INIT;
|
||||
}
|
||||
inline void lazy_mutex_destroy(lazy_mutex_handle &handle) { }
|
||||
|
||||
inline void lazy_mutex_lock(lazy_mutex_handle &handle) {
|
||||
AcquireSRWLockExclusive(&handle);
|
||||
}
|
||||
inline void lazy_mutex_unlock(lazy_mutex_handle &handle) {
|
||||
ReleaseSRWLockExclusive(&handle);
|
||||
}
|
||||
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) {
|
||||
return !!TryAcquireSRWLockExclusive(&handle);
|
||||
}
|
||||
|
||||
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) {
|
||||
AcquireSRWLockExclusive(&handle);
|
||||
}
|
||||
inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) {
|
||||
ReleaseSRWLockExclusive(&handle);
|
||||
}
|
||||
|
||||
// .. Once ...................................................................
|
||||
|
||||
typedef std::atomic<int64_t> once_t;
|
||||
|
||||
inline void once(once_t &predicate, void (*fn)(void *), void *context) {
|
||||
// Using INIT_ONCE is slower than doing this.
|
||||
if (predicate.load(std::memory_order_acquire) < 0)
|
||||
return;
|
||||
|
||||
once_slow(predicate, fn, context);
|
||||
}
|
||||
|
||||
// .. Thread local storage ...................................................
|
||||
|
||||
#if __cplusplus >= 201103L || __has_feature(cxx_thread_local)
|
||||
#define SWIFT_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
#define SWIFT_TLS_DECLARE_DTOR(name) void NTAPI name(void *)
|
||||
|
||||
using tls_key = DWORD;
|
||||
using tls_dtor = void NTAPI (*)(void *);
|
||||
|
||||
inline bool tls_alloc(tls_key &key, tls_dtor dtor) {
|
||||
key = FlsAlloc(dtor);
|
||||
return key != FLS_OUT_OF_INDEXES;
|
||||
}
|
||||
|
||||
inline void *tls_get(tls_key key) {
|
||||
return FlsGetValue(key);
|
||||
}
|
||||
|
||||
inline void tls_set(tls_key key, void *value) {
|
||||
FlsSetValue(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SWIFT_THREADING_IMPL_WIN32_H
|
||||
@@ -1,8 +1,8 @@
|
||||
//===--- Mutex.h - Mutex ----------------------------------------*- C++ -*-===//
|
||||
//===--- Mutex.h - Mutex and ScopedLock ----------------------- -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Copyright (c) 2022 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
|
||||
@@ -10,44 +10,23 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex and Scoped lock abstractions for use in Swift runtime.
|
||||
//
|
||||
// We intentionally do not provide a condition-variable abstraction.
|
||||
// Traditional condition-variable interfaces are subject to unavoidable
|
||||
// priority inversions, as well as making poor use of threads.
|
||||
// Prefer AtomicWaitQueue.
|
||||
//
|
||||
// We also intentionally avoid read/write locks. It's difficult to implement a
|
||||
// performant and fair read/write lock, and indeed many common implementations
|
||||
// rely on condition variables, which, again, are subject to unavoidable
|
||||
// priority inversions.
|
||||
// Provides a system-independent Mutex abstraction, as well as some
|
||||
// related utilities like ScopedLock.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_H
|
||||
#define SWIFT_RUNTIME_MUTEX_H
|
||||
#ifndef SWIFT_THREADING_MUTEX_H
|
||||
#define SWIFT_THREADING_MUTEX_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if __has_include(<unistd.h>)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_NONE
|
||||
#include "swift/Runtime/MutexSingleThreaded.h"
|
||||
#elif SWIFT_STDLIB_THREADING_PTHREADS || SWIFT_STDLIB_THREADING_DARWIN
|
||||
#include "swift/Runtime/MutexPThread.h"
|
||||
#elif SWIFT_STDLIB_THREADING_WIN32
|
||||
#include "swift/Runtime/MutexWin32.h"
|
||||
#elif SWIFT_STDLIB_THREADING_C11
|
||||
#include "swift/Runtime/MutexC11.h"
|
||||
#else
|
||||
#error "Implement equivalent of MutexPThread.h/cpp for your platform."
|
||||
#endif
|
||||
#include "Impl.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
// -- ScopedLock ---------------------------------------------------------------
|
||||
|
||||
/// Compile time adjusted stack based object that locks/unlocks the supplied
|
||||
/// Mutex type. Use the provided typedefs instead of this directly.
|
||||
template <typename T, bool Inverted> class ScopedLockT {
|
||||
@@ -78,6 +57,8 @@ private:
|
||||
T &Lock;
|
||||
};
|
||||
|
||||
// -- Mutex --------------------------------------------------------------------
|
||||
|
||||
/// A Mutex object that supports `BasicLockable` and `Lockable` C++ concepts.
|
||||
/// See http://en.cppreference.com/w/cpp/concept/BasicLockable
|
||||
/// See http://en.cppreference.com/w/cpp/concept/Lockable
|
||||
@@ -97,9 +78,9 @@ public:
|
||||
/// fatalError when detected. If `checked` is false (the default) the
|
||||
/// mutex will make little to no effort to check for misuse (more efficient).
|
||||
explicit Mutex(bool checked = false) {
|
||||
MutexPlatformHelper::init(Handle, checked);
|
||||
threading_impl::mutex_init(Handle, checked);
|
||||
}
|
||||
~Mutex() { MutexPlatformHelper::destroy(Handle); }
|
||||
~Mutex() { threading_impl::mutex_destroy(Handle); }
|
||||
|
||||
/// The lock() method has the following properties:
|
||||
/// - Behaves as an atomic operation.
|
||||
@@ -110,7 +91,7 @@ public:
|
||||
/// - The behavior is undefined if the calling thread already owns
|
||||
/// the mutex (likely a deadlock).
|
||||
/// - Does not throw exceptions but will halt on error (fatalError).
|
||||
void lock() { MutexPlatformHelper::lock(Handle); }
|
||||
void lock() { threading_impl::mutex_lock(Handle); }
|
||||
|
||||
/// The unlock() method has the following properties:
|
||||
/// - Behaves as an atomic operation.
|
||||
@@ -120,7 +101,7 @@ public:
|
||||
/// - The behavior is undefined if the calling thread does not own
|
||||
/// the mutex.
|
||||
/// - Does not throw exceptions but will halt on error (fatalError).
|
||||
void unlock() { MutexPlatformHelper::unlock(Handle); }
|
||||
void unlock() { threading_impl::mutex_unlock(Handle); }
|
||||
|
||||
/// The try_lock() method has the following properties:
|
||||
/// - Behaves as an atomic operation.
|
||||
@@ -134,7 +115,7 @@ public:
|
||||
/// - The behavior is undefined if the calling thread already owns
|
||||
/// the mutex (likely a deadlock)?
|
||||
/// - Does not throw exceptions but will halt on error (fatalError).
|
||||
bool try_lock() { return MutexPlatformHelper::try_lock(Handle); }
|
||||
bool try_lock() { return threading_impl::mutex_try_lock(Handle); }
|
||||
|
||||
/// Acquires lock before calling the supplied critical section and releases
|
||||
/// lock on return from critical section.
|
||||
@@ -167,38 +148,50 @@ public:
|
||||
/// Precondition: Mutex locked by this thread, undefined otherwise.
|
||||
typedef ScopedLockT<Mutex, true> ScopedUnlock;
|
||||
|
||||
private:
|
||||
MutexHandle Handle;
|
||||
protected:
|
||||
threading_impl::mutex_handle Handle;
|
||||
};
|
||||
|
||||
/// A static allocation variant of Mutex.
|
||||
/// An unsafe variant of the above (for use in the error handling path)
|
||||
///
|
||||
/// Use Mutex instead unless you need static allocation.
|
||||
class StaticMutex {
|
||||
/// This is used to ensure that we can't infinitely recurse if the mutex
|
||||
/// itself generates errors.
|
||||
class UnsafeMutex : public Mutex {
|
||||
public:
|
||||
UnsafeMutex() : Mutex() {}
|
||||
|
||||
StaticMutex(const StaticMutex &) = delete;
|
||||
StaticMutex &operator=(const StaticMutex &) = delete;
|
||||
StaticMutex(StaticMutex &&) = delete;
|
||||
StaticMutex &operator=(StaticMutex &&) = delete;
|
||||
void lock() { threading_impl::mutex_unsafe_unlock(Handle); }
|
||||
void unlock() { threading_impl::mutex_unsafe_unlock(Handle); }
|
||||
};
|
||||
|
||||
/// A lazily initialized variant of Mutex.
|
||||
///
|
||||
/// Use Mutex instead unless you need static allocation. LazyMutex *may*
|
||||
/// be entirely statically initialized, on some platforms, but on others
|
||||
/// it might be a little larger than and slightly slower than Mutex.
|
||||
class LazyMutex {
|
||||
|
||||
LazyMutex(const LazyMutex &) = delete;
|
||||
LazyMutex &operator=(const LazyMutex &) = delete;
|
||||
LazyMutex(LazyMutex &&) = delete;
|
||||
LazyMutex &operator=(LazyMutex &&) = delete;
|
||||
|
||||
public:
|
||||
#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
|
||||
constexpr
|
||||
#endif
|
||||
StaticMutex()
|
||||
: Handle(MutexPlatformHelper::staticInit()) {
|
||||
}
|
||||
constexpr LazyMutex() : Handle(threading_impl::lazy_mutex_initializer()) {}
|
||||
|
||||
// No destructor; this is intentional; this class is for STATIC allocation
|
||||
// and you don't need to delete mutexes on termination.
|
||||
|
||||
/// See Mutex::lock
|
||||
void lock() { MutexPlatformHelper::lock(Handle); }
|
||||
void lock() { threading_impl::lazy_mutex_lock(Handle); }
|
||||
|
||||
/// See Mutex::unlock
|
||||
void unlock() { MutexPlatformHelper::unlock(Handle); }
|
||||
void unlock() { threading_impl::lazy_mutex_unlock(Handle); }
|
||||
|
||||
/// See Mutex::try_lock
|
||||
bool try_lock() { return MutexPlatformHelper::try_lock(Handle); }
|
||||
bool try_lock() { return threading_impl::lazy_mutex_try_lock(Handle); }
|
||||
|
||||
/// See Mutex::lock
|
||||
/// See Mutex::withLock
|
||||
template <typename CriticalSection>
|
||||
auto withLock(CriticalSection &&criticalSection)
|
||||
-> decltype(std::forward<CriticalSection>(criticalSection)()) {
|
||||
@@ -210,74 +203,28 @@ public:
|
||||
/// and unlocks it on destruction.
|
||||
///
|
||||
/// Precondition: Mutex unlocked by this thread, undefined otherwise.
|
||||
typedef ScopedLockT<StaticMutex, false> ScopedLock;
|
||||
typedef ScopedLockT<LazyMutex, false> ScopedLock;
|
||||
|
||||
/// A stack based object that unlocks the supplied mutex on construction
|
||||
/// and relocks it on destruction.
|
||||
///
|
||||
/// Precondition: Mutex locked by this thread, undefined otherwise.
|
||||
typedef ScopedLockT<StaticMutex, true> ScopedUnlock;
|
||||
typedef ScopedLockT<LazyMutex, true> ScopedUnlock;
|
||||
|
||||
private:
|
||||
MutexHandle Handle;
|
||||
protected:
|
||||
threading_impl::lazy_mutex_handle Handle;
|
||||
};
|
||||
|
||||
/// A Mutex object that supports `BasicLockable` C++ concepts. It is
|
||||
/// considered
|
||||
/// unsafe to use because it doesn't do any error checking. It is only for
|
||||
/// use in pathways that deal with reporting fatalErrors to avoid the
|
||||
/// potential
|
||||
/// for recursive fatalErrors that could happen if you used Mutex.
|
||||
/// An unsafe variant of the above (for use in the error handling path)
|
||||
///
|
||||
/// Always use Mutex, unless in the above mentioned error pathway situation.
|
||||
class StaticUnsafeMutex {
|
||||
|
||||
StaticUnsafeMutex(const StaticUnsafeMutex &) = delete;
|
||||
StaticUnsafeMutex &operator=(const StaticUnsafeMutex &) = delete;
|
||||
StaticUnsafeMutex(StaticUnsafeMutex &&) = delete;
|
||||
StaticUnsafeMutex &operator=(StaticUnsafeMutex &&) = delete;
|
||||
|
||||
/// This is used to ensure that we can't infinitely recurse if the mutex
|
||||
/// itself generates errors.
|
||||
class LazyUnsafeMutex : public LazyMutex {
|
||||
public:
|
||||
#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
|
||||
constexpr
|
||||
#endif
|
||||
StaticUnsafeMutex()
|
||||
: Handle(MutexPlatformHelper::staticInit()) {
|
||||
}
|
||||
constexpr LazyUnsafeMutex() : LazyMutex() {}
|
||||
|
||||
/// The lock() method has the following properties:
|
||||
/// - Behaves as an atomic operation.
|
||||
/// - Blocks the calling thread until exclusive ownership of the mutex
|
||||
/// can be obtained.
|
||||
/// - Prior m.unlock() operations on the same mutex synchronize-with
|
||||
/// this lock operation.
|
||||
/// - The behavior is undefined if the calling thread already owns
|
||||
/// the mutex (likely a deadlock).
|
||||
/// - Ignores errors that may happen, undefined when an error happens.
|
||||
void lock() { MutexPlatformHelper::unsafeLock(Handle); }
|
||||
|
||||
/// The unlock() method has the following properties:
|
||||
/// - Behaves as an atomic operation.
|
||||
/// - Releases the calling thread's ownership of the mutex and
|
||||
/// synchronizes-with the subsequent successful lock operations on
|
||||
/// the same object.
|
||||
/// - The behavior is undefined if the calling thread does not own
|
||||
/// the mutex.
|
||||
/// - Ignores errors that may happen, undefined when an error happens.
|
||||
void unlock() { MutexPlatformHelper::unsafeUnlock(Handle); }
|
||||
|
||||
template <typename CriticalSection>
|
||||
auto withLock(CriticalSection &&criticalSection)
|
||||
-> decltype(std::forward<CriticalSection>(criticalSection)()) {
|
||||
ScopedLock guard(*this);
|
||||
return std::forward<CriticalSection>(criticalSection)();
|
||||
}
|
||||
|
||||
typedef ScopedLockT<StaticUnsafeMutex, false> ScopedLock;
|
||||
typedef ScopedLockT<StaticUnsafeMutex, true> ScopedUnlock;
|
||||
|
||||
private:
|
||||
MutexHandle Handle;
|
||||
void lock() { threading_impl::lazy_mutex_unsafe_lock(Handle); }
|
||||
void unlock() { threading_impl::lazy_mutex_unsafe_unlock(Handle); }
|
||||
};
|
||||
|
||||
/// An indirect variant of a Mutex. This allocates the mutex on the heap, for
|
||||
@@ -327,25 +274,6 @@ private:
|
||||
using SmallMutex =
|
||||
std::conditional_t<sizeof(Mutex) <= sizeof(void *), Mutex, IndirectMutex>;
|
||||
|
||||
// Enforce literal requirements for static variants.
|
||||
#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
|
||||
static_assert(std::is_literal_type<StaticMutex>::value,
|
||||
"StaticMutex must be literal type");
|
||||
static_assert(std::is_literal_type<StaticUnsafeMutex>::value,
|
||||
"StaticUnsafeMutex must be literal type");
|
||||
#else
|
||||
// Your platform doesn't currently support statically allocated Mutex
|
||||
// you will possibly see global-constructors warnings
|
||||
#endif
|
||||
} // namespace swift
|
||||
|
||||
#if SWIFT_CONDITION_SUPPORTS_CONSTEXPR
|
||||
static_assert(std::is_literal_type<StaticConditionVariable>::value,
|
||||
"StaticConditionVariable must be literal type");
|
||||
#else
|
||||
// Your platform doesn't currently support statically allocated ConditionVar
|
||||
// you will possibly see global-constructors warnings
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // SWIFT_THREADING_MUTEX_H
|
||||
35
include/swift/Threading/Once.h
Normal file
35
include/swift/Threading/Once.h
Normal file
@@ -0,0 +1,35 @@
|
||||
//===--- Once.h - Runtime support for lazy initialization -------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift runtime functions in support of lazy initialization.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_ONCE_H
|
||||
#define SWIFT_THREADING_ONCE_H
|
||||
|
||||
#include "Impl.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
using once_t = threading_impl::once_t;
|
||||
|
||||
/// Runs the given function with the given context argument exactly once.
|
||||
/// The predicate argument must refer to a global or static variable of static
|
||||
/// extent of type swift::once_t.
|
||||
inline void once(once_t &predicate, void (*fn)(void *), void *context=nullptr) {
|
||||
threading_impl::once(predicate, fn, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SWIFT_THREADING_ONCE_H
|
||||
72
include/swift/Threading/Thread.h
Normal file
72
include/swift/Threading/Thread.h
Normal file
@@ -0,0 +1,72 @@
|
||||
//===--- Thread.h - Thread abstraction ------------------------ -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Provides an abstract Thread class that identifies a system thread,
|
||||
// and can fetch the current and main threads as well as being comparable
|
||||
// with other Thread instances.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_THREAD_H
|
||||
#define SWIFT_THREADING_THREAD_H
|
||||
|
||||
#include "Impl.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Identifies a thread
|
||||
class Thread {
|
||||
private:
|
||||
threading_impl::thread_id id_;
|
||||
|
||||
public:
|
||||
Thread() {}
|
||||
Thread(const Thread& other) : id_(other.id_) {}
|
||||
Thread(Thread&& other) : id_(std::move(other.id_)) {}
|
||||
|
||||
Thread& operator=(const Thread& other) {
|
||||
id_ = other.id_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Thread& operator=(Thread&& other) {
|
||||
id_ = other.id_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Returns the currently executing thread
|
||||
static Thread current() {
|
||||
return Thread(threading_impl::thread_get_current());
|
||||
}
|
||||
|
||||
/// Returns the main thread in this program
|
||||
static Thread main() {
|
||||
return Thread(threading_impl::thread_get_main());
|
||||
}
|
||||
|
||||
/// Returns true iff executed on the main thread
|
||||
static bool onMainThread() {
|
||||
return threading_impl::thread_is_main();
|
||||
}
|
||||
|
||||
/// Returns true if the two Thread values are equal
|
||||
bool operator==(const Thread& other) const {
|
||||
return threading_impl::threads_same(id_, other.id_);
|
||||
}
|
||||
bool operator!=(const Thread& other) const {
|
||||
return !threading_impl::threads_same(id_, other.id_);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_THREADING_THREAD_H
|
||||
176
include/swift/Threading/ThreadLocalStorage.h
Normal file
176
include/swift/Threading/ThreadLocalStorage.h
Normal file
@@ -0,0 +1,176 @@
|
||||
//===--- ThreadLocalStorage.h - Thread-local storage interface. --*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_THREADING_THREADLOCALSTORAGE_H
|
||||
#define SWIFT_THREADING_THREADLOCALSTORAGE_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "Impl.h"
|
||||
#include "Once.h"
|
||||
#include "Errors.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
// -- Low-level TLS functions -------------------------------------------------
|
||||
|
||||
#if !SWIFT_THREADING_NONE
|
||||
using tls_key = threading_impl::tls_key;
|
||||
using tls_dtor = threading_impl::tls_dtor;
|
||||
|
||||
#if SWIFT_THREADING_USE_RESERVED_TLS_KEYS
|
||||
using threading_impl::tls_init;
|
||||
|
||||
/// tls_init_once() - Initialize TLS, once only
|
||||
inline void tls_init_once(once_t &token, tls_key key, tls_dtor dtor) {
|
||||
const struct tls_init_info { tls_key &k; tls_dtor d; } info = { key, dtor };
|
||||
once(token, [](void *ctx) {
|
||||
const struct tls_init_info *pinfo = static_cast<const struct tls_init_info *>(ctx);
|
||||
if (!tls_init(pinfo->k, pinfo->d))
|
||||
swift::threading::fatal("tls_init_once() failed to set destructor");
|
||||
}, (void *)&info);
|
||||
}
|
||||
#endif // SWIFT_THREADING_USE_RESERVED_TLS_KEYS
|
||||
|
||||
using threading_impl::tls_alloc;
|
||||
using threading_impl::tls_get;
|
||||
using threading_impl::tls_set;
|
||||
|
||||
/// tls_alloc_once() - Allocate TLS key, once only
|
||||
inline void tls_alloc_once(once_t &token, tls_key &key, tls_dtor dtor) {
|
||||
const struct tls_init_info { tls_key &k; tls_dtor d; } info = { key, dtor };
|
||||
once(token, [](void *ctx) {
|
||||
const struct tls_init_info *pinfo = static_cast<const struct tls_init_info *>(ctx);
|
||||
if (!tls_alloc(pinfo->k, pinfo->d))
|
||||
swift::threading::fatal("tls_alloc_once() failed to allocate key");
|
||||
}, (void *)&info);
|
||||
}
|
||||
#endif // !SWIFT_THREADING_NONE
|
||||
|
||||
// -- High-level TLS classes --------------------------------------------------
|
||||
|
||||
// Validate a type stored in thread-local storage, using static asserts. Such
|
||||
// types must fit in a pointer and be trivially copyable/destructible.
|
||||
#define VALIDATE_THREAD_LOCAL_TYPE(T) \
|
||||
static_assert(sizeof(T) <= sizeof(void *), \
|
||||
"cannot store more than a pointer"); \
|
||||
static_assert(std::is_trivially_copyable<T>::value, \
|
||||
"ThreadLocal values must be trivially copyable"); \
|
||||
static_assert(std::is_trivially_destructible<T>::value, \
|
||||
"ThreadLocal cleanup is not supported, stored types must be " \
|
||||
"trivially destructible");
|
||||
|
||||
// A wrapper class for thread-local storage.
|
||||
//
|
||||
// - On platforms that report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
// above, an object of this type is declared with
|
||||
// SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL. This makes the object
|
||||
// itself thread-local, and no internal support is required.
|
||||
//
|
||||
// Note that this includes platforms that don't support threading,
|
||||
// for which SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL is empty;
|
||||
// thread-local declarations then create an ordinary global.
|
||||
//
|
||||
// - On platforms that don't report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL,
|
||||
// we have to simulate thread-local storage. Fortunately, all of
|
||||
// these platforms (at least for now) support pthread_getspecific
|
||||
// or similar.
|
||||
#ifdef SWIFT_THREAD_LOCAL
|
||||
template <class T>
|
||||
class ThreadLocal {
|
||||
VALIDATE_THREAD_LOCAL_TYPE(T)
|
||||
|
||||
T value;
|
||||
|
||||
public:
|
||||
constexpr ThreadLocal() {}
|
||||
|
||||
T get() { return value; }
|
||||
|
||||
void set(T newValue) { value = newValue; }
|
||||
};
|
||||
#else
|
||||
// A wrapper around a TLS key that is lazily initialized using swift::once.
|
||||
class ThreadLocalKey {
|
||||
// We rely on the zero-initialization of objects with static storage
|
||||
// duration.
|
||||
once_t onceFlag;
|
||||
tls_key key;
|
||||
|
||||
public:
|
||||
threading_impl::tls_key getKey() {
|
||||
once(onceFlag, [](void *ctx) {
|
||||
tls_key *pkey = reinterpret_cast<tls_key *>(ctx);
|
||||
tls_alloc(*pkey, nullptr);
|
||||
}, &key);
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
// A type representing a constant TLS key, for use on platforms
|
||||
// that provide reserved keys.
|
||||
template <tls_key constantKey>
|
||||
class ConstantThreadLocalKey {
|
||||
public:
|
||||
tls_key getKey() { return constantKey; }
|
||||
};
|
||||
|
||||
template <class T, class Key>
|
||||
class ThreadLocal {
|
||||
VALIDATE_THREAD_LOCAL_TYPE(T)
|
||||
|
||||
Key key;
|
||||
|
||||
public:
|
||||
constexpr ThreadLocal() {}
|
||||
|
||||
T get() {
|
||||
void *storedValue = tls_get(key.getKey());
|
||||
T value;
|
||||
memcpy(&value, &storedValue, sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
void set(T newValue) {
|
||||
void *storedValue;
|
||||
memcpy(&storedValue, &newValue, sizeof(T));
|
||||
tls_set(key.getKey(), storedValue);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
/// SWIFT_THREAD_LOCAL_TYPE(TYPE, KEY) - Declare a variable
|
||||
/// to be a thread-local variable. The declaration must have static
|
||||
/// storage duration; it may be prefixed with "static".
|
||||
///
|
||||
/// For example
|
||||
///
|
||||
/// static SWIFT_THREAD_LOCAL_TYPE(int, SWIFT_RESERVED_TLS_KEY_9) frobble;
|
||||
///
|
||||
/// Because of the fallback path, the default-initialization of the
|
||||
/// type must be equivalent to a bitwise zero-initialization, and the
|
||||
/// type must be small and trivially copyable and destructible.
|
||||
#if SWIFT_THREAD_LOCAL
|
||||
#define SWIFT_THREAD_LOCAL_TYPE(TYPE, KEY) \
|
||||
SWIFT_THREAD_LOCAL swift::ThreadLocal<TYPE>
|
||||
#elif SWIFT_THREADING_USE_RESERVED_TLS_KEYS
|
||||
#define SWIFT_THREAD_LOCAL_TYPE(TYPE, KEY) \
|
||||
swift::ThreadLocal<TYPE, swift::ConstantThreadLocalKey<KEY>>
|
||||
#else
|
||||
#define SWIFT_THREAD_LOCAL_TYPE(TYPE, KEY) \
|
||||
swift::ThreadLocal<TYPE, swift::ThreadLocalKey>
|
||||
#endif
|
||||
|
||||
|
||||
#endif // SWIFT_THREADING_THREADLOCALSTORAGE_H
|
||||
@@ -50,3 +50,5 @@ add_subdirectory(SymbolGraphGen)
|
||||
add_subdirectory(Syntax)
|
||||
add_subdirectory(SyntaxParse)
|
||||
add_subdirectory(TBDGen)
|
||||
add_subdirectory(Threading)
|
||||
|
||||
|
||||
103
lib/Threading/C11.cpp
Normal file
103
lib/Threading/C11.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
//==--- C11.cpp - Threading abstraction implementation --------- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for C11 threads
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if SWIFT_THREADING_C11
|
||||
|
||||
#include "swift/Threading/Errors.h"
|
||||
#include "swift/Threading/Impl/C11.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wglobal-constructors"
|
||||
|
||||
class C11ThreadingHelper {
|
||||
private:
|
||||
thrd_t mainThread_;
|
||||
mut_t onceMutex_;
|
||||
cnd_t onceCond_;
|
||||
|
||||
public:
|
||||
C11ThreadingHelper() {
|
||||
mainThread_ = thrd_current();
|
||||
SWIFT_C11THREADS_CHECK(::mtx_init(&onceMutex_, ::mtx_plain));
|
||||
SWIFT_C11THREADS_CHECK(::cnd_init(&onceCond_));
|
||||
}
|
||||
|
||||
thrd_t main_thread() const { return mainThread_; }
|
||||
|
||||
void once_lock() {
|
||||
SWIFT_C11THREADS_CHECK(mtx_lock(&onceMutex_));
|
||||
}
|
||||
void once_unlock() {
|
||||
SWIFT_C11THREADS_CHECK(mtx_unlock(&onceMutex_));
|
||||
}
|
||||
void once_broadcast() {
|
||||
SWIFT_C11THREADS_CHECK(cnd_broadcast(&onceCond_));
|
||||
}
|
||||
void once_wait() {
|
||||
SWIFT_C11THREADS_CHECK(mtx_lock(&onceMutex_));
|
||||
SWIFT_C11THREADS_CHECK(cnd_wait(&onceCond_, &onceMutex_));
|
||||
SWIFT_C11THREADS_CHECK(mtx_unlock(&onceMutex_));
|
||||
}
|
||||
};
|
||||
|
||||
C11ThreadingHelper helper;
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
}
|
||||
|
||||
using namespace swift;
|
||||
using namespace threading_impl;
|
||||
|
||||
thread_id
|
||||
swift::threading_impl::thread_get_main() {
|
||||
return helper.main_thread();
|
||||
}
|
||||
|
||||
bool
|
||||
swift::threading_impl::thread_is_main() {
|
||||
return thrd_equal(thrd_current(), thread_get_main());
|
||||
}
|
||||
|
||||
void
|
||||
swift::threading_impl::once_slow(once_t &predicate,
|
||||
void (*fn)(void *),
|
||||
void *context) {
|
||||
if (::atomic_compare_exchange_strong_explicit(&predicate,
|
||||
&(int){ 0 },
|
||||
1,
|
||||
::memory_order_relaxed,
|
||||
::memory_order_relaxed)) {
|
||||
fn(context);
|
||||
|
||||
::atomic_store_explicit(&predicate, -1, ::memory_order_release);
|
||||
|
||||
helper.once_lock();
|
||||
helper.once_unlock();
|
||||
helper.once_broadcast();
|
||||
return;
|
||||
}
|
||||
|
||||
helper.once_lock();
|
||||
while (::atomic_load_explicit(&predicate, memory_order_acquire) >= 0) {
|
||||
helper.once_wait();
|
||||
}
|
||||
helper.once_unlock();
|
||||
}
|
||||
|
||||
#endif // SWIFT_THREADING_C11
|
||||
5
lib/Threading/CMakeLists.txt
Normal file
5
lib/Threading/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
add_swift_host_library(swiftThreading STATIC
|
||||
C11.cpp
|
||||
Nothreads.cpp
|
||||
Pthreads.cpp
|
||||
Win32.cpp)
|
||||
67
lib/Threading/Linux.cpp
Normal file
67
lib/Threading/Linux.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
//==--- Linux.cpp - Threading abstraction implementation ------- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for Linux
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if SWIFT_THREADING_LINUX
|
||||
|
||||
#include "swift/Threading/Errors.h"
|
||||
#include "swift/Threading/Impl/Linux.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wglobal-constructors"
|
||||
|
||||
class MainThreadRememberer {
|
||||
private:
|
||||
pthread_t mainThread_;
|
||||
public:
|
||||
MainThreadRememberer() { mainThread_ = pthread_self(); }
|
||||
|
||||
pthread_t main_thread() const { return mainThread_; }
|
||||
};
|
||||
|
||||
MainThreadRememberer rememberer;
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
}
|
||||
|
||||
using namespace swift;
|
||||
using namespace threading_impl;
|
||||
|
||||
thread_id
|
||||
swift::threading_impl::thread_get_main() {
|
||||
return rememberer.main_thread();
|
||||
}
|
||||
|
||||
bool
|
||||
swift::threading_impl::thread_is_main() {
|
||||
return pthread_equal(pthread_self(), thread_get_main());
|
||||
}
|
||||
|
||||
void
|
||||
swift::threading_impl::once_slow(once_t &predicate,
|
||||
void (*fn)(void *),
|
||||
void *context) {
|
||||
linux::ulock_lock(&predicate.lock);
|
||||
if (predicate.flag.load(std::memory_order_acquire) == 0) {
|
||||
fn(context);
|
||||
predicate.flag.store(-1, std::memory_order_release);
|
||||
}
|
||||
linux::ulock_unlock(&predicate.lock);
|
||||
}
|
||||
|
||||
#endif // SWIFT_THREADING_PTHREADS
|
||||
21
lib/Threading/Nothreads.cpp
Normal file
21
lib/Threading/Nothreads.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//==--- Nothreads.cpp - Threading abstraction implementation --- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for platforms without threading
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if SWIFT_THREADING_NONE
|
||||
|
||||
#include "swift/Threading/Impl/Nothreads.h"
|
||||
|
||||
#endif // SWIFT_THREADING_NONE
|
||||
82
lib/Threading/Pthreads.cpp
Normal file
82
lib/Threading/Pthreads.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
//==--- Pthreads.cpp - Threading abstraction implementation ---- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for plain pthreads
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if SWIFT_THREADING_PTHREADS
|
||||
|
||||
#include "swift/Threading/Errors.h"
|
||||
#include "swift/Threading/Impl/Pthreads.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wglobal-constructors"
|
||||
|
||||
class MainThreadRememberer {
|
||||
private:
|
||||
pthread_t mainThread_;
|
||||
public:
|
||||
MainThreadRememberer() { mainThread_ = pthread_self(); }
|
||||
|
||||
pthread_t main_thread() const { return mainThread_; }
|
||||
};
|
||||
|
||||
MainThreadRememberer rememberer;
|
||||
pthread_mutex_t onceMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t onceCond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
}
|
||||
|
||||
using namespace swift;
|
||||
using namespace threading_impl;
|
||||
|
||||
thread_id
|
||||
swift::threading_impl::thread_get_main() {
|
||||
return rememberer.main_thread();
|
||||
}
|
||||
|
||||
bool
|
||||
swift::threading_impl::thread_is_main() {
|
||||
return pthread_equal(pthread_self(), thread_get_main());
|
||||
}
|
||||
|
||||
void
|
||||
swift::threading_impl::once_slow(once_t &predicate,
|
||||
void (*fn)(void *),
|
||||
void *context) {
|
||||
std::int64_t zero = 0;
|
||||
if (predicate.compare_exchange_strong(zero, (std::int64_t)1,
|
||||
std::memory_order_relaxed,
|
||||
std::memory_order_relaxed)) {
|
||||
fn(context);
|
||||
|
||||
predicate.store((std::int64_t)-1, std::memory_order_release);
|
||||
|
||||
pthread_mutex_lock(&onceMutex);
|
||||
pthread_mutex_unlock(&onceMutex);
|
||||
pthread_cond_broadcast(&onceCond);
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&onceMutex);
|
||||
while (predicate.load(std::memory_order_acquire) >= (std::int64_t)0) {
|
||||
pthread_cond_wait(&onceCond);
|
||||
}
|
||||
pthread_mutex_unlock(&onceMutex);
|
||||
}
|
||||
|
||||
#endif // SWIFT_THREADING_PTHREADS
|
||||
103
lib/Threading/Win32.cpp
Normal file
103
lib/Threading/Win32.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
//==--- Win32.cpp - Threading abstraction implementation ------- -*-C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements threading support for Windows threads
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if SWIFT_THREADING_WIN32
|
||||
|
||||
#include "swift/Threading/Errors.h"
|
||||
#include "swift/Threading/Impl/Win32.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wglobal-constructors"
|
||||
|
||||
class MainThreadRememberer {
|
||||
private:
|
||||
DWORD dwMainThread_;
|
||||
public:
|
||||
MainThreadRememberer() { dwMainThread_ = ::GetCurrentThreadId(); }
|
||||
|
||||
DWORD main_thread() const { return dwMainThread_; }
|
||||
};
|
||||
|
||||
MainThreadRememberer rememberer;
|
||||
|
||||
// Prior to Windows 8, we have to use a global lock
|
||||
#if _WIN32_WINNT < 0x0602
|
||||
SRWLOCK onceMutex = SRWLOCK_INIT;
|
||||
CONDITION_VARIABLE onceCond = CONDITION_VARIABLE_INIT;
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
}
|
||||
|
||||
using namespace swift;
|
||||
using namespace threading_impl;
|
||||
|
||||
thread_id
|
||||
swift::threading_impl::thread_get_main() {
|
||||
return rememberer.main_thread();
|
||||
}
|
||||
|
||||
bool
|
||||
swift::threading_impl::thread_is_main() {
|
||||
return ::GetCurrentThreadId() == thread_get_main();
|
||||
}
|
||||
|
||||
void
|
||||
swift::threading_impl::once_slow(once_t &predicate,
|
||||
void (*fn)(void *),
|
||||
void *context) {
|
||||
std::int64_t expected = 0;
|
||||
if (predicate.compare_exchange_strong(expected, (std::int64_t)1,
|
||||
std::memory_order_relaxed,
|
||||
std::memory_order_relaxed)) {
|
||||
fn(context);
|
||||
|
||||
predicate.store((std::int64_t)-1, std::memory_order_release);
|
||||
|
||||
#if _WIN32_WINNT >= 0x0602
|
||||
// On Windows 8, use WakeByAddressAll() to wake waiters
|
||||
WakeByAddressAll(&predicate);
|
||||
#else
|
||||
// On Windows 7 and earlier, we use a global lock and condition variable;
|
||||
// this will wake *all* waiters on *all* onces, which might result in a
|
||||
// thundering herd problem, but it's the best we can do.
|
||||
AcquireSRWLockExclusive(&onceMutex);
|
||||
WakeAllConditionVariable(&onceCond);
|
||||
ReleaseSRWLockExclusive(&onceMutex);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#if _WIN32_WINNT >= 0x0602
|
||||
// On Windows 8, loop waiting on the address until it changes to -1
|
||||
while (expected >= 0) {
|
||||
WaitOnAddress(&predicate, &expected, 8, INFINITE);
|
||||
expected = predicate.load(std::memory_order_acquire);
|
||||
}
|
||||
#else
|
||||
// On Windows 7 and earlier, wait on the global condition variable
|
||||
AcquireSRWLockExclusive(&onceMutex);
|
||||
while (predicate.load(std::memory_order_acquire) >= 0) {
|
||||
SleepConditionVariableSRW(&onceCond, &onceMutex, INFINITE, 0);
|
||||
}
|
||||
ReleaseSRWLockExclusive(&onceMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SWIFT_THREADING_WIN32
|
||||
@@ -355,8 +355,8 @@ function(_add_target_variant_c_compile_flags)
|
||||
list(APPEND result "-DSWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY")
|
||||
endif()
|
||||
|
||||
threading_package_name(_threading_package)
|
||||
list(APPEND result "-DSWIFT_STDLIB_THREADING_${_threading_package}")
|
||||
threading_package_name("${CFLAGS_SDK}" _threading_package)
|
||||
list(APPEND result "-DSWIFT_THREADING_${_threading_package}")
|
||||
|
||||
if(SWIFT_STDLIB_OS_VERSIONING)
|
||||
list(APPEND result "-DSWIFT_RUNTIME_OS_VERSIONING")
|
||||
|
||||
@@ -6,6 +6,19 @@ include(${CMAKE_CURRENT_LIST_DIR}/../../../cmake/modules/Threading.cmake)
|
||||
precondition(SWIFT_HOST_VARIANT_SDK)
|
||||
precondition(SWIFT_DARWIN_PLATFORMS)
|
||||
|
||||
# +----------------------------------------------------------------------+
|
||||
# | |
|
||||
# | NOTE: It makes no sense setting defaults here on the basis of |
|
||||
# | SWIFT_HOST_VARIANT_SDK, because the stdlib is a *TARGET* |
|
||||
# | library, not a host library. |
|
||||
# | |
|
||||
# | Rather, if you have a default to set, you need to do that |
|
||||
# | in AddSwiftStdlib.cmake, in an appropriate place, |
|
||||
# | likely on the basis of CFLAGS_SDK, SWIFTLIB_SINGLE_SDK or |
|
||||
# | similar. |
|
||||
# | |
|
||||
# +----------------------------------------------------------------------+
|
||||
|
||||
if("${SWIFT_HOST_VARIANT_SDK}" MATCHES "CYGWIN")
|
||||
set(SWIFT_STDLIB_SUPPORTS_BACKTRACE_REPORTING_default FALSE)
|
||||
elseif("${SWIFT_HOST_VARIANT_SDK}" MATCHES "HAIKU")
|
||||
@@ -178,6 +191,16 @@ else()
|
||||
set(SWIFT_CONCURRENCY_GLOBAL_EXECUTOR_default "dispatch")
|
||||
endif()
|
||||
|
||||
include(Threading)
|
||||
|
||||
threading_package_default("${SWIFT_HOST_VARIANT_SDK}"
|
||||
SWIFT_THREADING_PACKAGE_default)
|
||||
|
||||
set(SWIFT_THREADING_PACKAGE "${SWIFT_THREADING_PACKAGE_default}"
|
||||
CACHE STRING
|
||||
"The threading package to use. Must be one of 'none', 'pthreads',
|
||||
'darwin', 'linux', 'win32', 'c11'.")
|
||||
|
||||
set(SWIFT_CONCURRENCY_GLOBAL_EXECUTOR
|
||||
"${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR_default}" CACHE STRING
|
||||
"Build the concurrency library to use the given global executor (options: dispatch, singlethreaded, hooked)")
|
||||
|
||||
@@ -327,8 +327,8 @@ function(_add_target_variant_swift_compile_flags
|
||||
list(APPEND result "-D" "SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY")
|
||||
endif()
|
||||
|
||||
threading_package_name(_threading_package)
|
||||
list(APPEND result "-D" "SWIFT_STDLIB_THREADING_${_threading_package}")
|
||||
threading_package_name("${sdk}" _threading_package)
|
||||
list(APPEND result "-D" "SWIFT_THREADING_${_threading_package}")
|
||||
|
||||
set("${result_var_name}" "${result}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -483,7 +483,7 @@ function(_compile_swift_files
|
||||
list(APPEND swift_flags "-Xfrontend" "-library-level" "-Xfrontend" "api")
|
||||
endif()
|
||||
|
||||
if(SWIFT_STDLIB_THREADING_PACKAGE STREQUAL "none")
|
||||
if(SWIFT_THREADING_PACKAGE STREQUAL "none")
|
||||
list(APPEND swift_flags "-Xfrontend" "-assume-single-threaded")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ endif()
|
||||
|
||||
add_subdirectory(SwiftShims)
|
||||
add_subdirectory(CommandLineSupport)
|
||||
add_subdirectory(Threading)
|
||||
|
||||
# This static library is shared across swiftCore and swiftReflection
|
||||
if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
|
||||
|
||||
@@ -31,11 +31,10 @@
|
||||
#include "swift/Runtime/Atomic.h"
|
||||
#include "swift/Runtime/AccessibleFunction.h"
|
||||
#include "swift/Runtime/Casting.h"
|
||||
#include "swift/Runtime/Once.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/ThreadLocal.h"
|
||||
#include "swift/Runtime/ThreadLocalStorage.h"
|
||||
#include "swift/Runtime/DispatchShims.h"
|
||||
#include "swift/Threading/Once.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "swift/Threading/ThreadLocalStorage.h"
|
||||
#include "swift/ABI/Task.h"
|
||||
#include "swift/ABI/Actor.h"
|
||||
#include "swift/Basic/ListMerger.h"
|
||||
@@ -126,9 +125,9 @@ class ExecutorTrackingInfo {
|
||||
/// the right executor. It would make sense for that to be a
|
||||
/// separate thread-local variable (or whatever is most efficient
|
||||
/// on the target platform).
|
||||
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
|
||||
Pointer<ExecutorTrackingInfo>, ActiveInfoInThread,
|
||||
SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY);
|
||||
static SWIFT_THREAD_LOCAL_TYPE(
|
||||
Pointer<ExecutorTrackingInfo>,
|
||||
SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY) ActiveInfoInThread;
|
||||
|
||||
/// The active executor.
|
||||
ExecutorRef ActiveExecutor = ExecutorRef::generic();
|
||||
@@ -194,8 +193,8 @@ public:
|
||||
class ActiveTask {
|
||||
/// A thread-local variable pointing to the active tracking
|
||||
/// information about the current thread, if any.
|
||||
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(Pointer<AsyncTask>, Value,
|
||||
SWIFT_CONCURRENCY_TASK_KEY);
|
||||
static SWIFT_THREAD_LOCAL_TYPE(Pointer<AsyncTask>,
|
||||
SWIFT_CONCURRENCY_TASK_KEY) Value;
|
||||
|
||||
public:
|
||||
static void set(AsyncTask *task) { Value.set(task); }
|
||||
@@ -203,15 +202,14 @@ public:
|
||||
};
|
||||
|
||||
/// Define the thread-locals.
|
||||
SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
|
||||
SWIFT_THREAD_LOCAL_TYPE(
|
||||
Pointer<AsyncTask>,
|
||||
ActiveTask::Value,
|
||||
SWIFT_CONCURRENCY_TASK_KEY);
|
||||
SWIFT_CONCURRENCY_TASK_KEY) ActiveTask::Value;
|
||||
|
||||
SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
|
||||
SWIFT_THREAD_LOCAL_TYPE(
|
||||
Pointer<ExecutorTrackingInfo>,
|
||||
ExecutorTrackingInfo::ActiveInfoInThread,
|
||||
SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY);
|
||||
SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY)
|
||||
ExecutorTrackingInfo::ActiveInfoInThread;
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
@@ -351,8 +349,8 @@ void swift::swift_task_reportUnexpectedExecutor(
|
||||
const unsigned char *file, uintptr_t fileLength, bool fileIsASCII,
|
||||
uintptr_t line, ExecutorRef executor) {
|
||||
// Make sure we have an appropriate log level.
|
||||
static swift_once_t logLevelToken;
|
||||
swift_once(&logLevelToken, checkUnexpectedExecutorLogLevel, nullptr);
|
||||
static swift::once_t logLevelToken;
|
||||
swift::once(logLevelToken, checkUnexpectedExecutorLogLevel, nullptr);
|
||||
|
||||
bool isFatalError = false;
|
||||
switch (unexpectedExecutorLogLevel) {
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
#include "swift/ABI/Metadata.h"
|
||||
#include "swift/ABI/Task.h"
|
||||
#include "swift/ABI/TaskOptions.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/Heap.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "TaskPrivate.h"
|
||||
#include "Debug.h"
|
||||
|
||||
@@ -10,30 +10,32 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include <new>
|
||||
|
||||
#include "swift/Threading/Mutex.h"
|
||||
|
||||
namespace swift {
|
||||
// return the size in words for the given mutex primitive
|
||||
extern "C"
|
||||
size_t _swift_async_stream_lock_size() {
|
||||
size_t words = sizeof(MutexHandle) / sizeof(void *);
|
||||
size_t words = sizeof(Mutex) / sizeof(void *);
|
||||
if (words < 1) { return 1; }
|
||||
return words;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void _swift_async_stream_lock_init(MutexHandle &lock) {
|
||||
MutexPlatformHelper::init(lock);
|
||||
void _swift_async_stream_lock_init(Mutex &lock) {
|
||||
new (&lock) Mutex();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void _swift_async_stream_lock_lock(MutexHandle &lock) {
|
||||
MutexPlatformHelper::lock(lock);
|
||||
void _swift_async_stream_lock_lock(Mutex &lock) {
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void _swift_async_stream_lock_unlock(MutexHandle &lock) {
|
||||
MutexPlatformHelper::unlock(lock);
|
||||
void _swift_async_stream_lock_unlock(Mutex &lock) {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -112,7 +112,6 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
|
||||
TaskSleep.swift
|
||||
ThreadSanitizer.cpp
|
||||
TracingSignpost.cpp
|
||||
Mutex.cpp
|
||||
AsyncStreamBuffer.swift
|
||||
AsyncStream.swift
|
||||
AsyncThrowingStream.swift
|
||||
@@ -128,6 +127,8 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
|
||||
SWIFT_MODULE_DEPENDS_HAIKU Glibc
|
||||
SWIFT_MODULE_DEPENDS_WINDOWS CRT
|
||||
|
||||
PRIVATE_LINK_LIBRARIES swiftThreading
|
||||
|
||||
LINK_LIBRARIES ${swift_concurrency_link_libraries}
|
||||
|
||||
C_COMPILE_FLAGS
|
||||
|
||||
@@ -116,7 +116,7 @@ extern "C" void dispatch_queue_set_width(dispatch_queue_t dq, long width);
|
||||
static dispatch_queue_t getGlobalQueue(JobPriority priority) {
|
||||
size_t numericPriority = static_cast<size_t>(priority);
|
||||
if (numericPriority >= globalQueueCacheCount)
|
||||
swift_Concurrency_fatalError(0, "invalid job priority %#zx");
|
||||
swift_Concurrency_fatalError(0, "invalid job priority %#zx", numericPriority);
|
||||
|
||||
#ifdef SWIFT_CONCURRENCY_BACK_DEPLOYMENT
|
||||
std::memory_order loadOrder = std::memory_order_acquire;
|
||||
|
||||
@@ -10,10 +10,35 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Threading/Errors.h"
|
||||
#include <cstdio>
|
||||
|
||||
#include "Error.h"
|
||||
|
||||
// swift::fatalError is not exported from libswiftCore and not shared, so define another
|
||||
// internal function instead.
|
||||
SWIFT_NORETURN void swift::swift_Concurrency_fatalError(uint32_t flags, const char *format, ...) {
|
||||
SWIFT_NORETURN
|
||||
SWIFT_VFORMAT(2)
|
||||
void swift::swift_Concurrency_fatalErrorv(uint32_t flags, const char *format, va_list val) {
|
||||
vfprintf(stderr, format, val);
|
||||
abort();
|
||||
}
|
||||
|
||||
SWIFT_NORETURN
|
||||
SWIFT_FORMAT(2, 3)
|
||||
void swift::swift_Concurrency_fatalError(uint32_t flags, const char *format, ...) {
|
||||
va_list val;
|
||||
|
||||
va_start(val, format);
|
||||
swift_Concurrency_fatalErrorv(flags, format, val);
|
||||
}
|
||||
|
||||
// Handle fatal errors from the threading library
|
||||
SWIFT_ATTRIBUTE_NORETURN
|
||||
SWIFT_FORMAT(1, 2)
|
||||
void swift::threading::fatal(const char *format, ...) {
|
||||
va_list val;
|
||||
|
||||
va_start(val, format);
|
||||
swift_Concurrency_fatalErrorv(0, format, val);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,17 @@
|
||||
#ifndef SWIFT_CONCURRENCY_ERRORS_H
|
||||
#define SWIFT_CONCURRENCY_ERRORS_H
|
||||
|
||||
#include "swift/Basic/Compiler.h"
|
||||
|
||||
#include "../SwiftShims/Visibility.h"
|
||||
#include <cstdint>
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace swift {
|
||||
|
||||
SWIFT_NORETURN void swift_Concurrency_fatalError(uint32_t flags, const char *format, ...);
|
||||
SWIFT_NORETURN SWIFT_FORMAT(2, 3) void swift_Concurrency_fatalError(uint32_t flags, const char *format, ...);
|
||||
SWIFT_NORETURN SWIFT_VFORMAT(2) void swift_Concurrency_fatalErrorv(uint32_t flags, const char *format, va_list val);
|
||||
|
||||
} // namespace swift
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
//===--- Mutex.cpp - Mutex support code -----------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
|
||||
#define SWIFT_FATAL_ERROR swift_Concurrency_fatalError
|
||||
|
||||
// Include the runtime's mutex support code.
|
||||
// FIXME: figure out some reasonable way to share this stuff
|
||||
|
||||
#include "../runtime/MutexPThread.cpp"
|
||||
#include "../runtime/MutexWin32.cpp"
|
||||
#include "../runtime/MutexC11.cpp"
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#include "swift/Runtime/MutexSingleThreaded.h"
|
||||
#endif
|
||||
@@ -20,8 +20,8 @@
|
||||
#include "swift/ABI/TaskLocal.h"
|
||||
#include "swift/ABI/TaskOptions.h"
|
||||
#include "swift/ABI/Metadata.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "TaskGroupPrivate.h"
|
||||
#include "TaskPrivate.h"
|
||||
#include "Tracing.h"
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include "swift/Runtime/Concurrency.h"
|
||||
#include "swift/Runtime/Config.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "Debug.h"
|
||||
#include "bitset"
|
||||
#include "string"
|
||||
|
||||
@@ -13,11 +13,8 @@
|
||||
#include "../CompatibilityOverride/CompatibilityOverride.h"
|
||||
#include "swift/Runtime/Atomic.h"
|
||||
#include "swift/Runtime/Casting.h"
|
||||
#include "swift/Runtime/Once.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/Concurrency.h"
|
||||
#include "swift/Runtime/ThreadLocal.h"
|
||||
#include "swift/Runtime/ThreadLocalStorage.h"
|
||||
#include "swift/Threading/ThreadLocalStorage.h"
|
||||
#include "swift/ABI/TaskLocal.h"
|
||||
#include "swift/ABI/Task.h"
|
||||
#include "swift/ABI/Actor.h"
|
||||
@@ -59,9 +56,9 @@ template <class T> struct Pointer {
|
||||
|
||||
/// THIS IS RUNTIME INTERNAL AND NOT ABI.
|
||||
class FallbackTaskLocalStorage {
|
||||
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
|
||||
Pointer<TaskLocal::Storage>, Value,
|
||||
SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY);
|
||||
static SWIFT_THREAD_LOCAL_TYPE(
|
||||
Pointer<TaskLocal::Storage>,
|
||||
SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY) Value;
|
||||
|
||||
public:
|
||||
static void set(TaskLocal::Storage *task) { Value.set(task); }
|
||||
@@ -69,9 +66,10 @@ public:
|
||||
};
|
||||
|
||||
/// Define the thread-locals.
|
||||
SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
|
||||
Pointer<TaskLocal::Storage>, FallbackTaskLocalStorage::Value,
|
||||
SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY);
|
||||
SWIFT_THREAD_LOCAL_TYPE(
|
||||
Pointer<TaskLocal::Storage>,
|
||||
SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY)
|
||||
FallbackTaskLocalStorage::Value;
|
||||
|
||||
// ==== ABI --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
#include "../CompatibilityOverride/CompatibilityOverride.h"
|
||||
#include "swift/Runtime/Concurrency.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/AtomicWaitQueue.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "swift/ABI/TaskStatus.h"
|
||||
#include "TaskPrivate.h"
|
||||
#include <atomic>
|
||||
@@ -36,7 +36,7 @@ ActiveTaskStatus::getStatusRecordParent(TaskStatusRecord *ptr) {
|
||||
|
||||
/// A lock used to protect management of task-specific status
|
||||
/// record locks.
|
||||
static StaticMutex StatusRecordLockLock;
|
||||
static LazyMutex StatusRecordLockLock;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace {
|
||||
/// must acquire the global status-record lock, find this record
|
||||
/// (which should be the innermost record), and wait for an unlock.
|
||||
class StatusRecordLockRecord :
|
||||
public AtomicWaitQueue<StatusRecordLockRecord, StaticMutex>,
|
||||
public AtomicWaitQueue<StatusRecordLockRecord, LazyMutex>,
|
||||
public TaskStatusRecord {
|
||||
public:
|
||||
StatusRecordLockRecord(TaskStatusRecord *parent)
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace trace {
|
||||
|
||||
os_log_t ActorLog;
|
||||
os_log_t TaskLog;
|
||||
OnceToken_t LogsToken;
|
||||
swift::once_t LogsToken;
|
||||
|
||||
void setupLogs(void *unused) {
|
||||
ActorLog = os_log_create(SWIFT_LOG_CONCURRENCY_ACTOR_SUBSYSTEM,
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace trace {
|
||||
|
||||
extern os_log_t ActorLog;
|
||||
extern os_log_t TaskLog;
|
||||
extern OnceToken_t LogsToken;
|
||||
extern swift::once_t LogsToken;
|
||||
|
||||
void setupLogs(void *unused);
|
||||
|
||||
@@ -80,7 +80,7 @@ void setupLogs(void *unused);
|
||||
do { \
|
||||
if (!SWIFT_RUNTIME_WEAK_CHECK(os_signpost_enabled)) \
|
||||
return __VA_ARGS__; \
|
||||
SWIFT_ONCE_F(LogsToken, setupLogs, nullptr); \
|
||||
swift::once(LogsToken, setupLogs, nullptr); \
|
||||
} while (0)
|
||||
|
||||
// Every function does ENSURE_LOGS() before making any os_signpost calls, so
|
||||
|
||||
6
stdlib/public/Threading/CMakeLists.txt
Normal file
6
stdlib/public/Threading/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
add_swift_target_library(swiftThreading STATIC
|
||||
"${SWIFT_SOURCE_DIR}/lib/Threading/C11.cpp"
|
||||
"${SWIFT_SOURCE_DIR}/lib/Threading/NoThreads.cpp"
|
||||
"${SWIFT_SOURCE_DIR}/lib/Threading/Pthreads.cpp"
|
||||
"${SWIFT_SOURCE_DIR}/lib/Threading/Win32.cpp"
|
||||
INSTALL_IN_COMPONENT never_install)
|
||||
@@ -245,7 +245,7 @@ endif()
|
||||
set(GROUP_INFO_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/GroupInfo.json)
|
||||
set(swift_core_link_flags "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}")
|
||||
set(swift_core_framework_depends)
|
||||
set(swift_core_private_link_libraries)
|
||||
set(swift_core_private_link_libraries swiftThreading)
|
||||
set(swift_stdlib_compile_flags "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}")
|
||||
|
||||
if(SWIFT_PRIMARY_VARIANT_SDK STREQUAL CYGWIN)
|
||||
|
||||
@@ -33,7 +33,6 @@ set(swift_runtime_sources
|
||||
Bincompat.cpp
|
||||
Casting.cpp
|
||||
CrashReporter.cpp
|
||||
CygwinPort.cpp
|
||||
Demangle.cpp
|
||||
DynamicCast.cpp
|
||||
Enum.cpp
|
||||
@@ -59,9 +58,6 @@ set(swift_runtime_sources
|
||||
KnownMetadata.cpp
|
||||
Metadata.cpp
|
||||
MetadataLookup.cpp
|
||||
MutexC11.cpp
|
||||
MutexPThread.cpp
|
||||
MutexWin32.cpp
|
||||
Numeric.cpp
|
||||
Once.cpp
|
||||
Portability.cpp
|
||||
|
||||
@@ -31,12 +31,7 @@
|
||||
#include "swift/Runtime/ExistentialContainer.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#if defined(__wasi__)
|
||||
# define SWIFT_CASTING_SUPPORTS_MUTEX 0
|
||||
#else
|
||||
# define SWIFT_CASTING_SUPPORTS_MUTEX 1
|
||||
# include "swift/Runtime/Mutex.h"
|
||||
#endif
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "swift/Basic/Unreachable.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
@@ -144,10 +139,8 @@ enum class TypeNameKind {
|
||||
|
||||
using TypeNameCacheKey = llvm::PointerIntPair<const Metadata *, 2, TypeNameKind>;
|
||||
|
||||
#if SWIFT_CASTING_SUPPORTS_MUTEX
|
||||
static StaticMutex TypeNameCacheLock;
|
||||
static StaticMutex MangledToPrettyFunctionNameCacheLock;
|
||||
#endif
|
||||
static LazyMutex TypeNameCacheLock;
|
||||
static LazyMutex MangledToPrettyFunctionNameCacheLock;
|
||||
|
||||
/// Cache containing rendered names for Metadata.
|
||||
/// Access MUST be protected using `TypeNameCacheLock`.
|
||||
@@ -166,9 +159,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
|
||||
|
||||
// Attempt read-only lookup of cache entry.
|
||||
{
|
||||
#if SWIFT_CASTING_SUPPORTS_MUTEX
|
||||
StaticMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
#endif
|
||||
LazyMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
|
||||
auto found = cache.find(key);
|
||||
if (found != cache.end()) {
|
||||
@@ -179,9 +170,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
|
||||
|
||||
// Read-only lookup failed to find item, we may need to create it.
|
||||
{
|
||||
#if SWIFT_CASTING_SUPPORTS_MUTEX
|
||||
StaticMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
#endif
|
||||
LazyMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
|
||||
// Do lookup again just to make sure it wasn't created by another
|
||||
// thread before we acquired the write lock.
|
||||
@@ -212,9 +201,7 @@ swift::swift_getMangledTypeName(const Metadata *type) {
|
||||
|
||||
// Attempt read-only lookup of cache entry.
|
||||
{
|
||||
#if SWIFT_CASTING_SUPPORTS_MUTEX
|
||||
StaticMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
#endif
|
||||
LazyMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
|
||||
auto found = cache.find(key);
|
||||
if (found != cache.end()) {
|
||||
@@ -225,9 +212,7 @@ swift::swift_getMangledTypeName(const Metadata *type) {
|
||||
|
||||
// Read-only cache lookup failed, we may need to create it.
|
||||
{
|
||||
#if SWIFT_CASTING_SUPPORTS_MUTEX
|
||||
StaticMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
#endif
|
||||
LazyMutex::ScopedLock guard(TypeNameCacheLock);
|
||||
|
||||
// Do lookup again just to make sure it wasn't created by another
|
||||
// thread before we acquired the write lock.
|
||||
@@ -270,9 +255,7 @@ swift::swift_getFunctionFullNameFromMangledName(
|
||||
auto &cache = MangledToPrettyFunctionNameCache.get();
|
||||
// Attempt read-only lookup of cache entry.
|
||||
{
|
||||
#if SWIFT_CASTING_SUPPORTS_MUTEX
|
||||
StaticMutex::ScopedLock guard(MangledToPrettyFunctionNameCacheLock);
|
||||
#endif
|
||||
LazyMutex::ScopedLock guard(MangledToPrettyFunctionNameCacheLock);
|
||||
|
||||
auto found = cache.find(mangledName);
|
||||
if (found != cache.end()) {
|
||||
@@ -387,9 +370,7 @@ swift::swift_getFunctionFullNameFromMangledName(
|
||||
result[size] = 0; // 0-terminated string
|
||||
|
||||
{
|
||||
#if SWIFT_CASTING_SUPPORTS_MUTEX
|
||||
StaticMutex::ScopedLock guard(MangledToPrettyFunctionNameCacheLock);
|
||||
#endif
|
||||
LazyMutex::ScopedLock guard(MangledToPrettyFunctionNameCacheLock);
|
||||
|
||||
cache.insert({mangledName, {result, size}});
|
||||
return TypeNamePair{result, size};
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
//===--- CygwinPort.cpp - Functions for Cygwin port -----------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementations Cygwin specific functions needed for running Swift.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER)
|
||||
#include "Private.h"
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
static std::mutex swiftOnceMutex;
|
||||
|
||||
void swift::_swift_once_f(uintptr_t *predicate, void *context,
|
||||
void (*function)(void *)) {
|
||||
// FIXME: This implementation does a global lock, which is much worse than
|
||||
// what we have on other platforms. Each swift_once should synchronize on the
|
||||
// token.
|
||||
swiftOnceMutex.lock();
|
||||
if (*predicate == 0) {
|
||||
*predicate = 1ul;
|
||||
swiftOnceMutex.unlock();
|
||||
|
||||
function(context);
|
||||
} else
|
||||
swiftOnceMutex.unlock();
|
||||
}
|
||||
#endif // (defined(_WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER)
|
||||
@@ -150,7 +150,7 @@ void printHelp(const char *extra) {
|
||||
#include "EnvironmentVariables.def"
|
||||
|
||||
// Initialization code.
|
||||
OnceToken_t swift::runtime::environment::initializeToken;
|
||||
swift::once_t swift::runtime::environment::initializeToken;
|
||||
|
||||
#if SWIFT_STDLIB_HAS_ENVIRON && (defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__))
|
||||
extern "C" char **environ;
|
||||
|
||||
@@ -30,8 +30,9 @@
|
||||
|
||||
#include "ImageInspection.h"
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/Portability.h"
|
||||
#include "swift/Threading/Errors.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "swift/Demangling/Demangle.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
@@ -460,3 +461,13 @@ void swift::swift_abortDisabledUnicodeSupport() {
|
||||
"Unicode normalization data is disabled on this platform");
|
||||
|
||||
}
|
||||
|
||||
/// Halt because of a problem in the threading library
|
||||
SWIFT_ATTRIBUTE_NORETURN
|
||||
SWIFT_FORMAT(1, 2)
|
||||
void swift::threading::fatal(const char *msg, ...) {
|
||||
va_list val;
|
||||
va_start(val, msg);
|
||||
|
||||
swift::fatalErrorv(0, msg, val);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include "swift/Runtime/EnvironmentVariables.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#include "swift/Runtime/ThreadLocalStorage.h"
|
||||
#include "swift/Threading/ThreadLocalStorage.h"
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
# include <objc/message.h>
|
||||
# include <objc/objc.h>
|
||||
# include "swift/Runtime/ObjCBridge.h"
|
||||
# include "swift/Runtime/Once.h"
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
#include "Leaks.h"
|
||||
@@ -162,13 +161,6 @@ struct InitStaticObjectContext {
|
||||
HeapMetadata const *metadata;
|
||||
};
|
||||
|
||||
// Callback for swift_once.
|
||||
static void initStaticObjectWithContext(void *OpaqueCtx) {
|
||||
InitStaticObjectContext *Ctx = (InitStaticObjectContext *)OpaqueCtx;
|
||||
Ctx->object->metadata = Ctx->metadata;
|
||||
Ctx->object->refCounts.initImmortal();
|
||||
}
|
||||
|
||||
// TODO: We could generate inline code for the fast-path, i.e. the metadata
|
||||
// pointer is already set. That would be a performance/codesize tradeoff.
|
||||
HeapObject *
|
||||
@@ -182,7 +174,11 @@ swift::swift_initStaticObject(HeapMetadata const *metadata,
|
||||
// refcount to 1 while another thread already incremented it - and would
|
||||
// decrement it to 0 afterwards.
|
||||
InitStaticObjectContext Ctx = { object, metadata };
|
||||
swift_once(token, initStaticObjectWithContext, &Ctx);
|
||||
swift::once(*token, [](void *OpaqueCtx) {
|
||||
InitStaticObjectContext *Ctx = (InitStaticObjectContext *)OpaqueCtx;
|
||||
Ctx->object->metadata = Ctx->metadata;
|
||||
Ctx->object->refCounts.initImmortal();
|
||||
}, &Ctx);
|
||||
|
||||
return object;
|
||||
}
|
||||
@@ -350,7 +346,7 @@ static HeapObject *_swift_retain_(HeapObject *object) {
|
||||
}
|
||||
|
||||
HeapObject *swift::swift_retain(HeapObject *object) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
return swift_nonatomic_retain(object);
|
||||
#else
|
||||
CALL_IMPL(swift_retain, (object));
|
||||
@@ -377,7 +373,7 @@ static HeapObject *_swift_retain_n_(HeapObject *object, uint32_t n) {
|
||||
}
|
||||
|
||||
HeapObject *swift::swift_retain_n(HeapObject *object, uint32_t n) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
return swift_nonatomic_retain_n(object, n);
|
||||
#else
|
||||
CALL_IMPL(swift_retain_n, (object, n));
|
||||
@@ -403,7 +399,7 @@ static void _swift_release_(HeapObject *object) {
|
||||
}
|
||||
|
||||
void swift::swift_release(HeapObject *object) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
swift_nonatomic_release(object);
|
||||
#else
|
||||
CALL_IMPL(swift_release, (object));
|
||||
@@ -428,7 +424,7 @@ static void _swift_release_n_(HeapObject *object, uint32_t n) {
|
||||
}
|
||||
|
||||
void swift::swift_release_n(HeapObject *object, uint32_t n) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
swift_nonatomic_release_n(object, n);
|
||||
#else
|
||||
CALL_IMPL(swift_release_n, (object, n));
|
||||
@@ -460,7 +456,7 @@ size_t swift::swift_weakRetainCount(HeapObject *object) {
|
||||
}
|
||||
|
||||
HeapObject *swift::swift_unownedRetain(HeapObject *object) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
return static_cast<HeapObject *>(swift_nonatomic_unownedRetain(object));
|
||||
#else
|
||||
SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetain);
|
||||
@@ -473,7 +469,7 @@ HeapObject *swift::swift_unownedRetain(HeapObject *object) {
|
||||
}
|
||||
|
||||
void swift::swift_unownedRelease(HeapObject *object) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
swift_nonatomic_unownedRelease(object);
|
||||
#else
|
||||
SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRelease);
|
||||
@@ -520,7 +516,7 @@ void swift::swift_nonatomic_unownedRelease(HeapObject *object) {
|
||||
}
|
||||
|
||||
HeapObject *swift::swift_unownedRetain_n(HeapObject *object, int n) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
return swift_nonatomic_unownedRetain_n(object, n);
|
||||
#else
|
||||
SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetain_n);
|
||||
@@ -533,7 +529,7 @@ HeapObject *swift::swift_unownedRetain_n(HeapObject *object, int n) {
|
||||
}
|
||||
|
||||
void swift::swift_unownedRelease_n(HeapObject *object, int n) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
swift_nonatomic_unownedRelease_n(object, n);
|
||||
#else
|
||||
SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRelease_n);
|
||||
@@ -583,7 +579,7 @@ static HeapObject *_swift_tryRetain_(HeapObject *object) {
|
||||
if (!isValidPointerForNativeRetain(object))
|
||||
return nullptr;
|
||||
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
if (object->refCounts.tryIncrementNonAtomic()) return object;
|
||||
else return nullptr;
|
||||
#else
|
||||
@@ -612,7 +608,7 @@ void swift::swift_setDeallocating(HeapObject *object) {
|
||||
}
|
||||
|
||||
HeapObject *swift::swift_unownedRetainStrong(HeapObject *object) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
return swift_nonatomic_unownedRetainStrong(object);
|
||||
#else
|
||||
SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetainStrong);
|
||||
@@ -640,7 +636,7 @@ HeapObject *swift::swift_nonatomic_unownedRetainStrong(HeapObject *object) {
|
||||
}
|
||||
|
||||
void swift::swift_unownedRetainStrongAndRelease(HeapObject *object) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
swift_nonatomic_unownedRetainStrongAndRelease(object);
|
||||
#else
|
||||
SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetainStrongAndRelease);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <DbgHelp.h>
|
||||
#endif
|
||||
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
@@ -73,7 +73,7 @@ int swift::lookupSymbol(const void *address, SymbolInfo *info) {
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
static StaticMutex mutex;
|
||||
static LazyMutex mutex;
|
||||
static bool isDbgHelpInitialized = false;
|
||||
|
||||
void swift::_swift_withWin32DbgHelpLibrary(
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
#include "swift/Runtime/EnvironmentVariables.h"
|
||||
#include "swift/Runtime/ExistentialContainer.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/Once.h"
|
||||
#include "swift/Runtime/Portability.h"
|
||||
#include "swift/Strings.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
@@ -786,8 +786,8 @@ _cacheCanonicalSpecializedMetadata(const TypeContextDescriptor *description) {
|
||||
static void
|
||||
cacheCanonicalSpecializedMetadata(const TypeContextDescriptor *description,
|
||||
swift_once_t *token) {
|
||||
swift_once(
|
||||
token,
|
||||
swift::once(
|
||||
*token,
|
||||
[](void *uncastDescription) {
|
||||
auto *description = (const TypeContextDescriptor *)uncastDescription;
|
||||
_cacheCanonicalSpecializedMetadata(description);
|
||||
@@ -3148,8 +3148,8 @@ _swift_initClassMetadataImpl(ClassMetadata *self,
|
||||
self->Superclass = getRootSuperclass();
|
||||
|
||||
// Register our custom implementation of class_getImageName.
|
||||
static swift_once_t onceToken;
|
||||
swift_once(&onceToken, [](void *unused) {
|
||||
static swift::once_t onceToken;
|
||||
swift::once(onceToken, [](void *unused) {
|
||||
(void)unused;
|
||||
setUpObjCRuntimeGetImageNameFromClass();
|
||||
}, nullptr);
|
||||
@@ -6282,8 +6282,8 @@ void *MetadataAllocator::Allocate(size_t size, size_t alignment) {
|
||||
assert(alignment <= alignof(void*));
|
||||
assert(size % alignof(void*) == 0);
|
||||
|
||||
static OnceToken_t getenvToken;
|
||||
SWIFT_ONCE_F(getenvToken, checkAllocatorDebugEnvironmentVariables, nullptr);
|
||||
static swift::once_t getenvToken;
|
||||
swift::once(getenvToken, checkAllocatorDebugEnvironmentVariables);
|
||||
|
||||
// If the size is larger than the maximum, just do a normal heap allocation.
|
||||
if (size > PoolRange::MaxPoolAllocationSize) {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "swift/Runtime/Concurrent.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/AtomicWaitQueue.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "../SwiftShims/Visibility.h"
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
@@ -170,7 +170,7 @@ class LockingConcurrentMapStorage {
|
||||
// space is not large enough to accommodate a Mutex along with everything
|
||||
// else. There, use a SmallMutex to squeeze into the available space.
|
||||
using MutexTy =
|
||||
std::conditional_t<sizeof(void *) == 8, StaticMutex, SmallMutex>;
|
||||
std::conditional_t<sizeof(void *) == 8, Mutex, SmallMutex>;
|
||||
StableAddressConcurrentReadableHashMap<EntryType,
|
||||
TaggedMetadataAllocator<Tag>, MutexTy>
|
||||
Map;
|
||||
|
||||
@@ -137,7 +137,7 @@ template <class Impl, class T> struct RetainableBoxBase {
|
||||
static constexpr size_t stride = sizeof(T);
|
||||
static constexpr bool isPOD = false;
|
||||
static constexpr bool isBitwiseTakable = true;
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
static constexpr bool isAtomic = false;
|
||||
#else
|
||||
static constexpr bool isAtomic = true;
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Strings.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
//===--- MutexC11.cpp - Supports Mutex.h using C11 threads ----------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex and Read/Write lock implementations using C11 threads.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/Debug.h"
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_C11
|
||||
|
||||
using namespace swift;
|
||||
|
||||
namespace c11threads {
|
||||
|
||||
#ifndef SWIFT_FATAL_ERROR
|
||||
#define SWIFT_FATAL_ERROR swift::fatalError
|
||||
#endif
|
||||
|
||||
// Triggered if a C11 threads call fails
|
||||
void fatalError(int errcode) {
|
||||
SWIFT_FATAL_ERROR(0, "C11 threads call failed with %d\n", errcode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SWIFT_STDLIB_THREADING_C11
|
||||
@@ -1,109 +0,0 @@
|
||||
//===--- MutexPThread.cpp - Supports Mutex.h using PThreads ---------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex and Read/Write lock implementations using pthreads.
|
||||
//
|
||||
// Darwin shares the pthreads implementation for read/write locks, but
|
||||
// uses inline implementations for os_unfair_lock.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_PTHREADS || SWIFT_STDLIB_THREADING_DARWIN
|
||||
|
||||
#if __has_include(<unistd.h>)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Notes: swift::fatalError is not shared between libswiftCore and libswift_Concurrency
|
||||
// and libswift_Concurrency uses swift_Concurrency_fatalError instead.
|
||||
#ifndef SWIFT_FATAL_ERROR
|
||||
#define SWIFT_FATAL_ERROR swift::fatalError
|
||||
#endif
|
||||
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
#define reportError(PThreadFunction) \
|
||||
do { \
|
||||
int errorcode = PThreadFunction; \
|
||||
if (errorcode != 0) { \
|
||||
SWIFT_FATAL_ERROR(/* flags = */ 0, "'%s' failed with error '%s'(%d)\n", \
|
||||
#PThreadFunction, errorName(errorcode), errorcode); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define returnTrueOrReportError(PThreadFunction, returnFalseOnEBUSY) \
|
||||
do { \
|
||||
int errorcode = PThreadFunction; \
|
||||
if (errorcode == 0) \
|
||||
return true; \
|
||||
if (returnFalseOnEBUSY && errorcode == EBUSY) \
|
||||
return false; \
|
||||
SWIFT_FATAL_ERROR(/* flags = */ 0, "'%s' failed with error '%s'(%d)\n", \
|
||||
#PThreadFunction, errorName(errorcode), errorcode); \
|
||||
} while (false)
|
||||
|
||||
static const char *errorName(int errorcode) {
|
||||
switch (errorcode) {
|
||||
case EINVAL:
|
||||
return "EINVAL";
|
||||
case EPERM:
|
||||
return "EPERM";
|
||||
case EDEADLK:
|
||||
return "EDEADLK";
|
||||
case ENOMEM:
|
||||
return "ENOMEM";
|
||||
case EAGAIN:
|
||||
return "EAGAIN";
|
||||
case EBUSY:
|
||||
return "EBUSY";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
#if !HAS_OS_UNFAIR_LOCK
|
||||
|
||||
void MutexPlatformHelper::init(pthread_mutex_t &mutex, bool checked) {
|
||||
pthread_mutexattr_t attr;
|
||||
int kind = (checked ? PTHREAD_MUTEX_ERRORCHECK : PTHREAD_MUTEX_NORMAL);
|
||||
reportError(pthread_mutexattr_init(&attr));
|
||||
reportError(pthread_mutexattr_settype(&attr, kind));
|
||||
reportError(pthread_mutex_init(&mutex, &attr));
|
||||
reportError(pthread_mutexattr_destroy(&attr));
|
||||
}
|
||||
|
||||
void MutexPlatformHelper::destroy(pthread_mutex_t &mutex) {
|
||||
reportError(pthread_mutex_destroy(&mutex));
|
||||
}
|
||||
|
||||
void MutexPlatformHelper::lock(pthread_mutex_t &mutex) {
|
||||
reportError(pthread_mutex_lock(&mutex));
|
||||
}
|
||||
|
||||
void MutexPlatformHelper::unlock(pthread_mutex_t &mutex) {
|
||||
reportError(pthread_mutex_unlock(&mutex));
|
||||
}
|
||||
|
||||
bool MutexPlatformHelper::try_lock(pthread_mutex_t &mutex) {
|
||||
returnTrueOrReportError(pthread_mutex_trylock(&mutex),
|
||||
/* returnFalseOnEBUSY = */ true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_STDLIB_THREADING_PTHREADS
|
||||
@@ -1,31 +0,0 @@
|
||||
//===--- MutexWin32.cpp - -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex, Read/Write lock, and Scoped lock implementations
|
||||
// using Windows Slim Reader/Writer Locks.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
// Notes: swift::fatalError is not shared between libswiftCore and libswift_Concurrency
|
||||
// and libswift_Concurrency uses swift_Concurrency_fatalError instead.
|
||||
#ifndef SWIFT_FATAL_ERROR
|
||||
#define SWIFT_FATAL_ERROR swift::fatalError
|
||||
#endif
|
||||
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/Debug.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
#endif
|
||||
@@ -15,17 +15,13 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Private.h"
|
||||
#include "swift/Runtime/Once.h"
|
||||
#include "swift/Threading/Once.h"
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include <type_traits>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
#if SWIFT_STDLIB_THREADING_NONE
|
||||
|
||||
// No dependencies on single-threaded environments.
|
||||
|
||||
#elif SWIFT_STDLIB_THREADING_DARWIN
|
||||
#if SWIFT_THREADING_DARWIN
|
||||
|
||||
// On macOS and iOS, swift_once is implemented using GCD.
|
||||
// The compiler emits an inline check matching the barrier-free inline fast
|
||||
@@ -34,12 +30,8 @@ using namespace swift;
|
||||
#include <dispatch/dispatch.h>
|
||||
static_assert(std::is_same<swift_once_t, dispatch_once_t>::value,
|
||||
"swift_once_t and dispatch_once_t must stay in sync");
|
||||
#else
|
||||
|
||||
// On non-Darwin platforms we do not assume any barrier-free inline path
|
||||
// and SwiftTargetInfo.OnceDonePredicateValue is unset in the compiler.
|
||||
|
||||
#endif
|
||||
#endif // SWIFT_THREADING_DARWIN
|
||||
|
||||
// The compiler generates the swift_once_t values as word-sized zero-initialized
|
||||
// variables, so we want to make sure swift_once_t isn't larger than the
|
||||
@@ -52,16 +44,5 @@ static_assert(sizeof(swift_once_t) <= sizeof(void*),
|
||||
/// extent of type swift_once_t.
|
||||
void swift::swift_once(swift_once_t *predicate, void (*fn)(void *),
|
||||
void *context) {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
if (! *predicate) {
|
||||
*predicate = true;
|
||||
fn(context);
|
||||
}
|
||||
#elif SWIFT_STDLIB_THREADING_DARWIN
|
||||
dispatch_once_f(predicate, context, fn);
|
||||
#elif defined(__CYGWIN__)
|
||||
_swift_once_f(predicate, context, fn);
|
||||
#else
|
||||
std::call_once(*predicate, fn, context);
|
||||
#endif
|
||||
swift::once(*predicate, fn, context);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "RuntimeInvocationsTracking.h"
|
||||
#include "swift/Basic/Lazy.h"
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
|
||||
#if defined(SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS)
|
||||
|
||||
@@ -49,7 +49,7 @@ static bool UpdateGlobalRuntimeFunctionCounters = false;
|
||||
/// Global set of counters tracking the total number of runtime invocations.
|
||||
struct RuntimeFunctionCountersStateSentinel {
|
||||
RuntimeFunctionCountersState State;
|
||||
StaticMutex Lock;
|
||||
LazyMutex Lock;
|
||||
};
|
||||
static RuntimeFunctionCountersStateSentinel RuntimeGlobalFunctionCountersState;
|
||||
|
||||
@@ -57,7 +57,7 @@ static RuntimeFunctionCountersStateSentinel RuntimeGlobalFunctionCountersState;
|
||||
/// them.
|
||||
struct RuntimeObjectCacheSentinel {
|
||||
llvm::DenseMap<HeapObject *, RuntimeFunctionCountersState> Cache;
|
||||
StaticMutex Lock;
|
||||
Mutex Lock;
|
||||
};
|
||||
static Lazy<RuntimeObjectCacheSentinel> RuntimeObjectStateCache;
|
||||
|
||||
@@ -101,7 +101,7 @@ static uint16_t RuntimeFunctionCountersOffsets[] = {
|
||||
void SWIFT_RT_TRACK_INVOCATION_NAME(RT_FUNCTION)(HeapObject * object) { \
|
||||
/* Update global counters. */ \
|
||||
if (UpdateGlobalRuntimeFunctionCounters) { \
|
||||
StaticMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock); \
|
||||
LazyMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock); \
|
||||
RuntimeGlobalFunctionCountersState.State \
|
||||
.SWIFT_RT_FUNCTION_INVOCATION_COUNTER_NAME(RT_FUNCTION)++; \
|
||||
if (GlobalRuntimeFunctionCountersUpdateHandler) { \
|
||||
@@ -117,7 +117,7 @@ static uint16_t RuntimeFunctionCountersOffsets[] = {
|
||||
/* Update per object counters. */ \
|
||||
if (UpdatePerObjectRuntimeFunctionCounters && object) { \
|
||||
auto &theSentinel = RuntimeObjectStateCache.get(); \
|
||||
StaticMutex::ScopedLock lock(theSentinel.Lock); \
|
||||
Mutex::ScopedLock lock(theSentinel.Lock); \
|
||||
theSentinel.Cache[object].SWIFT_RT_FUNCTION_INVOCATION_COUNTER_NAME( \
|
||||
RT_FUNCTION)++; \
|
||||
/* TODO: Remember the order/history of operations? */ \
|
||||
@@ -131,7 +131,7 @@ static uint16_t RuntimeFunctionCountersOffsets[] = {
|
||||
void _swift_getObjectRuntimeFunctionCounters(
|
||||
HeapObject *object, RuntimeFunctionCountersState *result) {
|
||||
auto &theSentinel = RuntimeObjectStateCache.get();
|
||||
StaticMutex::ScopedLock lock(theSentinel.Lock);
|
||||
Mutex::ScopedLock lock(theSentinel.Lock);
|
||||
*result = theSentinel.Cache[object];
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ void _swift_getObjectRuntimeFunctionCounters(
|
||||
void _swift_setObjectRuntimeFunctionCounters(
|
||||
HeapObject *object, RuntimeFunctionCountersState *state) {
|
||||
auto &theSentinel = RuntimeObjectStateCache.get();
|
||||
StaticMutex::ScopedLock lock(theSentinel.Lock);
|
||||
Mutex::ScopedLock lock(theSentinel.Lock);
|
||||
theSentinel.Cache[object] = *state;
|
||||
}
|
||||
|
||||
@@ -148,14 +148,14 @@ void _swift_setObjectRuntimeFunctionCounters(
|
||||
/// each runtime function of interest.
|
||||
void _swift_getGlobalRuntimeFunctionCounters(
|
||||
RuntimeFunctionCountersState *result) {
|
||||
StaticMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock);
|
||||
LazyMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock);
|
||||
*result = RuntimeGlobalFunctionCountersState.State;
|
||||
}
|
||||
|
||||
/// Set the global runtime state of function pointers from a provided state.
|
||||
void _swift_setGlobalRuntimeFunctionCounters(
|
||||
RuntimeFunctionCountersState *state) {
|
||||
StaticMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock);
|
||||
LazyMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock);
|
||||
RuntimeGlobalFunctionCountersState.State = *state;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ static void _swift_dumpRuntimeCounters(RuntimeFunctionCountersState *State) {
|
||||
/// Dump all per-object runtime function pointers.
|
||||
void _swift_dumpObjectsRuntimeFunctionPointers() {
|
||||
auto &theSentinel = RuntimeObjectStateCache.get();
|
||||
StaticMutex::ScopedLock lock(theSentinel.Lock);
|
||||
Mutex::ScopedLock lock(theSentinel.Lock);
|
||||
for (auto &Pair : theSentinel.Cache) {
|
||||
printf("\n\nRuntime counters for object at address %p:\n", Pair.getFirst());
|
||||
_swift_dumpRuntimeCounters(&Pair.getSecond());
|
||||
|
||||
@@ -11,81 +11,58 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SwiftTLSContext.h"
|
||||
#include "swift/Basic/Lazy.h"
|
||||
#include "swift/Runtime/Once.h"
|
||||
#include "swift/Runtime/ThreadLocalStorage.h"
|
||||
|
||||
#include "swift/Threading/Once.h"
|
||||
#include "swift/Threading/ThreadLocalStorage.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::runtime;
|
||||
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
|
||||
SwiftTLSContext &SwiftTLSContext::get() {
|
||||
static SwiftTLSContext TLSContext;
|
||||
return TLSContext;
|
||||
}
|
||||
|
||||
#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
|
||||
// Use the reserved TSD key if possible.
|
||||
#if SWIFT_THREADING_USE_RESERVED_TLS_KEYS
|
||||
|
||||
SwiftTLSContext &SwiftTLSContext::get() {
|
||||
SwiftTLSContext *ctx = static_cast<SwiftTLSContext *>(
|
||||
SWIFT_THREAD_GETSPECIFIC(SWIFT_RUNTIME_TLS_KEY));
|
||||
// If we have reserved keys, use those
|
||||
SwiftTLSContext *ctx
|
||||
= static_cast<SwiftTLSContext *>(swift::tls_get(SWIFT_RUNTIME_TLS_KEY));
|
||||
if (ctx)
|
||||
return *ctx;
|
||||
|
||||
static OnceToken_t setupToken;
|
||||
SWIFT_ONCE_F(
|
||||
setupToken,
|
||||
[](void *) {
|
||||
SWIFT_THREAD_KEY_INIT(SWIFT_RUNTIME_TLS_KEY, [](void *pointer) {
|
||||
delete static_cast<SwiftTLSContext *>(pointer);
|
||||
});
|
||||
},
|
||||
nullptr);
|
||||
static swift::once_t token;
|
||||
swift::tls_init_once(token, SWIFT_RUNTIME_TLS_KEY, [](void *pointer) {
|
||||
delete static_cast<SwiftTLSContext *>(pointer);
|
||||
});
|
||||
|
||||
ctx = new SwiftTLSContext();
|
||||
SWIFT_THREAD_SETSPECIFIC(SWIFT_RUNTIME_TLS_KEY, ctx);
|
||||
swift::tls_set(SWIFT_RUNTIME_TLS_KEY, ctx);
|
||||
return *ctx;
|
||||
}
|
||||
|
||||
#elif __has_feature(cxx_thread_local)
|
||||
// Second choice is direct language support for thread-locals.
|
||||
#elif defined(SWIFT_THREAD_LOCAL)
|
||||
|
||||
namespace {
|
||||
|
||||
static thread_local SwiftTLSContext TLSContext;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
SwiftTLSContext &SwiftTLSContext::get() { return TLSContext; }
|
||||
// If we have the thread local attribute, use that
|
||||
// (note that this happens for the no-threads case too)
|
||||
static SWIFT_THREAD_LOCAL SwiftTLSContext TLSContext;
|
||||
return TLSContext;
|
||||
|
||||
#else
|
||||
// Use the platform thread-local data API.
|
||||
|
||||
static __swift_thread_key_t createSwiftThreadKey() {
|
||||
__swift_thread_key_t key;
|
||||
int result = SWIFT_THREAD_KEY_CREATE(&key, [](void *pointer) {
|
||||
// Otherwise, allocate ourselves a key and use that
|
||||
static swift::tls_key runtimeKey;
|
||||
static swift::once_t token;
|
||||
|
||||
swift::tls_alloc_once(token, runtimeKey, [](void *pointer) {
|
||||
delete static_cast<SwiftTLSContext *>(pointer);
|
||||
});
|
||||
|
||||
if (result != 0) {
|
||||
fatalError(0, "couldn't create thread key for exclusivity: %s\n",
|
||||
strerror(result));
|
||||
}
|
||||
return key;
|
||||
}
|
||||
SwiftTLSContext *ctx
|
||||
= static_cast<SwiftTLSContext *>(swift::tls_get(runtimeKey));
|
||||
if (ctx)
|
||||
return *ctx;
|
||||
|
||||
static SwiftTLSContext &getTLSContext() {
|
||||
static __swift_thread_key_t key = createSwiftThreadKey();
|
||||
|
||||
SwiftTLSContext *ctx =
|
||||
static_cast<SwiftTLSContext *>(SWIFT_THREAD_GETSPECIFIC(key));
|
||||
if (!ctx) {
|
||||
ctx = new SwiftTLSContext();
|
||||
SWIFT_THREAD_SETSPECIFIC(key, ctx);
|
||||
}
|
||||
ctx = new SwiftTLSContext();
|
||||
swift::tls_set(runtimeKey, ctx);
|
||||
return *ctx;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
#include "swift/Basic/Lazy.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Runtime/ObjCBridge.h"
|
||||
#include "swift/Runtime/Portability.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include <vector>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
@@ -59,7 +59,7 @@ namespace {
|
||||
|
||||
struct SwiftNullSentinelCache {
|
||||
std::vector<id> Cache;
|
||||
StaticMutex Lock;
|
||||
Mutex Lock;
|
||||
};
|
||||
|
||||
static Lazy<SwiftNullSentinelCache> Sentinels;
|
||||
@@ -73,7 +73,7 @@ static id getSentinelForDepth(unsigned depth) {
|
||||
auto &theSentinels = Sentinels.get();
|
||||
unsigned depthIndex = depth - 2;
|
||||
{
|
||||
StaticMutex::ScopedLock lock(theSentinels.Lock);
|
||||
Mutex::ScopedLock lock(theSentinels.Lock);
|
||||
const auto &cache = theSentinels.Cache;
|
||||
if (depthIndex < cache.size()) {
|
||||
id cached = cache[depthIndex];
|
||||
@@ -83,7 +83,7 @@ static id getSentinelForDepth(unsigned depth) {
|
||||
}
|
||||
// Make one if we need to.
|
||||
{
|
||||
StaticMutex::ScopedLock lock(theSentinels.Lock);
|
||||
Mutex::ScopedLock lock(theSentinels.Lock);
|
||||
if (depthIndex >= theSentinels.Cache.size())
|
||||
theSentinels.Cache.resize(depthIndex + 1);
|
||||
auto &cached = theSentinels.Cache[depthIndex];
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "SwiftShims/Random.h"
|
||||
|
||||
#include <algorithm> // required for std::min
|
||||
@@ -108,6 +108,7 @@ void swift_stdlib_random(void *buf, __swift_size_t nbytes) {
|
||||
WHILE_EINTR(open("/dev/urandom", O_RDONLY | O_CLOEXEC, 0));
|
||||
|
||||
if (fd != -1) {
|
||||
// ###FIXME: Why is this locked? None of the others are.
|
||||
static StaticMutex mutex;
|
||||
mutex.withLock([&] {
|
||||
actual_nbytes = WHILE_EINTR(read(fd, buf, nbytes));
|
||||
|
||||
@@ -484,7 +484,7 @@ int _swift_stdlib_putc_stderr(int C) {
|
||||
}
|
||||
|
||||
size_t _swift_stdlib_getHardwareConcurrency() {
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
#ifdef SWIFT_THREADING_NONE
|
||||
return 1;
|
||||
#else
|
||||
return std::thread::hardware_concurrency();
|
||||
@@ -537,12 +537,12 @@ __swift_bool swift_stdlib_isStackAllocationSafe(__swift_size_t byteCount,
|
||||
|
||||
__swift_bool _swift_stdlib_getCurrentStackBounds(__swift_uintptr_t *outBegin,
|
||||
__swift_uintptr_t *outEnd) {
|
||||
#if SWIFT_STDLIB_THREADING_NONE
|
||||
#if SWIFT_THREADING_NONE
|
||||
// This platform does not support threads, so the API we'd call to get stack
|
||||
// bounds (i.e. libpthread) is not going to be usable.
|
||||
return false;
|
||||
|
||||
#elif SWIFT_STDLIB_THREADING_DARWIN
|
||||
#elif SWIFT_THREADING_DARWIN
|
||||
pthread_t thread = pthread_self();
|
||||
|
||||
// On Apple platforms, pthread_get_stackaddr_np() gets the address of the
|
||||
@@ -556,11 +556,11 @@ __swift_bool _swift_stdlib_getCurrentStackBounds(__swift_uintptr_t *outBegin,
|
||||
*outBegin = *outEnd - pthread_get_stacksize_np(thread);
|
||||
return true;
|
||||
|
||||
#elif SWIFT_STDLIB_THREADING_C11
|
||||
#elif SWIFT_THREADING_C11
|
||||
// We don't know any way to do this for C11 threads
|
||||
return false
|
||||
|
||||
#elif SWIFT_STDLIB_THREADING_WIN32
|
||||
#elif SWIFT_THREADING_WIN32
|
||||
|
||||
# if _WIN32_WINNT >= 0x0602
|
||||
ULONG_PTR lowLimit = 0;
|
||||
@@ -576,7 +576,7 @@ __swift_bool _swift_stdlib_getCurrentStackBounds(__swift_uintptr_t *outBegin,
|
||||
return false;
|
||||
# endif
|
||||
|
||||
#elif SWIFT_STDLIB_THREADING_PTHREADS
|
||||
#elif SWIFT_THREADING_PTHREADS
|
||||
|
||||
# if defined(__OpenBSD__)
|
||||
stack_t sinfo;
|
||||
|
||||
@@ -13,9 +13,8 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "SwiftShims/ThreadLocalStorage.h"
|
||||
#include "swift/Basic/Lazy.h"
|
||||
#include "swift/Threading/ThreadLocalStorage.h"
|
||||
#include "swift/Runtime/Debug.h"
|
||||
#include "swift/Runtime/ThreadLocalStorage.h"
|
||||
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
|
||||
void _stdlib_destroyTLS(void *);
|
||||
@@ -23,97 +22,49 @@ void _stdlib_destroyTLS(void *);
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
|
||||
void *_stdlib_createTLS(void);
|
||||
|
||||
#if !SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC || (defined(_WIN32) && !defined(__CYGWIN__))
|
||||
|
||||
static void
|
||||
#if defined(_M_IX86)
|
||||
__stdcall
|
||||
#endif
|
||||
destroyTLS_CCAdjustmentThunk(void *ptr) {
|
||||
_stdlib_destroyTLS(ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
|
||||
typedef
|
||||
#if defined(_M_IX86)
|
||||
__stdcall
|
||||
#endif
|
||||
void (*__swift_thread_key_destructor)(void *);
|
||||
|
||||
static inline int
|
||||
_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
|
||||
__swift_thread_key_destructor _Nullable destructor) {
|
||||
*key = FlsAlloc(destroyTLS_CCAdjustmentThunk);
|
||||
if (*key == FLS_OUT_OF_INDEXES)
|
||||
return GetLastError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SWIFT_STDLIB_THREADING_NONE
|
||||
|
||||
SWIFT_RUNTIME_STDLIB_INTERNAL
|
||||
void *
|
||||
_swift_stdlib_threadLocalStorageGet(void) {
|
||||
static void *value;
|
||||
if (!value) {
|
||||
value = _stdlib_createTLS();
|
||||
}
|
||||
|
||||
#if SWIFT_THREADING_NONE
|
||||
|
||||
// If there's no threading, we can just keep a static variable.
|
||||
static void *value = _stdlib_createTLS();
|
||||
return value;
|
||||
}
|
||||
|
||||
#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
|
||||
#elif SWIFT_THREADING_USE_RESERVED_TLS_KEYS
|
||||
|
||||
SWIFT_RUNTIME_STDLIB_INTERNAL
|
||||
void *
|
||||
_swift_stdlib_threadLocalStorageGet(void) {
|
||||
void *value = SWIFT_THREAD_GETSPECIFIC(SWIFT_STDLIB_TLS_KEY);
|
||||
// If we have reserved keys, use those
|
||||
void *value = swift::tls_get(SWIFT_STDLIB_TLS_KEY);
|
||||
if (value)
|
||||
return value;
|
||||
|
||||
static swift::OnceToken_t token;
|
||||
SWIFT_ONCE_F(token, [](void *) {
|
||||
int result = SWIFT_THREAD_KEY_INIT(SWIFT_STDLIB_TLS_KEY, [](void *pointer) {
|
||||
_stdlib_destroyTLS(pointer);
|
||||
});
|
||||
if (result != 0)
|
||||
swift::fatalError(0, "couldn't create pthread key for stdlib TLS: %s\n",
|
||||
std::strerror(result));
|
||||
}, nullptr);
|
||||
static swift::once_t token;
|
||||
swift::tls_init_once(token, SWIFT_STDLIB_TLS_KEY, [](void *pointer) {
|
||||
_stdlib_destroyTLS(pointer);
|
||||
});
|
||||
|
||||
value = _stdlib_createTLS();
|
||||
SWIFT_THREAD_SETSPECIFIC(SWIFT_STDLIB_TLS_KEY, value);
|
||||
swift::tls_set(SWIFT_STDLIB_TLS_KEY, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
#else
|
||||
#else // Threaded, but not using reserved keys
|
||||
|
||||
SWIFT_RUNTIME_STDLIB_INTERNAL
|
||||
void *
|
||||
_swift_stdlib_threadLocalStorageGet(void) {
|
||||
static swift::OnceToken_t token;
|
||||
static __swift_thread_key_t key;
|
||||
// Register a key and use it
|
||||
static swift::tls_key key;
|
||||
static swift::once_t token;
|
||||
|
||||
SWIFT_ONCE_F(token, [](void *) {
|
||||
int result = SWIFT_THREAD_KEY_CREATE(&key, destroyTLS_CCAdjustmentThunk);
|
||||
if (result != 0)
|
||||
swift::fatalError(0, "couldn't create pthread key for stdlib TLS: %s\n",
|
||||
std::strerror(result));
|
||||
}, nullptr);
|
||||
swift::tls_alloc_once(token, key, [](void *)pointer {
|
||||
_stdlib_destroyTLS(pointer);
|
||||
});
|
||||
|
||||
void *value = SWIFT_THREAD_GETSPECIFIC(key);
|
||||
void *value = swift::tls_get(key);
|
||||
if (!value) {
|
||||
value = _stdlib_createTLS();
|
||||
int result = SWIFT_THREAD_SETSPECIFIC(key, value);
|
||||
if (result != 0)
|
||||
swift::fatalError(0, "pthread_setspecific failed: %s\n",
|
||||
std::strerror(result));
|
||||
swift::tls_set(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "Overrides.h"
|
||||
#include "../../public/runtime/Private.h"
|
||||
#include "swift/Basic/Lazy.h"
|
||||
#include "swift/Threading/Once.h"
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach-o/getsect.h>
|
||||
@@ -91,8 +91,8 @@ swift::swift50override_conformsToProtocol(const Metadata *type,
|
||||
ConformsToProtocol_t *original_conformsToProtocol)
|
||||
{
|
||||
// Register our add image callback if necessary.
|
||||
static OnceToken_t token;
|
||||
SWIFT_ONCE_F(token, registerAddImageCallback, nullptr);
|
||||
static swift::once_t token;
|
||||
swift::once(token, registerAddImageCallback, nullptr);
|
||||
|
||||
// The implementation of swift_conformsToProtocol in Swift 5.0 would return
|
||||
// a false negative answer when asking whether a subclass conforms using
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
|
||||
#include "swift/Runtime/Exclusivity.h"
|
||||
#include "swift/Runtime/FunctionReplacement.h"
|
||||
#include "swift/Runtime/Once.h"
|
||||
#include "swift/Runtime/ThreadLocalStorage.h"
|
||||
#include "swift/Threading/ThreadLocalStorage.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
@@ -41,11 +40,11 @@ extern "C" char *swift_getFunctionReplacement50(char **ReplFnPtr, char *CurrFn)
|
||||
return nullptr;
|
||||
|
||||
auto origKey =
|
||||
(uintptr_t)SWIFT_THREAD_GETSPECIFIC(SWIFT_COMPATIBILITY_50_TLS_KEY);
|
||||
(uintptr_t)swift::tls_get(SWIFT_COMPATIBILITY_50_TLS_KEY);
|
||||
if ((origKey & 0x1) != 0) {
|
||||
auto mask = ((uintptr_t)-1) < 1;
|
||||
auto resetKey = origKey & mask;
|
||||
SWIFT_THREAD_SETSPECIFIC(SWIFT_COMPATIBILITY_50_TLS_KEY, (void *)resetKey);
|
||||
swift::tls_set(SWIFT_COMPATIBILITY_50_TLS_KEY, (void *)resetKey);
|
||||
return nullptr;
|
||||
}
|
||||
return ReplFn;
|
||||
@@ -59,9 +58,9 @@ extern "C" char *swift_getOrigOfReplaceable50(char **OrigFnPtr) {
|
||||
|
||||
char *OrigFn = *OrigFnPtr;
|
||||
auto origKey =
|
||||
(uintptr_t)SWIFT_THREAD_GETSPECIFIC(SWIFT_COMPATIBILITY_50_TLS_KEY);
|
||||
(uintptr_t)swift::tls_get(SWIFT_COMPATIBILITY_50_TLS_KEY);
|
||||
auto newKey = origKey | 0x1;
|
||||
SWIFT_THREAD_SETSPECIFIC(SWIFT_COMPATIBILITY_50_TLS_KEY, (void *)newKey);
|
||||
swift::tls_set(SWIFT_COMPATIBILITY_50_TLS_KEY, (void *)newKey);
|
||||
return OrigFn;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
include(SwiftTestUtils)
|
||||
include(Threading)
|
||||
|
||||
function(swift_configure_lit_site_cfg source_path destination_path installed_name)
|
||||
if (CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
@@ -394,6 +395,14 @@ foreach(SDK ${SWIFT_SDKS})
|
||||
list(APPEND LIT_ARGS "--param" "string_processing")
|
||||
endif()
|
||||
|
||||
if("${SWIFT_SDK_${SDK}_THREADING_PACKAGE}")
|
||||
list(APPEND LIT_ARGS "--param" "threading=${SWIFT_SDK_${SDK}_THREADING_PACKAGE}")
|
||||
else()
|
||||
threading_package_default("${SDK}" SWIFT_THREADING_PACKAGE)
|
||||
list(APPEND LIT_ARGS "--param"
|
||||
"threading=${SWIFT_THREADING_PACKAGE}")
|
||||
endif()
|
||||
|
||||
foreach(test_subset ${TEST_SUBSETS})
|
||||
set(directories)
|
||||
set(dependencies ${test_dependencies})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %clang -c -v %target-cc-options -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
// RUN: %clang -c -v %target-cc-options %target-threading-opt -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
|
||||
// RUN: %target-build-swift -v %mcp_opt %s %t/isPrespecialized.o -import-objc-header %S/Inputs/isPrespecialized.h -Xfrontend -prespecialize-generic-metadata -target %module-target-future -lc++ -L %clang-include-dir/../lib/swift/macosx -sdk %sdk -o %t/main
|
||||
// RUN: %target-codesign %t/main
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %clang -c -v %target-cc-options -g -O0 -isysroot %sdk %S/Inputs/extraDataFields.cpp -o %t/extraDataFields.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
// RUN: %clang -c -v %target-cc-options %target-threading-opt -g -O0 -isysroot %sdk %S/Inputs/extraDataFields.cpp -o %t/extraDataFields.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
|
||||
// RUN: %target-build-swift -c %S/Inputs/enum-extra-data-fields.swift -emit-library -emit-module -enable-library-evolution -module-name ExtraDataFieldsNoTrailingFlags -target %module-target-future -Xfrontend -disable-generic-metadata-prespecialization -emit-module-path %t/ExtraDataFieldsNoTrailingFlags.swiftmodule -o %t/%target-library-name(ExtraDataFieldsNoTrailingFlags)
|
||||
// RUN: %target-build-swift -c %S/Inputs/enum-extra-data-fields.swift -emit-library -emit-module -enable-library-evolution -module-name ExtraDataFieldsTrailingFlags -target %module-target-future -Xfrontend -prespecialize-generic-metadata -emit-module-path %t/ExtraDataFieldsTrailingFlags.swiftmodule -o %t/%target-library-name(ExtraDataFieldsTrailingFlags)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %clang -c -v %target-cc-options -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
// RUN: %clang -c -v %target-cc-options %target-threading-opt -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
|
||||
// RUN: %target-build-swift -v %mcp_opt %s %t/isPrespecialized.o -import-objc-header %S/Inputs/isPrespecialized.h -Xfrontend -prespecialize-generic-metadata -target %module-target-future -lc++ -L %clang-include-dir/../lib/swift/macosx -sdk %sdk -o %t/main
|
||||
// RUN: %target-codesign %t/main
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %clang -c -v %target-cc-options -g -O0 -isysroot %sdk %S/Inputs/extraDataFields.cpp -o %t/extraDataFields.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx -I %swift_obj_root/include
|
||||
// RUN: %clang -c -v %target-cc-options %target-threading-opt -g -O0 -isysroot %sdk %S/Inputs/extraDataFields.cpp -o %t/extraDataFields.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx -I %swift_obj_root/include
|
||||
|
||||
// RUN: %target-build-swift -c %S/Inputs/struct-extra-data-fields.swift -emit-library -emit-module -module-name ExtraDataFieldsNoTrailingFlags -target %module-target-future -Xfrontend -disable-generic-metadata-prespecialization -emit-module-path %t/ExtraDataFieldsNoTrailingFlags.swiftmodule -o %t/%target-library-name(ExtraDataFieldsNoTrailingFlags)
|
||||
// RUN: %target-build-swift -c %S/Inputs/struct-extra-data-fields.swift -emit-library -emit-module -module-name ExtraDataFieldsTrailingFlags -target %module-target-future -Xfrontend -prespecialize-generic-metadata -emit-module-path %t/ExtraDataFieldsTrailingFlags.swiftmodule -o %t/%target-library-name(ExtraDataFieldsTrailingFlags)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// RUN: %target-build-swift -c %s -DCONFORMANCE_2 -emit-library -emit-module -module-name Conformance2 -target %module-target-future -Xfrontend -prespecialize-generic-metadata -emit-module-path %t/Conformance2.swiftmodule -o %t/%target-library-name(Conformance2) -lBase -I %t -L %t
|
||||
// RUN: %target-build-swift -c %s -DGENERIC -emit-library -emit-module -module-name Generic -target %module-target-future -Xfrontend -prespecialize-generic-metadata -emit-module-path %t/Generic.swiftmodule -o %t/%target-library-name(Generic) -lBase -lConformance1 -I %t -L %t
|
||||
// RUN: %target-build-swift -c %s -DERASE -emit-library -emit-module -module-name Erase -target %module-target-future -Xfrontend -prespecialize-generic-metadata -emit-module-path %t/Erase.swiftmodule -o %t/%target-library-name(Erase) -lBase -lConformance2 -I %t -L %t
|
||||
// RUN: %clang -c -v %target-cc-options -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
// RUN: %clang -c -v %target-cc-options %target-threading-opt -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
// RUN: %target-build-swift %s %S/Inputs/main.swift %S/Inputs/consume-logging-metadata-value.swift %t/isPrespecialized.o -import-objc-header %S/Inputs/isPrespecialized.h -DMAIN -target %module-target-future -Xfrontend -prespecialize-generic-metadata -lBase -lConformance1 -lConformance2 -lGeneric -lErase -lc++ -I %t -L %t -L %clang-include-dir/../lib/swift/macosx -o %t/main
|
||||
|
||||
// RUN: %target-codesign %t/main
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %clang -c -v %target-cc-options -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
// RUN: %clang -c -v %target-cc-options %target-threading-opt -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
|
||||
// RUN: %target-build-swift %S/Inputs/struct-public-nonfrozen-1argument.swift -emit-module -emit-library -module-name Module -Xfrontend -prespecialize-generic-metadata -target %module-target-future -emit-module-path %t/Module.swiftmodule -o %t/%target-library-name(Module)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %clang -c -v %target-cc-options -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
// RUN: %clang -c -v %target-cc-options %target-threading-opt -g -O0 -isysroot %sdk %S/Inputs/isPrespecialized.cpp -o %t/isPrespecialized.o -I %clang-include-dir -I %swift_src_root/include/ -I %llvm_src_root/include -I %llvm_obj_root/include -L %clang-include-dir/../lib/swift/macosx
|
||||
|
||||
// RUN: %target-build-swift -v %mcp_opt %s %t/isPrespecialized.o -import-objc-header %S/Inputs/isPrespecialized.h -Xfrontend -prespecialize-generic-metadata -target %module-target-future -lc++ -L %clang-include-dir/../lib/swift/macosx -sdk %sdk -o %t/main
|
||||
// RUN: %target-codesign %t/main
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-clang -std=c++14 %target-rtti-opt %target-pic-opt %target-msvc-runtime-opt -DSWIFT_INLINE_NAMESPACE=__runtime -g -c %S/Inputs/RoundTrip/RoundTrip.cpp -I%swift_obj_root/include -I%swift_src_root/include -I%swift_src_root/stdlib/include -I%swift_src_root/stdlib/public/runtime -I%llvm_src_root/include -I%llvm_obj_root/include -o %t/RoundTrip.o
|
||||
// RUN: %target-clang -std=c++14 %target-threading-opt %target-rtti-opt %target-pic-opt %target-msvc-runtime-opt -DSWIFT_INLINE_NAMESPACE=__runtime -g -c %S/Inputs/RoundTrip/RoundTrip.cpp -I%swift_obj_root/include -I%swift_src_root/include -I%swift_src_root/stdlib/include -I%swift_src_root/stdlib/public/runtime -I%llvm_src_root/include -I%llvm_obj_root/include -o %t/RoundTrip.o
|
||||
// RUN: %target-build-swift -g -static -emit-module-path %t/RoundTrip.swiftmodule -emit-module -emit-library -module-name RoundTrip -o %t/%target-static-library-name(RoundTrip) %S/Inputs/RoundTrip/RoundTrip.swift %t/RoundTrip.o
|
||||
// RUN: echo "// AUTOGENERATED" > %t/all-tests.swift
|
||||
// RUN: for module in %S/Inputs/testcases/*.swift; do modname=$(basename $module .swift); echo "import $modname" >> %t/all-tests.swift; done
|
||||
|
||||
@@ -448,6 +448,14 @@ if string_processing is not None:
|
||||
|
||||
config.available_features.add('lld_lto')
|
||||
|
||||
threading = lit_config.params.get('threading', 'none')
|
||||
config.available_features.add('threading_{}'.format(threading))
|
||||
if threading != "none":
|
||||
config.available_features.add('thread_safe_runtime')
|
||||
|
||||
config.substitutions.append(('%target-threading-opt',
|
||||
'-DSWIFT_THREADING_{0}=1'.format(threading.upper())))
|
||||
|
||||
test_options = os.environ.get('SWIFT_TEST_OPTIONS')
|
||||
if test_options:
|
||||
config.swift_test_options += ' '
|
||||
|
||||
@@ -99,10 +99,10 @@ if "@SWIFT_OPTIMIZED@" == "TRUE":
|
||||
if "@SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY@" == "TRUE":
|
||||
config.available_features.add("single_threaded_concurrency")
|
||||
|
||||
if "@SWIFT_STDLIB_THREADING_PACKAGE@" != "none":
|
||||
if "@SWIFT_THREADING_PACKAGE@" != "none":
|
||||
# This is not called "threading" because we might want that later
|
||||
config.available_features.add("thread_safe_runtime")
|
||||
config.available_features.add("threading_@SWIFT_STDLIB_THREADING_PACKAGE@")
|
||||
config.available_features.add("threading_@SWIFT_THREADING_PACKAGE@")
|
||||
|
||||
if "@SWIFT_ENABLE_REFLECTION@" == "TRUE":
|
||||
config.available_features.add("reflection")
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/Mutex.h"
|
||||
#include "swift/Threading/Mutex.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
@@ -46,13 +46,13 @@ TEST(MutexTest, BasicLockableThreaded) {
|
||||
basicLockableThreaded(mutex);
|
||||
}
|
||||
|
||||
TEST(StaticMutexTest, BasicLockableThreaded) {
|
||||
static StaticMutex mutex;
|
||||
TEST(LazyMutexTest, BasicLockableThreaded) {
|
||||
static LazyMutex mutex;
|
||||
basicLockableThreaded(mutex);
|
||||
}
|
||||
|
||||
TEST(StaticUnsafeMutexTest, BasicLockableThreaded) {
|
||||
static StaticUnsafeMutex mutex;
|
||||
TEST(LazyUnsafeMutexTest, BasicLockableThreaded) {
|
||||
static LazyUnsafeMutex mutex;
|
||||
basicLockableThreaded(mutex);
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ TEST(MutexTest, LockableThreaded) {
|
||||
lockableThreaded(mutex);
|
||||
}
|
||||
|
||||
TEST(StaticMutexTest, LockableThreaded) {
|
||||
static StaticMutex Mutex;
|
||||
TEST(LazyMutexTest, LockableThreaded) {
|
||||
static LazyMutex Mutex;
|
||||
lockableThreaded(Mutex);
|
||||
}
|
||||
|
||||
@@ -126,9 +126,9 @@ TEST(MutexTest, ScopedLockThreaded) {
|
||||
scopedLockThreaded<Mutex::ScopedLock>(mutex);
|
||||
}
|
||||
|
||||
TEST(StaticMutexTest, ScopedLockThreaded) {
|
||||
static StaticMutex Mutex;
|
||||
scopedLockThreaded<StaticMutex::ScopedLock>(Mutex);
|
||||
TEST(LazyMutexTest, ScopedLockThreaded) {
|
||||
static LazyMutex Mutex;
|
||||
scopedLockThreaded<LazyMutex::ScopedLock>(Mutex);
|
||||
}
|
||||
|
||||
TEST(SmallMutexTest, ScopedLockThreaded) {
|
||||
@@ -165,10 +165,10 @@ TEST(MutexTest, ScopedUnlockUnderScopedLockThreaded) {
|
||||
mutex);
|
||||
}
|
||||
|
||||
TEST(StaticMutexTest, ScopedUnlockUnderScopedLockThreaded) {
|
||||
static StaticMutex Mutex;
|
||||
scopedUnlockUnderScopedLockThreaded<StaticMutex::ScopedLock,
|
||||
StaticMutex::ScopedUnlock>(Mutex);
|
||||
TEST(LazyMutexTest, ScopedUnlockUnderScopedLockThreaded) {
|
||||
static LazyMutex Mutex;
|
||||
scopedUnlockUnderScopedLockThreaded<LazyMutex::ScopedLock,
|
||||
LazyMutex::ScopedUnlock>(Mutex);
|
||||
}
|
||||
|
||||
TEST(SmallMutexTest, ScopedUnlockUnderScopedLockThreaded) {
|
||||
@@ -200,8 +200,8 @@ TEST(MutexTest, CriticalSectionThreaded) {
|
||||
criticalSectionThreaded(mutex);
|
||||
}
|
||||
|
||||
TEST(StaticMutexTest, CriticalSectionThreaded) {
|
||||
static StaticMutex Mutex;
|
||||
TEST(LazyMutexTest, CriticalSectionThreaded) {
|
||||
static LazyMutex Mutex;
|
||||
criticalSectionThreaded(Mutex);
|
||||
}
|
||||
|
||||
134
unittests/Threading/ThreadingHelpers.h
Normal file
134
unittests/Threading/ThreadingHelpers.h
Normal file
@@ -0,0 +1,134 @@
|
||||
//===--- Concurrent.cpp - Concurrent data structure tests -----------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef THREADING_HELPERS_H
|
||||
#define THREADING_HELPERS_H
|
||||
|
||||
#include <thread>
|
||||
|
||||
// When true many of the threaded tests log activity to help triage issues.
|
||||
static bool trace = false;
|
||||
|
||||
template <typename ThreadBody, typename AfterSpinRelease>
|
||||
void threadedExecute(int threadCount, ThreadBody threadBody,
|
||||
AfterSpinRelease afterSpinRelease) {
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
// Block the threads we are about to create.
|
||||
std::atomic<bool> spinWait(true);
|
||||
std::atomic<int> readyCount(0);
|
||||
std::atomic<int> activeCount(0);
|
||||
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
threads.push_back(std::thread([&, i] {
|
||||
readyCount++;
|
||||
|
||||
while (spinWait) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
activeCount++;
|
||||
|
||||
threadBody(i);
|
||||
}));
|
||||
}
|
||||
|
||||
while (readyCount < threadCount) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
// Allow our threads to fight for the lock.
|
||||
spinWait = false;
|
||||
|
||||
while (activeCount < threadCount) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
afterSpinRelease();
|
||||
|
||||
// Wait until all of our threads have finished.
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ThreadBody>
|
||||
void threadedExecute(int threadCount, ThreadBody threadBody) {
|
||||
threadedExecute(threadCount, threadBody, [] {});
|
||||
}
|
||||
|
||||
template <typename M, typename C, typename ConsumerBody, typename ProducerBody>
|
||||
void threadedExecute(M &mutex, C &condition, bool &doneCondition,
|
||||
ConsumerBody consumerBody, ProducerBody producerBody) {
|
||||
|
||||
std::vector<std::thread> producers;
|
||||
std::vector<std::thread> consumers;
|
||||
|
||||
// Block the threads we are about to create.
|
||||
std::atomic<bool> spinWait(true);
|
||||
|
||||
for (int i = 1; i <= 8; ++i) {
|
||||
consumers.push_back(std::thread([&, i] {
|
||||
while (spinWait) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
consumerBody(i);
|
||||
|
||||
if (trace)
|
||||
printf("### Consumer[%d] thread exiting.\n", i);
|
||||
}));
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
producers.push_back(std::thread([&, i] {
|
||||
while (spinWait) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
producerBody(i);
|
||||
|
||||
if (trace)
|
||||
printf("### Producer[%d] thread exiting.\n", i);
|
||||
}));
|
||||
}
|
||||
|
||||
// Poor mans attempt to get as many threads ready as possible before
|
||||
// dropping spinWait, it doesn't have to be perfect.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
// Allow our threads to fight for the lock.
|
||||
spinWait = false;
|
||||
|
||||
// Wait until all of our producer threads have finished.
|
||||
for (auto &thread : producers) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
// Inform consumers that producers are done.
|
||||
mutex.withLockThenNotifyAll(condition, [&] {
|
||||
if (trace)
|
||||
printf("### Informing consumers we are done.\n");
|
||||
doneCondition = true;
|
||||
});
|
||||
|
||||
// Wait for consumers to finish.
|
||||
for (auto &thread : consumers) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -84,7 +84,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT "${SWIFT_STDLIB_THREADING_PACKAGE}" STREQUAL "none")
|
||||
if(NOT "${SWIFT_THREADING_PACKAGE}" STREQUAL "none")
|
||||
list(APPEND PLATFORM_SOURCES Mutex.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ KNOWN_SETTINGS=(
|
||||
swift-stdlib-has-dladdr "1" "whether to build stdlib assuming the runtime environment provides dladdr API"
|
||||
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-stdlib-threading-package "" "which threading package to use for Swift; valid values are empty string (default based on platform), 'pthreads', 'darwin', 'win32', 'c11', 'none'"
|
||||
swift-threading-package "" "which threading package to use for Swift; valid values are empty string (default based on platform), 'pthreads', 'darwin', 'linux', 'win32', 'c11', 'none'"
|
||||
swift-stdlib-single-threaded-concurrency "0" "build Swift concurrency in single-threaded mode"
|
||||
swift-stdlib-concurrency-tracing "" "whether to enable tracing signposts for concurrency; default is 1 on Darwin platforms, 0 otherwise"
|
||||
swift-stdlib-os-versioning "1" "whether to build stdlib with availability based on OS versions (Darwin only)"
|
||||
@@ -2227,18 +2227,18 @@ for host in "${ALL_HOSTS[@]}"; do
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "${SWIFT_STDLIB_THREADING_PACKAGE}" ]] ; then
|
||||
case "${SWIFT_STDLIB_THREADING_PACKAGE}" in
|
||||
"" | pthreads | darwin | win32 | c11 | none) ;;
|
||||
if [[ "${SWIFT_THREADING_PACKAGE}" ]] ; then
|
||||
case "${SWIFT_THREADING_PACKAGE}" in
|
||||
"" | pthreads | darwin | linux | win32 | c11 | none) ;;
|
||||
*)
|
||||
echo "build-script: unknown threading package ${SWIFT_STDLIB_THREADING_PACKAGE}; must be one of 'pthreads', 'darwin', 'win32', 'c11', 'none', or empty for platform default" >&2
|
||||
echo "build-script: unknown threading package ${SWIFT_THREADING_PACKAGE}; must be one of 'pthreads', 'darwin', 'linux', 'win32', 'c11', 'none', or empty for platform default" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
cmake_options=(
|
||||
"${cmake_options[@]}"
|
||||
-DSWIFT_STDLIB_THREADING_PACKAGE:STRING="${SWIFT_STDLIB_THREADING_PACKAGE}"
|
||||
-DSWIFT_THREADING_PACKAGE:STRING="${SWIFT_THREADING_PACKAGE}"
|
||||
)
|
||||
fi
|
||||
|
||||
|
||||
@@ -97,10 +97,10 @@ if "@SWIFT_ENABLE_SOURCEKIT_TESTS@" == "TRUE":
|
||||
if "@SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY@" == "TRUE":
|
||||
config.available_features.add("single_threaded_concurrency")
|
||||
|
||||
if "@SWIFT_STDLIB_THREADING_PACKAGE@" != "none":
|
||||
if "@SWIFT_THREADING_PACKAGE@" != "none":
|
||||
# This is not called "threading" because we might want that later
|
||||
config.available_features.add("thread_safe_runtime")
|
||||
config.available_features.add("threading_@SWIFT_STDLIB_THREADING_PACKAGE@")
|
||||
config.available_features.add("threading_@SWIFT_THREADING_PACKAGE@")
|
||||
|
||||
if "@SWIFT_ENABLE_REFLECTION@" == "TRUE":
|
||||
config.available_features.add("reflection")
|
||||
|
||||
Reference in New Issue
Block a user