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

@ -41,6 +41,7 @@ LIBC_CALLS_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_BCRYPTPRIMITIVES \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
@ -132,7 +133,8 @@ endif
o/$(MODE)/libc/calls/pledge-linux.o: private \
CFLAGS += \
-Os \
-fPIC
-fPIC \
-ffreestanding
# these assembly files are safe to build on aarch64
o/$(MODE)/libc/calls/getcontext.o: libc/calls/getcontext.S

View file

@ -247,6 +247,8 @@ ssize_t tinyprint(int, const char *, ...) libcesque nullterminated();
void shm_path_np(const char *, char[hasatleast 78]) libcesque;
#endif /* _COSMO_SOURCE */
int system(const char *) libcesque;
int __wifstopped(int) libcesque pureconst;
int __wifcontinued(int) libcesque pureconst;
int __wifsignaled(int) libcesque pureconst;

View file

@ -21,12 +21,17 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/wintime.internal.h"
#include "libc/nt/accounting.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thread.h"
#define _CLOCK_REALTIME 0
#define _CLOCK_MONOTONIC 1
#define _CLOCK_REALTIME_COARSE 2
#define _CLOCK_BOOTTIME 3
#define _CLOCK_REALTIME 0
#define _CLOCK_MONOTONIC 1
#define _CLOCK_REALTIME_COARSE 2
#define _CLOCK_BOOTTIME 3
#define _CLOCK_PROCESS_CPUTIME_ID 4
#define _CLOCK_THREAD_CPUTIME_ID 5
static struct {
uint64_t base;
@ -35,7 +40,7 @@ static struct {
textwindows int sys_clock_gettime_nt(int clock, struct timespec *ts) {
uint64_t t;
struct NtFileTime ft;
struct NtFileTime ft, ftExit, ftUser, ftKernel, ftCreation;
switch (clock) {
case _CLOCK_REALTIME:
if (ts) {
@ -61,6 +66,22 @@ textwindows int sys_clock_gettime_nt(int clock, struct timespec *ts) {
*ts = timespec_frommillis(GetTickCount64());
}
return 0;
case _CLOCK_PROCESS_CPUTIME_ID:
if (ts) {
GetProcessTimes(GetCurrentProcess(), &ftCreation, &ftExit, &ftKernel,
&ftUser);
*ts = WindowsDurationToTimeSpec(ReadFileTime(ftUser) +
ReadFileTime(ftKernel));
}
return 0;
case _CLOCK_THREAD_CPUTIME_ID:
if (ts) {
GetThreadTimes(GetCurrentThread(), &ftCreation, &ftExit, &ftKernel,
&ftUser);
*ts = WindowsDurationToTimeSpec(ReadFileTime(ftUser) +
ReadFileTime(ftKernel));
}
return 0;
default:
return -EINVAL;
}

View file

@ -61,24 +61,13 @@ static int __clock_gettime_init(int clockid, struct timespec *ts) {
/**
* Returns nanosecond time.
*
* @param clock can be one of:
* - `CLOCK_REALTIME`: universally supported
* - `CLOCK_REALTIME_FAST`: ditto but faster on freebsd
* - `CLOCK_REALTIME_PRECISE`: ditto but better on freebsd
* - `CLOCK_REALTIME_COARSE`: : like `CLOCK_REALTIME_FAST` w/ Linux 2.6.32+
* - `CLOCK_MONOTONIC`: universally supported (except on XNU/NT w/o INVTSC)
* - `CLOCK_MONOTONIC_FAST`: ditto but faster on freebsd
* - `CLOCK_MONOTONIC_PRECISE`: ditto but better on freebsd
* - `CLOCK_MONOTONIC_COARSE`: : like `CLOCK_MONOTONIC_FAST` w/ Linux 2.6.32+
* - `CLOCK_MONOTONIC_RAW`: is actually monotonic but needs Linux 2.6.28+
* - `CLOCK_PROCESS_CPUTIME_ID`: linux and bsd (NetBSD permits OR'd PID)
* - `CLOCK_THREAD_CPUTIME_ID`: linux and bsd (NetBSD permits OR'd TID)
* - `CLOCK_MONOTONIC_COARSE`: linux, freebsd
* - `CLOCK_PROF`: linux and netbsd
* - `CLOCK_BOOTTIME`: linux and openbsd
* - `CLOCK_REALTIME_ALARM`: linux-only
* - `CLOCK_BOOTTIME_ALARM`: linux-only
* - `CLOCK_TAI`: linux-only
* @param clock supports the following values across OSes:
* - `CLOCK_REALTIME`
* - `CLOCK_MONOTONIC`
* - `CLOCK_REALTIME_COARSE`
* - `CLOCK_MONOTONIC_COARSE`
* - `CLOCK_THREAD_CPUTIME_ID`
* - `CLOCK_PROCESS_CPUTIME_ID`
* @param ts is where the result is stored (or null to do clock check)
* @return 0 on success, or -1 w/ errno
* @raise EFAULT if `ts` points to invalid memory

View file

@ -93,7 +93,7 @@ static int close_impl(int fd) {
*/
int close(int fd) {
int rc;
if (__isfdkind(fd, kFdZip)) { // XXX IsWindows()?
if (__isfdkind(fd, kFdZip)) { // XXX IsWindows()?
BLOCK_SIGNALS;
__fds_lock();
rc = close_impl(fd);

View file

@ -103,7 +103,7 @@ static ssize_t GetDevUrandom(char *p, size_t n) {
ssize_t __getrandom(void *p, size_t n, unsigned f) {
ssize_t rc;
if (IsWindows()) {
rc = RtlGenRandom(p, n) ? n : __winerr();
rc = ProcessPrng(p, n) ? n : __winerr();
} else if (have_getrandom) {
if (IsXnu() || IsOpenbsd()) {
rc = GetRandomBsd(p, n, GetRandomEntropy);
@ -131,7 +131,7 @@ ssize_t __getrandom(void *p, size_t n, unsigned f) {
*
* This random number seed generator obtains information from:
*
* - RtlGenRandom() on Windows
* - ProcessPrng() on Windows
* - getentropy() on XNU and OpenBSD
* - getrandom() on Linux, FreeBSD, and NetBSD
* - sysctl(KERN_ARND) on older versions of FreeBSD and NetBSD

View file

@ -75,7 +75,9 @@ textstartup void InitializeMetalFile(void) {
memcpy(copied_base, (void *)(BANE + IMAGE_BASE_PHYSICAL), size);
__ape_com_base = copied_base;
__ape_com_size = size;
KINFOF("%s @ %p,+%#zx", APE_COM_NAME, copied_base, size);
// TODO(tkchia): LIBC_CALLS doesn't depend on LIBC_VGA so references
// to its functions need to be weak
// KINFOF("%s @ %p,+%#zx", APE_COM_NAME, copied_base, size);
}
}

View file

@ -52,7 +52,7 @@ static dontinline uint64_t rdrand_failover(void) {
*
* If RDRAND isn't available (we check CPUID and we also disable it
* automatically for microarchitectures where it's slow or buggy) then
* we try getrandom(), RtlGenRandom(), or sysctl(KERN_ARND). If those
* we try getrandom(), ProcessPrng(), or sysctl(KERN_ARND). If those
* aren't available then we try /dev/urandom and if that fails, we try
* getauxval(AT_RANDOM), and if not we finally use RDTSC and getpid().
*

View file

@ -157,6 +157,8 @@ static textwindows struct Keystroke *NewKeystroke(void) {
struct Keystroke *k = KEYSTROKE_CONTAINER(e);
dll_remove(&__keystroke.free, &k->elem);
--__keystroke.freekeys;
// TODO(jart): What's wrong with GCC 12.3?
asm("" : "+r"(k));
k->buflen = 0;
return k;
}

View file

@ -19,15 +19,19 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/cpuset.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nexgen32e/rdtscp.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/nt/struct/processornumber.h"
#include "libc/nt/synchronization.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/errfuns.h"
int sys_getcpu(unsigned *opt_cpu, unsigned *opt_node, void *tcache);
/**
* Returns ID of CPU on which thread is currently scheduled.
* @return cpu number on success, or -1 w/ errno
*/
int sched_getcpu(void) {
if (X86_HAVE(RDTSCP)) {
@ -38,6 +42,19 @@ int sched_getcpu(void) {
struct NtProcessorNumber pn;
GetCurrentProcessorNumberEx(&pn);
return 64 * pn.Group + pn.Number;
} else if (IsXnuSilicon()) {
if (__syslib->__version >= 9) {
size_t cpu;
errno_t err = __syslib->__pthread_cpu_number_np(&cpu);
if (!err) {
return cpu;
} else {
errno = err;
return -1;
}
} else {
return enosys();
}
} else {
unsigned cpu = 0;
int rc = sys_getcpu(&cpu, 0, 0);

View file

@ -441,8 +441,7 @@ textwindows void __sig_generate(int sig, int sic) {
// to unblock our sig once the wait operation is completed; when
// that's the case we can cancel the thread's i/o to deliver sig
if (atomic_load_explicit(&pt->pt_blocker, memory_order_acquire) &&
!(atomic_load_explicit(&pt->pt_blkmask, memory_order_relaxed) &
(1ull << (sig - 1)))) {
!(pt->pt_blkmask & (1ull << (sig - 1)))) {
_pthread_ref(pt);
mark = pt;
break;

View file

@ -18,7 +18,7 @@ int sys_fcntl_nt_setfl(int, unsigned);
int sys_pause_nt(void);
int64_t __fix_enotdir(int64_t, char16_t *);
int64_t __fix_enotdir3(int64_t, char16_t *, char16_t *);
int64_t __winerr(void) nocallback privileged;
int64_t __winerr(void) dontcallback privileged;
int64_t ntreturn(uint32_t);
void *GetProcAddressModule(const char *, const char *);
void WinMainForked(void);

View file

@ -130,7 +130,7 @@ typedef struct ucontext ucontext_t;
int getcontext(ucontext_t *) dontthrow;
int setcontext(const ucontext_t *) dontthrow;
int swapcontext(ucontext_t *, const ucontext_t *) dontthrow returnstwice;
void makecontext(ucontext_t *, void (*)(), int, ...) dontthrow nocallback;
void makecontext(ucontext_t *, void *, int, ...) dontthrow dontcallback;
void __sig_restore(const ucontext_t *) wontreturn;
COSMOPOLITAN_C_END_

View file

@ -82,15 +82,27 @@ static textwindows void GetNtName(char *name, int kind) {
}
static inline textwindows int GetNtMajorVersion(void) {
#ifdef __x86_64__
return NtGetPeb()->OSMajorVersion;
#else
return 0;
#endif
}
static inline textwindows int GetNtMinorVersion(void) {
#ifdef __x86_64__
return NtGetPeb()->OSMinorVersion;
#else
return 0;
#endif
}
static inline textwindows int GetNtBuildNumber(void) {
#ifdef __x86_64__
return NtGetPeb()->OSBuildNumber;
#else
return 0;
#endif
}
static textwindows void GetNtVersion(char *p) {