From 8e971b78d7fa17d688abc229a730b85b0f5d8837 Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Wed, 12 Nov 2025 21:16:22 +0530 Subject: [PATCH 1/8] [libc] Add Darwin mutex support via os_sync primitives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch implements the generic mutex and raw_mutex interfaces on macOS. A new Futex class is provided that relies on os_sync_wait and os_sync_wake to emulate futex‑like wait and wake semantics. The OS‑specific part is moved into futex_utils, which now contains the Darwin implementation. --- libc/src/__support/threads/CMakeLists.txt | 29 +++- .../__support/threads/darwin/CMakeLists.txt | 16 +++ .../__support/threads/darwin/futex_utils.h | 66 +++++++++ libc/src/__support/threads/darwin/mutex.h | 131 ++++++++++++++++++ libc/src/__support/threads/mutex.h | 6 + .../__support/threads/{linux => }/raw_mutex.h | 24 ++-- .../threads/{linux/mutex.h => unix_mutex.h} | 9 +- 7 files changed, 265 insertions(+), 16 deletions(-) create mode 100644 libc/src/__support/threads/darwin/CMakeLists.txt create mode 100644 libc/src/__support/threads/darwin/futex_utils.h create mode 100644 libc/src/__support/threads/darwin/mutex.h rename libc/src/__support/threads/{linux => }/raw_mutex.h (89%) rename libc/src/__support/threads/{linux/mutex.h => unix_mutex.h} (90%) diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt index f8a44937721b4..b2abf19c53a50 100644 --- a/libc/src/__support/threads/CMakeLists.txt +++ b/libc/src/__support/threads/CMakeLists.txt @@ -23,13 +23,36 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) add_subdirectory(${LIBC_TARGET_OS}) endif() -if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.mutex) +if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.futex_utils) add_header_library( mutex HDRS - mutex.h + mutex.h + DEPENDS + .unix_mutex + ) + add_header_library( + unix_mutex + HDRS + unix_mutex.h + DEPENDS + .raw_mutex + ) + + add_header_library( + raw_mutex + HDRS + raw_mutex.h DEPENDS - .${LIBC_TARGET_OS}.mutex + .${LIBC_TARGET_OS}.futex_utils + libc.src.__support.threads.sleep + libc.src.__support.time.abs_timeout + libc.src.__support.time.monotonicity + libc.src.__support.CPP.optional + libc.hdr.types.pid_t + COMPILE_OPTIONS + -DLIBC_COPT_RAW_MUTEX_DEFAULT_SPIN_COUNT=${LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT} + ${monotonicity_flags} ) add_object_library( diff --git a/libc/src/__support/threads/darwin/CMakeLists.txt b/libc/src/__support/threads/darwin/CMakeLists.txt new file mode 100644 index 0000000000000..9c651d8c3b0f5 --- /dev/null +++ b/libc/src/__support/threads/darwin/CMakeLists.txt @@ -0,0 +1,16 @@ +if(NOT TARGET libc.src.__support.OSUtil.osutil) + return() +endif() + +add_header_library( + futex_utils + HDRS + futex_utils.h + DEPENDS + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.__support.CPP.atomic + libc.src.__support.CPP.limits + libc.src.__support.CPP.optional + libc.src.__support.threads.mutex_common +) diff --git a/libc/src/__support/threads/darwin/futex_utils.h b/libc/src/__support/threads/darwin/futex_utils.h new file mode 100644 index 0000000000000..180083b7b2c68 --- /dev/null +++ b/libc/src/__support/threads/darwin/futex_utils.h @@ -0,0 +1,66 @@ +//===--- Futex utils for Darwin -----------------------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H +#define LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H + +#include "src/__support/CPP/atomic.h" +#include "src/__support/CPP/optional.h" +#include "src/__support/time/abs_timeout.h" +#include "src/__support/time/clock_conversion.h" + +#include + +namespace LIBC_NAMESPACE_DECL { + +using FutexWordType = uint32_t; + +struct Futex : public cpp::Atomic { + using cpp::Atomic::Atomic; + using Timeout = internal::AbsTimeout; + + // The Darwin futex API does not return a value on timeout, so we have to + // check for it manually. This means we can't use the return value to + // distinguish between a timeout and a successful wake-up. + int wait(FutexWordType val, cpp::optional timeout, bool) { + if (timeout) { + struct timespec now; + clock_gettime(timeout->is_realtime() ? CLOCK_REALTIME : CLOCK_MONOTONIC, + &now); + const timespec &target_ts = timeout->get_timespec(); + + if (now.tv_sec > target_ts.tv_sec || + (now.tv_sec == target_ts.tv_sec && now.tv_nsec >= target_ts.tv_nsec)) + return ETIMEDOUT; + } + + os_sync_wait_on_address(reinterpret_cast(this), + static_cast(val), sizeof(FutexWordType), + OS_SYNC_WAIT_ON_ADDRESS_NONE); + return 0; + } + + void notify_one(bool) { + os_sync_wake_by_address_any(reinterpret_cast(this), + sizeof(FutexWordType), + OS_SYNC_WAKE_BY_ADDRESS_NONE); + } + + void notify_all(bool) { + // os_sync_wake_by_address_all is not available, so we use notify_one. + // This is not ideal, but it's the best we can do with the available API. + os_sync_wake_by_address_any(reinterpret_cast(this), + sizeof(FutexWordType), + OS_SYNC_WAKE_BY_ADDRESS_NONE); + } +}; + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H diff --git a/libc/src/__support/threads/darwin/mutex.h b/libc/src/__support/threads/darwin/mutex.h new file mode 100644 index 0000000000000..44ba14cc986a2 --- /dev/null +++ b/libc/src/__support/threads/darwin/mutex.h @@ -0,0 +1,131 @@ +//===--- Implementation of a Darwin mutex class -----------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H +#define LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H + +#include "src/__support/libc_assert.h" +#include "src/__support/macros/config.h" +#include "src/__support/threads/mutex_common.h" +#include "src/__support/threads/sleep.h" // For sleep_briefly +#include "src/__support/time/abs_timeout.h" + +#include // For mach_thread_self +#include // For mach_port_t and MACH_PORT_NULL +#include // For os_unfair_lock +#include // For clock_gettime + +namespace LIBC_NAMESPACE_DECL { + +// This file is an implementation of `LIBC_NAMESPACE::mutex` for Darwin-based +// platforms. It is a wrapper around `os_unfair_lock`, which is a low-level, +// high-performance locking primitive provided by the kernel. +// +// `os_unfair_lock` is a non-recursive, thread-owned lock that blocks waiters +// efficiently in the kernel. As the name implies, it is "unfair," meaning +// it does not guarantee the order in which waiting threads acquire the lock. +// This trade-off allows for higher performance in contended scenarios. +// +// The lock must be unlocked from the same thread that locked it. Attempting +// to unlock from a different thread will result in a runtime error. +// +// This implementation is suitable for simple critical sections where fairness +// and reentrancy are not concerns. + +class Mutex final { + os_unfair_lock_s lock_val = OS_UNFAIR_LOCK_INIT; + mach_port_t owner = MACH_PORT_NULL; + + // API compatibility fields. + unsigned char timed; + unsigned char recursive; + unsigned char robust; + unsigned char pshared; + +public: + LIBC_INLINE constexpr Mutex(bool is_timed, bool is_recursive, bool is_robust, + bool is_pshared) + : owner(MACH_PORT_NULL), timed(is_timed), recursive(is_recursive), + robust(is_robust), pshared(is_pshared) {} + + LIBC_INLINE constexpr Mutex() + : owner(MACH_PORT_NULL), timed(0), recursive(0), robust(0), pshared(0) {} + + LIBC_INLINE static MutexError init(Mutex *mutex, bool is_timed, bool is_recur, + bool is_robust, bool is_pshared) { + mutex->lock_val = OS_UNFAIR_LOCK_INIT; + mutex->owner = MACH_PORT_NULL; + mutex->timed = is_timed; + mutex->recursive = is_recur; + mutex->robust = is_robust; + mutex->pshared = is_pshared; + return MutexError::NONE; + } + + LIBC_INLINE static MutexError destroy(Mutex *lock) { + LIBC_ASSERT(lock->owner == MACH_PORT_NULL && + "Mutex destroyed while locked."); + return MutexError::NONE; + } + + LIBC_INLINE MutexError lock() { + os_unfair_lock_lock(&lock_val); + owner = mach_thread_self(); + return MutexError::NONE; + } + + LIBC_INLINE MutexError timed_lock(internal::AbsTimeout abs_time) { + while (true) { + if (try_lock() == MutexError::NONE) { + return MutexError::NONE; + } + + // Manually check if the timeout has expired. + struct timespec now; + // The clock used here must match the clock used to create the + // absolute timeout. + clock_gettime(abs_time.is_realtime() ? CLOCK_REALTIME : CLOCK_MONOTONIC, + &now); + const timespec &target_ts = abs_time.get_timespec(); + + if (now.tv_sec > target_ts.tv_sec || (now.tv_sec == target_ts.tv_sec && + now.tv_nsec >= target_ts.tv_nsec)) { + // We might have acquired the lock between the last try_lock() and now. + // To avoid returning TIMEOUT incorrectly, we do one last try_lock(). + if (try_lock() == MutexError::NONE) + return MutexError::NONE; + return MutexError::TIMEOUT; + } + + sleep_briefly(); + } + } + + LIBC_INLINE MutexError unlock() { + // This check is crucial. It prevents both double-unlocks and unlocks + // by threads that do not own the mutex. + if (owner != mach_thread_self()) { + return MutexError::UNLOCK_WITHOUT_LOCK; + } + owner = MACH_PORT_NULL; + os_unfair_lock_unlock(&lock_val); + return MutexError::NONE; + } + + LIBC_INLINE MutexError try_lock() { + if (os_unfair_lock_trylock(&lock_val)) { + owner = mach_thread_self(); + return MutexError::NONE; + } + return MutexError::BUSY; + } +}; + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H diff --git a/libc/src/__support/threads/mutex.h b/libc/src/__support/threads/mutex.h index f64f7e7b40082..2ebbf39873818 100644 --- a/libc/src/__support/threads/mutex.h +++ b/libc/src/__support/threads/mutex.h @@ -40,9 +40,15 @@ // few global locks. So, to avoid static initialization order fiasco, we // want the constructors of the Mutex classes to be constexprs. +<<<<<<< HEAD #if defined(__linux__) #include "src/__support/threads/linux/mutex.h" #endif // __linux__ +======= +#if defined(__linux__) || defined(__APPLE__) +#include "src/__support/threads/unix_mutex.h" +#endif +>>>>>>> c35b95c04bf7 ([libc] Add Darwin mutex support via os_sync primitives) #elif LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE diff --git a/libc/src/__support/threads/linux/raw_mutex.h b/libc/src/__support/threads/raw_mutex.h similarity index 89% rename from libc/src/__support/threads/linux/raw_mutex.h rename to libc/src/__support/threads/raw_mutex.h index 94d6129bbf69b..fb3f5c0f70ed6 100644 --- a/libc/src/__support/threads/linux/raw_mutex.h +++ b/libc/src/__support/threads/raw_mutex.h @@ -1,12 +1,12 @@ -//===--- Implementation of a Linux RawMutex class ---------------*- C++ -*-===// +//===--- Implementation of the RawMutex class ---------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -//===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_RAW_MUTEX_H -#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_RAW_MUTEX_H +//===------------------------------------------------------------------===// +#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H +#define LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H #include "src/__support/CPP/optional.h" #include "src/__support/common.h" @@ -14,15 +14,21 @@ #include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" -#include "src/__support/threads/linux/futex_utils.h" -#include "src/__support/threads/linux/futex_word.h" #include "src/__support/threads/sleep.h" #include "src/__support/time/abs_timeout.h" +#include "sys/errno.h" + +#if defined(__linux__) +#include "src/__support/threads/linux/futex_utils.h" +#elif defined(__APPLE__) +#include "src/__support/threads/darwin/futex_utils.h" +#endif #ifndef LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY #define LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY 1 #endif +// TODO(bojle): check this for darwin impl #if LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY #include "src/__support/time/monotonicity.h" #endif @@ -93,7 +99,9 @@ class RawMutex { LIBC_INLINE void wake(bool is_pshared) { futex.notify_one(is_pshared); } public: - LIBC_INLINE static void init(RawMutex *mutex) { mutex->futex = UNLOCKED; } + LIBC_INLINE static void init(RawMutex *mutex) { + mutex->futex.store(UNLOCKED); + } LIBC_INLINE constexpr RawMutex() : futex(UNLOCKED) {} [[nodiscard]] LIBC_INLINE bool try_lock() { FutexWordType expected = UNLOCKED; @@ -122,7 +130,7 @@ class RawMutex { LIBC_ASSERT(lock->futex == UNLOCKED && "Mutex destroyed while used."); } LIBC_INLINE Futex &get_raw_futex() { return futex; } - LIBC_INLINE void reset() { futex = UNLOCKED; } + LIBC_INLINE void reset() { futex.store(UNLOCKED); } }; } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/threads/linux/mutex.h b/libc/src/__support/threads/unix_mutex.h similarity index 90% rename from libc/src/__support/threads/linux/mutex.h rename to libc/src/__support/threads/unix_mutex.h index 0c4b1ae09af6f..31acd582d4c6c 100644 --- a/libc/src/__support/threads/linux/mutex.h +++ b/libc/src/__support/threads/unix_mutex.h @@ -1,4 +1,4 @@ -//===--- Implementation of a Linux mutex class ------------------*- C++ -*-===// +//===--- Implementation of a Unix mutex class ------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,16 +6,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H -#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H +#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_UNIX_MUTEX_H +#define LLVM_LIBC_SRC___SUPPORT_THREADS_UNIX_MUTEX_H #include "hdr/types/pid_t.h" #include "src/__support/CPP/optional.h" #include "src/__support/libc_assert.h" #include "src/__support/macros/config.h" -#include "src/__support/threads/linux/futex_utils.h" -#include "src/__support/threads/linux/raw_mutex.h" #include "src/__support/threads/mutex_common.h" +#include "src/__support/threads/raw_mutex.h" namespace LIBC_NAMESPACE_DECL { From 23ff0b8a7619ef8674c1f6309d8563deee84c171 Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Fri, 28 Nov 2025 23:19:18 +0530 Subject: [PATCH 2/8] [libc][darwin] use os_sync_*_timeouts and clear tests --- .../__support/threads/darwin/futex_utils.h | 72 +++++++++++-------- libc/src/__support/threads/raw_mutex.h | 2 + .../__support/threads/darwin/mutex_test.cpp | 45 ++++++++++++ 3 files changed, 89 insertions(+), 30 deletions(-) create mode 100644 libc/test/src/__support/threads/darwin/mutex_test.cpp diff --git a/libc/src/__support/threads/darwin/futex_utils.h b/libc/src/__support/threads/darwin/futex_utils.h index 180083b7b2c68..380be69b2a66a 100644 --- a/libc/src/__support/threads/darwin/futex_utils.h +++ b/libc/src/__support/threads/darwin/futex_utils.h @@ -1,11 +1,10 @@ -//===--- Futex utils for Darwin -----------------------------------*- C++ -//-*-===// +//===--- Futex utils for Darwin ------------------------*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -//===----------------------------------------------------------------------===// +//===------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H #define LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H @@ -25,39 +24,52 @@ struct Futex : public cpp::Atomic { using cpp::Atomic::Atomic; using Timeout = internal::AbsTimeout; - // The Darwin futex API does not return a value on timeout, so we have to - // check for it manually. This means we can't use the return value to - // distinguish between a timeout and a successful wake-up. - int wait(FutexWordType val, cpp::optional timeout, bool) { - if (timeout) { - struct timespec now; - clock_gettime(timeout->is_realtime() ? CLOCK_REALTIME : CLOCK_MONOTONIC, - &now); - const timespec &target_ts = timeout->get_timespec(); + LIBC_INLINE long wait(FutexWordType val, cpp::optional timeout, + bool /* is_shared */) { + // TODO(bojle): consider using OS_SYNC_WAIT_ON_ADDRESS_SHARED to sync + // betweeen processes. Catch: it is recommended to only be used by shared + // processes, not threads of a same process. - if (now.tv_sec > target_ts.tv_sec || - (now.tv_sec == target_ts.tv_sec && now.tv_nsec >= target_ts.tv_nsec)) - return ETIMEDOUT; + for (;;) { + if (this->load(cpp::MemoryOrder::RELAXED) != val) + return 0; + long ret = 0; + if (timeout) { + // Assuming, OS_CLOCK_MACH_ABSOLUTE_TIME is equivalent to CLOCK_REALTIME + uint64_t tnsec = timeout->get_timespec().tv_sec * 1000000000 + + timeout->get_timespec().tv_nsec; + ret = os_sync_wait_on_address_with_timeout( + reinterpret_cast(this), static_cast(val), + sizeof(FutexWordType), OS_SYNC_WAIT_ON_ADDRESS_NONE, + OS_CLOCK_MACH_ABSOLUTE_TIME, tnsec); + } else { + ret = os_sync_wait_on_address( + reinterpret_cast(this), static_cast(val), + sizeof(FutexWordType), OS_SYNC_WAIT_ON_ADDRESS_NONE); + } + if ((ret < 0) && (errno == ETIMEDOUT)) { + return -ETIMEDOUT; + } + // case when os_sync returns early with an error. retry. + if ((ret < 0) && ((errno == EINTR) || (errno == EFAULT))) { + continue; + } + return ret; } - - os_sync_wait_on_address(reinterpret_cast(this), - static_cast(val), sizeof(FutexWordType), - OS_SYNC_WAIT_ON_ADDRESS_NONE); - return 0; } - void notify_one(bool) { - os_sync_wake_by_address_any(reinterpret_cast(this), - sizeof(FutexWordType), - OS_SYNC_WAKE_BY_ADDRESS_NONE); + LIBC_INLINE long notify_one(bool /* is_shared */) { + // TODO(bojle): deal with is_shared + return os_sync_wake_by_address_any(reinterpret_cast(this), + sizeof(FutexWordType), + OS_SYNC_WAKE_BY_ADDRESS_NONE); } - void notify_all(bool) { - // os_sync_wake_by_address_all is not available, so we use notify_one. - // This is not ideal, but it's the best we can do with the available API. - os_sync_wake_by_address_any(reinterpret_cast(this), - sizeof(FutexWordType), - OS_SYNC_WAKE_BY_ADDRESS_NONE); + LIBC_INLINE long notify_all(bool /* is_shared */) { + // TODO(bojle): deal with is_shared + return os_sync_wake_by_address_all(reinterpret_cast(this), + sizeof(FutexWordType), + OS_SYNC_WAKE_BY_ADDRESS_NONE); } }; diff --git a/libc/src/__support/threads/raw_mutex.h b/libc/src/__support/threads/raw_mutex.h index fb3f5c0f70ed6..c8f35a5785fd7 100644 --- a/libc/src/__support/threads/raw_mutex.h +++ b/libc/src/__support/threads/raw_mutex.h @@ -18,6 +18,8 @@ #include "src/__support/time/abs_timeout.h" #include "sys/errno.h" +#include + #if defined(__linux__) #include "src/__support/threads/linux/futex_utils.h" #elif defined(__APPLE__) diff --git a/libc/test/src/__support/threads/darwin/mutex_test.cpp b/libc/test/src/__support/threads/darwin/mutex_test.cpp new file mode 100644 index 0000000000000..b87da8670e422 --- /dev/null +++ b/libc/test/src/__support/threads/darwin/mutex_test.cpp @@ -0,0 +1,45 @@ +//===-- Unittests for Darwin's Mutex ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/threads/mutex.h" +#include "src/__support/threads/mutex_common.h" +#include "src/__support/threads/raw_mutex.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcSupportThreadsMutexTest, SmokeTest) { + LIBC_NAMESPACE::Mutex mutex(0, 0, 0, 0); + ASSERT_EQ(mutex.lock(), LIBC_NAMESPACE::MutexError::NONE); + ASSERT_EQ(mutex.unlock(), LIBC_NAMESPACE::MutexError::NONE); + ASSERT_EQ(mutex.try_lock(), LIBC_NAMESPACE::MutexError::NONE); + ASSERT_EQ(mutex.try_lock(), LIBC_NAMESPACE::MutexError::BUSY); + ASSERT_EQ(mutex.unlock(), LIBC_NAMESPACE::MutexError::NONE); + ASSERT_EQ(mutex.unlock(), LIBC_NAMESPACE::MutexError::UNLOCK_WITHOUT_LOCK); +} + +TEST(LlvmLibcSupportThreadsRawMutexTest, Timeout) { + LIBC_NAMESPACE::RawMutex mutex; + ASSERT_TRUE(mutex.lock()); + timespec ts; + LIBC_NAMESPACE::internal::clock_gettime(CLOCK_MONOTONIC, &ts); + ts.tv_sec += 1; + // Timeout will be respected when deadlock happens. + auto timeout = LIBC_NAMESPACE::internal::AbsTimeout::from_timespec(ts, false); + ASSERT_TRUE(timeout.has_value()); + // The following will timeout + ASSERT_FALSE(mutex.lock(*timeout)); + ASSERT_TRUE(mutex.unlock()); + // Test that the mutex works after the timeout. + ASSERT_TRUE(mutex.lock()); + ASSERT_TRUE(mutex.unlock()); + // If a lock can be acquired directly, expired timeout will not count. + // Notice that the timeout is already reached during preivous deadlock. + ASSERT_TRUE(mutex.lock(*timeout)); + ASSERT_TRUE(mutex.unlock()); +} + +// TODO(bojle): add other tests a la linux From 031c00a3c657d6f7273d16238a62a4602f6c869f Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Wed, 3 Dec 2025 18:50:33 +0530 Subject: [PATCH 3/8] [libc][darwin] clean rebase conflict remnants --- libc/src/__support/threads/mutex.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libc/src/__support/threads/mutex.h b/libc/src/__support/threads/mutex.h index 2ebbf39873818..25feea891e429 100644 --- a/libc/src/__support/threads/mutex.h +++ b/libc/src/__support/threads/mutex.h @@ -40,15 +40,9 @@ // few global locks. So, to avoid static initialization order fiasco, we // want the constructors of the Mutex classes to be constexprs. -<<<<<<< HEAD -#if defined(__linux__) -#include "src/__support/threads/linux/mutex.h" -#endif // __linux__ -======= #if defined(__linux__) || defined(__APPLE__) #include "src/__support/threads/unix_mutex.h" #endif ->>>>>>> c35b95c04bf7 ([libc] Add Darwin mutex support via os_sync primitives) #elif LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE From 78c191a65c072fcff7ad578b7889d25d61ea0d00 Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Wed, 3 Dec 2025 19:16:31 +0530 Subject: [PATCH 4/8] [libc][darwin] cmake options, minor nits --- .../modules/LLVMLibCCompileOptionRules.cmake | 4 + libc/src/__support/threads/CMakeLists.txt | 44 +++--- .../__support/threads/darwin/futex_utils.h | 7 +- libc/src/__support/threads/darwin/mutex.h | 131 ------------------ 4 files changed, 29 insertions(+), 157 deletions(-) delete mode 100644 libc/src/__support/threads/darwin/mutex.h diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 619b53f828705..5caf840a4cfeb 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -119,6 +119,10 @@ function(_get_compile_options_from_config output_var) list(APPEND config_options "-DLIBC_TRAP_ON_RAISE_FP_EXCEPT") endif() + if(LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT) + list(APPEND config_options "-DLIBC_COPT_RAW_MUTEX_DEFAULT_SPIN_COUNT=${LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT}") + endif() + set(${output_var} ${config_options} PARENT_SCOPE) endfunction(_get_compile_options_from_config) diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt index b2abf19c53a50..dc1445634da2b 100644 --- a/libc/src/__support/threads/CMakeLists.txt +++ b/libc/src/__support/threads/CMakeLists.txt @@ -25,52 +25,52 @@ endif() if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.futex_utils) add_header_library( - mutex + raw_mutex HDRS - mutex.h + raw_mutex.h + COMPILE_OPTIONS + ${monotonicity_flags} DEPENDS - .unix_mutex + .${LIBC_TARGET_OS}.futex_utils + libc.src.__support.threads.sleep + libc.src.__support.time.abs_timeout + libc.src.__support.time.monotonicity + libc.src.__support.CPP.optional + libc.hdr.types.pid_t ) + add_header_library( unix_mutex HDRS - unix_mutex.h + unix_mutex.h DEPENDS - .raw_mutex + .raw_mutex ) add_header_library( - raw_mutex + mutex HDRS - raw_mutex.h + mutex.h DEPENDS - .${LIBC_TARGET_OS}.futex_utils - libc.src.__support.threads.sleep - libc.src.__support.time.abs_timeout - libc.src.__support.time.monotonicity - libc.src.__support.CPP.optional - libc.hdr.types.pid_t - COMPILE_OPTIONS - -DLIBC_COPT_RAW_MUTEX_DEFAULT_SPIN_COUNT=${LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT} - ${monotonicity_flags} + .unix_mutex ) add_object_library( fork_callbacks SRCS - fork_callbacks.cpp + fork_callbacks.cpp HDRS - fork_callbacks.h + fork_callbacks.h DEPENDS - .mutex - libc.src.__support.CPP.mutex + .mutex + libc.src.__support.CPP.mutex ) elseif(NOT (LIBC_CONF_THREAD_MODE STREQUAL LIBC_THREAD_MODE_PLATFORM)) add_header_library( mutex - HDRS + HDRS mutex.h - DEPENDS + DEPENDS .mutex_common ) endif() diff --git a/libc/src/__support/threads/darwin/futex_utils.h b/libc/src/__support/threads/darwin/futex_utils.h index 380be69b2a66a..f880d09f621fc 100644 --- a/libc/src/__support/threads/darwin/futex_utils.h +++ b/libc/src/__support/threads/darwin/futex_utils.h @@ -1,10 +1,10 @@ -//===--- Futex utils for Darwin ------------------------*- C++-*-===// +//===--- Futex utils for Darwin ----------------------------------*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -//===------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H #define LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H @@ -47,9 +47,8 @@ struct Futex : public cpp::Atomic { reinterpret_cast(this), static_cast(val), sizeof(FutexWordType), OS_SYNC_WAIT_ON_ADDRESS_NONE); } - if ((ret < 0) && (errno == ETIMEDOUT)) { + if ((ret < 0) && (errno == ETIMEDOUT)) return -ETIMEDOUT; - } // case when os_sync returns early with an error. retry. if ((ret < 0) && ((errno == EINTR) || (errno == EFAULT))) { continue; diff --git a/libc/src/__support/threads/darwin/mutex.h b/libc/src/__support/threads/darwin/mutex.h deleted file mode 100644 index 44ba14cc986a2..0000000000000 --- a/libc/src/__support/threads/darwin/mutex.h +++ /dev/null @@ -1,131 +0,0 @@ -//===--- Implementation of a Darwin mutex class -----------*- C++-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------===// - -#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H -#define LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H - -#include "src/__support/libc_assert.h" -#include "src/__support/macros/config.h" -#include "src/__support/threads/mutex_common.h" -#include "src/__support/threads/sleep.h" // For sleep_briefly -#include "src/__support/time/abs_timeout.h" - -#include // For mach_thread_self -#include // For mach_port_t and MACH_PORT_NULL -#include // For os_unfair_lock -#include // For clock_gettime - -namespace LIBC_NAMESPACE_DECL { - -// This file is an implementation of `LIBC_NAMESPACE::mutex` for Darwin-based -// platforms. It is a wrapper around `os_unfair_lock`, which is a low-level, -// high-performance locking primitive provided by the kernel. -// -// `os_unfair_lock` is a non-recursive, thread-owned lock that blocks waiters -// efficiently in the kernel. As the name implies, it is "unfair," meaning -// it does not guarantee the order in which waiting threads acquire the lock. -// This trade-off allows for higher performance in contended scenarios. -// -// The lock must be unlocked from the same thread that locked it. Attempting -// to unlock from a different thread will result in a runtime error. -// -// This implementation is suitable for simple critical sections where fairness -// and reentrancy are not concerns. - -class Mutex final { - os_unfair_lock_s lock_val = OS_UNFAIR_LOCK_INIT; - mach_port_t owner = MACH_PORT_NULL; - - // API compatibility fields. - unsigned char timed; - unsigned char recursive; - unsigned char robust; - unsigned char pshared; - -public: - LIBC_INLINE constexpr Mutex(bool is_timed, bool is_recursive, bool is_robust, - bool is_pshared) - : owner(MACH_PORT_NULL), timed(is_timed), recursive(is_recursive), - robust(is_robust), pshared(is_pshared) {} - - LIBC_INLINE constexpr Mutex() - : owner(MACH_PORT_NULL), timed(0), recursive(0), robust(0), pshared(0) {} - - LIBC_INLINE static MutexError init(Mutex *mutex, bool is_timed, bool is_recur, - bool is_robust, bool is_pshared) { - mutex->lock_val = OS_UNFAIR_LOCK_INIT; - mutex->owner = MACH_PORT_NULL; - mutex->timed = is_timed; - mutex->recursive = is_recur; - mutex->robust = is_robust; - mutex->pshared = is_pshared; - return MutexError::NONE; - } - - LIBC_INLINE static MutexError destroy(Mutex *lock) { - LIBC_ASSERT(lock->owner == MACH_PORT_NULL && - "Mutex destroyed while locked."); - return MutexError::NONE; - } - - LIBC_INLINE MutexError lock() { - os_unfair_lock_lock(&lock_val); - owner = mach_thread_self(); - return MutexError::NONE; - } - - LIBC_INLINE MutexError timed_lock(internal::AbsTimeout abs_time) { - while (true) { - if (try_lock() == MutexError::NONE) { - return MutexError::NONE; - } - - // Manually check if the timeout has expired. - struct timespec now; - // The clock used here must match the clock used to create the - // absolute timeout. - clock_gettime(abs_time.is_realtime() ? CLOCK_REALTIME : CLOCK_MONOTONIC, - &now); - const timespec &target_ts = abs_time.get_timespec(); - - if (now.tv_sec > target_ts.tv_sec || (now.tv_sec == target_ts.tv_sec && - now.tv_nsec >= target_ts.tv_nsec)) { - // We might have acquired the lock between the last try_lock() and now. - // To avoid returning TIMEOUT incorrectly, we do one last try_lock(). - if (try_lock() == MutexError::NONE) - return MutexError::NONE; - return MutexError::TIMEOUT; - } - - sleep_briefly(); - } - } - - LIBC_INLINE MutexError unlock() { - // This check is crucial. It prevents both double-unlocks and unlocks - // by threads that do not own the mutex. - if (owner != mach_thread_self()) { - return MutexError::UNLOCK_WITHOUT_LOCK; - } - owner = MACH_PORT_NULL; - os_unfair_lock_unlock(&lock_val); - return MutexError::NONE; - } - - LIBC_INLINE MutexError try_lock() { - if (os_unfair_lock_trylock(&lock_val)) { - owner = mach_thread_self(); - return MutexError::NONE; - } - return MutexError::BUSY; - } -}; - -} // namespace LIBC_NAMESPACE_DECL - -#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H From 212cc76d2f791becc92b580122d8dc94247f6bda Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Fri, 5 Dec 2025 18:35:58 +0530 Subject: [PATCH 5/8] [libc] linux/raw_mutex.h -> raw_mutex.h --- libc/src/__support/threads/CndVar.h | 2 +- .../__support/threads/linux/CMakeLists.txt | 30 ++----------------- libc/src/__support/threads/linux/CndVar.cpp | 4 +-- libc/src/__support/threads/linux/rwlock.h | 2 +- libc/src/__support/threads/raw_mutex.h | 6 ++-- libc/src/__support/threads/unix_mutex.h | 2 +- libc/src/threads/linux/CMakeLists.txt | 2 +- .../integration/src/pthread/CMakeLists.txt | 2 +- .../src/pthread/pthread_rwlock_test.cpp | 2 +- .../__support/threads/darwin/CMakeLists.txt | 11 +++++++ .../__support/threads/linux/CMakeLists.txt | 2 +- .../threads/linux/raw_mutex_test.cpp | 2 +- 12 files changed, 26 insertions(+), 41 deletions(-) create mode 100644 libc/test/src/__support/threads/darwin/CMakeLists.txt diff --git a/libc/src/__support/threads/CndVar.h b/libc/src/__support/threads/CndVar.h index 7b2a7126ca09c..901b652c553d8 100644 --- a/libc/src/__support/threads/CndVar.h +++ b/libc/src/__support/threads/CndVar.h @@ -12,8 +12,8 @@ #include "hdr/stdint_proxy.h" // uint32_t #include "src/__support/macros/config.h" #include "src/__support/threads/linux/futex_utils.h" // Futex -#include "src/__support/threads/linux/raw_mutex.h" // RawMutex #include "src/__support/threads/mutex.h" // Mutex +#include "src/__support/threads/raw_mutex.h" // RawMutex namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt index cc596d217d7d2..200a3b1529fec 100644 --- a/libc/src/__support/threads/linux/CMakeLists.txt +++ b/libc/src/__support/threads/linux/CMakeLists.txt @@ -31,29 +31,13 @@ else() set(monotonicity_flags -DLIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY=0) endif() -add_header_library( - raw_mutex - HDRS - mutex.h - DEPENDS - .futex_utils - libc.src.__support.threads.sleep - libc.src.__support.time.abs_timeout - libc.src.__support.time.monotonicity - libc.src.__support.CPP.optional - libc.hdr.types.pid_t - COMPILE_OPTIONS - -DLIBC_COPT_RAW_MUTEX_DEFAULT_SPIN_COUNT=${LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT} - ${monotonicity_flags} -) - add_header_library( rwlock HDRS rwlock.h DEPENDS .futex_utils - .raw_mutex + libc.src.__support.threads.raw_mutex libc.src.__support.common libc.src.__support.OSUtil.osutil libc.src.__support.CPP.limits @@ -63,16 +47,6 @@ add_header_library( ${monotonicity_flags} ) -add_header_library( - mutex - HDRS - mutex.h - DEPENDS - .futex_utils - .raw_mutex - libc.src.__support.threads.mutex_common -) - add_object_library( thread SRCS @@ -119,7 +93,7 @@ add_object_library( libc.src.__support.OSUtil.osutil libc.src.__support.threads.linux.futex_word_type libc.src.__support.threads.mutex - libc.src.__support.threads.linux.raw_mutex + libc.src.__support.threads.raw_mutex libc.src.__support.CPP.mutex ) diff --git a/libc/src/__support/threads/linux/CndVar.cpp b/libc/src/__support/threads/linux/CndVar.cpp index be74c18dddf31..60424673e819c 100644 --- a/libc/src/__support/threads/linux/CndVar.cpp +++ b/libc/src/__support/threads/linux/CndVar.cpp @@ -8,11 +8,11 @@ #include "src/__support/threads/CndVar.h" #include "src/__support/CPP/mutex.h" -#include "src/__support/OSUtil/syscall.h" // syscall_impl +#include "src/__support/OSUtil/syscall.h" // syscall_impl #include "src/__support/macros/config.h" #include "src/__support/threads/linux/futex_word.h" // FutexWordType -#include "src/__support/threads/linux/raw_mutex.h" // RawMutex #include "src/__support/threads/mutex.h" // Mutex +#include "src/__support/threads/raw_mutex.h" // RawMutex #include // For syscall numbers. diff --git a/libc/src/__support/threads/linux/rwlock.h b/libc/src/__support/threads/linux/rwlock.h index 165e17239bbd5..9fb3ff972b588 100644 --- a/libc/src/__support/threads/linux/rwlock.h +++ b/libc/src/__support/threads/linux/rwlock.h @@ -22,7 +22,7 @@ #include "src/__support/threads/identifier.h" #include "src/__support/threads/linux/futex_utils.h" #include "src/__support/threads/linux/futex_word.h" -#include "src/__support/threads/linux/raw_mutex.h" +#include "src/__support/threads/raw_mutex.h" #include "src/__support/threads/sleep.h" #ifndef LIBC_COPT_RWLOCK_DEFAULT_SPIN_COUNT diff --git a/libc/src/__support/threads/raw_mutex.h b/libc/src/__support/threads/raw_mutex.h index c8f35a5785fd7..571ea405dd851 100644 --- a/libc/src/__support/threads/raw_mutex.h +++ b/libc/src/__support/threads/raw_mutex.h @@ -1,10 +1,10 @@ -//===--- Implementation of the RawMutex class ---------------*- C++ -*-===// +//===--- Implementation of the RawMutex class -------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -//===------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H #define LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H @@ -136,4 +136,4 @@ class RawMutex { }; } // namespace LIBC_NAMESPACE_DECL -#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_RAW_MUTEX_H +#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H diff --git a/libc/src/__support/threads/unix_mutex.h b/libc/src/__support/threads/unix_mutex.h index 31acd582d4c6c..626cee9d0913d 100644 --- a/libc/src/__support/threads/unix_mutex.h +++ b/libc/src/__support/threads/unix_mutex.h @@ -1,4 +1,4 @@ -//===--- Implementation of a Unix mutex class ------------------*- C++ -*-===// +//===--- Implementation of a Unix mutex class -------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libc/src/threads/linux/CMakeLists.txt b/libc/src/threads/linux/CMakeLists.txt index 6c8e0845faf4c..3cbf2f85f3f9d 100644 --- a/libc/src/threads/linux/CMakeLists.txt +++ b/libc/src/threads/linux/CMakeLists.txt @@ -9,7 +9,7 @@ add_header_library( libc.src.__support.CPP.mutex libc.src.__support.OSUtil.osutil libc.src.__support.threads.mutex - libc.src.__support.threads.linux.raw_mutex + libc.src.__support.threads.raw_mutex libc.src.__support.threads.linux.futex_utils ) diff --git a/libc/test/integration/src/pthread/CMakeLists.txt b/libc/test/integration/src/pthread/CMakeLists.txt index 251b009994ab5..b7414f2bea120 100644 --- a/libc/test/integration/src/pthread/CMakeLists.txt +++ b/libc/test/integration/src/pthread/CMakeLists.txt @@ -62,7 +62,7 @@ add_integration_test( libc.src.pthread.pthread_rwlockattr_destroy libc.src.pthread.pthread_rwlockattr_setpshared libc.src.pthread.pthread_rwlockattr_setkind_np - libc.src.__support.threads.linux.raw_mutex + libc.src.__support.threads.raw_mutex libc.src.stdio.printf libc.src.stdlib.getenv libc.src.sys.mman.mmap diff --git a/libc/test/integration/src/pthread/pthread_rwlock_test.cpp b/libc/test/integration/src/pthread/pthread_rwlock_test.cpp index 205e9f74ea9a1..dddfb282ce167 100644 --- a/libc/test/integration/src/pthread/pthread_rwlock_test.cpp +++ b/libc/test/integration/src/pthread/pthread_rwlock_test.cpp @@ -12,8 +12,8 @@ #include "src/__support/CPP/new.h" #include "src/__support/OSUtil/syscall.h" #include "src/__support/macros/config.h" -#include "src/__support/threads/linux/raw_mutex.h" #include "src/__support/threads/linux/rwlock.h" +#include "src/__support/threads/raw_mutex.h" #include "src/__support/threads/sleep.h" #include "src/pthread/pthread_create.h" #include "src/pthread/pthread_join.h" diff --git a/libc/test/src/__support/threads/darwin/CMakeLists.txt b/libc/test/src/__support/threads/darwin/CMakeLists.txt new file mode 100644 index 0000000000000..4c399b4258d66 --- /dev/null +++ b/libc/test/src/__support/threads/darwin/CMakeLists.txt @@ -0,0 +1,11 @@ +add_libc_test( + mutex_test + SUITE + libc-support-threads-tests + SRCS + mutex_test.cpp + DEPENDS + libc.src.__support.threads.mutex + libc.src.__support.threads.darwin.futex_utils + libc.src.__support.time.darwin.clock_gettime +) diff --git a/libc/test/src/__support/threads/linux/CMakeLists.txt b/libc/test/src/__support/threads/linux/CMakeLists.txt index 4299a5617b8ff..a660e7ceb4490 100644 --- a/libc/test/src/__support/threads/linux/CMakeLists.txt +++ b/libc/test/src/__support/threads/linux/CMakeLists.txt @@ -5,7 +5,7 @@ add_libc_test( SRCS raw_mutex_test.cpp DEPENDS - libc.src.__support.threads.linux.raw_mutex + libc.src.__support.threads.raw_mutex libc.src.sys.mman.mmap libc.src.sys.mman.munmap libc.src.stdlib.exit diff --git a/libc/test/src/__support/threads/linux/raw_mutex_test.cpp b/libc/test/src/__support/threads/linux/raw_mutex_test.cpp index dadc706421d06..6522ec75e619c 100644 --- a/libc/test/src/__support/threads/linux/raw_mutex_test.cpp +++ b/libc/test/src/__support/threads/linux/raw_mutex_test.cpp @@ -10,7 +10,7 @@ #include "include/llvm-libc-macros/linux/time-macros.h" #include "src/__support/CPP/atomic.h" #include "src/__support/OSUtil/syscall.h" -#include "src/__support/threads/linux/raw_mutex.h" +#include "src/__support/threads/raw_mutex.h" #include "src/__support/threads/sleep.h" #include "src/__support/time/clock_gettime.h" #include "src/stdlib/exit.h" From eb03eff51fc7448f7a56b1e18798485f509c7b5a Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Fri, 5 Dec 2025 18:50:35 +0530 Subject: [PATCH 6/8] [libc] "" -> <> --- libc/src/__support/threads/raw_mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/__support/threads/raw_mutex.h b/libc/src/__support/threads/raw_mutex.h index 571ea405dd851..a5af02a3e1414 100644 --- a/libc/src/__support/threads/raw_mutex.h +++ b/libc/src/__support/threads/raw_mutex.h @@ -16,7 +16,7 @@ #include "src/__support/macros/optimization.h" #include "src/__support/threads/sleep.h" #include "src/__support/time/abs_timeout.h" -#include "sys/errno.h" +#include #include From 390aca8acf2ecf0b024c80bdf0bf325334772fc3 Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Fri, 5 Dec 2025 18:57:35 +0530 Subject: [PATCH 7/8] [libc] use hdr/errno_macros.h Signed-off-by: Shreeyash Pandey --- libc/src/__support/threads/raw_mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/__support/threads/raw_mutex.h b/libc/src/__support/threads/raw_mutex.h index a5af02a3e1414..e68469ad531cc 100644 --- a/libc/src/__support/threads/raw_mutex.h +++ b/libc/src/__support/threads/raw_mutex.h @@ -8,6 +8,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H #define LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H +#include "hdr/errno_macros.h" #include "src/__support/CPP/optional.h" #include "src/__support/common.h" #include "src/__support/libc_assert.h" @@ -16,7 +17,6 @@ #include "src/__support/macros/optimization.h" #include "src/__support/threads/sleep.h" #include "src/__support/time/abs_timeout.h" -#include #include From 475c70fa69d31d7d372b517631efb25ae32ef7c8 Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Fri, 5 Dec 2025 19:19:52 +0530 Subject: [PATCH 8/8] [libc] use time_units --- libc/src/__support/threads/darwin/futex_utils.h | 4 +++- libc/test/src/__support/threads/darwin/mutex_test.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libc/src/__support/threads/darwin/futex_utils.h b/libc/src/__support/threads/darwin/futex_utils.h index f880d09f621fc..65ac1ce0ab351 100644 --- a/libc/src/__support/threads/darwin/futex_utils.h +++ b/libc/src/__support/threads/darwin/futex_utils.h @@ -13,6 +13,7 @@ #include "src/__support/CPP/optional.h" #include "src/__support/time/abs_timeout.h" #include "src/__support/time/clock_conversion.h" +#include "src/__support/time/units.h" #include @@ -36,7 +37,8 @@ struct Futex : public cpp::Atomic { long ret = 0; if (timeout) { // Assuming, OS_CLOCK_MACH_ABSOLUTE_TIME is equivalent to CLOCK_REALTIME - uint64_t tnsec = timeout->get_timespec().tv_sec * 1000000000 + + using namespace time_units; + uint64_t tnsec = timeout->get_timespec().tv_sec * 1_s_ns + timeout->get_timespec().tv_nsec; ret = os_sync_wait_on_address_with_timeout( reinterpret_cast(this), static_cast(val), diff --git a/libc/test/src/__support/threads/darwin/mutex_test.cpp b/libc/test/src/__support/threads/darwin/mutex_test.cpp index b87da8670e422..a9df97bc94ebb 100644 --- a/libc/test/src/__support/threads/darwin/mutex_test.cpp +++ b/libc/test/src/__support/threads/darwin/mutex_test.cpp @@ -42,4 +42,5 @@ TEST(LlvmLibcSupportThreadsRawMutexTest, Timeout) { ASSERT_TRUE(mutex.unlock()); } -// TODO(bojle): add other tests a la linux +// TODO(bojle): merge threads test for darwin and linux into one after +// adding support for shared locks in darwin