mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 01:17:34 +00:00
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.
This commit is contained in:
parent
a482a3e609
commit
8fee93d868
2 changed files with 26 additions and 15 deletions
|
@ -7,7 +7,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__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);
|
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_VOLATILE 0x1
|
||||||
#define PURGE_ALL_CLEAN_INODE 0x2
|
#define PURGE_ALL_CLEAN_INODE 0x2
|
||||||
|
|
||||||
|
|
|
@ -458,27 +458,16 @@ int pthread_cond_destroy(pthread_cond_t*)
|
||||||
return 0;
|
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)
|
static int cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime)
|
||||||
{
|
{
|
||||||
u32 value = cond->value;
|
u32 value = cond->value;
|
||||||
cond->previous = value;
|
cond->previous = value;
|
||||||
pthread_mutex_unlock(mutex);
|
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);
|
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)
|
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue