From 8fee93d8680fe8408af552a74e00f5bc557e71a7 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 5 Jul 2021 14:24:40 +0300 Subject: [PATCH] LibC: Add futex_wait() and futex_wake() helpers These are convinient wrappers over the most used futex operations. futex_wait() also does some smarts for timeout and clock handling. Use the new futex_wait() instead of a similar private helper in LibPthread. --- Userland/Libraries/LibC/serenity.h | 22 ++++++++++++++++++++++ Userland/Libraries/LibPthread/pthread.cpp | 19 ++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/Userland/Libraries/LibC/serenity.h b/Userland/Libraries/LibC/serenity.h index db5b261c33..f375afcd86 100644 --- a/Userland/Libraries/LibC/serenity.h +++ b/Userland/Libraries/LibC/serenity.h @@ -7,7 +7,9 @@ #pragma once #include +#include #include +#include #include __BEGIN_DECLS @@ -70,6 +72,26 @@ int profiling_free_buffer(pid_t); int futex(uint32_t* userspace_address, int futex_op, uint32_t value, const struct timespec* timeout, uint32_t* userspace_address2, uint32_t value3); +static ALWAYS_INLINE int futex_wait(uint32_t* userspace_address, uint32_t value, const struct timespec* abstime, int clockid) +{ + int op; + + if (abstime) { + // NOTE: FUTEX_WAIT takes a relative timeout, so use FUTEX_WAIT_BITSET instead! + op = FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG; + if (clockid == CLOCK_REALTIME || clockid == CLOCK_REALTIME_COARSE) + op |= FUTEX_CLOCK_REALTIME; + } else { + op = FUTEX_WAIT; + } + return futex(userspace_address, op, value, abstime, nullptr, FUTEX_BITSET_MATCH_ANY); +} + +static ALWAYS_INLINE int futex_wake(uint32_t* userspace_address, uint32_t count) +{ + return futex(userspace_address, FUTEX_WAKE, count, NULL, NULL, 0); +} + #define PURGE_ALL_VOLATILE 0x1 #define PURGE_ALL_CLEAN_INODE 0x2 diff --git a/Userland/Libraries/LibPthread/pthread.cpp b/Userland/Libraries/LibPthread/pthread.cpp index fcfc5b5864..84b2a14329 100644 --- a/Userland/Libraries/LibPthread/pthread.cpp +++ b/Userland/Libraries/LibPthread/pthread.cpp @@ -458,27 +458,16 @@ int pthread_cond_destroy(pthread_cond_t*) return 0; } -static int futex_wait(uint32_t& futex_addr, uint32_t value, const struct timespec* abstime) -{ - int saved_errno = errno; - // NOTE: FUTEX_WAIT takes a relative timeout, so use FUTEX_WAIT_BITSET instead! - int rc = futex(&futex_addr, FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, value, abstime, nullptr, FUTEX_BITSET_MATCH_ANY); - if (rc < 0 && errno == EAGAIN) { - // If we didn't wait, that's not an error - errno = saved_errno; - rc = 0; - } - return rc; -} - static int cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime) { u32 value = cond->value; cond->previous = value; pthread_mutex_unlock(mutex); - int rc = futex_wait(cond->value, value, abstime); + int rc = futex_wait(&cond->value, value, abstime, cond->clockid); pthread_mutex_lock(mutex); - return rc; + if (rc < 0 && errno != EAGAIN) + return errno; + return 0; } int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)