1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 18:18:12 +00:00

Kernel: Some futex improvements

This adds support for FUTEX_WAKE_OP, FUTEX_WAIT_BITSET, FUTEX_WAKE_BITSET,
FUTEX_REQUEUE, and FUTEX_CMP_REQUEUE, as well well as global and private
futex and absolute/relative timeouts against the appropriate clock. This
also changes the implementation so that kernel resources are only used when
a thread is blocked on a futex.

Global futexes are implemented as offsets in VMObjects, so that different
processes can share a futex against the same VMObject despite potentially
being mapped at different virtual addresses.
This commit is contained in:
Tom 2020-12-21 23:21:58 -07:00 committed by Andreas Kling
parent 7581b64705
commit 1d621ab172
23 changed files with 928 additions and 63 deletions

View file

@ -495,12 +495,25 @@ 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, 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)
{
i32 value = cond->value;
u32 value = cond->value;
cond->previous = value;
pthread_mutex_unlock(mutex);
int rc = futex(&cond->value, FUTEX_WAIT, value, abstime);
int rc = futex_wait(cond->value, value, abstime);
pthread_mutex_lock(mutex);
return rc;
}
@ -538,7 +551,7 @@ int pthread_cond_signal(pthread_cond_t* cond)
{
u32 value = cond->previous + 1;
cond->value = value;
int rc = futex(&cond->value, FUTEX_WAKE, 1, nullptr);
int rc = futex(&cond->value, FUTEX_WAKE, 1, nullptr, nullptr, 0);
ASSERT(rc == 0);
return 0;
}
@ -547,7 +560,7 @@ int pthread_cond_broadcast(pthread_cond_t* cond)
{
u32 value = cond->previous + 1;
cond->value = value;
int rc = futex(&cond->value, FUTEX_WAKE, INT32_MAX, nullptr);
int rc = futex(&cond->value, FUTEX_WAKE, INT32_MAX, nullptr, nullptr, 0);
ASSERT(rc == 0);
return 0;
}