Clean up some of the threading code

This commit is contained in:
Justine Tunney 2022-09-08 11:54:56 -07:00
parent 0547eabcd6
commit 9f963dc597
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
62 changed files with 175 additions and 582 deletions

33
examples/thread.c Normal file
View file

@ -0,0 +1,33 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/intrin/pthread.h"
#include "libc/stdio/stdio.h"
/**
* @fileoverview Basic POSIX Threads Example.
*
* $ make -j8 o//examples/thread.com
* $ o//examples/thread.com
* hi there
*
*/
void *worker(void *arg) {
fputs(arg, stdout);
return "there\n";
}
int main() {
void *result;
pthread_t id;
pthread_create(&id, 0, worker, "hi ");
pthread_join(id, &result);
fputs(result, stdout);
}

View file

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_
#include "libc/intrin/nopl.h"
#include "libc/intrin/pthread.h"
#include "libc/nexgen32e/threaded.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -9,6 +10,7 @@ hidden extern int __vforked;
hidden extern bool __time_critical;
hidden extern unsigned __sighandrvas[NSIG];
hidden extern unsigned __sighandflags[NSIG];
hidden extern pthread_mutex_t __fds_lock_obj;
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
void __fds_lock(void);

View file

@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/errno.h"
#include "libc/intrin/once.h"
#include "libc/intrin/pthread.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/symboliclink.h"
@ -35,17 +35,20 @@
__msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW;
static bool AllowedToCreateSymlinks(void) {
static _Bool g_winlink_allowed;
static pthread_once_t g_winlink_once;
static textwindows void InitializeWinlink(void) {
int64_t tok;
struct NtLuid id;
struct NtTokenPrivileges tp;
if (!OpenProcessToken(GetCurrentProcess(), kNtTokenAllAccess, &tok)) return 0;
if (!LookupPrivilegeValue(0, u"SeCreateSymbolicLinkPrivilege", &id)) return 0;
if (!OpenProcessToken(GetCurrentProcess(), kNtTokenAllAccess, &tok)) return;
if (!LookupPrivilegeValue(0, u"SeCreateSymbolicLinkPrivilege", &id)) return;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = id;
tp.Privileges[0].Attributes = kNtSePrivilegeEnabled;
if (!AdjustTokenPrivileges(tok, 0, &tp, sizeof(tp), 0, 0)) return 0;
return GetLastError() != kNtErrorNotAllAssigned;
if (!AdjustTokenPrivileges(tok, 0, &tp, sizeof(tp), 0, 0)) return;
g_winlink_allowed = GetLastError() != kNtErrorNotAllAssigned;
}
textwindows int sys_symlinkat_nt(const char *target, int newdirfd,
@ -79,7 +82,8 @@ textwindows int sys_symlinkat_nt(const char *target, int newdirfd,
// windows only lets administrators do this
// even then we're required to ask for permission
if (!_once(AllowedToCreateSymlinks())) {
pthread_once(&g_winlink_once, InitializeWinlink);
if (!g_winlink_allowed) {
return eperm();
}

View file

@ -84,7 +84,7 @@
#endif
#ifndef __cplusplus
#define HAVE_STDBOOL_H
#define HAVE_STDBOOL_H 1
#if __STDC_VERSION__ + 0 >= 201112
typedef _Bool bool;
#define true ((bool)+1)

View file

@ -29,7 +29,6 @@
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/weaken.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/internal.h"

View file

@ -16,13 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/thread/thread.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/pthread.h"
/**
* Returns thread descriptor of the current thread.
*/
cthread_t(cthread_self)(void) {
return (cthread_t)__get_tls();
void(__fds_lock)(void) {
pthread_mutex_lock(&__fds_lock_obj);
}
void(__fds_unlock)(void) {
pthread_mutex_unlock(&__fds_lock_obj);
}

View file

@ -17,10 +17,9 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/weaken.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/o.h"
@ -28,15 +27,7 @@
STATIC_YOINK("_init_g_fds");
struct Fds g_fds;
static pthread_mutex_t __fds_lock_obj;
void(__fds_lock)(void) {
pthread_mutex_lock(&__fds_lock_obj);
}
void(__fds_unlock)(void) {
pthread_mutex_unlock(&__fds_lock_obj);
}
pthread_mutex_t __fds_lock_obj;
static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) {
int64_t h;

View file

@ -25,7 +25,7 @@
* Returns process id.
*
* This function does not need to issue a system call. The PID is
* tracked by a global variable which is updated atfork(). The only
* tracked by a global variable which is updated at fork(). The only
* exception is when the process is vfork()'d in which case a system
* call shall be issued.
*

View file

@ -31,7 +31,6 @@
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/log/internal.h"

View file

@ -16,18 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/pthread.h"
#include "libc/runtime/memtrack.internal.h"
STATIC_YOINK("_init__mmi");
struct MemoryIntervals _mmi;
pthread_mutex_t __mmi_lock_obj; // recursive :'(
void(__mmi_lock)(void) {
pthread_mutex_lock(&__mmi_lock_obj);
}
void(__mmi_unlock)(void) {
pthread_mutex_unlock(&__mmi_lock_obj);
}

View file

@ -1,7 +1,7 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Copyright 2022 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
@ -16,28 +16,15 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/futex.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/thread/thread.h"
#include "libc/runtime/memtrack.internal.h"
int cthread_memory_wait32(int* addr, int val, const struct timespec* timeout) {
size_t size;
if (IsLinux() || IsOpenbsd()) {
return _futex_wait(addr, val, PTHREAD_PROCESS_SHARED, timeout);
} else {
return sched_yield();
}
extern pthread_mutex_t __mmi_lock_obj;
void(__mmi_lock)(void) {
pthread_mutex_lock(&__mmi_lock_obj);
}
int cthread_memory_wake32(int* addr, int n) {
if (IsLinux() || IsOpenbsd()) {
return _futex_wake(addr, n, PTHREAD_PROCESS_SHARED);
} else {
return 0;
}
void(__mmi_unlock)(void) {
pthread_mutex_unlock(&__mmi_lock_obj);
}

View file

@ -1,7 +1,7 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Copyright 2022 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
@ -16,47 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/cmpxchg.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
#include "libc/intrin/pthread.h"
static struct AtFork {
volatile size_t i;
struct AtForkCallback {
void (*fn)(void *);
void *arg;
} p[ATEXIT_MAX];
} g_atfork;
/**
* Registers function to be called by fork() in child.
*
* @return 0 on success, or -1 w/ errno
* @note vfork() won't invoke callbacks
* @asyncsignalsafe
*/
int atfork(void *fn, void *arg) {
size_t i;
for (;;) {
i = g_atfork.i;
if (i == ARRAYLEN(g_atfork.p)) return enomem();
if (_cmpxchg(&g_atfork.i, i, i + 1)) {
g_atfork.p[i] = (struct AtForkCallback){.fn = fn, .arg = arg};
return 0;
}
}
}
/**
* Triggers callbacks registered by atfork().
*
* @note only fork() should call this
* @asyncsignalsafe
*/
void __onfork(void) {
size_t i;
for (i = 0; i < g_atfork.i; ++i) {
g_atfork.p[i].fn(g_atfork.p[i].arg);
}
}
pthread_mutex_t __mmi_lock_obj; // recursive :'(

View file

@ -1,23 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_ONCE_H_
#define COSMOPOLITAN_LIBC_INTRIN_ONCE_H_
#include "libc/intrin/spinlock.h"
/* TODO(jart): DELETE */
#define _once(x) \
({ \
typeof(x) oncerc; \
static bool once; \
static typeof(oncerc) onceresult; \
_Alignas(64) static char oncelock; \
_spinlock(&oncelock); \
if (once) { \
oncerc = onceresult; \
} else { \
oncerc = onceresult = x; \
} \
_spunlock(&oncelock); \
oncerc; \
})
#endif /* COSMOPOLITAN_LIBC_INTRIN_ONCE_H_ */

View file

@ -1,8 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_
#define COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_
#define PTHREAD_ONCE_INIT 0
#define PTHREAD_KEYS_MAX 64
#define PTHREAD_STACK_MIN FRAMESIZE
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
@ -27,6 +25,7 @@
COSMOPOLITAN_C_START_
/* clang-format off */
#define PTHREAD_ONCE_INIT {0}
#define PTHREAD_COND_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
#define PTHREAD_BARRIER_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
#define PTHREAD_RWLOCK_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
@ -34,16 +33,22 @@ COSMOPOLITAN_C_START_
PTHREAD_PROCESS_DEFAULT}
/* clang-format on */
typedef void *pthread_t;
typedef uintptr_t pthread_t;
typedef int pthread_id_np_t;
typedef char pthread_condattr_t;
typedef char pthread_rwlockattr_t;
typedef char pthread_barrierattr_t;
typedef unsigned pthread_key_t;
typedef _Atomic(char) pthread_once_t;
typedef _Atomic(char) pthread_spinlock_t;
typedef void (*pthread_key_dtor)(void *);
typedef struct pthread_once_s {
_Atomic(char) lock;
} pthread_once_t;
typedef struct pthread_spinlock_s {
_Atomic(char) lock;
} pthread_spinlock_t;
typedef struct pthread_mutex_s {
char type;
char pshared;
@ -167,45 +172,26 @@ int pthread_barrier_destroy(pthread_barrier_t *);
int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *,
unsigned);
#define pthread_spin_init(pSpin, multiprocess) (*(pSpin) = 0)
#define pthread_spin_destroy(pSpin) (*(pSpin) = 0)
#define pthread_spin_init(pSpin, multiprocess) ((pSpin)->lock = 0, 0)
#define pthread_spin_destroy(pSpin) ((pSpin)->lock = -1, 0)
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407
extern const errno_t EBUSY;
#define pthread_spin_unlock(pSpin) \
(__atomic_store_n(pSpin, 0, __ATOMIC_RELAXED), 0)
#define pthread_spin_trylock(pSpin) \
(__atomic_test_and_set(pSpin, __ATOMIC_SEQ_CST) ? EBUSY : 0)
#ifdef TINY
#define pthread_spin_lock(pSpin) _pthread_spin_lock_tiny(pSpin)
#else
#define pthread_spin_lock(pSpin) _pthread_spin_lock_cooperative(pSpin)
#endif
#define _pthread_spin_lock_tiny(pSpin) \
({ \
while (__atomic_test_and_set(pSpin, __ATOMIC_SEQ_CST)) { \
__builtin_ia32_pause(); \
} \
0; \
#define pthread_spin_lock(pSpin) \
({ \
pthread_spinlock_t *_s = pSpin; \
while (__atomic_test_and_set(&_s->lock, __ATOMIC_SEQ_CST)) donothing; \
0; \
})
#define _pthread_spin_lock_cooperative(pSpin) \
({ \
char __x; \
volatile int __i; \
unsigned __tries = 0; \
pthread_spinlock_t *__lock = pSpin; \
for (;;) { \
__atomic_load(__lock, &__x, __ATOMIC_RELAXED); \
if (!__x && !__atomic_test_and_set(__lock, __ATOMIC_SEQ_CST)) { \
break; \
} else if (__tries < 7) { \
for (__i = 0; __i != 1 << __tries; __i++) { \
} \
__tries++; \
} else { \
pthread_yield(); \
} \
} \
0; \
#define pthread_spin_unlock(pSpin) \
({ \
pthread_spinlock_t *_s = pSpin; \
__atomic_store_n(&_s->lock, 0, __ATOMIC_RELAXED); \
0; \
})
#define pthread_spin_trylock(pSpin) \
({ \
pthread_spinlock_t *_s = pSpin; \
__atomic_test_and_set(&_s->lock, __ATOMIC_SEQ_CST) ? EBUSY : 0; \
})
#endif /* GCC 4.7+ */

View file

@ -24,7 +24,6 @@
#include "libc/intrin/atomic.h"
#include "libc/intrin/futex.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/linux/futex.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/sysv/consts/futex.h"
@ -85,20 +84,6 @@ static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int expect,
* // do work...
* pthread_mutex_unlock(&lock);
*
* Microbenchmarks for single-threaded lock + unlock:
*
* pthread_spinlock_t : 12c ( 4ns)
* PTHREAD_MUTEX_NORMAL : 37c ( 12ns)
* PTHREAD_MUTEX_RECURSIVE : 22c ( 7ns)
* PTHREAD_MUTEX_ERRORCHECK : 27c ( 9ns)
*
* Microbenchmarks for multi-threaded lock + unlock:
*
* pthread_spinlock_t : 2,396c (774ns)
* PTHREAD_MUTEX_NORMAL : 535c (173ns)
* PTHREAD_MUTEX_RECURSIVE : 1,045c (338ns)
* PTHREAD_MUTEX_ERRORCHECK : 917c (296ns)
*
* @return 0 on success, or error number on failure
* @see pthread_spin_lock()
*/

View file

@ -45,20 +45,21 @@
*/
int pthread_once(pthread_once_t *once, void init(void)) {
char old;
switch ((old = atomic_load_explicit(once, memory_order_relaxed))) {
switch ((old = atomic_load_explicit(&once->lock, memory_order_relaxed))) {
case INIT:
if (atomic_compare_exchange_strong_explicit(once, &old, CALLING,
if (atomic_compare_exchange_strong_explicit(&once->lock, &old, CALLING,
memory_order_acquire,
memory_order_relaxed)) {
init();
atomic_store(once, FINISHED);
atomic_store(&once->lock, FINISHED);
break;
}
// fallthrough
case CALLING:
do {
pthread_yield();
} while (atomic_load_explicit(once, memory_order_relaxed) == CALLING);
} while (atomic_load_explicit(&once->lock, memory_order_relaxed) ==
CALLING);
break;
case FINISHED:
break;

View file

@ -21,11 +21,6 @@
/**
* Acquires spin lock.
*
* spin l: 181,570c 58,646ns
* mutex normal l: 297,965c 96,241ns
* mutex recursive l: 1,112,166c 359,223ns
* mutex errorcheck l: 1,449,723c 468,252ns
*
* If the lock is already held, this function will wait for it to become
* available. No genuine error conditions are currently defined. This is
* similar to pthread_mutex_lock() except spin locks are much simpler so
@ -45,7 +40,7 @@
*
* Cosmopolitan permits succinct notation for spin locks:
*
* pthread_spinlock_t lock = 0;
* pthread_spinlock_t lock = {0};
* pthread_spin_lock(&lock);
* // do work...
* pthread_spin_unlock(&lock);

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/_getauxval.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/internal.h"

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.h"
void __releasefd(int fd) {

View file

@ -1,58 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
#define COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* TODO(jart): DELETE */
#ifdef TINY
#define _spinlock(lock) _spinlock_tiny(lock)
#else
#define _spinlock(lock) _spinlock_cooperative(lock)
#endif
#define _spunlock(lock) (__atomic_store_n(lock, 0, __ATOMIC_RELAXED), 0)
#define _seizelock(lock, value) \
({ \
autotype(lock) __lock = (lock); \
typeof(*__lock) __x = (value); \
__atomic_store(__lock, &__x, __ATOMIC_RELEASE); \
})
#define _spinlock_tiny(lock) \
({ \
while (_trylock(lock)) { \
__builtin_ia32_pause(); \
} \
0; \
})
#define _spinlock_cooperative(lock) \
({ \
char __x; \
volatile int __i; \
unsigned __tries = 0; \
char *__lock = (lock); \
for (;;) { \
__atomic_load(__lock, &__x, __ATOMIC_RELAXED); \
if (!__x && !_trylock(__lock)) { \
break; \
} else if (__tries < 7) { \
for (__i = 0; __i != 1 << __tries; __i++) { \
} \
__tries++; \
} else { \
_spinlock_yield(); \
} \
} \
0; \
})
#define _trylock(lock) __atomic_test_and_set(lock, __ATOMIC_SEQ_CST)
int _spinlock_yield(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ */

View file

@ -16,8 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/bits.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/dprintf.h"
#include "libc/calls/strace.internal.h"
@ -27,7 +25,8 @@
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/math.h"

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/gc.internal.h"
@ -72,10 +71,7 @@ static void DeferFunction(struct StackFrame *frame, void *fn, void *arg) {
if (!(g = malloc(sizeof(struct Garbages)))) notpossible;
g->i = 0;
g->n = 4;
if (!(g->p = malloc(g->n * sizeof(struct Garbage)))) {
kprintf("malloc failed\n");
notpossible;
}
if (!(g->p = malloc(g->n * sizeof(struct Garbage)))) notpossible;
tls->garbages = g;
} else if (UNLIKELY(g->i == g->n)) {
p2 = g->p;

View file

@ -23,7 +23,7 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/pthread.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/gettls.h"
@ -63,7 +63,7 @@ struct CloneArgs {
uint32_t utid;
int64_t tid64;
};
char lock;
pthread_spinlock_t lock;
int *ptid;
int *ctid;
int *ztid;
@ -163,7 +163,7 @@ XnuThreadMain(void *pthread, // rdi
wt->tid = tid;
*wt->ptid = tid;
*wt->ctid = tid;
_spunlock(&wt->lock);
pthread_spin_unlock(&wt->lock);
if (wt->tls) {
// XNU uses the same 0x30 offset as the WIN32 TIB x64. They told the
@ -216,11 +216,11 @@ static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->tls = flags & CLONE_SETTLS ? tls : 0;
wt->lock = 1;
wt->lock.lock = 1;
if ((rc = bsdthread_create(fn, arg, wt, 0, PTHREAD_START_CUSTOM_XNU)) != -1) {
_spinlock(&wt->lock);
pthread_spin_lock(&wt->lock);
rc = wt->tid;
_spunlock(&wt->lock);
pthread_spin_unlock(&wt->lock);
}
return rc;
}

View file

@ -16,18 +16,17 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/bits.h"
#include "libc/intrin/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nt/process.h"
#include "libc/runtime/internal.h"
#include "libc/sysv/consts/sig.h"
/**
* Creates new process.
@ -37,14 +36,17 @@
*/
int fork(void) {
axdx_t ad;
sigset_t old, all;
int ax, dx, parent;
sigfillset(&all);
sigprocmask(SIG_BLOCK, &all, &old);
if (!IsWindows()) {
ad = sys_fork();
ax = ad.ax;
dx = ad.dx;
if (IsXnu() && ax != -1) {
/* eax always returned with childs pid */
/* edx is 0 for parent and 1 for child */
// eax always returned with childs pid
// edx is 0 for parent and 1 for child
ax &= dx - 1;
}
} else {
@ -62,11 +64,10 @@ int fork(void) {
*(int *)(__get_tls() + 0x38) = IsLinux() ? dx : sys_gettid();
}
STRACE("fork() → 0 (child of %d)", parent);
if (weaken(__onfork)) {
weaken(__onfork)();
}
sigprocmask(SIG_SETMASK, &old, 0);
} else {
STRACE("fork() → %d% m", ax);
sigprocmask(SIG_SETMASK, &old, 0);
}
return ax;
}

View file

@ -17,11 +17,11 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/weaken.h"
#include "libc/calls/strace.internal.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/promises.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
@ -32,7 +32,7 @@
#include "libc/zipos/zipos.internal.h"
#include "third_party/zlib/puff.h"
static int g_lock;
static pthread_spinlock_t g_lock;
hidden struct SymbolTable *__symtab; // for kprintf
/**
@ -125,7 +125,7 @@ static struct SymbolTable *GetSymbolTableFromElf(void) {
*/
struct SymbolTable *GetSymbolTable(void) {
struct Zipos *z;
if (_trylock(&g_lock)) return 0;
if (pthread_spin_trylock(&g_lock)) return 0;
if (!__symtab && !__isworker) {
if (weaken(__zipos_get) && (z = weaken(__zipos_get)())) {
if ((__symtab = GetSymbolTableFromZip(z))) {
@ -139,7 +139,7 @@ struct SymbolTable *GetSymbolTable(void) {
__symtab = GetSymbolTableFromElf();
}
}
_spunlock(&g_lock);
pthread_spin_unlock(&g_lock);
return __symtab;
}

View file

@ -30,7 +30,6 @@
#include "libc/intrin/likely.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/log/backtrace.internal.h"

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/spinlock.h"
#include "libc/nt/memory.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/internal.h"

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.h"
#include "libc/nt/files.h"
#include "libc/nt/memory.h"

View file

@ -24,7 +24,6 @@
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/weaken.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/libfatal.internal.h"

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/spinlock.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"

View file

@ -19,7 +19,6 @@
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/mem/mem.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"

View file

@ -38,7 +38,6 @@
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/spinlock.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"

View file

@ -17,12 +17,10 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sock/yoink.inc"
#include "libc/sysv/errfuns.h"
textwindows int sys_getsockname_nt(struct Fd *fd, void *out_addr,
uint32_t *out_addrsize) {

View file

@ -16,11 +16,10 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/weaken.h"
#include "libc/mem/mem.h"
#include "libc/nt/runtime.h"
#include "libc/nt/winsock.h"

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/mem/mem.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/iphlpapi.h"

View file

@ -19,7 +19,6 @@
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"

View file

@ -21,7 +21,6 @@
#include "libc/intrin/bits.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/mem/mem.h"

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/calls.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/stdio/fflush.internal.h"
#include "libc/stdio/lock.h"
#include "libc/stdio/stdio.h"

View file

@ -32,7 +32,7 @@ struct lconv {
int wcwidth(wchar_t) pureconst;
int wcswidth(const wchar_t *, size_t) strlenesque;
int wcsnwidth(const wchar_t *, size_t, size_t) strlenesque;
int wcsnwidth(const wchar_t *, size_t, int) strlenesque;
struct lconv *localeconv(void);
COSMOPOLITAN_C_END_

View file

@ -21,7 +21,7 @@
/**
* Returns monospace display width of wide character string.
*/
int wcsnwidth(const wchar_t *pwcs, size_t n, size_t o) {
int wcsnwidth(const wchar_t *pwcs, size_t n, int o) {
int w, width = 0;
for (; *pwcs && n-- > 0; pwcs++) {
if ((w = wcwidth(*pwcs)) < 0) {

View file

@ -29,7 +29,7 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/weaken.h"
#include "libc/log/check.h"
#include "libc/log/internal.h"
@ -52,7 +52,7 @@ static int x;
char g_testlib_olddir[PATH_MAX];
char g_testlib_tmpdir[PATH_MAX];
struct sigaction wanthandlers[31];
static char testlib_error_lock;
static pthread_spinlock_t testlib_error_lock;
void testlib_finish(void) {
if (g_testlib_failed) {
@ -64,7 +64,7 @@ void testlib_finish(void) {
void testlib_error_enter(const char *file, const char *func) {
atomic_fetch_sub_explicit(&__ftrace, 1, memory_order_relaxed);
atomic_fetch_sub_explicit(&__strace, 1, memory_order_relaxed);
if (!__vforked) _spinlock(&testlib_error_lock);
if (!__vforked) pthread_spin_lock(&testlib_error_lock);
if (!IsWindows()) sys_getpid(); /* make strace easier to read */
if (!IsWindows()) sys_getpid();
if (g_testlib_shoulddebugbreak) {
@ -77,7 +77,7 @@ void testlib_error_enter(const char *file, const char *func) {
void testlib_error_leave(void) {
atomic_fetch_add_explicit(&__ftrace, 1, memory_order_relaxed);
atomic_fetch_add_explicit(&__strace, 1, memory_order_relaxed);
_spunlock(&testlib_error_lock);
pthread_spin_unlock(&testlib_error_lock);
}
wontreturn void testlib_abort(void) {

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 2020 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/errno.h"
#include "libc/runtime/stack.h"
#include "libc/thread/thread.h"
#define MIN_STACKSIZE (8 * PAGESIZE) // includes guard, rounds up to FRAMESIZE
#define MIN_GUARDSIZE PAGESIZE
// CTOR/DTOR
int cthread_attr_init(cthread_attr_t* attr) {
attr->stacksize = GetStackSize();
attr->guardsize = PAGESIZE;
attr->mode = CTHREAD_CREATE_JOINABLE;
return 0;
}
int cthread_attr_destroy(cthread_attr_t* attr) {
(void)attr;
return 0;
}
// stacksize
int cthread_attr_setstacksize(cthread_attr_t* attr, size_t size) {
if (size & (PAGESIZE - 1)) return EINVAL;
if (size < MIN_STACKSIZE) return EINVAL;
attr->stacksize = size;
return 0;
}
size_t cthread_attr_getstacksize(const cthread_attr_t* attr) {
return attr->stacksize;
}
// guardsize
int cthread_attr_setguardsize(cthread_attr_t* attr, size_t size) {
if (size & (PAGESIZE - 1)) return EINVAL;
if (size < MIN_GUARDSIZE) return EINVAL;
attr->guardsize = size;
return 0;
}
size_t cthread_attr_getguardsize(const cthread_attr_t* attr) {
return attr->guardsize;
}
// detachstate
int cthread_attr_setdetachstate(cthread_attr_t* attr, int mode) {
if (mode & ~(CTHREAD_CREATE_JOINABLE | CTHREAD_CREATE_DETACHED))
return EINVAL;
attr->mode = mode;
return 0;
}
int cthread_attr_getdetachstate(const cthread_attr_t* attr) {
return attr->mode;
}

View file

@ -53,7 +53,7 @@ static int PosixThread(void *arg, int tid) {
struct PosixThread *pt = arg;
enum PosixThreadStatus status;
if (!setjmp(pt->exiter)) {
((cthread_t)__get_tls())->pthread = pt;
((cthread_t)__get_tls())->pthread = (pthread_t)pt;
pt->rc = pt->start_routine(pt->arg);
}
if (weaken(_pthread_key_destruct)) {
@ -72,7 +72,20 @@ static int PosixThread(void *arg, int tid) {
}
/**
* Creates thread.
* Creates thread, e.g.
*
* void *worker(void *arg) {
* fputs(arg, stdout);
* return "there\n";
* }
*
* int main() {
* void *result;
* pthread_t id;
* pthread_create(&id, 0, worker, "hi ");
* pthread_join(id, &result);
* fputs(result, stdout);
* }
*
* Here's the OSI model of threads in Cosmopolitan:
*
@ -216,7 +229,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
}
if (thread) {
*thread = pt;
*thread = (pthread_t)pt;
}
return 0;
}

View file

@ -30,7 +30,7 @@
*/
int pthread_detach(pthread_t thread) {
enum PosixThreadStatus status;
struct PosixThread *pt = thread;
struct PosixThread *pt = (struct PosixThread *)thread;
for (;;) {
status = atomic_load_explicit(&pt->status, memory_order_relaxed);
if (status == kPosixThreadDetached || status == kPosixThreadZombie) {

View file

@ -25,7 +25,7 @@
* @return nonzero if equal, otherwise zero
*/
int pthread_equal(pthread_t t1, pthread_t t2) {
struct PosixThread *a = t1;
struct PosixThread *b = t2;
struct PosixThread *a = (struct PosixThread *)t1;
struct PosixThread *b = (struct PosixThread *)t2;
return a->spawn.ptid == b->spawn.ptid;
}

View file

@ -37,7 +37,7 @@
*/
wontreturn void pthread_exit(void *rc) {
struct PosixThread *pt;
if ((pt = ((cthread_t)__get_tls())->pthread)) {
if ((pt = (struct PosixThread *)((cthread_t)__get_tls())->pthread)) {
pt->rc = rc;
_gclongjmp(pt->exiter, 1);
} else {

View file

@ -22,7 +22,7 @@
#include "libc/thread/thread.h"
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) {
struct PosixThread *pt = thread;
struct PosixThread *pt = (struct PosixThread *)thread;
memcpy(attr, &pt->attr, sizeof(pt->attr));
return 0;
}

View file

@ -23,6 +23,6 @@
* Returns thread id of POSIX thread.
*/
int64_t pthread_getunique_np(pthread_t thread) {
struct PosixThread *pt = thread;
struct PosixThread *pt = (struct PosixThread *)thread;
return pt->spawn.ptid;
}

View file

@ -31,7 +31,7 @@
* @raise EDEADLK if thread is detached
*/
int pthread_join(pthread_t thread, void **value_ptr) {
struct PosixThread *pt = thread;
struct PosixThread *pt = (struct PosixThread *)thread;
if (pt->status == kPosixThreadDetached || //
pt->status == kPosixThreadZombie) {
assert(!"badjoin");

View file

@ -1,133 +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 2020 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/intrin/atomic.h"
#include "libc/calls/calls.h"
#include "libc/thread/thread.h"
#define CTHREAD_THREAD_VAL_BITS 32
static void Pause(int attempt) {
if (attempt < 16) {
for (int i = 0; i < (1 << attempt); ++i) {
__builtin_ia32_pause();
}
} else {
sched_yield();
}
}
/**
* Initializes semaphore.
*/
int cthread_sem_init(cthread_sem_t* sem, int count) {
sem->linux.count = count;
return 0;
}
/**
* Destroys semaphore.
*/
int cthread_sem_destroy(cthread_sem_t* sem) {
(void)sem;
return 0;
}
/**
* Notifies a thread waiting on semaphore.
*/
int cthread_sem_signal(cthread_sem_t* sem) {
uint64_t count;
count = atomic_fetch_add(&sem->linux.count, 1);
if ((count >> CTHREAD_THREAD_VAL_BITS)) {
// WARNING: an offset of 4 bytes would be required on little-endian archs
void* wait_address = &sem->linux.count;
cthread_memory_wake32(wait_address, 1);
}
return 0;
}
/**
* Waits on semaphore with kernel assistance.
*/
int cthread_sem_wait_futex(cthread_sem_t* sem, const struct timespec* timeout) {
uint64_t count;
// record current thread as waiter
count = atomic_fetch_add(&sem->linux.count,
(uint64_t)1 << CTHREAD_THREAD_VAL_BITS);
for (;;) {
// try to acquire the semaphore, as well as remove itself from waiters
while ((uint32_t)count > 0) {
// without spin, we could miss a futex wake
if (atomic_compare_exchange_weak(
&sem->linux.count, &count,
count - 1 - ((uint64_t)1 << CTHREAD_THREAD_VAL_BITS))) {
return 0;
}
}
// WARNING: an offset of 4 bytes would be required on little-endian archs
void* wait_address = &sem->linux.count;
cthread_memory_wait32(wait_address, count, timeout);
count = atomic_load(&sem->linux.count);
}
return 0;
}
/**
* Waits on semaphore without kernel assistance.
*/
int cthread_sem_wait_spin(cthread_sem_t* sem, uint64_t count, int spin,
const struct timespec* timeout) {
// spin on pause
for (int attempt = 0; attempt < spin; ++attempt) {
// if ((count >> CTHREAD_THREAD_VAL_BITS) != 0) break;
while ((uint32_t)count > 0) {
// spin is useful if multiple waiters can acquire the semaphore at the
// same time
if (atomic_compare_exchange_weak(&sem->linux.count, &count, count - 1)) {
return 0;
}
}
Pause(attempt);
}
return cthread_sem_wait_futex(sem, timeout);
}
/**
* Waits on semaphore.
*/
int cthread_sem_wait(cthread_sem_t* sem, int spin,
const struct timespec* timeout) {
uint64_t count = atomic_load(&sem->linux.count);
// uncontended
while ((uint32_t)count > 0) {
// spin is useful if multiple waiters can acquire the semaphore at the same
// time
if (atomic_compare_exchange_weak(&sem->linux.count, &count, count - 1)) {
return 0;
}
}
return cthread_sem_wait_spin(sem, count, spin, timeout);
}

View file

@ -1,23 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_THREAD_THREAD_H_
#define COSMOPOLITAN_LIBC_THREAD_THREAD_H_
#include "libc/calls/struct/timespec.h"
#include "libc/intrin/pthread.h"
#include "libc/runtime/runtime.h"
#include "libc/str/locale.h"
#define CTHREAD_CREATE_DETACHED 1
#define CTHREAD_CREATE_JOINABLE 0
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
enum cthread_state {
cthread_started = 0,
cthread_joining = 1,
cthread_finished = 2,
cthread_detached = 4,
};
struct FtraceTls { /* 16 */
bool once; /* 0 */
bool noreentry; /* 1 */
@ -38,32 +26,6 @@ struct cthread_descriptor_t {
typedef struct cthread_descriptor_t *cthread_t;
typedef union cthread_sem_t {
struct {
uint64_t count;
} linux;
} cthread_sem_t;
typedef struct cthread_attr_t {
size_t stacksize, guardsize;
int mode;
} cthread_attr_t;
cthread_t cthread_self(void);
int cthread_attr_init(cthread_attr_t *);
int cthread_attr_destroy(cthread_attr_t *);
int cthread_attr_setstacksize(cthread_attr_t *, size_t);
size_t thread_attr_getstacksize(const cthread_attr_t *);
int cthread_attr_setguardsize(cthread_attr_t *, size_t);
size_t cthread_attr_getguardsize(const cthread_attr_t *);
int cthread_attr_setdetachstate(cthread_attr_t *, int);
int cthread_attr_getdetachstate(const cthread_attr_t *);
int cthread_sem_init(cthread_sem_t *, int);
int cthread_sem_destroy(cthread_sem_t *);
int cthread_sem_wait(cthread_sem_t *, int, const struct timespec *);
int cthread_sem_signal(cthread_sem_t *);
int cthread_memory_wait32(int *, int, const struct timespec *);
int cthread_memory_wake32(int *, int);
void cthread_ungarbage(void);
COSMOPOLITAN_C_END_

View file

@ -6,7 +6,6 @@
#include "libc/intrin/bits.h"
#include "libc/intrin/nopl.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/gc.h"

View file

@ -28,7 +28,6 @@
#include "libc/intrin/atomic.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/spinlock.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/internal.h"

View file

@ -23,7 +23,6 @@
#include "libc/calls/struct/rlimit.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/wait0.internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/threaded.h"

View file

@ -109,7 +109,7 @@ void BenchLockUnlock(pthread_mutex_t *m) {
BENCH(pthread_mutex_lock, bench_uncontended) {
{
pthread_spinlock_t s = 0;
pthread_spinlock_t s = {0};
EZBENCH2("spin 1x", donothing, BenchSpinUnspin(&s));
}
{
@ -161,7 +161,7 @@ int MutexContentionWorker(void *arg, int tid) {
BENCH(pthread_mutex_lock, bench_contended) {
struct spawn t;
{
pthread_spinlock_t s = 0;
pthread_spinlock_t s = {0};
struct SpinContentionArgs a = {&s};
_spawn(SpinContentionWorker, &a, &t);
while (!a.ready) sched_yield();

View file

@ -23,7 +23,6 @@
#include "libc/errno.h"
#include "libc/intrin/futex.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/wait0.internal.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"

View file

@ -22,7 +22,6 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/spinlock.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"

View file

@ -21,7 +21,6 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/futex.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/wait0.internal.h"
#include "libc/log/backtrace.internal.h"
#include "libc/macros.internal.h"

View file

@ -18,9 +18,12 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/timespec.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/msync.h"
@ -29,10 +32,6 @@
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
void SetUpOnce(void) {
ASSERT_SYS(0, 0, pledge("stdio proc", 0));
}
TEST(fork, testPipes) {
int a, b;
int ws, pid;
@ -142,5 +141,5 @@ void ForkInSerial(void) {
}
BENCH(fork, bench) {
EZBENCH2("fork", donothing, ForkInSerial());
EZBENCH2("fork a", donothing, ForkInSerial());
}

View file

@ -20,7 +20,6 @@
#include "libc/calls/struct/sched_param.h"
#include "libc/dce.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/wait0.internal.h"
#include "libc/macros.internal.h"
#include "libc/math.h"

View file

@ -16,27 +16,25 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/mem/alg.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/mem/arraylist2.internal.h"
#include "libc/mem/bisectcarleft.internal.h"
#include "libc/assert.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/sysparam.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/wait0.internal.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/alg.h"
#include "libc/mem/alloca.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/mem/arraylist2.internal.h"
#include "libc/mem/bisectcarleft.internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/nexgen32e/threaded.h"

View file

@ -36,8 +36,8 @@
#include "libc/intrin/atomic.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
@ -343,7 +343,7 @@ static struct Shared {
#include "tool/net/counters.inc"
#undef C
} c;
_Alignas(64) char montermlock;
pthread_spinlock_t montermlock;
} * shared;
static const char kCounterNames[] =
@ -6257,7 +6257,7 @@ static int MemoryMonitor(void *arg, int tid) {
sigaddset(&ss, SIGUSR2);
sigprocmask(SIG_BLOCK, &ss, 0);
_spinlock(&shared->montermlock);
pthread_spin_lock(&shared->montermlock);
if (!id) {
if ((tty = open(monitortty, O_RDWR | O_NOCTTY)) != -1) {
ioctl(tty, TCGETS, &oldterm);
@ -6273,7 +6273,7 @@ static int MemoryMonitor(void *arg, int tid) {
WRITE(tty, "\e[?25l", 6);
}
}
_spunlock(&shared->montermlock);
pthread_spin_unlock(&shared->montermlock);
if (tty != -1) {
for (gen = 0, mi = 0, b = 0; !terminatemonitor;) {
@ -6355,11 +6355,11 @@ static int MemoryMonitor(void *arg, int tid) {
" GEN=%ld\e[J",
id, getpid(), ws.ws_col, ws.ws_row, workers, gen);
_spinlock(&shared->montermlock);
pthread_spin_lock(&shared->montermlock);
WRITE(tty, b, appendz(b).i);
appendr(&b, 0);
usleep(MONITOR_MICROS);
_spunlock(&shared->montermlock);
pthread_spin_unlock(&shared->montermlock);
} else {
// running out of memory temporarily is a real possibility here
// the right thing to do, is stand aside and let lua try to fix