Introduce pthread_condattr_setclock()

This is one of the few POSIX APIs that was missing. It lets you choose a
monotonic clock for your condition variables. This might improve perf on
some platforms. It might also grant more flexibility with NTP configs. I
know Qt is one project that believes it needs this. To introduce this, I
needed to change some the *NSYNC APIs, to support passing a clock param.
There's also new benchmarks, demonstrating Cosmopolitan's supremacy over
many libc implementations when it comes to mutex performance. Cygwin has
an alarmingly bad pthread_mutex_t implementation. It is so bad that they
would have been significantly better off if they'd used naive spinlocks.
This commit is contained in:
Justine Tunney 2024-09-02 23:37:50 -07:00
parent 79516bf08e
commit 3c61a541bd
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
55 changed files with 449 additions and 155 deletions

View file

@ -20,6 +20,7 @@
#include "libc/calls/cp.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/consts/clock.h"
#include "libc/thread/lock.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
@ -63,7 +64,7 @@ static errno_t pthread_cond_timedwait_impl(pthread_cond_t *cond,
struct PthreadWait waiter = {cond, mutex};
pthread_cleanup_push(pthread_cond_leave, &waiter);
rc = nsync_futex_wait_((atomic_int *)&cond->_sequence, seq1, cond->_pshared,
abstime);
cond->_clock, abstime);
pthread_cleanup_pop(true);
if (rc == -EAGAIN)
rc = 0;
@ -82,8 +83,10 @@ static errno_t pthread_cond_timedwait_impl(pthread_cond_t *cond,
* }
*
* @param mutex needs to be held by thread when calling this function
* @param abstime may be null to wait indefinitely and should contain
* some arbitrary interval added to a `CLOCK_REALTIME` timestamp
* @param abstime is an absolute timestamp, which may be null to wait
* forever; it's relative to `clock_gettime(CLOCK_REALTIME)` by
* default; pthread_condattr_setclock() may be used to customize
* which system clock is used
* @return 0 on success, or errno on error
* @raise ETIMEDOUT if `abstime` was specified and the current time
* exceeded its value
@ -125,7 +128,7 @@ errno_t pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
// if using Mike Burrows' code isn't possible, use a naive impl
if (!cond->_pshared && !IsXnuSilicon()) {
err = nsync_cv_wait_with_deadline(
(nsync_cv *)cond, (nsync_mu *)mutex,
(nsync_cv *)cond, (nsync_mu *)mutex, cond->_clock,
abstime ? *abstime : nsync_time_no_deadline, 0);
} else {
err = pthread_cond_timedwait_impl(cond, mutex, abstime);