diff --git a/CoreFoundation/Base.subproj/CFInternal.h b/CoreFoundation/Base.subproj/CFInternal.h index b737f30ec7..6f99889099 100644 --- a/CoreFoundation/Base.subproj/CFInternal.h +++ b/CoreFoundation/Base.subproj/CFInternal.h @@ -654,6 +654,37 @@ CF_INLINE int _CFRecursiveMutexUnlock(_CFRecursiveMutex *mutex) { LeaveCriticalSection(mutex); return 0; } +#elif TARGET_OS_WASI +// For wasi-libc without pthread support (_POSIX_THREADS), just assume that it's single-threaded. +// wasi-libc with pthread support is handled by the _POSIX_THREADS case above. +typedef void *_CFMutex; +#define _CF_MUTEX_STATIC_INITIALIZER {} +CF_INLINE int _CFMutexCreate(_CFMutex *lock) { + return 0; +} +CF_INLINE int _CFMutexDestroy(_CFMutex *lock) { + return 0; +} +CF_INLINE int _CFMutexLock(_CFMutex *lock) { + return 0; +} +CF_INLINE int _CFMutexUnlock(_CFMutex *lock) { + return 0; +} + +typedef void *_CFRecursiveMutex; +CF_INLINE int _CFRecursiveMutexCreate(_CFRecursiveMutex *mutex) { + return 0; +} +CF_INLINE int _CFRecursiveMutexDestroy(_CFRecursiveMutex *mutex) { + return 0; +} +CF_INLINE int _CFRecursiveMutexLock(_CFRecursiveMutex *mutex) { + return 0; +} +CF_INLINE int _CFRecursiveMutexUnlock(_CFRecursiveMutex *mutex) { + return 0; +} #else #error "do not know how to define mutex and recursive mutex for this OS" #endif @@ -677,7 +708,7 @@ typedef uint32_t os_unfair_lock_options_t; static void os_unfair_lock_lock(os_unfair_lock_t lock) { pthread_mutex_lock(lock); } static void os_unfair_lock_lock_with_options(os_unfair_lock_t lock, os_unfair_lock_options_t options) { pthread_mutex_lock(lock); } static void os_unfair_lock_unlock(os_unfair_lock_t lock) { pthread_mutex_unlock(lock); } -#elif defined(_WIN32) +#elif defined(_WIN32) || TARGET_OS_WASI #define OS_UNFAIR_LOCK_INIT CFLockInit #define os_unfair_lock CFLock_t #define os_unfair_lock_lock __CFLock diff --git a/CoreFoundation/Base.subproj/CFPlatform.c b/CoreFoundation/Base.subproj/CFPlatform.c index 040e8966f2..bbb3cdba97 100644 --- a/CoreFoundation/Base.subproj/CFPlatform.c +++ b/CoreFoundation/Base.subproj/CFPlatform.c @@ -1628,6 +1628,8 @@ CF_PRIVATE int asprintf(char **ret, const char *format, ...) { extern void swift_retain(void *); extern void swift_release(void *); +#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + #if TARGET_OS_WIN32 typedef struct _CFThreadSpecificData { CFTypeRef value; @@ -1806,6 +1808,7 @@ CF_CROSS_PLATFORM_EXPORT int _CFThreadGetName(char *buf, int length) { #endif return -1; } +#endif // SWIFT_CORELIBS_FOUNDATION_HAS_THREADS CF_EXPORT char **_CFEnviron(void) { #if TARGET_OS_MAC diff --git a/CoreFoundation/Base.subproj/CFRuntime.c b/CoreFoundation/Base.subproj/CFRuntime.c index afdbf5d21e..61e6b29313 100644 --- a/CoreFoundation/Base.subproj/CFRuntime.c +++ b/CoreFoundation/Base.subproj/CFRuntime.c @@ -1194,9 +1194,13 @@ void __CFInitialize(void) { DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &_CFMainPThread, 0, FALSE, DUPLICATE_SAME_ACCESS); -#else +#elif _POSIX_THREADS // move this next line up into the #if above after Foundation gets off this symbol. Also: Stop using _CFMainPThread _CFMainPThread = pthread_self(); +#elif TARGET_OS_WASI + _CFMainPThread = kNilPthreadT; +#else +#error Dont know how to get the main thread on this platform #endif #if TARGET_OS_WIN32 diff --git a/CoreFoundation/Base.subproj/CFUtilities.c b/CoreFoundation/Base.subproj/CFUtilities.c index 7c3fc9f8e7..5b4a25e13d 100644 --- a/CoreFoundation/Base.subproj/CFUtilities.c +++ b/CoreFoundation/Base.subproj/CFUtilities.c @@ -927,8 +927,13 @@ static void _populateBanner(char **banner, char **time, char **thread, int *bann bannerLen = asprintf(banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%lx] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), GetCurrentThreadId()); asprintf(thread, "%lx", GetCurrentThreadId()); #elif TARGET_OS_WASI - bannerLen = asprintf(banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d [%x] ", year, month, day, hour, minute, second, ms, (unsigned int)pthread_self()); - asprintf(thread, "%lx", pthread_self()); + _CFThreadRef tid = 0; + // When pthread API is available from wasi-libc, use it. Otherwise use the dummy value. +# if _POSIX_THREADS + tid = pthread_self(); +# endif + bannerLen = asprintf(banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d [%x] ", year, month, day, hour, minute, second, ms, (unsigned int)tid); + asprintf(thread, "%lx", tid); #else bannerLen = asprintf(banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), (unsigned int)pthread_self()); asprintf(thread, "%lx", pthread_self()); diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h index 642151ab34..80c881be58 100644 --- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h +++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h @@ -412,6 +412,10 @@ typedef unsigned long _CFThreadSpecificKey; typedef pthread_t _CFThreadRef; typedef pthread_attr_t _CFThreadAttributes; typedef pthread_key_t _CFThreadSpecificKey; +#elif TARGET_OS_WASI // WASI without pthreads +typedef void *_CFThreadRef; +typedef void *_CFThreadAttributes; +typedef void *_CFThreadSpecificKey; #endif CF_CROSS_PLATFORM_EXPORT Boolean _CFIsMainThread(void); @@ -423,6 +427,7 @@ CF_EXPORT CFHashCode __CFHashDouble(double d); CF_CROSS_PLATFORM_EXPORT void CFSortIndexes(CFIndex *indexBuffer, CFIndex count, CFOptionFlags opts, CFComparisonResult (^cmp)(CFIndex, CFIndex)); #endif +#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS CF_EXPORT CFTypeRef _Nullable _CFThreadSpecificGet(_CFThreadSpecificKey key); CF_EXPORT void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value); CF_EXPORT _CFThreadSpecificKey _CFThreadSpecificKeyCreate(void); @@ -431,6 +436,7 @@ CF_EXPORT _CFThreadRef _CFThreadCreate(const _CFThreadAttributes attrs, void *_N CF_CROSS_PLATFORM_EXPORT int _CFThreadSetName(_CFThreadRef thread, const char *_Nonnull name); CF_CROSS_PLATFORM_EXPORT int _CFThreadGetName(char *_Nonnull buf, int length); +#endif CF_EXPORT Boolean _CFCharacterSetIsLongCharacterMember(CFCharacterSetRef theSet, UTF32Char theChar); CF_EXPORT CFCharacterSetRef _CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet); diff --git a/CoreFoundation/CMakeLists.txt b/CoreFoundation/CMakeLists.txt index beb48d6c86..31175fda5a 100644 --- a/CoreFoundation/CMakeLists.txt +++ b/CoreFoundation/CMakeLists.txt @@ -99,6 +99,10 @@ else() add_compile_definitions($<$:DEPLOYMENT_RUNTIME_C>) endif() +if(Threads_FOUND) + add_compile_definitions($<$:SWIFT_CORELIBS_FOUNDATION_HAS_THREADS>) +endif() + # TODO(compnerd) ensure that the compiler supports the warning flag add_compile_options($<$:-Wno-shorten-64-to-32>) add_compile_options($<$:-Wno-deprecated-declarations>) diff --git a/Sources/Foundation/CMakeLists.txt b/Sources/Foundation/CMakeLists.txt index fc093ce0c8..f3cc6bf252 100644 --- a/Sources/Foundation/CMakeLists.txt +++ b/Sources/Foundation/CMakeLists.txt @@ -150,6 +150,13 @@ add_library(Foundation WinSDK+Extensions.swift) target_compile_definitions(Foundation PRIVATE DEPLOYMENT_RUNTIME_SWIFT) +if(Threads_FOUND) + target_compile_definitions(Foundation PRIVATE + SWIFT_CORELIBS_FOUNDATION_HAS_THREADS) + target_compile_options(Foundation PRIVATE + "SHELL:-Xcc -DSWIFT_CORELIBS_FOUNDATION_HAS_THREADS") +endif() + target_compile_options(Foundation PUBLIC $<$:-enable-testing> "SHELL:-Xfrontend -disable-autolink-framework -Xfrontend CoreFoundation" diff --git a/Sources/Foundation/NSLock.swift b/Sources/Foundation/NSLock.swift index f4384b70ac..0513bfd96e 100644 --- a/Sources/Foundation/NSLock.swift +++ b/Sources/Foundation/NSLock.swift @@ -57,7 +57,9 @@ open class NSLock: NSObject, NSLocking { #endif public override init() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) InitializeSRWLock(mutex) InitializeConditionVariable(timeoutCond) InitializeSRWLock(timeoutMutex) @@ -71,7 +73,9 @@ open class NSLock: NSObject, NSLocking { } deinit { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) // SRWLocks do not need to be explicitly destroyed #else pthread_mutex_destroy(mutex) @@ -84,7 +88,9 @@ open class NSLock: NSObject, NSLocking { } open func lock() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) AcquireSRWLockExclusive(mutex) #else pthread_mutex_lock(mutex) @@ -92,7 +98,9 @@ open class NSLock: NSObject, NSLocking { } open func unlock() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) ReleaseSRWLockExclusive(mutex) AcquireSRWLockExclusive(timeoutMutex) WakeAllConditionVariable(timeoutCond) @@ -109,7 +117,10 @@ open class NSLock: NSObject, NSLocking { } open func `try`() -> Bool { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms + return true +#elseif os(Windows) return TryAcquireSRWLockExclusive(mutex) != 0 #else return pthread_mutex_trylock(mutex) == 0 @@ -117,7 +128,9 @@ open class NSLock: NSObject, NSLocking { } open func lock(before limit: Date) -> Bool { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) if TryAcquireSRWLockExclusive(mutex) != 0 { return true } @@ -127,17 +140,16 @@ open class NSLock: NSObject, NSLocking { } #endif -#if os(macOS) || os(iOS) || os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms + return true +#elseif os(macOS) || os(iOS) || os(Windows) return timedLock(mutex: mutex, endTime: limit, using: timeoutCond, with: timeoutMutex) #else guard var endTime = timeSpecFrom(date: limit) else { return false } -#if os(WASI) - return true -#else return pthread_mutex_timedlock(mutex, &endTime) == 0 -#endif #endif } @@ -152,7 +164,7 @@ extension NSLock { } } -#if !os(WASI) +#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS open class NSConditionLock : NSObject, NSLocking { internal var _cond = NSCondition() internal var _value: Int @@ -256,7 +268,9 @@ open class NSRecursiveLock: NSObject, NSLocking { public override init() { super.init() -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) InitializeCriticalSection(mutex) InitializeConditionVariable(timeoutCond) InitializeSRWLock(timeoutMutex) @@ -284,7 +298,9 @@ open class NSRecursiveLock: NSObject, NSLocking { } deinit { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) DeleteCriticalSection(mutex) #else pthread_mutex_destroy(mutex) @@ -297,7 +313,9 @@ open class NSRecursiveLock: NSObject, NSLocking { } open func lock() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) EnterCriticalSection(mutex) #else pthread_mutex_lock(mutex) @@ -305,7 +323,9 @@ open class NSRecursiveLock: NSObject, NSLocking { } open func unlock() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) LeaveCriticalSection(mutex) AcquireSRWLockExclusive(timeoutMutex) WakeAllConditionVariable(timeoutCond) @@ -322,7 +342,10 @@ open class NSRecursiveLock: NSObject, NSLocking { } open func `try`() -> Bool { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms + return true +#elseif os(Windows) return TryEnterCriticalSection(mutex) #else return pthread_mutex_trylock(mutex) == 0 @@ -330,7 +353,9 @@ open class NSRecursiveLock: NSObject, NSLocking { } open func lock(before limit: Date) -> Bool { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) if TryEnterCriticalSection(mutex) { return true } @@ -340,17 +365,16 @@ open class NSRecursiveLock: NSObject, NSLocking { } #endif -#if os(macOS) || os(iOS) || os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms + return true +#elseif os(macOS) || os(iOS) || os(Windows) return timedLock(mutex: mutex, endTime: limit, using: timeoutCond, with: timeoutMutex) #else guard var endTime = timeSpecFrom(date: limit) else { return false } -#if os(WASI) - return true -#else return pthread_mutex_timedlock(mutex, &endTime) == 0 -#endif #endif } @@ -362,7 +386,9 @@ open class NSCondition: NSObject, NSLocking { internal var cond = _ConditionVariablePointer.allocate(capacity: 1) public override init() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) InitializeSRWLock(mutex) InitializeConditionVariable(cond) #else @@ -372,7 +398,9 @@ open class NSCondition: NSObject, NSLocking { } deinit { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) // SRWLock do not need to be explicitly destroyed #else pthread_mutex_destroy(mutex) @@ -385,7 +413,9 @@ open class NSCondition: NSObject, NSLocking { } open func lock() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) AcquireSRWLockExclusive(mutex) #else pthread_mutex_lock(mutex) @@ -393,7 +423,9 @@ open class NSCondition: NSObject, NSLocking { } open func unlock() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) ReleaseSRWLockExclusive(mutex) #else pthread_mutex_unlock(mutex) @@ -401,7 +433,9 @@ open class NSCondition: NSObject, NSLocking { } open func wait() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) SleepConditionVariableSRW(cond, mutex, WinSDK.INFINITE, 0) #else pthread_cond_wait(cond, mutex) @@ -409,7 +443,10 @@ open class NSCondition: NSObject, NSLocking { } open func wait(until limit: Date) -> Bool { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms + return true +#elseif os(Windows) return SleepConditionVariableSRW(cond, mutex, timeoutFrom(date: limit), 0) #else guard var timeout = timeSpecFrom(date: limit) else { @@ -420,7 +457,9 @@ open class NSCondition: NSObject, NSLocking { } open func signal() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) WakeConditionVariable(cond) #else pthread_cond_signal(cond) @@ -428,7 +467,9 @@ open class NSCondition: NSObject, NSLocking { } open func broadcast() { -#if os(Windows) +#if !SWIFT_CORELIBS_FOUNDATION_HAS_THREADS + // noop on no thread platforms +#elseif os(Windows) WakeAllConditionVariable(cond) #else pthread_cond_broadcast(cond)