Clean up the clone() code a bit

This commit is contained in:
Justine Tunney 2022-05-17 07:40:00 -07:00
parent ce71677156
commit 2743f3d012
20 changed files with 252 additions and 150 deletions

View file

@ -18,11 +18,11 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/threaded.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/sysconf.h"
#include "libc/sock/sock.h"

View file

@ -35,12 +35,11 @@ privileged wontreturn void _Exit1(int rc) {
struct WinThread *wt;
STRACE("_Exit1(%d)", rc);
if (!IsWindows() && !IsMetal()) {
register long r10 asm("r10") = 0;
asm volatile("syscall"
asm volatile("xor\t%%r10d,%%r10d\n\t"
"syscall"
: /* no outputs */
: "a"(__NR_exit), "D"(IsLinux() ? rc : 0), "S"(0), "d"(0),
"r"(r10)
: "rcx", "r11", "memory");
: "a"(__NR_exit), "D"(IsLinux() ? rc : 0), "S"(0), "d"(0)
: "rcx", "r10", "r11", "memory");
} else if (IsWindows()) {
ExitThread(rc);
}

View file

@ -18,7 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/threaded.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nt/thread.h"
/**

View file

@ -31,11 +31,11 @@
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/threaded.h"
#include "libc/limits.h"
#include "libc/log/internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"

View file

@ -1,16 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_THREADED_H_
#define COSMOPOLITAN_LIBC_INTRIN_THREADED_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern bool __threaded;
extern bool __tls_enabled;
extern unsigned __tls_index;
void *__initialize_tls(char[hasatleast 64]);
void __install_tls(char[hasatleast 64]);
char *__get_tls(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_THREADED_H_ */

View file

@ -20,7 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/threaded.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nt/thread.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/sysv/consts/nrlinux.h"

View file

@ -0,0 +1,38 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 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/macros.internal.h"
// Checks that stack is 16-byte aligned.
//
// This function crashes if called with a misaligned stack.
_checkstackalign:
push %rbp
mov %rsp,%rbp
/ allocate sixteen bytes
push %rax
push %rax
/ put a value in it
xorps %xmm0,%xmm0
movaps %xmm0,-16(%rbp)
leave
ret
.endfn _checkstackalign,globl

View file

@ -7,6 +7,7 @@ extern long kHalfCache3;
void imapxlatab(void *);
void insertionsort(int32_t *, size_t);
void _checkstackalign(void);
int64_t div10int64(int64_t) libcesque pureconst;
int64_t div100int64(int64_t) libcesque pureconst;

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/threaded.h"
#include "libc/nexgen32e/threaded.h"
bool __threaded;
bool __tls_enabled;

39
libc/nexgen32e/threaded.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_THREADED_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_THREADED_H_
#include "libc/dce.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern bool __threaded;
extern bool __tls_enabled;
extern unsigned __tls_index;
void *__initialize_tls(char[hasatleast 64]);
void __install_tls(char[hasatleast 64]);
#if defined(__GNUC__) && defined(__x86_64__)
/**
* Returns address of thread information block.
*
* This function must not be called until TLS is initialized.
*
* @see __install_tls()
* @see clone()
*/
static noasan inline char *__get_tls(void) {
char *tib, *lin = (char *)0x30;
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd()) {
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin));
} else {
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin));
if (IsWindows()) {
tib = *(char **)(tib + 0x1480 + __tls_index * 8);
}
}
return tib;
}
#endif /* GNU x86-64 */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_THREADED_H_ */

View file

