Skip to content

[libc] implement pthread_mutex_trylock #93359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

changkhothuychung
Copy link
Contributor

fix issue #85278

@llvmbot llvmbot added the libc label May 25, 2024
@llvmbot
Copy link
Member

llvmbot commented May 25, 2024

@llvm/pr-subscribers-libc

Author: Nhat Nguyen (changkhothuychung)

Changes

fix issue #85278


Full diff: https://github.com/llvm/llvm-project/pull/93359.diff

1 Files Affected:

  • (modified) libc/src/__support/threads/linux/mutex.h (+21-1)
diff --git a/libc/src/__support/threads/linux/mutex.h b/libc/src/__support/threads/linux/mutex.h
index 6702de4651686..c7f9b4f320dc3 100644
--- a/libc/src/__support/threads/linux/mutex.h
+++ b/libc/src/__support/threads/linux/mutex.h
@@ -116,7 +116,27 @@ struct Mutex {
     }
   }
 
-  MutexError trylock();
+  MutexError trylock() {
+    FutexWordType mutex_status = FutexWordType(LockState::Free);
+    FutexWordType locked_status = FutexWordType(LockState::Locked);
+
+    if (futex_word.compare_exchange_strong(mutex_status,
+                                           FutexWordType(LockState::Locked))) {
+      return MutexError::NONE;
+    }
+
+    switch (LockState(mutex_status)) {
+    case LockState::Locked:
+      if (recursive && this == owner) {
+        lock_count++;
+        return MutexError::NONE;
+      }
+
+    case LockState::Free:
+      // If it was LockState::Free, we shouldn't be here at all.
+      return MutexError::BAD_LOCK_STATE;
+    }
+  }
 };
 
 } // namespace LIBC_NAMESPACE

@SchrodingerZhu
Copy link
Contributor

SchrodingerZhu commented May 25, 2024

I think this will conflict with the mutex rework. I will get that part fixed over the weekend. Sorry for that PR lasting longer than I have expected. My jet lag does not agree with me when coding at night 🤦.

@changkhothuychung
Copy link
Contributor Author

I think this will conflict with the mutex rework. I will get that part fixed over the weekend. Sorry for that PR lasting longer than I have expected. My jet lag does not agree with me when coding at night 🤦.

which PR are you referring to? can u send me the link here? Im not aware of that.

Copy link
Member

@nickdesaulniers nickdesaulniers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs unit tests. If you implement
C11 https://en.cppreference.com/w/c/thread/mtx_trylock in terms of this, then you can test it in test/integration/src/threads/mtx_test.cpp. I'd test an uncontended and a contended vanilla Mutex to start with.

Comment on lines +123 to +126
if (futex_word.compare_exchange_strong(mutex_status,
FutexWordType(LockState::Locked))) {
return MutexError::NONE;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (futex_word.compare_exchange_strong(mutex_status,
FutexWordType(LockState::Locked))) {
return MutexError::NONE;
}
if (futex_word.compare_exchange_strong(mutex_status,
FutexWordType(LockState::Locked)))
return MutexError::NONE;

https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements

MutexError trylock();
MutexError trylock() {
FutexWordType mutex_status = FutexWordType(LockState::Free);
FutexWordType locked_status = FutexWordType(LockState::Locked);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable appears unused?

Comment on lines +130 to +132
if (recursive && this == owner) {
lock_count++;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (recursive && this == owner) {
lock_count++;
}
if (recursive && this == owner)
lock_count++;

Though I think we don't care what the resulting mutex_status value is if it's NOT Lock state::Locked, we should simply return MutexError::BUSY;.

@SchrodingerZhu
Copy link
Contributor

@nickdesaulniers I hope to put a pause to this PR since my mutex patch actually exposes try_lock api. (Sorry again for such conflicts.) It is okay to discuss suggested changes but please keep in mind that the implementation of try_lock using strong CAS may be already covered in another PR in flight.

It can be valuable if you can extend this PR to actually implement the POSIX API and provide test cases for that API.

@apparentlymart
Copy link

I found myself here while trying to understand the current implementation status of the POSIX threads API, so I'm really just a random passer-by here, but FWIW I saw the two mentions of a mutex rework patch above without any direct link to the relevant change and so I went digging and I'm guessing that was referring to #92168, in which case that has now been merged and does appear to include an implementation of try_lock for Linux, here:

LIBC_INLINE MutexError try_lock() {
if (this->RawMutex::try_lock())
return MutexError::NONE;
return MutexError::BUSY;
}

[[nodiscard]] LIBC_INLINE bool try_lock() {
FutexWordType expected = UNLOCKED;
// Use strong version since this is a one-time operation.
return futex.compare_exchange_strong(
expected, LOCKED, cpp::MemoryOrder::ACQUIRE, cpp::MemoryOrder::RELAXED);
}

However, as far as I can tell there is still (in main at the time of writing this comment) not an entrypoint for pthread_mutex_trylock, and so this PR could still potentially add that in terms of the Mutex::try_lock function as described in the previous comment.

I'm just sharing this in case it's useful to a future visitor to this PR. I'm sorry if anything I said here is inaccurate.

@SchrodingerZhu
Copy link
Contributor

@apparentlymart Thank you for the nice summary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants