[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:
Alastair Houghton
2022-04-15 13:50:33 +01:00
parent 66b9d21000
commit f5bdb858e0
98 changed files with 2286 additions and 1410 deletions

View File

@@ -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}")

View File

@@ -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>)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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
View 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

View 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
View 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

View 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

View 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
View 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

View File

@@ -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")

View File

@@ -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)")

View File

@@ -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()

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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"

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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 --------------------------------------------------------------------

View File

@@ -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)

View File

@@ -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,

View File

@@ -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

View 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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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};

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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);

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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());

View File

@@ -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
}

View File

@@ -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];

View File

@@ -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));

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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})

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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 += ' '

View File

@@ -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")

View File

@@ -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);
}

View 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

View File

@@ -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()

View File

@@ -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

View File

@@ -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")