Skip to content

Commit

Permalink
add FreeBSD support
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-yuji committed Dec 18, 2024
1 parent 1df9545 commit 6753c35
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Sources/Testing/ExitTests/ExitTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ extension ExitTest {
// As with Linux, disable the generation core files. FreeBSD does not, as
// far as I can tell, special-case RLIMIT_CORE=1.
var rl = rlimit(rlim_cur: 0, rlim_max: 0)
_ = setrlimit(CInt(RLIMIT_CORE.rawValue), &rl)
_ = setrlimit(RLIMIT_CORE, &rl)
#elseif os(Windows)
// On Windows, similarly disable Windows Error Reporting and the Windows
// Error Reporting UI. Note we expect to be the first component to call
Expand Down
9 changes: 8 additions & 1 deletion Sources/Testing/ExitTests/SpawnProcess.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,19 @@ func spawnExecutable(
#if SWT_TARGET_OS_APPLE
// Close all other file descriptors open in the parent.
flags |= CShort(POSIX_SPAWN_CLOEXEC_DEFAULT)
#elseif os(Linux) || os(FreeBSD)
#elseif os(Linux)
// This platform doesn't have POSIX_SPAWN_CLOEXEC_DEFAULT, but we can at
// least close all file descriptors higher than the highest inherited one.
// We are assuming here that the caller didn't set FD_CLOEXEC on any of
// these file descriptors.
_ = swt_posix_spawn_file_actions_addclosefrom_np(fileActions, highestFD + 1)
#elseif os(FreeBSD)
// Like Linux, this platfrom doesn't have POSIX_SPAWN_CLOEXEC_DEFAULT;
// However; unlike Linux, all non-EOL FreeBSD (>= 13.1) supports
// `posix_spawn_file_actions_addclosefrom_np` and therefore we don't need
// need `swt_posix_spawn_file_actions_addclosefrom_np` to guard the availability
// of this api.
_ = posix_spawn_file_actions_addclosefrom_np(fileActions, highestFD + 1)
#else
#warning("Platform-specific implementation missing: cannot close unused file descriptors")
#endif
Expand Down
6 changes: 5 additions & 1 deletion Sources/Testing/ExitTests/WaitFor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ private let _childProcessContinuations = Locked<[pid_t: CheckedContinuation<Exit
/// A condition variable used to suspend the waiter thread created by
/// `_createWaitThread()` when there are no child processes to await.
private nonisolated(unsafe) let _waitThreadNoChildrenCondition = {
#if os(FreeBSD)
let result = UnsafeMutablePointer<pthread_cond_t?>.allocate(capacity: 1)
#else
let result = UnsafeMutablePointer<pthread_cond_t>.allocate(capacity: 1)
#endif
_ = pthread_cond_init(result, nil)
return result
}()
Expand Down Expand Up @@ -132,7 +136,7 @@ private let _createWaitThread: Void = {

// Create the thread. It will run immediately; because it runs in an infinite
// loop, we aren't worried about detaching or joining it.
#if SWT_TARGET_OS_APPLE
#if SWT_TARGET_OS_APPLE || os(FreeBSD)
var thread: pthread_t?
#else
var thread = pthread_t()
Expand Down
34 changes: 32 additions & 2 deletions Sources/Testing/Support/Locked.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ struct Locked<T>: 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(FreeBSD) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
private typealias _Lock = pthread_mutex_t
#elseif os(FreeBSD)
private typealias _Lock = pthread_mutex_t?
#elseif os(Windows)
private typealias _Lock = SRWLOCK
#elseif os(WASI)
Expand Down Expand Up @@ -121,7 +123,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
}
}

#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
/// Acquire the lock and invoke a function while it is held, yielding both the
/// protected value and a reference to the lock itself.
///
Expand Down Expand Up @@ -149,6 +151,34 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
}
}
}
#elseif os(FreeBSD)
/// Acquire the lock and invoke a function while it is held, yielding both the
/// protected value and a reference to the lock itself.
///
/// - Parameters:
/// - body: A closure to invoke while the lock is held.
///
/// - Returns: Whatever is returned by `body`.
///
/// - Throws: Whatever is thrown by `body`.
///
/// This function is equivalent to ``withLock(_:)`` except that the closure
/// passed to it also takes a reference to the underlying platform lock. This
/// function can be used when platform-specific functionality such as a
/// `pthread_cond_t` is needed. Because the caller has direct access to the
/// lock and is able to unlock and re-lock it, it is unsafe to modify the
/// protected value.
///
/// - Warning: Callers that unlock the lock _must_ lock it again before the
/// closure returns. If the lock is not acquired when `body` returns, the
/// effect is undefined.
nonmutating func withUnsafeUnderlyingLock<R>(_ body: (UnsafeMutablePointer<pthread_mutex_t?>, T) throws -> R) rethrows -> R {
try withLock { value in
try _storage.withUnsafeMutablePointerToElements { lock in
try body(lock, value)
}
}
}
#endif
}

Expand Down
4 changes: 4 additions & 0 deletions Sources/_TestingInternals/include/Includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
#include <pthread.h>
#endif

#if __has_include(<pthread_np.h>)
#include <pthread_np.h>
#endif

#if __has_include(<pty.h>)
#include <pty.h>
#endif
Expand Down

0 comments on commit 6753c35

Please sign in to comment.