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

@ -48,7 +48,7 @@
"notpossible=",
"thatispacked=",
"dontthrow=",
"nocallback=",
"dontcallback=",
"relegated=",
"hidden=",
"textstartup=",

View file

@ -101,7 +101,6 @@ XARGS ?= xargs -P4 -rs8000
DOT ?= dot
CLANG = clang
TMPDIR = o/tmp
AR = build/bootstrap/ar.com
CP = build/bootstrap/cp.com
RM = build/bootstrap/rm.com -f
@ -134,10 +133,10 @@ endif
ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi studio freebsdarm
HOSTS ?= pi pi5 studio freebsdarm
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd
HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd meatball nightmare
endif
ZIPOBJ_FLAGS += -a$(ARCH)
@ -209,7 +208,7 @@ endif
libc/stdbool.h \
libc/disclaimer.inc \
rwc:/dev/shm \
rx:cosmocc \
rx:.cosmocc \
rx:build/bootstrap \
r:build/portcosmo.h \
/proc/stat \
@ -481,6 +480,7 @@ COSMOPOLITAN_OBJECTS = \
LIBC_STR \
LIBC_SYSV \
LIBC_INTRIN \
LIBC_NT_BCRYPTPRIMITIVES \
LIBC_NT_KERNEL32 \
LIBC_NEXGEN32E

View file

@ -39,7 +39,7 @@
/* maximum path size that cosmo can take */
#define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024)
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 8
#define SYSLIB_VERSION 9 /* sync with libc/runtime/syslib.internal.h */
struct Syslib {
int magic;
@ -96,11 +96,16 @@ struct Syslib {
long (*sem_trywait)(int *);
long (*getrlimit)(int, struct rlimit *);
long (*setrlimit)(int, const struct rlimit *);
// v6 (2023-11-03)
/* v6 (2023-11-03) */
void *(*dlopen)(const char *, int);
void *(*dlsym)(void *, const char *);
int (*dlclose)(void *);
char *(*dlerror)(void);
/* MANDATORY (cosmo runtime won't load if version < 8)
---------------------------------------------------
OPTIONAL (cosmo lib should check __syslib->version) */
/* v9 (2024-01-31) */
int (*pthread_cpu_number_np)(size_t *);
};
#define ELFCLASS32 1
@ -660,9 +665,9 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
if (prot1 & PROT_EXEC) {
#ifdef SIP_DISABLED
// if sip is disabled then we can load the executable segments
// off the binary into memory without needing to copy anything
// which provides considerably better performance for building
/* if sip is disabled then we can load the executable segments
off the binary into memory without needing to copy anything
which provides considerably better performance for building */
rc = sys_mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz);
if (rc < 0) {
if (rc == -EPERM) {
@ -674,12 +679,12 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
}
}
#else
// the issue is that if sip is enabled then, attempting to map
// it with exec permission will cause xnu to phone home a hash
// of the entire file to apple intelligence as a one time cost
// which is literally minutes for executables holding big data
// since there's no public apple api for detecting sip we read
// as the default strategy which is slow but it works for both
/* the issue is that if sip is enabled then, attempting to map
it with exec permission will cause xnu to phone home a hash
of the entire file to apple intelligence as a one time cost
which is literally minutes for executables holding big data
since there's no public apple api for detecting sip we read
as the default strategy which is slow but it works for both */
rc = sys_mmap(addr, size, (prot1 = PROT_READ | PROT_WRITE),
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
if (rc < 0) Pexit(exe, rc, "prog mmap anon");
@ -812,12 +817,10 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
}
}
/*
* merge adjacent loads that are contiguous with equal protection,
* which prevents our program header overlap check from needlessly
* failing later on; it also shaves away a microsecond of latency,
* since every program header requires invoking at least 1 syscall
*/
/* merge adjacent loads that are contiguous with equal protection,
which prevents our program header overlap check from needlessly
failing later on; it also shaves away a microsecond of latency,
since every program header requires invoking at least 1 syscall */
for (i = 0; i + 1 < e->e_phnum;) {
if (p[i].p_type == PT_LOAD && p[i + 1].p_type == PT_LOAD &&
((p[i].p_flags & (PF_R | PF_W | PF_X)) ==
@ -944,6 +947,7 @@ int main(int argc, char **argv, char **envp) {
M->lib.dlsym = dlsym;
M->lib.dlclose = dlclose;
M->lib.dlerror = dlerror;
M->lib.pthread_cpu_number_np = pthread_cpu_number_np;
/* getenv("_") is close enough to at_execfn */
execfn = 0;

View file

@ -282,12 +282,9 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.init.*)))
KEEP(*(.init))
KEEP(*(.initepilogue))
KEEP(*(.pltprologue))
*(.plt)
KEEP(*(.pltepilogue))
KEEP(*(.pltgotprologue))
*(.plt.got)
KEEP(*(.pltgotepilogue))
*(.iplt)
*(.text.startup .text.startup.*)
*(.text.exit .text.exit.*)
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
@ -323,7 +320,7 @@ SECTIONS {
/*BEGIN: Read Only Data */
.rodata . : {
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
KEEP(*(.rodata.pytab.0));
KEEP(*(.rodata.pytab.1));
KEEP(*(.rodata.pytab.2));
@ -398,13 +395,12 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.sort.data.*)))
. += . > 0 ? CODE_GRANULE : 0;
KEEP(*(.gotprologue))
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
__got_start = .;
*(.got)
KEEP(*(.gotepilogue))
__got_end = .;
KEEP(*(.gotpltprologue))
*(.got.plt)
KEEP(*(.gotpltepilogue))
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
__init_array_start = .;
@ -430,6 +426,8 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
KEEP(*(.piro.pad.data))
KEEP(*(.dataepilogue))
*(.igot.plt)
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
/*END: NT FORK COPYING */
_edata = .;
@ -528,6 +526,7 @@ SECTIONS {
#endif
*(__patchable_function_entries)
*(__mcount_loc)
*(.rela.dyn)
*(.discard)
*(.yoink)
}

View file

