[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