From 69367817ae1a3ac5ddef5cb1a3102c447c75f9e9 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Sun, 31 Mar 2024 10:15:11 -0400 Subject: [PATCH 1/3] Enable `pthread_mutex_t` use on WASI with a multithreaded runtime. This PR opts WASI builds into using `pthread_mutex_t` in `Locked` when the WASI environment supports threading. `_runtime(_multithreaded)` was added very recently with https://github.com/apple/swift/pull/72649, so we need an additional compiler version check before testing the runtime flag. WASI with Swift 5.10, as well as WASI without threading, will continue to stub out `Locked`. --- Sources/Testing/Support/Locked.swift | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/Sources/Testing/Support/Locked.swift b/Sources/Testing/Support/Locked.swift index 05bef558a..225996b54 100644 --- a/Sources/Testing/Support/Locked.swift +++ b/Sources/Testing/Support/Locked.swift @@ -36,12 +36,12 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { /// To keep the implementation of this type as simple as possible, /// `pthread_mutex_t` is used on Apple platforms instead of `os_unfair_lock` /// or `OSAllocatedUnfairLock`. -#if SWT_TARGET_OS_APPLE || os(Linux) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) private typealias _Lock = pthread_mutex_t #elseif os(Windows) private typealias _Lock = SRWLOCK #elseif os(WASI) - // No locks on WASI. + // No locks on WASI without multithreaded runtime. #else #warning("Platform-specific implementation missing: locking unavailable") private typealias _Lock = Void @@ -51,12 +51,12 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { private final class _Storage: ManagedBuffer { deinit { withUnsafeMutablePointerToElements { lock in -#if SWT_TARGET_OS_APPLE || os(Linux) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) _ = pthread_mutex_destroy(lock) #elseif os(Windows) // No deinitialization needed. #elseif os(WASI) - // No locks on WASI. + // No locks on WASI without multithreaded runtime. #else #warning("Platform-specific implementation missing: locking unavailable") #endif @@ -70,12 +70,12 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { init(rawValue: T) { let storage = _Storage.create(minimumCapacity: 1, makingHeaderWith: { _ in rawValue }) storage.withUnsafeMutablePointerToElements { lock in -#if SWT_TARGET_OS_APPLE || os(Linux) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) _ = pthread_mutex_init(lock, nil) #elseif os(Windows) InitializeSRWLock(lock) #elseif os(WASI) - // No locks on WASI. + // No locks on WASI without multithreaded runtime. #else #warning("Platform-specific implementation missing: locking unavailable") #endif @@ -101,7 +101,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { /// concurrency tools. nonmutating func withLock(_ body: (inout T) throws -> R) rethrows -> R { try _storage.rawValue.withUnsafeMutablePointers { rawValue, lock in -#if SWT_TARGET_OS_APPLE || os(Linux) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) _ = pthread_mutex_lock(lock) defer { _ = pthread_mutex_unlock(lock) @@ -112,7 +112,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { ReleaseSRWLockExclusive(lock) } #elseif os(WASI) - // No locks on WASI. + // No locks on WASI without multithreaded runtime. #else #warning("Platform-specific implementation missing: locking unavailable") #endif @@ -150,11 +150,6 @@ extension Locked where T: Numeric { } extension Locked { - /// Initialize an instance of this type with a raw value of `0`. - init() where T: AdditiveArithmetic { - self.init(rawValue: .zero) - } - /// Initialize an instance of this type with a raw value of `nil`. init() where T == V? { self.init(rawValue: nil) From e18f6cbb93eafc9c25b84a4bee623689ed267724 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Sun, 31 Mar 2024 10:26:12 -0400 Subject: [PATCH 2/3] The new runtime condition hasn't been cherry-picked to release/6.0, so assume it will be available in Swift 6.1 instead. --- Sources/Testing/Support/Locked.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Testing/Support/Locked.swift b/Sources/Testing/Support/Locked.swift index 225996b54..ab150f9de 100644 --- a/Sources/Testing/Support/Locked.swift +++ b/Sources/Testing/Support/Locked.swift @@ -36,7 +36,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { /// To keep the implementation of this type as simple as possible, /// `pthread_mutex_t` is used on Apple platforms instead of `os_unfair_lock` /// or `OSAllocatedUnfairLock`. -#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) private typealias _Lock = pthread_mutex_t #elseif os(Windows) private typealias _Lock = SRWLOCK @@ -51,7 +51,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { private final class _Storage: ManagedBuffer { deinit { withUnsafeMutablePointerToElements { lock in -#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) _ = pthread_mutex_destroy(lock) #elseif os(Windows) // No deinitialization needed. @@ -70,7 +70,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { init(rawValue: T) { let storage = _Storage.create(minimumCapacity: 1, makingHeaderWith: { _ in rawValue }) storage.withUnsafeMutablePointerToElements { lock in -#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) _ = pthread_mutex_init(lock, nil) #elseif os(Windows) InitializeSRWLock(lock) @@ -101,7 +101,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { /// concurrency tools. nonmutating func withLock(_ body: (inout T) throws -> R) rethrows -> R { try _storage.rawValue.withUnsafeMutablePointers { rawValue, lock in -#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.0) && _runtime(_multithreaded)) +#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) _ = pthread_mutex_lock(lock) defer { _ = pthread_mutex_unlock(lock) From ea23bc554a940b746702bcf35253ec1e168fc575 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Sun, 31 Mar 2024 10:28:19 -0400 Subject: [PATCH 3/3] Tab -> spaces --- Sources/Testing/Support/Locked.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Testing/Support/Locked.swift b/Sources/Testing/Support/Locked.swift index ab150f9de..f8dd603b8 100644 --- a/Sources/Testing/Support/Locked.swift +++ b/Sources/Testing/Support/Locked.swift @@ -41,7 +41,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { #elseif os(Windows) private typealias _Lock = SRWLOCK #elseif os(WASI) - // No locks on WASI without multithreaded runtime. + // No locks on WASI without multithreaded runtime. #else #warning("Platform-specific implementation missing: locking unavailable") private typealias _Lock = Void