[libc-commits] [libc] [libc][semaphore] Add post and wait operations for internal semaphore (PR #198959)
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Fri Jun 12 12:53:13 PDT 2026
================
@@ -54,6 +81,83 @@ class Semaphore {
const_cast<Futex &>(value).load(cpp::MemoryOrder::RELAXED));
}
+ // Atomically increments the semaphore value and
+ // wakes one blocked waiter if any.
+ LIBC_INLINE int post() {
+ FutexWordType v = value.load(cpp::MemoryOrder::RELAXED);
+
+ do {
+ if (v >= SEM_VALUE_MAX)
+ return EOVERFLOW;
+ // RELEASE on success, since post should publish prior writes
+ // RELAXED on failure, since no synchronization event occurs
+ } while (!value.compare_exchange_weak(v, v + 1, cpp::MemoryOrder::RELEASE,
+ cpp::MemoryOrder::RELAXED));
+
+ // Wake one waiter if any,
+ // waiter selection is left to linux futex implementation.
+ value.notify_one(is_shared);
+ return 0;
+ }
+
+ // Attempts to decrement the semaphore value without blocking.
+ LIBC_INLINE int trywait() {
+ FutexWordType v = value.load(cpp::MemoryOrder::RELAXED);
+
+ while (v > 0) {
+ // ACQUIRE on success to synchronize with the matching post().
+ if (value.compare_exchange_weak(v, v - 1, cpp::MemoryOrder::ACQUIRE,
+ cpp::MemoryOrder::RELAXED))
+ return 0;
+ }
+
+ return EAGAIN;
+ }
+
+ // Blocking wait, decrements the value when positive, or blocks until a
+ // post() makes it positive again.
+ LIBC_INLINE int wait() {
+ for (;;) {
+ if (trywait() == 0)
+ return 0;
+
+ // Blocks when value was zero.
+ // Futex wait re-checks the value atomically,
+ // so a racing post() before sleep is not lost.
+ // Spurious wakeups just send back to trywait().
+ (void)value.wait(/*expected=*/0, /*timeout=*/cpp::nullopt, is_shared);
----------------
michaelrj-google wrote:
this should probably handle the error cases
https://github.com/llvm/llvm-project/pull/198959
More information about the libc-commits
mailing list