[libc-commits] [libc] 3c97829 - [libc] Add Darwin mutex support via os_sync primitives (#167722)
via libc-commits
libc-commits at lists.llvm.org
Tue Dec 16 09:52:23 PST 2025
Author: Shreeyash Pandey
Date: 2025-12-16T23:22:19+05:30
New Revision: 3c97829d971d133c8984987271a31b90da64da84
URL: https://github.com/llvm/llvm-project/commit/3c97829d971d133c8984987271a31b90da64da84
DIFF: https://github.com/llvm/llvm-project/commit/3c97829d971d133c8984987271a31b90da64da84.diff
LOG: [libc] Add Darwin mutex support via os_sync primitives (#167722)
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.
Added:
libc/src/__support/threads/darwin/CMakeLists.txt
libc/src/__support/threads/darwin/futex_utils.h
libc/src/__support/threads/raw_mutex.h
libc/src/__support/threads/unix_mutex.h
libc/test/src/__support/threads/darwin/CMakeLists.txt
libc/test/src/__support/threads/darwin/mutex_test.cpp
Modified:
libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
libc/src/__support/File/file.h
libc/src/__support/threads/CMakeLists.txt
libc/src/__support/threads/CndVar.h
libc/src/__support/threads/linux/CMakeLists.txt
libc/src/__support/threads/linux/CndVar.cpp
libc/src/__support/threads/linux/rwlock.h
libc/src/__support/threads/mutex.h
libc/src/threads/linux/CMakeLists.txt
libc/test/integration/src/pthread/CMakeLists.txt
libc/test/integration/src/pthread/pthread_rwlock_test.cpp
libc/test/src/__support/threads/linux/CMakeLists.txt
libc/test/src/__support/threads/linux/raw_mutex_test.cpp
Removed:
libc/src/__support/threads/linux/mutex.h
libc/src/__support/threads/linux/raw_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/File/file.h b/libc/src/__support/File/file.h
index 3652e448c7f5a..e4b2ab425a168 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -257,7 +257,15 @@ class File {
return error_unlocked();
}
+ // TODO: https://github.com/llvm/llvm-project/issues/172302
+ // MacOS defines clearerr_unlocked as a macro. While pre-processing, the
+ // identifier below is substituted for the definition in the SDK, which leads
+ // to compile time errors due to ill-formed statements. This is a workaround
+ // for the pre-processor.
+#pragma push_macro("clearerr_unlocked")
+#undef clearerr_unlocked
void clearerr_unlocked() { err = false; }
+#pragma pop_macro("clearerr_unlocked")
void clearerr() {
FileLock l(this);
diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt
index f8a44937721b4..dc1445634da2b 100644
--- a/libc/src/__support/threads/CMakeLists.txt
+++ b/libc/src/__support/threads/CMakeLists.txt
@@ -23,31 +23,54 @@ 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(
+ raw_mutex
+ HDRS
+ raw_mutex.h
+ COMPILE_OPTIONS
+ ${monotonicity_flags}
+ 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
+ )
+
+ add_header_library(
+ unix_mutex
+ HDRS
+ unix_mutex.h
+ DEPENDS
+ .raw_mutex
+ )
+
add_header_library(
mutex
HDRS
- mutex.h
+ mutex.h
DEPENDS
- .${LIBC_TARGET_OS}.mutex
+ .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/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/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..65ac1ce0ab351
--- /dev/null
+++ b/libc/src/__support/threads/darwin/futex_utils.h
@@ -0,0 +1,79 @@
+//===--- 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 "src/__support/time/units.h"
+
+#include <os/os_sync_wait_on_address.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+using FutexWordType = uint32_t;
+
+struct Futex : public cpp::Atomic<FutexWordType> {
+ using cpp::Atomic<FutexWordType>::Atomic;
+ using Timeout = internal::AbsTimeout;
+
+ LIBC_INLINE long wait(FutexWordType val, cpp::optional<Timeout> 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.
+
+ 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
+ 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<void *>(this), static_cast<uint64_t>(val),
+ sizeof(FutexWordType), OS_SYNC_WAIT_ON_ADDRESS_NONE,
+ OS_CLOCK_MACH_ABSOLUTE_TIME, tnsec);
+ } else {
+ ret = os_sync_wait_on_address(
+ reinterpret_cast<void *>(this), static_cast<uint64_t>(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;
+ }
+ }
+
+ LIBC_INLINE long notify_one(bool /* is_shared */) {
+ // TODO(bojle): deal with is_shared
+ return os_sync_wake_by_address_any(reinterpret_cast<void *>(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<void *>(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/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 <sys/syscall.h> // 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/mutex.h b/libc/src/__support/threads/mutex.h
index f64f7e7b40082..25feea891e429 100644
--- a/libc/src/__support/threads/mutex.h
+++ b/libc/src/__support/threads/mutex.h
@@ -40,9 +40,9 @@
// few global locks. So, to avoid static initialization order fiasco, we
// want the constructors of the Mutex classes to be constexprs.
-#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
#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 88%
rename from libc/src/__support/threads/linux/raw_mutex.h
rename to libc/src/__support/threads/raw_mutex.h
index 94d6129bbf69b..e68469ad531cc 100644
--- a/libc/src/__support/threads/linux/raw_mutex.h
+++ b/libc/src/__support/threads/raw_mutex.h
@@ -1,28 +1,36 @@
-//===--- 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 "hdr/errno_macros.h"
#include "src/__support/CPP/optional.h"
#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
#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 <stdio.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 +101,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,8 +132,8 @@ 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
-#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/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..626cee9d0913d 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 {
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/darwin/mutex_test.cpp b/libc/test/src/__support/threads/darwin/mutex_test.cpp
new file mode 100644
index 0000000000000..a9df97bc94ebb
--- /dev/null
+++ b/libc/test/src/__support/threads/darwin/mutex_test.cpp
@@ -0,0 +1,46 @@
+//===-- 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): merge threads test for darwin and linux into one after
+// adding support for shared locks in darwin
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"
More information about the libc-commits
mailing list