mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-31 15:00:28 +00:00
Write more runtime tests and fix bugs
This change adds tests for the new memory manager code particularly with its windows support. Function call tracing now works reliably on Silicon since our function hooker was missing new Apple self-modifying code APIs Many tests that were disabled a long time ago on aarch64 are reactivated by this change, now that arm support is on equal terms with x86. There's been a lot of places where ftrace could cause deadlocks, which have been hunted down across all platforms thanks to new tests. A bug in Windows's kill() function has been identified.
This commit is contained in:
parent
0b3c81dd4e
commit
f24c854b28
45 changed files with 550 additions and 872 deletions
28
third_party/nsync/common.c
vendored
28
third_party/nsync/common.c
vendored
|
@ -110,6 +110,8 @@ uint32_t nsync_spin_test_and_set_ (nsync_atomic_uint32_ *w, uint32_t test,
|
|||
|
||||
/* ====================================================================================== */
|
||||
|
||||
#if NSYNC_DEBUG
|
||||
|
||||
struct nsync_waiter_s *nsync_dll_nsync_waiter_ (struct Dll *e) {
|
||||
struct nsync_waiter_s *nw = DLL_CONTAINER(struct nsync_waiter_s, q, e);
|
||||
ASSERT (nw->tag == NSYNC_WAITER_TAG);
|
||||
|
@ -133,6 +135,8 @@ waiter *nsync_dll_waiter_samecond_ (struct Dll *e) {
|
|||
return (w);
|
||||
}
|
||||
|
||||
#endif /* NSYNC_DEBUG */
|
||||
|
||||
/* -------------------------------- */
|
||||
|
||||
// TODO(jart): enforce in dbg mode once off-by-one flake is fixed
|
||||
|
@ -249,8 +253,10 @@ static bool free_waiters_populate (void) {
|
|||
return (false);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
waiter *w = &waiters[i];
|
||||
#if NSYNC_DEBUG
|
||||
w->tag = WAITER_TAG;
|
||||
w->nw.tag = NSYNC_WAITER_TAG;
|
||||
#endif
|
||||
if (!nsync_mu_semaphore_init (&w->sem)) {
|
||||
if (!i) {
|
||||
// netbsd can run out of semaphores
|
||||
|
@ -327,18 +333,26 @@ void nsync_waiter_wipe_ (void) {
|
|||
nsync_mu_semaphore_destroy (&w->sem);
|
||||
for (w = wall; w; w = next) {
|
||||
next = w->next_all;
|
||||
w->tag = 0;
|
||||
w->flags = 0;
|
||||
w->nw.tag = 0;
|
||||
#if NSYNC_DEBUG
|
||||
w->tag = WAITER_TAG;
|
||||
w->nw.tag = NSYNC_WAITER_TAG;
|
||||
#endif
|
||||
w->nw.flags = NSYNC_WAITER_FLAG_MUCV;
|
||||
atomic_init(&w->nw.waiting, 0);
|
||||
w->l_type = 0;
|
||||
bzero (&w->cond, sizeof (w->cond));
|
||||
w->cond.f = 0;
|
||||
w->cond.v = 0;
|
||||
w->cond.eq = 0;
|
||||
dll_init (&w->same_condition);
|
||||
if (w->wipe_mu)
|
||||
bzero (w->wipe_mu, sizeof (*w->wipe_mu));
|
||||
if (w->wipe_cv)
|
||||
bzero (w->wipe_cv, sizeof (*w->wipe_cv));
|
||||
if (w->wipe_mu) {
|
||||
atomic_init(&w->wipe_mu->word, 0);
|
||||
w->wipe_mu->waiters = 0;
|
||||
}
|
||||
if (w->wipe_cv) {
|
||||
atomic_init(&w->wipe_cv->word, 0);
|
||||
w->wipe_cv->waiters = 0;
|
||||
}
|
||||
if (!nsync_mu_semaphore_init (&w->sem))
|
||||
continue; /* leak it */
|
||||
w->next_free = prev;
|
||||
|
|
11
third_party/nsync/common.internal.h
vendored
11
third_party/nsync/common.internal.h
vendored
|
@ -9,15 +9,10 @@
|
|||
#include "third_party/nsync/mu_semaphore.h"
|
||||
#include "third_party/nsync/note.h"
|
||||
#include "third_party/nsync/time.h"
|
||||
#include "third_party/nsync/defs.h"
|
||||
#include "third_party/nsync/wait_s.internal.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#ifdef MODE_DBG
|
||||
#define NSYNC_DEBUG 1
|
||||
#else
|
||||
#define NSYNC_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* Yield the CPU. Platform specific. */
|
||||
void nsync_yield_(void);
|
||||
|
||||
|
@ -191,13 +186,15 @@ struct wait_condition_s {
|
|||
ATM_STORE_REL (&w.waiting, 0);
|
||||
nsync_mu_semaphore_v (&w.sem); */
|
||||
typedef struct waiter_s {
|
||||
#if NSYNC_DEBUG
|
||||
uint32_t tag; /* Debug DLL_NSYNC_WAITER, DLL_WAITER, DLL_WAITER_SAMECOND. */
|
||||
#endif
|
||||
int flags; /* See WAITER_* bits below. */
|
||||
nsync_atomic_uint32_ remove_count; /* Monotonic count of removals from queue. */
|
||||
nsync_semaphore sem; /* Thread waits on this semaphore. */
|
||||
struct nsync_waiter_s nw; /* An embedded nsync_waiter_s. */
|
||||
struct nsync_mu_s_ *cv_mu; /* Pointer to nsync_mu associated with a cv wait. */
|
||||
lock_type *l_type; /* Lock type of the mu, or nil if not associated with a mu. */
|
||||
nsync_atomic_uint32_ remove_count; /* Monotonic count of removals from queue. */
|
||||
struct wait_condition_s cond; /* A condition on which to acquire a mu. */
|
||||
struct Dll same_condition; /* Links neighbours in nw.q with same non-nil condition. */
|
||||
struct waiter_s * next_all;
|
||||
|
|
12
third_party/nsync/defs.h
vendored
Normal file
12
third_party/nsync/defs.h
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef COSMOPOLITAN_THIRD_PARTY_NSYNC_DEFS_H_
|
||||
#define COSMOPOLITAN_THIRD_PARTY_NSYNC_DEFS_H_
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#ifdef MODE_DBG
|
||||
#define NSYNC_DEBUG 1
|
||||
#else
|
||||
#define NSYNC_DEBUG 0
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_NSYNC_DEFS_H_ */
|
9
third_party/nsync/mem/nsync_debug.c
vendored
9
third_party/nsync/mem/nsync_debug.c
vendored
|
@ -20,6 +20,7 @@
|
|||
#include "third_party/nsync/common.internal.h"
|
||||
#include "third_party/nsync/mu_semaphore.h"
|
||||
#include "third_party/nsync/races.internal.h"
|
||||
#include "third_party/nsync/defs.h"
|
||||
#include "third_party/nsync/wait_s.internal.h"
|
||||
__static_yoink("nsync_notice");
|
||||
|
||||
|
@ -148,15 +149,23 @@ static void emit_waiters (struct emit_buf *b, struct Dll *list) {
|
|||
waiter *w = DLL_WAITER (p);
|
||||
next = NULL;
|
||||
emit_print (b, " %i", (uintptr_t) w);
|
||||
#if NSYNC_DEBUG
|
||||
if (w->tag != WAITER_TAG) {
|
||||
emit_print (b, "bad WAITER_TAG %i",
|
||||
(uintptr_t) w->tag);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
next = dll_next (list, p);
|
||||
#if NSYNC_DEBUG
|
||||
if (nw->tag != NSYNC_WAITER_TAG) {
|
||||
emit_print (b, " bad WAITER_TAG %i",
|
||||
(uintptr_t) nw->tag);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
emit_print (b, " embedded=%i waiting=%i",
|
||||
(uintptr_t) (w->flags & NSYNC_WAITER_FLAG_MUCV),
|
||||
(uintptr_t) ATM_LOAD (&nw->waiting));
|
||||
|
|
2
third_party/nsync/mem/nsync_sem_wait.c
vendored
2
third_party/nsync/mem/nsync_sem_wait.c
vendored
|
@ -40,7 +40,9 @@ int nsync_sem_wait_with_cancel_ (waiter *w, int clock, nsync_time abs_deadline,
|
|||
sem_outcome = ECANCELED;
|
||||
if (nsync_time_cmp (cancel_time, nsync_time_zero) > 0) {
|
||||
struct nsync_waiter_s nw;
|
||||
#if NSYNC_DEBUG
|
||||
nw.tag = NSYNC_WAITER_TAG;
|
||||
#endif
|
||||
nw.sem = &w->sem;
|
||||
dll_init (&nw.q);
|
||||
ATM_STORE (&nw.waiting, 1);
|
||||
|
|
2
third_party/nsync/mem/nsync_wait.c
vendored
2
third_party/nsync/mem/nsync_wait.c
vendored
|
@ -51,7 +51,9 @@ int nsync_wait_n (void *mu, void (*lock) (void *), void (*unlock) (void *),
|
|||
nw = (struct nsync_waiter_s *) malloc (count * sizeof (nw[0]));
|
||||
}
|
||||
for (i = 0; i != count && enqueued; i++) {
|
||||
#if NSYNC_DEBUG
|
||||
nw[i].tag = NSYNC_WAITER_TAG;
|
||||
#endif
|
||||
nw[i].sem = &w->sem;
|
||||
dll_init (&nw[i].q);
|
||||
ATM_STORE (&nw[i].waiting, 0);
|
||||
|
|
1
third_party/nsync/mu.h
vendored
1
third_party/nsync/mu.h
vendored
|
@ -48,7 +48,6 @@ COSMOPOLITAN_C_START_
|
|||
*/
|
||||
typedef struct nsync_mu_s_ {
|
||||
nsync_atomic_uint32_ word; /* internal use only */
|
||||
int _zero; /* c pthread_mutex_t */
|
||||
struct Dll *waiters; /* internal use only */
|
||||
} nsync_mu;
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef struct cv_stress_data_s {
|
|||
/* The delays in cv_stress_inc_loop(), cv_stress_reader_loop(), mu_stress_inc_loop(),
|
||||
and mu_stress_reader_loop() are uniformly distributed from 0 to
|
||||
STRESS_MAX_DELAY_MICROS-1 microseconds. */
|
||||
#define STRESS_MAX_DELAY_MICROS (IsNetbsd() || IsOpenbsd() ? 20000 : 4000) /* maximum delay */
|
||||
#define STRESS_MAX_DELAY_MICROS (IsNetbsd() || IsOpenbsd() ? 30000 : 4000) /* maximum delay */
|
||||
#define STRESS_MEAN_DELAY_MICROS (STRESS_MAX_DELAY_MICROS / 2) /* mean delay */
|
||||
#define STRESS_EXPECT_TIMEOUTS_PER_SEC (1000000 / STRESS_MEAN_DELAY_MICROS) /* expect timeouts/s*/
|
||||
|
||||
|
|
3
third_party/nsync/testing/note_test.c
vendored
3
third_party/nsync/testing/note_test.c
vendored
|
@ -20,6 +20,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/dce.h"
|
||||
#include "third_party/nsync/time.h"
|
||||
|
||||
/* Verify the properties of a prenotified note. */
|
||||
|
@ -78,7 +79,7 @@ static void test_note_unnotified (testing t) {
|
|||
TEST_ERROR (t, ("timed wait on unnotified note returned too quickly (1s wait took %s)",
|
||||
nsync_time_str (waited, 2)));
|
||||
}
|
||||
if (nsync_time_cmp (waited, nsync_time_ms (2000)) > 0) {
|
||||
if (nsync_time_cmp (waited, nsync_time_ms (IsNetbsd() || IsOpenbsd() || IsFreebsd() ? 4000 : 2000)) > 0) {
|
||||
TEST_ERROR (t, ("timed wait on unnotified note returned too slowly (1s wait took %s)",
|
||||
nsync_time_str (waited, 2)));
|
||||
}
|
||||
|
|
5
third_party/nsync/wait_s.internal.h
vendored
5
third_party/nsync/wait_s.internal.h
vendored
|
@ -1,6 +1,7 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_WAIT_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_WAIT_INTERNAL_H_
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "third_party/nsync/defs.h"
|
||||
#include "third_party/nsync/atomic.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
@ -10,10 +11,12 @@ COSMOPOLITAN_C_START_
|
|||
with v pointing to the client's object and nw pointing to a struct
|
||||
nsync_waiter_s. */
|
||||
struct nsync_waiter_s {
|
||||
#if NSYNC_DEBUG
|
||||
uint32_t tag; /* used for debugging */
|
||||
#endif
|
||||
uint32_t flags; /* see below */
|
||||
struct Dll q; /* used to link children of parent */
|
||||
nsync_atomic_uint32_ waiting; /* non-zero <=> the waiter is waiting */
|
||||
struct Dll q; /* used to link children of parent */
|
||||
struct nsync_semaphore_s_ *sem; /* *sem will be Ved when waiter is woken */
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue