mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-03 11:12:27 +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
|
@ -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++;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue