New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for WASILibc #2671
base: main
Are you sure you want to change the base?
Add support for WASILibc #2671
Changes from all commits
70ff245
66e3f0e
9170712
1958d91
4cfee57
e5ccda5
9fe470a
85f140e
4ee91c6
fdd622f
b1b5d7f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
#if __wasi__ | ||
|
||
#include <fcntl.h> | ||
#include <time.h> | ||
|
||
static inline void CNIOWASI_gettime(struct timespec *tv) { | ||
// ClangImporter doesn't support `CLOCK_MONOTONIC` declaration in WASILibc, thus we have to define a bridge manually | ||
clock_gettime(CLOCK_MONOTONIC, tv); | ||
} | ||
|
||
static inline int CNIOWASI_O_CREAT() { | ||
// ClangImporter doesn't support `O_CREATE` declaration in WASILibc, thus we have to define a bridge manually | ||
return O_CREAT; | ||
} | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,8 @@ import WinSDK | |
import Glibc | ||
#elseif canImport(Musl) | ||
import Musl | ||
#elseif canImport(WASILibc) | ||
import WASILibc | ||
#else | ||
#error("The concurrency lock module was unable to identify your C library.") | ||
#endif | ||
|
@@ -45,7 +47,7 @@ public final class Lock { | |
public init() { | ||
#if os(Windows) | ||
InitializeSRWLock(self.mutex) | ||
#else | ||
#elseif !os(WASI) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we can merge a PR that silently disables these primitives on WASI without being extremely confident that we'll never need them. Is there any way we can replace this with a feature-detection on threading? |
||
var attr = pthread_mutexattr_t() | ||
pthread_mutexattr_init(&attr) | ||
debugOnly { | ||
|
@@ -60,7 +62,7 @@ public final class Lock { | |
deinit { | ||
#if os(Windows) | ||
// SRWLOCK does not need to be free'd | ||
#else | ||
#elseif !os(WASI) | ||
let err = pthread_mutex_destroy(self.mutex) | ||
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") | ||
#endif | ||
|
@@ -74,7 +76,7 @@ public final class Lock { | |
public func lock() { | ||
#if os(Windows) | ||
AcquireSRWLockExclusive(self.mutex) | ||
#else | ||
#elseif !os(WASI) | ||
let err = pthread_mutex_lock(self.mutex) | ||
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") | ||
#endif | ||
|
@@ -87,7 +89,7 @@ public final class Lock { | |
public func unlock() { | ||
#if os(Windows) | ||
ReleaseSRWLockExclusive(self.mutex) | ||
#else | ||
#elseif !os(WASI) | ||
let err = pthread_mutex_unlock(self.mutex) | ||
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") | ||
#endif | ||
|
@@ -127,7 +129,7 @@ public final class ConditionLock<T: Equatable> { | |
#if os(Windows) | ||
private let cond: UnsafeMutablePointer<CONDITION_VARIABLE> = | ||
UnsafeMutablePointer.allocate(capacity: 1) | ||
#else | ||
#elseif !os(WASI) | ||
private let cond: UnsafeMutablePointer<pthread_cond_t> = | ||
UnsafeMutablePointer.allocate(capacity: 1) | ||
#endif | ||
|
@@ -140,7 +142,7 @@ public final class ConditionLock<T: Equatable> { | |
self.mutex = NIOLock() | ||
#if os(Windows) | ||
InitializeConditionVariable(self.cond) | ||
#else | ||
#elseif !os(WASI) | ||
let err = pthread_cond_init(self.cond, nil) | ||
precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") | ||
#endif | ||
|
@@ -149,11 +151,13 @@ public final class ConditionLock<T: Equatable> { | |
deinit { | ||
#if os(Windows) | ||
// condition variables do not need to be explicitly destroyed | ||
#else | ||
#elseif !os(WASI) | ||
let err = pthread_cond_destroy(self.cond) | ||
precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") | ||
#endif | ||
#if !os(WASI) | ||
self.cond.deallocate() | ||
#endif | ||
} | ||
|
||
/// Acquire the lock, regardless of the value of the state variable. | ||
|
@@ -193,7 +197,7 @@ public final class ConditionLock<T: Equatable> { | |
#if os(Windows) | ||
let result = SleepConditionVariableSRW(self.cond, mutex, INFINITE, 0) | ||
precondition(result, "\(#function) failed in SleepConditionVariableSRW with error \(GetLastError())") | ||
#else | ||
#elseif !os(WASI) | ||
let err = pthread_cond_wait(self.cond, mutex) | ||
precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") | ||
#endif | ||
|
@@ -235,6 +239,8 @@ public final class ConditionLock<T: Equatable> { | |
// NOTE: this may be a spurious wakeup, adjust the timeout accordingly | ||
dwMilliseconds = dwMilliseconds - (timeGetTime() - dwWaitStart) | ||
} | ||
#elseif os(WASI) | ||
return true | ||
#else | ||
let nsecPerSec: Int64 = 1000000000 | ||
self.lock() | ||
|
@@ -277,7 +283,7 @@ public final class ConditionLock<T: Equatable> { | |
self.unlock() | ||
#if os(Windows) | ||
WakeAllConditionVariable(self.cond) | ||
#else | ||
#elseif !os(WASI) | ||
let err = pthread_cond_broadcast(self.cond) | ||
precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") | ||
#endif | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,11 @@ private let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>?, UnsafeMut | |
#elseif canImport(Darwin) | ||
import Darwin | ||
|
||
private let sysInet_ntop: @convention(c) (CInt, UnsafeRawPointer?, UnsafeMutablePointer<CChar>?, socklen_t) -> UnsafePointer<CChar>? = inet_ntop | ||
private let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> CInt = inet_pton | ||
#elseif canImport(WASILibc) | ||
import WASILibc | ||
|
||
private let sysInet_ntop: @convention(c) (CInt, UnsafeRawPointer?, UnsafeMutablePointer<CChar>?, socklen_t) -> UnsafePointer<CChar>? = inet_ntop | ||
private let sysInet_pton: @convention(c) (CInt, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> CInt = inet_pton | ||
#else | ||
|
@@ -199,12 +204,14 @@ extension NIOBSDSocket.ProtocolFamily { | |
public static let inet6: NIOBSDSocket.ProtocolFamily = | ||
NIOBSDSocket.ProtocolFamily(rawValue: PF_INET6) | ||
|
||
#if !os(WASI) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My general preference here would be that the APIs here are present, they just end up failing when actually used in WASI. That would mean hardcoding the syscall value on WASI, or deliberately using a spoiler value. That note applies to the rest of this file. |
||
/// UNIX local to the host. | ||
public static let unix: NIOBSDSocket.ProtocolFamily = | ||
NIOBSDSocket.ProtocolFamily(rawValue: PF_UNIX) | ||
#endif | ||
} | ||
|
||
#if !os(Windows) | ||
#if !os(Windows) && !os(WASI) | ||
extension NIOBSDSocket.ProtocolFamily { | ||
/// UNIX local to the host, alias for `PF_UNIX` (`.unix`) | ||
public static let local: NIOBSDSocket.ProtocolFamily = | ||
|
@@ -370,6 +377,7 @@ extension NIOBSDSocket.Option { | |
public static let mptcp_info = NIOBSDSocket.Option(rawValue: 1) | ||
} | ||
|
||
#if !os(WASI) | ||
// Socket Options | ||
extension NIOBSDSocket.Option { | ||
/// Get the error status and clear. | ||
|
@@ -396,8 +404,9 @@ extension NIOBSDSocket.Option { | |
public static let so_reuseaddr: NIOBSDSocket.Option = | ||
NIOBSDSocket.Option(rawValue: SO_REUSEADDR) | ||
} | ||
#endif | ||
|
||
#if !os(Windows) | ||
#if !os(Windows) && !os(WASI) | ||
extension NIOBSDSocket.Option { | ||
/// Indicate when to generate timestamps. | ||
public static let so_timestamp: NIOBSDSocket.Option = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition should probably be persisted across almost any library target that depends on
NIO
which also depends onNIOCore
._NIOConcurrency
,NIOFoundationCompat
,NIOWebSocket
,NIOTLS
appear to be the other places.