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:
parent
5536f3c277
commit
00d8dbe739
4 changed files with 135 additions and 73 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue