mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-25 05:48:31 +00:00
Clean up some of the threading code
This commit is contained in:
parent
0547eabcd6
commit
9f963dc597
62 changed files with 175 additions and 582 deletions
|
@ -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"
|
||||
|
|
28
libc/intrin/fds_lock.c
Normal file
28
libc/intrin/fds_lock.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 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 │
|
||||
│ 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/calls/state.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
void(__fds_lock)(void) {
|
||||
pthread_mutex_lock(&__fds_lock_obj);
|
||||
}
|
||||
|
||||
void(__fds_unlock)(void) {
|
||||
pthread_mutex_unlock(&__fds_lock_obj);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
30
libc/intrin/mmi_lock.c
Normal file
30
libc/intrin/mmi_lock.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 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 │
|
||||
│ 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/pthread.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
extern pthread_mutex_t __mmi_lock_obj;
|
||||
|
||||
void(__mmi_lock)(void) {
|
||||
pthread_mutex_lock(&__mmi_lock_obj);
|
||||
}
|
||||
|
||||
void(__mmi_unlock)(void) {
|
||||
pthread_mutex_unlock(&__mmi_lock_obj);
|
||||
}
|
21
libc/intrin/mmi_lock_obj.c
Normal file
21
libc/intrin/mmi_lock_obj.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*-*- 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 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 │
|
||||
│ 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/pthread.h"
|
||||
|
||||
pthread_mutex_t __mmi_lock_obj; // recursive :'(
|
|
@ -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_ */
|
|
@ -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+ */
|
||||
|
||||
|
|
|
@ -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()
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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_ */
|
Loading…
Add table
Add a link
Reference in a new issue