@ -166,13 +166,6 @@
(unsigned long)(255 & (S)[1]) << 010 | \
(unsigned long)(255 & (S)[0]) << 000)
#define DEBUG(VAR) \
{ \
char ibuf[19] = {0}; \
Utox(ibuf, VAR); \
Print(os, 2, ibuf, " " #VAR, "\n", 0l); \
}
struct ElfEhdr {
unsigned char e_ident[16];
unsigned short e_type;
@ -340,23 +333,6 @@ static char *GetEnv(char **p, const char *s) {
return 0;
}
static char *Utox(char p[19], unsigned long x) {
int i;
if (x) {
*p++ = '0';
*p++ = 'x';
i = (__builtin_clzl(x) ^ (sizeof(long) * 8 - 1)) + 1;
i = (i + 3) & -4;
do {
*p++ = "0123456789abcdef"[(x >> (i -= 4)) & 15];
} while (i);
} else {
*p++ = '0';
}
*p = 0;
return p;
}
static char *Utoa(char p[20], unsigned long x) {
char t;
unsigned long i, a, b;
@ -534,6 +510,53 @@ static long Print(int os, int fd, const char *s, ...) {
return Write(fd, b, n, os);
}
static long Printf(int os, int fd, const char *fmt, ...) {
int i;
char c;
int k = 0;
unsigned u;
char b[512];
const char *s;
unsigned long d;
__builtin_va_list va;
__builtin_va_start(va, fmt);
for (;;) {
switch ((c = *fmt++)) {
case '\0':
__builtin_va_end(va);
return Write(fd, b, k, os);
case '%':
switch ((c = *fmt++)) {
case 's':
for (s = __builtin_va_arg(va, const char *); s && *s; ++s) {
if (k < 512) b[k++] = *s;
}
break;
case 'd':
d = __builtin_va_arg(va, unsigned long);
for (i = 16; i--;) {
u = (d >> (i * 4)) & 15;
if (u < 10) {
c = '0' + u;
} else {
u -= 10;
c = 'a' + u;
}
if (k < 512) b[k++] = c;
}
break;
default:
if (k < 512) b[k++] = c;
break;
}
break;
default:
if (k < 512) b[k++] = c;
break;
}
}
}
static void Perror(int os, const char *thing, long rc, const char *reason) {
char ibuf[21];
ibuf[0] = 0;
@ -901,7 +924,7 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
long *auxv, *ap, *endp, *sp2;
char *p, *pe, *exe, *prog, **argv, **envp;
(void)Utox;
(void)Printf;
/* detect freebsd */
if (SupportsXnu() && dl == XNU) {

View file

@ -18,10 +18,12 @@ extern unsigned char _tbss_end[] __attribute__((__weak__));
extern unsigned char _tls_align[] __attribute__((__weak__));
extern unsigned char __test_start[] __attribute__((__weak__));
extern unsigned char __ro[] __attribute__((__weak__));
extern uint8_t __data_start[] __attribute__((__weak__));
extern uint8_t __data_end[] __attribute__((__weak__));
extern uint8_t __bss_start[] __attribute__((__weak__));
extern uint8_t __bss_end[] __attribute__((__weak__));
extern unsigned char __data_start[] __attribute__((__weak__));
extern unsigned char __data_end[] __attribute__((__weak__));
extern unsigned char __bss_start[] __attribute__((__weak__));
extern unsigned char __bss_end[] __attribute__((__weak__));
extern unsigned long __got_start[] __attribute__((__weak__));
extern unsigned long __got_end[] __attribute__((__weak__));
extern unsigned char ape_phdrs[] __attribute__((__weak__));
COSMOPOLITAN_C_END_

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,58 @@
--nocompress-debug-sections
--noexecstack
-Wa,--nocompress-debug-sections
-Wa,--noexecstack
-Wa,-msse2avx
-Werror=maybe-uninitialized
-Wno-literal-suffix
-Wno-unused-but-set-variable
-Wunsafe-loop-optimizations
-fbranch-target-load-optimize
-fcx-limited-range
-fdelete-dead-exceptions
-femit-struct-debug-baseonly
-ffp-int-builtin-inexact
-finline-functions-called-once
-fipa-pta
-fivopts
-flimit-function-alignment
-fmerge-constants
-fmodulo-sched
-fmodulo-sched-allow-regmoves
-fno-align-jumps
-fno-align-labels
-fno-align-loops
-fno-code-hoisting
-fno-cx-limited-range
-fno-fp-int-builtin-inexact
-fno-gnu-unique
-fno-inline-functions-called-once
-fno-instrument-functions
-fno-schedule-insns2
-fno-whole-program
-fopt-info-vec
-fopt-info-vec-missed
-freg-struct-return
-freschedule-modulo-scheduled-loops
-frounding-math
-fsched2-use-superblocks
-fschedule-insns
-fschedule-insns2
-fshrink-wrap
-fshrink-wrap-separate
-fsignaling-nans
-fstack-clash-protection
-ftracer
-ftrapv
-ftree-loop-im
-ftree-loop-vectorize
-funsafe-loop-optimizations
-fversion-loops-for-strides
-fwhole-program
-gdescribe-dies
-gstabs
-mcall-ms2sysv-xlogues
-mdispatch-scheduler
-mfpmath=sse+387
-mmitigate-rop
-mno-fentry

Binary file not shown.

View file

@ -54,7 +54,7 @@
#
ifeq ($(LANDLOCKMAKE_VERSION),)
TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp
TMPSAFE = $(join $(TMPDIR)/,$(subst /,_,$@)).tmp
else
TMPSAFE = $(TMPDIR)/
endif
@ -93,9 +93,9 @@ DEFAULT_CCFLAGS += \
-frecord-gcc-switches
DEFAULT_COPTS ?= \
-fno-math-errno \
-fno-ident \
-fno-common \
-fno-math-errno \
-fno-gnu-unique \
-fstrict-aliasing \
-fstrict-overflow \
@ -138,6 +138,7 @@ MATHEMATICAL = \
DEFAULT_CPPFLAGS += \
-D_COSMO_SOURCE \
-DMODE='"$(MODE)"' \
-Wno-unknown-pragmas \
-nostdinc \
-iquote. \
-isystem libc/isystem

View file

@ -55,7 +55,7 @@ set -- --regex-c='/_Atomic(\([^)]*\))/\1/b' "$@"
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
# ctags doesn't understand function prototypes, e.g.
# bool isheap(void *p) dontthrow nocallback;
# bool isheap(void *p) dontthrow dontcallback;
set -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)(.*/\2/b' "$@"
# ctags doesn't understand function pointers, e.g.

View file

@ -23,7 +23,8 @@
# - tool/build/runitd.c
.PRECIOUS: o/$(MODE)/%.com.ok
o/$(MODE)/%.com.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet
o/$(MODE)/%.com.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet dns
o/$(MODE)/%.com.ok: private .UNVEIL += r:/etc/resolv.conf
o/$(MODE)/%.com.ok: \
o/$(MODE)/tool/build/runit.com \
o/$(MODE)/tool/build/runitd.com \

View file

@ -39,6 +39,7 @@ o/$(MODE)/%.h: %.c
o/$(MODE)/%.o: %.cc
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
o/$(MODE)/%.o: %.cpp
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<

View file

@ -85,6 +85,7 @@ EXAMPLES_DIRECTDEPS = \
THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_OPENMP \
THIRD_PARTY_SED \
THIRD_PARTY_STB \
THIRD_PARTY_TR \
@ -153,6 +154,7 @@ o/$(MODE)/examples/picol.com.dbg: \
@$(APELINK)
o/$(MODE)/usr/share/dict/words.zip.o: private ZIPOBJ_FLAGS += -C2
o/$(MODE)/examples/wut.o: private COPTS += -fopenmp
$(EXAMPLES_OBJS): examples/BUILD.mk

View file

@ -7,6 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"

View file

@ -2569,8 +2569,7 @@ static int shlex() {
case 'y':
case 'z':
p = buf;
while (buf++, is_in_name(*buf))
;
while (buf++, is_in_name(*buf));
yylval.name = stalloc(buf - p + 1);
*(char *)mempcpy(yylval.name, p, buf - p) = 0;
value = ARITH_VAR;
@ -2994,7 +2993,7 @@ static const char *updatepwd(const char *dir) {
lim = (char *)stackblock() + 1;
if (*dir != '/') {
if (new[-1] != '/') USTPUTC('/', new);
if (new > lim &&*lim == '/') lim++;
if (new > lim && *lim == '/') lim++;
} else {
USTPUTC('/', new);
cdcomppath++;
@ -6565,6 +6564,10 @@ struct job *makejob(union node *node, int nprocs) {
return jp;
}
#if defined(__GNUC__) && __GNUC__ >= 12
#pragma GCC diagnostic ignored "-Wuse-after-free"
#endif
static struct job *growjobtab(void) {
unsigned len;
long offset;
@ -7446,8 +7449,7 @@ static int ulimitcmd(int argc, char **argv) {
what = optc;
}
}
for (l = limits; l->option != what; l++)
;
for (l = limits; l->option != what; l++);
set = *argptr ? 1 : 0;
if (set) {
char *p = *argptr;
@ -7660,8 +7662,7 @@ static void setparam(char **argv) {
char **newparam;
char **ap;
int nparam;
for (nparam = 0; argv[nparam]; nparam++)
;
for (nparam = 0; argv[nparam]; nparam++);
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
while (*argv) {
*ap++ = savestr(*argv++);
@ -7701,8 +7702,7 @@ static int shiftcmd(int argc, char **argv) {
if (shellparam.malloc) ckfree(*ap1);
}
ap2 = shellparam.p;
while ((*ap2++ = *ap1++) != NULL)
;
while ((*ap2++ = *ap1++) != NULL);
shellparam.optind = 1;
shellparam.optoff = -1;
INTON;
@ -8308,8 +8308,7 @@ static void parsefname(void) {
if (heredoclist == NULL)
heredoclist = here;
else {
for (p = heredoclist; p->next; p = p->next)
;
for (p = heredoclist; p->next; p = p->next);
p->next = here;
}
} else if (n->type == NTOFD || n->type == NFROMFD) {
@ -8432,8 +8431,7 @@ static int xxreadtoken(void) {
case '\t':
continue;
case '#':
while ((c = pgetc()) != '\n' && c != PEOF)
;
while ((c = pgetc()) != '\n' && c != PEOF);
pungetc();
continue;
case '\n':
@ -8553,7 +8551,7 @@ static int readtoken1(int firstc, char const *syntax, char *eofmark,
quotef = 0;
bqlist = NULL;
STARTSTACKSTR(out);
loop : { /* for each line, until end of word */
loop: { /* for each line, until end of word */
CHECKEND(); /* set c to PEOF if at end of here document */
for (;;) { /* until end of line or end of word */
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
@ -8701,7 +8699,7 @@ endword:
* is called, c is set to the first character of the next input line. If
* we are at the end of the here document, this routine sets the c to PEOF.
*/
checkend : {
checkend: {
if (realeofmark(eofmark)) {
int markloc;
char *p;
@ -8742,7 +8740,7 @@ checkend : {
* specifying the fd to be redirected. The variable "c" contains the
* first character of the redirection operator.
*/
parseredir : {
parseredir: {
char fd = *out;
union node *np;
np = (union node *)stalloc(sizeof(struct nfile));
@ -8798,7 +8796,7 @@ parseredir : {
* Parse a substitution. At this point, we have read the dollar sign
* and nothing else.
*/
parsesub : {
parsesub: {
int subtype;
int typeloc;
char *p;
@ -8910,7 +8908,7 @@ parsesub : {
* list of commands (passed by reference), and savelen is the number of
* characters on the top of the stack which must be preserved.
*/
parsebackq : {
parsebackq: {
struct nodelist **nlpp;
union node *n;
char *str;
@ -9002,7 +9000,7 @@ parsebackq : {
/*
* Parse an arithmetic expansion (indicate start of one and set state)
*/
parsearith : {
parsearith: {
synstack_push(&synstack, synstack->prev ?: alloca(sizeof(*synstack)),
ARISYNTAX);
synstack->dblquote = 1;

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) {

View file

@ -4,6 +4,7 @@ COSMOPOLITAN_C_START_
errno_t cosmo_once(_Atomic(uint32_t) *, void (*)(void));
int systemvpe(const char *, char *const[], char *const[]) libcesque;
char *GetProgramExecutableName(void);
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_COSMO_H_ */

View file

@ -159,7 +159,7 @@ typedef struct {
#include "libc/integral/lp64arg.inc"
#endif
#define libcesque dontthrow nocallback
#define libcesque dontthrow dontcallback
#define memcpyesque libcesque
#define strlenesque libcesque nosideeffect paramsnonnull()
#define vallocesque \
@ -364,14 +364,14 @@ typedef struct {
#endif
#endif
#ifndef nocallback
#ifndef dontcallback
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__leaf__) || \
(!defined(__llvm__) && \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406))
#define nocallback __attribute__((__leaf__))
#define dontcallback __attribute__((__leaf__))
#else
#define nocallback
#define dontcallback
#endif
#endif
@ -645,11 +645,23 @@ void abort(void) wontreturn;
#define initarray _Section(".init_array")
#endif
#pragma GCC diagnostic ignored "-Wformat" /* todo: patch gcc */
#ifndef __llvm__
#pragma GCC diagnostic ignored "-Wformat=0" /* todo: patch gcc */
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
#pragma GCC diagnostic warning "-Wunknown-pragmas"
#else
#pragma GCC diagnostic ignored "-Wformat"
#pragma GCC diagnostic ignored "-Wconstant-logical-operand" /* what */
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wstring-plus-int" /* features 4 losers */
#pragma GCC diagnostic ignored "-Wkeyword-compat" /* c++ upgrade */
#pragma GCC diagnostic ignored "-Wuser-defined-literals" /* reserved for me */
#endif
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* todo: patch gcc */
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce */
#pragma GCC diagnostic ignored "-Wunused-const-variable" /* sooo ridiculous */
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
#ifndef __cplusplus
#pragma GCC diagnostic ignored "-Wold-style-definition" /* orwellian bullsh */
#endif
@ -745,5 +757,18 @@ void abort(void) wontreturn;
#define __funline static inline
#endif
#if defined(__x86_64__) && (defined(__GNUC__) || defined(__llvm__)) && \
!defined(__chibicc__) && 0 /* TODO: enable with toolchain upgrade */
#define __target_clones(x) __attribute__((__target_clones__(x ",default")))
#else
#define __target_clones(x)
#endif
#if !defined(TINY) && !defined(__AVX__) && 0
#define __vex __target_clones("avx")
#else
#define __vex
#endif
#define MACHINE_CODE_ANALYSIS_BEGIN_
#define MACHINE_CODE_ANALYSIS_END_

View file

@ -86,6 +86,11 @@ o/$(MODE)/libc/intrin/memmove.o: private \
CFLAGS += \
-fpie
o/$(MODE)/libc/intrin/x86.o: private \
CFLAGS += \
-ffreestanding \
-fno-jump-tables
# these assembly files are safe to build on aarch64
o/$(MODE)/libc/intrin/aarch64/%.o: libc/intrin/aarch64/%.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<

View file

@ -24,7 +24,6 @@
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asmflag.h"
#include "libc/intrin/atomic.h"
#include "libc/serialize.h"
#include "libc/intrin/getenv.internal.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/nomultics.internal.h"
@ -46,6 +45,7 @@
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/serialize.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"

View file

@ -67,10 +67,9 @@ static inline const unsigned char *memchr_sse(const unsigned char *s,
* @return is pointer to first instance of c or NULL if not found
* @asyncsignalsafe
*/
void *memchr(const void *s, int c, size_t n) {
__vex void *memchr(const void *s, int c, size_t n) {
#if defined(__x86_64__) && !defined(__chibicc__)
const void *r;
if (IsAsan()) __asan_verify(s, n);
r = memchr_sse(s, c, n);
return (void *)r;
#else

View file

@ -86,7 +86,7 @@ typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
* @return dst
* @asyncsignalsafe
*/
void *memmove(void *dst, const void *src, size_t n) {
__vex void *memmove(void *dst, const void *src, size_t n) {
char *d;
size_t i;
const char *s;

View file

@ -67,7 +67,7 @@ static inline const unsigned char *memrchr_sse(const unsigned char *s,
* @return is pointer to first instance of c or NULL if not found
* @asyncsignalsafe
*/
void *memrchr(const void *s, int c, size_t n) {
__vex void *memrchr(const void *s, int c, size_t n) {
#if defined(__x86_64__) && !defined(__chibicc__)
const void *r;
r = memrchr_sse(s, c, n);

View file

@ -44,14 +44,16 @@
#include "libc/runtime/runtime.h"
#ifdef __x86_64__
#define INVERT(x) (BANE + PHYSICAL(x))
#define NOPAGE ((uint64_t)-1)
#define INVERT(x) (BANE + PHYSICAL((uintptr_t)(x)))
#define NOPAGE ((uint64_t) - 1)
#define ABS64(x) \
({ \
int64_t vAddr; \
__asm__("movabs\t%1,%0" : "=r"(vAddr) : "i"(x)); \
vAddr; \
#define APE_STACK_VADDR \
({ \
int64_t vAddr; \
__asm__(".weak\tape_stack_vaddr\n\t" \
"movabs\t$ape_stack_vaddr,%0" \
: "=r"(vAddr)); \
vAddr; \
})
struct ReclaimedPage {
@ -305,7 +307,6 @@ textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
extern char ape_phdrs_end[] __attribute__((__weak__));
extern char ape_stack_pf[] __attribute__((__weak__));
extern char ape_stack_offset[] __attribute__((__weak__));
extern char ape_stack_vaddr[] __attribute__((__weak__));
extern char ape_stack_filesz[] __attribute__((__weak__));
extern char ape_stack_memsz[] __attribute__((__weak__));
__setup_mman(mm, pml4t, top);
@ -318,7 +319,7 @@ textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
.p_type = PT_LOAD,
.p_flags = (uintptr_t)ape_stack_pf,
.p_offset = (uintptr_t)ape_stack_offset,
.p_vaddr = ABS64(ape_stack_vaddr),
.p_vaddr = APE_STACK_VADDR,
.p_filesz = (uintptr_t)ape_stack_filesz,
.p_memsz = (uintptr_t)ape_stack_memsz,
});

View file

@ -27,8 +27,6 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
static volatile size_t mapsize;
/**
* Grows file descriptor array memory if needed.
*

View file

@ -1,24 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_BITS_SEGMENTATION_H_
#define COSMOPOLITAN_LIBC_BITS_SEGMENTATION_H_
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#ifdef _COSMO_SOURCE
/**
* Reads scalar from memory, offset by segment.
*
* @return *(MEM) relative to segment
* @see pushpop()
*/
#define fs(MEM) __peek("fs", MEM)
#define gs(MEM) __peek("gs", MEM)
#define __peek(SEGMENT, ADDRESS) \
({ \
typeof(*(ADDRESS)) Pk; \
asm("mov\t%%" SEGMENT ":%1,%0" : "=r"(Pk) : "m"(*(ADDRESS))); \
Pk; \
})
#endif /* _COSMO_SOURCE */
#endif /* __GNUC__ && !__STRICT_ANSI__ */
#endif /* COSMOPOLITAN_LIBC_BITS_SEGMENTATION_H_ */

View file

@ -33,7 +33,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return pointer to nul byte
* @asyncsignalsafe
*/
char *stpcpy(char *d, const char *s) {
__vex char *stpcpy(char *d, const char *s) {
size_t i = 0;
#if defined(__x86_64__) && !defined(__chibicc__)
for (; (uintptr_t)(s + i) & 15; ++i) {

View file

@ -94,7 +94,7 @@ static inline const char *strchr_x64(const char *p, uint64_t c) {
* @asyncsignalsafe
* @vforksafe
*/
char *strchr(const char *s, int c) {
__vex char *strchr(const char *s, int c) {
#if defined(__x86_64__) && !defined(__chibicc__)
const char *r;
if (X86_HAVE(SSE)) {

View file

@ -92,7 +92,7 @@ static const char *strchrnul_x64(const char *p, uint64_t c) {
* @return pointer to first instance of c, or pointer to
* NUL terminator if c is not found
*/
char *strchrnul(const char *s, int c) {
__vex char *strchrnul(const char *s, int c) {
#if defined(__x86_64__) && !defined(__chibicc__)
const char *r;
if (X86_HAVE(SSE)) {

View file

@ -32,7 +32,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return original dest
* @asyncsignalsafe
*/
char *strcpy(char *d, const char *s) {
__vex char *strcpy(char *d, const char *s) {
size_t i = 0;
#if defined(__x86_64__) && !defined(__chibicc__)
for (; (uintptr_t)(s + i) & 15; ++i) {

View file

@ -37,7 +37,7 @@ size_t strlen(const char *s) {
while (!m) m = __builtin_ia32_pmovmskb128(*++p == z);
return (const char *)p + __builtin_ctzl(m) - s;
#else
#define ONES ((word)-1 / 255)
#define ONES ((word) - 1 / 255)
#define BANE (ONES * (255 / 2 + 1))
typedef unsigned long mayalias word;
word w;
@ -56,5 +56,4 @@ size_t strlen(const char *s) {
return (const char *)p + (__builtin_ctzl(w) >> 3) - s;
#endif
}
#endif /* __aarch64__ */

808
libc/intrin/x86.c Normal file
View file

@ -0,0 +1,808 @@
//===-- cpu_model/x86.c - Support for __cpu_model builtin --------*- C -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is based on LLVM's lib/Support/Host.cpp.
// It implements the operating system Host concept and builtin
// __cpu_model for the compiler_rt library for x86.
//
//===----------------------------------------------------------------------===//
#if defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__))
#include "libc/intrin/strace.internal.h"
#include "third_party/compiler_rt/cpu_model.h"
enum VendorSignatures {
SIG_INTEL = 0x756e6547, // Genu
SIG_AMD = 0x68747541, // Auth
};
enum ProcessorVendors {
VENDOR_INTEL = 1,
VENDOR_AMD,
VENDOR_OTHER,
VENDOR_MAX
};
enum ProcessorTypes {
INTEL_BONNELL = 1,
INTEL_CORE2,
INTEL_COREI7,
AMDFAM10H,
AMDFAM15H,
INTEL_SILVERMONT,
INTEL_KNL,
AMD_BTVER1,
AMD_BTVER2,
AMDFAM17H,
INTEL_KNM,
INTEL_GOLDMONT,
INTEL_GOLDMONT_PLUS,
INTEL_TREMONT,
AMDFAM19H,
ZHAOXIN_FAM7H,
INTEL_SIERRAFOREST,
INTEL_GRANDRIDGE,
INTEL_CLEARWATERFOREST,
CPU_TYPE_MAX
};
enum ProcessorSubtypes {
INTEL_COREI7_NEHALEM = 1,
INTEL_COREI7_WESTMERE,
INTEL_COREI7_SANDYBRIDGE,
AMDFAM10H_BARCELONA,
AMDFAM10H_SHANGHAI,
AMDFAM10H_ISTANBUL,
AMDFAM15H_BDVER1,
AMDFAM15H_BDVER2,
AMDFAM15H_BDVER3,
AMDFAM15H_BDVER4,
AMDFAM17H_ZNVER1,
INTEL_COREI7_IVYBRIDGE,
INTEL_COREI7_HASWELL,
INTEL_COREI7_BROADWELL,
INTEL_COREI7_SKYLAKE,
INTEL_COREI7_SKYLAKE_AVX512,
INTEL_COREI7_CANNONLAKE,
INTEL_COREI7_ICELAKE_CLIENT,
INTEL_COREI7_ICELAKE_SERVER,
AMDFAM17H_ZNVER2,
INTEL_COREI7_CASCADELAKE,
INTEL_COREI7_TIGERLAKE,
INTEL_COREI7_COOPERLAKE,
INTEL_COREI7_SAPPHIRERAPIDS,
INTEL_COREI7_ALDERLAKE,
AMDFAM19H_ZNVER3,
INTEL_COREI7_ROCKETLAKE,
ZHAOXIN_FAM7H_LUJIAZUI,
AMDFAM19H_ZNVER4,
INTEL_COREI7_GRANITERAPIDS,
INTEL_COREI7_GRANITERAPIDS_D,
INTEL_COREI7_ARROWLAKE,
INTEL_COREI7_ARROWLAKE_S,
INTEL_COREI7_PANTHERLAKE,
CPU_SUBTYPE_MAX
};
enum ProcessorFeatures {
FEATURE_CMOV = 0,
FEATURE_MMX,
FEATURE_POPCNT,
FEATURE_SSE,
FEATURE_SSE2,
FEATURE_SSE3,
FEATURE_SSSE3,
FEATURE_SSE4_1,
FEATURE_SSE4_2,
FEATURE_AVX,
FEATURE_AVX2,
FEATURE_SSE4_A,
FEATURE_FMA4,
FEATURE_XOP,
FEATURE_FMA,
FEATURE_AVX512F,
FEATURE_BMI,
FEATURE_BMI2,
FEATURE_AES,
FEATURE_PCLMUL,
FEATURE_AVX512VL,
FEATURE_AVX512BW,
FEATURE_AVX512DQ,
FEATURE_AVX512CD,
FEATURE_AVX512ER,
FEATURE_AVX512PF,
FEATURE_AVX512VBMI,
FEATURE_AVX512IFMA,
FEATURE_AVX5124VNNIW,
FEATURE_AVX5124FMAPS,
FEATURE_AVX512VPOPCNTDQ,
FEATURE_AVX512VBMI2,
FEATURE_GFNI,
FEATURE_VPCLMULQDQ,
FEATURE_AVX512VNNI,
FEATURE_AVX512BITALG,
FEATURE_AVX512BF16,
FEATURE_AVX512VP2INTERSECT,
FEATURE_CMPXCHG16B = 46,
FEATURE_F16C = 49,
FEATURE_LAHF_LM = 54,
FEATURE_LM,
FEATURE_WP,
FEATURE_LZCNT,
FEATURE_MOVBE,
FEATURE_AVX512FP16 = 94,
FEATURE_X86_64_BASELINE,
FEATURE_X86_64_V2,
FEATURE_X86_64_V3,
FEATURE_X86_64_V4,
CPU_FEATURE_MAX
};
// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
// support. Consequently, for i386, the presence of CPUID is checked first
// via the corresponding eflags bit.
static bool isCpuIdSupported(void) {
return true;
}
// This code is copied from lib/Support/Host.cpp.
// Changes to either file should be mirrored in the other.
/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
/// the specified arguments. If we can't run cpuid on the host, return true.
static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
unsigned *rECX, unsigned *rEDX) {
// gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
// FIXME: should we save this for Clang?
__asm__("movq\t%%rbx, %%rsi\n\t"
"cpuid\n\t"
"xchgq\t%%rbx, %%rsi\n\t"
: "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
: "a"(value));
return false;
}
/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
/// the 4 values in the specified arguments. If we can't run cpuid on the host,
/// return true.
static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
unsigned *rEDX) {
// gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
// FIXME: should we save this for Clang?
__asm__("movq\t%%rbx, %%rsi\n\t"
"cpuid\n\t"
"xchgq\t%%rbx, %%rsi\n\t"
: "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
: "a"(value), "c"(subleaf));
return false;
}
// Read control register 0 (XCR0). Used to detect features such as AVX.
static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
// Check xgetbv; this uses a .byte sequence instead of the instruction
// directly because older assemblers do not include support for xgetbv and
// there is no easy way to conditionally compile based on the assembler used.
__asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
return false;
}
static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
unsigned *Model) {
*Family = (EAX >> 8) & 0xf; // Bits 8 - 11
*Model = (EAX >> 4) & 0xf; // Bits 4 - 7
if (*Family == 6 || *Family == 0xf) {
if (*Family == 0xf)
// Examine extended family ID if family ID is F.
*Family += (EAX >> 20) & 0xff; // Bits 20 - 27
// Examine extended model ID if family ID is 6 or F.
*Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
}
}
static const char *getIntelProcessorTypeAndSubtype(unsigned Family,
unsigned Model,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) {
#define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0
// We select CPU strings to match the code in Host.cpp, but we don't use them
// in compiler-rt.
const char *CPU = 0;
switch (Family) {
case 6:
switch (Model) {
case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
// processor, Intel Core 2 Quad processor, Intel Core 2 Quad
// mobile processor, Intel Core 2 Extreme processor, Intel
// Pentium Dual-Core processor, Intel Xeon processor, model
// 0Fh. All processors are manufactured using the 65 nm
// process.
case 0x16: // Intel Celeron processor model 16h. All processors are
// manufactured using the 65 nm process
CPU = "core2";
*Type = INTEL_CORE2;
break;
case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor,
// model 17h. All processors are manufactured using the 45
// nm process.
//
// 45nm: Penryn , Wolfdale, Yorkfield (XE)
case 0x1d: // Intel Xeon processor MP. All processors are manufactured
// using the 45 nm process.
CPU = "penryn";
*Type = INTEL_CORE2;
break;
case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
// processors are manufactured using the 45 nm process.
case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
// As found in a Summer 2010 model iMac.
case 0x1f:
case 0x2e: // Nehalem EX
CPU = "nehalem";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_NEHALEM;
break;
case 0x25: // Intel Core i7, laptop version.
case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
// processors are manufactured using the 32 nm process.
case 0x2f: // Westmere EX
CPU = "westmere";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_WESTMERE;
break;
case 0x2a: // Intel Core i7 processor. All processors are manufactured
// using the 32 nm process.
case 0x2d:
CPU = "sandybridge";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_SANDYBRIDGE;
break;
case 0x3a:
case 0x3e: // Ivy Bridge EP
CPU = "ivybridge";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_IVYBRIDGE;
break;
// Haswell:
case 0x3c:
case 0x3f:
case 0x45:
case 0x46:
CPU = "haswell";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_HASWELL;
break;
// Broadwell:
case 0x3d:
case 0x47:
case 0x4f:
case 0x56:
CPU = "broadwell";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_BROADWELL;
break;
// Skylake:
case 0x4e: // Skylake mobile
case 0x5e: // Skylake desktop
case 0x8e: // Kaby Lake mobile
case 0x9e: // Kaby Lake desktop
case 0xa5: // Comet Lake-H/S
case 0xa6: // Comet Lake-U
CPU = "skylake";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_SKYLAKE;
break;
// Rocketlake:
case 0xa7:
CPU = "rocketlake";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_ROCKETLAKE;
break;
// Skylake Xeon:
case 0x55:
*Type = INTEL_COREI7;
if (testFeature(FEATURE_AVX512BF16)) {
CPU = "cooperlake";
*Subtype = INTEL_COREI7_COOPERLAKE;
} else if (testFeature(FEATURE_AVX512VNNI)) {
CPU = "cascadelake";
*Subtype = INTEL_COREI7_CASCADELAKE;
} else {
CPU = "skylake-avx512";
*Subtype = INTEL_COREI7_SKYLAKE_AVX512;
}
break;
// Cannonlake:
case 0x66:
CPU = "cannonlake";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_CANNONLAKE;
break;
// Icelake:
case 0x7d:
case 0x7e:
CPU = "icelake-client";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_ICELAKE_CLIENT;
break;
// Tigerlake:
case 0x8c:
case 0x8d:
CPU = "tigerlake";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_TIGERLAKE;
break;
// Alderlake:
case 0x97:
case 0x9a:
// Raptorlake:
case 0xb7:
case 0xba:
case 0xbf:
// Meteorlake:
case 0xaa:
case 0xac:
// Gracemont:
case 0xbe:
CPU = "alderlake";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_ALDERLAKE;
break;
// Arrowlake:
case 0xc5:
CPU = "arrowlake";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_ARROWLAKE;
break;
// Arrowlake S:
case 0xc6:
// Lunarlake:
case 0xbd:
CPU = "arrowlake-s";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_ARROWLAKE_S;
break;
// Pantherlake:
case 0xcc:
CPU = "pantherlake";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_PANTHERLAKE;
break;
// Icelake Xeon:
case 0x6a:
case 0x6c:
CPU = "icelake-server";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_ICELAKE_SERVER;
break;
// Emerald Rapids:
case 0xcf:
// Sapphire Rapids:
case 0x8f:
CPU = "sapphirerapids";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_SAPPHIRERAPIDS;
break;
// Granite Rapids:
case 0xad:
CPU = "graniterapids";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_GRANITERAPIDS;
break;
// Granite Rapids D:
case 0xae:
CPU = "graniterapids-d";
*Type = INTEL_COREI7;
*Subtype = INTEL_COREI7_GRANITERAPIDS_D;
break;
case 0x1c: // Most 45 nm Intel Atom processors
case 0x26: // 45 nm Atom Lincroft
case 0x27: // 32 nm Atom Medfield
case 0x35: // 32 nm Atom Midview
case 0x36: // 32 nm Atom Midview
CPU = "bonnell";
*Type = INTEL_BONNELL;
break;
// Atom Silvermont codes from the Intel software optimization guide.
case 0x37:
case 0x4a:
case 0x4d:
case 0x5a:
case 0x5d:
case 0x4c: // really airmont
CPU = "silvermont";
*Type = INTEL_SILVERMONT;
break;
// Goldmont:
case 0x5c: // Apollo Lake
case 0x5f: // Denverton
CPU = "goldmont";
*Type = INTEL_GOLDMONT;
break; // "goldmont"
case 0x7a:
CPU = "goldmont-plus";
*Type = INTEL_GOLDMONT_PLUS;
break;
case 0x86:
case 0x8a: // Lakefield
case 0x96: // Elkhart Lake
case 0x9c: // Jasper Lake
CPU = "tremont";
*Type = INTEL_TREMONT;
break;
// Sierraforest:
case 0xaf:
CPU = "sierraforest";
*Type = INTEL_SIERRAFOREST;
break;
// Grandridge:
case 0xb6:
CPU = "grandridge";
*Type = INTEL_GRANDRIDGE;
break;
// Clearwaterforest:
case 0xdd:
CPU = "clearwaterforest";
*Type = INTEL_COREI7;
*Subtype = INTEL_CLEARWATERFOREST;
break;
case 0x57:
CPU = "knl";
*Type = INTEL_KNL;
break;
case 0x85:
CPU = "knm";
*Type = INTEL_KNM;
break;
default: // Unknown family 6 CPU.
break;
}
break;
default:
break; // Unknown.
}
return CPU;
}
static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
unsigned Model,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) {
// We select CPU strings to match the code in Host.cpp, but we don't use them
// in compiler-rt.
const char *CPU = 0;
switch (Family) {
case 16:
CPU = "amdfam10";
*Type = AMDFAM10H;
switch (Model) {
case 2:
*Subtype = AMDFAM10H_BARCELONA;
break;
case 4:
*Subtype = AMDFAM10H_SHANGHAI;
break;
case 8:
*Subtype = AMDFAM10H_ISTANBUL;
break;
}
break;
case 20:
CPU = "btver1";
*Type = AMD_BTVER1;
break;
case 21:
CPU = "bdver1";
*Type = AMDFAM15H;
if (Model >= 0x60 && Model <= 0x7f) {
CPU = "bdver4";
*Subtype = AMDFAM15H_BDVER4;
break; // 60h-7Fh: Excavator
}
if (Model >= 0x30 && Model <= 0x3f) {
CPU = "bdver3";
*Subtype = AMDFAM15H_BDVER3;
break; // 30h-3Fh: Steamroller
}
if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
CPU = "bdver2";
*Subtype = AMDFAM15H_BDVER2;
break; // 02h, 10h-1Fh: Piledriver
}
if (Model <= 0x0f) {
*Subtype = AMDFAM15H_BDVER1;
break; // 00h-0Fh: Bulldozer
}
break;
case 22:
CPU = "btver2";
*Type = AMD_BTVER2;
break;
case 23:
CPU = "znver1";
*Type = AMDFAM17H;
if ((Model >= 0x30 && Model <= 0x3f) || (Model == 0x47) ||
(Model >= 0x60 && Model <= 0x67) ||
(Model >= 0x68 && Model <= 0x6f) ||
(Model >= 0x70 && Model <= 0x7f) ||
(Model >= 0x84 && Model <= 0x87) ||
(Model >= 0x90 && Model <= 0x97) ||
(Model >= 0x98 && Model <= 0x9f) ||
(Model >= 0xa0 && Model <= 0xaf)) {
// Family 17h Models 30h-3Fh (Starship) Zen 2
// Family 17h Models 47h (Cardinal) Zen 2
// Family 17h Models 60h-67h (Renoir) Zen 2
// Family 17h Models 68h-6Fh (Lucienne) Zen 2
// Family 17h Models 70h-7Fh (Matisse) Zen 2
// Family 17h Models 84h-87h (ProjectX) Zen 2
// Family 17h Models 90h-97h (VanGogh) Zen 2
// Family 17h Models 98h-9Fh (Mero) Zen 2
// Family 17h Models A0h-AFh (Mendocino) Zen 2
CPU = "znver2";
*Subtype = AMDFAM17H_ZNVER2;
break;
}
if ((Model >= 0x10 && Model <= 0x1f) ||
(Model >= 0x20 && Model <= 0x2f)) {
// Family 17h Models 10h-1Fh (Raven1) Zen
// Family 17h Models 10h-1Fh (Picasso) Zen+
// Family 17h Models 20h-2Fh (Raven2 x86) Zen
*Subtype = AMDFAM17H_ZNVER1;
break;
}
break;
case 25:
CPU = "znver3";
*Type = AMDFAM19H;
if ((Model <= 0x0f) || (Model >= 0x20 && Model <= 0x2f) ||
(Model >= 0x30 && Model <= 0x3f) ||
(Model >= 0x40 && Model <= 0x4f) ||
(Model >= 0x50 && Model <= 0x5f)) {
// Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 3
// Family 19h Models 20h-2Fh (Vermeer) Zen 3
// Family 19h Models 30h-3Fh (Badami) Zen 3
// Family 19h Models 40h-4Fh (Rembrandt) Zen 3+
// Family 19h Models 50h-5Fh (Cezanne) Zen 3
*Subtype = AMDFAM19H_ZNVER3;
break;
}
if ((Model >= 0x10 && Model <= 0x1f) ||
(Model >= 0x60 && Model <= 0x6f) ||
(Model >= 0x70 && Model <= 0x77) ||
(Model >= 0x78 && Model <= 0x7f) ||
(Model >= 0xa0 && Model <= 0xaf)) {
// Family 19h Models 10h-1Fh (Stones; Storm Peak) Zen 4
// Family 19h Models 60h-6Fh (Raphael) Zen 4
// Family 19h Models 70h-77h (Phoenix, Hawkpoint1) Zen 4
// Family 19h Models 78h-7Fh (Phoenix 2, Hawkpoint2) Zen 4
// Family 19h Models A0h-AFh (Stones-Dense) Zen 4
CPU = "znver4";
*Subtype = AMDFAM19H_ZNVER4;
break; // "znver4"
}
break; // family 19h
default:
break; // Unknown AMD CPU.
}
return CPU;
}
static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
unsigned *Features) {
unsigned EAX = 0, EBX = 0;
#define hasFeature(F) ((Features[F / 32] >> (F % 32)) & 1)
#define setFeature(F) Features[F / 32] |= 1U << (F % 32)
if ((EDX >> 15) & 1) setFeature(FEATURE_CMOV);
if ((EDX >> 23) & 1) setFeature(FEATURE_MMX);
if ((EDX >> 25) & 1) setFeature(FEATURE_SSE);
if ((EDX >> 26) & 1) setFeature(FEATURE_SSE2);
if ((ECX >> 0) & 1) setFeature(FEATURE_SSE3);
if ((ECX >> 1) & 1) setFeature(FEATURE_PCLMUL);
if ((ECX >> 9) & 1) setFeature(FEATURE_SSSE3);
if ((ECX >> 12) & 1) setFeature(FEATURE_FMA);
if ((ECX >> 13) & 1) setFeature(FEATURE_CMPXCHG16B);
if ((ECX >> 19) & 1) setFeature(FEATURE_SSE4_1);
if ((ECX >> 20) & 1) setFeature(FEATURE_SSE4_2);
if ((ECX >> 22) & 1) setFeature(FEATURE_MOVBE);
if ((ECX >> 23) & 1) setFeature(FEATURE_POPCNT);
if ((ECX >> 25) & 1) setFeature(FEATURE_AES);
if ((ECX >> 29) & 1) setFeature(FEATURE_F16C);
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
// indicates that the AVX registers will be saved and restored on context
// switch, then we have full AVX support.
const unsigned AVXBits = (1 << 27) | (1 << 28);
bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
((EAX & 0x6) == 0x6);
#if defined(__APPLE__)
// Darwin lazily saves the AVX512 context on first use: trust that the OS will
// save the AVX512 context if we use AVX512 instructions, even the bit is not
// set right now.
bool HasAVX512Save = true;
#else
// AVX512 requires additional context to be saved by the OS.
bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
#endif
if (HasAVX) setFeature(FEATURE_AVX);
bool HasLeaf7 =
MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
if (HasLeaf7) {
if ((EBX >> 3) & 1) setFeature(FEATURE_BMI);
if (((EBX >> 5) & 1) && HasAVX) setFeature(FEATURE_AVX2);
if ((EBX >> 8) & 1) setFeature(FEATURE_BMI2);
if (HasAVX512Save) {
if ((EBX >> 16) & 1) setFeature(FEATURE_AVX512F);
if ((EBX >> 17) & 1) setFeature(FEATURE_AVX512DQ);
if ((EBX >> 21) & 1) setFeature(FEATURE_AVX512IFMA);
if ((EBX >> 26) & 1) setFeature(FEATURE_AVX512PF);
if ((EBX >> 27) & 1) setFeature(FEATURE_AVX512ER);
if ((EBX >> 28) & 1) setFeature(FEATURE_AVX512CD);
if ((EBX >> 30) & 1) setFeature(FEATURE_AVX512BW);
if ((EBX >> 31) & 1) setFeature(FEATURE_AVX512VL);
if ((ECX >> 1) & 1) setFeature(FEATURE_AVX512VBMI);
if ((ECX >> 6) & 1) setFeature(FEATURE_AVX512VBMI2);
if ((ECX >> 11) & 1) setFeature(FEATURE_AVX512VNNI);
if ((ECX >> 12) & 1) setFeature(FEATURE_AVX512BITALG);
if ((ECX >> 14) & 1) setFeature(FEATURE_AVX512VPOPCNTDQ);
if ((EDX >> 2) & 1) setFeature(FEATURE_AVX5124VNNIW);
if ((EDX >> 3) & 1) setFeature(FEATURE_AVX5124FMAPS);
if ((EDX >> 8) & 1) setFeature(FEATURE_AVX512VP2INTERSECT);
if ((EDX >> 23) & 1) setFeature(FEATURE_AVX512FP16);
}
if ((ECX >> 8) & 1) setFeature(FEATURE_GFNI);
if (((ECX >> 10) & 1) && HasAVX) setFeature(FEATURE_VPCLMULQDQ);
}
// EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
// return all 0s for invalid subleaves so check the limit.
bool HasLeaf7Subleaf1 =
HasLeaf7 && EAX >= 1 &&
!getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512BF16);
unsigned MaxExtLevel;
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
!getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
if (HasExtLeaf1) {
if (ECX & 1) setFeature(FEATURE_LAHF_LM);
if ((ECX >> 5) & 1) setFeature(FEATURE_LZCNT);
if (((ECX >> 6) & 1)) setFeature(FEATURE_SSE4_A);
if (((ECX >> 11) & 1)) setFeature(FEATURE_XOP);
if (((ECX >> 16) & 1)) setFeature(FEATURE_FMA4);
if (((EDX >> 29) & 1)) setFeature(FEATURE_LM);
}
if (hasFeature(FEATURE_LM) && hasFeature(FEATURE_SSE2)) {
setFeature(FEATURE_X86_64_BASELINE);
if (hasFeature(FEATURE_CMPXCHG16B) && hasFeature(FEATURE_POPCNT) &&
hasFeature(FEATURE_LAHF_LM) && hasFeature(FEATURE_SSE4_2)) {
setFeature(FEATURE_X86_64_V2);
if (hasFeature(FEATURE_AVX2) && hasFeature(FEATURE_BMI) &&
hasFeature(FEATURE_BMI2) && hasFeature(FEATURE_F16C) &&
hasFeature(FEATURE_FMA) && hasFeature(FEATURE_LZCNT) &&
hasFeature(FEATURE_MOVBE)) {
setFeature(FEATURE_X86_64_V3);
if (hasFeature(FEATURE_AVX512BW) && hasFeature(FEATURE_AVX512CD) &&
hasFeature(FEATURE_AVX512DQ) && hasFeature(FEATURE_AVX512VL))
setFeature(FEATURE_X86_64_V4);
}
}
}
#undef hasFeature
#undef setFeature
}
int __cpu_indicator_init(void) CONSTRUCTOR_ATTRIBUTE;
struct __processor_model {
unsigned int __cpu_vendor;
unsigned int __cpu_type;
unsigned int __cpu_subtype;
unsigned int __cpu_features[1];
} __cpu_model = {0, 0, 0, {0}};
unsigned __cpu_features2[(CPU_FEATURE_MAX - 1) / 32];
// A constructor function that is sets __cpu_model and __cpu_features2 with
// the right values. This needs to run only once. This constructor is
// given the highest priority and it should run before constructors without
// the priority set. However, it still runs after ifunc initializers and
// needs to be called explicitly there.
int CONSTRUCTOR_ATTRIBUTE __cpu_indicator_init(void) {
unsigned EAX, EBX, ECX, EDX;
unsigned MaxLeaf = 5;
unsigned Vendor;
unsigned Model, Family;
unsigned Features[(CPU_FEATURE_MAX + 31) / 32] = {0};
_Static_assert(sizeof(Features) / sizeof(Features[0]) == 4, "");
_Static_assert(sizeof(__cpu_features2) / sizeof(__cpu_features2[0]) == 3, "");
// This function needs to run just once.
if (__cpu_model.__cpu_vendor) return 0;
if (!isCpuIdSupported() ||
getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1) {
__cpu_model.__cpu_vendor = VENDOR_OTHER;
return -1;
}
getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
detectX86FamilyModel(EAX, &Family, &Model);
// Find available features.
getAvailableFeatures(ECX, EDX, MaxLeaf, &Features[0]);
__cpu_model.__cpu_features[0] = Features[0];
__cpu_features2[0] = Features[1];
__cpu_features2[1] = Features[2];
__cpu_features2[2] = Features[3];
if (Vendor == SIG_INTEL) {
// Get CPU type.
getIntelProcessorTypeAndSubtype(Family, Model, &Features[0],
&(__cpu_model.__cpu_type),
&(__cpu_model.__cpu_subtype));
__cpu_model.__cpu_vendor = VENDOR_INTEL;
} else if (Vendor == SIG_AMD) {
// Get CPU type.
getAMDProcessorTypeAndSubtype(Family, Model, &Features[0],
&(__cpu_model.__cpu_type),
&(__cpu_model.__cpu_subtype));
__cpu_model.__cpu_vendor = VENDOR_AMD;
} else {
__cpu_model.__cpu_vendor = VENDOR_OTHER;
}
return 0;
}
#endif // __x86_64__ && (gnuc || clang)

View file

@ -36,7 +36,7 @@ static struct {
char buf[PATH_MAX];
} g_addr2line;
const void GetAddr2linePathInit(void) {
void GetAddr2linePathInit(void) {
int e = errno;
const char *path;
if (!(path = getenv("ADDR2LINE"))) {

View file

@ -48,10 +48,10 @@ void __cxa_printexits(FILE *f, void *pred) {
if (symbol) {
snprintf(name, sizeof(name), "%s", symbol);
} else {
snprintf(name, sizeof(name), "0x%016lx", b->p[i].fp);
snprintf(name, sizeof(name), "0x%016lx", (unsigned long)b->p[i].fp);
}
fprintf(f, "%-22s 0x%016lx 0x%016lx\n", name, b->p[i].arg,
b->p[i].pred);
fprintf(f, "%-22s 0x%016lx 0x%016lx\n", name,
(unsigned long)b->p[i].arg, (unsigned long)b->p[i].pred);
}
}
} while ((b = b->next));

View file

@ -20,6 +20,7 @@
#include "libc/errno.h"
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
@ -51,5 +52,6 @@ relegated wontreturn void __die(void) {
__nocolor ? "" : "\e[1;31m", program_invocation_short_name, host,
getpid(), gettid(), __nocolor ? "" : "\e[0m", FindDebugBinary(),
DescribeBacktrace(__builtin_frame_address(0)));
ShowBacktrace(2, __builtin_frame_address(0));
_Exit(77);
}

View file

@ -41,7 +41,7 @@ relegated int(gdbexec)(const char *cmd) {
elf = "-q";
}
bp = __builtin_frame_address(0);
sprintf(breakcmd, "%s *%#p", "break", bp->addr);
sprintf(breakcmd, "%s *%#lx", "break", (unsigned long)bp->addr);
if (!(pid = vfork())) {
execv(gdb, (char *const[]){
"gdb",

View file

@ -252,16 +252,9 @@ static relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
}
relegated void __oncrash(int sig, struct siginfo *si, void *arg) {
ucontext_t *ctx = arg;
int gdbpid, err;
err = errno;
if ((gdbpid = IsDebuggerPresent(true))) {
DebugBreak();
}
if (!(gdbpid > 0 && (sig == SIGTRAP || sig == SIGQUIT))) {
__restore_tty();
ShowCrashReport(err, sig, si, ctx);
}
int err = errno;
__restore_tty();
ShowCrashReport(err, sig, si, arg);
}
#endif /* __x86_64__ */

View file

@ -21,8 +21,8 @@
#define TRUE 1
#define FALSE 0
#define IS2POW(X) (!((X) & ((X)-1)))
#define ROUNDUP(X, K) (((X) + (K)-1) & -(K))
#define IS2POW(X) (!((X) & ((X) - 1)))
#define ROUNDUP(X, K) (((X) + (K) - 1) & -(K))
#define ROUNDDOWN(X, K) ((X) & -(K))
#ifndef __ASSEMBLER__
#define ABS(X) ((X) >= 0 ? (X) : -(X))
@ -40,7 +40,7 @@
#define STRINGIFY(A) __STRINGIFY(A)
#define EQUIVALENT(X, Y) (__builtin_constant_p((X) == (Y)) && ((X) == (Y)))
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
#define TYPE_SIGNED(type) (((type)-1) < 0)
#define TYPE_SIGNED(type) (((type) - 1) < 0)
#define TYPE_INTEGRAL(type) (((type)0.5) != 0.5)
#define ARRAYLEN(A) \

View file

@ -54,8 +54,8 @@ asm(".include \"libc/disclaimer.inc\"");
* (The default is pairwise merging.)
*/
static void setup(uint8_t *, uint8_t *, size_t, size_t, int (*)(), void *);
static void insertionsort(uint8_t *, size_t, size_t, int (*)(), void *);
static void setup(uint8_t *, uint8_t *, size_t, size_t, int (*)(const void *, const void *, void *), void *);
static void insertionsort(uint8_t *, size_t, size_t, int (*)(const void *, const void *, void *), void *);
#define ISIZE sizeof(int)
#define PSIZE sizeof(uint8_t *)

View file

@ -5,7 +5,7 @@
#include "libc/nexgen32e/x86feature.h"
COSMOPOLITAN_C_START_
#define TSC_AUX_CORE(MSR) ((MSR)&0xfff)
#define TSC_AUX_CORE(MSR) ((MSR) & 0xfff)
#define TSC_AUX_NODE(MSR) (((MSR) >> 12) & 0xfff)
/**
@ -41,9 +41,10 @@ COSMOPOLITAN_C_START_
asm volatile("rdpid\t%0" : "=r"(Msr) : /* no inputs */ : "memory"); \
Ok = true; \
} else if (IsLinux()) { \
char *p = (char *)0x7b; \
asm volatile(ZFLAG_ASM("lsl\t%2,%1") \
: ZFLAG_CONSTRAINT(Ok), "=r"(Msr) \
: "r"(0x7b) \
: "r"(p) \
: "memory"); \
} \
if (!Ok && X86_HAVE(RDTSCP)) { \

View file

@ -1,18 +1,18 @@
#include "libc/nt/codegen.h"
.imp advapi32,__imp_SystemFunction036,SystemFunction036
.imp BCryptPrimitives,__imp_ProcessPrng,ProcessPrng
.text.windows
.ftrace1
RtlGenRandom:
ProcessPrng:
.ftrace2
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov __imp_SystemFunction036(%rip),%rax
mov __imp_ProcessPrng(%rip),%rax
jmp __sysv2nt
#elif defined(__aarch64__)
mov x0,#0
ret
#endif
.endfn RtlGenRandom,globl
.endfn ProcessPrng,globl
.previous

View file

@ -297,6 +297,24 @@ $(LIBC_NT_PSAPI_A).pkg: \
#───────────────────────────────────────────────────────────────────────────────
LIBC_NT_ARTIFACTS += LIBC_NT_BCRYPTPRIMITIVES_A
LIBC_NT_BCRYPTPRIMITIVES = $(LIBC_NT_BCRYPTPRIMITIVES_A_DEPS) $(LIBC_NT_BCRYPTPRIMITIVES_A)
LIBC_NT_BCRYPTPRIMITIVES_A = o/$(MODE)/libc/nt/BCryptPrimitives.a
LIBC_NT_BCRYPTPRIMITIVES_A_SRCS := $(wildcard libc/nt/BCryptPrimitives/*.S)
LIBC_NT_BCRYPTPRIMITIVES_A_OBJS = $(LIBC_NT_BCRYPTPRIMITIVES_A_SRCS:%.S=o/$(MODE)/%.o)
LIBC_NT_BCRYPTPRIMITIVES_A_CHECKS = $(LIBC_NT_BCRYPTPRIMITIVES_A).pkg
LIBC_NT_BCRYPTPRIMITIVES_A_DIRECTDEPS = LIBC_NT_KERNEL32
LIBC_NT_BCRYPTPRIMITIVES_A_DEPS := $(call uniq,$(foreach x,$(LIBC_NT_BCRYPTPRIMITIVES_A_DIRECTDEPS),$($(x))))
$(LIBC_NT_BCRYPTPRIMITIVES_A): \
libc/nt/BCryptPrimitives/ \
$(LIBC_NT_BCRYPTPRIMITIVES_A).pkg \
$(LIBC_NT_BCRYPTPRIMITIVES_A_OBJS)
$(LIBC_NT_BCRYPTPRIMITIVES_A).pkg: \
$(LIBC_NT_BCRYPTPRIMITIVES_A_OBJS) \
$(foreach x,$(LIBC_NT_BCRYPTPRIMITIVES_A_DIRECTDEPS),$($(x)_A).pkg)
#───────────────────────────────────────────────────────────────────────────────
# let aarch64 compile these
o/$(MODE)/libc/nt/%.o: libc/nt/%.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<

View file

@ -362,7 +362,6 @@ imp 'RegisterEventSource' RegisterEventSourceW advapi32 2
imp 'ReportEvent' ReportEventW advapi32 9
imp 'ReportEventA' ReportEventA advapi32 9
imp 'RevertToSelf' RevertToSelf advapi32 0
imp 'RtlGenRandom' SystemFunction036 advapi32 2
imp 'TraceSetInformation' TraceSetInformation advapi32 # Windows 7+
# USER32.DLL
@ -611,6 +610,11 @@ imp 'GetModuleBaseName' GetModuleBaseNameW psapi 4
imp 'GetProcessImageFileName' GetProcessImageFileNameW psapi 3
imp 'GetProcessMemoryInfo' GetProcessMemoryInfo psapi 3
# BCryptPrimitives.dll
#
# Name Actual DLL Arity
imp 'ProcessPrng' ProcessPrng BCryptPrimitives 2
# API-MS-Win-Core-Synch-l1-2-0.dll (Windows 8+)
#
# Name Actual DLL Arity

View file

@ -36,11 +36,11 @@ bool32 TerminateProcess(int64_t hProcess, uint32_t uExitCode);
void TerminateThisProcess(uint32_t dwWaitStatus) wontreturn;
void ExitProcess(uint32_t uExitCode) wontreturn;
uint32_t GetLastError(void) nosideeffect;
bool32 CloseHandle(int64_t hObject) dontthrow nocallback;
bool32 CloseHandle(int64_t hObject) dontthrow dontcallback;
intptr_t GetStdHandle(uint32_t nStdHandle) nosideeffect;
bool32 SetStdHandle(uint32_t nStdHandle, int64_t hHandle);
bool32 SetDefaultDllDirectories(unsigned dirflags);
bool32 RtlGenRandom(void *RandomBuffer, uint32_t RandomBufferLength);
bool32 ProcessPrng(void *RandomBuffer, uint32_t RandomBufferLength);
uint32_t GetModuleFileName(int64_t hModule, char16_t *lpFilename,
uint32_t nSize);

View file

@ -1,6 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_NT_TEB_H_
#define COSMOPOLITAN_LIBC_NT_TEB_H_
#include "libc/intrin/segmentation.h"
#include "libc/nt/struct/peb.h"
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
@ -8,19 +7,19 @@
* These macros address directly into NT's TEB a.k.a. TIB
* Any function that does this needs the `dontasan` keyword
*/
#define NtGetPeb() gs((struct NtPeb **)(0x60ULL))
#define NtGetTeb() gs((void **)(0x30)) /* %gs:0 linear address */
#define NtGetPid() gs((uint32_t *)(0x40)) /* GetCurrentProcessId() */
#define NtGetTid() gs((uint32_t *)(0x48)) /* GetCurrentThreadId() */
#define NtGetErr() gs((int *)(0x68))
#define _NtGetSeh() gs((void **)(0x00))
#define _NtGetStackHigh() gs((void **)(0x08))
#define _NtGetStackLow() gs((void **)(0x10))
#define _NtGetSubsystemTib() gs((void **)(0x18))
#define _NtGetFib() gs((void **)(0x20))
#define _NtGetEnv() gs((char16_t **)(0x38))
#define _NtGetRpc() gs((void **)(0x50))
#define _NtGetTls() gs((void **)(0x58)) /* cf. gs((long *)0x1480 + i0..64) */
#define NtGetPeb() ((__seg_gs struct NtPeb *)0x60)
#define NtGetTeb() ((void *)*(__seg_gs uintptr_t *)0x30)
#define NtGetPid() (*(__seg_gs uint32_t *)0x40)
#define NtGetTid() (*(__seg_gs uint32_t *)0x48)
#define NtGetErr() (*(__seg_gs int *)0x68)
#define _NtGetSeh() ((void *)*(__seg_gs uintptr_t *)0x00)
#define _NtGetStackHigh() ((void *)*(__seg_gs uintptr_t *)0x08)
#define _NtGetStackLow() ((void *)*(__seg_gs uintptr_t *)0x10)
#define _NtGetSubsystemTib() ((void *)*(__seg_gs uintptr_t *)0x18)
#define _NtGetFib() ((void *)*(__seg_gs uintptr_t *)0x20)
#define _NtGetEnv() ((char16_t *)*(__seg_gs intptr_t *)0x38)
#define _NtGetRpc() ((void *)*(__seg_gs uintptr_t *)0x50)
#define _NtGetTls() ((void *)*(__seg_gs uintptr_t *)0x58)
#endif /* __GNUC__ && !__STRICT_ANSI__ */
#endif /* COSMOPOLITAN_LIBC_NT_TEB_H_ */

View file

@ -78,7 +78,9 @@ static textwindows char16_t *ParseInt(char16_t *p, int64_t *x) {
}
static inline textwindows ssize_t ForkIo(int64_t h, char *p, size_t n,
bool32 (*f)()) {
bool32 (*f)(int64_t, void *, uint32_t,
uint32_t *,
struct NtOverlapped *)) {
size_t i;
uint32_t x;
for (i = 0; i < n; i += x) {
@ -90,8 +92,10 @@ static inline textwindows ssize_t ForkIo(int64_t h, char *p, size_t n,
}
static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n,
bool32 (*fn)(), const char *sf,
bool ischild) {
bool32 (*fn)(int64_t, void *,
uint32_t, uint32_t *,
struct NtOverlapped *),
const char *sf, bool ischild) {
ssize_t rc = ForkIo(h, buf, n, fn);
if (ischild) __tls_enabled_set(false); // prevent tls crash in kprintf
NTTRACE("%s(%ld, %p, %'zu) → %'zd% m", sf, h, buf, n, rc);
@ -100,9 +104,9 @@ static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n,
static dontinline textwindows bool WriteAll(int64_t h, void *buf, size_t n) {
bool ok;
ok = ForkIo2(h, buf, n, WriteFile, "WriteFile", false);
ok = ForkIo2(h, buf, n, (void *)WriteFile, "WriteFile", false);
#ifndef NDEBUG
if (ok) ok = ForkIo2(h, &n, sizeof(n), WriteFile, "WriteFile", false);
if (ok) ok = ForkIo2(h, &n, sizeof(n), (void *)WriteFile, "WriteFile", false);
#endif
#if SYSDEBUG
if (!ok) {

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

@ -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));

View file

@ -2,15 +2,22 @@
#define COSMOPOLITAN_LIBC_STDBOOL_H_
#ifndef __cplusplus
#if __STDC_VERSION__ + 0 >= 201112
#define bool _Bool
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
#define true ((_Bool) + 1u)
#define false ((_Bool) + 0u)
#else
#define bool unsigned char
#endif
#define true 1
#define true 1
#define false 0
#endif
#else /* __cplusplus */
#define _Bool bool
#endif /* __cplusplus */
#define __bool_true_false_are_defined
#define __bool_true_false_are_defined 1
#endif /* COSMOPOLITAN_LIBC_STDBOOL_H_ */

View file

@ -43,7 +43,6 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/divmod10.internal.h"
#include "libc/fmt/itoa.h"
#include "libc/serialize.h"
#include "libc/intrin/bsr.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/safemacros.internal.h"
@ -53,6 +52,7 @@
#include "libc/mem/mem.h"
#include "libc/mem/reverse.internal.h"
#include "libc/runtime/internal.h"
#include "libc/serialize.h"
#include "libc/str/str.h"
#include "libc/str/strwidth.h"
#include "libc/str/tab.internal.h"
@ -800,7 +800,7 @@ int __fmt(void *fn, void *arg, const char *format, va_list va) {
x = 0;
lasterr = errno;
out = fn ? fn : __fmt_noop;
out = fn ? fn : (void *)__fmt_noop;
while (*format) {
if (*format != '%') {

View file

@ -50,5 +50,5 @@ int ftw(const char *dirpath,
/* The following cast assumes that calling a function with one
* argument more than it needs behaves as expected. This is
* actually undefined, but works on all real-world machines. */
return nftw(dirpath, (int (*)())fn, fd_limit, FTW_PHYS);
return nftw(dirpath, (void *)fn, fd_limit, FTW_PHYS);
}

View file

@ -84,6 +84,7 @@ static const char *FindNameById(const struct IdName *names, unsigned long id) {
}
static void PrintDependencies(const char *prologue) {
#ifdef __x86_64__
struct NtLinkedList *head = &NtGetPeb()->Ldr->InLoadOrderModuleList;
struct NtLinkedList *ldr = head->Next;
do {
@ -92,6 +93,7 @@ static void PrintDependencies(const char *prologue) {
PRINT(" ☼ %.*!hs (%'zukb @ %p)", dll->FullDllName.Length,
dll->FullDllName.Data, dll->SizeOfImage / 1024, dll->DllBase);
} while ((ldr = ldr->Next) && ldr != head);
#endif
}
static void Print(const char *prologue) {
@ -624,6 +626,7 @@ textstartup void __printargs(const char *prologue) {
if (GetConsoleMode(GetStdHandle(kNtStdErrorHandle), &cm))
PRINT(" %s", DescribeNtConsoleOutFlags(cm));
#ifdef __x86_64__
PRINT("");
PRINT("TEB");
PRINT(" ☼ gs:0x%02x %s = %p", 0x00, "NtGetSeh()", _NtGetSeh());
@ -640,6 +643,7 @@ textstartup void __printargs(const char *prologue) {
PRINT(" ☼ gs:0x%02x %s = %p", 0x58, "NtGetTls()", _NtGetTls());
PRINT(" ☼ gs:0x%02x %s = %p", 0x60, "NtGetPeb()", NtGetPeb());
PRINT(" ☼ gs:0x%02x %s = %p", 0x68, "NtGetErr()", NtGetErr());
#endif
PRINT("");
PRINT("DEPENDENCIES");

View file

@ -27,7 +27,7 @@
*
* If RDSEED isn't available, we'll try RDRAND (which we automatically
* disable for microarchitectures where it's known to be slow or buggy).
* If RDRAND isn't available then we try getrandom(), RtlGenRandom(), or
* If RDRAND isn't available then we try getrandom(), ProcessPrng(), or
* sysctl(KERN_ARND). If those aren't available then we try /dev/urandom
* and if that fails, we use RDTSC and getpid().
*

View file

@ -45,9 +45,6 @@ dontasan void *rngset(void *b, size_t n, uint64_t seed(void), size_t reseed) {
size_t m;
uint64_t x, t = 0;
unsigned char *p = b;
if (IsAsan()) {
__asan_verify(b, n);
}
if (!seed) {
t = reseed;
reseed = -1;

View file

@ -90,7 +90,7 @@ int fsetpos(FILE *, const fpos_t *) libcesque paramsnonnull();
FILE *tmpfile(void) libcesque __wur;
char *tmpnam(char *) libcesque __wur;
char *tmpnam_r(char *) libcesque __wur;
int system(const char *) libcesque;
FILE *popen(const char *, const char *) libcesque;
/*───────────────────────────────────────────────────────────────────────────│─╗

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@ -35,7 +34,6 @@ static char g_tmpnam[L_tmpnam];
* is only mutated on success
*/
char *tmpnam(char *buf) {
if (IsAsan()) __asan_verify(buf, L_tmpnam);
char path[] = P_tmpdir "/tmpnam_XXXXXX";
for (int t = 0; t < 100; ++t) {
int w = _rand64();

View file

@ -88,7 +88,7 @@ o/$(MODE)/libc/str/windowstimetotimespec.o: private \
-O2
$(LIBC_STR_A_OBJS): private \
COPTS += \
CFLAGS += \
-fno-sanitize=all \
-Wframe-larger-than=4096 \
-Walloca-larger-than=4096

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/runtime/runtime.h"
#include "libc/stdckdint.h"
@ -28,11 +27,6 @@ void djbsort_avx2(int32_t *, long);
* D.J. Bernstein's outrageously fast integer sorting algorithm.
*/
void djbsort(int32_t *a, size_t n) {
size_t m;
if (IsAsan()) {
if (ckd_mul(&m, n, 4)) m = -1;
__asan_verify(a, m);
}
if (n > 1) {
#if defined(__x86_64__) && !defined(__chibicc__)
if (X86_HAVE(AVX2)) {

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/likely.h"
#include "libc/str/str.h"
@ -53,7 +52,6 @@ bool32 isutf8(const void *data, size_t size) {
long c;
const char *p, *e;
if (size == -1) size = data ? strlen(data) : 0;
if (IsAsan()) __asan_verify(data, size);
p = data;
e = p + size;
while (p < e) {

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/likely.h"
#include "libc/str/str.h"
@ -32,16 +31,14 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @param needlelen is its character count
* @return pointer to first result or NULL if not found
*/
void *memmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen) {
__vex void *memmem(const void *haystack, size_t haystacklen, const void *needle,
size_t needlelen) {
#if defined(__x86_64__) && !defined(__chibicc__)
char c;
xmm_t n;
const xmm_t *v;
unsigned i, k, m;
const char *p, *q, *e;
if (IsAsan()) __asan_verify(needle, needlelen);
if (IsAsan()) __asan_verify(haystack, haystacklen);
if (!needlelen) return (void *)haystack;
if (UNLIKELY(needlelen > haystacklen)) return 0;
q = needle;

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/limits.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/str.h"
@ -36,8 +35,8 @@ static inline const char16_t *memrchr16_pure(const char16_t *s, char16_t c,
}
#if defined(__x86_64__) && !defined(__chibicc__)
static inline const char16_t *memrchr16_sse(const char16_t *s,
char16_t c, size_t n) {
static inline const char16_t *memrchr16_sse(const char16_t *s, char16_t c,
size_t n) {
size_t i;
unsigned m;
xmm_t v, t = {c, c, c, c, c, c, c, c};
@ -67,11 +66,10 @@ static inline const char16_t *memrchr16_sse(const char16_t *s,
* @return is pointer to first instance of c or NULL if not found
* @asyncsignalsafe
*/
void *memrchr16(const void *s, int c, size_t n) {
__vex void *memrchr16(const void *s, int c, size_t n) {
#if defined(__x86_64__) && !defined(__chibicc__)
const void *r;
if (!IsTiny() && X86_HAVE(SSE)) {
if (IsAsan()) __asan_verify(s, n * 2);
r = memrchr16_sse(s, c, n);
} else {
r = memrchr16_pure(s, c, n);

View file

@ -18,7 +18,6 @@
*/
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/str.h"
@ -33,8 +32,7 @@ static inline const unsigned char *rawmemchr_pure(const unsigned char *s,
#if defined(__x86_64__) && !defined(__chibicc__)
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
static inline const char *rawmemchr_sse(const char *s,
unsigned char c) {
static inline const char *rawmemchr_sse(const char *s, unsigned char c) {
unsigned k;
unsigned m;
const xmm_t *p;
@ -67,11 +65,10 @@ static inline uint64_t UncheckedAlignedRead64(const unsigned char *p) {
* @param c is search byte which is masked with 255
* @return is pointer to first instance of c
*/
void *rawmemchr(const void *s, int c) {
__vex void *rawmemchr(const void *s, int c) {
#if defined(__x86_64__) && !defined(__chibicc__)
const void *r;
if (X86_HAVE(SSE)) {
if (IsAsan()) __asan_verify(s, 1);
r = rawmemchr_sse(s, c);
} else {
r = rawmemchr_pure(s, c);

View file

@ -167,7 +167,7 @@ wint_t towctrans(wint_t, wctrans_t) libcesque;
int getsubopt(char **, char *const *, char **) libcesque paramsnonnull();
char *strsignal(int) returnsnonnull libcesque;
char *strerror(int) returnsnonnull dontthrow nocallback;
char *strerror(int) returnsnonnull dontthrow dontcallback;
errno_t strerror_r(int, char *, size_t) libcesque;
char *__xpg_strerror_r(int, char *, size_t) libcesque;

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
@ -34,8 +33,6 @@ int strcasecmp(const char *a, const char *b) {
size_t i = 0;
uint64_t v, w;
if (a == b) return 0;
if (IsAsan()) __asan_verify_str(a);
if (IsAsan()) __asan_verify_str(b);
if (((uintptr_t)a & 7) == ((uintptr_t)b & 7)) {
for (; (uintptr_t)(a + i) & 7; ++i) {
CheckEm:

View file

@ -18,7 +18,6 @@
*/
#include "libc/str/str.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/str/tab.internal.h"
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
@ -35,15 +34,13 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @asyncsignalsafe
* @see strstr()
*/
char *strcasestr(const char *haystack, const char *needle) {
__vex char *strcasestr(const char *haystack, const char *needle) {
#if defined(__x86_64__) && !defined(__chibicc__)
char c;
size_t i;
unsigned k, m;
const xmm_t *p;
xmm_t v, n1, n2, z = {0};
if (IsAsan()) __asan_verify(needle, 1);
if (IsAsan()) __asan_verify(haystack, 1);
if (haystack == needle || !*needle) return (char *)haystack;
c = *needle;
n1 = (xmm_t){c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/str/str.h"
typedef char16_t xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
@ -29,17 +28,15 @@ typedef char16_t xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return number of shorts (excluding NUL)
* @asyncsignalsafe
*/
size_t strlen16(const char16_t *s) {
__vex size_t strlen16(const char16_t *s) {
#if defined(__x86_64__) && !defined(__chibicc__)
size_t n;
xmm_t z = {0};
unsigned m, k = (uintptr_t)s & 15;
const xmm_t *p = (const xmm_t *)((uintptr_t)s & -16);
if (IsAsan()) __asan_verify(s, 2);
m = __builtin_ia32_pmovmskb128(*p == z) >> k << k;
while (!m) m = __builtin_ia32_pmovmskb128(*++p == z);
n = (const char16_t *)p + (__builtin_ctzl(m) >> 1) - s;
if (IsAsan()) __asan_verify(s, n * 2);
return n;
#else
size_t n = 0;

View file

@ -18,7 +18,6 @@
*/
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/str/str.h"
static size_t strnlen_s_x64(const char *s, size_t n, size_t i) {
@ -48,7 +47,6 @@ static size_t strnlen_s_x64(const char *s, size_t n, size_t i) {
size_t strnlen_s(const char *s, size_t n) {
size_t i;
if (!s) return 0;
if (IsAsan()) __asan_verify(s, n);
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
if (i == n || !s[i]) return i;
}

View file

@ -18,7 +18,6 @@
*/
#include "libc/str/str.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
@ -35,14 +34,12 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @see strcasestr()
* @see memmem()
*/
char *strstr(const char *haystack, const char *needle) {
__vex char *strstr(const char *haystack, const char *needle) {
#if defined(__x86_64__) && !defined(__chibicc__)
size_t i;
unsigned k, m;
const xmm_t *p;
xmm_t v, n, z = {0};
if (IsAsan()) __asan_verify(needle, 1);
if (IsAsan()) __asan_verify(haystack, 1);
if (haystack == needle || !*needle) return (char *)haystack;
n = (xmm_t){*needle, *needle, *needle, *needle, *needle, *needle,
*needle, *needle, *needle, *needle, *needle, *needle,

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/str/str.h"
typedef wchar_t xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
@ -29,17 +28,15 @@ typedef wchar_t xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return number of wide characters (excluding NUL)
* @asyncsignalsafe
*/
size_t wcslen(const wchar_t *s) {
__vex size_t wcslen(const wchar_t *s) {
#if defined(__x86_64__) && !defined(__chibicc__)
size_t n;
xmm_t z = {0};
unsigned m, k = (uintptr_t)s & 15;
const xmm_t *p = (const xmm_t *)((uintptr_t)s & -16);
if (IsAsan()) __asan_verify(s, 4);
m = __builtin_ia32_pmovmskb128(*p == z) >> k << k;
while (!m) m = __builtin_ia32_pmovmskb128(*++p == z);
n = (const wchar_t *)p + (__builtin_ctzl(m) >> 2) - s;
if (IsAsan()) __asan_verify(s, n);
return n;
#else
size_t n = 0;

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/limits.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/stdckdint.h"
@ -38,7 +37,7 @@ static inline const wchar_t *wmemrchr_pure(const wchar_t *s, wchar_t c,
#if defined(__x86_64__) && !defined(__chibicc__)
static inline const wchar_t *wmemrchr_sse(const wchar_t *s, wchar_t c,
size_t n) {
size_t n) {
size_t i;
unsigned m;
xmm_t v, t = {c, c, c, c};
@ -68,16 +67,9 @@ static inline const wchar_t *wmemrchr_sse(const wchar_t *s, wchar_t c,
* @return is pointer to first instance of c or NULL if not found
* @asyncsignalsafe
*/
void *wmemrchr(const wchar_t *s, wchar_t c, size_t n) {
__vex void *wmemrchr(const wchar_t *s, wchar_t c, size_t n) {
#if defined(__x86_64__) && !defined(__chibicc__)
size_t bytes;
const void *r;
if (IsAsan()) {
if (ckd_mul(&bytes, n, sizeof(wchar_t))) bytes = -1;
__asan_verify(s, bytes);
}
r = wmemrchr_sse(s, c, n);
return (void *)r;
return (void *)wmemrchr_sse(s, c, n);
#else
return (void *)wmemrchr_pure(s, c, n);
#endif

View file

@ -234,7 +234,9 @@ syscon mmap MAP_INHERIT -1 -1 -1 -1 -1 -1 0x00000080 -1 # make
syscon mmap MAP_HASSEMAPHORE 0 0 0x00000200 0x00000200 0x00000200 0 0x00000200 0 # does it matter on x86?
syscon mmap MAP_NOSYNC 0 0 0 0 0x00000800 0 0 0 # flush to physical media only when necessary rather than gratuitously; be sure to use write() rather than ftruncate() with this!
syscon mmap MAP_CONCEAL 0 0 0 0 0x00020000 0x00008000 0x00008000 0 # omit from core dumps; MAP_NOCORE on FreeBSD
syscon mmap MAP_JIT 0 0 0 0x00000800 0 0 0 0 # omit from core dumps; MAP_NOCORE on FreeBSD
syscon mmap MAP_JIT 0 0 0 0x00000800 0 0 0 0 # allocate region used for just-in-time compilation
syscon mmap MAP_NOCACHE 0 0 0x00000400 0x00000400 0 0 0 0 # don't cache pages for this mapping
syscon mmap MAP_NOEXTEND 0 0 0x00000100 0x00000100 0 0 0 0 # for MAP_FILE, don't change file size
syscon compat MAP_NOCORE 0 0 0 0 0x00020000 0x00008000 0x00008000 0 # use MAP_CONCEAL
syscon compat MAP_ANON 0x00000020 0x00000020 0x00001000 0x00001000 0x00001000 0x00001000 0x00001000 0x00000020 # bsd consensus; faked nt
syscon compat MAP_EXECUTABLE 0x00001000 0x00001000 0 0 0 0 0 0 # ignored
@ -269,17 +271,18 @@ syscon madv MADV_WIPEONFORK 18 18 127 127 127 127 127 127 # T
syscon madv MADV_KEEPONFORK 19 19 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_COLD 20 20 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_PAGEOUT 21 21 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_POPULATE_READ 22 22 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_POPULATE_WRITE 23 23 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_DONTNEED_LOCKED 24 24 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_POPULATE_READ 22 22 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_POPULATE_WRITE 23 23 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_DONTNEED_LOCKED 24 24 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_COLLAPSE 25 25 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_DOFORK 11 11 127 127 127 127 127 127 # TODO(jart): what is it?
syscon madv MADV_DONTDUMP 16 16 127 127 127 127 127 127 # see MAP_CONCEAL in OpenBSD; TODO(jart): what is it?
syscon madv MADV_DONTFORK 10 10 127 127 127 127 127 127 # TODO(jart): what is it?
syscon madv MADV_HWPOISON 100 100 127 127 127 127 127 127 # TODO(jart): what is it?
syscon madv MADV_SOFT_OFFLINE 101 101 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_SOFT_OFFLINE 101 101 127 127 127 127 127 127 # TODO: add support ?
syscon madv MADV_REMOVE 9 9 127 127 127 127 127 127 # TODO(jart): what is it?
syscon fadv POSIX_FADV_NOREUSE 5 5 127 127 5 127 5 127 # wut
syscon madv MADV_REMOVE 9 9 127 127 127 127 127 127 # TODO(jart): what is it?
# mmap(), mprotect(), etc.
# digital restrictions management for the people
@ -579,19 +582,19 @@ syscon clock CLOCK_REALTIME 0 0 0 0 0 0 0 0 # consensus
syscon clock CLOCK_REALTIME_PRECISE 0 0 0 0 9 0 0 0 #
syscon clock CLOCK_REALTIME_FAST 0 0 0 0 10 0 0 0 #
syscon clock CLOCK_REALTIME_COARSE 5 5 0 0 10 0 0 2 # Linux 2.6.32+; bsd consensus; not available on RHEL5
syscon clock CLOCK_MONOTONIC 1 1 1 6 4 3 3 1 # XNU/NT faked; could move backwards if NTP introduces negative leap second
syscon clock CLOCK_MONOTONIC_PRECISE 1 1 1 6 11 3 3 1 #
syscon clock CLOCK_MONOTONIC_FAST 1 1 1 6 12 3 3 1 #
syscon clock CLOCK_MONOTONIC_COARSE 6 6 1 6 12 3 3 1 # Linux 2.6.32+; bsd consensus; not available on RHEL5
syscon clock CLOCK_MONOTONIC_RAW 4 4 127 4 127 127 127 127 # actually monotonic; not subject to NTP adjustments; Linux 2.6.28+; XNU/NT/FreeBSD/OpenBSD faked; not available on RHEL5
syscon clock CLOCK_PROCESS_CPUTIME_ID 2 2 127 12 15 2 0x40000000 127 # NetBSD lets you bitwise a PID into clockid_t
syscon clock CLOCK_THREAD_CPUTIME_ID 3 3 127 16 14 4 0x20000000 127 #
syscon clock CLOCK_MONOTONIC 1 1 6 6 4 3 3 1 # XNU/NT faked; could move backwards if NTP introduces negative leap second
syscon clock CLOCK_MONOTONIC_PRECISE 1 1 6 6 11 3 3 1 #
syscon clock CLOCK_MONOTONIC_FAST 1 1 6 6 12 3 3 1 #
syscon clock CLOCK_MONOTONIC_COARSE 6 6 5 5 12 3 3 1 # Linux 2.6.32+; bsd consensus; not available on RHEL5
syscon clock CLOCK_MONOTONIC_RAW 4 4 4 4 127 127 127 127 # actually monotonic; not subject to NTP adjustments; Linux 2.6.28+; XNU/NT/FreeBSD/OpenBSD faked; not available on RHEL5
syscon clock CLOCK_PROCESS_CPUTIME_ID 2 2 12 12 15 2 0x40000000 4 # NetBSD lets you bitwise a PID into clockid_t
syscon clock CLOCK_THREAD_CPUTIME_ID 3 3 16 16 14 4 0x20000000 5 #
syscon clock CLOCK_PROF 127 127 127 127 2 127 2 127 #
syscon clock CLOCK_BOOTTIME 7 7 7 127 127 6 127 3 #
syscon clock CLOCK_REALTIME_ALARM 8 8 127 127 127 127 127 127 #
syscon clock CLOCK_BOOTTIME_ALARM 9 9 127 127 127 127 127 127 #
syscon clock CLOCK_TAI 11 11 127 127 127 127 127 127 #
syscon clock CLOCK_UPTIME 127 127 127 127 5 5 127 127 #
syscon clock CLOCK_UPTIME 127 127 8 8 5 5 127 127 #
syscon clock CLOCK_UPTIME_PRECISE 127 127 127 127 7 127 127 127 #
syscon clock CLOCK_UPTIME_FAST 127 127 127 127 8 127 127 127 #
syscon clock CLOCK_SECOND 127 127 127 127 13 127 127 127 #

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon clock,CLOCK_MONOTONIC,1,1,1,6,4,3,3,1
.syscon clock,CLOCK_MONOTONIC,1,1,6,6,4,3,3,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon clock,CLOCK_MONOTONIC_COARSE,6,6,1,6,12,3,3,1
.syscon clock,CLOCK_MONOTONIC_COARSE,6,6,5,5,12,3,3,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon clock,CLOCK_MONOTONIC_FAST,1,1,1,6,12,3,3,1
.syscon clock,CLOCK_MONOTONIC_FAST,1,1,6,6,12,3,3,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon clock,CLOCK_MONOTONIC_PRECISE,1,1,1,6,11,3,3,1
.syscon clock,CLOCK_MONOTONIC_PRECISE,1,1,6,6,11,3,3,1

Some files were not shown because too many files have changed in this diff Show more