mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-04 10:18:31 +00:00
Make improvements
- Get threads working on NetBSD - Get threads working on OpenBSD - Fix Emacs config for Emacs v28 - Improve --strace logging of sigset_t - Improve --strace logging of struct stat - Improve memory safety of DescribeThing functions - Refactor auto stack allocation into LIBC_RUNTIME - Introduce shell.com example which works on Windows - Refactor __strace_thing into DescribeThing functions - Document the CHECK macros and improve them in NDEBUG mode - Rewrite MAP_STACK so it uses FreeBSD behavior across platforms - Deprecate and discourage the use of MAP_GROWSDOWN (it's weird)
This commit is contained in:
parent
dd9ab01d25
commit
e7611a8476
101 changed files with 967 additions and 464 deletions
|
@ -47,7 +47,7 @@
|
|||
STATIC_YOINK("gettid"); // for kprintf()
|
||||
|
||||
#define __NR_thr_new 455
|
||||
#define __NR_sys___tfork 8
|
||||
#define __NR___tfork 8
|
||||
#define __NR_clone_linux 56
|
||||
#define __NR__lwp_create 309
|
||||
#define __NR_getcontext_netbsd 307
|
||||
|
@ -67,6 +67,7 @@ static struct Cloner {
|
|||
} __cloner;
|
||||
|
||||
static textwindows uint32_t WinThreadMain(void *notused) {
|
||||
intptr_t rdi, rdx;
|
||||
int (*func)(void *);
|
||||
void *arg, *stack;
|
||||
struct WinThread *wt;
|
||||
|
@ -82,16 +83,18 @@ static textwindows uint32_t WinThreadMain(void *notused) {
|
|||
wt->pid = tid;
|
||||
TlsSetValue(__winthread, wt);
|
||||
if (flags & CLONE_CHILD_SETTID) *ctid = tid;
|
||||
asm volatile("mov\t%%rbp,%%rbx\n\t"
|
||||
asm volatile("push\t%%rbp\n\t"
|
||||
"mov\t%%rsp,%%r15\n\t"
|
||||
"xor\t%%ebp,%%ebp\n\t"
|
||||
"xchg\t%%rax,%%rsp\n\t"
|
||||
"call\t*%2\n\t"
|
||||
"mov\t%%rbx,%%rbp\n\t"
|
||||
"mov\t%%r15,%%rsp"
|
||||
: "=a"(exitcode)
|
||||
: "0"(stack), "d"(func), "D"(arg)
|
||||
: "rbx", "r15", "memory");
|
||||
"mov\t%%r15,%%rsp\n\t"
|
||||
"pop\t%%rbp"
|
||||
: "=a"(exitcode), "=D"(rdi), "=d"(rdx)
|
||||
: "0"(stack), "1"(arg), "2"(func)
|
||||
: "rbx", "rcx", "rsi", "r8", "r9", "r10", "r11", "r15",
|
||||
"memory");
|
||||
if (flags & CLONE_CHILD_CLEARTID) *ctid = 0;
|
||||
__releasefd(tid);
|
||||
free(wt);
|
||||
|
@ -113,8 +116,7 @@ static textwindows int CloneWindows(int (*func)(void *), void *stk,
|
|||
__cloner.ctid = ctid;
|
||||
__cloner.flags = flags;
|
||||
__cloner.stack = (char *)stk + stksz;
|
||||
if (!(hand = CreateThread(&kNtIsInheritable, 0, NT2SYSV(WinThreadMain), 0, 0,
|
||||
&wintid))) {
|
||||
if (!(hand = CreateThread(0, 0, NT2SYSV(WinThreadMain), 0, 0, &wintid))) {
|
||||
_spunlock(&__cloner.lock);
|
||||
return -1;
|
||||
}
|
||||
|
@ -132,6 +134,7 @@ static dontinline wontreturn void BsdThreadMain(void *unused) {
|
|||
void *arg;
|
||||
int (*func)(void *);
|
||||
int tid, flags, exitcode, *ctid;
|
||||
asm("xor\t%ebp,%ebp");
|
||||
tid = __cloner.tid;
|
||||
arg = __cloner.arg;
|
||||
func = __cloner.func;
|
||||
|
@ -193,26 +196,24 @@ static privileged noasan int CloneOpenbsd(int (*func)(void *), char *stk,
|
|||
asm volatile("" ::: "memory");
|
||||
params.tf_tid = (int *)&__cloner.tid;
|
||||
params.tf_tcb = flags & CLONE_SETTLS ? tls : 0;
|
||||
params.tf_stack = stk + stksz;
|
||||
// we need openbsd:stackbound because openbsd kernel enforces rsp must
|
||||
// be on interval [stack, stack+size) thus the top address is an error
|
||||
// furthermore this needs to be allocated using MAP_STACK OR GROWSDOWN
|
||||
params.tf_stack = (void *)((intptr_t)((char *)stk + stksz - 1) & -16);
|
||||
asm volatile(CFLAG_ASM("syscall")
|
||||
: CFLAG_CONSTRAINT(failed), "=a"(ax)
|
||||
: "1"(__NR_sys___tfork), "D"(¶ms), "S"(sizeof(params))
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
if (!failed) {
|
||||
if (!ax) {
|
||||
// this is the child thread
|
||||
// we probably can't access local variables anymore
|
||||
asm volatile("" ::: "memory");
|
||||
BsdThreadMain(0);
|
||||
unreachable;
|
||||
} else {
|
||||
if (flags & CLONE_PARENT_SETTID) *ptid = ax;
|
||||
return ax;
|
||||
}
|
||||
} else {
|
||||
: "1"(__NR___tfork), "D"(¶ms), "S"(sizeof(params))
|
||||
: "r11", "memory", "cc");
|
||||
if (failed) {
|
||||
errno = ax;
|
||||
return -1;
|
||||
}
|
||||
if (ax) {
|
||||
if (flags & CLONE_PARENT_SETTID) *ptid = ax;
|
||||
return ax;
|
||||
}
|
||||
BsdThreadMain(0);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
static privileged noasan int CloneNetbsd(int (*func)(void *), void *stk,
|
||||
|
@ -231,8 +232,8 @@ static privileged noasan int CloneNetbsd(int (*func)(void *), void *stk,
|
|||
errno = ax;
|
||||
return -1;
|
||||
}
|
||||
stack = (void *)(((long)((char *)stk + stksz) & -16) - 8 * 3);
|
||||
*(long *)stack = (long)_Exit1;
|
||||
stack = (intptr_t *)((intptr_t)((char *)stk + stksz) & -16);
|
||||
*--stack = (intptr_t)_Exit1;
|
||||
ctx.uc_link = 0;
|
||||
ctx.uc_mcontext.rip = (intptr_t)func;
|
||||
ctx.uc_mcontext.rdi = (intptr_t)arg;
|
||||
|
@ -265,14 +266,15 @@ static privileged int CloneLinux(int (*func)(void *), void *stk, size_t stksz,
|
|||
size_t tlssz, int *ctid) {
|
||||
int ax;
|
||||
bool failed;
|
||||
intptr_t *stack;
|
||||
register int *r8 asm("r8") = tls;
|
||||
register int (*r9)(void *) asm("r9") = func;
|
||||
register int *r10 asm("r10") = ctid;
|
||||
stk = (void *)(((long)((char *)stk + stksz) & -16) - 8);
|
||||
*(long *)stk = (long)arg;
|
||||
stack = (intptr_t *)((long)((char *)stk + stksz) & -16);
|
||||
*--stack = (long)arg; // push 1
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(__NR_clone_linux), "D"(flags), "S"(stk), "d"(ptid),
|
||||
: "0"(__NR_clone_linux), "D"(flags), "S"(stack), "d"(ptid),
|
||||
"r"(r10), "r"(r8), "r"(r9)
|
||||
: "rcx", "r11", "memory");
|
||||
if (ax > -4096u) {
|
||||
|
@ -281,8 +283,8 @@ static privileged int CloneLinux(int (*func)(void *), void *stk, size_t stksz,
|
|||
}
|
||||
if (ax) return ax;
|
||||
asm volatile("xor\t%%ebp,%%ebp\n\t"
|
||||
"pop\t%%rdi\n\t"
|
||||
"call\t%0\n\t"
|
||||
"pop\t%%rdi\n\t" // pop 1
|
||||
"call\t*%0\n\t"
|
||||
"xchg\t%%eax,%%edi\n\t"
|
||||
"jmp\t_Exit1"
|
||||
: /* no outputs */
|
||||
|
@ -302,6 +304,8 @@ static privileged int CloneLinux(int (*func)(void *), void *stk, size_t stksz,
|
|||
* @param func is your callback function
|
||||
* @param stk points to the bottom of a caller allocated stack, which
|
||||
* must be null when fork() and vfork() equivalent flags are used
|
||||
* and furthermore this must be mmap()'d using MAP_STACK in order
|
||||
* to work on OpenBSD
|
||||
* @param stksz is the size of that stack in bytes which must be zero
|
||||
* if the fork() or vfork() equivalent flags are used it's highly
|
||||
* recommended that this value be GetStackSize(), or else kprintf
|
||||
|
@ -350,7 +354,8 @@ privileged int clone(int (*func)(void *), void *stk, size_t stksz, int flags,
|
|||
}
|
||||
|
||||
// polyfill fork() and vfork() use case on platforms w/o clone
|
||||
else if (flags == (CLONE_VFORK | CLONE_VM | SIGCHLD)) {
|
||||
else if ((SupportsWindows() || SupportsBsd()) &&
|
||||
flags == (CLONE_VFORK | CLONE_VM | SIGCHLD)) {
|
||||
if (IsTiny()) {
|
||||
rc = einval();
|
||||
} else if (!arg && !stksz) {
|
||||
|
@ -358,7 +363,7 @@ privileged int clone(int (*func)(void *), void *stk, size_t stksz, int flags,
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
} else if (flags == SIGCHLD) {
|
||||
} else if ((SupportsWindows() || SupportsBsd()) && flags == SIGCHLD) {
|
||||
if (IsTiny()) {
|
||||
rc = eopnotsupp();
|
||||
} else if (!arg && !stksz) {
|
||||
|
|
|
@ -46,6 +46,7 @@ $(LIBC_THREAD_A).pkg: \
|
|||
$(LIBC_THREAD_A_OBJS) \
|
||||
$(foreach x,$(LIBC_THREAD_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
# no red zone because asm("call")
|
||||
o/$(MODE)/libc/thread/clone.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-mno-red-zone
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue