mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Remove __threaded variable
This commit is contained in:
parent
01b09bc817
commit
cf1559c448
15 changed files with 51 additions and 71 deletions
|
@ -129,6 +129,7 @@ int linkat(int, const char *, int, const char *, int) libcesque __read_only(2) _
|
||||||
int mincore(void *, size_t, unsigned char *) libcesque __read_only(1) __write_only(3);
|
int mincore(void *, size_t, unsigned char *) libcesque __read_only(1) __write_only(3);
|
||||||
int mkdir(const char *, unsigned) libcesque __read_only(1);
|
int mkdir(const char *, unsigned) libcesque __read_only(1);
|
||||||
int mkdirat(int, const char *, unsigned) libcesque __read_only(2);
|
int mkdirat(int, const char *, unsigned) libcesque __read_only(2);
|
||||||
|
int mkfifo(const char *, unsigned);
|
||||||
int mknod(const char *, unsigned, uint64_t) libcesque __read_only(1);
|
int mknod(const char *, unsigned, uint64_t) libcesque __read_only(1);
|
||||||
int nice(int) libcesque;
|
int nice(int) libcesque;
|
||||||
int open(const char *, int, ...) libcesque __read_only(1);
|
int open(const char *, int, ...) libcesque __read_only(1);
|
||||||
|
|
|
@ -169,8 +169,7 @@
|
||||||
* turn APE binaries into static native binaries.
|
* turn APE binaries into static native binaries.
|
||||||
*
|
*
|
||||||
* - "prot_exec" allows mmap(PROT_EXEC) and mprotect(PROT_EXEC). This is
|
* - "prot_exec" allows mmap(PROT_EXEC) and mprotect(PROT_EXEC). This is
|
||||||
* needed to (1) code morph mutexes in __enable_threads(), and it's
|
* needed to launch non-static or non-native executables, e.g.
|
||||||
* needed to (2) launch non-static or non-native executables, e.g.
|
|
||||||
* non-assimilated APE binaries, or dynamic-linked executables.
|
* non-assimilated APE binaries, or dynamic-linked executables.
|
||||||
*
|
*
|
||||||
* - "unveil" allows unveil() to be called, as well as the underlying
|
* - "unveil" allows unveil() to be called, as well as the underlying
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
* special; the kernel treats this as a thread id (noting that
|
* special; the kernel treats this as a thread id (noting that
|
||||||
* `getpid() == gettid()` is always the case on Linux for the main
|
* `getpid() == gettid()` is always the case on Linux for the main
|
||||||
* thread) and will only take effect for the specified tid.
|
* thread) and will only take effect for the specified tid.
|
||||||
* Therefore this function is POSIX-compliant iif `!__threaded`.
|
|
||||||
* @return scheduler policy, or -1 w/ errno
|
* @return scheduler policy, or -1 w/ errno
|
||||||
* @error ESRCH if `pid` not found
|
* @error ESRCH if `pid` not found
|
||||||
* @error EPERM if not permitted
|
* @error EPERM if not permitted
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
* special; the kernel treats this as a thread id (noting that
|
* special; the kernel treats this as a thread id (noting that
|
||||||
* `getpid() == gettid()` is always the case on Linux for the main
|
* `getpid() == gettid()` is always the case on Linux for the main
|
||||||
* thread) and will only take effect for the specified tid.
|
* thread) and will only take effect for the specified tid.
|
||||||
* Therefore this function is POSIX-compliant iif `!__threaded`.
|
|
||||||
*
|
*
|
||||||
* @param policy specifies the kernel's timesharing strategy.
|
* @param policy specifies the kernel's timesharing strategy.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,11 +18,6 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains TID of main thread or 0 if threading isn't enabled.
|
|
||||||
*/
|
|
||||||
int __threaded;
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
char __tls_enabled;
|
char __tls_enabled;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -113,7 +113,6 @@ static dontinline textwindows ssize_t ForkIo2(
|
||||||
ssize_t rc = ForkIo(h, buf, n, fn);
|
ssize_t rc = ForkIo(h, buf, n, fn);
|
||||||
if (ischild) {
|
if (ischild) {
|
||||||
// prevent crashes
|
// prevent crashes
|
||||||
__threaded = false;
|
|
||||||
__tls_enabled = false;
|
__tls_enabled = false;
|
||||||
__pid = __imp_GetCurrentProcessId();
|
__pid = __imp_GetCurrentProcessId();
|
||||||
__klog_handle = 0;
|
__klog_handle = 0;
|
||||||
|
@ -268,7 +267,6 @@ textwindows void WinMainForked(void) {
|
||||||
ReadOrDie(reader, __bss_start, __bss_end - __bss_start);
|
ReadOrDie(reader, __bss_start, __bss_end - __bss_start);
|
||||||
kStartTsc = savetsc;
|
kStartTsc = savetsc;
|
||||||
__tls_enabled = false;
|
__tls_enabled = false;
|
||||||
__threaded = false;
|
|
||||||
|
|
||||||
// fixup memory manager
|
// fixup memory manager
|
||||||
__maps.maps = 0;
|
__maps.maps = 0;
|
||||||
|
@ -464,8 +462,6 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
|
||||||
// the child's pending signals is initially empty
|
// the child's pending signals is initially empty
|
||||||
atomic_store_explicit(&__sig.pending, 0, memory_order_relaxed);
|
atomic_store_explicit(&__sig.pending, 0, memory_order_relaxed);
|
||||||
atomic_store_explicit(&tib->tib_sigpending, 0, memory_order_relaxed);
|
atomic_store_explicit(&tib->tib_sigpending, 0, memory_order_relaxed);
|
||||||
// re-enable threads
|
|
||||||
__enable_threads();
|
|
||||||
// re-apply code morphing for function tracing
|
// re-apply code morphing for function tracing
|
||||||
if (ftrace_stackdigs) {
|
if (ftrace_stackdigs) {
|
||||||
_weaken(__hook)(_weaken(ftrace_hook), _weaken(GetSymbolTable)());
|
_weaken(__hook)(_weaken(ftrace_hook), _weaken(GetSymbolTable)());
|
||||||
|
|
|
@ -236,7 +236,6 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
|
||||||
* Lazy initializes process tracker data structures and worker.
|
* Lazy initializes process tracker data structures and worker.
|
||||||
*/
|
*/
|
||||||
static textwindows void __proc_setup(void) {
|
static textwindows void __proc_setup(void) {
|
||||||
__enable_threads();
|
|
||||||
__proc.onbirth = CreateEvent(0, 0, 0, 0); // auto reset
|
__proc.onbirth = CreateEvent(0, 0, 0, 0); // auto reset
|
||||||
__proc.haszombies = CreateEvent(0, 1, 0, 0); // manual reset
|
__proc.haszombies = CreateEvent(0, 1, 0, 0); // manual reset
|
||||||
__proc.thread = CreateThread(0, 65536, __proc_worker, 0,
|
__proc.thread = CreateThread(0, 65536, __proc_worker, 0,
|
||||||
|
|
|
@ -746,10 +746,6 @@ errno_t clone(void *func, void *stk, size_t stksz, int flags, void *arg,
|
||||||
void *ptid, void *tls, void *ctid) {
|
void *ptid, void *tls, void *ctid) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (flags & CLONE_THREAD) {
|
|
||||||
__enable_threads();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!func) {
|
if (!func) {
|
||||||
rc = EINVAL;
|
rc = EINVAL;
|
||||||
} else if (IsLinux()) {
|
} else if (IsLinux()) {
|
||||||
|
|
|
@ -113,7 +113,6 @@ void _weakfree(void *) libcesque;
|
||||||
void *_mapanon(size_t) attributeallocsize((1)) mallocesque libcesque;
|
void *_mapanon(size_t) attributeallocsize((1)) mallocesque libcesque;
|
||||||
void *_mapshared(size_t) attributeallocsize((1)) mallocesque libcesque;
|
void *_mapshared(size_t) attributeallocsize((1)) mallocesque libcesque;
|
||||||
void CheckForFileLeaks(void) libcesque;
|
void CheckForFileLeaks(void) libcesque;
|
||||||
void __enable_threads(void) libcesque;
|
|
||||||
void __oom_hook(size_t) libcesque;
|
void __oom_hook(size_t) libcesque;
|
||||||
/* code morphing */
|
/* code morphing */
|
||||||
void __morph_begin(void) libcesque;
|
void __morph_begin(void) libcesque;
|
||||||
|
|
|
@ -42,7 +42,6 @@ struct CosmoTib {
|
||||||
_Atomic(void *) tib_keys[46];
|
_Atomic(void *) tib_keys[46];
|
||||||
} __attribute__((__aligned__(64)));
|
} __attribute__((__aligned__(64)));
|
||||||
|
|
||||||
extern int __threaded;
|
|
||||||
extern char __tls_morphed;
|
extern char __tls_morphed;
|
||||||
extern unsigned __tls_index;
|
extern unsigned __tls_index;
|
||||||
|
|
||||||
|
|
|
@ -189,8 +189,6 @@ int main(int argc, char *argv[]) {
|
||||||
_Exit(1);
|
_Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
__threaded = 1;
|
|
||||||
|
|
||||||
ASSERT_EQ(0, pthread_mutexattr_init(&attr));
|
ASSERT_EQ(0, pthread_mutexattr_init(&attr));
|
||||||
ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL));
|
ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL));
|
||||||
ASSERT_EQ(0, pthread_mutex_init(&mu, &attr));
|
ASSERT_EQ(0, pthread_mutex_init(&mu, &attr));
|
||||||
|
|
|
@ -179,47 +179,15 @@ void MallocFree(void) {
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void eat(void *p) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*pEat)(void *) = eat;
|
||||||
|
|
||||||
BENCH(bulk_free, bench) {
|
BENCH(bulk_free, bench) {
|
||||||
|
/* pEat(pthread_create); */
|
||||||
EZBENCH2("free() bulk", BulkFreeBenchSetup(), FreeBulk());
|
EZBENCH2("free() bulk", BulkFreeBenchSetup(), FreeBulk());
|
||||||
EZBENCH2("bulk_free()", BulkFreeBenchSetup(),
|
EZBENCH2("bulk_free()", BulkFreeBenchSetup(),
|
||||||
bulk_free(bulk, ARRAYLEN(bulk)));
|
bulk_free(bulk, ARRAYLEN(bulk)));
|
||||||
EZBENCH2("free(malloc(16)) ST", donothing, MallocFree());
|
EZBENCH2("free(malloc(16))", donothing, MallocFree());
|
||||||
__enable_threads();
|
|
||||||
EZBENCH2("free(malloc(16)) MT", donothing, MallocFree());
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ITERATIONS 1000
|
|
||||||
#define THREADS 10
|
|
||||||
#define SIZE 1024
|
|
||||||
|
|
||||||
void *Worker(void *arg) {
|
|
||||||
for (int i = 0; i < ITERATIONS; ++i) {
|
|
||||||
char *p;
|
|
||||||
ASSERT_NE(NULL, (p = malloc(lemur64() % SIZE)));
|
|
||||||
ASSERT_NE(NULL, (p = realloc(p, max(lemur64() % SIZE, 1))));
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(malloc, torture) {
|
|
||||||
int i, n = THREADS;
|
|
||||||
pthread_t *t = gc(malloc(sizeof(pthread_t) * n));
|
|
||||||
if (!n)
|
|
||||||
return;
|
|
||||||
printf("\nmalloc torture test w/ %d threads and %d iterations\n", n,
|
|
||||||
ITERATIONS);
|
|
||||||
SPAWN(fork);
|
|
||||||
struct timespec t1 = timespec_real();
|
|
||||||
for (i = 0; i < n; ++i) {
|
|
||||||
ASSERT_EQ(0, pthread_create(t + i, 0, Worker, 0));
|
|
||||||
}
|
|
||||||
for (i = 0; i < n; ++i) {
|
|
||||||
ASSERT_EQ(0, pthread_join(t[i], 0));
|
|
||||||
}
|
|
||||||
struct timespec t2 = timespec_real();
|
|
||||||
printf("consumed %g wall and %g cpu seconds\n",
|
|
||||||
timespec_tomicros(timespec_sub(t2, t1)) * 1e-6,
|
|
||||||
(double)clock() / CLOCKS_PER_SEC);
|
|
||||||
EXITS(0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
@ -16,9 +16,46 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/intrin/safemacros.h"
|
||||||
|
#include "libc/mem/gc.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/stdio/rand.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/testlib/subprocess.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
void __enable_threads(void) {
|
#define ITERATIONS 1000
|
||||||
__threaded = 1;
|
#define THREADS 10
|
||||||
|
#define SIZE 1024
|
||||||
|
|
||||||
|
void *Worker(void *arg) {
|
||||||
|
for (int i = 0; i < ITERATIONS; ++i) {
|
||||||
|
char *p;
|
||||||
|
ASSERT_NE(NULL, (p = malloc(lemur64() % SIZE)));
|
||||||
|
ASSERT_NE(NULL, (p = realloc(p, max(lemur64() % SIZE, 1))));
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(malloc, torture) {
|
||||||
|
int i, n = THREADS;
|
||||||
|
pthread_t *t = gc(malloc(sizeof(pthread_t) * n));
|
||||||
|
if (!n)
|
||||||
|
return;
|
||||||
|
printf("\nmalloc torture test w/ %d threads and %d iterations\n", n,
|
||||||
|
ITERATIONS);
|
||||||
|
SPAWN(fork);
|
||||||
|
struct timespec t1 = timespec_real();
|
||||||
|
for (i = 0; i < n; ++i)
|
||||||
|
ASSERT_EQ(0, pthread_create(t + i, 0, Worker, 0));
|
||||||
|
for (i = 0; i < n; ++i)
|
||||||
|
ASSERT_EQ(0, pthread_join(t[i], 0));
|
||||||
|
struct timespec t2 = timespec_real();
|
||||||
|
printf("consumed %g wall and %g cpu seconds\n",
|
||||||
|
timespec_tomicros(timespec_sub(t2, t1)) * 1e-6,
|
||||||
|
(double)clock() / CLOCKS_PER_SEC);
|
||||||
|
EXITS(0);
|
||||||
}
|
}
|
|
@ -48,7 +48,6 @@ void *ForceThreadingMode(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pthread_atfork, test) {
|
TEST(pthread_atfork, test) {
|
||||||
__enable_threads();
|
|
||||||
SPAWN(fork);
|
SPAWN(fork);
|
||||||
ASSERT_EQ(0, pthread_atfork(prepare1, parent1, child1));
|
ASSERT_EQ(0, pthread_atfork(prepare1, parent1, child1));
|
||||||
ASSERT_EQ(0, pthread_atfork(prepare2, parent2, child2));
|
ASSERT_EQ(0, pthread_atfork(prepare2, parent2, child2));
|
||||||
|
|
4
third_party/dlmalloc/locks.inc
vendored
4
third_party/dlmalloc/locks.inc
vendored
|
@ -39,7 +39,6 @@ static int malloc_wipe(MLOCK_T *lk) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int malloc_lock(MLOCK_T *lk) {
|
static int malloc_lock(MLOCK_T *lk) {
|
||||||
if (!__threaded) return 0;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!atomic_exchange_explicit(lk, 1, memory_order_acquire))
|
if (!atomic_exchange_explicit(lk, 1, memory_order_acquire))
|
||||||
break;
|
break;
|
||||||
|
@ -51,7 +50,6 @@ static int malloc_lock(MLOCK_T *lk) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int malloc_unlock(MLOCK_T *lk) {
|
static int malloc_unlock(MLOCK_T *lk) {
|
||||||
if (!__threaded) return 0;
|
|
||||||
atomic_store_explicit(lk, 0, memory_order_release);
|
atomic_store_explicit(lk, 0, memory_order_release);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -66,13 +64,11 @@ static int malloc_wipe(MLOCK_T *lk) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int malloc_lock(MLOCK_T *lk) {
|
static int malloc_lock(MLOCK_T *lk) {
|
||||||
if (!__threaded) return 0;
|
|
||||||
nsync_mu_lock(lk);
|
nsync_mu_lock(lk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int malloc_unlock(MLOCK_T *lk) {
|
static int malloc_unlock(MLOCK_T *lk) {
|
||||||
if (!__threaded) return 0;
|
|
||||||
nsync_mu_unlock(lk);
|
nsync_mu_unlock(lk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue