[libc-commits] [libc] [libc] Replace `MutexLock` with `cpp::lock_guard` (PR #89340)

Vlad Mishel via libc-commits libc-commits at lists.llvm.org
Thu Apr 18 19:56:36 PDT 2024


https://github.com/vmishelcs updated https://github.com/llvm/llvm-project/pull/89340

>From 42f47affea0f76dd3352e6a671d361583629bebc Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Wed, 17 Apr 2024 20:44:29 -0700
Subject: [PATCH 01/12] [libc] Added lock_guard

---
 libc/src/__support/CPP/CMakeLists.txt | 10 ++++
 libc/src/__support/CPP/mutex.h        | 66 +++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)
 create mode 100644 libc/src/__support/CPP/mutex.h

diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 84d01fe0451602..9f1fd3671def73 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -51,6 +51,16 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.mutex)
+  add_header_library(
+    mutex
+    HDRS
+      mutex.h
+    DEPENDS
+      libc.src.__support.threads.${LIBC_TARGET_OS}.mutex
+  )
+endif()
+
 add_header_library(
   span
   HDRS
diff --git a/libc/src/__support/CPP/mutex.h b/libc/src/__support/CPP/mutex.h
new file mode 100644
index 00000000000000..30d671d7e99f06
--- /dev/null
+++ b/libc/src/__support/CPP/mutex.h
@@ -0,0 +1,66 @@
+//===--- A platform independent abstraction layer for mutexes ---*- 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_CPP_MUTEX_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H
+
+#include "src/__support/macros/properties/architectures.h"
+
+// Platform independent code will include this header file which pulls
+// the platfrom specific specializations using platform macros.
+//
+// The platform specific specializations should define a class by name
+// Mutex with non-static methods having the following signature:
+//
+// MutexError lock();
+// MutexError trylock();
+// MutexError timedlock(...);
+// MutexError unlock();
+// MutexError reset(); // Used to reset inconsistent robust mutexes.
+//
+// Apart from the above non-static methods, the specializations should
+// also provide few static methods with the following signature:
+//
+// static MutexError init(mtx_t *);
+// static MutexError destroy(mtx_t *);
+//
+// All of the static and non-static methods should ideally be implemented
+// as inline functions so that implementations of public functions can
+// call them without a function call overhead.
+//
+// Another point to keep in mind that is that the libc internally needs a
+// 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 "linux/mutex.h"
+#elif defined(LIBC_TARGET_ARCH_IS_GPU)
+#include "gpu/mutex.h"
+#endif // __linux__
+
+namespace LIBC_NAMESPACE {
+namespace cpp {
+
+// An RAII class for easy locking and unlocking of mutexes.
+class lock_guard {
+  Mutex &mutex;
+
+public:
+  explicit lock_guard(Mutex &m) : mutex(m) { mutex->lock(); }
+
+  ~lock_guard() { mutex->unlock(); }
+
+  // non-copyable
+  lock_guard &operator=(const lock_guard &) = delete;
+  lock_guard(const lock_guard &) = delete;
+};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H

>From 0d98c20934d857be94854a9f60dc308553d428d0 Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 15:23:40 -0700
Subject: [PATCH 02/12] [libc] Added test file

---
 libc/src/__support/CPP/CMakeLists.txt      | 14 +++++---------
 libc/src/__support/CPP/mutex.h             | 18 ++++++------------
 libc/test/src/__support/CPP/CMakeLists.txt | 10 ++++++++++
 libc/test/src/__support/CPP/mutex_test.cpp | 18 ++++++++++++++++++
 4 files changed, 39 insertions(+), 21 deletions(-)
 create mode 100644 libc/test/src/__support/CPP/mutex_test.cpp

diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 9f1fd3671def73..08661aba5b6b18 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -51,15 +51,11 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
-if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.mutex)
-  add_header_library(
-    mutex
-    HDRS
-      mutex.h
-    DEPENDS
-      libc.src.__support.threads.${LIBC_TARGET_OS}.mutex
-  )
-endif()
+add_header_library(
+  mutex
+  HDRS
+    mutex.h
+)
 
 add_header_library(
   span
diff --git a/libc/src/__support/CPP/mutex.h b/libc/src/__support/CPP/mutex.h
index 30d671d7e99f06..72d1b4cc1bd6c5 100644
--- a/libc/src/__support/CPP/mutex.h
+++ b/libc/src/__support/CPP/mutex.h
@@ -1,4 +1,4 @@
-//===--- A platform independent abstraction layer for mutexes ---*- C++ -*-===//
+//===--- A simple std::mutex implementation ---------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -9,8 +9,6 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H
 #define LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H
 
-#include "src/__support/macros/properties/architectures.h"
-
 // Platform independent code will include this header file which pulls
 // the platfrom specific specializations using platform macros.
 //
@@ -37,27 +35,23 @@
 // 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 "linux/mutex.h"
-#elif defined(LIBC_TARGET_ARCH_IS_GPU)
-#include "gpu/mutex.h"
-#endif // __linux__
-
 namespace LIBC_NAMESPACE {
 namespace cpp {
 
 // An RAII class for easy locking and unlocking of mutexes.
+template<typename mutex_type>
 class lock_guard {
-  Mutex &mutex;
-
 public:
-  explicit lock_guard(Mutex &m) : mutex(m) { mutex->lock(); }
+  explicit lock_guard(mutex_type &m) : mutex(m) { mutex->lock(); }
 
   ~lock_guard() { mutex->unlock(); }
 
   // non-copyable
   lock_guard &operator=(const lock_guard &) = delete;
   lock_guard(const lock_guard &) = delete;
+
+private:
+  mutex_type &mutex;
 };
 
 } // namespace cpp
diff --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt
index 708548f812c66c..cec13afc8dd125 100644
--- a/libc/test/src/__support/CPP/CMakeLists.txt
+++ b/libc/test/src/__support/CPP/CMakeLists.txt
@@ -64,6 +64,16 @@ add_libc_test(
     libc.src.__support.macros.properties.types
 )
 
+add_libc_test(
+  mutex_test
+  SUITE
+    libc-cpp-utils-tests
+  SRCS
+    mutex_test.cpp
+  DEPENDS
+    libc.src.__support.CPP.mutex
+)
+
 add_libc_test(
   int_seq_test
   SUITE
diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
new file mode 100644
index 00000000000000..01cb8e1b3beebc
--- /dev/null
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -0,0 +1,18 @@
+//===-- Unittests for 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/CPP/mutex.h"
+#include "test/UnitTest/Test.h"
+
+namespace LIBC_NAMESPACE {
+
+TEST(LlvmLibcMutexTest, Basic) {
+    // ...
+}
+
+} // namespace LIBC_NAMESPACE

>From f75fba7a264979a6e4c91227896c43260b6a3ebb Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 16:32:13 -0700
Subject: [PATCH 03/12] [libc] Changed lock_guard typename for clarity

---
 libc/src/__support/CPP/mutex.h | 37 +++++-----------------------------
 1 file changed, 5 insertions(+), 32 deletions(-)

diff --git a/libc/src/__support/CPP/mutex.h b/libc/src/__support/CPP/mutex.h
index 72d1b4cc1bd6c5..12eb073f480b37 100644
--- a/libc/src/__support/CPP/mutex.h
+++ b/libc/src/__support/CPP/mutex.h
@@ -1,4 +1,4 @@
-//===--- A simple std::mutex implementation ---------------------*- C++ -*-===//
+//===--- A simple lock_guard implementation ---------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -9,49 +9,22 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H
 #define LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H
 
-// Platform independent code will include this header file which pulls
-// the platfrom specific specializations using platform macros.
-//
-// The platform specific specializations should define a class by name
-// Mutex with non-static methods having the following signature:
-//
-// MutexError lock();
-// MutexError trylock();
-// MutexError timedlock(...);
-// MutexError unlock();
-// MutexError reset(); // Used to reset inconsistent robust mutexes.
-//
-// Apart from the above non-static methods, the specializations should
-// also provide few static methods with the following signature:
-//
-// static MutexError init(mtx_t *);
-// static MutexError destroy(mtx_t *);
-//
-// All of the static and non-static methods should ideally be implemented
-// as inline functions so that implementations of public functions can
-// call them without a function call overhead.
-//
-// Another point to keep in mind that is that the libc internally needs a
-// few global locks. So, to avoid static initialization order fiasco, we
-// want the constructors of the Mutex classes to be constexprs.
-
 namespace LIBC_NAMESPACE {
 namespace cpp {
 
 // An RAII class for easy locking and unlocking of mutexes.
-template<typename mutex_type>
+template <typename LockableType>
 class lock_guard {
 public:
-  explicit lock_guard(mutex_type &m) : mutex(m) { mutex->lock(); }
-
-  ~lock_guard() { mutex->unlock(); }
+  explicit lock_guard(LockableType &m) : mutex(m) { mutex.lock(); }
+  ~lock_guard() { mutex.unlock(); }
 
   // non-copyable
   lock_guard &operator=(const lock_guard &) = delete;
   lock_guard(const lock_guard &) = delete;
 
 private:
-  mutex_type &mutex;
+  LockableType &mutex;
 };
 
 } // namespace cpp

>From 5c4e4dd2aa193b9fb48f0297f6065e5a65ecfe4d Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 17:04:19 -0700
Subject: [PATCH 04/12] [libc] Added basic lock_guard test

---
 libc/test/src/__support/CPP/mutex_test.cpp | 26 ++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
index 01cb8e1b3beebc..e594a55a7531c9 100644
--- a/libc/test/src/__support/CPP/mutex_test.cpp
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -9,10 +9,28 @@
 #include "src/__support/CPP/mutex.h"
 #include "test/UnitTest/Test.h"
 
-namespace LIBC_NAMESPACE {
+using LIBC_NAMESPACE::cpp::lock_guard;
+
+// Simple class for testing cpp::lock_guard. It defines methods 'lock' and 
+// 'unlock' which are required for the cpp::lock_guard class template.
+class LockableObject {
+    bool locked;
+
+public:
+    LockableObject() : locked(false) {}
+    void lock() { locked = true; }
+    void unlock() { locked = false; }
+    bool is_locked() { return locked; }
+};
 
 TEST(LlvmLibcMutexTest, Basic) {
-    // ...
-}
+    LockableObject obj;
+    ASSERT_FALSE(obj.is_locked());
 
-} // namespace LIBC_NAMESPACE
+    {
+        lock_guard lg(obj);
+        ASSERT_TRUE(obj.is_locked());
+    }
+
+    ASSERT_FALSE(obj.is_locked());
+}

>From 30d9cb62f5425007af3a1f3cf1d04777f74c33dc Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 17:23:16 -0700
Subject: [PATCH 05/12] [libc] Added template argument in mutex_test.cpp

---
 libc/test/src/__support/CPP/mutex_test.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
index e594a55a7531c9..dc346255d74c6f 100644
--- a/libc/test/src/__support/CPP/mutex_test.cpp
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -28,7 +28,7 @@ TEST(LlvmLibcMutexTest, Basic) {
     ASSERT_FALSE(obj.is_locked());
 
     {
-        lock_guard lg(obj);
+        lock_guard<LockableObject> lg(obj);
         ASSERT_TRUE(obj.is_locked());
     }
 

>From 5cba525e43281bc080360f414b7754b8c65eec8a Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 17:51:41 -0700
Subject: [PATCH 06/12] [libc] Improved mutex_test.cpp

---
 libc/test/src/__support/CPP/mutex_test.cpp | 37 +++++++++++++++-------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
index dc346255d74c6f..8150ffe6b430ba 100644
--- a/libc/test/src/__support/CPP/mutex_test.cpp
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -13,24 +13,37 @@ using LIBC_NAMESPACE::cpp::lock_guard;
 
 // Simple class for testing cpp::lock_guard. It defines methods 'lock' and 
 // 'unlock' which are required for the cpp::lock_guard class template.
-class LockableObject {
-    bool locked;
+struct Mutex {
+    Mutex() : locked(false) {}
+
+    void lock() {
+        if (locked)
+            // Sends signal 6.
+            abort();
+        locked = true;
+    }
 
-public:
-    LockableObject() : locked(false) {}
-    void lock() { locked = true; }
-    void unlock() { locked = false; }
-    bool is_locked() { return locked; }
+    void unlock() { 
+        if (!locked)
+            // Sends signal 6.
+            abort();
+        locked = false;
+    }
+
+    bool locked;
 };
 
 TEST(LlvmLibcMutexTest, Basic) {
-    LockableObject obj;
-    ASSERT_FALSE(obj.is_locked());
+    Mutex m;
+    ASSERT_FALSE(m.locked);
+
+    const int SIGABRT = 5;
 
     {
-        lock_guard<LockableObject> lg(obj);
-        ASSERT_TRUE(obj.is_locked());
+        lock_guard<Mutex> lg(m);
+        ASSERT_TRUE(m.locked);
+        ASSERT_DEATH([&](){ lock_guard<Mutex> lg2(m); }, SIGABRT);
     }
 
-    ASSERT_FALSE(obj.is_locked());
+    ASSERT_FALSE(m.locked);
 }

>From f17ff1c28a1dd24d5ffb260512367abf45c60903 Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 19:11:51 -0700
Subject: [PATCH 07/12] [libc] Replace references to `MutexLock` with
 `cpp::lock_guard`

---
 libc/src/__support/File/CMakeLists.txt        |  1 +
 libc/src/__support/File/dir.cpp               |  5 +++--
 libc/src/__support/threads/CMakeLists.txt     |  2 ++
 libc/src/__support/threads/fork_callbacks.cpp |  9 +++++----
 libc/src/__support/threads/thread.cpp         | 11 ++++++-----
 libc/src/stdlib/CMakeLists.txt                |  1 +
 libc/src/stdlib/atexit.cpp                    |  3 ++-
 libc/src/threads/linux/CMakeLists.txt         |  1 +
 libc/src/threads/linux/CndVar.h               |  5 +++--
 libc/test/src/__support/CPP/mutex_test.cpp    |  4 ++--
 10 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/libc/src/__support/File/CMakeLists.txt b/libc/src/__support/File/CMakeLists.txt
index b7c0612096aa9f..0416ac2cc902e7 100644
--- a/libc/src/__support/File/CMakeLists.txt
+++ b/libc/src/__support/File/CMakeLists.txt
@@ -25,6 +25,7 @@ add_object_library(
   HDRS
     dir.h
   DEPENDS
+    libc.src.__support.CPP.mutex
     libc.src.__support.CPP.new
     libc.src.__support.CPP.span
     libc.src.__support.threads.mutex
diff --git a/libc/src/__support/File/dir.cpp b/libc/src/__support/File/dir.cpp
index 9ff639a777e234..0aa217b62abe55 100644
--- a/libc/src/__support/File/dir.cpp
+++ b/libc/src/__support/File/dir.cpp
@@ -8,6 +8,7 @@
 
 #include "dir.h"
 
+#include "src/__support/CPP/mutex.h" // For lock_guard
 #include "src/__support/CPP/new.h"
 #include "src/__support/error_or.h"
 #include "src/errno/libc_errno.h" // For error macros
@@ -27,7 +28,7 @@ ErrorOr<Dir *> Dir::open(const char *path) {
 }
 
 ErrorOr<struct ::dirent *> Dir::read() {
-  MutexLock lock(&mutex);
+  cpp::lock_guard<Mutex> lock(mutex);
   if (readptr >= fillsize) {
     auto readsize = platform_fetch_dirents(fd, buffer);
     if (!readsize)
@@ -51,7 +52,7 @@ ErrorOr<struct ::dirent *> Dir::read() {
 
 int Dir::close() {
   {
-    MutexLock lock(&mutex);
+    cpp::lock_guard<Mutex> lock(mutex);
     int retval = platform_closedir(fd);
     if (retval != 0)
       return retval;
diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt
index 731adf6f9c8e4e..34412be4dfed6f 100644
--- a/libc/src/__support/threads/CMakeLists.txt
+++ b/libc/src/__support/threads/CMakeLists.txt
@@ -31,6 +31,7 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.mutex)
       fork_callbacks.h
     DEPENDS
       .mutex
+      libc.src.__support.CPP.mutex
   )
 endif()
 
@@ -57,6 +58,7 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.thread)
       libc.src.__support.common
       libc.src.__support.fixedvector
       libc.src.__support.CPP.array
+      libc.src.__support.CPP.mutex
       libc.src.__support.CPP.optional
   )
 endif()
diff --git a/libc/src/__support/threads/fork_callbacks.cpp b/libc/src/__support/threads/fork_callbacks.cpp
index 54fda676f281ed..99990a6c41a29d 100644
--- a/libc/src/__support/threads/fork_callbacks.cpp
+++ b/libc/src/__support/threads/fork_callbacks.cpp
@@ -8,6 +8,7 @@
 
 #include "fork_callbacks.h"
 
+#include "src/__support/CPP/mutex.h" // For lock_guard
 #include "src/__support/threads/mutex.h"
 
 #include <stddef.h> // For size_t
@@ -35,7 +36,7 @@ class AtForkCallbackManager {
   constexpr AtForkCallbackManager() : mtx(false, false, false), next_index(0) {}
 
   bool register_triple(const ForkCallbackTriple &triple) {
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     if (next_index >= CALLBACK_SIZE)
       return false;
     list[next_index] = triple;
@@ -44,7 +45,7 @@ class AtForkCallbackManager {
   }
 
   void invoke_prepare() {
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     for (size_t i = 0; i < next_index; ++i) {
       auto prepare = list[i].prepare;
       if (prepare)
@@ -53,7 +54,7 @@ class AtForkCallbackManager {
   }
 
   void invoke_parent() {
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     for (size_t i = 0; i < next_index; ++i) {
       auto parent = list[i].parent;
       if (parent)
@@ -62,7 +63,7 @@ class AtForkCallbackManager {
   }
 
   void invoke_child() {
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     for (size_t i = 0; i < next_index; ++i) {
       auto child = list[i].child;
       if (child)
diff --git a/libc/src/__support/threads/thread.cpp b/libc/src/__support/threads/thread.cpp
index 62aa86b7aef708..0fba2ddfb63432 100644
--- a/libc/src/__support/threads/thread.cpp
+++ b/libc/src/__support/threads/thread.cpp
@@ -10,6 +10,7 @@
 #include "mutex.h"
 
 #include "src/__support/CPP/array.h"
+#include "src/__support/CPP/mutex.h" // For lock_guard
 #include "src/__support/CPP/optional.h"
 #include "src/__support/fixedvector.h"
 #include "src/__support/macros/attributes.h"
@@ -56,7 +57,7 @@ class TSSKeyMgr {
   constexpr TSSKeyMgr() : mtx(false, false, false) {}
 
   cpp::optional<unsigned int> new_key(TSSDtor *dtor) {
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     for (unsigned int i = 0; i < TSS_KEY_COUNT; ++i) {
       TSSKeyUnit &u = units[i];
       if (!u.active) {
@@ -70,20 +71,20 @@ class TSSKeyMgr {
   TSSDtor *get_dtor(unsigned int key) {
     if (key >= TSS_KEY_COUNT)
       return nullptr;
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     return units[key].dtor;
   }
 
   bool remove_key(unsigned int key) {
     if (key >= TSS_KEY_COUNT)
       return false;
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     units[key].reset();
     return true;
   }
 
   bool is_valid_key(unsigned int key) {
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     return units[key].active;
   }
 };
@@ -113,7 +114,7 @@ class ThreadAtExitCallbackMgr {
   constexpr ThreadAtExitCallbackMgr() : mtx(false, false, false) {}
 
   int add_callback(AtExitCallback *callback, void *obj) {
-    MutexLock lock(&mtx);
+    cpp::lock_guard<Mutex> lock(mtx);
     return callback_list.push_back({callback, obj});
   }
 
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index e526ba040befb7..9b76a6a0f85757 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -414,6 +414,7 @@ add_entrypoint_object(
   CXX_STANDARD
     20 # For constinit of the atexit callback list.
   DEPENDS
+    libc.src.__support.CPP.mutex
     libc.src.__support.CPP.new
     libc.src.__support.OSUtil.osutil
     libc.src.__support.blockstore
diff --git a/libc/src/stdlib/atexit.cpp b/libc/src/stdlib/atexit.cpp
index fa072b2fdf8d09..0dec3af786fb1d 100644
--- a/libc/src/stdlib/atexit.cpp
+++ b/libc/src/stdlib/atexit.cpp
@@ -9,6 +9,7 @@
 #include "src/stdlib/atexit.h"
 #include "src/__support/blockstore.h"
 #include "src/__support/common.h"
+#include "src/__support/CPP/mutex.h" // For lock_guard
 #include "src/__support/fixedvector.h"
 #include "src/__support/threads/mutex.h"
 
@@ -68,7 +69,7 @@ void call_exit_callbacks() {
 }
 
 int add_atexit_unit(const AtExitUnit &unit) {
-  MutexLock lock(&handler_list_mtx);
+  cpp::lock_guard<Mutex> lock(handler_list_mtx);
   if (exit_callbacks.push_back(unit))
     return 0;
   return -1;
diff --git a/libc/src/threads/linux/CMakeLists.txt b/libc/src/threads/linux/CMakeLists.txt
index be5407031aaddb..f32d24f01f86f7 100644
--- a/libc/src/threads/linux/CMakeLists.txt
+++ b/libc/src/threads/linux/CMakeLists.txt
@@ -7,6 +7,7 @@ add_header_library(
     libc.include.sys_syscall
     libc.include.threads
     libc.src.__support.CPP.atomic
+    libc.src.__support.CPP.mutex
     libc.src.__support.OSUtil.osutil
     libc.src.__support.threads.mutex
     libc.src.__support.threads.linux.futex_word_type
diff --git a/libc/src/threads/linux/CndVar.h b/libc/src/threads/linux/CndVar.h
index b4afdef9f9eba7..4ab52156bb4e3a 100644
--- a/libc/src/threads/linux/CndVar.h
+++ b/libc/src/threads/linux/CndVar.h
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_SRC_THREADS_LINUX_CNDVAR_H
 
 #include "src/__support/CPP/atomic.h"
+#include "src/__support/CPP/mutex.h" // For lock_guard
 #include "src/__support/OSUtil/syscall.h" // For syscall functions.
 #include "src/__support/threads/linux/futex_word.h"
 #include "src/__support/threads/mutex.h"
@@ -58,7 +59,7 @@ struct CndVar {
 
     CndWaiter waiter;
     {
-      MutexLock ml(&qmtx);
+      cpp::lock_guard<Mutex> ml(qmtx);
       CndWaiter *old_back = nullptr;
       if (waitq_front == nullptr) {
         waitq_front = waitq_back = &waiter;
@@ -117,7 +118,7 @@ struct CndVar {
   }
 
   int broadcast() {
-    MutexLock ml(&qmtx);
+    cpp::lock_guard<Mutex> ml(qmtx);
     uint32_t dummy_futex_word;
     CndWaiter *waiter = waitq_front;
     waitq_front = waitq_back = nullptr;
diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
index 8150ffe6b430ba..b7725cc3f1bc4f 100644
--- a/libc/test/src/__support/CPP/mutex_test.cpp
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -11,6 +11,8 @@
 
 using LIBC_NAMESPACE::cpp::lock_guard;
 
+static const int SIGABRT = 6;
+
 // Simple class for testing cpp::lock_guard. It defines methods 'lock' and 
 // 'unlock' which are required for the cpp::lock_guard class template.
 struct Mutex {
@@ -37,8 +39,6 @@ TEST(LlvmLibcMutexTest, Basic) {
     Mutex m;
     ASSERT_FALSE(m.locked);
 
-    const int SIGABRT = 5;
-
     {
         lock_guard<Mutex> lg(m);
         ASSERT_TRUE(m.locked);

>From 5572fd786defcda893f9ba34459eb0d3e9a15d7a Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 19:21:12 -0700
Subject: [PATCH 08/12] [libc] Ran `clang-format`

---
 libc/src/stdlib/atexit.cpp      | 2 +-
 libc/src/threads/linux/CndVar.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/src/stdlib/atexit.cpp b/libc/src/stdlib/atexit.cpp
index 0dec3af786fb1d..85235f20c674c6 100644
--- a/libc/src/stdlib/atexit.cpp
+++ b/libc/src/stdlib/atexit.cpp
@@ -7,9 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/stdlib/atexit.h"
+#include "src/__support/CPP/mutex.h" // For lock_guard
 #include "src/__support/blockstore.h"
 #include "src/__support/common.h"
-#include "src/__support/CPP/mutex.h" // For lock_guard
 #include "src/__support/fixedvector.h"
 #include "src/__support/threads/mutex.h"
 
diff --git a/libc/src/threads/linux/CndVar.h b/libc/src/threads/linux/CndVar.h
index 4ab52156bb4e3a..fb0de8780cd767 100644
--- a/libc/src/threads/linux/CndVar.h
+++ b/libc/src/threads/linux/CndVar.h
@@ -10,7 +10,7 @@
 #define LLVM_LIBC_SRC_THREADS_LINUX_CNDVAR_H
 
 #include "src/__support/CPP/atomic.h"
-#include "src/__support/CPP/mutex.h" // For lock_guard
+#include "src/__support/CPP/mutex.h"      // For lock_guard
 #include "src/__support/OSUtil/syscall.h" // For syscall functions.
 #include "src/__support/threads/linux/futex_word.h"
 #include "src/__support/threads/mutex.h"

>From c6528edb74581ecae10c0bdcc9d6aafee7c876ac Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 19:25:48 -0700
Subject: [PATCH 09/12] [libc] `clang-format` on mutex_test.cpp

---
 libc/test/src/__support/CPP/mutex_test.cpp | 46 +++++++++++-----------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
index b7725cc3f1bc4f..0c4a29e519b29d 100644
--- a/libc/test/src/__support/CPP/mutex_test.cpp
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -16,33 +16,33 @@ static const int SIGABRT = 6;
 // Simple class for testing cpp::lock_guard. It defines methods 'lock' and 
 // 'unlock' which are required for the cpp::lock_guard class template.
 struct Mutex {
-    Mutex() : locked(false) {}
-
-    void lock() {
-        if (locked)
-            // Sends signal 6.
-            abort();
-        locked = true;
-    }
-
-    void unlock() { 
-        if (!locked)
-            // Sends signal 6.
-            abort();
-        locked = false;
-    }
-
-    bool locked;
+  Mutex() : locked(false) {}
+
+  void lock() {
+    if (locked)
+      // Sends signal 6.
+      abort();
+    locked = true;
+  }
+
+  void unlock() {
+    if (!locked)
+      // Sends signal 6.
+      abort();
+    locked = false;
+  }
+
+  bool locked;
 };
 
 TEST(LlvmLibcMutexTest, Basic) {
-    Mutex m;
-    ASSERT_FALSE(m.locked);
+  Mutex m;
+  ASSERT_FALSE(m.locked);
 
-    {
-        lock_guard<Mutex> lg(m);
-        ASSERT_TRUE(m.locked);
-        ASSERT_DEATH([&](){ lock_guard<Mutex> lg2(m); }, SIGABRT);
+  {
+    lock_guard<Mutex> lg(m);
+    ASSERT_TRUE(m.locked);
+    ASSERT_DEATH([&]() { lock_guard<Mutex> lg2(m); }, SIGABRT);
     }
 
     ASSERT_FALSE(m.locked);

>From 9bc3554ffdcb46d7f65e6c5ad5d97785aad835e2 Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 19:26:56 -0700
Subject: [PATCH 10/12] [libc] More `clang-format`

---
 libc/src/__support/CPP/mutex.h             | 3 +--
 libc/test/src/__support/CPP/mutex_test.cpp | 6 +++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/CPP/mutex.h b/libc/src/__support/CPP/mutex.h
index 12eb073f480b37..b88b6b4dd9611e 100644
--- a/libc/src/__support/CPP/mutex.h
+++ b/libc/src/__support/CPP/mutex.h
@@ -13,8 +13,7 @@ namespace LIBC_NAMESPACE {
 namespace cpp {
 
 // An RAII class for easy locking and unlocking of mutexes.
-template <typename LockableType>
-class lock_guard {
+template <typename LockableType> class lock_guard {
 public:
   explicit lock_guard(LockableType &m) : mutex(m) { mutex.lock(); }
   ~lock_guard() { mutex.unlock(); }
diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
index 0c4a29e519b29d..50c3beab20fa4c 100644
--- a/libc/test/src/__support/CPP/mutex_test.cpp
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -13,7 +13,7 @@ using LIBC_NAMESPACE::cpp::lock_guard;
 
 static const int SIGABRT = 6;
 
-// Simple class for testing cpp::lock_guard. It defines methods 'lock' and 
+// Simple class for testing cpp::lock_guard. It defines methods 'lock' and
 // 'unlock' which are required for the cpp::lock_guard class template.
 struct Mutex {
   Mutex() : locked(false) {}
@@ -43,7 +43,7 @@ TEST(LlvmLibcMutexTest, Basic) {
     lock_guard<Mutex> lg(m);
     ASSERT_TRUE(m.locked);
     ASSERT_DEATH([&]() { lock_guard<Mutex> lg2(m); }, SIGABRT);
-    }
+  }
 
-    ASSERT_FALSE(m.locked);
+  ASSERT_FALSE(m.locked);
 }

>From 5f7c3bc4a90d3ae07b9eb27cf2981b69a9f801fb Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 19:55:45 -0700
Subject: [PATCH 11/12] [libc] Implemented `lock_guard` constructor for locked
 mutexes

---
 libc/src/__support/CPP/mutex.h             | 21 +++++++++++++++++----
 libc/test/src/__support/CPP/mutex_test.cpp | 16 ++++++++++++++++
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/CPP/mutex.h b/libc/src/__support/CPP/mutex.h
index b88b6b4dd9611e..f1a460686ada37 100644
--- a/libc/src/__support/CPP/mutex.h
+++ b/libc/src/__support/CPP/mutex.h
@@ -12,18 +12,31 @@
 namespace LIBC_NAMESPACE {
 namespace cpp {
 
+// Assume the calling thread has already obtained mutex ownership.
+struct adopt_lock_t { explicit adopt_lock_t() = default; };
+
+// Tag used to make a scoped lock take ownership of a locked mutex.
+constexpr adopt_lock_t	adopt_lock { };
+
 // An RAII class for easy locking and unlocking of mutexes.
-template <typename LockableType> class lock_guard {
+template <typename MutexType> class lock_guard {
 public:
-  explicit lock_guard(LockableType &m) : mutex(m) { mutex.lock(); }
+  // Calls `m.lock()` upon resource acquisition.
+  explicit lock_guard(MutexType &m) : mutex(m) { mutex.lock(); }
+
+  // Acquires ownership of the mutex object `m` without attempting to lock
+  // it. The behavior is undefined if the current thread does not hold the
+  // lock on `m`.
+  lock_guard(MutexType &m, adopt_lock_t t) : mutex(m) {}
+
   ~lock_guard() { mutex.unlock(); }
 
+private:
   // non-copyable
   lock_guard &operator=(const lock_guard &) = delete;
   lock_guard(const lock_guard &) = delete;
 
-private:
-  LockableType &mutex;
+  MutexType &mutex;
 };
 
 } // namespace cpp
diff --git a/libc/test/src/__support/CPP/mutex_test.cpp b/libc/test/src/__support/CPP/mutex_test.cpp
index 50c3beab20fa4c..858e1ff22bf5d5 100644
--- a/libc/test/src/__support/CPP/mutex_test.cpp
+++ b/libc/test/src/__support/CPP/mutex_test.cpp
@@ -9,6 +9,7 @@
 #include "src/__support/CPP/mutex.h"
 #include "test/UnitTest/Test.h"
 
+using LIBC_NAMESPACE::cpp::adopt_lock;
 using LIBC_NAMESPACE::cpp::lock_guard;
 
 static const int SIGABRT = 6;
@@ -47,3 +48,18 @@ TEST(LlvmLibcMutexTest, Basic) {
 
   ASSERT_FALSE(m.locked);
 }
+
+TEST(LlvmLibcMutexTest, AcquireLocked) {
+  Mutex m;
+  ASSERT_FALSE(m.locked);
+
+  m.lock();
+  ASSERT_TRUE(m.locked);
+
+  {
+    lock_guard<Mutex> lg(m, adopt_lock);
+    ASSERT_TRUE(m.locked);
+  }
+
+  ASSERT_FALSE(m.locked);
+}

>From 4ef858e6242b2dc26174f7407f5812e4a8b30b48 Mon Sep 17 00:00:00 2001
From: Vladimir Mishel <vmishel at outlook.com>
Date: Thu, 18 Apr 2024 19:56:23 -0700
Subject: [PATCH 12/12] [libc] `clang-format` on mutex.h

---
 libc/src/__support/CPP/mutex.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/CPP/mutex.h b/libc/src/__support/CPP/mutex.h
index f1a460686ada37..4d50f85e345f9f 100644
--- a/libc/src/__support/CPP/mutex.h
+++ b/libc/src/__support/CPP/mutex.h
@@ -13,10 +13,12 @@ namespace LIBC_NAMESPACE {
 namespace cpp {
 
 // Assume the calling thread has already obtained mutex ownership.
-struct adopt_lock_t { explicit adopt_lock_t() = default; };
+struct adopt_lock_t {
+  explicit adopt_lock_t() = default;
+};
 
 // Tag used to make a scoped lock take ownership of a locked mutex.
-constexpr adopt_lock_t	adopt_lock { };
+constexpr adopt_lock_t adopt_lock{};
 
 // An RAII class for easy locking and unlocking of mutexes.
 template <typename MutexType> class lock_guard {



More information about the libc-commits mailing list