Iterate more on recent changes

This commit is contained in:
Justine Tunney 2023-11-10 22:55:33 -08:00
parent 7138399f96
commit d0ad2694ed
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
22 changed files with 90 additions and 158 deletions

View file

@ -41,6 +41,8 @@ static const char *GetFrameName(int x) {
return "stack";
} else if (IsGfdsFrame(x)) {
return "g_fds";
} else if (IsNsyncFrame(x)) {
return "nsync";
} else if (IsZiposFrame(x)) {
return "zipos";
} else if (IsMemtrackFrame(x)) {

View file

@ -44,11 +44,9 @@ static void *_mapframe_impl(void *p, int f) {
if (!rc) {
return p;
} else {
unassert(errno == ENOMEM);
return 0;
}
} else {
unassert(errno == ENOMEM);
return 0;
}
}
@ -86,12 +84,16 @@ static void *_mapframe(void *p, int f) {
*/
void *_extend(void *p, size_t n, void *e, int f, intptr_t h) {
char *q;
unassert(!((uintptr_t)SHADOW(p) & (G - 1)));
unassert((uintptr_t)p + (G << kAsanScale) <= h);
#ifndef NDEBUG
if ((uintptr_t)SHADOW(p) & (G - 1)) notpossible;
if ((uintptr_t)p + (G << kAsanScale) > h) notpossible;
#endif
// TODO(jart): Make this spin less in non-ASAN mode.
for (q = e; q < ((char *)p + n); q += 8) {
if (!((uintptr_t)q & (G - 1))) {
unassert(q + G <= (char *)h);
#ifndef NDEBUG
if (q + G > (char *)h) notpossible;
#endif
if (!_mapframe(q, f)) return 0;
if (IsAsan()) {
if (!((uintptr_t)SHADOW(q) & (G - 1))) {

View file

@ -19,6 +19,8 @@
#include "libc/runtime/memtrack.internal.h"
#include "libc/thread/thread.h"
// nsync depends on this non-nsync lock
extern pthread_mutex_t __mmi_lock_obj;
void __mmi_lock(void) {

View file

@ -21,9 +21,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/describentoverlapped.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/internal.h"
__msabi extern typeof(WSARecv) *const __imp_WSARecv;

View file

@ -20,6 +20,7 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/describentoverlapped.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"

View file

@ -25,6 +25,12 @@
#define _X86_CC_AVX2 0
#endif
#ifdef __F16C__
#define _X86_CC_F16C 1
#else
#define _X86_CC_F16C 0
#endif
#ifdef __AVXVNNI__
#define _X86_CC_AVXVNNI 1
#else

View file

@ -64,7 +64,7 @@
#define X86_DTES64 1H, ECX, 2, 0
#define X86_ERMS 7H, EBX, 9, 0 /* broaadwell c. 2014 */
#define X86_EST 1H, ECX, 7, 0
#define X86_F16C 1H, ECX, 29, 0
#define X86_F16C 1H, ECX, 29, _X86_CC_F16C
#define X86_FDP_EXCPTN_ONLY 7H, EBX, 6, 0
#define X86_FLUSH_L1D 7H, EDX, 28, 0
#define X86_FMA 1H, ECX, 12, _X86_CC_FMA /* haswell c. 2013 */

View file

@ -288,9 +288,6 @@ static textwindows errno_t posix_spawn_nt_impl(
char errno_buf[30];
char oflags_buf[128];
char openmode_buf[15];
(void)errno_buf;
(void)oflags_buf;
(void)openmode_buf;
switch (a->action) {
case _POSIX_SPAWN_CLOSE:
err = spawnfds_close(&fds, a->fildes);
@ -331,14 +328,13 @@ static textwindows errno_t posix_spawn_nt_impl(
// figure out flags
uint32_t dwCreationFlags = 0;
if (attrp && *attrp) {
if ((*attrp)->flags & POSIX_SPAWN_SETSID) {
short flags = attrp && *attrp ? (*attrp)->flags : 0;
if (flags & POSIX_SPAWN_SETSID) {
dwCreationFlags |= kNtDetachedProcess;
}
if ((*attrp)->flags & POSIX_SPAWN_SETPGROUP) {
if (flags & POSIX_SPAWN_SETPGROUP) {
dwCreationFlags |= kNtCreateNewProcessGroup;
}
}
// create process startinfo
struct NtStartupInfo startinfo = {
@ -361,8 +357,14 @@ static textwindows errno_t posix_spawn_nt_impl(
}
// inherit signal mask
sigset_t childmask;
char maskvar[6 + 21];
FormatUint64(stpcpy(maskvar, "_MASK="), sigmask);
if (flags & POSIX_SPAWN_SETSIGMASK) {
childmask = (*attrp)->sigmask;
} else {
childmask = sigmask;
}
FormatUint64(stpcpy(maskvar, "_MASK="), childmask);
// launch process
int rc = -1;
@ -490,7 +492,7 @@ errno_t posix_spawn(int *pid, const char *path,
}
if (!(child = vfork())) {
can_clobber = true;
sigset_t *childmask;
sigset_t childmask;
bool lost_cloexec = 0;
struct sigaction dfl = {0};
short flags = attrp && *attrp ? (*attrp)->flags : 0;
@ -599,11 +601,11 @@ errno_t posix_spawn(int *pid, const char *path,
fcntl(pfds[1], F_SETFD, FD_CLOEXEC);
}
if (flags & POSIX_SPAWN_SETSIGMASK) {
childmask = &(*attrp)->sigmask;
childmask = (*attrp)->sigmask;
} else {
childmask = &oldmask;
childmask = oldmask;
}
sigprocmask(SIG_SETMASK, childmask, 0);
sigprocmask(SIG_SETMASK, &childmask, 0);
if (!envp) envp = environ;
execve(path, argv, envp);
ChildFailed:

View file

@ -157,9 +157,13 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
// check if killed or win32 error
if (wi) {
if (pr && !--pr->waiters && pr->status == PROC_UNDEAD) {
if (pr) {
if (!--pr->waiters && pr->status == PROC_UNDEAD) {
__proc_free(pr);
}
} else {
--__proc.waiters;
}
__proc_unlock();
if (wi == 1) {
// __sig_cancel() woke our semaphore

View file

@ -17,6 +17,8 @@ COSMOPOLITAN_C_START_
#define kMemtrackSize (0x1ffffffc0000 - kMemtrackStart)
#define kFixedmapStart 0x300000040000
#define kFixedmapSize (0x400000040000 - kFixedmapStart)
#define kMemtrackNsyncStart 0x6fc000040000
#define kMemtrackNsyncSize (0x6fcffffc0000 - kMemtrackNsyncStart)
#define kMemtrackFdsStart 0x6fe000040000
#define kMemtrackFdsSize (0x6feffffc0000 - kMemtrackFdsStart)
#define kMemtrackZiposStart 0x6fd000040000
@ -114,6 +116,11 @@ forceinline pureconst bool IsGfdsFrame(int x) {
x <= (int)((kMemtrackFdsStart + kMemtrackFdsSize - 1) >> 16);
}
forceinline pureconst bool IsNsyncFrame(int x) {
return (int)(kMemtrackNsyncStart >> 16) <= x &&
x <= (int)((kMemtrackNsyncStart + kMemtrackNsyncSize - 1) >> 16);
}
forceinline pureconst bool IsZiposFrame(int x) {
return (int)(kMemtrackZiposStart >> 16) <= x &&
x <= (int)((kMemtrackZiposStart + kMemtrackZiposSize - 1) >> 16);

View file

@ -1808,7 +1808,7 @@
6f900000-6f9fffff 64gb free
6fa00000-6fafffff 64gb free
6fb00000-6fbfffff 64gb free
6fc00004-6fcffffb 64gb free
6fc00004-6fcffffb 64gb nsync
6fd00004-6fdffffb 64gb zipos
6fe00004-6feffffb 64gb g_fds
6ff00004-70000003 64gb free

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/ucontext.h"
#include "libc/dce.h"
#include "libc/log/check.h"
@ -33,6 +34,8 @@ void OnUsr1(int sig) {
}
void SetUpOnce(void) {
sigset_t ss;
sigprocmask(SIG_SETMASK, 0, &ss);
ASSERT_SYS(0, 0, pledge("stdio proc", 0));
}

View file

@ -1,69 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/atomic.h"
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#include "libc/testlib/subprocess.h"
#include "libc/testlib/testlib.h"
#include "libc/thread/thread.h"
// create a bunch of threads with nsync semaphore waiter objects
// then fork and verify that unlocking in child safely cleans up
// this test matters on netbsd, where waiters have a file number
#define N 10
pthread_t thread[N];
atomic_uint countdown = N;
atomic_uint final_countdown = N;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *WaitWorker(void *arg) {
ASSERT_EQ(0, pthread_mutex_lock(&lock));
--countdown;
ASSERT_EQ(0, pthread_cond_wait(&cond, &lock));
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
ASSERT_EQ(0, pthread_mutex_lock(&lock));
--final_countdown;
ASSERT_EQ(0, pthread_cond_wait(&cond, &lock));
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
return 0;
}
TEST(mu_semaphore_sem, test) {
for (int i = 0; i < N; ++i) {
ASSERT_EQ(0, pthread_create(thread + i, 0, WaitWorker, 0));
}
while (countdown) pthread_yield();
SPAWN(fork);
CheckForFileLeaks();
EXITS(0);
ASSERT_EQ(0, pthread_mutex_lock(&lock));
ASSERT_EQ(0, pthread_cond_broadcast(&cond));
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
while (final_countdown) pthread_yield(); // make extra sure still works
ASSERT_EQ(0, pthread_mutex_lock(&lock));
ASSERT_EQ(0, pthread_cond_broadcast(&cond));
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
for (int i = 0; i < N; ++i) {
ASSERT_EQ(0, pthread_join(thread[i], 0));
}
CheckForFileLeaks();
}

View file

@ -19,7 +19,12 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/dll.h"
#include "libc/intrin/extend.internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/thread/tls.h"
@ -149,36 +154,28 @@ waiter *nsync_dll_waiter_samecond_ (struct Dll *e) {
/* -------------------------------- */
#define kMallocBlockSize 16384
static struct {
nsync_atomic_uint32_ mu;
size_t used;
char *block;
char *p, *e;
} malloc;
static void *nsync_malloc (size_t size) {
void *res;
ASSERT (size <= kMallocBlockSize);
if (IsWindows ()) {
res = HeapAlloc (GetProcessHeap (), 0, size);
if (!res) {
nsync_panic_ ("out of memory\n");
}
} else {
void *res = 0;
nsync_spin_test_and_set_ (&malloc.mu, 1, 1, 0);
if (!malloc.block || malloc.used + size > kMallocBlockSize) {
malloc.used = 0;
malloc.block = __sys_mmap (0, kMallocBlockSize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, 0);
if (malloc.block == MAP_FAILED) {
if (malloc.p + malloc.used + size > malloc.e) {
if (!malloc.p) {
malloc.p = malloc.e = (char *)kMemtrackNsyncStart;
}
malloc.e = _extend (malloc.p, malloc.used + size, malloc.e, MAP_PRIVATE,
kMemtrackNsyncStart + kMemtrackNsyncSize);
if (!malloc.e) {
nsync_panic_ ("out of memory\n");
}
}
res = malloc.block + malloc.used;
res = malloc.p + malloc.used;
malloc.used = (malloc.used + size + 15) & -16;
ATM_STORE_REL (&malloc.mu, 0);
}
return res;
}

View file

@ -40,7 +40,7 @@ uint32_t nsync_spin_test_and_set_(nsync_atomic_uint32_ *w, uint32_t test,
uint32_t set, uint32_t clear);
/* Abort after printing the nul-temrinated string s[]. */
void nsync_panic_(const char *s);
void nsync_panic_(const char *s) wontreturn;
/* ---------- */

View file

@ -42,15 +42,6 @@ void nsync_mu_semaphore_init (nsync_semaphore *s) {
}
}
/* Releases system resources associated with *s. */
void nsync_mu_semaphore_destroy (nsync_semaphore *s) {
if (PREFER_GCD_OVER_ULOCK && IsXnuSilicon ()) {
return nsync_mu_semaphore_destroy_gcd (s);
} else if (IsNetbsd ()) {
return nsync_mu_semaphore_destroy_sem (s);
}
}
/* Wait until the count of *s exceeds 0, and decrement it. If POSIX cancellations
are currently disabled by the thread, then this function always succeeds. When
they're enabled in MASKED mode, this function may return ECANCELED. Otherwise,

View file

@ -11,9 +11,6 @@ typedef struct nsync_semaphore_s_ {
/* Initialize *s; the initial value is 0. */
void nsync_mu_semaphore_init(nsync_semaphore *s);
/* Releases system resources associated with *s. */
void nsync_mu_semaphore_destroy(nsync_semaphore *s);
/* Wait until the count of *s exceeds 0, and decrement it. */
errno_t nsync_mu_semaphore_p(nsync_semaphore *s);

View file

@ -11,13 +11,11 @@ errno_t nsync_mu_semaphore_p_with_deadline_futex(nsync_semaphore *, nsync_time);
void nsync_mu_semaphore_v_futex(nsync_semaphore *);
void nsync_mu_semaphore_init_sem(nsync_semaphore *);
void nsync_mu_semaphore_destroy_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);
void nsync_mu_semaphore_v_sem(nsync_semaphore *);
void nsync_mu_semaphore_init_gcd(nsync_semaphore *);
void nsync_mu_semaphore_destroy_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);
void nsync_mu_semaphore_v_gcd(nsync_semaphore *);

View file

@ -90,11 +90,6 @@ void nsync_mu_semaphore_init_gcd (nsync_semaphore *s) {
*(dispatch_semaphore_t *)s = dispatch_semaphore_create (0);
}
/* Releases system resources associated with *s. */
void nsync_mu_semaphore_destroy_gcd (nsync_semaphore *s) {
dispatch_release (*(dispatch_semaphore_t *)s);
}
/* Wait until the count of *s exceeds 0, and decrement it. If POSIX cancellations
are currently disabled by the thread, then this function always succeeds. When
they're enabled in MASKED mode, this function may return ECANCELED. Otherwise,

View file

@ -55,12 +55,24 @@ static struct {
static nsync_semaphore *sem_big_enough_for_sem = (nsync_semaphore *) (uintptr_t)(1 /
(sizeof (struct sem) <= sizeof (*sem_big_enough_for_sem)));
static void nsync_mu_semaphore_sem_create (struct sem *f) {
int lol;
f->id = 0;
ASSERT (!sys_sem_init (0, &f->id));
if ((lol = __sys_fcntl (f->id, F_DUPFD_CLOEXEC, 50)) >= 50) {
sys_close (f->id);
f->id = lol;
}
}
static void nsync_mu_semaphore_sem_fork_child (void) {
struct Dll *e;
struct sem *f;
for (e = dll_first (g_sems.list); e; e = dll_next (g_sems.list, e)) {
sys_close (SEM_CONTAINER (e)->id);
f = SEM_CONTAINER (e);
sys_close (f->id);
nsync_mu_semaphore_sem_create (f);
}
g_sems.list = 0; /* list memory is on dead thread stacks */
(void) pthread_spin_init (&g_sems.lock, 0);
}
@ -70,14 +82,8 @@ static void nsync_mu_semaphore_sem_init (void) {
/* Initialize *s; the initial value is 0. */
void nsync_mu_semaphore_init_sem (nsync_semaphore *s) {
int lol;
struct sem *f = (struct sem *) s;
f->id = 0;
ASSERT (!sys_sem_init (0, &f->id));
if ((lol = __sys_fcntl (f->id, F_DUPFD_CLOEXEC, 50)) >= 50) {
sys_close (f->id);
f->id = lol;
}
nsync_mu_semaphore_sem_create (f);
cosmo_once (&g_sems.once, nsync_mu_semaphore_sem_init);
pthread_spin_lock (&g_sems.lock);
dll_init (&f->list);
@ -86,17 +92,6 @@ void nsync_mu_semaphore_init_sem (nsync_semaphore *s) {
STRACE ("sem_init(0, [%ld]) → 0", f->id);
}
/* Releases system resources associated with *s. */
void nsync_mu_semaphore_destroy_sem (nsync_semaphore *s) {
int rc;
struct sem *f = (struct sem *) s;
ASSERT (!(rc = sys_sem_destroy (f->id)));
pthread_spin_lock (&g_sems.lock);
dll_remove (&g_sems.list, &f->list);
pthread_spin_unlock (&g_sems.lock);
STRACE ("sem_destroy(%ld) → %d", f->id, rc);
}
/* Wait until the count of *s exceeds 0, and decrement it. If POSIX cancellations
are currently disabled by the thread, then this function always succeeds. When
they're enabled in MASKED mode, this function may return ECANCELED. Otherwise,

View file

@ -25,7 +25,7 @@
/* Aborts after printing the nul-terminated string s[]. */
void nsync_panic_ (const char *s) {
tinyprint(2, "error: nsync panic: ", s, "\n",
tinyprint(2, "error: nsync panic: ", s,
"cosmoaddr2line ", program_invocation_name, " ",
DescribeBacktrace (__builtin_frame_address (0)), "\n",
NULL);

View file

@ -792,9 +792,6 @@ void Daemonize(void) {
}
int main(int argc, char *argv[]) {
/* #ifndef NDEBUG */
ShowCrashReports();
/* #endif */
GetOpts(argc, argv);
g_psk = GetRunitPsk();
signal(SIGPIPE, SIG_IGN);