[libc-commits] [libc] [libc] implement recursive mutex and fix wrong initializer (PR #193992)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Mon Apr 27 13:53:39 PDT 2026


================
@@ -143,6 +156,79 @@ void trylock_test() {
   LIBC_NAMESPACE::pthread_mutex_destroy(&trylock_mutex);
 }
 
+void *trylock_other_thread(void *arg) {
+  auto *mutex = reinterpret_cast<pthread_mutex_t *>(arg);
+  int result = LIBC_NAMESPACE::pthread_mutex_trylock(mutex);
+  if (result == 0)
+    ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(mutex), 0);
+  return reinterpret_cast<void *>(uintptr_t(result));
+}
+
+void recursive_mutex_test() {
+  pthread_mutexattr_t attr;
+  pthread_mutex_t recursive_mutex;
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutexattr_init(&attr), 0);
+  ASSERT_EQ(
+      LIBC_NAMESPACE::pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE),
+      0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&recursive_mutex, &attr), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutexattr_destroy(&attr), 0);
+
+  pthread_mutex_t snapshot = snapshot_mutex(&recursive_mutex);
+  ASSERT_TRUE(snapshot.__recursive);
+  ASSERT_EQ(snapshot.__owner, 0);
+  ASSERT_EQ(snapshot.__lock_count, size_t(0));
+
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&recursive_mutex), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&recursive_mutex), 0);
+
+  pthread_t thread;
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_create(
+                &thread, nullptr, trylock_other_thread, &recursive_mutex),
+            0);
+  void *retval = nullptr;
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_join(thread, &retval), 0);
+  ASSERT_EQ(uintptr_t(retval), uintptr_t(EBUSY));
+
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&recursive_mutex), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&recursive_mutex), 0);
+  snapshot = snapshot_mutex(&recursive_mutex);
+  ASSERT_EQ(snapshot.__owner, 0);
+  ASSERT_EQ(snapshot.__lock_count, size_t(0));
+
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_trylock(&recursive_mutex), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&recursive_mutex), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_destroy(&recursive_mutex), 0);
+}
+
+void initializer_acts_the_same_as_null_attr() {
+  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+  pthread_mutex_t mutex_from_init;
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&mutex_from_init, nullptr), 0);
+
+  pthread_mutex_t mutex_snapshot = snapshot_mutex(&mutex);
+  pthread_mutex_t mutex_from_init_snapshot = snapshot_mutex(&mutex_from_init);
+  ASSERT_EQ(mutex_snapshot.__ftxw.__word,
+            mutex_from_init_snapshot.__ftxw.__word);
+  ASSERT_EQ(mutex_snapshot.__priority_inherit,
+            mutex_from_init_snapshot.__priority_inherit);
+  ASSERT_EQ(mutex_snapshot.__recursive, mutex_from_init_snapshot.__recursive);
+  ASSERT_EQ(mutex_snapshot.__robust, mutex_from_init_snapshot.__robust);
+  ASSERT_EQ(mutex_snapshot.__pshared, mutex_from_init_snapshot.__pshared);
+  ASSERT_EQ(mutex_snapshot.__owner, mutex_from_init_snapshot.__owner);
+  ASSERT_EQ(mutex_snapshot.__lock_count, mutex_from_init_snapshot.__lock_count);
----------------
SchrodingerZhu wrote:

This is just test that INITIALIZER is the same as null attribute initialization, which is in the spec. 

May be I should change this to bytewise memcmp. 

https://github.com/llvm/llvm-project/pull/193992


More information about the libc-commits mailing list