@ -26,7 +26,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/threaded.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thread.h"
#include "libc/nt/thunk/msabi.h"
@ -50,17 +50,32 @@ STATIC_YOINK("gettid"); // for kprintf()
#define LWP_DETACHED 0x00000040
#define LWP_SUSPENDED 0x00000080
static char tibdefault[64];
struct WinThread {
uint32_t tid;
struct CloneArgs {
union {
int tid;
uint32_t utid;
int64_t tid64;
};
int lock;
int flags;
int *ctid;
void *tls;
char *tls;
int (*func)(void *);
void *arg;
void *pad; // TODO: Why does FreeBSD clobber this?
};
struct __tfork {
void *tf_tcb;
int32_t *tf_tid;
void *tf_stack;
};
static char tibdefault[64];
////////////////////////////////////////////////////////////////////////////////
// THE NEW TECHNOLOGY
uint32_t WinThreadThunk(void *warg);
asm(".section\t.text.windows,\"ax\",@progbits\n\t"
".local\tWinThreadThunk\n"
@ -69,13 +84,14 @@ asm(".section\t.text.windows,\"ax\",@progbits\n\t"
"mov\t%rcx,%rdi\n\t"
"mov\t%rcx,%rsp\n\t"
"and\t$-16,%rsp\n\t"
"call\tWinThreadMain\n\t"
"push\t%rax\n\t"
"jmp\tWinThreadMain\n\t"
".size\tWinThreadThunk,.-WinThreadThunk\n\t"
".previous");
__attribute__((__used__, __no_reorder__))
static textwindows wontreturn void
WinThreadMain(struct WinThread *wt) {
WinThreadMain(struct CloneArgs *wt) {
int rc;
if (wt->flags & CLONE_SETTLS) {
TlsSetValue(__tls_index, wt->tls);
@ -91,16 +107,16 @@ static textwindows int CloneWindows(int (*func)(void *), char *stk,
size_t stksz, int flags, void *arg,
void *tls, size_t tlssz, int *ctid) {
int64_t h;
struct WinThread *wt;
wt = (struct WinThread *)(((intptr_t)(stk + stksz) -
sizeof(struct WinThread)) &
-alignof(struct WinThread));
struct CloneArgs *wt;
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
sizeof(struct CloneArgs)) &
-alignof(struct CloneArgs));
wt->flags = flags;
wt->ctid = ctid;
wt->func = func;
wt->arg = arg;
wt->tls = tls;
if ((h = CreateThread(0, 0, WinThreadThunk, wt, 0, &wt->tid))) {
if ((h = CreateThread(0, 0, WinThreadThunk, wt, 0, &wt->utid))) {
CloseHandle(h);
return wt->tid;
} else {
@ -108,45 +124,49 @@ static textwindows int CloneWindows(int (*func)(void *), char *stk,
}
}
////////////////////////////////////////////////////////////////////////////////
// XNU'S NOT UNIX
void XnuThreadThunk(void *pthread, int machport, void *(*func)(void *),
void *arg, intptr_t *stack, unsigned flags);
asm(".local\tXnuThreadThunk\n"
"XnuThreadThunk:\n\t"
"xor\t%ebp,%ebp\n\t"
"mov\t%r8,%rsp\n\t"
"and\t$-16,%rsp\n\t"
"push\t%rax\n\t"
"jmp\tXnuThreadMain\n\t"
".size\tXnuThreadThunk,.-XnuThreadThunk");
__attribute__((__used__, __no_reorder__))
static wontreturn void
XnuThreadMain(void *pthread, int tid, int (*func)(void *arg), void *arg,
intptr_t *sp, unsigned flags) {
int rc;
sp[1] = tid;
_spunlock(sp);
if (sp[4] & CLONE_SETTLS) {
struct CloneArgs *wt, unsigned flags) {
int ax;
wt->tid = tid;
_spunlock(&wt->lock);
if (wt->flags & CLONE_SETTLS) {
// XNU uses the same 0x30 offset as the WIN32 TIB x64. They told the
// Go team at Google that they Apply stands by our ability to use it
// https://github.com/golang/go/issues/23617#issuecomment-376662373
asm volatile("syscall"
: "=a"(rc)
: "0"(__NR_thread_fast_set_cthread_self), "D"(sp[3] - 0x30)
: "=a"(ax)
: "0"(__NR_thread_fast_set_cthread_self), "D"(wt->tls - 0x30)
: "rcx", "r11", "memory", "cc");
}
if (sp[4] & CLONE_CHILD_SETTID) {
*(int *)sp[2] = tid;
if (wt->flags & CLONE_CHILD_SETTID) {
*wt->ctid = tid;
}
rc = func(arg);
_Exit1(rc);
_Exit1(func(arg));
}
static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
void *arg, void *tls, size_t tlssz, int *ctid) {
int rc;
bool failed;
intptr_t *sp;
static bool once;
static int broken;
struct CloneArgs *wt;
if (!once) {
if (bsdthread_register(XnuThreadThunk, 0, 0, 0, 0, 0, 0) == -1) {
broken = errno;
@ -157,38 +177,40 @@ static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
errno = broken;
return -1;
}
sp = (intptr_t *)(stk + stksz);
*--sp = 0; // 5 padding
*--sp = flags; // 4 clone() flags
*--sp = (intptr_t)tls; // 3 thread local storage
*--sp = (intptr_t)ctid; // 2 child tid api
*--sp = 0; // 1 receives tid
*--sp = 0; // 0 lock
_seizelock(sp); // TODO: How can we get the tid without locking?
if ((rc = bsdthread_create(fn, arg, sp, 0, PTHREAD_START_CUSTOM_XNU)) != -1) {
_spinlock(sp);
rc = sp[1];
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
sizeof(struct CloneArgs)) &
-alignof(struct CloneArgs));
wt->flags = flags;
wt->ctid = ctid;
wt->tls = tls;
_seizelock(&wt->lock); // TODO: How can we get the tid without locking?
if ((rc = bsdthread_create(fn, arg, wt, 0, PTHREAD_START_CUSTOM_XNU)) != -1) {
_spinlock(&wt->lock);
rc = wt->tid;
}
return rc;
}
void FreebsdThreadThunk(void *sp) wontreturn;
////////////////////////////////////////////////////////////////////////////////
// FREE BESIYATA DISHMAYA
void FreebsdThreadThunk(void *) wontreturn;
asm(".local\tFreebsdThreadThunk\n"
"FreebsdThreadThunk:\n\t"
"xor\t%ebp,%ebp\n\t"
"mov\t%rdi,%rsp\n\t"
"and\t$-16,%rsp\n\t"
"push\t%rax\n\t"
"jmp\tFreebsdThreadMain\n\t"
".size\tFreebsdThreadThunk,.-FreebsdThreadThunk");
__attribute__((__used__, __no_reorder__))
static wontreturn void
FreebsdThreadMain(intptr_t *sp) {
int rc;
if (sp[3] & CLONE_CHILD_SETTID) {
*(int *)sp[2] = sp[4];
FreebsdThreadMain(struct CloneArgs *wt) {
if (wt->flags & CLONE_CHILD_SETTID) {
*wt->ctid = wt->tid;
}
rc = ((int (*)(intptr_t))sp[0])(sp[1]);
_Exit1(rc);
_Exit1(wt->func(wt->arg));
}
static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
@ -196,22 +218,23 @@ static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
int ax;
bool failed;
int64_t tid;
intptr_t *sp;
sp = (intptr_t *)(stk + stksz);
*--sp = 0; // 5 [padding]
*--sp = 0; // 4 [child_tid]
*--sp = flags; // 3
*--sp = (intptr_t)ctid; // 2
*--sp = (intptr_t)arg; // 1
*--sp = (intptr_t)func; // 0
struct CloneArgs *wt;
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
sizeof(struct CloneArgs)) &
-alignof(struct CloneArgs));
wt->flags = flags;
wt->ctid = ctid;
wt->tls = tls;
wt->func = func;
wt->arg = arg;
struct thr_param params = {
.start_func = FreebsdThreadThunk,
.arg = sp,
.arg = wt,
.stack_base = stk,
.stack_size = stksz,
.tls_base = flags & CLONE_SETTLS ? tls : 0,
.tls_size = flags & CLONE_SETTLS ? tlssz : 0,
.child_tid = sp + 4,
.child_tid = &wt->tid64,
.parent_tid = &tid,
};
asm volatile(CFLAG_ASM("syscall")
@ -225,13 +248,10 @@ static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
return tid;
}
struct __tfork {
void *tf_tcb;
int32_t *tf_tid;
void *tf_stack;
};
////////////////////////////////////////////////////////////////////////////////
// OPEN BESIYATA DISHMAYA
int __tfork(struct __tfork *params, size_t psize, intptr_t *stack);
int __tfork(struct __tfork *params, size_t psize, struct CloneArgs *wt);
asm(".section\t.privileged,\"ax\",@progbits\n\t"
".local\t__tfork\n"
"__tfork:\n\t"
@ -248,46 +268,50 @@ asm(".section\t.privileged,\"ax\",@progbits\n\t"
"xor\t%ebp,%ebp\n\t"
"mov\t%r8,%rsp\n\t"
"mov\t%r8,%rdi\n\t"
"and\t$-16,%rsp\n\t"
"push\t%rax\n\t"
"jmp\tOpenbsdThreadMain\n\t"
".size\t__tfork,.-__tfork\n\t"
".previous");
__attribute__((__used__, __no_reorder__))
static privileged wontreturn void
OpenbsdThreadMain(intptr_t *sp) {
int rc;
rc = ((int (*)(intptr_t))sp[0])(sp[1]);
_Exit1(rc);
OpenbsdThreadMain(struct CloneArgs *wt) {
_Exit1(wt->func(wt->arg));
}
static int CloneOpenbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
void *arg, void *tls, size_t tlssz, int *ctid) {
int tid;
intptr_t *sp;
struct CloneArgs *wt;
struct __tfork params;
sp = (intptr_t *)(stk + stksz);
*--sp = flags; // 3
*--sp = (intptr_t)ctid; // 2
*--sp = (intptr_t)arg; // 1
*--sp = (intptr_t)func; // 0
params.tf_stack = sp;
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
sizeof(struct CloneArgs)) &
-alignof(struct CloneArgs));
wt->flags = flags;
wt->ctid = ctid;
wt->func = func;
wt->arg = arg;
params.tf_stack = wt;
params.tf_tcb = flags & CLONE_SETTLS ? tls : 0;
params.tf_tid = flags & CLONE_CHILD_SETTID ? ctid : 0;
if ((tid = __tfork(&params, sizeof(params), sp)) < 0) {
if ((tid = __tfork(&params, sizeof(params), wt)) < 0) {
errno = -tid;
tid = -1;
}
return tid;
}
////////////////////////////////////////////////////////////////////////////////
// NET BESIYATA DISHMAYA
static wontreturn void NetbsdThreadMain(void *arg, int (*func)(void *arg),
int *tid, int *ctid, int flags) {
int rc;
if (flags & CLONE_CHILD_SETTID) {
*ctid = *tid;
}
rc = func(arg);
_Exit1(rc);
_Exit1(func(arg));
}
static int CloneNetbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
@ -353,16 +377,21 @@ static int CloneNetbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
}
}
static int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
void *arg, int *ptid, void *tls, size_t tlssz,
int *ctid) {
////////////////////////////////////////////////////////////////////////////////
// GNU/SYSTEMD
int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
void *arg, int *ptid, void *tls, size_t tlssz, int *ctid) {
#ifdef __chibicc__
return -1; // TODO
#else
int ax;
register int *r8 asm("r8") = tls;
register int *r10 asm("r10") = ctid;
register void *r9 asm("r9") = func;
intptr_t *stack = (intptr_t *)(stk + stksz);
*--stack = (intptr_t)arg;
asm volatile("syscall\n\t"
asm volatile("mov\t%4,%%r10\n\t" // ctid
"mov\t%5,%%r8\n\t" // tls
"mov\t%6,%%r9\n\t" // func
"syscall\n\t"
"test\t%0,%0\n\t"
"jnz\t1f\n\t"
"xor\t%%ebp,%%ebp\n\t"
@ -371,13 +400,17 @@ static int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
"xchg\t%%eax,%%edi\n\t"
"jmp\t_Exit1\n1:"
: "=a"(ax)
: "0"(__NR_clone_linux), "D"(flags), "S"(stack), "r"(r10),
"r"(r8), "r"(r9)
: "rcx", "r11", "memory");
: "0"(__NR_clone_linux), "D"(flags), "S"(stack), "g"(ctid),
"g"(tls), "g"(func)
: "rcx", "r8", "r9", "r10", "r11", "memory");
if (ax > -4096u) errno = -ax, ax = -1;
return ax;
#endif
}
////////////////////////////////////////////////////////////////////////////////
// COSMOPOLITAN
/**
* Creates thread.
*
@ -446,9 +479,13 @@ static int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
int clone(int (*func)(void *), void *stk, size_t stksz, int flags, void *arg,
int *ptid, void *tls, size_t tlssz, int *ctid) {
int rc;
struct CloneArgs *wt;
__threaded = true;
if (tls && !__tls_enabled) {
if (flags & CLONE_THREAD) {
__threaded = true;
}
if ((flags & CLONE_SETTLS) && !__tls_enabled) {
__initialize_tls(tibdefault);
__install_tls(tibdefault);
}

View file

@ -16,11 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/threaded.h"
#include "libc/nt/thread.h"
#include "libc/errno.h"
#include "libc/nexgen32e/threaded.h"
/**
* Global variable for last error.
@ -36,24 +33,9 @@
*/
errno_t __errno;
/**
* Returns address of thread information block.
* @see __install_tls()
* @see clone()
*/
privileged nocallersavedregisters char *__get_tls(void) {
char *tib, *linear = (char *)0x30;
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd()) {
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(linear));
} else {
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(linear));
if (IsWindows()) tib = *(char **)(tib + 0x1480 + __tls_index * 8);
}
return tib;
}
/**
* Returns address of errno variable.
*
* @see __initialize_tls()
* @see __install_tls()
*/

