Make improvements

- Introduce portable sched_getcpu() api
- Support GCC's __target_clones__ feature
- Make fma() go faster on x86 in default mode
- Remove some asan checks from core libraries
- WinMain() now ensures $HOME and $USER are defined
This commit is contained in:
Justine Tunney 2024-02-01 03:39:46 -08:00
parent d5225a693b
commit 2ab9e9f7fd
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
192 changed files with 2809 additions and 932 deletions

View file

@ -94,7 +94,7 @@ struct CloneArgs {
void *arg;
};
int sys_set_tls();
int sys_set_tls(uintptr_t, void *);
int __stack_call(void *, int, long, long, int (*)(void *, int), void *);
static struct CloneArgs *AllocateCloneArgs(char *stk, size_t stksz) {

View file

@ -149,7 +149,7 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1, char *exename,
}
// check system call abi compatibility
if (IsXnu() && __syslib->__version < SYSLIB_VERSION) {
if (IsXnu() && __syslib->__version < SYSLIB_VERSION_MANDATORY) {
sys_write(2, "need newer ape loader\n", 22);
_Exit(127);
}

View file

@ -30,6 +30,9 @@
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#pragma GCC diagnostic ignored "-Warray-bounds"
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#ifdef __x86_64__
/* TODO: Why can't we change CR3? Could it really need PML5T? */
@ -162,7 +165,7 @@ static void EfiInitAcpi(struct mman *mm, EFI_SYSTEM_TABLE *SystemTable) {
* @see libc/dce.h
*/
__msabi EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable) {
EFI_SYSTEM_TABLE *SystemTable) {
struct mman *mm;
uint32_t DescVersion;
uintptr_t i, j, MapSize;
@ -215,9 +218,8 @@ __msabi EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
&kEfiLoadedImageProtocol, &ImgInfo);
CmdLine = (const char16_t *)ImgInfo->LoadOptions;
if (!CmdLine || !CmdLine[0]) CmdLine = u"BOOTX64.EFI";
Args = GetDosArgv(CmdLine, ArgBlock->ArgBlock,
sizeof(ArgBlock->ArgBlock), ArgBlock->Args,
ARRAYLEN(ArgBlock->Args));
Args = GetDosArgv(CmdLine, ArgBlock->ArgBlock, sizeof(ArgBlock->ArgBlock),
ArgBlock->Args, ARRAYLEN(ArgBlock->Args));
/*
* Gets information about our current video mode. Clears the screen.

View file

@ -1,39 +0,0 @@
/*-*- 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
Copyright 2021 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/runtime/fenv.h"
/**
* Sets rounding mode.
*
* This configures the x87 FPU as well as SSE.
*
* @param mode may be FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, or FE_TOWARDZERO
* @return 0 on success, or -1 on error
*/
int fesetround(int r) {
switch (r) {
case FE_TONEAREST:
case FE_DOWNWARD:
case FE_UPWARD:
case FE_TOWARDZERO:
return __fesetround(r);
default:
return -1;
}
}

View file

@ -19,6 +19,8 @@
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/sysparam.h"
#include "libc/sysv/consts/_posix.h"
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/rlimit.h"
@ -29,6 +31,7 @@
* Returns expensive but more correct version of `ARG_MAX`.
*/
int __get_arg_max(void) {
int res;
if (IsLinux()) {
// You might think that just returning a constant 128KiB (ARG_MAX)
// would make sense, as this guy did:
@ -57,10 +60,11 @@ int __get_arg_max(void) {
// does. Right now (2019, Linux 5.3) that amounts to:
uint64_t stacksz;
stacksz = __get_rlimit(RLIMIT_STACK);
return MAX(MIN(stacksz / 4, 3 * (8 * 1024 * 1024) / 4), _ARG_MAX);
res = MAX(MIN(stacksz / 4, 3 * (8 * 1024 * 1024) / 4), _ARG_MAX);
} else if (IsBsd()) {
return __get_sysctl(CTL_KERN, KERN_ARGMAX);
res = __get_sysctl(CTL_KERN, KERN_ARGMAX);
} else {
return _ARG_MAX;
res = _ARG_MAX;
}
return MAX(res, _POSIX_ARG_MAX);
}

View file

@ -164,9 +164,9 @@ forceinline pureconst bool OverlapsImageSpace(const void *p, size_t n) {
const unsigned char *BegA, *EndA, *BegB, *EndB;
if (n) {
BegA = p;
EndA = BegA + (n - 1);
EndA = BegA + n;
BegB = __executable_start;
EndB = _end - 1;
EndB = _end;
return MAX(BegA, BegB) < MIN(EndA, EndB);
} else {
return 0;
@ -177,9 +177,9 @@ forceinline pureconst bool OverlapsShadowSpace(const void *p, size_t n) {
intptr_t BegA, EndA, BegB, EndB;
if (n) {
BegA = (intptr_t)p;
EndA = BegA + (n - 1);
EndA = BegA + n;
BegB = 0x7fff0000;
EndB = 0x10007fffffff;
EndB = 0x100080000000;
return MAX(BegA, BegB) < MIN(EndA, EndB);
} else {
return 0;

View file

@ -54,7 +54,7 @@ char *getlogin(void);
int getlogin_r(char *, size_t);
int login_tty(int);
int getpagesize(void);
int syncfs(int);
int syncfs(int) dontthrow;
int vhangup(void);
int getdtablesize(void);
int sethostname(const char *, size_t);

View file

@ -29,7 +29,7 @@
#define AMD64_SET_FSBASE 129
#define AMD64_SET_GSBASE 131
int sys_set_tls();
int sys_set_tls(uintptr_t, void *);
// we can't allow --ftrace here because cosmo_dlopen() calls this
// function to fix the tls register, and ftrace needs it unbroken
@ -47,12 +47,12 @@ dontinstrument textstartup void __set_tls(struct CosmoTib *tib) {
// netbsd has sysarch(X86_SET_FSBASE) but we can't use that because
// signal handlers will cause it to be reset due to not setting the
// _mc_tlsbase field in struct mcontext_netbsd.
sys_set_tls(tib);
sys_set_tls((uintptr_t)tib, 0);
} else if (IsOpenbsd()) {
sys_set_tls(tib);
sys_set_tls((uintptr_t)tib, 0);
} else if (IsXnu()) {
// thread_fast_set_cthread_self has a weird ABI
sys_set_tls((intptr_t)tib - 0x30);
sys_set_tls((intptr_t)tib - 0x30, 0);
} else {
uint64_t val = (uint64_t)tib;
asm volatile("wrmsr"

View file

@ -10,8 +10,14 @@ COSMOPOLITAN_C_START_
* `-errno` convention, and hence should be wrapped with `_sysret()`.
*/
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 8
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 9 /* sync with ape/ape-m1.c */
/* if this number increases, then everyone on macos arm will need to
reinstall ape loader in order to run newer ape binaries so please
don't do this if it's sufficient to just check __syslib->version. */
#define SYSLIB_VERSION_MANDATORY 8
typedef uint64_t dispatch_time_t;
typedef uint64_t dispatch_semaphore_t;
@ -69,11 +75,13 @@ struct Syslib {
long (*__sem_trywait)(int *);
long (*__getrlimit)(int, void *);
long (*__setrlimit)(int, const void *);
// v6 (2023-11-03)
/* v6 (2023-11-03) */
void *(*__dlopen)(const char *, int);
void *(*__dlsym)(void *, const char *);
int (*__dlclose)(void *);
char *(*__dlerror)(void);
/* v9 (2024-01-31) */
int (*__pthread_cpu_number_np)(size_t *);
};
extern struct Syslib *__syslib;

View file

@ -4,12 +4,17 @@
COSMOPOLITAN_C_START_
struct WinArgs {
char *argv[8192];
char *envp[512];
intptr_t auxv[2][2];
char argv0buf[256];
char argblock[32767];
char envblock[32767];
union {
struct {
char *argv[8192];
char *envp[512];
intptr_t auxv[2][2];
char argv0buf[256];
char argblock[32767];
char envblock[32767];
};
char16_t tmp16[257];
};
} forcealign(16);
COSMOPOLITAN_C_END_

View file

@ -24,6 +24,7 @@
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nt/accounting.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/enum/filemapflags.h"
@ -59,6 +60,7 @@ __msabi extern typeof(GetEnvironmentStrings) *const __imp_GetEnvironmentStringsW
__msabi extern typeof(GetEnvironmentVariable) *const __imp_GetEnvironmentVariableW;
__msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW;
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
__msabi extern typeof(GetUserName) *const __imp_GetUserNameW;
__msabi extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx;
__msabi extern typeof(SetConsoleCP) *const __imp_SetConsoleCP;
__msabi extern typeof(SetConsoleMode) *const __imp_SetConsoleMode;
@ -142,6 +144,11 @@ static abi void DeduplicateStdioHandles(void) {
}
}
static bool32 HasEnvironmentVariable(const char16_t *name) {
char16_t buf[4];
return __imp_GetEnvironmentVariableW(name, buf, ARRAYLEN(buf));
}
// main function of windows init process
// i.e. first process spawned that isn't forked
static abi wontreturn void WinInit(const char16_t *cmdline) {
@ -168,12 +175,6 @@ static abi wontreturn void WinInit(const char16_t *cmdline) {
}
}
// avoid programs like emacs nagging the user to define this
char16_t var[8];
if (!__imp_GetEnvironmentVariableW(u"TERM", var, 8)) {
__imp_SetEnvironmentVariableW(u"TERM", u"xterm-256color");
}
// allocate memory for stack and argument block
_mmi.p = _mmi.s;
_mmi.n = ARRAYLEN(_mmi.s);
@ -200,6 +201,34 @@ static abi wontreturn void WinInit(const char16_t *cmdline) {
struct WinArgs *wa =
(struct WinArgs *)(stackaddr + (stacksize - sizeof(struct WinArgs)));
// define $TERM if it's not already present
// programs like emacs will stop the world and nag if it's not set
if (!HasEnvironmentVariable(u"TERM")) {
__imp_SetEnvironmentVariableW(u"TERM", u"xterm-256color");
}
// define $USER as GetUserName() if not set
// Windows doesn't define this environment variable by default
uint32_t vsize = ARRAYLEN(wa->tmp16);
if (!HasEnvironmentVariable(u"USER") &&
__imp_GetUserNameW(&wa->tmp16, &vsize)) {
__imp_SetEnvironmentVariableW(u"USER", wa->tmp16);
}
// define $HOME as $HOMEDRIVE$HOMEPATH if not set
// Windows doesn't define this environment variable by default
uint32_t vlen;
if (!HasEnvironmentVariable(u"HOME") &&
(vlen = __imp_GetEnvironmentVariableW(u"HOMEDRIVE", wa->tmp16,
ARRAYLEN(wa->tmp16))) <
ARRAYLEN(wa->tmp16) &&
(vlen += __imp_GetEnvironmentVariableW(u"HOMEPATH", wa->tmp16 + vlen,
ARRAYLEN(wa->tmp16) - vlen)) <
ARRAYLEN(wa->tmp16) &&
vlen) {
__imp_SetEnvironmentVariableW(u"HOME", wa->tmp16);
}
// parse utf-16 command into utf-8 argv array in argument block
int count = GetDosArgv(cmdline, wa->argblock, ARRAYLEN(wa->argblock),
wa->argv, ARRAYLEN(wa->argv));