mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 23:09:16 +00:00
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:
parent
79516bf08e
commit
3c61a541bd
55 changed files with 449 additions and 155 deletions
3
third_party/lua/lunix.c
vendored
3
third_party/lua/lunix.c
vendored
|
@ -110,6 +110,7 @@
|
|||
#include "third_party/lua/lua.h"
|
||||
#include "third_party/lua/luaconf.h"
|
||||
#include "third_party/nsync/futex.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "tool/net/luacheck.h"
|
||||
|
||||
#define DNS_NAME_MAX 253
|
||||
|
@ -2855,7 +2856,7 @@ static int LuaUnixMemoryWait(lua_State *L) {
|
|||
}
|
||||
BEGIN_CANCELATION_POINT;
|
||||
rc = nsync_futex_wait_((atomic_int *)GetWord(L), expect,
|
||||
PTHREAD_PROCESS_SHARED, deadline);
|
||||
PTHREAD_PROCESS_SHARED, CLOCK_REALTIME, deadline);
|
||||
END_CANCELATION_POINT;
|
||||
if (rc < 0) errno = -rc, rc = -1;
|
||||
return SysretInteger(L, "futex_wait", olderr, rc);
|
||||
|
|
2
third_party/nsync/README.cosmo
vendored
2
third_party/nsync/README.cosmo
vendored
|
@ -17,6 +17,8 @@ LOCAL CHANGES
|
|||
|
||||
- Fix nsync_mu_unlock() on Apple Silicon
|
||||
|
||||
- Add clock parameter to many NSYNC wait APIs
|
||||
|
||||
- Time APIs were so good that they're now in libc
|
||||
|
||||
- Double linked list API was so good that it's now in libc
|
||||
|
|
2
third_party/nsync/common.internal.h
vendored
2
third_party/nsync/common.internal.h
vendored
|
@ -266,7 +266,7 @@ void nsync_mu_unlock_slow_(nsync_mu *mu, lock_type *l_type);
|
|||
struct Dll *nsync_remove_from_mu_queue_(struct Dll *mu_queue, struct Dll *e);
|
||||
void nsync_maybe_merge_conditions_(struct Dll *p, struct Dll *n);
|
||||
nsync_time nsync_note_notified_deadline_(nsync_note n);
|
||||
int nsync_sem_wait_with_cancel_(waiter *w, nsync_time abs_deadline,
|
||||
int nsync_sem_wait_with_cancel_(waiter *w, int clock, nsync_time abs_deadline,
|
||||
nsync_note cancel_note);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
4
third_party/nsync/cv.h
vendored
4
third_party/nsync/cv.h
vendored
|
@ -144,7 +144,7 @@ int nsync_cv_wait(nsync_cv *cv, nsync_mu *mu);
|
|||
mostly in tests and trivial examples than they are in real
|
||||
programmes. */
|
||||
int nsync_cv_wait_with_deadline(nsync_cv *cv, nsync_mu *mu,
|
||||
nsync_time abs_deadline,
|
||||
int clock, nsync_time abs_deadline,
|
||||
struct nsync_note_s_ *cancel_note);
|
||||
|
||||
/* Like nsync_cv_wait_with_deadline(), but allow an arbitrary lock *v to be
|
||||
|
@ -152,7 +152,7 @@ int nsync_cv_wait_with_deadline(nsync_cv *cv, nsync_mu *mu,
|
|||
int nsync_cv_wait_with_deadline_generic(nsync_cv *cv, void *mu,
|
||||
void (*lock)(void *),
|
||||
void (*unlock)(void *),
|
||||
nsync_time abs_deadline,
|
||||
int clock, nsync_time abs_deadline,
|
||||
struct nsync_note_s_ *cancel_note);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
88
third_party/nsync/futex.c
vendored
88
third_party/nsync/futex.c
vendored
|
@ -52,7 +52,6 @@
|
|||
#include "third_party/nsync/atomic.h"
|
||||
#include "third_party/nsync/common.internal.h"
|
||||
#include "third_party/nsync/futex.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "third_party/nsync/time.h"
|
||||
|
||||
#define FUTEX_WAIT_BITS_ FUTEX_BITSET_MATCH_ANY
|
||||
|
@ -65,6 +64,7 @@ static struct NsyncFutex {
|
|||
atomic_uint once;
|
||||
int FUTEX_WAIT_;
|
||||
int FUTEX_PRIVATE_FLAG_;
|
||||
int FUTEX_CLOCK_REALTIME_;
|
||||
bool is_supported;
|
||||
bool timeout_is_relative;
|
||||
} nsync_futex_;
|
||||
|
@ -92,9 +92,8 @@ static void nsync_futex_init_ (void) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(nsync_futex_.is_supported = IsLinux () || IsOpenbsd ())) {
|
||||
if (!(nsync_futex_.is_supported = IsLinux () || IsOpenbsd ()))
|
||||
return;
|
||||
}
|
||||
|
||||
// In our testing, we found that the monotonic clock on various
|
||||
// popular systems (such as Linux, and some BSD variants) was no
|
||||
|
@ -111,16 +110,11 @@ static void nsync_futex_init_ (void) {
|
|||
if (IsLinux () &&
|
||||
_futex (&x, FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME,
|
||||
1, 0, 0, FUTEX_BITSET_MATCH_ANY) == -EAGAIN) {
|
||||
nsync_futex_.FUTEX_WAIT_ =
|
||||
FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME;
|
||||
nsync_futex_.FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
|
||||
} else if (!IsTiny () && IsLinux () &&
|
||||
_futex (&x, FUTEX_WAIT_BITSET, 1, 0, 0,
|
||||
FUTEX_BITSET_MATCH_ANY) == -EAGAIN) {
|
||||
nsync_futex_.FUTEX_WAIT_ = FUTEX_WAIT_BITSET;
|
||||
nsync_futex_.FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
|
||||
nsync_futex_.FUTEX_CLOCK_REALTIME_ = FUTEX_CLOCK_REALTIME;
|
||||
} else if (IsOpenbsd () ||
|
||||
(!IsTiny () && IsLinux () &&
|
||||
(IsLinux () &&
|
||||
!_futex_wake (&x, FUTEX_WAKE_PRIVATE, 1))) {
|
||||
nsync_futex_.FUTEX_WAIT_ = FUTEX_WAIT;
|
||||
nsync_futex_.FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
|
||||
|
@ -132,24 +126,24 @@ static void nsync_futex_init_ (void) {
|
|||
errno = e;
|
||||
}
|
||||
|
||||
static int nsync_futex_polyfill_ (atomic_int *w, int expect, struct timespec *abstime) {
|
||||
static int nsync_futex_polyfill_ (atomic_int *w, int expect, int clock, struct timespec *abstime) {
|
||||
for (;;) {
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect) {
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect)
|
||||
return 0;
|
||||
}
|
||||
if (_weaken (pthread_testcancel_np) &&
|
||||
_weaken (pthread_testcancel_np) ()) {
|
||||
_weaken (pthread_testcancel_np) ())
|
||||
return -ECANCELED;
|
||||
}
|
||||
if (abstime && timespec_cmp (timespec_real (), *abstime) >= 0) {
|
||||
struct timespec now;
|
||||
if (clock_gettime (clock, &now))
|
||||
return -EINVAL;
|
||||
if (abstime && timespec_cmp (now, *abstime) >= 0)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
pthread_yield_np ();
|
||||
}
|
||||
}
|
||||
|
||||
static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare,
|
||||
const struct timespec *timeout,
|
||||
int clock, const struct timespec *timeout,
|
||||
struct PosixThread *pt,
|
||||
sigset_t waitmask) {
|
||||
#ifdef __x86_64__
|
||||
|
@ -164,23 +158,20 @@ static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare,
|
|||
}
|
||||
|
||||
for (;;) {
|
||||
now = timespec_real ();
|
||||
if (timespec_cmp (now, deadline) >= 0) {
|
||||
return etimedout();
|
||||
}
|
||||
if (clock_gettime (clock, &now))
|
||||
return einval ();
|
||||
if (timespec_cmp (now, deadline) >= 0)
|
||||
return etimedout ();
|
||||
wait = timespec_sub (deadline, now);
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect) {
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect)
|
||||
return 0;
|
||||
}
|
||||
if (pt) {
|
||||
if (_check_cancel () == -1) {
|
||||
if (_check_cancel () == -1)
|
||||
return -1; /* ECANCELED */
|
||||
}
|
||||
if ((sig = __sig_get (waitmask))) {
|
||||
__sig_relay (sig, SI_KERNEL, waitmask);
|
||||
if (_check_cancel () == -1) {
|
||||
if (_check_cancel () == -1)
|
||||
return -1; /* ECANCELED */
|
||||
}
|
||||
return eintr ();
|
||||
}
|
||||
pt->pt_blkmask = waitmask;
|
||||
|
@ -192,9 +183,8 @@ static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare,
|
|||
atomic_store_explicit (&pt->pt_blocker, 0, memory_order_release);
|
||||
if (ok && atomic_load_explicit (w, memory_order_acquire) == expect && (sig = __sig_get (waitmask))) {
|
||||
__sig_relay (sig, SI_KERNEL, waitmask);
|
||||
if (_check_cancel () == -1) {
|
||||
if (_check_cancel () == -1)
|
||||
return -1; /* ECANCELED */
|
||||
}
|
||||
return eintr ();
|
||||
}
|
||||
}
|
||||
|
@ -209,33 +199,41 @@ static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare,
|
|||
#endif /* __x86_64__ */
|
||||
}
|
||||
|
||||
static struct timespec *nsync_futex_timeout_ (struct timespec *memory,
|
||||
const struct timespec *abstime) {
|
||||
static int nsync_futex_fix_timeout_ (struct timespec *memory, int clock,
|
||||
const struct timespec *abstime,
|
||||
struct timespec **result) {
|
||||
struct timespec now;
|
||||
if (!abstime) {
|
||||
*result = 0;
|
||||
return 0;
|
||||
} else if (!nsync_futex_.timeout_is_relative) {
|
||||
*memory = *abstime;
|
||||
return memory;
|
||||
*result = memory;
|
||||
return 0;
|
||||
} else {
|
||||
now = timespec_real ();
|
||||
if (clock_gettime (clock, &now))
|
||||
return -EINVAL;
|
||||
*memory = timespec_subz (*abstime, now);
|
||||
return memory;
|
||||
*result = memory;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, const struct timespec *abstime) {
|
||||
int nsync_futex_wait_ (atomic_int *w, int expect, char pshare,
|
||||
int clock, const struct timespec *abstime) {
|
||||
int e, rc, op;
|
||||
struct CosmoTib *tib;
|
||||
struct PosixThread *pt;
|
||||
struct timespec tsmem, *timeout;
|
||||
struct timespec tsmem;
|
||||
struct timespec *timeout = 0;
|
||||
|
||||
cosmo_once (&nsync_futex_.once, nsync_futex_init_);
|
||||
|
||||
op = nsync_futex_.FUTEX_WAIT_;
|
||||
if (pshare == PTHREAD_PROCESS_PRIVATE) {
|
||||
if (pshare == PTHREAD_PROCESS_PRIVATE)
|
||||
op |= nsync_futex_.FUTEX_PRIVATE_FLAG_;
|
||||
}
|
||||
if (clock == CLOCK_REALTIME)
|
||||
op |= nsync_futex_.FUTEX_CLOCK_REALTIME_;
|
||||
|
||||
if (abstime && timespec_cmp (*abstime, timespec_zero) <= 0) {
|
||||
rc = -ETIMEDOUT;
|
||||
|
@ -247,7 +245,8 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, const struct time
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
timeout = nsync_futex_timeout_ (&tsmem, abstime);
|
||||
if ((rc = nsync_futex_fix_timeout_ (&tsmem, clock, abstime, &timeout)))
|
||||
goto Finished;
|
||||
|
||||
LOCKTRACE ("futex(%t [%d], %s, %#x, %s) → ...",
|
||||
w, atomic_load_explicit (w, memory_order_relaxed),
|
||||
|
@ -263,7 +262,7 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, const struct time
|
|||
// Windows 8 futexes don't support multiple processes :(
|
||||
if (pshare) goto Polyfill;
|
||||
sigset_t m = __sig_block ();
|
||||
rc = nsync_futex_wait_win32_ (w, expect, pshare, timeout, pt, m);
|
||||
rc = nsync_futex_wait_win32_ (w, expect, pshare, clock, timeout, pt, m);
|
||||
__sig_unblock (m);
|
||||
} else if (IsXnu ()) {
|
||||
uint32_t op, us;
|
||||
|
@ -280,7 +279,7 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, const struct time
|
|||
rc = ulock_wait (op, w, expect, us);
|
||||
if (rc > 0) rc = 0; // don't care about #waiters
|
||||
} else if (IsFreebsd ()) {
|
||||
rc = sys_umtx_timedwait_uint (w, expect, pshare, timeout);
|
||||
rc = sys_umtx_timedwait_uint (w, expect, pshare, clock, timeout);
|
||||
} else {
|
||||
if (IsOpenbsd()) {
|
||||
// OpenBSD 6.8 futex() returns errors as
|
||||
|
@ -313,7 +312,7 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, const struct time
|
|||
}
|
||||
} else {
|
||||
Polyfill:
|
||||
rc = nsync_futex_polyfill_ (w, expect, timeout);
|
||||
rc = nsync_futex_polyfill_ (w, expect, clock, timeout);
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
@ -334,9 +333,8 @@ int nsync_futex_wake_ (atomic_int *w, int count, char pshare) {
|
|||
cosmo_once (&nsync_futex_.once, nsync_futex_init_);
|
||||
|
||||
op = FUTEX_WAKE;
|
||||
if (pshare == PTHREAD_PROCESS_PRIVATE) {
|
||||
if (pshare == PTHREAD_PROCESS_PRIVATE)
|
||||
op |= nsync_futex_.FUTEX_PRIVATE_FLAG_;
|
||||
}
|
||||
|
||||
if (nsync_futex_.is_supported) {
|
||||
if (IsWindows ()) {
|
||||
|
|
2
third_party/nsync/futex.internal.h
vendored
2
third_party/nsync/futex.internal.h
vendored
|
@ -11,7 +11,7 @@ COSMOPOLITAN_C_START_
|
|||
#endif
|
||||
|
||||
int nsync_futex_wake_(_FUTEX_ATOMIC(int) *, int, char);
|
||||
int nsync_futex_wait_(_FUTEX_ATOMIC(int) *, int, char, const struct timespec *);
|
||||
int nsync_futex_wait_(_FUTEX_ATOMIC(int) *, int, char, int, const struct timespec *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* NSYNC_FUTEX_INTERNAL_H_ */
|
||||
|
|
3
third_party/nsync/mem/nsync_counter.c
vendored
3
third_party/nsync/mem/nsync_counter.c
vendored
|
@ -25,6 +25,7 @@
|
|||
#include "third_party/nsync/mu_semaphore.h"
|
||||
#include "third_party/nsync/races.internal.h"
|
||||
#include "third_party/nsync/wait_s.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/waiter.h"
|
||||
__static_yoink("nsync_notice");
|
||||
|
||||
|
@ -100,7 +101,7 @@ uint32_t nsync_counter_wait (nsync_counter c, nsync_time abs_deadline) {
|
|||
uint32_t result = 0;
|
||||
waitable.v = c;
|
||||
waitable.funcs = &nsync_counter_waitable_funcs;
|
||||
if (nsync_wait_n (NULL, NULL, NULL, abs_deadline, 1, &pwaitable) != 0) {
|
||||
if (nsync_wait_n (NULL, NULL, NULL, CLOCK_REALTIME, abs_deadline, 1, &pwaitable) != 0) {
|
||||
IGNORE_RACES_START ();
|
||||
result = ATM_LOAD_ACQ (&c->value);
|
||||
IGNORE_RACES_END ();
|
||||
|
|
12
third_party/nsync/mem/nsync_cv.c
vendored
12
third_party/nsync/mem/nsync_cv.c
vendored
|
@ -175,6 +175,7 @@ struct nsync_cv_wait_with_deadline_s {
|
|||
void *pmu;
|
||||
void (*lock) (void *);
|
||||
nsync_mu *cv_mu;
|
||||
int clock;
|
||||
nsync_time abs_deadline;
|
||||
nsync_note cancel_note;
|
||||
waiter *w;
|
||||
|
@ -187,7 +188,7 @@ static int nsync_cv_wait_with_deadline_impl_ (struct nsync_cv_wait_with_deadline
|
|||
IGNORE_RACES_START ();
|
||||
while (ATM_LOAD_ACQ (&c->w->nw.waiting) != 0) { /* acquire load */
|
||||
if (c->sem_outcome == 0) {
|
||||
c->sem_outcome = nsync_sem_wait_with_cancel_ (c->w, c->abs_deadline, c->cancel_note);
|
||||
c->sem_outcome = nsync_sem_wait_with_cancel_ (c->w, c->clock, c->abs_deadline, c->cancel_note);
|
||||
}
|
||||
if (c->sem_outcome != 0 && ATM_LOAD (&c->w->nw.waiting) != 0) {
|
||||
/* A timeout or cancellation occurred, and no wakeup.
|
||||
|
@ -278,13 +279,14 @@ static void nsync_cv_wait_with_deadline_unwind_ (void *arg) {
|
|||
programmes. */
|
||||
int nsync_cv_wait_with_deadline_generic (nsync_cv *pcv, void *pmu,
|
||||
void (*lock) (void *), void (*unlock) (void *),
|
||||
nsync_time abs_deadline,
|
||||
int clock, nsync_time abs_deadline,
|
||||
nsync_note cancel_note) {
|
||||
int outcome;
|
||||
struct nsync_cv_wait_with_deadline_s c;
|
||||
IGNORE_RACES_START ();
|
||||
|
||||
c.w = nsync_waiter_new_ ();
|
||||
c.clock = clock;
|
||||
c.abs_deadline = abs_deadline;
|
||||
c.cancel_note = cancel_note;
|
||||
c.cv_mu = NULL;
|
||||
|
@ -470,10 +472,10 @@ void nsync_cv_broadcast (nsync_cv *pcv) {
|
|||
|
||||
/* Wait with deadline, using an nsync_mu. */
|
||||
errno_t nsync_cv_wait_with_deadline (nsync_cv *pcv, nsync_mu *pmu,
|
||||
nsync_time abs_deadline,
|
||||
int clock, nsync_time abs_deadline,
|
||||
nsync_note cancel_note) {
|
||||
return (nsync_cv_wait_with_deadline_generic (pcv, pmu, &void_mu_lock,
|
||||
&void_mu_unlock,
|
||||
&void_mu_unlock, clock,
|
||||
abs_deadline, cancel_note));
|
||||
}
|
||||
|
||||
|
@ -486,7 +488,7 @@ errno_t nsync_cv_wait_with_deadline (nsync_cv *pcv, nsync_mu *pmu,
|
|||
ECANCELED may be returned if calling POSIX thread is cancelled only when
|
||||
the PTHREAD_CANCEL_MASKED mode is in play. */
|
||||
errno_t nsync_cv_wait (nsync_cv *pcv, nsync_mu *pmu) {
|
||||
return nsync_cv_wait_with_deadline (pcv, pmu, nsync_time_no_deadline, NULL);
|
||||
return nsync_cv_wait_with_deadline (pcv, pmu, 0, nsync_time_no_deadline, NULL);
|
||||
}
|
||||
|
||||
static nsync_time cv_ready_time (void *v, struct nsync_waiter_s *nw) {
|
||||
|
|
6
third_party/nsync/mem/nsync_mu_wait.c
vendored
6
third_party/nsync/mem/nsync_mu_wait.c
vendored
|
@ -141,7 +141,7 @@ int nsync_mu_wait_with_deadline (nsync_mu *mu,
|
|||
int (*condition) (const void *condition_arg),
|
||||
const void *condition_arg,
|
||||
int (*condition_arg_eq) (const void *a, const void *b),
|
||||
nsync_time abs_deadline, nsync_note cancel_note) {
|
||||
int clock, nsync_time abs_deadline, nsync_note cancel_note) {
|
||||
lock_type *l_type;
|
||||
int first_wait;
|
||||
int condition_is_true;
|
||||
|
@ -231,7 +231,7 @@ int nsync_mu_wait_with_deadline (nsync_mu *mu,
|
|||
have_lock = 0;
|
||||
while (ATM_LOAD_ACQ (&w->nw.waiting) != 0) { /* acquire load */
|
||||
if (sem_outcome == 0) {
|
||||
sem_outcome = nsync_sem_wait_with_cancel_ (w, abs_deadline,
|
||||
sem_outcome = nsync_sem_wait_with_cancel_ (w, clock, abs_deadline,
|
||||
cancel_note);
|
||||
if (sem_outcome != 0 && ATM_LOAD (&w->nw.waiting) != 0) {
|
||||
/* A timeout or cancellation occurred, and no wakeup.
|
||||
|
@ -280,7 +280,7 @@ void nsync_mu_wait (nsync_mu *mu, int (*condition) (const void *condition_arg),
|
|||
const void *condition_arg,
|
||||
int (*condition_arg_eq) (const void *a, const void *b)) {
|
||||
if (nsync_mu_wait_with_deadline (mu, condition, condition_arg, condition_arg_eq,
|
||||
nsync_time_no_deadline, NULL) != 0) {
|
||||
0, nsync_time_no_deadline, NULL) != 0) {
|
||||
nsync_panic_ ("nsync_mu_wait woke but condition not true\n");
|
||||
}
|
||||
}
|
||||
|
|
3
third_party/nsync/mem/nsync_note.c
vendored
3
third_party/nsync/mem/nsync_note.c
vendored
|
@ -24,6 +24,7 @@
|
|||
#include "third_party/nsync/mu_wait.h"
|
||||
#include "third_party/nsync/races.internal.h"
|
||||
#include "third_party/nsync/wait_s.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/waiter.h"
|
||||
__static_yoink("nsync_notice");
|
||||
|
||||
|
@ -247,7 +248,7 @@ int nsync_note_wait (nsync_note n, nsync_time abs_deadline) {
|
|||
struct nsync_waitable_s *pwaitable = &waitable;
|
||||
waitable.v = n;
|
||||
waitable.funcs = &nsync_note_waitable_funcs;
|
||||
return (nsync_wait_n (NULL, NULL, NULL, abs_deadline, 1, &pwaitable) == 0);
|
||||
return (nsync_wait_n (NULL, NULL, NULL, CLOCK_REALTIME, abs_deadline, 1, &pwaitable) == 0);
|
||||
}
|
||||
|
||||
nsync_time nsync_note_expiry (nsync_note n) {
|
||||
|
|
3
third_party/nsync/mem/nsync_once.c
vendored
3
third_party/nsync/mem/nsync_once.c
vendored
|
@ -22,6 +22,7 @@
|
|||
#include "third_party/nsync/once.h"
|
||||
#include "third_party/nsync/races.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/wait_s.internal.h"
|
||||
__static_yoink("nsync_notice");
|
||||
|
||||
|
@ -91,7 +92,7 @@ static void nsync_run_once_impl (nsync_once *once, struct once_sync_s *s,
|
|||
attempts += 10;
|
||||
}
|
||||
deadline = nsync_time_add (nsync_time_now (), nsync_time_ms (attempts));
|
||||
nsync_cv_wait_with_deadline (&s->once_cv, &s->once_mu, deadline, NULL);
|
||||
nsync_cv_wait_with_deadline (&s->once_cv, &s->once_mu, CLOCK_REALTIME, deadline, NULL);
|
||||
} else {
|
||||
attempts = pthread_delay_np (once, attempts);
|
||||
}
|
||||
|
|
6
third_party/nsync/mem/nsync_sem_wait.c
vendored
6
third_party/nsync/mem/nsync_sem_wait.c
vendored
|
@ -29,11 +29,11 @@ __static_yoink("nsync_notice");
|
|||
w->sem is non-zero----decrement it and return 0.
|
||||
abs_deadline expires---return ETIMEDOUT.
|
||||
cancel_note is non-NULL and *cancel_note becomes notified---return ECANCELED. */
|
||||
int nsync_sem_wait_with_cancel_ (waiter *w, nsync_time abs_deadline,
|
||||
int nsync_sem_wait_with_cancel_ (waiter *w, int clock, nsync_time abs_deadline,
|
||||
nsync_note cancel_note) {
|
||||
int sem_outcome;
|
||||
if (cancel_note == NULL) {
|
||||
sem_outcome = nsync_mu_semaphore_p_with_deadline (&w->sem, abs_deadline);
|
||||
sem_outcome = nsync_mu_semaphore_p_with_deadline (&w->sem, clock, abs_deadline);
|
||||
} else {
|
||||
nsync_time cancel_time;
|
||||
cancel_time = nsync_note_notified_deadline_ (cancel_note);
|
||||
|
@ -58,7 +58,7 @@ int nsync_sem_wait_with_cancel_ (waiter *w, nsync_time abs_deadline,
|
|||
}
|
||||
nsync_mu_unlock (&cancel_note->note_mu);
|
||||
sem_outcome = nsync_mu_semaphore_p_with_deadline (&w->sem,
|
||||
local_abs_deadline);
|
||||
clock, local_abs_deadline);
|
||||
if (sem_outcome == ETIMEDOUT && !deadline_is_nearer) {
|
||||
sem_outcome = ECANCELED;
|
||||
nsync_note_notify (cancel_note);
|
||||
|
|
4
third_party/nsync/mem/nsync_wait.c
vendored
4
third_party/nsync/mem/nsync_wait.c
vendored
|
@ -28,7 +28,7 @@
|
|||
__static_yoink("nsync_notice");
|
||||
|
||||
int nsync_wait_n (void *mu, void (*lock) (void *), void (*unlock) (void *),
|
||||
nsync_time abs_deadline,
|
||||
int clock, nsync_time abs_deadline,
|
||||
int count, struct nsync_waitable_s *waitable[]) {
|
||||
int ready;
|
||||
IGNORE_RACES_START ();
|
||||
|
@ -77,7 +77,7 @@ int nsync_wait_n (void *mu, void (*lock) (void *), void (*unlock) (void *),
|
|||
}
|
||||
} while (nsync_time_cmp (min_ntime, nsync_time_zero) > 0 &&
|
||||
nsync_mu_semaphore_p_with_deadline (&w->sem,
|
||||
min_ntime) == 0);
|
||||
clock, min_ntime) == 0);
|
||||
}
|
||||
|
||||
/* An attempt was made above to enqueue waitable[0..i-1].
|
||||
|
|
8
third_party/nsync/mu_semaphore.c
vendored
8
third_party/nsync/mu_semaphore.c
vendored
|
@ -54,15 +54,15 @@ errno_t nsync_mu_semaphore_p (nsync_semaphore *s) {
|
|||
while additionally supporting a time parameter specifying at what point
|
||||
in the future ETIMEDOUT should be returned, if neither cancelation, or
|
||||
semaphore release happens. */
|
||||
errno_t nsync_mu_semaphore_p_with_deadline (nsync_semaphore *s, nsync_time abs_deadline) {
|
||||
errno_t nsync_mu_semaphore_p_with_deadline (nsync_semaphore *s, int clock, nsync_time abs_deadline) {
|
||||
errno_t err;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
if (NSYNC_USE_GRAND_CENTRAL && IsXnuSilicon ()) {
|
||||
err = nsync_mu_semaphore_p_with_deadline_gcd (s, abs_deadline);
|
||||
err = nsync_mu_semaphore_p_with_deadline_gcd (s, clock, abs_deadline);
|
||||
} else if (IsNetbsd ()) {
|
||||
err = nsync_mu_semaphore_p_with_deadline_sem (s, abs_deadline);
|
||||
err = nsync_mu_semaphore_p_with_deadline_sem (s, clock, abs_deadline);
|
||||
} else {
|
||||
err = nsync_mu_semaphore_p_with_deadline_futex (s, abs_deadline);
|
||||
err = nsync_mu_semaphore_p_with_deadline_futex (s, clock, abs_deadline);
|
||||
}
|
||||
END_CANCELATION_POINT;
|
||||
return err;
|
||||
|
|
2
third_party/nsync/mu_semaphore.h
vendored
2
third_party/nsync/mu_semaphore.h
vendored
|
@ -16,7 +16,7 @@ errno_t nsync_mu_semaphore_p(nsync_semaphore *s);
|
|||
/* Wait until one of: the count of *s is non-zero, in which case
|
||||
decrement *s and return 0; or abs_deadline expires, in which case
|
||||
return ETIMEDOUT. */
|
||||
errno_t nsync_mu_semaphore_p_with_deadline(nsync_semaphore *s,
|
||||
errno_t nsync_mu_semaphore_p_with_deadline(nsync_semaphore *s, int clock,
|
||||
nsync_time abs_deadline);
|
||||
|
||||
/* Ensure that the count of *s is at least 1. */
|
||||
|
|
6
third_party/nsync/mu_semaphore.internal.h
vendored
6
third_party/nsync/mu_semaphore.internal.h
vendored
|
@ -20,17 +20,17 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
bool nsync_mu_semaphore_init_futex(nsync_semaphore *);
|
||||
errno_t nsync_mu_semaphore_p_futex(nsync_semaphore *);
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_futex(nsync_semaphore *, nsync_time);
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_futex(nsync_semaphore *, int, nsync_time);
|
||||
void nsync_mu_semaphore_v_futex(nsync_semaphore *);
|
||||
|
||||
bool nsync_mu_semaphore_init_sem(nsync_semaphore *);
|
||||
errno_t nsync_mu_semaphore_p_sem(nsync_semaphore *);
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_sem(nsync_semaphore *, nsync_time);
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_sem(nsync_semaphore *, int, nsync_time);
|
||||
void nsync_mu_semaphore_v_sem(nsync_semaphore *);
|
||||
|
||||
bool nsync_mu_semaphore_init_gcd(nsync_semaphore *);
|
||||
errno_t nsync_mu_semaphore_p_gcd(nsync_semaphore *);
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_gcd(nsync_semaphore *, nsync_time);
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_gcd(nsync_semaphore *, int, nsync_time);
|
||||
void nsync_mu_semaphore_v_gcd(nsync_semaphore *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
16
third_party/nsync/mu_semaphore_futex.c
vendored
16
third_party/nsync/mu_semaphore_futex.c
vendored
|
@ -63,7 +63,7 @@ errno_t nsync_mu_semaphore_p_futex (nsync_semaphore *s) {
|
|||
int futex_result;
|
||||
futex_result = -nsync_futex_wait_ (
|
||||
(atomic_int *)&f->i, i,
|
||||
PTHREAD_PROCESS_PRIVATE, 0);
|
||||
PTHREAD_PROCESS_PRIVATE, 0, 0);
|
||||
ASSERT (futex_result == 0 ||
|
||||
futex_result == EINTR ||
|
||||
futex_result == EAGAIN ||
|
||||
|
@ -81,7 +81,7 @@ errno_t nsync_mu_semaphore_p_futex (nsync_semaphore *s) {
|
|||
while additionally supporting a time parameter specifying at what point
|
||||
in the future ETIMEDOUT should be returned, if neither cancellation, or
|
||||
semaphore release happens. */
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_futex (nsync_semaphore *s, nsync_time abs_deadline) {
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_futex (nsync_semaphore *s, int clock, nsync_time abs_deadline) {
|
||||
struct futex *f = (struct futex *)s;
|
||||
int i;
|
||||
int result = 0;
|
||||
|
@ -98,7 +98,8 @@ errno_t nsync_mu_semaphore_p_with_deadline_futex (nsync_semaphore *s, nsync_time
|
|||
ts = &ts_buf;
|
||||
}
|
||||
futex_result = nsync_futex_wait_ ((atomic_int *)&f->i, i,
|
||||
PTHREAD_PROCESS_PRIVATE, ts);
|
||||
PTHREAD_PROCESS_PRIVATE,
|
||||
clock, ts);
|
||||
ASSERT (futex_result == 0 ||
|
||||
futex_result == -EINTR ||
|
||||
futex_result == -EAGAIN ||
|
||||
|
@ -106,9 +107,12 @@ errno_t nsync_mu_semaphore_p_with_deadline_futex (nsync_semaphore *s, nsync_time
|
|||
futex_result == -ETIMEDOUT ||
|
||||
futex_result == -EWOULDBLOCK);
|
||||
/* Some systems don't wait as long as they are told. */
|
||||
if (futex_result == -ETIMEDOUT &&
|
||||
nsync_time_cmp (abs_deadline, nsync_time_now ()) <= 0) {
|
||||
result = ETIMEDOUT;
|
||||
if (futex_result == -ETIMEDOUT) {
|
||||
nsync_time now;
|
||||
if (clock_gettime (clock, &now))
|
||||
result = EINVAL;
|
||||
if (nsync_time_cmp (now, abs_deadline) >= 0)
|
||||
result = ETIMEDOUT;
|
||||
}
|
||||
if (futex_result == -ECANCELED) {
|
||||
result = ECANCELED;
|
||||
|
|
9
third_party/nsync/mu_semaphore_gcd.c
vendored
9
third_party/nsync/mu_semaphore_gcd.c
vendored
|
@ -94,14 +94,14 @@ bool nsync_mu_semaphore_init_gcd (nsync_semaphore *s) {
|
|||
they're enabled in MASKED mode, this function may return ECANCELED. Otherwise,
|
||||
cancellation will occur by unwinding cleanup handlers pushed to the stack. */
|
||||
errno_t nsync_mu_semaphore_p_gcd (nsync_semaphore *s) {
|
||||
return nsync_mu_semaphore_p_with_deadline_gcd (s, nsync_time_no_deadline);
|
||||
return nsync_mu_semaphore_p_with_deadline_gcd (s, 0, nsync_time_no_deadline);
|
||||
}
|
||||
|
||||
/* Like nsync_mu_semaphore_p() this waits for the count of *s to exceed 0,
|
||||
while additionally supporting a time parameter specifying at what point
|
||||
in the future ETIMEDOUT should be returned, if neither cancellation, or
|
||||
semaphore release happens. */
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_gcd (nsync_semaphore *s,
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_gcd (nsync_semaphore *s, int clock,
|
||||
nsync_time abs_deadline) {
|
||||
errno_t result = 0;
|
||||
struct PosixThread *pt;
|
||||
|
@ -117,7 +117,10 @@ errno_t nsync_mu_semaphore_p_with_deadline_gcd (nsync_semaphore *s,
|
|||
result = ECANCELED;
|
||||
break;
|
||||
}
|
||||
now = timespec_real();
|
||||
if (clock_gettime (clock, &now)) {
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (timespec_cmp (now, abs_deadline) >= 0) {
|
||||
result = ETIMEDOUT;
|
||||
break;
|
||||
|
|
15
third_party/nsync/mu_semaphore_sem.c
vendored
15
third_party/nsync/mu_semaphore_sem.c
vendored
|
@ -33,6 +33,7 @@
|
|||
#include "third_party/nsync/mu_semaphore.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/time.h"
|
||||
|
||||
/**
|
||||
|
@ -126,10 +127,22 @@ errno_t nsync_mu_semaphore_p_sem (nsync_semaphore *s) {
|
|||
while additionally supporting a time parameter specifying at what point
|
||||
in the future ETIMEDOUT should be returned, if neither cancellation, or
|
||||
semaphore release happens. */
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_sem (nsync_semaphore *s, nsync_time abs_deadline) {
|
||||
errno_t nsync_mu_semaphore_p_with_deadline_sem (nsync_semaphore *s, int clock,
|
||||
nsync_time abs_deadline) {
|
||||
int e, rc;
|
||||
errno_t result;
|
||||
struct sem *f = (struct sem *) s;
|
||||
|
||||
// convert monotonic back to realtime just for netbsd
|
||||
if (clock && nsync_time_cmp (abs_deadline, nsync_time_no_deadline)) {
|
||||
struct timespec now, delta;
|
||||
if (clock_gettime (clock, &now))
|
||||
return EINVAL;
|
||||
delta = timespec_subz (abs_deadline, now);
|
||||
clock_gettime (CLOCK_REALTIME, &now);
|
||||
abs_deadline = timespec_add (now, delta);
|
||||
}
|
||||
|
||||
e = errno;
|
||||
rc = sys_sem_timedwait (f->id, &abs_deadline);
|
||||
STRACE ("sem_timedwait(%ld, %s) → %d% m", f->id,
|
||||
|
|
2
third_party/nsync/mu_wait.h
vendored
2
third_party/nsync/mu_wait.h
vendored
|
@ -97,7 +97,7 @@ void nsync_mu_wait(nsync_mu *mu, int (*condition)(const void *condition_arg),
|
|||
int nsync_mu_wait_with_deadline(
|
||||
nsync_mu *mu, int (*condition)(const void *condition_arg),
|
||||
const void *condition_arg,
|
||||
int (*condition_arg_eq)(const void *a, const void *b),
|
||||
int (*condition_arg_eq)(const void *a, const void *b), int clock,
|
||||
nsync_time abs_deadline, struct nsync_note_s_ *cancel_note);
|
||||
|
||||
/* Unlock *mu, which must be held in write mode, and wake waiters, if
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "third_party/nsync/mu_wait.h"
|
||||
#include "third_party/nsync/testing/closure.h"
|
||||
#include "third_party/nsync/testing/smprintf.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/testing/testing.h"
|
||||
|
||||
/* A cv_stress_data represents the data used by the threads of the tests below. */
|
||||
|
@ -79,7 +80,7 @@ static void cv_stress_inc_loop (cv_stress_data *s, uintmax_t count_imod4) {
|
|||
nsync_time_us (rand () % STRESS_MAX_DELAY_MICROS));
|
||||
while (nsync_cv_wait_with_deadline (
|
||||
&s->count_is_imod4[count_imod4],
|
||||
&s->mu, abs_deadline, NULL) != 0 &&
|
||||
&s->mu, CLOCK_REALTIME, abs_deadline, NULL) != 0 &&
|
||||
(s->count&3) != count_imod4) {
|
||||
nsync_mu_assert_held (&s->mu);
|
||||
s->timeouts++;
|
||||
|
@ -130,7 +131,8 @@ static void cv_stress_reader_loop (cv_stress_data *s, uintmax_t count_imod4) {
|
|||
abs_deadline = nsync_time_add (nsync_time_now (),
|
||||
nsync_time_us (rand () % STRESS_MAX_DELAY_MICROS));
|
||||
while (nsync_cv_wait_with_deadline (&s->count_is_imod4[count_imod4],
|
||||
&s->mu, abs_deadline, NULL) != 0 &&
|
||||
&s->mu, CLOCK_REALTIME,
|
||||
abs_deadline, NULL) != 0 &&
|
||||
(s->count&3) != count_imod4 && s->refs != 0) {
|
||||
|
||||
nsync_mu_rassert_held (&s->mu);
|
||||
|
|
11
third_party/nsync/testing/cv_test.c
vendored
11
third_party/nsync/testing/cv_test.c
vendored
|
@ -29,6 +29,7 @@
|
|||
#include "third_party/nsync/testing/smprintf.h"
|
||||
#include "third_party/nsync/testing/testing.h"
|
||||
#include "third_party/nsync/testing/time_extra.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/time.h"
|
||||
|
||||
/* --------------------------- */
|
||||
|
@ -63,7 +64,7 @@ static int cv_queue_put (cv_queue *q, void *v, nsync_time abs_deadline) {
|
|||
int wake = 0;
|
||||
nsync_mu_lock (&q->mu);
|
||||
while (q->count == q->limit &&
|
||||
nsync_cv_wait_with_deadline (&q->non_full, &q->mu, abs_deadline, NULL) == 0) {
|
||||
nsync_cv_wait_with_deadline (&q->non_full, &q->mu, CLOCK_REALTIME, abs_deadline, NULL) == 0) {
|
||||
}
|
||||
if (q->count != q->limit) {
|
||||
int i = q->pos + q->count;
|
||||
|
@ -91,7 +92,7 @@ static void *cv_queue_get (cv_queue *q, nsync_time abs_deadline) {
|
|||
void *v = NULL;
|
||||
nsync_mu_lock (&q->mu);
|
||||
while (q->count == 0 &&
|
||||
nsync_cv_wait_with_deadline (&q->non_empty, &q->mu, abs_deadline, NULL) == 0) {
|
||||
nsync_cv_wait_with_deadline (&q->non_empty, &q->mu, CLOCK_REALTIME, abs_deadline, NULL) == 0) {
|
||||
}
|
||||
if (q->count != 0) {
|
||||
v = q->data[q->pos];
|
||||
|
@ -237,7 +238,7 @@ static void test_cv_deadline (testing t) {
|
|||
nsync_time expected_end_time;
|
||||
start_time = nsync_time_now ();
|
||||
expected_end_time = nsync_time_add (start_time, nsync_time_ms (87));
|
||||
if (nsync_cv_wait_with_deadline (&cv, &mu, expected_end_time,
|
||||
if (nsync_cv_wait_with_deadline (&cv, &mu, CLOCK_REALTIME, expected_end_time,
|
||||
NULL) != ETIMEDOUT) {
|
||||
TEST_FATAL (t, ("nsync_cv_wait() returned non-expired for a timeout"));
|
||||
}
|
||||
|
@ -289,7 +290,7 @@ static void test_cv_cancel (testing t) {
|
|||
|
||||
cancel = nsync_note_new (NULL, expected_end_time);
|
||||
|
||||
x = nsync_cv_wait_with_deadline (&cv, &mu, future_time, cancel);
|
||||
x = nsync_cv_wait_with_deadline (&cv, &mu, CLOCK_REALTIME, future_time, cancel);
|
||||
if (x != ECANCELED) {
|
||||
TEST_FATAL (t, ("nsync_cv_wait() returned non-cancelled (%d) for "
|
||||
"a cancellation; expected %d",
|
||||
|
@ -308,7 +309,7 @@ static void test_cv_cancel (testing t) {
|
|||
/* Check that an already cancelled wait returns immediately. */
|
||||
start_time = nsync_time_now ();
|
||||
|
||||
x = nsync_cv_wait_with_deadline (&cv, &mu, nsync_time_no_deadline, cancel);
|
||||
x = nsync_cv_wait_with_deadline (&cv, &mu, CLOCK_REALTIME, nsync_time_no_deadline, cancel);
|
||||
if (x != ECANCELED) {
|
||||
TEST_FATAL (t, ("nsync_cv_wait() returned non-cancelled (%d) for "
|
||||
"a cancellation; expected %d",
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "third_party/nsync/testing/closure.h"
|
||||
#include "third_party/nsync/testing/smprintf.h"
|
||||
#include "third_party/nsync/testing/testing.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/testing/time_extra.h"
|
||||
|
||||
/* Example use of CV.wait(): A priority queue of strings whose
|
||||
|
@ -74,7 +75,8 @@ static const char *string_priority_queue_cv_remove_with_deadline (string_priorit
|
|||
const char *s = NULL;
|
||||
nsync_mu_lock (&q->mu);
|
||||
while (A_LEN (&q->heap) == 0 &&
|
||||
nsync_cv_wait_with_deadline (&q->non_empty, &q->mu, abs_deadline, NULL) == 0) {
|
||||
nsync_cv_wait_with_deadline (&q->non_empty, &q->mu, CLOCK_REALTIME,
|
||||
abs_deadline, NULL) == 0) {
|
||||
}
|
||||
alen = A_LEN (&q->heap);
|
||||
if (alen != 0) {
|
||||
|
|
4
third_party/nsync/testing/mu_test.c
vendored
4
third_party/nsync/testing/mu_test.c
vendored
|
@ -24,6 +24,7 @@
|
|||
#include "third_party/nsync/testing/closure.h"
|
||||
#include "third_party/nsync/testing/smprintf.h"
|
||||
#include "third_party/nsync/testing/testing.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "third_party/nsync/testing/time_extra.h"
|
||||
|
||||
/* The state shared between the threads in each of the tests below. */
|
||||
|
@ -67,6 +68,7 @@ static void test_data_wait_for_all_threads (test_data *td) {
|
|||
while (td->finished_threads != td->n_threads) {
|
||||
nsync_cv_wait_with_deadline_generic (&td->done, td->mu_in_use,
|
||||
td->lock, td->unlock,
|
||||
CLOCK_REALTIME,
|
||||
nsync_time_no_deadline, NULL);
|
||||
}
|
||||
(*td->unlock) (td->mu_in_use);
|
||||
|
@ -303,7 +305,7 @@ static int counter_wait_for_zero_with_deadline (counter *c, nsync_time abs_deadl
|
|||
int value;
|
||||
nsync_mu_rlock (&c->mu);
|
||||
while (c->value != 0 &&
|
||||
nsync_cv_wait_with_deadline (&c->cv, &c->mu, abs_deadline, NULL) == 0) {
|
||||
nsync_cv_wait_with_deadline (&c->cv, &c->mu, CLOCK_REALTIME, abs_deadline, NULL) == 0) {
|
||||
}
|
||||
value = c->value;
|
||||
nsync_mu_runlock (&c->mu);
|
||||
|
|
5
third_party/nsync/testing/pingpong_test.c
vendored
5
third_party/nsync/testing/pingpong_test.c
vendored
|
@ -107,6 +107,7 @@ static void mutex_cv_ping_pong (ping_pong *pp, int parity) {
|
|||
nsync_cv_wait_with_deadline_generic (&pp->cv[parity], &pp->mutex,
|
||||
&void_pthread_mutex_lock,
|
||||
&void_pthread_mutex_unlock,
|
||||
CLOCK_REALTIME,
|
||||
nsync_time_no_deadline, NULL);
|
||||
}
|
||||
pp->i++;
|
||||
|
@ -163,7 +164,8 @@ static void mu_cv_unexpired_deadline_ping_pong (ping_pong *pp, int parity) {
|
|||
while (pp->i < pp->limit) {
|
||||
while ((pp->i & 1) == parity) {
|
||||
nsync_cv_wait_with_deadline (&pp->cv[parity], &pp->mu,
|
||||
deadline_in1hour, NULL);
|
||||
CLOCK_REALTIME, deadline_in1hour,
|
||||
NULL);
|
||||
}
|
||||
pp->i++;
|
||||
nsync_cv_signal (&pp->cv[1 - parity]);
|
||||
|
@ -318,6 +320,7 @@ static void rw_mutex_cv_ping_pong (ping_pong *pp, int parity) {
|
|||
nsync_cv_wait_with_deadline_generic (&pp->cv[parity], &pp->rwmutex,
|
||||
&void_pthread_rwlock_wrlock,
|
||||
&void_pthread_rwlock_unlock,
|
||||
CLOCK_REALTIME,
|
||||
nsync_time_no_deadline, NULL);
|
||||
}
|
||||
pp->i++;
|
||||
|
|
2
third_party/nsync/waiter.h
vendored
2
third_party/nsync/waiter.h
vendored
|
@ -102,7 +102,7 @@ struct nsync_waitable_s {
|
|||
mu/lock/unlock are used to acquire and release the relevant locks
|
||||
whan waiting on condition variables. */
|
||||
int nsync_wait_n(void *mu, void (*lock)(void *), void (*unlock)(void *),
|
||||
nsync_time abs_deadline, int count,
|
||||
int clock, nsync_time abs_deadline, int count,
|
||||
struct nsync_waitable_s *waitable[]);
|
||||
|
||||
/* A "struct nsync_waitable_s" implementation must implement these
|
||||
|
|
2
third_party/openmp/kmp_lock.cpp
vendored
2
third_party/openmp/kmp_lock.cpp
vendored
|
@ -380,7 +380,7 @@ __kmp_acquire_futex_lock_timed_template(kmp_futex_lock_t *lck, kmp_int32 gtid) {
|
|||
|
||||
long rc;
|
||||
#ifdef __COSMOPOLITAN__
|
||||
if ((rc = nsync_futex_wait_((int *)&(lck->lk.poll), poll_val, false, NULL)) != 0) {
|
||||
if ((rc = nsync_futex_wait_((int *)&(lck->lk.poll), poll_val, false, 0, NULL)) != 0) {
|
||||
#else
|
||||
if ((rc = syscall(__NR_futex, (int *)&(lck->lk.poll), FUTEX_WAIT, poll_val, NULL,
|
||||
NULL, 0)) != 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue