mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 06:59:10 +00:00
Clean up more code
The *NSYNC linked list API is good enough that it deserves to be part of the C libray, so this change writes an improved version of it which uses that offsetof() trick from the Linux Kernel. We vendor all of the *NSYNC tests in third_party which helped confirm the needed refactoring is safe This change also deletes more old code that didn't pan out. My goal here is to work towards a vision where the Cosmopolitan core libraries become less experimental and more focused on curation. This better reflects the current level of quality we've managed to achieve.
This commit is contained in:
parent
88612a2cd7
commit
0a24b4fc3c
268 changed files with 632 additions and 8688 deletions
|
@ -2,10 +2,10 @@
|
|||
#define COSMOPOLITAN_LIBC_THREAD_POSIXTHREAD_INTERNAL_H_
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "third_party/nsync/dll.h"
|
||||
|
||||
#define PT_OWNSTACK 1
|
||||
#define PT_STATIC 2
|
||||
|
@ -64,26 +64,28 @@ enum PosixThreadStatus {
|
|||
kPosixThreadZombie,
|
||||
};
|
||||
|
||||
#define POSIXTHREAD_CONTAINER(e) DLL_CONTAINER(struct PosixThread, list, e)
|
||||
|
||||
struct PosixThread {
|
||||
int flags; // 0x00: see PT_* constants
|
||||
_Atomic(int) cancelled; // 0x04: thread has bad beliefs
|
||||
_Atomic(enum PosixThreadStatus) status;
|
||||
_Atomic(int) ptid; // transitions 0 → tid
|
||||
void *(*start)(void *); // creation callback
|
||||
void *arg; // start's parameter
|
||||
void *rc; // start's return value
|
||||
char *altstack; // thread sigaltstack
|
||||
char *tls; // bottom of tls allocation
|
||||
struct CosmoTib *tib; // middle of tls allocation
|
||||
nsync_dll_element_ list; // list of threads
|
||||
jmp_buf exiter; // for pthread_exit
|
||||
_Atomic(int) ptid; // transitions 0 → tid
|
||||
void *(*start)(void *); // creation callback
|
||||
void *arg; // start's parameter
|
||||
void *rc; // start's return value
|
||||
char *altstack; // thread sigaltstack
|
||||
char *tls; // bottom of tls allocation
|
||||
struct CosmoTib *tib; // middle of tls allocation
|
||||
struct Dll list; // list of threads
|
||||
jmp_buf exiter; // for pthread_exit
|
||||
pthread_attr_t attr;
|
||||
struct _pthread_cleanup_buffer *cleanup;
|
||||
};
|
||||
|
||||
typedef void (*atfork_f)(void);
|
||||
|
||||
extern nsync_dll_list_ _pthread_list;
|
||||
extern struct Dll *_pthread_list;
|
||||
extern pthread_spinlock_t _pthread_lock;
|
||||
extern _Atomic(pthread_key_dtor) _pthread_key_dtor[PTHREAD_KEYS_MAX] _Hide;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/intrin/kmalloc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
@ -37,10 +38,10 @@ static struct AtForks {
|
|||
} _atforks;
|
||||
|
||||
static void _pthread_purge(void) {
|
||||
nsync_dll_element_ *e;
|
||||
while ((e = nsync_dll_first_(_pthread_list))) {
|
||||
_pthread_list = nsync_dll_remove_(_pthread_list, e);
|
||||
_pthread_free(e->container);
|
||||
struct Dll *e;
|
||||
while ((e = dll_first(_pthread_list))) {
|
||||
dll_remove(&_pthread_list, e);
|
||||
_pthread_free(POSIXTHREAD_CONTAINER(e));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,9 +98,9 @@ void _pthread_onfork_child(void) {
|
|||
|
||||
// delete other threads that existed before forking
|
||||
// this must come after onfork, since it calls free
|
||||
_pthread_list = nsync_dll_remove_(_pthread_list, &pt->list);
|
||||
dll_remove(&_pthread_list, &pt->list);
|
||||
_pthread_purge();
|
||||
_pthread_list = nsync_dll_make_first_in_list_(_pthread_list, &pt->list);
|
||||
dll_make_first(&_pthread_list, &pt->list);
|
||||
}
|
||||
|
||||
int _pthread_atfork(atfork_f prepare, atfork_f parent, atfork_f child) {
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/clone.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -43,7 +43,6 @@
|
|||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/wait0.internal.h"
|
||||
#include "third_party/nsync/dll.h"
|
||||
|
||||
STATIC_YOINK("nsync_mu_lock");
|
||||
STATIC_YOINK("nsync_mu_unlock");
|
||||
|
@ -246,9 +245,9 @@ static errno_t pthread_create_impl(pthread_t *thread,
|
|||
|
||||
// add thread to global list
|
||||
// we add it to the end since zombies go at the beginning
|
||||
nsync_dll_init_(&pt->list, pt);
|
||||
dll_init(&pt->list);
|
||||
pthread_spin_lock(&_pthread_lock);
|
||||
_pthread_list = nsync_dll_make_last_in_list_(_pthread_list, &pt->list);
|
||||
dll_make_last(&_pthread_list, &pt->list);
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
|
||||
// launch PosixThread(pt) in new thread
|
||||
|
@ -260,7 +259,7 @@ static errno_t pthread_create_impl(pthread_t *thread,
|
|||
CLONE_CHILD_CLEARTID,
|
||||
pt, &pt->ptid, __adj_tls(pt->tib), &pt->tib->tib_tid))) {
|
||||
pthread_spin_lock(&_pthread_lock);
|
||||
_pthread_list = nsync_dll_remove_(_pthread_list, &pt->list);
|
||||
dll_remove(&_pthread_list, &pt->list);
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
_pthread_free(pt);
|
||||
return rc;
|
||||
|
|
|
@ -17,29 +17,28 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "third_party/nsync/dll.h"
|
||||
|
||||
/**
|
||||
* Releases memory of detached threads that have terminated.
|
||||
*/
|
||||
void pthread_decimate_np(void) {
|
||||
nsync_dll_element_ *e;
|
||||
struct Dll *e;
|
||||
struct PosixThread *pt;
|
||||
enum PosixThreadStatus status;
|
||||
StartOver:
|
||||
pthread_spin_lock(&_pthread_lock);
|
||||
for (e = nsync_dll_first_(_pthread_list); e;
|
||||
e = nsync_dll_next_(_pthread_list, e)) {
|
||||
pt = (struct PosixThread *)e->container;
|
||||
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
|
||||
pt = POSIXTHREAD_CONTAINER(e);
|
||||
if (pt->tib == __get_tls()) continue;
|
||||
status = atomic_load_explicit(&pt->status, memory_order_acquire);
|
||||
if (status != kPosixThreadZombie) break;
|
||||
if (!atomic_load_explicit(&pt->tib->tib_tid, memory_order_acquire)) {
|
||||
_pthread_list = nsync_dll_remove_(_pthread_list, e);
|
||||
dll_remove(&_pthread_list, e);
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
_pthread_free(pt);
|
||||
goto StartOver;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "third_party/nsync/dll.h"
|
||||
|
||||
/**
|
||||
* Asks POSIX thread to free itself automatically upon termination.
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "third_party/nsync/dll.h"
|
||||
#include "third_party/nsync/futex.internal.h"
|
||||
|
||||
static void CleanupThread(struct PosixThread *pt) {
|
||||
|
|
|
@ -1,91 +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 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/blockcancel.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "third_party/nsync/dll.h"
|
||||
|
||||
#define N 2048
|
||||
#define M 15
|
||||
|
||||
#define append(f, ...) o += f(buf + o, N - o, __VA_ARGS__)
|
||||
|
||||
static const char *DescribeStatus(enum PosixThreadStatus status) {
|
||||
switch (status) {
|
||||
case kPosixThreadJoinable:
|
||||
return "JOINAB";
|
||||
case kPosixThreadDetached:
|
||||
return "DETACH";
|
||||
case kPosixThreadTerminated:
|
||||
return "TERMIN";
|
||||
case kPosixThreadZombie:
|
||||
return "ZOMBIE";
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static const char *DescribeFlags(char buf[M], struct PosixThread *pt) {
|
||||
char *p = buf;
|
||||
if (pt->cancelled) *p++ = '*';
|
||||
if (pt->flags & PT_EXITING) *p++ = 'X';
|
||||
if (pt->flags & PT_STATIC) *p++ = 'S';
|
||||
if (pt->flags & PT_OWNSTACK) *p++ = 'O';
|
||||
if (pt->flags & PT_ASYNC) *p++ = 'A';
|
||||
if (pt->flags & PT_MASKED) *p++ = 'M';
|
||||
if (pt->flags & PT_OPENBSD_KLUDGE) *p++ = 'K';
|
||||
if (pt->flags & PT_INCANCEL) *p++ = '?';
|
||||
if (pt->flags & PT_NOCANCEL) *p++ = '!';
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int pthread_print_np(int fd, const char *fmt, ...) {
|
||||
va_list va;
|
||||
int rc, o = 0;
|
||||
nsync_dll_element_ *e;
|
||||
struct PosixThread *pt;
|
||||
char buf[N], flagbuf[M];
|
||||
pthread_spin_lock(&_pthread_lock);
|
||||
if (fmt) {
|
||||
va_start(va, fmt);
|
||||
append(kvsnprintf, fmt, va);
|
||||
va_end(va);
|
||||
append(ksnprintf, "\n");
|
||||
}
|
||||
append(ksnprintf, "%6s %6s %6s %6s %s\n", "ptid", "tid", "status", "flags",
|
||||
"start");
|
||||
for (e = nsync_dll_first_(_pthread_list); e;
|
||||
e = nsync_dll_next_(_pthread_list, e)) {
|
||||
pt = (struct PosixThread *)e->container;
|
||||
append(ksnprintf, "%-6d %-6d %6s %6s %t\n", pt->ptid, pt->tib->tib_tid,
|
||||
DescribeStatus(pt->status), DescribeFlags(flagbuf, pt), pt->start);
|
||||
}
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
BLOCK_CANCELLATIONS;
|
||||
strace_enabled(-1);
|
||||
rc = write(fd, buf, strlen(buf));
|
||||
strace_enabled(+1);
|
||||
ALLOW_CANCELLATIONS;
|
||||
return rc;
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/thread2.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
@ -60,7 +61,7 @@ errno_t pthread_timedjoin_np(pthread_t thread, void **value_ptr,
|
|||
_unassert(status == kPosixThreadJoinable || status == kPosixThreadTerminated);
|
||||
if (!(rc = _wait0(&pt->tib->tib_tid, abstime))) {
|
||||
pthread_spin_lock(&_pthread_lock);
|
||||
_pthread_list = nsync_dll_remove_(_pthread_list, &pt->list);
|
||||
dll_remove(&_pthread_list, &pt->list);
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
if (value_ptr) {
|
||||
*value_ptr = pt->rc;
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "third_party/nsync/dll.h"
|
||||
|
||||
void _pthread_zombify(struct PosixThread *pt) {
|
||||
pthread_spin_lock(&_pthread_lock);
|
||||
_pthread_list = nsync_dll_remove_(_pthread_list, &pt->list);
|
||||
_pthread_list = nsync_dll_make_first_in_list_(_pthread_list, &pt->list);
|
||||
dll_remove(&_pthread_list, &pt->list);
|
||||
dll_make_first(&_pthread_list, &pt->list);
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/clone.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
|
|
|
@ -170,7 +170,6 @@ int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int) paramsnonnull();
|
|||
int pthread_mutexattr_settype(pthread_mutexattr_t *, int) paramsnonnull();
|
||||
int pthread_once(pthread_once_t *, void (*)(void)) paramsnonnull();
|
||||
int pthread_orphan_np(void);
|
||||
int pthread_print_np(int, const char *, ...);
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *) paramsnonnull();
|
||||
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *) paramsnonnull((1));
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *) paramsnonnull();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue