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

LibPthread: Reimplement condition variables

This implementation features a fast path for pthread_cond_signal() and
pthread_cond_broadcast() for the case there's no thread waiting, and
does not exhibit the "thundering herd" issue in
pthread_cond_broadcast().

Fixes https://github.com/SerenityOS/serenity/issues/8432
This commit is contained in:
Sergey Bugaev 2021-07-05 15:06:54 +03:00 committed by Andreas Kling
parent 5536f3c277
commit 00d8dbe739
4 changed files with 135 additions and 73 deletions

View file

@ -445,78 +445,6 @@ int pthread_setschedparam([[maybe_unused]] pthread_t thread, [[maybe_unused]] in
return 0;
}
int pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* attr)
{
cond->value = 0;
cond->previous = 0;
cond->clockid = attr ? attr->clockid : CLOCK_MONOTONIC_COARSE;
return 0;
}
int pthread_cond_destroy(pthread_cond_t*)
{
return 0;
}
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, cond->clockid);
pthread_mutex_lock(mutex);
if (rc < 0 && errno != EAGAIN)
return errno;
return 0;
}
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
{
int rc = cond_wait(cond, mutex, nullptr);
VERIFY(rc == 0);
return 0;
}
int pthread_condattr_init(pthread_condattr_t* attr)
{
attr->clockid = CLOCK_MONOTONIC_COARSE;
return 0;
}
int pthread_condattr_destroy(pthread_condattr_t*)
{
return 0;
}
int pthread_condattr_setclock(pthread_condattr_t* attr, clockid_t clock)
{
attr->clockid = clock;
return 0;
}
int pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime)
{
return cond_wait(cond, mutex, abstime);
}
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, nullptr, 0);
VERIFY(rc >= 0);
return 0;
}
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, nullptr, 0);
VERIFY(rc >= 0);
return 0;
}
// libgcc expects this function to exist in libpthread, even
// if it is not implemented.
int pthread_cancel(pthread_t)