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)