mirror of
https://github.com/jart/cosmopolitan.git
synced 2024-05-18 03:22:40 +00:00
Compare commits
11 commits
c1942d7ca5
...
43573173c6
Author | SHA1 | Date | |
---|---|---|---|
43573173c6 | |||
5488f0b2ca | |||
deff138e7e | |||
b6e40a3a58 | |||
8f6bc9dabc | |||
181cd4cbe8 | |||
5c6877b02b | |||
403bc25412 | |||
3bcd40be12 | |||
fcfdd26b72 | |||
a1f5160fab |
33
ape/ape-m1.c
33
ape/ape-m1.c
|
@ -31,6 +31,8 @@
|
|||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
@ -39,7 +41,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 9 /* sync with libc/runtime/syslib.internal.h */
|
||||
#define SYSLIB_VERSION 10 /* sync with libc/runtime/syslib.internal.h */
|
||||
|
||||
struct Syslib {
|
||||
int magic;
|
||||
|
@ -106,6 +108,10 @@ struct Syslib {
|
|||
OPTIONAL (cosmo lib should check __syslib->version) */
|
||||
/* v9 (2024-01-31) */
|
||||
int (*pthread_cpu_number_np)(size_t *);
|
||||
/* v10 (2024-05-02) */
|
||||
long (*sysctl)(int *, u_int, void *, size_t *, void *, size_t);
|
||||
long (*sysctlbyname)(const char *, void *, size_t *, void *, size_t);
|
||||
long (*sysctlnametomib)(const char *, int *, size_t *);
|
||||
};
|
||||
|
||||
#define ELFCLASS32 1
|
||||
|
@ -148,8 +154,8 @@ struct Syslib {
|
|||
#define _COMM_PAGE_APRR_WRITE_ENABLE (_COMM_PAGE_START_ADDRESS + 0x110)
|
||||
#define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118)
|
||||
|
||||
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||
#define Min(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||
#define Max(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||
|
||||
#define READ32(S) \
|
||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||
|
@ -552,6 +558,20 @@ static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds,
|
|||
return sysret(pselect(nfds, readfds, writefds, errorfds, timeout, sigmask));
|
||||
}
|
||||
|
||||
static long sys_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
|
||||
void *newp, size_t newlen) {
|
||||
return sysret(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
|
||||
}
|
||||
|
||||
static long sys_sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
|
||||
void *newp, size_t newlen) {
|
||||
return sysret(sysctlbyname(name, oldp, oldlenp, newp, newlen));
|
||||
}
|
||||
|
||||
static long sys_sysctlnametomib(const char *name, int *mibp, size_t *sizep) {
|
||||
return sysret(sysctlnametomib(name, mibp, sizep));
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
||||
long *sp, struct ElfEhdr *e,
|
||||
struct ElfPhdr *p,
|
||||
|
@ -596,7 +616,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
|||
continue;
|
||||
c = p[j].p_vaddr & -pagesz;
|
||||
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
|
||||
if (MAX(a, c) < MIN(b, d)) {
|
||||
if (Max(a, c) < Min(b, d)) {
|
||||
Pexit(exe, 0, "ELF segments overlap each others virtual memory");
|
||||
}
|
||||
}
|
||||
|
@ -670,7 +690,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
|||
a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */
|
||||
b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */
|
||||
c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */
|
||||
wipe = MIN(b - a, c - a);
|
||||
wipe = Min(b - a, c - a);
|
||||
if (wipe && (~prot1 & PROT_WRITE)) {
|
||||
prot1 = PROT_READ | PROT_WRITE;
|
||||
}
|
||||
|
@ -970,6 +990,9 @@ int main(int argc, char **argv, char **envp) {
|
|||
M->lib.dlclose = dlclose;
|
||||
M->lib.dlerror = dlerror;
|
||||
M->lib.pthread_cpu_number_np = pthread_cpu_number_np;
|
||||
M->lib.sysctl = sys_sysctl;
|
||||
M->lib.sysctlbyname = sys_sysctlbyname;
|
||||
M->lib.sysctlnametomib = sys_sysctlnametomib;
|
||||
|
||||
/* getenv("_") is close enough to at_execfn */
|
||||
execfn = 0;
|
||||
|
|
|
@ -10,8 +10,8 @@ if [ ! -f ape/loader.c ]; then
|
|||
cd "$COSMO" || exit
|
||||
fi
|
||||
|
||||
if [ -x build/bootstrap/make.com ]; then
|
||||
MAKE=build/bootstrap/make.com
|
||||
if [ -x build/bootstrap/make ]; then
|
||||
MAKE=build/bootstrap/make
|
||||
else
|
||||
MAKE=make
|
||||
fi
|
||||
|
|
142
examples/trapping.c
Normal file
142
examples/trapping.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
#include <fenv.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
#include "libc/calls/struct/aarch64.internal.h"
|
||||
|
||||
/*
|
||||
Do you put lots of assert(!isnan(x)) in your code??
|
||||
Your microprocessor has a feature to automate this.
|
||||
|
||||
Uncaught SIGFPE (FPE_FLTINV)
|
||||
__math_invalidf at libc/tinymath/math_errf.c:88
|
||||
logf at libc/tinymath/logf.c:100
|
||||
main at examples/trapping.c:29
|
||||
cosmo at libc/runtime/cosmo.S:105
|
||||
_start at libc/crt/crt.S:116
|
||||
|
||||
This file shows how to use floating point exception
|
||||
trapping with Cosmopolitan Libc.
|
||||
*/
|
||||
|
||||
#define TRAPS (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)
|
||||
|
||||
void spring_trap(int sig, siginfo_t *si, void *arg) {
|
||||
|
||||
// print signal safely
|
||||
const char *msg;
|
||||
int sic = si->si_code;
|
||||
if (sic == FPE_INTDIV)
|
||||
msg = "FPE_INTDIV: "; // integer divide by zero
|
||||
else if (sic == FPE_INTOVF)
|
||||
msg = "FPE_INTOVF: "; // integer overflow
|
||||
else if (sic == FPE_FLTDIV)
|
||||
msg = "FPE_FLTDIV: "; // floating point divide by zero
|
||||
else if (sic == FPE_FLTOVF)
|
||||
msg = "FPE_FLTOVF: "; // floating point overflow
|
||||
else if (sic == FPE_FLTUND)
|
||||
msg = "FPE_FLTUND: "; // floating point underflow
|
||||
else if (sic == FPE_FLTRES)
|
||||
msg = "FPE_FLTRES: "; // floating point inexact
|
||||
else if (sic == FPE_FLTINV)
|
||||
msg = "FPE_FLTINV: "; // invalid floating point operation
|
||||
else if (sic == FPE_FLTSUB)
|
||||
msg = "FPE_FLTSUB: "; // subscript out of range
|
||||
else
|
||||
msg = "SIGFPE: ";
|
||||
write(1, msg, strlen(msg));
|
||||
|
||||
// recover from trap so that execution may resume
|
||||
// without this the same signal will just keep getting raised
|
||||
ucontext_t *ctx = arg;
|
||||
#ifdef __x86_64__
|
||||
if (ctx->uc_mcontext.fpregs) {
|
||||
ctx->uc_mcontext.fpregs->mxcsr |= TRAPS << 7; // disable traps
|
||||
ctx->uc_mcontext.fpregs->mxcsr &= ~TRAPS; // clear cages
|
||||
return;
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
struct _aarch64_ctx *ac;
|
||||
for (ac = (struct _aarch64_ctx *)ctx->uc_mcontext.__reserved; ac->magic;
|
||||
ac = (struct _aarch64_ctx *)((char *)ac + ac->size)) {
|
||||
if (ac->magic == FPSIMD_MAGIC) {
|
||||
struct fpsimd_context *sm = (struct fpsimd_context *)ac;
|
||||
sm->fpcr &= ~(TRAPS << 8); // disable traps
|
||||
sm->fpsr &= ~TRAPS; // clear cages
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// exit if we can't recover execution
|
||||
msg = "cannot recover from signal\n";
|
||||
write(1, msg, strlen(msg));
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
void setup_trap(void) {
|
||||
struct sigaction sa;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = spring_trap;
|
||||
sigaction(SIGFPE, &sa, 0);
|
||||
}
|
||||
|
||||
void activate_trap(void) {
|
||||
feclearexcept(TRAPS);
|
||||
if (feenableexcept(TRAPS)) {
|
||||
static bool once;
|
||||
if (!once) {
|
||||
fprintf(stderr, "warning: trapping math isn't supported on this cpu\n");
|
||||
once = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float ident(float x) {
|
||||
return x;
|
||||
}
|
||||
float (*veil)(float) = ident;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
float x;
|
||||
setup_trap();
|
||||
|
||||
// test illegal math
|
||||
activate_trap();
|
||||
x = 0 / veil(0);
|
||||
printf("0/0 = %g\n", x);
|
||||
|
||||
// test divide by zero
|
||||
activate_trap();
|
||||
x = 1 / veil(0);
|
||||
printf("1/0 = %g\n", x);
|
||||
|
||||
// test divide by zero again
|
||||
activate_trap();
|
||||
x = -1 / veil(0);
|
||||
printf("-1/0 = %g\n", x);
|
||||
|
||||
// test domain error
|
||||
activate_trap();
|
||||
x = logf(veil(-1));
|
||||
printf("log(-1) = %g\n", x);
|
||||
|
||||
// test imaginary number
|
||||
activate_trap();
|
||||
x = sqrtf(veil(-1));
|
||||
printf("sqrt(-1) = %g\n", x);
|
||||
|
||||
// test overflow
|
||||
activate_trap();
|
||||
x = expf(veil(88.8));
|
||||
printf("expf(88.8) = %g\n", x);
|
||||
|
||||
// test underflow
|
||||
activate_trap();
|
||||
x = expf(veil(-104));
|
||||
printf("expf(-104) = %g\n", x);
|
||||
}
|
|
@ -237,7 +237,9 @@ int sys_munlock(const void *, size_t) libcesque;
|
|||
int sys_munlockall(void) libcesque;
|
||||
int sys_personality(uint64_t) libcesque;
|
||||
int sys_ptrace(int, ...) libcesque;
|
||||
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
|
||||
int sysctl(int *, unsigned, void *, size_t *, void *, size_t) libcesque;
|
||||
int sysctlbyname(const char *, void *, size_t *, void *, size_t) libcesque;
|
||||
int sysctlnametomib(const char *, int *, size_t *) libcesque;
|
||||
int tmpfd(void) libcesque;
|
||||
int touch(const char *, unsigned) libcesque;
|
||||
int unveil(const char *, const char *) libcesque;
|
||||
|
|
|
@ -53,7 +53,7 @@ static dontinline int __clk_tck_init(void) {
|
|||
cmd[0] = 1; // CTL_KERN
|
||||
cmd[1] = 12; // KERN_CLOCKRATE
|
||||
len = sizeof(clock);
|
||||
if (sys_sysctl(cmd, 2, &clock, &len, NULL, 0) != -1) {
|
||||
if (sysctl(cmd, 2, &clock, &len, NULL, 0) != -1) {
|
||||
x = clock.hz;
|
||||
} else {
|
||||
x = -1;
|
||||
|
|
|
@ -67,7 +67,7 @@ int sys_clock_gettime_xnu(int clock, struct timespec *ts) {
|
|||
struct timeval x;
|
||||
size_t n = sizeof(x);
|
||||
int mib[] = {CTL_KERN, KERN_BOOTTIME};
|
||||
if (sys_sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
|
||||
if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
|
||||
return -1;
|
||||
if (ts)
|
||||
*ts = timeval_totimespec(timeval_sub(timeval_real(), x));
|
||||
|
|
|
@ -332,7 +332,8 @@ textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
|||
if (__isfdkind(fd, kFdFile) || //
|
||||
__isfdkind(fd, kFdSocket) || //
|
||||
__isfdkind(fd, kFdConsole) || //
|
||||
__isfdkind(fd, kFdDevNull)) {
|
||||
__isfdkind(fd, kFdDevNull) || //
|
||||
__isfdkind(fd, kFdDevRandom)) {
|
||||
if (cmd == F_GETFL) {
|
||||
rc = g_fds.p[fd].flags & (O_ACCMODE | _O_APPEND | _O_DIRECT |
|
||||
_O_NONBLOCK | _O_RANDOM | _O_SEQUENTIAL);
|
||||
|
|
|
@ -104,6 +104,7 @@ textwindows int sys_fstat_nt(int fd, struct stat *st) {
|
|||
return ebadf();
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
case kFdDevRandom:
|
||||
return sys_fstat_nt_special(g_fds.p[fd].kind, st);
|
||||
case kFdSocket:
|
||||
return sys_fstat_nt_socket(g_fds.p[fd].kind, st);
|
||||
|
|
|
@ -59,6 +59,8 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
|||
return sys_fstat_nt_special(kFdConsole, st);
|
||||
} else if (!strcmp(path + 5, "null")) {
|
||||
return sys_fstat_nt_special(kFdDevNull, st);
|
||||
} else if (!strcmp(path + 5, "random") || !strcmp(path + 5, "urandom")) {
|
||||
return sys_fstat_nt_special(kFdDevRandom, st);
|
||||
} else if (!strcmp(path + 5, "stdin")) {
|
||||
return sys_fstat_nt(STDIN_FILENO, st);
|
||||
} else if (!strcmp(path + 5, "stdout")) {
|
||||
|
|
|
@ -51,7 +51,7 @@ static int __get_cpu_count_bsd(void) {
|
|||
} else {
|
||||
cmd[1] = HW_NCPU;
|
||||
}
|
||||
if (!sys_sysctl(cmd, 2, &c, &n, 0, 0)) {
|
||||
if (!sysctl(cmd, 2, &c, &n, 0, 0)) {
|
||||
return c;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
int gethostname_bsd(char *name, size_t len, int kind) {
|
||||
int cmd[2] = {CTL_KERN, kind};
|
||||
if (sys_sysctl(cmd, 2, name, &len, 0, 0) != -1) {
|
||||
if (sysctl(cmd, 2, name, &len, 0, 0) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
if (errno == ENOMEM) {
|
||||
|
|
|
@ -64,7 +64,7 @@ int getloadavg(double *a, int n) {
|
|||
struct loadavg loadinfo;
|
||||
int mib[2] = {CTL_VM, VM_LOADAVG};
|
||||
size = sizeof(loadinfo);
|
||||
if ((rc = sys_sysctl(mib, 2, &loadinfo, &size, 0, 0)) != -1) {
|
||||
if ((rc = sysctl(mib, 2, &loadinfo, &size, 0, 0)) != -1) {
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i] = (double)loadinfo.ldavg[i] / loadinfo.fscale;
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ static inline void InitProgramExecutableNameImpl(void) {
|
|||
cmd[2] = KERN_PROC_PATHNAME_NETBSD;
|
||||
}
|
||||
cmd[3] = -1; // current process
|
||||
if (sys_sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) {
|
||||
if (sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) {
|
||||
if (!OldApeLoader(b)) {
|
||||
goto UseBuf;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ static void GetRandomArnd(char *p, size_t n) {
|
|||
cmd[0] = 1; // CTL_KERN
|
||||
cmd[1] = IsFreebsd() ? 37 : 81; // KERN_ARND
|
||||
unassert((m = n) <= 256);
|
||||
if (sys_sysctl(cmd, 2, p, &n, 0, 0) == -1)
|
||||
if (sysctl(cmd, 2, p, &n, 0, 0) == -1)
|
||||
notpossible;
|
||||
if (m != n)
|
||||
notpossible;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
|
@ -42,6 +41,7 @@
|
|||
#include "libc/nt/winsock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/struct/ifconf.h"
|
||||
#include "libc/sock/struct/ifreq.h"
|
||||
|
@ -66,7 +66,7 @@ static struct HostAdapterInfoNode {
|
|||
struct sockaddr netmask;
|
||||
struct sockaddr broadcast;
|
||||
short flags;
|
||||
} *__hostInfo;
|
||||
} * __hostInfo;
|
||||
|
||||
static int ioctl_default(int fd, unsigned long request, void *arg) {
|
||||
int rc;
|
||||
|
@ -107,8 +107,9 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
|
|||
*arg = MAX(0, bytes);
|
||||
return 0;
|
||||
} else if (g_fds.p[fd].kind == kFdDevNull) {
|
||||
*arg = 1;
|
||||
return 0;
|
||||
return enotty();
|
||||
} else if (g_fds.p[fd].kind == kFdDevRandom) {
|
||||
return einval();
|
||||
} else if (GetFileType(handle) == kNtFileTypePipe) {
|
||||
uint32_t avail;
|
||||
if (PeekNamedPipe(handle, 0, 0, 0, &avail, 0)) {
|
||||
|
|
|
@ -55,6 +55,7 @@ bool32 ischardev(int fd) {
|
|||
}
|
||||
} else {
|
||||
return __isfdkind(fd, kFdConsole) || __isfdkind(fd, kFdDevNull) ||
|
||||
__isfdkind(fd, kFdDevRandom) ||
|
||||
(__isfdkind(fd, kFdFile) &&
|
||||
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ static textwindows int64_t Seek(struct Fd *f, int64_t offset, int whence) {
|
|||
}
|
||||
|
||||
textwindows int64_t sys_lseek_nt(int fd, int64_t offset, int whence) {
|
||||
if (__isfdkind(fd, kFdDevNull)) {
|
||||
if (__isfdkind(fd, kFdDevNull) || __isfdkind(fd, kFdDevRandom)) {
|
||||
return offset;
|
||||
} else if (__isfdkind(fd, kFdFile)) {
|
||||
struct Fd *f = g_fds.p + fd;
|
||||
|
|
|
@ -159,6 +159,15 @@ static textwindows int sys_open_nt_special(int fd, int flags, int mode,
|
|||
return fd;
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_no_handle(int fd, int flags, int mode,
|
||||
int kind) {
|
||||
g_fds.p[fd].kind = kind;
|
||||
g_fds.p[fd].mode = mode;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].handle = -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_dup(int fd, int flags, int mode, int oldfd) {
|
||||
int64_t handle;
|
||||
if (!__isfdopen(oldfd)) {
|
||||
|
@ -211,6 +220,8 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
|
|||
rc = sys_open_nt_special(fd, flags, mode, kFdConsole, u"CONIN$");
|
||||
} else if (!strcmp(file + 5, "null")) {
|
||||
rc = sys_open_nt_special(fd, flags, mode, kFdDevNull, u"NUL");
|
||||
} else if (!strcmp(file + 5, "urandom") || !strcmp(file + 5, "random")) {
|
||||
rc = sys_open_nt_no_handle(fd, flags, mode, kFdDevRandom);
|
||||
} else if (!strcmp(file + 5, "stdin")) {
|
||||
rc = sys_open_nt_dup(fd, flags, mode, STDIN_FILENO);
|
||||
} else if (!strcmp(file + 5, "stdout")) {
|
||||
|
|
|
@ -72,7 +72,8 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
|||
rc = sys_pread(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = espipe();
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull) ||
|
||||
__isfdkind(fd, kFdDevRandom)) {
|
||||
rc = sys_read_nt(fd, (struct iovec[]){{buf, size}}, 1, offset);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
|
|
|
@ -40,6 +40,8 @@ static const char *__fdkind2str(int x) {
|
|||
return "kFdZip";
|
||||
case kFdEpoll:
|
||||
return "kFdEpoll";
|
||||
case kFdDevRandom:
|
||||
return "kFdRandom";
|
||||
default:
|
||||
return "kFdWut";
|
||||
}
|
||||
|
|
|
@ -65,7 +65,8 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
rc = sys_pwrite(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = espipe();
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull) ||
|
||||
__isfdkind(fd, kFdDevRandom)) {
|
||||
rc = sys_write_nt(fd, (struct iovec[]){{(void *)buf, size}}, 1, offset);
|
||||
} else {
|
||||
return ebadf();
|
||||
|
|
|
@ -786,6 +786,10 @@ textwindows ssize_t ReadBuffer(int fd, void *data, size_t size, int64_t offset,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (f->kind == kFdDevRandom) {
|
||||
return ProcessPrng(data, size) ? size : __winerr();
|
||||
}
|
||||
|
||||
if (f->kind == kFdConsole) {
|
||||
return ReadFromConsole(f, data, size, waitmask);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ textwindows ssize_t sys_readv_nt(int fd, const struct iovec *iov, int iovlen) {
|
|||
case kFdFile:
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
case kFdDevRandom:
|
||||
return sys_read_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return _weaken(sys_recv_nt)(fd, iov, iovlen, 0);
|
||||
|
|
|
@ -61,7 +61,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
|
|||
bool pwriting = offset != -1;
|
||||
bool seekable =
|
||||
(f->kind == kFdFile && GetFileType(handle) == kNtFileTypeDisk) ||
|
||||
f->kind == kFdDevNull;
|
||||
f->kind == kFdDevNull || f->kind == kFdDevRandom;
|
||||
if (pwriting && !seekable) {
|
||||
return espipe();
|
||||
}
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_FD_INTERNAL_H_
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define kFdEmpty 0
|
||||
#define kFdFile 1
|
||||
#define kFdSocket 2
|
||||
#define kFdConsole 4
|
||||
#define kFdSerial 5
|
||||
#define kFdZip 6
|
||||
#define kFdEpoll 7
|
||||
#define kFdReserved 8
|
||||
#define kFdDevNull 9
|
||||
#define kFdEmpty 0
|
||||
#define kFdFile 1
|
||||
#define kFdSocket 2
|
||||
#define kFdConsole 4
|
||||
#define kFdSerial 5
|
||||
#define kFdZip 6
|
||||
#define kFdEpoll 7
|
||||
#define kFdReserved 8
|
||||
#define kFdDevNull 9
|
||||
#define kFdDevRandom 10
|
||||
|
||||
struct Fd {
|
||||
char kind;
|
||||
|
|
33
libc/calls/sysctl.c
Normal file
33
libc/calls/sysctl.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
|
||||
int sys_sysctl(int *, unsigned, void *, size_t *, void *, size_t) libcesque;
|
||||
|
||||
int sysctl(int *name, unsigned namelen, void *oldp, size_t *oldlenp, void *newp,
|
||||
size_t newlen) {
|
||||
if (__syslib && __syslib->__version >= 10) {
|
||||
return _sysret(
|
||||
__syslib->__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
|
||||
} else {
|
||||
return sys_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
|
||||
}
|
||||
}
|
31
libc/calls/sysctlbyname.c
Normal file
31
libc/calls/sysctlbyname.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
|
||||
size_t newlen) {
|
||||
if (__syslib && __syslib->__version >= 10) {
|
||||
return _sysret(__syslib->__sysctlbyname(name, oldp, oldlenp, newp, newlen));
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
30
libc/calls/sysctlnametomib.c
Normal file
30
libc/calls/sysctlnametomib.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sysctlnametomib(const char *name, int *mibp, size_t *sizep) {
|
||||
if (__syslib && __syslib->__version >= 10) {
|
||||
return _sysret(__syslib->__sysctlnametomib(name, mibp, sizep));
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ static int64_t GetUptime(void) {
|
|||
struct timeval x;
|
||||
size_t n = sizeof(x);
|
||||
int mib[] = {CTL_KERN, KERN_BOOTTIME};
|
||||
if (sys_sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
|
||||
if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
|
||||
return 0;
|
||||
return timespec_real().tv_sec - x.tv_sec;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ static int64_t GetPhysmem(void) {
|
|||
uint64_t x = 0;
|
||||
size_t n = sizeof(x);
|
||||
int mib[] = {CTL_HW, HW_PHYSMEM};
|
||||
if (sys_sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
|
||||
if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
|
||||
return 0;
|
||||
return x;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ static void GetLoads(uint64_t loads[3]) {
|
|||
struct loadavg loadinfo;
|
||||
int mib[2] = {CTL_VM, VM_LOADAVG};
|
||||
size = sizeof(loadinfo);
|
||||
if (sys_sysctl(mib, 2, &loadinfo, &size, 0, 0) != -1) {
|
||||
if (sysctl(mib, 2, &loadinfo, &size, 0, 0) != -1) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
loads[i] = (double)loadinfo.ldavg[i] / loadinfo.fscale * 65536;
|
||||
}
|
||||
|
|
|
@ -43,14 +43,55 @@ struct FpuStackEntry {
|
|||
};
|
||||
|
||||
struct thatispacked FpuState {
|
||||
|
||||
/* 8087 FPU Control Word
|
||||
IM: Invalid Operation ───────────────┐
|
||||
DM: Denormal Operand ───────────────┐│
|
||||
ZM: Zero Divide ───────────────────┐││
|
||||
OM: Overflow ─────────────────────┐│││
|
||||
UM: Underflow ───────────────────┐││││
|
||||
PM: Precision ──────────────────┐│││││
|
||||
PC: Precision Control ───────┐ ││││││
|
||||
{float,∅,double,long double}│ ││││││
|
||||
RC: Rounding Control ──────┐ │ ││││││
|
||||
{even, →-∞, →+∞, →0} │┌┤ ││││││
|
||||
┌┤││ ││││││
|
||||
d││││rr││││││
|
||||
0b0000001001111111 */
|
||||
uint16_t cwd;
|
||||
|
||||
/* 8087 FPU Status Word */
|
||||
uint16_t swd;
|
||||
|
||||
uint16_t ftw;
|
||||
uint16_t fop;
|
||||
uint64_t rip;
|
||||
uint64_t rdp;
|
||||
|
||||
/* SSE CONTROL AND STATUS REGISTER
|
||||
IE: Invalid Operation Flag ──────────────┐
|
||||
DE: Denormal Flag ──────────────────────┐│
|
||||
ZE: Divide-by-Zero Flag ───────────────┐││
|
||||
OE: Overflow Flag ────────────────────┐│││
|
||||
UE: Underflow Flag ──────────────────┐││││
|
||||
PE: Precision Flag ─────────────────┐│││││
|
||||
DAZ: Denormals Are Zeros ──────────┐││││││
|
||||
IM: Invalid Operation Mask ───────┐│││││││
|
||||
DM: Denormal Operation Mask ─────┐││││││││
|
||||
ZM: Divide-by-Zero Mask ────────┐│││││││││
|
||||
OM: Overflow Mask ─────────────┐││││││││││
|
||||
UM: Underflow Mask ───────────┐│││││││││││
|
||||
PM: Precision Mask ──────────┐││││││││││││
|
||||
RC: Rounding Control ───────┐│││││││││││││
|
||||
{even, →-∞, →+∞, →0} ││││││││││││││
|
||||
FTZ: Flush To Zero ───────┐ ││││││││││││││
|
||||
│┌┤│││││││││││││
|
||||
┌──────────────┐││││││││││││││││
|
||||
│ reserved │││││││││││││││││
|
||||
0b00000000000000000001111110000000 */
|
||||
uint32_t mxcsr;
|
||||
uint32_t mxcr_mask;
|
||||
|
||||
struct FpuStackEntry st[8];
|
||||
struct XmmRegister xmm[16];
|
||||
uint32_t __padding[24];
|
||||
|
|
|
@ -62,7 +62,7 @@ static void GetBsdStr(int c0, int c1, char *s) {
|
|||
size_t n = SYS_NMLN;
|
||||
int cmd[2] = {c0, c1};
|
||||
bzero(s, n), --n;
|
||||
sys_sysctl(cmd, 2, s, &n, NULL, 0);
|
||||
sysctl(cmd, 2, s, &n, NULL, 0);
|
||||
errno = e;
|
||||
// sysctl kern.version is too verbose for uname
|
||||
if ((p = strchr(s, '\n'))) {
|
||||
|
|
|
@ -52,6 +52,11 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
|||
struct Fd *f = g_fds.p + fd;
|
||||
bool isconsole = f->kind == kFdConsole;
|
||||
|
||||
// not implemented, XNU returns eperm();
|
||||
if (f->kind == kFdDevRandom) {
|
||||
return eperm();
|
||||
}
|
||||
|
||||
// determine win32 handle for writing
|
||||
int64_t handle = f->handle;
|
||||
if (isconsole && _weaken(GetConsoleOutputHandle)) {
|
||||
|
|
|
@ -28,6 +28,7 @@ textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
|
|||
case kFdFile:
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
case kFdDevRandom:
|
||||
return sys_write_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return _weaken(sys_send_nt)(fd, iov, iovlen, 0);
|
||||
|
|
|
@ -5,6 +5,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);
|
||||
void unleaf(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_COSMO_H_ */
|
||||
|
|
92
libc/intrin/fedisableexcept.c
Normal file
92
libc/intrin/fedisableexcept.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/fenv.h"
|
||||
|
||||
/**
|
||||
* Disables floating point exception trapping, e.g.
|
||||
*
|
||||
* feenableexcept(FE_INVALID | FE_DIVBYZERO |
|
||||
* FE_OVERFLOW | FE_UNDERFLOW);
|
||||
*
|
||||
* When trapping is enabled, something should handle SIGFPE. Calling
|
||||
* ShowCrashReports() at startup will install a generic handler with
|
||||
* backtraces and the symbol of the `si->si_code` which UNIX defines
|
||||
*
|
||||
* - `FPE_INTOVF`: integer overflow
|
||||
* - `FPE_INTDIV`: integer divide by zero
|
||||
* - `FPE_FLTDIV`: floating point divide by zero
|
||||
* - `FPE_FLTOVF`: floating point overflow
|
||||
* - `FPE_FLTUND`: floating point underflow
|
||||
* - `FPE_FLTRES`: floating point inexact
|
||||
* - `FPE_FLTINV`: invalid floating point operation
|
||||
* - `FPE_FLTSUB`: subscript out of range
|
||||
*
|
||||
* It's important to not use the `-ffast-math` or `-Ofast` flags when
|
||||
* compiling code that needs to be debugged. Using `-fsignaling-nans`
|
||||
* will also help, since GCC doesn't enable that by default.
|
||||
*
|
||||
* @param excepts may bitwise-or the following:
|
||||
* - `FE_INVALID`
|
||||
* - `FE_DIVBYZERO`
|
||||
* - `FE_OVERFLOW`
|
||||
* - `FE_UNDERFLOW`
|
||||
* - `FE_INEXACT`
|
||||
* - `FE_ALL_EXCEPT` (all of the above)
|
||||
* @see fetestexcept() if you don't want to deal with signals
|
||||
* @see feenableexcept() to turn it on in the first place
|
||||
*/
|
||||
int fedisableexcept(int excepts) {
|
||||
|
||||
// limit to what we know
|
||||
excepts &= FE_ALL_EXCEPT;
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#ifndef NOX87
|
||||
// configure 8087 fpu control word
|
||||
// setting the bits enables suppression
|
||||
unsigned short x87cw;
|
||||
asm("fstcw\t%0" : "=m"(x87cw));
|
||||
x87cw |= excepts;
|
||||
asm("fldcw\t%0" : /* no inputs */ : "m"(x87cw));
|
||||
#endif
|
||||
|
||||
// configure modern sse control word
|
||||
// setting the bits enables suppression
|
||||
unsigned mxcsr;
|
||||
asm("stmxcsr\t%0" : "=m"(mxcsr));
|
||||
mxcsr |= excepts << 7;
|
||||
asm("ldmxcsr\t%0" : /* no inputs */ : "m"(mxcsr));
|
||||
|
||||
return 0;
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
unsigned fpcr;
|
||||
unsigned fpcr2;
|
||||
fpcr = __builtin_aarch64_get_fpcr();
|
||||
fpcr2 = fpcr & ~(excepts << 8);
|
||||
if (fpcr != fpcr2)
|
||||
__builtin_aarch64_set_fpcr(fpcr2);
|
||||
return (fpcr >> 8) & FE_ALL_EXCEPT;
|
||||
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
98
libc/intrin/feenableexcept.c
Normal file
98
libc/intrin/feenableexcept.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/fenv.h"
|
||||
|
||||
/**
|
||||
* Enables floating point exception trapping, e.g.
|
||||
*
|
||||
* feenableexcept(FE_INVALID | FE_DIVBYZERO |
|
||||
* FE_OVERFLOW | FE_UNDERFLOW);
|
||||
*
|
||||
* When trapping is enabled, something should handle SIGFPE. Calling
|
||||
* ShowCrashReports() at startup will install a generic handler with
|
||||
* backtraces and the symbol of the `si->si_code` which UNIX defines
|
||||
*
|
||||
* - `FPE_INTOVF`: integer overflow
|
||||
* - `FPE_INTDIV`: integer divide by zero
|
||||
* - `FPE_FLTDIV`: floating point divide by zero
|
||||
* - `FPE_FLTOVF`: floating point overflow
|
||||
* - `FPE_FLTUND`: floating point underflow
|
||||
* - `FPE_FLTRES`: floating point inexact
|
||||
* - `FPE_FLTINV`: invalid floating point operation
|
||||
* - `FPE_FLTSUB`: subscript out of range
|
||||
*
|
||||
* It's important to not use the `-ffast-math` or `-Ofast` flags when
|
||||
* compiling code that needs to be debugged. Using `-fsignaling-nans`
|
||||
* will also help, since GCC doesn't enable that by default.
|
||||
*
|
||||
* @param excepts may bitwise-or the following:
|
||||
* - `FE_INVALID`
|
||||
* - `FE_DIVBYZERO`
|
||||
* - `FE_OVERFLOW`
|
||||
* - `FE_UNDERFLOW`
|
||||
* - `FE_INEXACT`
|
||||
* - `FE_ALL_EXCEPT` (all of the above)
|
||||
* @see fetestexcept() if you don't want to deal with signals
|
||||
* @see fedisableexcept() to turn it back off again
|
||||
*/
|
||||
int feenableexcept(int excepts) {
|
||||
|
||||
// limit to what we know
|
||||
excepts &= FE_ALL_EXCEPT;
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#ifndef NOX87
|
||||
// configure 8087 fpu control word
|
||||
// celaring the bits disables suppression
|
||||
unsigned short x87cw;
|
||||
asm("fstcw\t%0" : "=m"(x87cw));
|
||||
x87cw &= ~excepts;
|
||||
asm("fldcw\t%0" : /* no inputs */ : "m"(x87cw));
|
||||
#endif
|
||||
|
||||
// configure modern sse control word
|
||||
// clearing the bits disables suppression
|
||||
unsigned mxcsr;
|
||||
asm("stmxcsr\t%0" : "=m"(mxcsr));
|
||||
mxcsr &= ~(excepts << 7);
|
||||
asm("ldmxcsr\t%0" : /* no inputs */ : "m"(mxcsr));
|
||||
|
||||
return 0;
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
unsigned fpcr;
|
||||
unsigned fpcr2;
|
||||
unsigned updated_fpcr;
|
||||
fpcr = __builtin_aarch64_get_fpcr();
|
||||
fpcr2 = fpcr | (excepts << 8);
|
||||
if (fpcr != fpcr2) {
|
||||
__builtin_aarch64_set_fpcr(fpcr2);
|
||||
// floating point exception trapping is optional in aarch64
|
||||
updated_fpcr = __builtin_aarch64_get_fpsr();
|
||||
if (fpcr2 & ~updated_fpcr)
|
||||
return -1;
|
||||
}
|
||||
return (fpcr >> 8) & FE_ALL_EXCEPT;
|
||||
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
|
@ -48,6 +48,7 @@ textwindows void _ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
|
|||
ctx->uc_mcontext.fs = cr->SegFs;
|
||||
ctx->uc_mcontext.fpregs = &ctx->__fpustate;
|
||||
__repmovsb(&ctx->__fpustate, &cr->FltSave, sizeof(ctx->__fpustate));
|
||||
ctx->__fpustate.mxcsr = cr->MxCsr;
|
||||
}
|
||||
|
||||
textwindows void _ntlinux2context(struct NtContext *cr, const ucontext_t *ctx) {
|
||||
|
@ -74,6 +75,7 @@ textwindows void _ntlinux2context(struct NtContext *cr, const ucontext_t *ctx) {
|
|||
cr->SegCs = ctx->uc_mcontext.cs;
|
||||
cr->SegGs = ctx->uc_mcontext.gs;
|
||||
cr->SegFs = ctx->uc_mcontext.fs;
|
||||
cr->MxCsr = ctx->__fpustate.mxcsr;
|
||||
__repmovsb(&cr->FltSave, &ctx->__fpustate, sizeof(ctx->__fpustate));
|
||||
}
|
||||
|
||||
|
|
32
libc/intrin/unleaf.c
Normal file
32
libc/intrin/unleaf.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/cosmo.h"
|
||||
|
||||
/**
|
||||
* Does nothing.
|
||||
*
|
||||
* Calling this function will force the compiler to generate a stack
|
||||
* frame. This ensures backtraces will work better in a few critical
|
||||
* routines.
|
||||
*/
|
||||
void unleaf(void) {
|
||||
// TODO: We should make ShowCrashReports() so __math_invalidf()
|
||||
// doesn't have to call this in order for the actual math
|
||||
// function to show up in the backtrace.
|
||||
}
|
|
@ -254,10 +254,28 @@ static relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
|||
kprintf("\n");
|
||||
}
|
||||
|
||||
static inline void SpinLock(atomic_uint *lock) {
|
||||
int x;
|
||||
for (;;) {
|
||||
x = atomic_exchange_explicit(lock, 1, memory_order_acquire);
|
||||
if (!x)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SpinUnlock(atomic_uint *lock) {
|
||||
atomic_store_explicit(lock, 0, memory_order_release);
|
||||
}
|
||||
|
||||
relegated void __oncrash(int sig, struct siginfo *si, void *arg) {
|
||||
static atomic_uint lock;
|
||||
BLOCK_CANCELATION;
|
||||
SpinLock(&lock);
|
||||
int err = errno;
|
||||
__restore_tty();
|
||||
ShowCrashReport(err, sig, si, arg);
|
||||
SpinUnlock(&lock);
|
||||
ALLOW_CANCELATION;
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/sections.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/blockcancel.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/aarch64.internal.h"
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/cxxabi.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/describebacktrace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
@ -377,10 +379,25 @@ static relegated void __oncrash_impl(int sig, struct siginfo *si,
|
|||
klog(b->p, MIN(b->i, b->n));
|
||||
}
|
||||
|
||||
static inline void SpinLock(atomic_uint *lock) {
|
||||
int x;
|
||||
for (;;) {
|
||||
x = atomic_exchange_explicit(lock, 1, memory_order_acquire);
|
||||
if (!x)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SpinUnlock(atomic_uint *lock) {
|
||||
atomic_store_explicit(lock, 0, memory_order_release);
|
||||
}
|
||||
|
||||
relegated void __oncrash(int sig, struct siginfo *si, void *arg) {
|
||||
ucontext_t *ctx = arg;
|
||||
static atomic_uint lock;
|
||||
BLOCK_CANCELATION;
|
||||
__oncrash_impl(sig, si, ctx);
|
||||
SpinLock(&lock);
|
||||
__oncrash_impl(sig, si, arg);
|
||||
SpinUnlock(&lock);
|
||||
ALLOW_CANCELATION;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,19 @@ cosmo: push %rbp
|
|||
#ifdef __FAST_MATH__
|
||||
push %rax
|
||||
stmxcsr (%rsp)
|
||||
//
|
||||
// Enable hardware optimizations in violation of the IEEE standard.
|
||||
//
|
||||
// - 0x0040 enables "DAZ: Denormals Are Zeros" in MXCSR. This causes the
|
||||
// processor to turn denormal inputs into zero, before computing them.
|
||||
// See Intel Manual Vol. 1 §10.2.3.4
|
||||
//
|
||||
// - 0x8000 enables "FTZ: Flush To Zero" in MXCSR. This means a floating
|
||||
// point operation that results in underflow will be set to zero, with
|
||||
// the same sign, rather than producing a denormalized output. It will
|
||||
// happen only if underflow trapping hasnt been enabled. See the Intel
|
||||
// Manual Vol. 1 §10.2.3.3.
|
||||
//
|
||||
orl $0x8040,(%rsp)
|
||||
ldmxcsr (%rsp)
|
||||
pop %rax
|
||||
|
|
|
@ -81,6 +81,8 @@ int fesetenv(const fenv_t *);
|
|||
int fesetexceptflag(const fexcept_t *, int);
|
||||
int fesetround(int);
|
||||
int fetestexcept(int);
|
||||
int feenableexcept(int);
|
||||
int fedisableexcept(int);
|
||||
int feupdateenv(const fenv_t *);
|
||||
int __flt_rounds(void);
|
||||
int __fesetround(int);
|
||||
|
|
|
@ -74,9 +74,9 @@ char *GetInterpreterExecutableName(char *p, size_t n) {
|
|||
cmd[2] = 12; // KERN_PROC_PATHNAME
|
||||
} else { //
|
||||
cmd[2] = 5; // KERN_PROC_PATHNAME
|
||||
} //
|
||||
cmd[3] = -1; // current process
|
||||
if (sys_sysctl(cmd, ARRAYLEN(cmd), p, &n, 0, 0) != -1) {
|
||||
} //
|
||||
cmd[3] = -1; // current process
|
||||
if (sysctl(cmd, ARRAYLEN(cmd), p, &n, 0, 0) != -1) {
|
||||
errno = e;
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ long __get_sysctl(int x, int y) {
|
|||
int value;
|
||||
int mib[2] = {x, y};
|
||||
size_t len = sizeof(value);
|
||||
if (sys_sysctl(mib, 2, &value, &len, 0, 0) != -1) {
|
||||
if (sysctl(mib, 2, &value, &len, 0, 0) != -1) {
|
||||
return value;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -12,7 +12,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
||||
|
||||
#define SYSLIB_VERSION 9 /* sync with ape/ape-m1.c */
|
||||
#define SYSLIB_VERSION 10 /* 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
|
||||
|
@ -82,6 +82,9 @@ struct Syslib {
|
|||
char *(*__dlerror)(void);
|
||||
/* v9 (2024-01-31) */
|
||||
int (*__pthread_cpu_number_np)(size_t *);
|
||||
long (*__sysctl)(int *, unsigned, void *, size_t *, void *, size_t);
|
||||
long (*__sysctlbyname)(const char *, void *, size_t *, void *, size_t);
|
||||
long (*__sysctlnametomib)(const char *, int *, size_t *);
|
||||
};
|
||||
|
||||
extern struct Syslib *__syslib;
|
||||
|
|
|
@ -70,6 +70,9 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
|
|||
if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = sys_recvfrom_nt(fd, (struct iovec[]){{buf, size}}, 1, flags, &addr,
|
||||
&addrsize);
|
||||
if (rc != -1 && addrsize == sizeof(addr)) {
|
||||
addrsize = 0;
|
||||
}
|
||||
} else if (__isfdkind(fd, kFdFile) && !opt_out_srcaddr) { /* socketpair */
|
||||
if (!flags) {
|
||||
rc = sys_read_nt(fd, (struct iovec[]){{buf, size}}, 1, -1);
|
||||
|
@ -84,10 +87,14 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
|
|||
}
|
||||
|
||||
if (rc != -1) {
|
||||
if (IsBsd()) {
|
||||
__convert_bsd_to_sockaddr(&addr);
|
||||
if (addrsize) {
|
||||
if (IsBsd()) {
|
||||
__convert_bsd_to_sockaddr(&addr);
|
||||
}
|
||||
__write_sockaddr(&addr, opt_out_srcaddr, opt_inout_srcaddrsize);
|
||||
} else {
|
||||
*opt_inout_srcaddrsize = 0;
|
||||
}
|
||||
__write_sockaddr(&addr, opt_out_srcaddr, opt_inout_srcaddrsize);
|
||||
}
|
||||
|
||||
END_CANCELATION_POINT;
|
||||
|
|
|
@ -57,11 +57,7 @@ char *fgets_unlocked(char *s, int size, FILE *f) {
|
|||
break;
|
||||
} else {
|
||||
if ((c = fgetc_unlocked(f)) == -1) {
|
||||
if (ferror_unlocked(f) == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*p++ = c & 255;
|
||||
if (c == '\n')
|
||||
|
|
|
@ -26,8 +26,8 @@ static const char kUtf8Dispatch[] = {
|
|||
1, 1, 1, 1, 1, 1, 1, 1, // 0320
|
||||
1, 1, 1, 1, 1, 1, 1, 1, // 0330
|
||||
2, 3, 3, 3, 3, 3, 3, 3, // 0340 utf8-3
|
||||
3, 3, 3, 3, 3, 3, 3, 3, // 0350
|
||||
4, 5, 5, 5, 5, 0, 0, 0, // 0360 utf8-4
|
||||
3, 3, 3, 3, 3, 4, 3, 3, // 0350
|
||||
5, 6, 6, 6, 7, 0, 0, 0, // 0360 utf8-4
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 0370
|
||||
};
|
||||
|
||||
|
@ -95,6 +95,7 @@ bool32 isutf8(const void *data, size_t size) {
|
|||
}
|
||||
// fallthrough
|
||||
case 3:
|
||||
case_utf8_3:
|
||||
if (p + 2 <= e && //
|
||||
(p[0] & 0300) == 0200 && //
|
||||
(p[1] & 0300) == 0200) { //
|
||||
|
@ -104,11 +105,17 @@ bool32 isutf8(const void *data, size_t size) {
|
|||
return false; // missing cont
|
||||
}
|
||||
case 4:
|
||||
if (p < e && (*p & 040)) {
|
||||
return false; // utf-16 surrogate
|
||||
}
|
||||
goto case_utf8_3;
|
||||
case 5:
|
||||
if (p < e && (*p & 0377) < 0220) {
|
||||
return false; // overlong
|
||||
}
|
||||
// fallthrough
|
||||
case 5:
|
||||
case 6:
|
||||
case_utf8_4:
|
||||
if (p + 3 <= e && //
|
||||
(((uint32_t)(p[+2] & 0377) << 030 | //
|
||||
(uint32_t)(p[+1] & 0377) << 020 | //
|
||||
|
@ -120,6 +127,11 @@ bool32 isutf8(const void *data, size_t size) {
|
|||
} else {
|
||||
return false; // missing cont
|
||||
}
|
||||
case 7:
|
||||
if (p < e && (*p & 0x3F) > 0xF) {
|
||||
return false; // over limit
|
||||
}
|
||||
goto case_utf8_4;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
#define COSMOPOLITAN_LIBC_THREAD_THREADS_H_
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#if !defined(__cplusplus) && \
|
||||
(!(defined(__GNUC__) && __GNUC__ >= 13) || \
|
||||
!(defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L))
|
||||
#define thread_local _Thread_local
|
||||
#endif
|
||||
|
||||
#define TSS_DTOR_ITERATIONS 4
|
||||
|
||||
enum {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
│ │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/tinymath/arm.internal.h"
|
||||
|
||||
#if WANT_ERRNO
|
||||
|
@ -45,6 +46,7 @@ with_errnof (float y, int e)
|
|||
dontinline static float
|
||||
xflowf (uint32_t sign, float y)
|
||||
{
|
||||
unleaf();
|
||||
y = eval_as_float (opt_barrier_float (sign ? -y : y) * y);
|
||||
return with_errnof (y, ERANGE);
|
||||
}
|
||||
|
@ -74,6 +76,7 @@ __math_oflowf (uint32_t sign)
|
|||
float
|
||||
__math_divzerof (uint32_t sign)
|
||||
{
|
||||
unleaf();
|
||||
float y = opt_barrier_float (sign ? -1.0f : 1.0f) / 0.0f;
|
||||
return with_errnof (y, ERANGE);
|
||||
}
|
||||
|
@ -81,6 +84,7 @@ __math_divzerof (uint32_t sign)
|
|||
dontinstrument float
|
||||
__math_invalidf (float x)
|
||||
{
|
||||
unleaf();
|
||||
float y = (x - x) / (x - x);
|
||||
return isnan (x) ? y : with_errnof (y, EDOM);
|
||||
}
|
||||
|
|
|
@ -20,15 +20,19 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
int pipefd[2];
|
||||
int stdoutBack;
|
||||
int allowMask;
|
||||
|
||||
void SetUpOnce(void) {
|
||||
testlib_enable_tmp_setup_teardown();
|
||||
// qemu-aarch64 defines o_largefile wrong
|
||||
allowMask = ~(O_LARGEFILE | 0x00008000);
|
||||
}
|
||||
|
||||
void CaptureStdout(void) {
|
||||
|
@ -46,8 +50,7 @@ void RestoreStdout(void) {
|
|||
|
||||
TEST(specialfile, devNull) {
|
||||
ASSERT_SYS(0, 3, creat("/dev/null", 0644));
|
||||
// qemu-aarch64 defines o_largefile wrong
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & ~(O_LARGEFILE | 0x00008000));
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 2, write(3, "hi", 2));
|
||||
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 0));
|
||||
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 2));
|
||||
|
@ -64,12 +67,51 @@ TEST(specialfile, devNull) {
|
|||
TEST(specialfile, devNullRead) {
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, open("/dev/null", O_RDONLY));
|
||||
// qemu-aarch64 defines o_largefile wrong
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & ~(O_LARGEFILE | 0x00008000));
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 0, read(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devRandomRead) {
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, open("/dev/random", O_RDONLY));
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_NE(0, memcmp(buf, " ", 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devUrandomRead) {
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, open("/dev/urandom", O_RDONLY));
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_NE(0, memcmp(buf, " ", 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devRandomWrite_fails_on_nt) {
|
||||
if (!IsWindows()) {
|
||||
return;
|
||||
}
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("/dev/random", 0644));
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(EPERM, -1, write(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devUrandomWrite_fails_on_nt) {
|
||||
if (!IsWindows()) {
|
||||
return;
|
||||
}
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("/dev/urandom", 0644));
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(EPERM, -1, write(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devStdout) {
|
||||
char buf[8] = {8};
|
||||
CaptureStdout();
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
|
||||
__static_yoink("zipos");
|
||||
__static_yoink("libc/testlib/hyperion.txt");
|
||||
__static_yoink("_Cz_inflate");
|
||||
__static_yoink("_Cz_inflateInit2");
|
||||
__static_yoink("_Cz_inflateEnd");
|
||||
__static_yoink("inflate");
|
||||
__static_yoink("inflateInit2");
|
||||
__static_yoink("inflateEnd");
|
||||
|
||||
void *Worker(void *arg) {
|
||||
int i, fd;
|
||||
|
|
|
@ -93,3 +93,44 @@ TEST(recvfrom, test) {
|
|||
EXPECT_SYS(0, 0, close(client1));
|
||||
WAIT(exit, 0);
|
||||
}
|
||||
|
||||
// server listens for connections, accepts a connection, and sends data
|
||||
// client connects to server recieves with recvfrom and verifies addrsize
|
||||
// is 0 as the sender info isn't available on connection sockets.
|
||||
TEST(recvfrom, tcp) {
|
||||
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in server = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl(0x7f000001),
|
||||
};
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&server, sizeof(server)));
|
||||
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&server, &addrsize));
|
||||
ASSERT_SYS(0, 0, listen(3, 5));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
SPAWN(fork);
|
||||
struct sockaddr_in data, addr;
|
||||
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&server, sizeof(server)));
|
||||
ASSERT_SYS(
|
||||
0, sizeof(data),
|
||||
recvfrom(3, &data, sizeof(data), 0, (struct sockaddr *)&addr, &addrsize));
|
||||
ASSERT_EQ(0, addrsize);
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
PARENT();
|
||||
int client;
|
||||
struct sockaddr client_sockaddr;
|
||||
uint32_t sockaddr_size = sizeof(client_sockaddr);
|
||||
ASSERT_NE(-1, (client = accept(3, &client_sockaddr, &sockaddr_size)));
|
||||
ASSERT_SYS(0, sizeof(client_sockaddr),
|
||||
sendto(client, &client_sockaddr, sizeof(client_sockaddr), 0,
|
||||
(struct sockaddr *)&server, sizeof(server)));
|
||||
EXPECT_SYS(0, 0, close(client));
|
||||
WAIT(exit, 0);
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
|
138
test/libc/stdio/fgets_interrupt_test.c
Normal file
138
test/libc/stdio/fgets_interrupt_test.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Cadence Ember │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/isystem/errno.h"
|
||||
#include "libc/isystem/sched.h"
|
||||
#include "libc/isystem/signal.h"
|
||||
#include "libc/isystem/stddef.h"
|
||||
#include "libc/isystem/unistd.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#define MY_TEST_STRING_1 "He"
|
||||
#define MY_TEST_STRING_2 "llo world!"
|
||||
|
||||
char buf[20] = {0};
|
||||
int pipes[2];
|
||||
int pid;
|
||||
int got_sigusr1 = 0;
|
||||
|
||||
// -=- these get called for each test ------------------------------------------
|
||||
|
||||
void sigusr1_handler(int) {
|
||||
got_sigusr1 = 1;
|
||||
}
|
||||
|
||||
void write_pipe(int send_signal_before_end) {
|
||||
// Set up pipe for writing
|
||||
close(pipes[0]);
|
||||
FILE *stream = fdopen(pipes[1], "w");
|
||||
|
||||
// Start writing the first part of the stream
|
||||
fputs(MY_TEST_STRING_1, stream);
|
||||
|
||||
// Send SIGUSR1 to parent (if we're currently testing that)
|
||||
if (send_signal_before_end) {
|
||||
kill(getppid(), SIGUSR1);
|
||||
}
|
||||
|
||||
// Send rest of stream
|
||||
fputs(MY_TEST_STRING_2, stream);
|
||||
// Close stream - this will cause the parent's fgets to end
|
||||
fclose(stream);
|
||||
}
|
||||
|
||||
void read_pipe() {
|
||||
// Set up pipe for reading
|
||||
close(pipes[1]);
|
||||
FILE *stream = fdopen(pipes[0], "r");
|
||||
|
||||
// Read with fgets
|
||||
fgets(buf, 20, stream);
|
||||
|
||||
// Tidy up
|
||||
fclose(stream);
|
||||
}
|
||||
|
||||
// -=- these set up the tests --------------------------------------------------
|
||||
|
||||
void SetUpOnce(void) {
|
||||
cpu_set_t set;
|
||||
CPU_ZERO(&set);
|
||||
CPU_SET(1, &set);
|
||||
if (sched_setaffinity(0, sizeof set, &set) == -1) {
|
||||
perror("sched_setaffinity");
|
||||
fprintf(stderr, "single core affinity is needed for test reliability\n");
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_signal_and_pipe(uint64_t sa_flags) {
|
||||
// Set up SIGUSR1 handler
|
||||
struct sigaction sa = {.sa_handler = sigusr1_handler, .sa_flags = sa_flags};
|
||||
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
|
||||
perror("sigaction");
|
||||
_exit(1);
|
||||
}
|
||||
got_sigusr1 = 0;
|
||||
|
||||
// Set up pipe between parent and child
|
||||
if (pipe(pipes) == -1) {
|
||||
perror("pipe");
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// -=- these are the tests -----------------------------------------------------
|
||||
|
||||
TEST(fgets_eintr, testThatFgetsReadsFromPipeNormally) {
|
||||
setup_signal_and_pipe(0); // 0 = no SA_RESTART
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
write_pipe(0); // 0 = no signal
|
||||
_exit(0);
|
||||
}
|
||||
read_pipe();
|
||||
EXPECT_STREQ(MY_TEST_STRING_1 MY_TEST_STRING_2, buf);
|
||||
}
|
||||
|
||||
TEST(fgets_eintr, testThatTheSignalInterruptsFgets) {
|
||||
setup_signal_and_pipe(0); // 0 = no SA_RESTART
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
write_pipe(1); // 1 = signal
|
||||
_exit(0);
|
||||
}
|
||||
read_pipe();
|
||||
EXPECT_STRNE(MY_TEST_STRING_1 MY_TEST_STRING_2, buf);
|
||||
EXPECT_EQ(EINTR, errno);
|
||||
EXPECT_EQ(1, got_sigusr1);
|
||||
}
|
||||
|
||||
TEST(fgets_eintr, testThatFgetsRestartsWhenSaRestartIsSet) {
|
||||
setup_signal_and_pipe(SA_RESTART); // SA_RESTART
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
write_pipe(1); // 1 = signal
|
||||
_exit(0);
|
||||
}
|
||||
read_pipe();
|
||||
EXPECT_STREQ(MY_TEST_STRING_1 MY_TEST_STRING_2, buf);
|
||||
EXPECT_NE(EINTR, errno);
|
||||
EXPECT_EQ(1, got_sigusr1);
|
||||
}
|
|
@ -39,6 +39,9 @@ TEST(isutf8, good) {
|
|||
"剑号巨阙 珠称夜光 果珍李柰 菜重芥姜 海咸河淡 鳞潜羽翔"
|
||||
"龙师火帝 鸟官人皇 始制文字 乃服衣裳 推位让国 有虞陶唐",
|
||||
-1));
|
||||
EXPECT_TRUE(isutf8("\xf4\x8f\xbf\xbf", -1));
|
||||
EXPECT_TRUE(isutf8("\xed\x9f\xbf", -1));
|
||||
EXPECT_TRUE(isutf8("\xee\x80\x80", -1));
|
||||
}
|
||||
|
||||
TEST(isutf8, bad) {
|
||||
|
@ -46,6 +49,9 @@ TEST(isutf8, bad) {
|
|||
ASSERT_FALSE(isutf8("\200\300", -1)); // latin1 c1 control code
|
||||
ASSERT_FALSE(isutf8("\300\300", -1)); // missing continuation
|
||||
ASSERT_FALSE(isutf8("\377\200\200\200\200", -1)); // thompson-pike varint
|
||||
ASSERT_FALSE(isutf8("\xf4\x90\x80\x80", -1)); // over limit
|
||||
ASSERT_FALSE(isutf8("\xed\xa0\x80", -1));
|
||||
ASSERT_FALSE(isutf8("\xed\xbf\xbf", -1)); // surrogate pairs
|
||||
}
|
||||
|
||||
TEST(isutf8, oob) {
|
||||
|
|
|
@ -16,7 +16,8 @@ TEST_MATH_DIRECTDEPS = \
|
|||
LIBC_RUNTIME \
|
||||
LIBC_SYSV \
|
||||
LIBC_TINYMATH \
|
||||
THIRD_PARTY_COMPILER_RT
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
THIRD_PARTY_OPENMP
|
||||
|
||||
TEST_MATH_DEPS := \
|
||||
$(call uniq,$(foreach x,$(TEST_MATH_DIRECTDEPS),$($(x))))
|
||||
|
@ -33,7 +34,7 @@ o/$(MODE)/test/math/%.dbg: \
|
|||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
$(TEST_MATH_OBJS): private CFLAGS += -fno-builtin
|
||||
$(TEST_MATH_OBJS): private CFLAGS += -fno-builtin -fopenmp
|
||||
|
||||
.PHONY: o/$(MODE)/test/math
|
||||
o/$(MODE)/test/math: \
|
||||
|
|
55
test/math/erff_test.c
Normal file
55
test/math/erff_test.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_ERROR_ULP 1
|
||||
#define GOTTA_TEST_THEM_ALL 0
|
||||
|
||||
unsigned rand32(void) {
|
||||
/* Knuth, D.E., "The Art of Computer Programming," Vol 2,
|
||||
Seminumerical Algorithms, Third Edition, Addison-Wesley, 1998,
|
||||
p. 106 (line 26) & p. 108 */
|
||||
static unsigned long long lcg = 1;
|
||||
lcg *= 6364136223846793005;
|
||||
lcg += 1442695040888963407;
|
||||
return lcg >> 32;
|
||||
}
|
||||
|
||||
int main() {
|
||||
#if GOTTA_TEST_THEM_ALL
|
||||
#pragma omp parallel for
|
||||
for (long i = 0; i < 4294967296; ++i) {
|
||||
#else
|
||||
for (long r = 0; r < 100000; ++r) {
|
||||
unsigned i = rand32();
|
||||
#endif
|
||||
union {
|
||||
float f;
|
||||
unsigned i;
|
||||
} x, a, b;
|
||||
x.i = i;
|
||||
a.f = erf(x.f);
|
||||
b.f = erff(x.f);
|
||||
long ai = a.i;
|
||||
long bi = b.i;
|
||||
long e = bi - ai;
|
||||
if (e < 0)
|
||||
e = -e;
|
||||
if (e > MAX_ERROR_ULP)
|
||||
exit(99);
|
||||
}
|
||||
}
|
87
test/math/expf_test.c
Normal file
87
test/math/expf_test.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_ERROR_ULP 1
|
||||
#define GOTTA_TEST_THEM_ALL 0
|
||||
|
||||
float ident(float x) {
|
||||
return x;
|
||||
}
|
||||
float (*veil)(float) = ident;
|
||||
|
||||
unsigned rand32(void) {
|
||||
/* Knuth, D.E., "The Art of Computer Programming," Vol 2,
|
||||
Seminumerical Algorithms, Third Edition, Addison-Wesley, 1998,
|
||||
p. 106 (line 26) & p. 108 */
|
||||
static unsigned long long lcg = 1;
|
||||
lcg *= 6364136223846793005;
|
||||
lcg += 1442695040888963407;
|
||||
return lcg >> 32;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
// specials
|
||||
if (expf(veil(0.f)) != 1.f)
|
||||
return 1;
|
||||
if (!isnan(expf(veil(NAN))))
|
||||
return 2;
|
||||
if (expf(veil(-INFINITY)) != 0.f)
|
||||
return 3;
|
||||
if (expf(veil(INFINITY)) != INFINITY)
|
||||
return 4;
|
||||
if (errno)
|
||||
return 5;
|
||||
|
||||
// overflow
|
||||
if (expf(veil(88.8)) != HUGE_VALF)
|
||||
return 6;
|
||||
if (errno != ERANGE)
|
||||
return 7;
|
||||
errno = 0;
|
||||
|
||||
// underflow
|
||||
if (expf(veil(-104)) != 0.)
|
||||
return 8;
|
||||
if (errno != ERANGE)
|
||||
return 9;
|
||||
|
||||
#if GOTTA_TEST_THEM_ALL
|
||||
#pragma omp parallel for
|
||||
for (long i = 0; i < 4294967296; ++i) {
|
||||
#else
|
||||
for (long r = 0; r < 100000; ++r) {
|
||||
unsigned i = rand32();
|
||||
#endif
|
||||
union {
|
||||
float f;
|
||||
unsigned i;
|
||||
} x, a, b;
|
||||
x.i = i;
|
||||
a.f = exp(x.f);
|
||||
b.f = expf(x.f);
|
||||
long ai = a.i;
|
||||
long bi = b.i;
|
||||
long e = bi - ai;
|
||||
if (e < 0)
|
||||
e = -e;
|
||||
if (e > MAX_ERROR_ULP)
|
||||
exit(99);
|
||||
}
|
||||
}
|
1
third_party/awk/b.c
vendored
1
third_party/awk/b.c
vendored
|
@ -1463,6 +1463,7 @@ rescan:
|
|||
}
|
||||
break;
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
int cgoto(fa *f, int s, int c)
|
||||
|
|
6
third_party/musl/pwd.c
vendored
6
third_party/musl/pwd.c
vendored
|
@ -45,9 +45,9 @@ __static_yoink("musl_libc_notice");
|
|||
// something as substantive as this library, then we shall assume the
|
||||
// application is meaty enough to benefit from the performance of the
|
||||
// chromium zlib library (costs ~40kb binary) versus just having puff
|
||||
__static_yoink("_Cz_inflateInit2");
|
||||
__static_yoink("_Cz_inflate");
|
||||
__static_yoink("_Cz_inflateEnd");
|
||||
__static_yoink("inflateInit2");
|
||||
__static_yoink("inflate");
|
||||
__static_yoink("inflateEnd");
|
||||
#endif
|
||||
|
||||
static char *
|
||||
|
|
2
third_party/zip/crc32.h
vendored
2
third_party/zip/crc32.h
vendored
|
@ -31,7 +31,7 @@
|
|||
#ifndef USE_ZLIB
|
||||
ZCONST ulg near *get_crc_table OF((void));
|
||||
#endif
|
||||
#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))
|
||||
#if (1 || defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))
|
||||
# ifdef IZ_CRC_BE_OPTIMIZ
|
||||
# undef IZ_CRC_BE_OPTIMIZ
|
||||
# endif
|
||||
|
|
10
third_party/zip/zipfile.c
vendored
10
third_party/zip/zipfile.c
vendored
|
@ -72,7 +72,7 @@
|
|||
#include "libc/nt/winsock.h"
|
||||
#endif
|
||||
|
||||
unsigned _Cz_crc32(unsigned crc, const unsigned char *buf, unsigned len);
|
||||
unsigned crc32(unsigned crc, const unsigned char *buf, unsigned len);
|
||||
|
||||
/*
|
||||
* XXX start of zipfile.h
|
||||
|
@ -867,7 +867,7 @@ local void read_Unicode_Path_entry(pZipListEntry)
|
|||
}
|
||||
strcpy(iname, pZipListEntry->iname);
|
||||
|
||||
chksum = _Cz_crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
chksum = crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
|
||||
free(iname);
|
||||
|
||||
|
@ -972,7 +972,7 @@ local void read_Unicode_Path_local_entry(pZipListEntry)
|
|||
}
|
||||
strcpy(iname, pZipListEntry->iname);
|
||||
|
||||
chksum = _Cz_crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
chksum = crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
|
||||
free(iname);
|
||||
|
||||
|
@ -1558,7 +1558,7 @@ local int add_Unicode_Path_local_extra_field(pZEntry)
|
|||
# define inameLocal (pZEntry->iname)
|
||||
#endif
|
||||
|
||||
chksum = _Cz_crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
chksum = crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
|
||||
#ifdef WIN32_OEM
|
||||
free(inameLocal);
|
||||
|
@ -1685,7 +1685,7 @@ local int add_Unicode_Path_cen_extra_field(pZEntry)
|
|||
# define inameLocal (pZEntry->iname)
|
||||
#endif
|
||||
|
||||
chksum = _Cz_crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
chksum = crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
|
||||
#ifdef WIN32_OEM
|
||||
free(inameLocal);
|
||||
|
|
4
third_party/zlib/zconf.h
vendored
4
third_party/zlib/zconf.h
vendored
|
@ -13,6 +13,7 @@
|
|||
|
||||
#define z_const const
|
||||
|
||||
#if 0
|
||||
#define Z_COSMO_PREFIX_SET
|
||||
|
||||
#define Bytef _Cz_Bytef
|
||||
|
@ -162,6 +163,9 @@
|
|||
#define zlibCompileFlags _Cz_zlibCompileFlags
|
||||
#define zlibVersion _Cz_zlibVersion
|
||||
|
||||
#pragma message "zconf is included, so zlibVersion should be renamed"
|
||||
|
||||
#endif
|
||||
|
||||
typedef unsigned char Byte;
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
(runs (format "o/$m/%s%s V=5 TESTARGS=-b" name runsuffix))
|
||||
(buns (format "o/$m/test/%s_test%s V=5 TESTARGS=-b" name runsuffix)))
|
||||
(cond ((not (member ext '("c" "cc" "cpp" "s" "S" "rl" "f" "cu")))
|
||||
(format "m=%s; make -j32 MODE=$m o/$m/%s"
|
||||
(format "m=%s; make -j96 MODE=$m o/$m/%s"
|
||||
mode
|
||||
(directory-file-name
|
||||
(or (file-name-directory
|
||||
|
@ -226,7 +226,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s"
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
,(concat "make -j96 $f MODE=$m")
|
||||
"scp $f $f.dbg win10:; ssh win10 ./%s"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((eq kind 'run-xnu)
|
||||
|
@ -234,19 +234,19 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s"
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
,(concat "make -j96 $f MODE=$m")
|
||||
"scp $f $f.dbg xnu:"
|
||||
"ssh xnu ./%s"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((and (equal suffix "")
|
||||
(cosmo-contains "_test." (buffer-file-name)))
|
||||
(format "m=%s; make -j32 MODE=$m %s"
|
||||
(format "m=%s; make -j96 MODE=$m %s"
|
||||
mode runs))
|
||||
((and (equal suffix "")
|
||||
(file-exists-p (format "%s" buddy)))
|
||||
(format (cosmo-join
|
||||
" && "
|
||||
'("m=%s; n=%s; make -j32 o/$m/$n%s.o MODE=$m"
|
||||
'("m=%s; n=%s; make -j96 o/$m/$n%s.o MODE=$m"
|
||||
;; "bloat o/$m/%s.o | head"
|
||||
;; "nm -C --size o/$m/%s.o | sort -r"
|
||||
"echo"
|
||||
|
@ -258,11 +258,11 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s"
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
,(concat "make -j96 $f MODE=$m")
|
||||
"build/run ./$f"))
|
||||
mode name))
|
||||
((eq kind 'test)
|
||||
(format `"m=%s; f=o/$m/%s.ok && make -j32 $f MODE=$m" mode name))
|
||||
(format `"m=%s; f=o/$m/%s.ok && make -j96 $f MODE=$m" mode name))
|
||||
((and (file-regular-p this)
|
||||
(file-executable-p this))
|
||||
(format "build/run ./%s" file))
|
||||
|
@ -271,7 +271,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s%s.o"
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
,(concat "make -j96 $f MODE=$m")
|
||||
;; "nm -C --size $f | sort -r"
|
||||
"echo"
|
||||
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
|
||||
|
@ -481,7 +481,7 @@
|
|||
(error "don't know how to show assembly for non c/c++ source file"))
|
||||
(let* ((default-directory root)
|
||||
(compile-command
|
||||
(format "make %s -j32 MODE=%s %s %s"
|
||||
(format "make %s -j96 MODE=%s %s %s"
|
||||
(or extra-make-flags "") mode asm-gcc asm-clang)))
|
||||
(save-buffer)
|
||||
(set-visited-file-modtime (current-time))
|
||||
|
@ -641,11 +641,11 @@
|
|||
(compile (format "sh -c %s" file)))
|
||||
((eq major-mode 'lua-mode)
|
||||
(let* ((mode (cosmo--make-mode arg)))
|
||||
(compile (format "make -j32 MODE=%s o/%s/tool/net/redbean && build/run o/%s/tool/net/redbean -i %s" mode mode mode file))))
|
||||
(compile (format "make -j96 MODE=%s o/%s/tool/net/redbean && build/run o/%s/tool/net/redbean -i %s" mode mode mode file))))
|
||||
((and (eq major-mode 'python-mode)
|
||||
(cosmo-startswith "third_party/python/Lib/test/" file))
|
||||
(let ((mode (cosmo--make-mode arg)))
|
||||
(compile (format "make -j32 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
|
||||
(compile (format "make -j96 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
|
||||
mode mode (file-name-sans-extension file)))))
|
||||
((eq major-mode 'python-mode)
|
||||
(compile (format "python %s" file)))
|
||||
|
|
|
@ -1612,7 +1612,7 @@ FUNCTIONS
|
|||
called from `.init.lua`. This function is not available in
|
||||
unsecure mode.
|
||||
|
||||
ProgramSslRequired(mandatory:str)
|
||||
ProgramSslRequired(mandatory:bool)
|
||||
Enables the blocking of HTTP so that all inbound clients and
|
||||
must use the TLS transport layer. This has the same effect as
|
||||
the `-J` flag. Fetch() is still allowed to make outbound HTTP
|
||||
|
|
Loading…
Reference in a new issue