From 3bb369cd91b35de9bafdd481e562e5996abc85c6 Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Sat, 21 Jun 2025 10:24:55 -0400 Subject: [PATCH] Use libpthread primitives for OpenBSD mutexes. There has been some discussion as to whether this is the right approach, centered around internal pointers in the underlying mutex structure. After much thought, let's commit this for now. The argument: * While it is true that OpenBSD has futex(2) and in fact is used in the underlying implementations in Dispatch. I'm not confident right now creating robust locking primitives by hand from futexes. It would be ideal to just delegate all of this to Dispatch, but Dispatch doesn't expose a ready-use API for mutexes. Cobbling one together might be possible, but that would take some time and finesse. * While recent versions of C and C++ have language support for mutexes, they are implemented in many cases by libpthread anyway, so there is nothing inherently gained right now by not using the pthread API other than portability. * While the concern for internal pointers for the pthread API is important, the OpenBSD is mitigated by the fact that pthread_mutex_t is pointer-valued on the platform. The concern that this might not always be the case is mitigated by the fact that this commit does not attempt to use the pthread implementation as a catch-all for all platforms. * The alternative is to use MutexUnavailable, but given Foundation has some dependencies on Mutex, this may cause problems elsewhere throughout the port. --- stdlib/public/Synchronization/CMakeLists.txt | 11 ++++ .../Synchronization/Mutex/OpenBSDImpl.swift | 58 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 stdlib/public/Synchronization/Mutex/OpenBSDImpl.swift diff --git a/stdlib/public/Synchronization/CMakeLists.txt b/stdlib/public/Synchronization/CMakeLists.txt index df593d4933e7d..357aef5546974 100644 --- a/stdlib/public/Synchronization/CMakeLists.txt +++ b/stdlib/public/Synchronization/CMakeLists.txt @@ -80,6 +80,13 @@ set(SWIFT_SYNCHRONIZATION_WINDOWS_SOURCES Mutex/WindowsImpl.swift ) +# OpenBSD sources + +set(SWIFT_SYNCHRONIZATION_OPENBSD_SOURCES + Mutex/Mutex.swift + Mutex/OpenBSDImpl.swift +) + set(SWIFT_SYNCHRNOIZATION_SWIFT_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} "-enable-builtin-module" @@ -115,6 +122,8 @@ add_swift_target_library(swiftSynchronization ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES ${SWIFT_SYNCHRONIZATION_WINDOWS_SOURCES} SWIFT_SOURCES_DEPENDS_FREEBSD ${SWIFT_SYNCHRONIZATION_FREEBSD_SOURCES} + SWIFT_SOURCES_DEPENDS_OPENBSD + ${SWIFT_SYNCHRONIZATION_OPENBSD_SOURCES} SWIFT_SOURCES_DEPENDS_FREESTANDING Mutex/MutexUnavailable.swift @@ -140,6 +149,8 @@ add_swift_target_library(swiftSynchronization ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES WinSDK SWIFT_MODULE_DEPENDS_FREEBSD Glibc + SWIFT_MODULE_DEPENDS_OPENBSD + Glibc SWIFT_COMPILE_FLAGS ${SWIFT_SYNCHRNOIZATION_SWIFT_FLAGS} diff --git a/stdlib/public/Synchronization/Mutex/OpenBSDImpl.swift b/stdlib/public/Synchronization/Mutex/OpenBSDImpl.swift new file mode 100644 index 0000000000000..ad4de24cf28b6 --- /dev/null +++ b/stdlib/public/Synchronization/Mutex/OpenBSDImpl.swift @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Atomics open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import Glibc + +@available(SwiftStdlib 6.0, *) +@frozen +@_staticExclusiveOnly +public struct _MutexHandle: ~Copyable { + @usableFromInline + let value: _Cell + + @available(SwiftStdlib 6.0, *) + @_alwaysEmitIntoClient + @_transparent + public init() { + var mx = pthread_mutex_t(bitPattern: 0) + pthread_mutex_init(&mx, nil) + value = _Cell(mx) + } + + @available(SwiftStdlib 6.0, *) + @_alwaysEmitIntoClient + @_transparent + internal borrowing func _lock() { + pthread_mutex_lock(value._address) + } + + @available(SwiftStdlib 6.0, *) + @_alwaysEmitIntoClient + @_transparent + internal borrowing func _tryLock() -> Bool { + pthread_mutex_trylock(value._address) != 0 + } + + @available(SwiftStdlib 6.0, *) + @_alwaysEmitIntoClient + @_transparent + internal borrowing func _unlock() { + pthread_mutex_unlock(value._address) + } + + @available(SwiftStdlib 6.0, *) + @_alwaysEmitIntoClient + @_transparent + deinit { + pthread_mutex_destroy(value._address) + } +}