View file

@ -34,13 +34,15 @@ int cthread_join(cthread_t td, int* rc) {
: "cc");
if (!(state & cthread_finished)) {
int ax;
int flags = FUTEX_WAIT; // PRIVATE makes it hang
register struct timespec* timeout asm("r10") = NULL;
asm volatile("syscall"
: /* no outputs */
: "a"(__NR_futex), "D"(&td->tid), "S"(flags), "d"(tid),
"r"(timeout)
: "rcx", "r11", "cc", "memory");
struct timespec* timeout = NULL;
asm volatile("mov\t%5,%%r10\n\t" // timeout
"syscall"
: "=a"(ax)
: "0"(__NR_futex), "D"(&td->tid), "S"(flags), "d"(tid),
"g"(timeout)
: "rcx", "r10", "r11", "cc", "memory");
}
*rc = td->rc;

View file

@ -25,12 +25,12 @@ int cthread_memory_wait32(uint32_t* addr, uint32_t val,
if (__NR_futex != 0xfff) {
int flags = FUTEX_WAIT;
int rc;
register struct timespec* timeout_ asm("r10") = timeout;
asm volatile("syscall"
asm volatile("mov\t%5,%%r10\n\t" // timeout
"syscall"
: "=a"(rc)
: "0"(__NR_futex), "D"(addr), "S"(flags), "d"(val),
"r"(timeout_)
: "rcx", "r11", "cc", "memory");
"g"(timeout)
: "rcx", "r10", "r11", "cc", "memory");
return rc;
}
return -1;

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/intrin/threaded.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/runtime.h"
#include "libc/testlib/testlib.h"

View file

@ -23,8 +23,8 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/threaded.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/rand/rand.h"
#include "libc/runtime/stack.h"
#include "libc/str/str.h"

View file

@ -21,13 +21,15 @@
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/threaded.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/consts/clone.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
#include "libc/time/time.h"
@ -48,15 +50,11 @@ void SetUp(void) {
}
void TearDown(void) {
if (thechilde) {
tkill(thechilde, SIGKILL);
errno = 0;
}
sched_yield();
free(tls);
}
int CloneTest1(void *arg) {
_checkstackalign();
x = 42;
if (!IsWindows()) {
ASSERT_EQ(31337, errno);
@ -72,6 +70,7 @@ int CloneTest1(void *arg) {
}
int DoNothing(void *arg) {
_checkstackalign();
return 0;
}
@ -92,6 +91,7 @@ TEST(clone, test1) {
}
int CloneTestSys(void *arg) {
_checkstackalign();
thechilde = gettid();
ASSERT_EQ(31337, errno);
open(0, 0);
@ -112,3 +112,10 @@ TEST(clone, tlsSystemCallsErrno_wontClobberMainThreadBecauseTls) {
ASSERT_EQ(0, errno);
ASSERT_EQ(EFAULT, *(int *)(tls + 0x3c));
}
BENCH(clone, bench) {
errno_t *volatile ep;
char *volatile tp;
EZBENCH2("__errno_location", donothing, (ep = (__errno_location())));
EZBENCH2("__get_tls", donothing, (tp = __get_tls()));
}

View file

@ -559,6 +559,7 @@ static Token *thing_attributes(Token *tok, void *arg) {
consume_attribute(&tok, tok, "warn_unused_result") ||
consume_attribute(&tok, tok, "flatten") ||
consume_attribute(&tok, tok, "leaf") ||
consume_attribute(&tok, tok, "no_reorder") ||
consume_attribute(&tok, tok, "dontthrow") ||
consume_attribute(&tok, tok, "optnone") ||
consume_attribute(&tok, tok, "returns_twice") ||

View file

@ -1174,6 +1174,14 @@ __INT_FAST32_TYPE__\000\
int\000\
__UINT_FAST32_TYPE__\000\
unsigned\000\
__INT_FAST8_MAX__\000\
0x7f\000\
__INT_FAST16_MAX__\000\
0x7fffffff\000\
__INT_FAST32_MAX__\000\
0x7fffffff\000\
__INT_FAST64_MAX__\000\
0x7fffffffffffffffl\000\
__INT_FAST64_TYPE__\000\
long\000\
__UINT_FAST64_TYPE__\000\

View file

@ -1,3 +1,4 @@
#include "libc/assert.h"
#include "third_party/chibicc/chibicc.h"
/* TODO(jart): Why can't these be const? */
@ -144,6 +145,9 @@ static Type *get_common_type(Type *ty1, Type *ty2) {
//
// This operation is called the "usual arithmetic conversion".
static void usual_arith_conv(Node **lhs, Node **rhs) {
if (!(*lhs)->ty || !(*rhs)->ty) {
error_tok((*lhs)->tok, "internal npe error");
}
Type *ty = get_common_type((*lhs)->ty, (*rhs)->ty);
*lhs = new_cast(*lhs, ty);
*rhs = new_cast(*rhs, ty);