diff --git a/Sources/CoreFoundation/CFPlatform.c b/Sources/CoreFoundation/CFPlatform.c index 8112cec632..1dee6cf195 100644 --- a/Sources/CoreFoundation/CFPlatform.c +++ b/Sources/CoreFoundation/CFPlatform.c @@ -1715,43 +1715,37 @@ typedef struct _CFThreadSpecificData { __stdcall #endif static void _CFThreadSpecificDestructor(void *ctx) { -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS #if TARGET_OS_WIN32 _CFThreadSpecificData *data = (_CFThreadSpecificData *)ctx; FlsSetValue(data->key, NULL); swift_release(data->value); free(data); -#else +#elif !TARGET_OS_WASI || defined(_REENTRANT) swift_release(ctx); #endif -#endif } _CFThreadSpecificKey _CFThreadSpecificKeyCreate() { -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS _CFThreadSpecificKey key; #if TARGET_OS_WIN32 key = FlsAlloc(_CFThreadSpecificDestructor); -#else +#elif !TARGET_OS_WASI || defined(_REENTRANT) pthread_key_create(&key, &_CFThreadSpecificDestructor); -#endif - return key; #else - return 0; + key = 0; #endif + return key; } CFTypeRef _Nullable _CFThreadSpecificGet(_CFThreadSpecificKey key) { -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS #if TARGET_OS_WIN32 _CFThreadSpecificData *data = (_CFThreadSpecificData *)FlsGetValue(key); if (data == NULL) { return NULL; } return data->value; -#else +#elif !TARGET_OS_WASI || defined(_REENTRANT) return (CFTypeRef)pthread_getspecific(key); -#endif #else return NULL; #endif @@ -1761,7 +1755,6 @@ void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value) { // Intentionally not calling `swift_release` for previous value. // OperationQueue uses these API (through NSThreadSpecific), and balances // retain count manually. -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS #if TARGET_OS_WIN32 free(FlsGetValue(key)); @@ -1778,7 +1771,7 @@ void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value) { } FlsSetValue(key, data); -#else +#elif !TARGET_OS_WASI || defined(_REENTRANT) if (value != NULL) { swift_retain((void *)value); pthread_setspecific(key, value); @@ -1786,12 +1779,9 @@ void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value) { pthread_setspecific(key, NULL); } #endif -#else -#endif } _CFThreadRef _CFThreadCreate(const _CFThreadAttributes attrs, void *_Nullable (* _Nonnull startfn)(void *_Nullable), void *_CF_RESTRICT _Nullable context) { -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS #if TARGET_OS_WIN32 DWORD dwCreationFlags = 0; DWORD dwStackSize = 0; @@ -1807,18 +1797,16 @@ _CFThreadRef _CFThreadCreate(const _CFThreadAttributes attrs, void *_Nullable (* return (_CFThreadRef)_beginthreadex(NULL, dwStackSize, (_beginthreadex_proc_type)startfn, context, dwCreationFlags, NULL); -#else +#elif !TARGET_OS_WASI || defined(_REENTRANT) _CFThreadRef thread; pthread_create(&thread, &attrs, startfn, context); return thread; -#endif #else return NULL; #endif } CF_CROSS_PLATFORM_EXPORT int _CFThreadSetName(_CFThreadRef thread, const char *_Nonnull name) { -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS #if TARGET_OS_MAC if (pthread_equal(pthread_self(), thread)) { return pthread_setname_np(name); @@ -1848,15 +1836,14 @@ CF_CROSS_PLATFORM_EXPORT int _CFThreadSetName(_CFThreadRef thread, const char *_ #elif TARGET_OS_BSD pthread_set_name_np(thread, name); return 0; -#endif -#else +#elif TARGET_OS_WASI + // No thread naming support in WASI return -1; #endif } // `buf` must be null-terminated CF_CROSS_PLATFORM_EXPORT int _CFThreadGetName(char *buf, int length) { -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS #if TARGET_OS_MAC return pthread_getname_np(pthread_self(), buf, length); #elif TARGET_OS_ANDROID @@ -1902,11 +1889,11 @@ CF_CROSS_PLATFORM_EXPORT int _CFThreadGetName(char *buf, int length) { LocalFree(pszThreadDescription); return 0; -#endif - return -1; -#else +#elif TARGET_OS_WASI + // No thread naming support in WASI return -1; #endif + return -1; } CF_EXPORT char **_CFEnviron(void) { diff --git a/Sources/Foundation/NSLock.swift b/Sources/Foundation/NSLock.swift index 938074d9e5..a154e03cc8 100644 --- a/Sources/Foundation/NSLock.swift +++ b/Sources/Foundation/NSLock.swift @@ -59,7 +59,7 @@ open class NSLock: NSObject, NSLocking, @unchecked Sendable { #endif public override init() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) InitializeSRWLock(mutex) @@ -75,7 +75,7 @@ open class NSLock: NSObject, NSLocking, @unchecked Sendable { } deinit { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) // SRWLocks do not need to be explicitly destroyed @@ -91,7 +91,7 @@ open class NSLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func lock() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) AcquireSRWLockExclusive(mutex) @@ -102,7 +102,7 @@ open class NSLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func unlock() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) ReleaseSRWLockExclusive(mutex) @@ -122,7 +122,7 @@ open class NSLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func `try`() -> Bool { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms return true #elseif os(Windows) @@ -134,7 +134,7 @@ open class NSLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func lock(before limit: Date) -> Bool { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) if TryAcquireSRWLockExclusive(mutex) != 0 { @@ -146,7 +146,7 @@ open class NSLock: NSObject, NSLocking, @unchecked Sendable { } #endif -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms return true #elseif os(macOS) || os(iOS) || os(Windows) @@ -170,7 +170,7 @@ extension NSLock { } } -#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if _runtime(_multithreaded) open class NSConditionLock : NSObject, NSLocking, @unchecked Sendable { internal var _cond = NSCondition() internal var _value: Int @@ -282,7 +282,7 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { public override init() { super.init() -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) InitializeCriticalSection(mutex) @@ -312,7 +312,7 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { } deinit { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) DeleteCriticalSection(mutex) @@ -328,7 +328,7 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func lock() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) EnterCriticalSection(mutex) @@ -339,7 +339,7 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func unlock() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) LeaveCriticalSection(mutex) @@ -359,7 +359,7 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func `try`() -> Bool { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms return true #elseif os(Windows) @@ -371,7 +371,7 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func lock(before limit: Date) -> Bool { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) if TryEnterCriticalSection(mutex) { @@ -383,7 +383,7 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { } #endif -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms return true #elseif os(macOS) || os(iOS) || os(Windows) @@ -404,7 +404,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { internal var cond = _ConditionVariablePointer.allocate(capacity: 1) public override init() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) InitializeSRWLock(mutex) @@ -416,7 +416,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { } deinit { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) // SRWLock do not need to be explicitly destroyed @@ -432,7 +432,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func lock() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) AcquireSRWLockExclusive(mutex) @@ -443,7 +443,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func unlock() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) ReleaseSRWLockExclusive(mutex) @@ -454,7 +454,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func wait() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) SleepConditionVariableSRW(cond, mutex, WinSDK.INFINITE, 0) @@ -465,7 +465,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func wait(until limit: Date) -> Bool { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms return true #elseif os(Windows) @@ -480,7 +480,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { @available(*, noasync, message: "Use async-safe scoped locking instead") open func signal() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) WakeConditionVariable(cond) @@ -490,7 +490,7 @@ open class NSCondition: NSObject, NSLocking, @unchecked Sendable { } open func broadcast() { -#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS +#if !_runtime(_multithreaded) // noop on no thread platforms #elseif os(Windows) WakeAllConditionVariable(cond) diff --git a/Sources/Foundation/Thread.swift b/Sources/Foundation/Thread.swift index ac1aa0eed4..a05534ac69 100644 --- a/Sources/Foundation/Thread.swift +++ b/Sources/Foundation/Thread.swift @@ -7,7 +7,6 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // -#if canImport(Dispatch) @_implementationOnly import CoreFoundation #if os(Windows) import WinSDK @@ -19,6 +18,8 @@ import WinSDK @preconcurrency import Musl #elseif canImport(Bionic) @preconcurrency import Bionic +#elseif canImport(WASILibc) && _runtime(_multithreaded) +import wasi_pthread #endif // WORKAROUND_SR9811 @@ -124,7 +125,11 @@ open class Thread : NSObject { } open class func isMultiThreaded() -> Bool { +#if _runtime(_multithreaded) return true +#else + return false +#endif } @available(*, noasync) @@ -201,13 +206,18 @@ open class Thread : NSObject { #endif } + #if os(WASI) + @available(*, unavailable, message: "exit() is not available on WASI") + #endif @available(*, noasync) open class func exit() { +#if !os(WASI) Thread.current._status = .finished #if os(Windows) ExitThread(0) #else pthread_exit(nil) +#endif #endif } @@ -248,7 +258,9 @@ open class Thread : NSObject { #if !os(Windows) let _ = withUnsafeMutablePointer(to: &_attr) { attr in pthread_attr_init(attr) + #if !os(WASI) // WASI does not support scheduling contention scope pthread_attr_setscope(attr, Int32(PTHREAD_SCOPE_SYSTEM)) + #endif pthread_attr_setdetachstate(attr, Int32(PTHREAD_CREATE_DETACHED)) } #endif @@ -385,7 +397,7 @@ open class Thread : NSObject { let maxSupportedStackDepth = 128; let addrs = UnsafeMutablePointer.allocate(capacity: maxSupportedStackDepth) defer { addrs.deallocate() } -#if os(Android) || os(OpenBSD) || canImport(Musl) +#if os(Android) || os(OpenBSD) || canImport(Musl) || os(WASI) let count = 0 #elseif os(Windows) let count = RtlCaptureStackBackTrace(0, DWORD(maxSupportedStackDepth), @@ -408,7 +420,7 @@ open class Thread : NSObject { } open class var callStackSymbols: [String] { -#if os(Android) || os(OpenBSD) || canImport(Musl) +#if os(Android) || os(OpenBSD) || canImport(Musl) || os(WASI) return [] #elseif os(Windows) let hProcess: HANDLE = GetCurrentProcess() @@ -478,4 +490,3 @@ extension NSNotification.Name { public static let NSDidBecomeSingleThreaded = NSNotification.Name(rawValue: "NSDidBecomeSingleThreadedNotification") public static let NSThreadWillExit = NSNotification.Name(rawValue: "NSThreadWillExitNotification") } -#endif