[libc-commits] [libc] [WIP] implement recursive mutex and deadlock detection (PR #133258)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Thu Mar 27 07:41:02 PDT 2025
https://github.com/SchrodingerZhu created https://github.com/llvm/llvm-project/pull/133258
None
>From 751de535e219cbd98c2e90500a8ab57d6782932d Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Thu, 27 Mar 2025 10:40:13 -0400
Subject: [PATCH] [WIP] implement recursive mutex and deadlock detection
---
.../__support/threads/linux/CMakeLists.txt | 1 +
libc/src/__support/threads/linux/mutex.h | 51 +++++++++++++++++--
libc/src/__support/threads/mutex_common.h | 2 +
3 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt
index 364e7e2b90585..ba25f9b6a75fc 100644
--- a/libc/src/__support/threads/linux/CMakeLists.txt
+++ b/libc/src/__support/threads/linux/CMakeLists.txt
@@ -69,6 +69,7 @@ add_header_library(
.futex_utils
.raw_mutex
libc.src.__support.threads.mutex_common
+ libc.src.__support.threads.identifier
)
add_object_library(
diff --git a/libc/src/__support/threads/linux/mutex.h b/libc/src/__support/threads/linux/mutex.h
index 0c4b1ae09af6f..e161159ec06e5 100644
--- a/libc/src/__support/threads/linux/mutex.h
+++ b/libc/src/__support/threads/linux/mutex.h
@@ -13,6 +13,7 @@
#include "src/__support/CPP/optional.h"
#include "src/__support/libc_assert.h"
#include "src/__support/macros/config.h"
+#include "src/__support/threads/identifier.h"
#include "src/__support/threads/linux/futex_utils.h"
#include "src/__support/threads/linux/raw_mutex.h"
#include "src/__support/threads/mutex_common.h"
@@ -31,6 +32,25 @@ class Mutex final : private RawMutex {
pid_t owner;
unsigned long long lock_count;
+ LIBC_INLINE bool increase_lock_count() {
+ if (__builtin_add_overflow(this->lock_count, 1, &this->lock_count))
+ return false;
+ return true;
+ }
+
+ LIBC_INLINE MutexError recursive_lock() {
+ if (!this->recursive)
+ return MutexError::DEADLOCK;
+ if (increase_lock_count())
+ return MutexError::NONE;
+ return MutexError::MAX_RECURSION;
+ }
+
+ LIBC_INLINE void post_raw_lock() {
+ this->lock_count++;
+ this->owner = internal::gettid();
+ }
+
public:
LIBC_INLINE constexpr Mutex(bool is_timed, bool is_recursive, bool is_robust,
bool is_pshared)
@@ -56,29 +76,50 @@ class Mutex final : private RawMutex {
return MutexError::NONE;
}
- // TODO: record owner and lock count.
LIBC_INLINE MutexError lock() {
+ if (this->owner == internal::gettid())
+ return recursive_lock();
// Since timeout is not specified, we do not need to check the return value.
this->RawMutex::lock(
/* timeout=*/cpp::nullopt, this->pshared);
+ post_raw_lock();
return MutexError::NONE;
}
- // TODO: record owner and lock count.
LIBC_INLINE MutexError timed_lock(internal::AbsTimeout abs_time) {
- if (this->RawMutex::lock(abs_time, this->pshared))
+ if (this->owner == internal::gettid())
+ return recursive_lock();
+ if (this->RawMutex::lock(abs_time, this->pshared)) {
+ post_raw_lock();
return MutexError::NONE;
+ }
return MutexError::TIMEOUT;
}
LIBC_INLINE MutexError unlock() {
- if (this->RawMutex::unlock(this->pshared))
+ if (this->owner != internal::gettid())
+ return MutexError::UNLOCK_WITHOUT_LOCK;
+
+ if (this->lock_count > 1) {
+ this->lock_count--;
return MutexError::NONE;
- return MutexError::UNLOCK_WITHOUT_LOCK;
+ }
+
+ // no longer holding the lock
+ if (this->RawMutex::unlock(this->pshared)) {
+ this->lock_count--;
+ this->owner = 0;
+ return MutexError::NONE;
+ }
+
+ // memory corrupted
+ return MutexError::BAD_LOCK_STATE;
}
// TODO: record owner and lock count.
LIBC_INLINE MutexError try_lock() {
+ if (this->owner == internal::gettid())
+ return recursive_lock();
if (this->RawMutex::try_lock())
return MutexError::NONE;
return MutexError::BUSY;
diff --git a/libc/src/__support/threads/mutex_common.h b/libc/src/__support/threads/mutex_common.h
index 9913f69a6a61a..c849420d0d50f 100644
--- a/libc/src/__support/threads/mutex_common.h
+++ b/libc/src/__support/threads/mutex_common.h
@@ -19,6 +19,8 @@ enum class MutexError : int {
TIMEOUT,
UNLOCK_WITHOUT_LOCK,
BAD_LOCK_STATE,
+ DEADLOCK,
+ MAX_RECURSION,
};
} // namespace LIBC_NAMESPACE_DECL
More information about the libc-commits
mailing list