[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