diff --git a/Makefile b/Makefile
index f9e65d1b2..24d55da4f 100644
--- a/Makefile
+++ b/Makefile
@@ -61,7 +61,6 @@
SHELL = build/bootstrap/cocmd.com
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win7 win10 xnu
-#SANITY := $(shell build/sanitycheck $$PPID)
.SUFFIXES:
.DELETE_ON_ERROR:
diff --git a/README.md b/README.md
index 19cf9ed5c..fecec2159 100644
--- a/README.md
+++ b/README.md
@@ -42,9 +42,9 @@ bash -c './hello.com' # zsh/fish workaround (we patched them in 2021)
Since we used the `ape-no-modify-self.o` bootloader (rather than
`ape.o`) your executable will not modify itself when it's run. What
-it'll instead do, is extract a 4kb program to `${TMPDIR:-/tmp}` that
-maps your program into memory without needing to copy it. It's possible
-to install the APE loader systemwide as follows.
+it'll instead do, is extract a 4kb program to `${TMPDIR:-${HOME:-.}}`
+that maps your program into memory without needing to copy it. It's
+possible to install the APE loader systemwide as follows.
```sh
# (1) linux systems that want binfmt_misc
diff --git a/build/definitions.mk b/build/definitions.mk
index 6274df0b3..73f35cbc1 100644
--- a/build/definitions.mk
+++ b/build/definitions.mk
@@ -63,7 +63,7 @@ PKG = build/bootstrap/package.com
MKDEPS = build/bootstrap/mkdeps.com
ZIPOBJ = build/bootstrap/zipobj.com
MKDIR = build/bootstrap/mkdir.com -p
-COMPILE = build/bootstrap/compile.com -V9 $(QUOTA)
+COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
COMMA := ,
PWD := $(shell build/bootstrap/pwd.com)
diff --git a/libc/assert.h b/libc/assert.h
index 6583800c8..ce6933b2a 100644
--- a/libc/assert.h
+++ b/libc/assert.h
@@ -3,7 +3,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
-void __assert_fail(const char *, const char *, int) hidden wontreturn relegated;
+extern bool __assert_disable;
+void __assert_fail(const char *, const char *, int) hidden relegated;
#ifdef NDEBUG
#define assert(EXPR) ((void)0)
diff --git a/libc/calls/clock_gettime-nt.c b/libc/calls/clock_gettime-nt.c
index 50dcb25de..4330bf588 100644
--- a/libc/calls/clock_gettime-nt.c
+++ b/libc/calls/clock_gettime-nt.c
@@ -16,15 +16,27 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/likely.h"
+#include "libc/calls/internal.h"
+#include "libc/calls/struct/timespec.h"
#include "libc/fmt/conv.h"
+#include "libc/intrin/kprintf.h"
+#include "libc/intrin/spinlock.h"
#include "libc/nexgen32e/rdtsc.h"
+#include "libc/nexgen32e/threaded.h"
+#include "libc/nexgen32e/x86feature.h"
+#include "libc/nt/struct/filetime.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/errfuns.h"
+#include "libc/time/clockstonanos.internal.h"
textwindows int sys_clock_gettime_nt(int clockid, struct timespec *ts) {
- int64_t ms;
+ uint64_t nanos;
+ static bool once;
+ static char lock;
struct timespec res;
+ static uint64_t base;
struct NtFileTime ft;
static struct timespec mono;
if (!ts) return efault();
@@ -32,21 +44,21 @@ textwindows int sys_clock_gettime_nt(int clockid, struct timespec *ts) {
GetSystemTimeAsFileTime(&ft);
*ts = FileTimeToTimeSpec(ft);
return 0;
- } else if (clockid == CLOCK_MONOTONIC || clockid == CLOCK_MONOTONIC_RAW) {
- ms = GetTickCount64();
- res.tv_sec = ms / 1000;
- res.tv_nsec = ms % 1000 * 1000000;
- res.tv_nsec += rdtsc() / 3 % 1000000000;
- if (res.tv_nsec > 1000000000) {
- res.tv_nsec -= 1000000000;
- res.tv_sec += 1;
- }
- if (res.tv_sec > mono.tv_sec ||
- (res.tv_sec == mono.tv_sec && res.tv_nsec > mono.tv_nsec)) {
- mono = res;
- } else {
- res = mono;
+ } else if ((clockid == CLOCK_MONOTONIC || clockid == CLOCK_MONOTONIC_RAW) &&
+ X86_HAVE(INVTSC)) {
+ // this routine stops being monotonic after 194 years of uptime
+ if (__threaded) _spinlock(&lock);
+ if (UNLIKELY(!once)) {
+ GetSystemTimeAsFileTime(&ft);
+ mono = FileTimeToTimeSpec(ft);
+ base = rdtsc();
+ once = true;
}
+ nanos = ClocksToNanos(rdtsc(), base);
+ res = mono;
+ res.tv_sec += nanos / 1000000000;
+ res.tv_nsec += nanos % 1000000000;
+ _spunlock(&lock);
*ts = res;
return 0;
} else {
diff --git a/libc/calls/clock_gettime.c b/libc/calls/clock_gettime.c
index 68e4bcf62..ee8c062ea 100644
--- a/libc/calls/clock_gettime.c
+++ b/libc/calls/clock_gettime.c
@@ -57,7 +57,6 @@
*/
int clock_gettime(int clockid, struct timespec *ts) {
int rc;
- char *buf;
if (IsAsan() && !__asan_is_valid_timespec(ts)) {
rc = efault();
} else {
@@ -65,9 +64,8 @@ int clock_gettime(int clockid, struct timespec *ts) {
}
#if SYSDEBUG
if (!__time_critical) {
- buf = alloca(45);
- STRACE("clock_gettime(%d, [%s]) → %d% m", clockid,
- DescribeTimespec(buf, 45, rc, ts), rc);
+ STRACE("clock_gettime(%d, [%s]) → %d% m", clockid, DescribeTimespec(rc, ts),
+ rc);
}
#endif
return rc;
diff --git a/libc/calls/directmap.c b/libc/calls/directmap.c
index 502f0fbd4..cafcf48d1 100644
--- a/libc/calls/directmap.c
+++ b/libc/calls/directmap.c
@@ -16,10 +16,13 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/likely.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
+#include "libc/intrin/kprintf.h"
+#include "libc/intrin/spinlock.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
@@ -38,7 +41,6 @@
*/
struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
int64_t off) {
- /* asan runtime depends on this function */
struct DirectMap d;
if (!IsWindows() && !IsMetal()) {
d.addr = __sys_mmap(addr, size, prot, flags, fd, off, off);
diff --git a/libc/calls/faccessat.c b/libc/calls/faccessat.c
index e682d4f83..875b3b885 100644
--- a/libc/calls/faccessat.c
+++ b/libc/calls/faccessat.c
@@ -41,7 +41,6 @@
*/
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
int rc;
- char buf[12];
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (weaken(__zipos_notat) &&
@@ -52,7 +51,7 @@ int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
} else {
rc = sys_faccessat_nt(dirfd, path, mode, flags);
}
- STRACE("faccessat(%s, %#s, %#o, %#x) → %d% m", DescribeDirfd(buf, dirfd),
- path, mode, flags, rc);
+ STRACE("faccessat(%s, %#s, %#o, %#x) → %d% m", DescribeDirfd(dirfd), path,
+ mode, flags, rc);
return rc;
}
diff --git a/libc/calls/fchmodat.c b/libc/calls/fchmodat.c
index 5ea267d00..5c27909ff 100644
--- a/libc/calls/fchmodat.c
+++ b/libc/calls/fchmodat.c
@@ -43,7 +43,6 @@
*/
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
int rc;
- char buf[12];
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
@@ -53,7 +52,7 @@ int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
} else {
rc = sys_fchmodat_nt(dirfd, path, mode, flags);
}
- STRACE("fchmodat(%s, %#s, %#o, %d) → %d% m", DescribeDirfd(buf, dirfd), path,
- mode, flags, rc);
+ STRACE("fchmodat(%s, %#s, %#o, %d) → %d% m", DescribeDirfd(dirfd), path, mode,
+ flags, rc);
return rc;
}
diff --git a/libc/calls/fchownat.c b/libc/calls/fchownat.c
index bf743aa5c..aa774759d 100644
--- a/libc/calls/fchownat.c
+++ b/libc/calls/fchownat.c
@@ -42,7 +42,6 @@
int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
int flags) {
int rc;
- char sb[12];
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
@@ -50,7 +49,7 @@ int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
} else {
rc = sys_fchownat(dirfd, path, uid, gid, flags);
}
- STRACE("fchownat(%s, %#s, %d, %d, %#b) → %d% m", DescribeDirfd(sb, dirfd),
- path, uid, gid, flags, rc);
+ STRACE("fchownat(%s, %#s, %d, %d, %#b) → %d% m", DescribeDirfd(dirfd), path,
+ uid, gid, flags, rc);
return rc;
}
diff --git a/libc/calls/fstatat.c b/libc/calls/fstatat.c
index b59ca4639..825845ad5 100644
--- a/libc/calls/fstatat.c
+++ b/libc/calls/fstatat.c
@@ -28,13 +28,13 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
+#include "libc/mem/alloca.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
-static inline const char *__strace_fstatat_flags(int flags) {
- static char buf[12];
+static inline const char *__strace_fstatat_flags(char buf[12], int flags) {
if (flags == AT_SYMLINK_NOFOLLOW) return "AT_SYMLINK_NOFOLLOW";
FormatInt32(buf, flags);
return buf;
@@ -55,7 +55,6 @@ static inline const char *__strace_fstatat_flags(int flags) {
int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
/* execve() depends on this */
int rc;
- char buf[12];
struct ZiposUri zipname;
if (__isfdkind(dirfd, kFdZip)) {
STRACE("zipos dirfd not supported yet");
@@ -72,7 +71,7 @@ int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
} else {
rc = sys_fstatat_nt(dirfd, path, st, flags);
}
- STRACE("fstatat(%s, %#s, [%s], %s) → %d% m", DescribeDirfd(buf, dirfd), path,
- DescribeStat(rc, st), __strace_fstatat_flags(flags), rc);
+ STRACE("fstatat(%s, %#s, [%s], %s) → %d% m", DescribeDirfd(dirfd), path,
+ DescribeStat(rc, st), __strace_fstatat_flags(alloca(12), flags), rc);
return rc;
}
diff --git a/libc/calls/getrlimit.c b/libc/calls/getrlimit.c
index cb0c2ee61..ada1a7a04 100644
--- a/libc/calls/getrlimit.c
+++ b/libc/calls/getrlimit.c
@@ -35,7 +35,6 @@
*/
int getrlimit(int resource, struct rlimit *rlim) {
int rc;
- char buf[64];
if (resource == 127) {
rc = einval();
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
@@ -50,6 +49,6 @@ int getrlimit(int resource, struct rlimit *rlim) {
rc = einval();
}
STRACE("getrlimit(%s, [%s]) → %d% m", DescribeRlimitName(resource),
- DescribeRlimit(buf, sizeof(buf), rc, rlim), rc);
+ DescribeRlimit(rc, rlim), rc);
return rc;
}
diff --git a/libc/calls/ioctl_tcsets-nt.c b/libc/calls/ioctl_tcsets-nt.c
index 126b57d2f..a9219933f 100644
--- a/libc/calls/ioctl_tcsets-nt.c
+++ b/libc/calls/ioctl_tcsets-nt.c
@@ -63,7 +63,7 @@ textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
}
ok = SetConsoleMode(in, inmode);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", in,
- DescribeNtConsoleModeInputFlags(inmode), ok);
+ DescribeNtConsoleInFlags(inmode), ok);
}
if (outok) {
@@ -77,7 +77,7 @@ textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
}
ok = SetConsoleMode(out, outmode);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", out,
- DescribeNtConsoleModeOutputFlags(outmode), ok);
+ DescribeNtConsoleOutFlags(outmode), ok);
}
return 0;
diff --git a/libc/calls/linkat.c b/libc/calls/linkat.c
index 4f02f6286..ed64b0706 100644
--- a/libc/calls/linkat.c
+++ b/libc/calls/linkat.c
@@ -40,7 +40,6 @@
int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
int flags) {
int rc;
- char buf[2][12];
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
rc = efault();
@@ -53,8 +52,7 @@ int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
} else {
rc = sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
}
- STRACE("linkat(%s, %#s, %s, %#s, %#b) → %d% m",
- DescribeDirfd(buf[0], olddirfd), oldpath,
- DescribeDirfd(buf[1], newdirfd), newpath, flags, rc);
+ STRACE("linkat(%s, %#s, %s, %#s, %#b) → %d% m", DescribeDirfd(olddirfd),
+ oldpath, DescribeDirfd(newdirfd), newpath, flags, rc);
return rc;
}
diff --git a/libc/calls/mkdirat.c b/libc/calls/mkdirat.c
index cc42bbeb5..153039b1a 100644
--- a/libc/calls/mkdirat.c
+++ b/libc/calls/mkdirat.c
@@ -42,7 +42,6 @@
*/
int mkdirat(int dirfd, const char *path, unsigned mode) {
int rc;
- char buf[12];
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
@@ -52,7 +51,6 @@ int mkdirat(int dirfd, const char *path, unsigned mode) {
} else {
rc = sys_mkdirat_nt(dirfd, path, mode);
}
- STRACE("mkdirat(%s, %#s, %#o) → %d% m", DescribeDirfd(buf, dirfd), path, mode,
- rc);
+ STRACE("mkdirat(%s, %#s, %#o) → %d% m", DescribeDirfd(dirfd), path, mode, rc);
return rc;
}
diff --git a/libc/calls/munmap-sysv.c b/libc/calls/munmap-sysv.c
index 95b697034..9f4c412ca 100644
--- a/libc/calls/munmap-sysv.c
+++ b/libc/calls/munmap-sysv.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
diff --git a/libc/calls/nanosleep.c b/libc/calls/nanosleep.c
index 4f0e6edc3..153acc2be 100644
--- a/libc/calls/nanosleep.c
+++ b/libc/calls/nanosleep.c
@@ -31,7 +31,6 @@
*/
noinstrument int nanosleep(const struct timespec *req, struct timespec *rem) {
int rc;
- char buf[2][45];
if (!req || (IsAsan() && (!__asan_is_valid_timespec(req) ||
(rem && !__asan_is_valid_timespec(rem))))) {
rc = efault();
@@ -48,9 +47,8 @@ noinstrument int nanosleep(const struct timespec *req, struct timespec *rem) {
rc = sys_nanosleep_nt(req, rem);
}
if (!__time_critical) {
- POLLTRACE("nanosleep(%s, [%s]) → %d% m",
- DescribeTimespec(buf[0], sizeof(buf[0]), rc, req),
- DescribeTimespec(buf[1], sizeof(buf[1]), rc, rem), rc);
+ POLLTRACE("nanosleep(%s, [%s]) → %d% m", DescribeTimespec(rc, req),
+ DescribeTimespec(rc, rem), rc);
}
return rc;
}
diff --git a/libc/calls/now.c b/libc/calls/now.c
index 68fa408af..d04e02c6b 100644
--- a/libc/calls/now.c
+++ b/libc/calls/now.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/initializer.internal.h"
#include "libc/bits/safemacros.internal.h"
@@ -44,10 +45,10 @@ static long double GetTimeSample(void) {
uint64_t tick1, tick2;
long double time1, time2;
sched_yield();
- time1 = dtime(CLOCK_MONOTONIC_FAST);
+ time1 = dtime(CLOCK_REALTIME_FAST);
tick1 = rdtsc();
nanosleep(&(struct timespec){0, 1000000}, NULL);
- time2 = dtime(CLOCK_MONOTONIC_FAST);
+ time2 = dtime(CLOCK_REALTIME_FAST);
tick2 = rdtsc();
return (time2 - time1) * 1e9 / MAX(1, tick2 - tick1);
}
@@ -75,13 +76,13 @@ static long double MeasureNanosPerCycle(void) {
void RefreshTime(void) {
struct Now now;
now.cpn = MeasureNanosPerCycle();
- now.r0 = dtime(CLOCK_REALTIME);
+ now.r0 = dtime(CLOCK_REALTIME_FAST);
now.k0 = rdtsc();
memcpy(&g_now, &now, sizeof(now));
}
static long double nowl_sys(void) {
- return dtime(CLOCK_REALTIME);
+ return dtime(CLOCK_REALTIME_FAST);
}
static long double nowl_art(void) {
@@ -92,7 +93,8 @@ static long double nowl_art(void) {
static long double nowl_vdso(void) {
long double secs;
struct timespec tv;
- __gettime(CLOCK_REALTIME, &tv);
+ assert(__gettime);
+ __gettime(CLOCK_REALTIME_FAST, &tv);
secs = tv.tv_nsec;
secs *= 1 / 1e9L;
secs += tv.tv_sec;
diff --git a/libc/calls/openat.c b/libc/calls/openat.c
index c5a7db199..59ccfb9da 100644
--- a/libc/calls/openat.c
+++ b/libc/calls/openat.c
@@ -24,7 +24,6 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
-#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/log/log.h"
@@ -52,7 +51,6 @@
int openat(int dirfd, const char *file, int flags, ...) {
int rc;
va_list va;
- char buf[12];
unsigned mode;
struct ZiposUri zipname;
va_start(va, flags);
@@ -80,7 +78,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
} else {
rc = efault();
}
- STRACE("openat(%s, %#s, %s, %#o) → %d% m", DescribeDirfd(buf, dirfd), file,
+ STRACE("openat(%s, %#s, %s, %#o) → %d% m", DescribeDirfd(dirfd), file,
DescribeOpenFlags(flags), (flags & (O_CREAT | O_TMPFILE)) ? mode : 0,
rc);
return rc;
diff --git a/libc/calls/poll.c b/libc/calls/poll.c
index 11d50c385..bb40620dc 100644
--- a/libc/calls/poll.c
+++ b/libc/calls/poll.c
@@ -89,13 +89,11 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
(IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd)))) {
kprintf("%p", fds);
} else {
- char flagbuf[2][64];
kprintf("[{");
for (i = 0; i < MIN(5, nfds); ++i) {
- kprintf(
- "%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
- DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
- DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
+ kprintf("%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
+ DescribePollFlags(fds[i].events),
+ DescribePollFlags(fds[i].revents));
}
kprintf("%s}]", i == 5 ? "..." : "");
}
diff --git a/libc/calls/prctl.c b/libc/calls/prctl.c
index 71681273b..44626a8ce 100644
--- a/libc/calls/prctl.c
+++ b/libc/calls/prctl.c
@@ -19,22 +19,10 @@
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/pr.h"
#include "libc/sysv/errfuns.h"
-static const char *DescribePrctlOperation(int x) {
- switch (x) {
- case PR_SET_NO_NEW_PRIVS:
- return "PR_SET_NO_NEW_PRIVS";
- case PR_SET_SECCOMP:
- return "PR_SET_SECCOMP";
- case PR_GET_SECCOMP:
- return "PR_GET_SECCOMP";
- default:
- return "PRCTL_???";
- }
-}
-
/**
* Tunes process on Linux.
*
diff --git a/libc/calls/readlinkat.c b/libc/calls/readlinkat.c
index b06d285e3..58a1a118e 100644
--- a/libc/calls/readlinkat.c
+++ b/libc/calls/readlinkat.c
@@ -45,7 +45,6 @@
* @asyncsignalsafe
*/
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
- char sb[12];
ssize_t bytes;
if ((IsAsan() && !__asan_is_valid(buf, bufsiz)) || (bufsiz && !buf)) {
bytes = efault();
@@ -58,7 +57,7 @@ ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
} else {
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
}
- STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", DescribeDirfd(sb, dirfd), path,
+ STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", DescribeDirfd(dirfd), path,
MAX(0, bytes), buf, bytes);
return bytes;
}
diff --git a/libc/calls/renameat.c b/libc/calls/renameat.c
index f3084e9bc..ce66e3470 100644
--- a/libc/calls/renameat.c
+++ b/libc/calls/renameat.c
@@ -46,7 +46,6 @@
int renameat(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) {
int rc;
- char buf[2][12];
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
rc = efault();
@@ -59,7 +58,7 @@ int renameat(int olddirfd, const char *oldpath, int newdirfd,
} else {
rc = sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath);
}
- STRACE("renameat(%s, %#s, %s, %#s) → %d% m", DescribeDirfd(buf[0], olddirfd),
- oldpath, DescribeDirfd(buf[1], newdirfd), newpath, rc);
+ STRACE("renameat(%s, %#s, %s, %#s) → %d% m", DescribeDirfd(olddirfd), oldpath,
+ DescribeDirfd(newdirfd), newpath, rc);
return rc;
}
diff --git a/libc/calls/samplepids.c b/libc/calls/samplepids.c
index a14712ebb..99b0f9a06 100644
--- a/libc/calls/samplepids.c
+++ b/libc/calls/samplepids.c
@@ -19,6 +19,8 @@
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
+#include "libc/intrin/spinlock.h"
+#include "libc/nexgen32e/threaded.h"
#include "libc/rand/lcg.internal.h"
/**
@@ -33,9 +35,12 @@
textwindows int __sample_pids(int pids[hasatleast 64],
int64_t handles[hasatleast 64],
bool exploratory) {
+ static char lock;
static uint64_t rando = 1;
uint32_t i, j, base, count;
+ if (__threaded) _spinlock(&lock);
base = KnuthLinearCongruentialGenerator(&rando) >> 32;
+ _spunlock(&lock);
for (count = i = 0; i < g_fds.n; ++i) {
j = (base + i) % g_fds.n;
if (g_fds.p[j].kind == kFdProcess && (!exploratory || !g_fds.p[j].zombie)) {
diff --git a/libc/calls/seccomp.c b/libc/calls/seccomp.c
index 9f0e3c0a1..a090d3f61 100644
--- a/libc/calls/seccomp.c
+++ b/libc/calls/seccomp.c
@@ -25,21 +25,6 @@
#include "libc/sysv/consts/pr.h"
#include "libc/sysv/errfuns.h"
-static const char *DescribeSeccompOperation(int x) {
- switch (x) {
- case SECCOMP_SET_MODE_STRICT:
- return "SECCOMP_SET_MODE_STRICT";
- case SECCOMP_SET_MODE_FILTER:
- return "SECCOMP_SET_MODE_FILTER";
- case SECCOMP_GET_ACTION_AVAIL:
- return "SECCOMP_GET_ACTION_AVAIL";
- case SECCOMP_GET_NOTIF_SIZES:
- return "SECCOMP_GET_NOTIF_SIZES";
- default:
- return "SECCOMP_???";
- }
-}
-
/**
* Tunes Linux security policy.
*
diff --git a/libc/calls/setrlimit.c b/libc/calls/setrlimit.c
index 6cd4a3412..2f5e5c81a 100644
--- a/libc/calls/setrlimit.c
+++ b/libc/calls/setrlimit.c
@@ -66,7 +66,6 @@
*/
int setrlimit(int resource, const struct rlimit *rlim) {
int rc;
- char buf[64];
if (resource == 127) {
rc = einval();
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
@@ -84,6 +83,6 @@ int setrlimit(int resource, const struct rlimit *rlim) {
rc = einval();
}
STRACE("setrlimit(%s, %s) → %d% m", DescribeRlimitName(resource),
- DescribeRlimit(buf, sizeof(buf), 0, rlim), rc);
+ DescribeRlimit(0, rlim), rc);
return rc;
}
diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c
index 9ed0f535d..16d285750 100644
--- a/libc/calls/sigaction.c
+++ b/libc/calls/sigaction.c
@@ -444,7 +444,6 @@ static int __sigaction(int sig, const struct sigaction *act,
*/
int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
int rc;
- char buf[2][128];
if (sig == SIGKILL || sig == SIGSTOP) {
rc = einval();
} else {
@@ -452,8 +451,7 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
rc = __sigaction(sig, act, oldact);
__sig_unlock();
}
- STRACE("sigaction(%G, %s, [%s]) → %d% m", sig,
- DescribeSigaction(buf[0], sizeof(buf[0]), 0, act),
- DescribeSigaction(buf[1], sizeof(buf[1]), rc, oldact), rc);
+ STRACE("sigaction(%G, %s, [%s]) → %d% m", sig, DescribeSigaction(0, act),
+ DescribeSigaction(rc, oldact), rc);
return rc;
}
diff --git a/libc/calls/sigaltstack.c b/libc/calls/sigaltstack.c
index d150d27ac..90826fbd9 100644
--- a/libc/calls/sigaltstack.c
+++ b/libc/calls/sigaltstack.c
@@ -80,7 +80,6 @@ int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
int rc;
void *b;
const void *a;
- char buf[2][128];
struct sigaltstack_bsd bsd;
if (IsAsan() && ((old && __asan_check(old, sizeof(*old)).kind) ||
(neu && (__asan_check(neu, sizeof(*neu)).kind ||
@@ -114,8 +113,7 @@ int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
} else {
rc = enosys();
}
- STRACE("sigaltstack(%s, [%s]) → %d% m",
- DescribeSigaltstk(buf[0], sizeof(buf[0]), 0, neu),
- DescribeSigaltstk(buf[0], sizeof(buf[0]), 0, old), rc);
+ STRACE("sigaltstack(%s, [%s]) → %d% m", DescribeSigaltstk(0, neu),
+ DescribeSigaltstk(0, old), rc);
return rc;
}
diff --git a/libc/calls/sigprocmask.c b/libc/calls/sigprocmask.c
index 2b2a3020f..7247e9596 100644
--- a/libc/calls/sigprocmask.c
+++ b/libc/calls/sigprocmask.c
@@ -32,14 +32,6 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
-static const char *DescribeHow(char buf[12], int how) {
- if (how == SIG_BLOCK) return "SIG_BLOCK";
- if (how == SIG_UNBLOCK) return "SIG_UNBLOCK";
- if (how == SIG_SETMASK) return "SIG_SETMASK";
- FormatInt32(buf, how);
- return buf;
-}
-
/**
* Changes signal blocking state of calling thread, e.g.:
*
@@ -58,8 +50,6 @@ static const char *DescribeHow(char buf[12], int how) {
*/
int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
sigset_t old;
- char howbuf[12];
- char buf[2][41];
int res, rc, arg1;
const sigset_t *arg2;
sigemptyset(&old);
@@ -77,8 +67,7 @@ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
if (rc != -1 && opt_out_oldset) {
*opt_out_oldset = old;
}
- STRACE("sigprocmask(%s, %s, [%s]) → %d% m", DescribeHow(howbuf, how),
- DescribeSigset(buf[0], sizeof(buf[0]), 0, opt_set),
- DescribeSigset(buf[1], sizeof(buf[1]), rc, opt_out_oldset), rc);
+ STRACE("sigprocmask(%s, %s, [%s]) → %d% m", DescribeHow(how),
+ DescribeSigset(0, opt_set), DescribeSigset(rc, opt_out_oldset), rc);
return rc;
}
diff --git a/libc/calls/sigsuspend.c b/libc/calls/sigsuspend.c
index e1682df38..978ecb3ad 100644
--- a/libc/calls/sigsuspend.c
+++ b/libc/calls/sigsuspend.c
@@ -44,10 +44,9 @@
*/
int sigsuspend(const sigset_t *ignore) {
int rc;
- char buf[41];
long ms, totoms;
sigset_t save, mask, *arg;
- STRACE("sigsuspend(%s) → ...", DescribeSigset(buf, sizeof(buf), 0, ignore));
+ STRACE("sigsuspend(%s) → ...", DescribeSigset(0, ignore));
if (IsAsan() && ignore && !__asan_is_valid(ignore, sizeof(*ignore))) {
rc = efault();
} else if (IsXnu() || IsOpenbsd()) {
diff --git a/libc/calls/symlinkat.c b/libc/calls/symlinkat.c
index cfc877f2d..6f14274ef 100644
--- a/libc/calls/symlinkat.c
+++ b/libc/calls/symlinkat.c
@@ -41,7 +41,6 @@
*/
int symlinkat(const char *target, int newdirfd, const char *linkpath) {
int rc;
- char buf[12];
if (IsAsan() &&
(!__asan_is_valid(target, 1) || !__asan_is_valid(linkpath, 1))) {
rc = efault();
@@ -51,7 +50,7 @@ int symlinkat(const char *target, int newdirfd, const char *linkpath) {
} else {
rc = sys_symlinkat_nt(target, newdirfd, linkpath);
}
- STRACE("symlinkat(%#s, %s, %#s) → %d% m", target,
- DescribeDirfd(buf, newdirfd), linkpath);
+ STRACE("symlinkat(%#s, %s, %#s) → %d% m", target, DescribeDirfd(newdirfd),
+ linkpath);
return rc;
}
diff --git a/libc/calls/unlinkat.c b/libc/calls/unlinkat.c
index 996bc6962..18676c5c8 100644
--- a/libc/calls/unlinkat.c
+++ b/libc/calls/unlinkat.c
@@ -40,7 +40,6 @@
*/
int unlinkat(int dirfd, const char *path, int flags) {
int rc;
- char buf[12];
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
@@ -50,7 +49,7 @@ int unlinkat(int dirfd, const char *path, int flags) {
} else {
rc = sys_unlinkat_nt(dirfd, path, flags);
}
- STRACE("unlinkat(%s, %#s, %#b) → %d% m", DescribeDirfd(buf, dirfd), path,
- flags, rc);
+ STRACE("unlinkat(%s, %#s, %#b) → %d% m", DescribeDirfd(dirfd), path, flags,
+ rc);
return rc;
}
diff --git a/libc/calls/utimensat.c b/libc/calls/utimensat.c
index 688c739b7..c514a43ca 100644
--- a/libc/calls/utimensat.c
+++ b/libc/calls/utimensat.c
@@ -54,7 +54,6 @@
int utimensat(int dirfd, const char *path, const struct timespec ts[2],
int flags) {
int rc;
- char buf[12];
if (IsAsan() && ((dirfd == AT_FDCWD && !__asan_is_valid(path, 1)) ||
(ts && (!__asan_is_valid_timespec(ts + 0) ||
!__asan_is_valid_timespec(ts + 1))))) {
@@ -72,11 +71,11 @@ int utimensat(int dirfd, const char *path, const struct timespec ts[2],
}
if (ts) {
STRACE("utimensat(%s, %#s, {{%,ld, %,ld}, {%,ld, %,ld}}, %#b) → %d% m",
- DescribeDirfd(buf, dirfd), path, ts[0].tv_sec, ts[0].tv_nsec,
+ DescribeDirfd(dirfd), path, ts[0].tv_sec, ts[0].tv_nsec,
ts[1].tv_sec, ts[1].tv_nsec, flags, rc);
} else {
- STRACE("utimensat(%s, %#s, 0, %#b) → %d% m", DescribeDirfd(buf, dirfd),
- path, flags, rc);
+ STRACE("utimensat(%s, %#s, 0, %#b) → %d% m", DescribeDirfd(dirfd), path,
+ flags, rc);
}
return rc;
}
diff --git a/libc/fmt/magnumstrs.internal.h b/libc/fmt/magnumstrs.internal.h
index af425fc93..7283f010d 100644
--- a/libc/fmt/magnumstrs.internal.h
+++ b/libc/fmt/magnumstrs.internal.h
@@ -25,11 +25,7 @@ hidden extern const struct MagnumStr kSignalNames[];
hidden extern const struct MagnumStr kSockOptnames[];
hidden extern const struct MagnumStr kTcpOptnames[];
-char *DescribeClockName(int) hidden;
-char *DescribeOpenFlags(int) hidden;
-char *DescribeSockLevel(int) hidden;
-char *DescribeSockOptname(int, int) hidden;
-char *GetMagnumStr(const struct MagnumStr *, int) hidden;
+char *GetMagnumStr(const struct MagnumStr *, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c
index 622c14c08..16045e9fe 100644
--- a/libc/intrin/asan.c
+++ b/libc/intrin/asan.c
@@ -1308,13 +1308,13 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
size = (size_t)i << 16;
addr = (void *)(intptr_t)((int64_t)((uint64_t)a << 32) >> 16);
prot = PROT_READ | PROT_WRITE;
- flag = MAP_PRIVATE | MAP_FIXED | *weaken(MAP_ANONYMOUS);
+ flag = MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS;
sm = weaken(sys_mmap)(addr, size, prot, flag, -1, 0);
if (sm.addr == MAP_FAILED ||
- weaken(TrackMemoryInterval)(
- m, a, a + i - 1, sm.maphandle, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, false, false, 0,
- size) == -1) {
+ weaken(TrackMemoryInterval)(m, a, a + i - 1, sm.maphandle,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ false, false, 0, size) == -1) {
kprintf("error: could not map asan shadow memory\n");
__asan_die()();
__asan_unreachable();
@@ -1379,7 +1379,6 @@ textstartup void __asan_init(int argc, char **argv, char **envp,
}
REQUIRE(_mmi);
REQUIRE(sys_mmap);
- REQUIRE(MAP_ANONYMOUS);
REQUIRE(TrackMemoryInterval);
if (weaken(hook_malloc) || weaken(hook_calloc) || weaken(hook_realloc) ||
weaken(hook_realloc_in_place) || weaken(hook_free) ||
diff --git a/libc/intrin/assertdisable.c b/libc/intrin/assertdisable.c
new file mode 100644
index 000000000..788f68484
--- /dev/null
+++ b/libc/intrin/assertdisable.c
@@ -0,0 +1,23 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+
+/**
+ * Disables assert() failures at runtime.
+ */
+bool __assert_disable;
diff --git a/libc/intrin/assertfail.greg.c b/libc/intrin/assertfail.greg.c
index 75a5a071f..e24603215 100644
--- a/libc/intrin/assertfail.greg.c
+++ b/libc/intrin/assertfail.greg.c
@@ -19,6 +19,7 @@
#include "libc/assert.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
+#include "libc/calls/syscall-sysv.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/lockcmpxchgp.h"
#include "libc/log/backtrace.internal.h"
@@ -30,32 +31,33 @@
/**
* Handles failure of assert() macro.
*/
-relegated wontreturn void __assert_fail(const char *expr, const char *file,
- int line) {
+relegated void __assert_fail(const char *expr, const char *file, int line) {
int me, owner;
static int sync;
- --__strace;
- --__ftrace;
- owner = 0;
- me = gettid();
- kprintf("%s:%d: assert(%s) failed (tid %d)\n", file, line, expr, me);
- if (_lockcmpxchgp(&sync, &owner, me)) {
- __restore_tty();
- if (weaken(ShowBacktrace)) {
- weaken(ShowBacktrace)(2, __builtin_frame_address(0));
- } else if (weaken(PrintBacktraceUsingSymbols) && weaken(GetSymbolTable)) {
- weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0),
- weaken(GetSymbolTable)());
+ if (!__assert_disable) {
+ --__strace;
+ --__ftrace;
+ owner = 0;
+ me = sys_gettid();
+ kprintf("%s:%d: assert(%s) failed (tid %d)\n", file, line, expr, me);
+ if (_lockcmpxchgp(&sync, &owner, me)) {
+ __restore_tty();
+ if (weaken(ShowBacktrace)) {
+ weaken(ShowBacktrace)(2, __builtin_frame_address(0));
+ } else if (weaken(PrintBacktraceUsingSymbols) && weaken(GetSymbolTable)) {
+ weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0),
+ weaken(GetSymbolTable)());
+ } else {
+ kprintf("can't backtrace b/c `ShowCrashReports` not linked\n");
+ }
+ __restorewintty();
+ _Exit(23);
+ } else if (owner == me) {
+ kprintf("assert failed while failing\n");
+ __restorewintty();
+ _Exit(24);
} else {
- kprintf("can't backtrace b/c `ShowCrashReports` not linked\n");
+ _Exit1(25);
}
- __restorewintty();
- _Exit(23);
- } else if (owner == me) {
- kprintf("assert failed while failing\n");
- __restorewintty();
- _Exit(24);
- } else {
- _Exit1(25);
}
}
diff --git a/libc/intrin/createfile.c b/libc/intrin/createfile.c
index 31e3fef92..2df5cc867 100644
--- a/libc/intrin/createfile.c
+++ b/libc/intrin/createfile.c
@@ -45,7 +45,7 @@ textwindows int64_t CreateFile(
DescribeNtFileShareFlags(dwShareMode),
DescribeNtSecurityAttributes(opt_lpSecurityAttributes),
DescribeNtCreationDisposition(dwCreationDisposition),
- DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes),
- opt_hTemplateFile, hHandle);
+ DescribeNtFileFlagAttr(dwFlagsAndAttributes), opt_hTemplateFile,
+ hHandle);
return hHandle;
}
diff --git a/libc/intrin/createsymboliclink.c b/libc/intrin/createsymboliclink.c
index 18bc51c8b..3f8101069 100644
--- a/libc/intrin/createsymboliclink.c
+++ b/libc/intrin/createsymboliclink.c
@@ -34,6 +34,6 @@ bool32 CreateSymbolicLink(const char16_t *lpSymlinkFileName,
ok = __imp_CreateSymbolicLinkW(lpSymlinkFileName, lpTargetPathName, dwFlags);
if (!ok) __winerr();
NTTRACE("CreateSymbolicLink(%#hs, %#hs, %s) → %hhhd% m", lpSymlinkFileName,
- lpTargetPathName, DescribeNtSymbolicLinkFlags(dwFlags), ok);
+ lpTargetPathName, DescribeNtSymlinkFlags(dwFlags), ok);
return ok;
}
diff --git a/libc/calls/describeclockname.c b/libc/intrin/describeclockname.c
similarity index 84%
rename from libc/calls/describeclockname.c
rename to libc/intrin/describeclockname.c
index 5a32ff0cc..0590921f0 100644
--- a/libc/calls/describeclockname.c
+++ b/libc/intrin/describeclockname.c
@@ -18,18 +18,34 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sol.h"
+static inline char *StpCpy(char *d, const char *s) {
+ size_t i;
+ for (i = 0;; ++i) {
+ if (!(d[i] = s[i])) {
+ return d + i;
+ }
+ }
+}
+
/**
* Describes clock_gettime() clock argument.
*/
-char *DescribeClockName(int x) {
+const char *(DescribeClockName)(char buf[32], int x) {
int i;
- char *s;
- _Alignas(char) static char buf[32];
+ char *s, *p;
if ((s = GetMagnumStr(kClockNames, x))) {
- stpcpy(stpcpy(buf, "CLOCK_"), s);
+ p = buf;
+ *p++ = 'C';
+ *p++ = 'L';
+ *p++ = 'O';
+ *p++ = 'C';
+ *p++ = 'K';
+ *p++ = '_';
+ StpCpy(p, s);
return buf;
} else {
FormatInt32(buf, x);
diff --git a/libc/intrin/describedirfd.greg.c b/libc/intrin/describedirfd.c
similarity index 96%
rename from libc/intrin/describedirfd.greg.c
rename to libc/intrin/describedirfd.c
index 86a72cbcd..04b38c371 100644
--- a/libc/intrin/describedirfd.greg.c
+++ b/libc/intrin/describedirfd.c
@@ -20,7 +20,7 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/at.h"
-const char *DescribeDirfd(char buf[hasatleast 12], int dirfd) {
+const char *(DescribeDirfd)(char buf[12], int dirfd) {
if (dirfd == AT_FDCWD) return "AT_FDCWD";
FormatInt32(buf, dirfd);
return buf;
diff --git a/libc/intrin/describeflags.greg.c b/libc/intrin/describeflags.c
similarity index 97%
rename from libc/intrin/describeflags.greg.c
rename to libc/intrin/describeflags.c
index b7166d269..09089d540 100644
--- a/libc/intrin/describeflags.greg.c
+++ b/libc/intrin/describeflags.c
@@ -19,6 +19,7 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
+// TODO(jart): Fork this function into ASAN and non-ASAN versions.
const char *DescribeFlags(char *p, size_t n, struct DescribeFlags *d, size_t m,
const char *prefix, unsigned x) {
bool t;
diff --git a/libc/intrin/describeflags.internal.h b/libc/intrin/describeflags.internal.h
index e797abc9a..c0b688406 100644
--- a/libc/intrin/describeflags.internal.h
+++ b/libc/intrin/describeflags.internal.h
@@ -7,7 +7,10 @@
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/timespec.h"
+#include "libc/mem/alloca.h"
+#include "libc/nt/struct/iovec.h"
#include "libc/nt/struct/securityattributes.h"
+#include "libc/sock/struct/sockaddr.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@@ -19,39 +22,90 @@ struct thatispacked DescribeFlags {
const char *DescribeFlags(char *, size_t, struct DescribeFlags *, size_t,
const char *, unsigned);
-const char *DescribeMapFlags(int);
-const char *DescribeProtFlags(int);
-const char *DescribeRemapFlags(int);
-const char *DescribeRlimitName(int);
-const char *DescribePersonalityFlags(int);
-const char *DescribeSeccompOperationFlags(int);
-const char *DescribePollFlags(char *, size_t, int);
-const char *DescribeStat(int, const struct stat *);
-const char *DescribeDirfd(char[hasatleast 12], int);
-const char *DescribeSigaction(char *, size_t, int, const struct sigaction *);
-const char *DescribeSigaltstk(char *, size_t, int, const struct sigaltstack *);
-const char *DescribeSigset(char *, size_t, int, const sigset_t *);
-const char *DescribeRlimit(char *, size_t, int, const struct rlimit *);
-const char *DescribeTimespec(char *, size_t, int, const struct timespec *);
-
-const char *DescribeNtPageFlags(uint32_t);
-const char *DescribeNtStartFlags(uint32_t);
-const char *DescribeNtFileMapFlags(uint32_t);
-const char *DescribeNtFiletypeFlags(uint32_t);
-const char *DescribeNtPipeOpenFlags(uint32_t);
-const char *DescribeNtPipeModeFlags(uint32_t);
-const char *DescribeNtFileShareFlags(uint32_t);
-const char *DescribeNtFileAccessFlags(uint32_t);
-const char *DescribeNtSymbolicLinkFlags(uint32_t);
-const char *DescribeNtProcessAccessFlags(uint32_t);
-const char *DescribeNtMoveFileInputFlags(uint32_t);
+const char *DescribeClockName(char[32], int);
+const char *DescribeDirfd(char[12], int);
+const char *DescribeFrame(char[32], int);
+const char *DescribeHow(char[12], int);
+const char *DescribeMapFlags(char[64], int);
+const char *DescribeMapping(char[8], int, int);
+const char *DescribeNtConsoleInFlags(char[256], uint32_t);
+const char *DescribeNtConsoleOutFlags(char[128], uint32_t);
const char *DescribeNtCreationDisposition(uint32_t);
-const char *DescribeNtConsoleModeInputFlags(uint32_t);
-const char *DescribeNtConsoleModeOutputFlags(uint32_t);
-const char *DescribeNtFileFlagsAndAttributes(uint32_t);
+const char *DescribeNtFileAccessFlags(char[512], uint32_t);
+const char *DescribeNtFileFlagAttr(char[256], uint32_t);
+const char *DescribeNtFileMapFlags(char[64], uint32_t);
+const char *DescribeNtFileShareFlags(char[64], uint32_t);
+const char *DescribeNtFiletypeFlags(char[64], uint32_t);
+const char *DescribeNtMovFileInpFlags(char[256], uint32_t);
+const char *DescribeNtPageFlags(char[64], uint32_t);
+const char *DescribeNtPipeModeFlags(char[64], uint32_t);
+const char *DescribeNtPipeOpenFlags(char[64], uint32_t);
+const char *DescribeNtProcAccessFlags(char[256], uint32_t);
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *);
+const char *DescribeNtStartFlags(char[128], uint32_t);
+const char *DescribeNtSymlinkFlags(char[64], uint32_t);
+const char *DescribeOpenFlags(char[128], int);
+const char *DescribePersonalityFlags(char[128], int);
+const char *DescribePollFlags(char[64], int);
+const char *DescribePrctlOperation(int);
+const char *DescribeProtFlags(char[48], int);
+const char *DescribeRemapFlags(char[48], int);
+const char *DescribeRlimit(char[64], int, const struct rlimit *);
+const char *DescribeRlimitName(char[12], int);
+const char *DescribeSeccompOperation(int);
+const char *DescribeSigaction(char[128], int, const struct sigaction *);
+const char *DescribeSigaltstk(char[128], int, const struct sigaltstack *);
+const char *DescribeSigset(char[64], int, const sigset_t *);
+const char *DescribeSockLevel(char[12], int);
+const char *DescribeSockOptname(char[32], int, int);
+const char *DescribeSockaddr(char[128], const struct sockaddr *, size_t);
+const char *DescribeSocketFamily(char[12], int);
+const char *DescribeSocketProtocol(char[12], int);
+const char *DescribeSocketType(char[64], int);
+const char *DescribeStat(char[300], int, const struct stat *);
+const char *DescribeTimespec(char[45], int, const struct timespec *);
void DescribeIov(const struct iovec *, int, ssize_t);
+void DescribeIovNt(const struct NtIovec *, uint32_t, ssize_t);
+
+#define DescribeClockName(x) DescribeClockName(alloca(32), x)
+#define DescribeDirfd(dirfd) DescribeDirfd(alloca(12), dirfd)
+#define DescribeFrame(x) DescribeFrame(alloca(32), x)
+#define DescribeHow(x) DescribeHow(alloca(12), x)
+#define DescribeMapFlags(dirfd) DescribeMapFlags(alloca(64), dirfd)
+#define DescribeMapping(x, y) DescribeMapping(alloca(8), x, y)
+#define DescribeNtConsoleInFlags(x) DescribeNtConsoleInFlags(alloca(256), x)
+#define DescribeNtConsoleOutFlags(x) DescribeNtConsoleOutFlags(alloca(128), x)
+#define DescribeNtFileAccessFlags(x) DescribeNtFileAccessFlags(alloca(512), x)
+#define DescribeNtFileFlagAttr(x) DescribeNtFileFlagAttr(alloca(256), x)
+#define DescribeNtFileMapFlags(x) DescribeNtFileMapFlags(alloca(64), x)
+#define DescribeNtFileShareFlags(x) DescribeNtFileShareFlags(alloca(64), x)
+#define DescribeNtFiletypeFlags(x) DescribeNtFiletypeFlags(alloca(64), x)
+#define DescribeNtMovFileInpFlags(x) DescribeNtMovFileInpFlags(alloca(256), x)
+#define DescribeNtPageFlags(x) DescribeNtPageFlags(alloca(64), x)
+#define DescribeNtPipeModeFlags(x) DescribeNtPipeModeFlags(alloca(64), x)
+#define DescribeNtPipeOpenFlags(x) DescribeNtPipeOpenFlags(alloca(64), x)
+#define DescribeNtProcAccessFlags(x) DescribeNtProcAccessFlags(alloca(256), x)
+#define DescribeNtStartFlags(x) DescribeNtStartFlags(alloca(128), x)
+#define DescribeNtSymlinkFlags(x) DescribeNtSymlinkFlags(alloca(64), x)
+#define DescribeOpenFlags(x) DescribeOpenFlags(alloca(128), x)
+#define DescribePersonalityFlags(p) DescribePersonalityFlags(alloca(128), p)
+#define DescribePollFlags(p) DescribePollFlags(alloca(64), p)
+#define DescribeProtFlags(dirfd) DescribeProtFlags(alloca(48), dirfd)
+#define DescribeRemapFlags(dirfd) DescribeRemapFlags(alloca(48), dirfd)
+#define DescribeRlimit(rc, rl) DescribeRlimit(alloca(64), rc, rl)
+#define DescribeRlimitName(rl) DescribeRlimitName(alloca(12), rl)
+#define DescribeSigaction(rc, sa) DescribeSigaction(alloca(128), rc, sa)
+#define DescribeSigaltstk(rc, ss) DescribeSigaltstk(alloca(128), rc, ss)
+#define DescribeSigset(rc, ss) DescribeSigset(alloca(64), rc, ss)
+#define DescribeSockLevel(x) DescribeSockLevel(alloca(12), x)
+#define DescribeSockOptname(x, y) DescribeSockOptname(alloca(32), x, y)
+#define DescribeSockaddr(sa, sz) DescribeSockaddr(alloca(128), sa, sz)
+#define DescribeSocketFamily(x) DescribeSocketFamily(alloca(12), x)
+#define DescribeSocketProtocol(x) DescribeSocketProtocol(alloca(12), x)
+#define DescribeSocketType(x) DescribeSocketType(alloca(64), x)
+#define DescribeStat(rc, st) DescribeStat(alloca(300), rc, st)
+#define DescribeTimespec(rc, ts) DescribeTimespec(alloca(45), rc, ts)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
diff --git a/libc/intrin/describeframe.c b/libc/intrin/describeframe.c
index f252ff429..4bb56aad1 100644
--- a/libc/intrin/describeframe.c
+++ b/libc/intrin/describeframe.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
@@ -25,12 +26,11 @@
#define UNSHADOW(x) ((int64_t)(MAX(0, (x)-0x7fff8000)) << 3)
#define FRAME(x) ((int)((x) >> 16))
-noasan const char *DescribeFrame(int x) {
+const char *(DescribeFrame)(char buf[32], int x) {
/* asan runtime depends on this function */
char *p;
- static char buf[32];
if (IsShadowFrame(x)) {
- ksnprintf(buf, sizeof(buf), " shadow=%.8x", FRAME(UNSHADOW(ADDR(x))));
+ ksnprintf(buf, 32, " shadow=%.8x", FRAME(UNSHADOW(ADDR(x))));
return buf;
return " shadow ";
} else if (IsAutoFrame(x)) {
diff --git a/libc/intrin/describehow.c b/libc/intrin/describehow.c
new file mode 100644
index 000000000..87777d9d8
--- /dev/null
+++ b/libc/intrin/describehow.c
@@ -0,0 +1,29 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/sysv/consts/sig.h"
+
+const char *(DescribeHow)(char buf[12], int how) {
+ if (how == SIG_BLOCK) return "SIG_BLOCK";
+ if (how == SIG_UNBLOCK) return "SIG_UNBLOCK";
+ if (how == SIG_SETMASK) return "SIG_SETMASK";
+ FormatInt32(buf, how);
+ return buf;
+}
diff --git a/libc/intrin/describeiov.greg.c b/libc/intrin/describeiov.c
similarity index 100%
rename from libc/intrin/describeiov.greg.c
rename to libc/intrin/describeiov.c
diff --git a/libc/intrin/describeiovnt.c b/libc/intrin/describeiovnt.c
new file mode 100644
index 000000000..5704ecc5a
--- /dev/null
+++ b/libc/intrin/describeiovnt.c
@@ -0,0 +1,42 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/dce.h"
+#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/intrin/kprintf.h"
+#include "libc/macros.internal.h"
+#include "libc/nt/winsock.h"
+
+void DescribeIovNt(const struct NtIovec *iov, uint32_t iovlen, ssize_t rem) {
+ int i;
+ if ((!IsAsan() && kisdangerous(iov)) ||
+ (IsAsan() && !__asan_is_valid(iov, iovlen * sizeof(struct NtIovec)))) {
+ kprintf("%p", iov);
+ return;
+ }
+ kprintf("{");
+ for (i = 0; rem && i < MIN(5, iovlen); ++i) {
+ kprintf("%s{%#.*hhs%s, %'zu}", i ? ", " : "",
+ MAX(0, MIN(40, MIN(rem, iov[i].len))), iov[i].buf,
+ MAX(0, MIN(40, MIN(rem, iov[i].len))) < iov[i].len ? "..." : "",
+ iov[i].len);
+ rem -= iov[i].len;
+ }
+ kprintf("%s}", iovlen > 5 ? "..." : "");
+}
diff --git a/libc/intrin/describemapflags.greg.c b/libc/intrin/describemapflags.c
similarity index 93%
rename from libc/intrin/describemapflags.greg.c
rename to libc/intrin/describemapflags.c
index b0fdefd50..8271d8f9a 100644
--- a/libc/intrin/describemapflags.greg.c
+++ b/libc/intrin/describemapflags.c
@@ -22,8 +22,7 @@
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
-const char *DescribeMapFlags(int x) {
- _Alignas(char) static char mapflags[256];
+const char *(DescribeMapFlags)(char buf[64], int x) {
const struct DescribeFlags kMapFlags[] = {
{MAP_STACK, "STACK"}, // order matters
{MAP_PRIVATE, "PRIVATE"}, //
@@ -39,6 +38,5 @@ const char *DescribeMapFlags(int x) {
{MAP_NONBLOCK, "NONBLOCK"}, //
{MAP_POPULATE, "POPULATE"}, //
};
- return DescribeFlags(mapflags, sizeof(mapflags), kMapFlags,
- ARRAYLEN(kMapFlags), "MAP_", x);
+ return DescribeFlags(buf, 64, kMapFlags, ARRAYLEN(kMapFlags), "MAP_", x);
}
diff --git a/libc/intrin/describemapping.greg.c b/libc/intrin/describemapping.c
similarity index 92%
rename from libc/intrin/describemapping.greg.c
rename to libc/intrin/describemapping.c
index cbce1ac6d..328ec5cb6 100644
--- a/libc/intrin/describemapping.greg.c
+++ b/libc/intrin/describemapping.c
@@ -16,11 +16,12 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/intrin/describeflags.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
-static noasan char DescribeMapType(int flags) {
+static char DescribeMapType(int flags) {
switch (flags & MAP_TYPE) {
case MAP_FILE:
return 'f';
@@ -35,7 +36,7 @@ static noasan char DescribeMapType(int flags) {
}
}
-noasan char *DescribeProt(int prot, char p[hasatleast 4]) {
+char *DescribeProt(char p[4], int prot) {
p[0] = (prot & PROT_READ) ? 'r' : '-';
p[1] = (prot & PROT_WRITE) ? 'w' : '-';
p[2] = (prot & PROT_EXEC) ? 'x' : '-';
@@ -43,9 +44,9 @@ noasan char *DescribeProt(int prot, char p[hasatleast 4]) {
return p;
}
-noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
+const char *(DescribeMapping)(char p[8], int prot, int flags) {
/* asan runtime depends on this function */
- DescribeProt(prot, p);
+ DescribeProt(p, prot);
p[3] = DescribeMapType(flags);
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
p[5] = (flags & MAP_GROWSDOWN) ? 'G' : '-';
diff --git a/libc/intrin/describentconsolemodeinputflags.greg.c b/libc/intrin/describentconsolemodeinputflags.c
similarity index 89%
rename from libc/intrin/describentconsolemodeinputflags.greg.c
rename to libc/intrin/describentconsolemodeinputflags.c
index 1b3fb94eb..8c665030f 100644
--- a/libc/intrin/describentconsolemodeinputflags.greg.c
+++ b/libc/intrin/describentconsolemodeinputflags.c
@@ -33,9 +33,7 @@ static const struct DescribeFlags kConsoleModeInputFlags[] = {
{kNtEnableVirtualTerminalInput, "VirtualTerminalInput"}, //
};
-const char *DescribeNtConsoleModeInputFlags(uint32_t x) {
- _Alignas(char) static char consolemodeinputflags[256];
- return DescribeFlags(consolemodeinputflags, sizeof(consolemodeinputflags),
- kConsoleModeInputFlags, ARRAYLEN(kConsoleModeInputFlags),
- "kNtEnable", x);
+const char *(DescribeNtConsoleInFlags)(char buf[256], uint32_t x) {
+ return DescribeFlags(buf, 256, kConsoleModeInputFlags,
+ ARRAYLEN(kConsoleModeInputFlags), "kNtEnable", x);
}
diff --git a/libc/intrin/describentconsolemodeoutputflags.greg.c b/libc/intrin/describentconsolemodeoutputflags.c
similarity index 91%
rename from libc/intrin/describentconsolemodeoutputflags.greg.c
rename to libc/intrin/describentconsolemodeoutputflags.c
index 139b6e9ed..29ef54456 100644
--- a/libc/intrin/describentconsolemodeoutputflags.greg.c
+++ b/libc/intrin/describentconsolemodeoutputflags.c
@@ -28,9 +28,7 @@ static const struct DescribeFlags kConsoleModeOutputFlags[] = {
{kNtEnableLvbGridWorldwide, "EnableLvbGridWorldwide"}, //
};
-const char *DescribeNtConsoleModeOutputFlags(uint32_t x) {
- _Alignas(char) static char consolemodeoutputflags[128];
- return DescribeFlags(consolemodeoutputflags, sizeof(consolemodeoutputflags),
- kConsoleModeOutputFlags,
+const char *(DescribeNtConsoleOutFlags)(char buf[128], uint32_t x) {
+ return DescribeFlags(buf, 128, kConsoleModeOutputFlags,
ARRAYLEN(kConsoleModeOutputFlags), "kNt", x);
}
diff --git a/libc/intrin/describentcreationdisposition.greg.c b/libc/intrin/describentcreationdisposition.c
similarity index 100%
rename from libc/intrin/describentcreationdisposition.greg.c
rename to libc/intrin/describentcreationdisposition.c
diff --git a/libc/intrin/describentfileaccessflags.greg.c b/libc/intrin/describentfileaccessflags.c
similarity index 94%
rename from libc/intrin/describentfileaccessflags.greg.c
rename to libc/intrin/describentfileaccessflags.c
index 79924afb7..a29c17066 100644
--- a/libc/intrin/describentfileaccessflags.greg.c
+++ b/libc/intrin/describentfileaccessflags.c
@@ -63,8 +63,7 @@ static const struct DescribeFlags kFileAccessflags[] = {
{kNtTokenAdjustSessionid, "TokenAdjustSessionid"}, //
};
-const char *DescribeNtFileAccessFlags(uint32_t x) {
- _Alignas(char) static char ntfileaccessflags[512];
- return DescribeFlags(ntfileaccessflags, sizeof(ntfileaccessflags),
- kFileAccessflags, ARRAYLEN(kFileAccessflags), "kNt", x);
+const char *(DescribeNtFileAccessFlags)(char buf[512], uint32_t x) {
+ return DescribeFlags(buf, 512, kFileAccessflags, ARRAYLEN(kFileAccessflags),
+ "kNt", x);
}
diff --git a/libc/intrin/describentfileflagsandattributes.greg.c b/libc/intrin/describentfileflagattr.c
similarity index 94%
rename from libc/intrin/describentfileflagsandattributes.greg.c
rename to libc/intrin/describentfileflagattr.c
index 53a5a47d7..5b1517b2f 100644
--- a/libc/intrin/describentfileflagsandattributes.greg.c
+++ b/libc/intrin/describentfileflagattr.c
@@ -51,9 +51,8 @@ static const struct DescribeFlags kFileFlags[] = {
{kNtFileFlagFirstPipeInstance, "FlagFirstPipeInstance"}, //
};
-const char *DescribeNtFileFlagsAndAttributes(uint32_t x) {
- _Alignas(char) static char ntfileflags[256];
+const char *(DescribeNtFileFlagAttr)(char buf[256], uint32_t x) {
if (x == -1u) return "-1u";
- return DescribeFlags(ntfileflags, sizeof(ntfileflags), kFileFlags,
- ARRAYLEN(kFileFlags), "kNtFile", x);
+ return DescribeFlags(buf, 256, kFileFlags, ARRAYLEN(kFileFlags), "kNtFile",
+ x);
}
diff --git a/libc/intrin/describentfilemapflags.greg.c b/libc/intrin/describentfilemapflags.c
similarity index 91%
rename from libc/intrin/describentfilemapflags.greg.c
rename to libc/intrin/describentfilemapflags.c
index f5cdabaf5..cda7a7f5f 100644
--- a/libc/intrin/describentfilemapflags.greg.c
+++ b/libc/intrin/describentfilemapflags.c
@@ -30,8 +30,7 @@ static const struct DescribeFlags kFileMapFlags[] = {
{kNtFileMapLargePages, "LargePages"}, //
};
-const char *DescribeNtFileMapFlags(uint32_t x) {
- _Alignas(char) static char filemapflags[64];
- return DescribeFlags(filemapflags, sizeof(filemapflags), kFileMapFlags,
- ARRAYLEN(kFileMapFlags), "kNtFileMap", x);
+const char *(DescribeNtFileMapFlags)(char buf[64], uint32_t x) {
+ return DescribeFlags(buf, 64, kFileMapFlags, ARRAYLEN(kFileMapFlags),
+ "kNtFileMap", x);
}
diff --git a/libc/intrin/describentfileshareflags.greg.c b/libc/intrin/describentfileshareflags.c
similarity index 90%
rename from libc/intrin/describentfileshareflags.greg.c
rename to libc/intrin/describentfileshareflags.c
index c322e3b86..a378bebe8 100644
--- a/libc/intrin/describentfileshareflags.greg.c
+++ b/libc/intrin/describentfileshareflags.c
@@ -26,9 +26,7 @@ static const struct DescribeFlags kFileShareflags[] = {
{kNtFileShareDelete, "Delete"}, //
};
-const char *DescribeNtFileShareFlags(uint32_t x) {
- _Alignas(char) static char ntfileshareflags[64];
- return DescribeFlags(ntfileshareflags, sizeof(ntfileshareflags),
- kFileShareflags, ARRAYLEN(kFileShareflags),
+const char *(DescribeNtFileShareFlags)(char buf[64], uint32_t x) {
+ return DescribeFlags(buf, 64, kFileShareflags, ARRAYLEN(kFileShareflags),
"kNtFileShare", x);
}
diff --git a/libc/intrin/describentfiletypeflags.greg.c b/libc/intrin/describentfiletypeflags.c
similarity index 90%
rename from libc/intrin/describentfiletypeflags.greg.c
rename to libc/intrin/describentfiletypeflags.c
index 70b48ea1b..a9160d08a 100644
--- a/libc/intrin/describentfiletypeflags.greg.c
+++ b/libc/intrin/describentfiletypeflags.c
@@ -28,8 +28,7 @@ static const struct DescribeFlags kFiletypeFlags[] = {
{kNtFileTypeChar, "Char"}, //
};
-const char *DescribeNtFiletypeFlags(uint32_t x) {
- _Alignas(char) static char filetypeflags[64];
- return DescribeFlags(filetypeflags, sizeof(filetypeflags), kFiletypeFlags,
- ARRAYLEN(kFiletypeFlags), "kNtFileType", x);
+const char *(DescribeNtFiletypeFlags)(char buf[64], uint32_t x) {
+ return DescribeFlags(buf, 64, kFiletypeFlags, ARRAYLEN(kFiletypeFlags),
+ "kNtFileType", x);
}
diff --git a/libc/intrin/describentmovefileflags.greg.c b/libc/intrin/describentmovfileinpflags.c
similarity index 89%
rename from libc/intrin/describentmovefileflags.greg.c
rename to libc/intrin/describentmovfileinpflags.c
index c2f29b869..ea3853423 100644
--- a/libc/intrin/describentmovefileflags.greg.c
+++ b/libc/intrin/describentmovfileinpflags.c
@@ -29,9 +29,7 @@ static const struct DescribeFlags kMoveFileInputFlags[] = {
{kNtMovefileFailIfNotTrackable, "FailIfNotTrackable"}, //
};
-const char *DescribeNtMoveFileInputFlags(uint32_t x) {
- _Alignas(char) static char movefileflags[256];
- return DescribeFlags(movefileflags, sizeof(movefileflags),
- kMoveFileInputFlags, ARRAYLEN(kMoveFileInputFlags),
- "kNtMovefile", x);
+const char *(DescribeNtMovFileInpFlags)(char buf[256], uint32_t x) {
+ return DescribeFlags(buf, 256, kMoveFileInputFlags,
+ ARRAYLEN(kMoveFileInputFlags), "kNtMovefile", x);
}
diff --git a/libc/intrin/describentpageflags.greg.c b/libc/intrin/describentpageflags.c
similarity index 93%
rename from libc/intrin/describentpageflags.greg.c
rename to libc/intrin/describentpageflags.c
index 02a7451c8..3333808f9 100644
--- a/libc/intrin/describentpageflags.greg.c
+++ b/libc/intrin/describentpageflags.c
@@ -41,8 +41,6 @@ static const struct DescribeFlags kPageFlags[] = {
{kNtSecWritecombine, "SecWritecombine"}, //
};
-const char *DescribeNtPageFlags(uint32_t x) {
- _Alignas(char) static char pageflags[64];
- return DescribeFlags(pageflags, sizeof(pageflags), kPageFlags,
- ARRAYLEN(kPageFlags), "kNt", x);
+const char *(DescribeNtPageFlags)(char buf[64], uint32_t x) {
+ return DescribeFlags(buf, 64, kPageFlags, ARRAYLEN(kPageFlags), "kNt", x);
}
diff --git a/libc/intrin/describentpipemodeflags.greg.c b/libc/intrin/describentpipemodeflags.c
similarity index 91%
rename from libc/intrin/describentpipemodeflags.greg.c
rename to libc/intrin/describentpipemodeflags.c
index f8f1f89ee..56d095078 100644
--- a/libc/intrin/describentpipemodeflags.greg.c
+++ b/libc/intrin/describentpipemodeflags.c
@@ -32,8 +32,7 @@ static const struct DescribeFlags kPipeModeFlags[] = {
//{kNtPipeTypeByte, "TypeByte"}, // 0x00000000
};
-const char *DescribeNtPipeModeFlags(uint32_t x) {
- _Alignas(char) static char pipemodeflags[64];
- return DescribeFlags(pipemodeflags, sizeof(pipemodeflags), kPipeModeFlags,
- ARRAYLEN(kPipeModeFlags), "kNtPipe", x);
+const char *(DescribeNtPipeModeFlags)(char buf[64], uint32_t x) {
+ return DescribeFlags(buf, 64, kPipeModeFlags, ARRAYLEN(kPipeModeFlags),
+ "kNtPipe", x);
}
diff --git a/libc/intrin/describentpipeopenflags.greg.c b/libc/intrin/describentpipeopenflags.c
similarity index 90%
rename from libc/intrin/describentpipeopenflags.greg.c
rename to libc/intrin/describentpipeopenflags.c
index 10ab98a81..ebb81c990 100644
--- a/libc/intrin/describentpipeopenflags.greg.c
+++ b/libc/intrin/describentpipeopenflags.c
@@ -27,8 +27,7 @@ static const struct DescribeFlags kPipeOpenFlags[] = {
{kNtPipeAccessInbound, "Inbound"}, // 0x00000001
};
-const char *DescribeNtPipeOpenFlags(uint32_t x) {
- _Alignas(char) static char pipeopenflags[64];
- return DescribeFlags(pipeopenflags, sizeof(pipeopenflags), kPipeOpenFlags,
- ARRAYLEN(kPipeOpenFlags), "kNtPipeAccess", x);
+const char *(DescribeNtPipeOpenFlags)(char buf[64], uint32_t x) {
+ return DescribeFlags(buf, 64, kPipeOpenFlags, ARRAYLEN(kPipeOpenFlags),
+ "kNtPipeAccess", x);
}
diff --git a/libc/intrin/describentprocessaccessflags.greg.c b/libc/intrin/describentprocaccessflags.c
similarity index 90%
rename from libc/intrin/describentprocessaccessflags.greg.c
rename to libc/intrin/describentprocaccessflags.c
index 5f3d7fcdd..4d2db8d9a 100644
--- a/libc/intrin/describentprocessaccessflags.greg.c
+++ b/libc/intrin/describentprocaccessflags.c
@@ -37,9 +37,7 @@ static const struct DescribeFlags kProcessAccessflags[] = {
{kNtProcessSynchronize, "Synchronize"}, //
};
-const char *DescribeNtProcessAccessFlags(uint32_t x) {
- _Alignas(char) static char ntprocessaccessflags[256];
- return DescribeFlags(ntprocessaccessflags, sizeof(ntprocessaccessflags),
- kProcessAccessflags, ARRAYLEN(kProcessAccessflags),
- "kNtProcess", x);
+const char *(DescribeNtProcAccessFlags)(char buf[256], uint32_t x) {
+ return DescribeFlags(buf, 256, kProcessAccessflags,
+ ARRAYLEN(kProcessAccessflags), "kNtProcess", x);
}
diff --git a/libc/intrin/describentsecurityattributes.greg.c b/libc/intrin/describentsecurityattributes.c
similarity index 100%
rename from libc/intrin/describentsecurityattributes.greg.c
rename to libc/intrin/describentsecurityattributes.c
diff --git a/libc/intrin/describentstartflags.greg.c b/libc/intrin/describentstartflags.c
similarity index 92%
rename from libc/intrin/describentstartflags.greg.c
rename to libc/intrin/describentstartflags.c
index d80e2778b..523f4fee2 100644
--- a/libc/intrin/describentstartflags.greg.c
+++ b/libc/intrin/describentstartflags.c
@@ -38,8 +38,7 @@ static const struct DescribeFlags kNtStartFlags[] = {
{kNtStartfUntrustedsource, "Untrustedsource"}, //
};
-const char *DescribeNtStartFlags(uint32_t x) {
- _Alignas(char) static char startflags[128];
- return DescribeFlags(startflags, sizeof(startflags), kNtStartFlags,
- ARRAYLEN(kNtStartFlags), "kNtStartf", x);
+const char *(DescribeNtStartFlags)(char buf[128], uint32_t x) {
+ return DescribeFlags(buf, 128, kNtStartFlags, ARRAYLEN(kNtStartFlags),
+ "kNtStartf", x);
}
diff --git a/libc/intrin/describentsymboliclinkflags.greg.c b/libc/intrin/describentsymlinkflags.c
similarity index 87%
rename from libc/intrin/describentsymboliclinkflags.greg.c
rename to libc/intrin/describentsymlinkflags.c
index 233945f94..f0ed54b47 100644
--- a/libc/intrin/describentsymboliclinkflags.greg.c
+++ b/libc/intrin/describentsymlinkflags.c
@@ -25,9 +25,7 @@ static const struct DescribeFlags kSymbolicLinkflags[] = {
{kNtSymbolicLinkFlagAllowUnprivilegedCreate, "AllowUnprivilegedCreate"}, //
};
-const char *DescribeNtSymbolicLinkFlags(uint32_t x) {
- _Alignas(char) static char ntsymboliclinkflags[64];
- return DescribeFlags(ntsymboliclinkflags, sizeof(ntsymboliclinkflags),
- kSymbolicLinkflags, ARRAYLEN(kSymbolicLinkflags),
- "kNtSymbolicLinkFlag", x);
+const char *(DescribeNtSymlinkFlags)(char buf[64], uint32_t x) {
+ return DescribeFlags(buf, 64, kSymbolicLinkflags,
+ ARRAYLEN(kSymbolicLinkflags), "kNtSymbolicLinkFlag", x);
}
diff --git a/libc/intrin/describeopenflags.greg.c b/libc/intrin/describeopenflags.c
similarity index 85%
rename from libc/intrin/describeopenflags.greg.c
rename to libc/intrin/describeopenflags.c
index 57ab7a46a..d1a3c840d 100644
--- a/libc/intrin/describeopenflags.greg.c
+++ b/libc/intrin/describeopenflags.c
@@ -16,26 +16,32 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/describeflags.internal.h"
-#include "libc/mem/alloca.h"
+#include "libc/macros.internal.h"
#include "libc/sysv/consts/sol.h"
+#define N (PAGESIZE / 2 / sizeof(struct DescribeFlags))
+
/**
* Describes clock_gettime() clock argument.
*/
-char *DescribeOpenFlags(int x) {
+const char *(DescribeOpenFlags)(char buf[128], int x) {
char *s;
int i, n;
- struct DescribeFlags *d;
- _Alignas(char) static char openflags[128];
+ struct DescribeFlags d[N];
// TODO(jart): unify DescribeFlags and MagnumStr data structures
- for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR;) ++n;
- d = alloca(n * sizeof(struct DescribeFlags));
+ for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) {
+ if (n == N) {
+ assert(!"too many open flags");
+ break;
+ }
+ }
for (i = 0; i < n; ++i) {
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i);
d[i].name = MAGNUM_STRING(kOpenFlags, i);
}
- return DescribeFlags(openflags, sizeof(openflags), d, n, "O_", x);
+ return DescribeFlags(buf, 128, d, n, "O_", x);
}
diff --git a/libc/intrin/describepersonalityflags.c b/libc/intrin/describepersonalityflags.c
index 5e09fde70..6e3a859f2 100644
--- a/libc/intrin/describepersonalityflags.c
+++ b/libc/intrin/describepersonalityflags.c
@@ -36,8 +36,7 @@ static const struct DescribeFlags kPersonalityFlags[] = {
{UNAME26, "UNAME26"}, //
};
-const char *DescribePersonalityFlags(int x) {
- _Alignas(char) static char personalityflags[128];
- return DescribeFlags(personalityflags, sizeof(personalityflags),
- kPersonalityFlags, ARRAYLEN(kPersonalityFlags), "", x);
+const char *(DescribePersonalityFlags)(char buf[128], int x) {
+ return DescribeFlags(buf, 128, kPersonalityFlags, ARRAYLEN(kPersonalityFlags),
+ "", x);
}
diff --git a/libc/intrin/describepollflags.greg.c b/libc/intrin/describepollflags.c
similarity index 94%
rename from libc/intrin/describepollflags.greg.c
rename to libc/intrin/describepollflags.c
index c1c868e51..fdff13f6d 100644
--- a/libc/intrin/describepollflags.greg.c
+++ b/libc/intrin/describepollflags.c
@@ -21,7 +21,7 @@
#include "libc/nt/enum/filemapflags.h"
#include "libc/sysv/consts/poll.h"
-const char *DescribePollFlags(char *buf, size_t size, int x) {
+const char *(DescribePollFlags)(char buf[64], int x) {
const struct DescribeFlags kPollFlags[] = {
{POLLIN, "IN"}, // order matters
{POLLOUT, "OUT"}, // order matters
@@ -35,5 +35,5 @@ const char *DescribePollFlags(char *buf, size_t size, int x) {
{POLLWRBAND, "WRBAND"}, //
{POLLWRNORM, "WRNORM"}, //
};
- return DescribeFlags(buf, size, kPollFlags, ARRAYLEN(kPollFlags), "POLL", x);
+ return DescribeFlags(buf, 64, kPollFlags, ARRAYLEN(kPollFlags), "POLL", x);
}
diff --git a/libc/intrin/describeprctloperation.c b/libc/intrin/describeprctloperation.c
new file mode 100644
index 000000000..b881d5f3d
--- /dev/null
+++ b/libc/intrin/describeprctloperation.c
@@ -0,0 +1,33 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/sysv/consts/pr.h"
+
+const char *DescribePrctlOperation(int x) {
+ switch (x) {
+ case PR_SET_NO_NEW_PRIVS:
+ return "PR_SET_NO_NEW_PRIVS";
+ case PR_SET_SECCOMP:
+ return "PR_SET_SECCOMP";
+ case PR_GET_SECCOMP:
+ return "PR_GET_SECCOMP";
+ default:
+ return "PRCTL_???";
+ }
+}
diff --git a/libc/intrin/describeprotflags.greg.c b/libc/intrin/describeprotflags.c
similarity index 91%
rename from libc/intrin/describeprotflags.greg.c
rename to libc/intrin/describeprotflags.c
index ac30ab5fc..a2cca029f 100644
--- a/libc/intrin/describeprotflags.greg.c
+++ b/libc/intrin/describeprotflags.c
@@ -26,8 +26,6 @@ static const struct DescribeFlags kProtFlags[] = {
{PROT_EXEC, "EXEC"}, //
};
-const char *DescribeProtFlags(int x) {
- _Alignas(char) static char protflags[64];
- return DescribeFlags(protflags, sizeof(protflags), kProtFlags,
- ARRAYLEN(kProtFlags), "PROT_", x);
+const char *(DescribeProtFlags)(char buf[48], int x) {
+ return DescribeFlags(buf, 48, kProtFlags, ARRAYLEN(kProtFlags), "PROT_", x);
}
diff --git a/libc/intrin/describeremapflags.greg.c b/libc/intrin/describeremapflags.c
similarity index 90%
rename from libc/intrin/describeremapflags.greg.c
rename to libc/intrin/describeremapflags.c
index 40ce7219e..9c1684a6d 100644
--- a/libc/intrin/describeremapflags.greg.c
+++ b/libc/intrin/describeremapflags.c
@@ -25,8 +25,7 @@ static const struct DescribeFlags kRemapFlags[] = {
{MREMAP_FIXED, "FIXED"}, //
};
-const char *DescribeRemapFlags(int x) {
- _Alignas(char) static char remapflags[64];
- return DescribeFlags(remapflags, sizeof(remapflags), kRemapFlags,
- ARRAYLEN(kRemapFlags), "MREMAP_", x);
+const char *(DescribeRemapFlags)(char buf[48], int x) {
+ return DescribeFlags(buf, 48, kRemapFlags, ARRAYLEN(kRemapFlags), "MREMAP_",
+ x);
}
diff --git a/libc/intrin/describerlimit.greg.c b/libc/intrin/describerlimit.c
similarity index 90%
rename from libc/intrin/describerlimit.greg.c
rename to libc/intrin/describerlimit.c
index ecf233140..0cdbfef48 100644
--- a/libc/intrin/describerlimit.greg.c
+++ b/libc/intrin/describerlimit.c
@@ -21,15 +21,14 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
-const char *DescribeRlimit(char *buf, size_t bufsize, int rc,
- const struct rlimit *rlim) {
+const char *DescribeRlimit(char buf[64], int rc, const struct rlimit *rlim) {
if (rc == -1) return "n/a";
if (!rlim) return "NULL";
if ((!IsAsan() && kisdangerous(rlim)) ||
(IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
- ksnprintf(buf, sizeof(buf), "%p", rlim);
+ ksnprintf(buf, 64, "%p", rlim);
} else {
- ksnprintf(buf, bufsize, "{%'ld, %'ld}", rlim->rlim_cur, rlim->rlim_max);
+ ksnprintf(buf, 64, "{%'ld, %'ld}", rlim->rlim_cur, rlim->rlim_max);
}
return buf;
}
diff --git a/libc/intrin/describerlimit_name.greg.c b/libc/intrin/describerlimit_name.c
similarity index 97%
rename from libc/intrin/describerlimit_name.greg.c
rename to libc/intrin/describerlimit_name.c
index 35fc0bb21..61ec49245 100644
--- a/libc/intrin/describerlimit_name.greg.c
+++ b/libc/intrin/describerlimit_name.c
@@ -20,8 +20,7 @@
#include "libc/fmt/itoa.h"
#include "libc/sysv/consts/rlimit.h"
-const char *DescribeRlimitName(int resource) {
- static char buf[12];
+const char *(DescribeRlimitName)(char buf[12], int resource) {
if (resource == 127) return "n/a";
if (resource == RLIMIT_AS) return "RLIMIT_AS";
if (resource == RLIMIT_CPU) return "RLIMIT_CPU";
diff --git a/libc/intrin/describeseccompoperation.c b/libc/intrin/describeseccompoperation.c
new file mode 100644
index 000000000..69808d1ab
--- /dev/null
+++ b/libc/intrin/describeseccompoperation.c
@@ -0,0 +1,35 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/struct/seccomp.h"
+#include "libc/intrin/describeflags.internal.h"
+
+const char *DescribeSeccompOperation(int x) {
+ switch (x) {
+ case SECCOMP_SET_MODE_STRICT:
+ return "SECCOMP_SET_MODE_STRICT";
+ case SECCOMP_SET_MODE_FILTER:
+ return "SECCOMP_SET_MODE_FILTER";
+ case SECCOMP_GET_ACTION_AVAIL:
+ return "SECCOMP_GET_ACTION_AVAIL";
+ case SECCOMP_GET_NOTIF_SIZES:
+ return "SECCOMP_GET_NOTIF_SIZES";
+ default:
+ return "SECCOMP_???";
+ }
+}
diff --git a/libc/calls/describesigaction.greg.c b/libc/intrin/describesigaction.c
similarity index 84%
rename from libc/calls/describesigaction.greg.c
rename to libc/intrin/describesigaction.c
index c6be76e17..f56e2ac1d 100644
--- a/libc/calls/describesigaction.greg.c
+++ b/libc/intrin/describesigaction.c
@@ -21,18 +21,16 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
-const char *DescribeSigaction(char *buf, size_t bufsize, int rc,
- const struct sigaction *sa) {
- char maskbuf[64];
+const char *(DescribeSigaction)(char buf[128], int rc,
+ const struct sigaction *sa) {
if (rc == -1) return "n/a";
if (!sa) return "NULL";
if ((!IsAsan() && kisdangerous(sa)) ||
(IsAsan() && !__asan_is_valid(sa, sizeof(*sa)))) {
- ksnprintf(buf, sizeof(buf), "%p", sa);
+ ksnprintf(buf, 128, "%p", sa);
} else {
- ksnprintf(buf, bufsize, "{.sa_handler=%p, .sa_flags=%#lx, .sa_mask=%s}",
- sa->sa_handler, sa->sa_flags,
- DescribeSigset(maskbuf, sizeof(maskbuf), rc, &sa->sa_mask));
+ ksnprintf(buf, 128, "{.sa_handler=%p, .sa_flags=%#lx, .sa_mask=%s}",
+ sa->sa_handler, sa->sa_flags, DescribeSigset(rc, &sa->sa_mask));
}
return buf;
}
diff --git a/libc/calls/describesigaltstack.greg.c b/libc/intrin/describesigaltstack.c
similarity index 88%
rename from libc/calls/describesigaltstack.greg.c
rename to libc/intrin/describesigaltstack.c
index dbfc830cb..be8c04026 100644
--- a/libc/calls/describesigaltstack.greg.c
+++ b/libc/intrin/describesigaltstack.c
@@ -22,16 +22,16 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
-const char *DescribeSigaltstk(char *buf, size_t bufsize, int rc,
- const struct sigaltstack *ss) {
+const char *(DescribeSigaltstk)(char buf[128], int rc,
+ const struct sigaltstack *ss) {
if (rc == -1) return "n/a";
if (!ss) return "NULL";
if ((!IsAsan() && kisdangerous(ss)) ||
(IsAsan() && !__asan_is_valid(ss, sizeof(*ss)))) {
- ksnprintf(buf, sizeof(buf), "%p", ss);
+ ksnprintf(buf, 128, "%p", ss);
} else {
- ksnprintf(buf, bufsize, "{.ss_sp=%p, .ss_flags=%#lx, .ss_size=%'zu}",
- ss->ss_sp, ss->ss_flags, ss->ss_size);
+ ksnprintf(buf, 128, "{.ss_sp=%p, .ss_flags=%#lx, .ss_size=%'zu}", ss->ss_sp,
+ ss->ss_flags, ss->ss_size);
}
return buf;
}
diff --git a/libc/calls/describesigset.greg.c b/libc/intrin/describesigset.c
similarity index 94%
rename from libc/calls/describesigset.greg.c
rename to libc/intrin/describesigset.c
index ad194d44e..4b9530524 100644
--- a/libc/calls/describesigset.greg.c
+++ b/libc/intrin/describesigset.c
@@ -23,8 +23,7 @@
#include "libc/intrin/kprintf.h"
#include "libc/str/str.h"
-const char *DescribeSigset(char *buf, size_t bufsize, int rc,
- const sigset_t *ss) {
+const char *(DescribeSigset)(char buf[64], int rc, const sigset_t *ss) {
bool gotsome;
int i, n, sig;
sigset_t sigset;
@@ -33,12 +32,12 @@ const char *DescribeSigset(char *buf, size_t bufsize, int rc,
if (!ss) return "NULL";
if ((!IsAsan() && kisdangerous(ss)) ||
(IsAsan() && !__asan_is_valid(ss, sizeof(*ss)))) {
- ksnprintf(buf, sizeof(buf), "%p", ss);
+ ksnprintf(buf, 64, "%p", ss);
return buf;
}
i = 0;
- n = bufsize;
+ n = 64;
sigset = *ss;
gotsome = false;
if (popcnt(sigset.__bits[0]) + popcnt(sigset.__bits[1]) > 64) {
diff --git a/libc/intrin/describesocketfamily.c b/libc/intrin/describesocketfamily.c
new file mode 100644
index 000000000..cf330facc
--- /dev/null
+++ b/libc/intrin/describesocketfamily.c
@@ -0,0 +1,29 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/sysv/consts/af.h"
+
+const char *(DescribeSocketFamily)(char buf[12], int family) {
+ if (family == AF_UNIX) return "AF_UNIX";
+ if (family == AF_INET) return "AF_INET";
+ if (family == AF_INET6) return "AF_INET6";
+ FormatInt32(buf, family);
+ return buf;
+}
diff --git a/libc/intrin/describesocketprotocol.c b/libc/intrin/describesocketprotocol.c
new file mode 100644
index 000000000..a2ae09142
--- /dev/null
+++ b/libc/intrin/describesocketprotocol.c
@@ -0,0 +1,32 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/sysv/consts/ipproto.h"
+
+const char *(DescribeSocketProtocol)(char buf[12], int family) {
+ if (family == IPPROTO_IP) return "IPPROTO_IP";
+ if (family == IPPROTO_ICMP) return "IPPROTO_ICMP";
+ if (family == IPPROTO_TCP) return "IPPROTO_TCP";
+ if (family == IPPROTO_UDP) return "IPPROTO_UDP";
+ if (family == IPPROTO_RAW) return "IPPROTO_RAW";
+ if (family == IPPROTO_IPV6) return "IPPROTO_IPv6";
+ FormatInt32(buf, family);
+ return buf;
+}
diff --git a/libc/intrin/describesockettype.c b/libc/intrin/describesockettype.c
new file mode 100644
index 000000000..ec144b4b9
--- /dev/null
+++ b/libc/intrin/describesockettype.c
@@ -0,0 +1,54 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/sock.h"
+
+static char *StpCpy(char *d, const char *s) {
+ size_t i;
+ for (i = 0;; ++i) {
+ if (!(d[i] = s[i])) {
+ return d + i;
+ }
+ }
+}
+
+const char *(DescribeSocketType)(char buf[64], int type) {
+ int x;
+ char *p;
+ p = buf;
+ x = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
+ if (x == SOCK_STREAM) {
+ p = StpCpy(p, "SOCK_STREAM");
+ } else if (x == SOCK_DGRAM) {
+ p = StpCpy(p, "SOCK_DGRAM");
+ } else if (x == SOCK_RAW) {
+ p = StpCpy(p, "SOCK_RAW");
+ } else if (x == SOCK_RDM) {
+ p = StpCpy(p, "SOCK_RDM");
+ } else if (x == SOCK_SEQPACKET) {
+ p = StpCpy(p, "SOCK_SEQPACKET");
+ } else {
+ p = FormatInt32(p, x);
+ }
+ if (type & SOCK_CLOEXEC) p = StpCpy(p, "|SOCK_CLOEXEC");
+ if (type & SOCK_NONBLOCK) p = StpCpy(p, "|SOCK_NONBLOCK");
+ return buf;
+}
diff --git a/libc/sock/describesocklevel.greg.c b/libc/intrin/describesocklevel.c
similarity index 95%
rename from libc/sock/describesocklevel.greg.c
rename to libc/intrin/describesocklevel.c
index 7dd91118b..c009ae249 100644
--- a/libc/sock/describesocklevel.greg.c
+++ b/libc/intrin/describesocklevel.c
@@ -17,13 +17,13 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes setsockopt() level arguments.
*/
-char *DescribeSockLevel(int x) {
- static char buf[12];
+const char *(DescribeSockLevel)(char buf[12], int x) {
if (x == SOL_IP) return "SOL_IP";
if (x == SOL_TCP) return "SOL_TCP";
if (x == SOL_UDP) return "SOL_UDP";
diff --git a/libc/sock/describesockoptname.greg.c b/libc/intrin/describesockoptname.c
similarity index 78%
rename from libc/sock/describesockoptname.greg.c
rename to libc/intrin/describesockoptname.c
index 09213b2a0..94e726f0b 100644
--- a/libc/sock/describesockoptname.greg.c
+++ b/libc/intrin/describesockoptname.c
@@ -18,34 +18,56 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sol.h"
+static inline char *StpCpy(char *d, const char *s) {
+ size_t i;
+ for (i = 0;; ++i) {
+ if (!(d[i] = s[i])) {
+ return d + i;
+ }
+ }
+}
+
/**
* Describes setsockopt() optname arguments.
*/
-char *DescribeSockOptname(int l, int x) {
+const char *(DescribeSockOptname)(char buf[32], int l, int x) {
int i;
- char *ps, *s;
- const struct MagnumStr *ms = 0;
- _Alignas(char) static char buf[32];
+ char *s, *p;
+ const struct MagnumStr *ms;
+ p = buf;
if (x) {
if (l == SOL_SOCKET) {
- ps = "SO_";
+ *p++ = 'S';
+ *p++ = 'O';
+ *p++ = '_';
+ *p = 0;
ms = kSockOptnames;
} else if (l == SOL_TCP) {
- ps = "TCP_";
+ *p++ = 'T';
+ *p++ = 'C';
+ *p++ = 'P';
+ *p++ = '_';
ms = kTcpOptnames;
} else if (l == SOL_IP) {
- ps = "IP_";
+ *p++ = 'I';
+ *p++ = 'P';
+ *p++ = '_';
+ *p = 0;
ms = kIpOptnames;
+ } else {
+ ms = 0;
}
+ } else {
+ ms = 0;
}
if (ms && (s = GetMagnumStr(ms, x))) {
- stpcpy(stpcpy(buf, ps), s);
- return buf;
+ StpCpy(p, s);
} else {
- FormatInt32(buf, x);
- return buf;
+ FormatInt32(p, x);
}
+ return buf;
}
diff --git a/libc/intrin/describestat.greg.c b/libc/intrin/describestat.c
similarity index 95%
rename from libc/intrin/describestat.greg.c
rename to libc/intrin/describestat.c
index d2c1190f9..6e93e0e32 100644
--- a/libc/intrin/describestat.greg.c
+++ b/libc/intrin/describestat.c
@@ -21,20 +21,19 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
-const char *DescribeStat(int rc, const struct stat *st) {
- _Alignas(char) static char buf[300];
+const char *(DescribeStat)(char buf[300], int rc, const struct stat *st) {
int i, n;
if (rc == -1) return "n/a";
if (!st) return "NULL";
if ((!IsAsan() && kisdangerous(st)) ||
(IsAsan() && !__asan_is_valid(st, sizeof(*st)))) {
- ksnprintf(buf, sizeof(buf), "%p", st);
+ ksnprintf(buf, 300, "%p", st);
return buf;
}
i = 0;
- n = sizeof(buf);
+ n = 300;
i += ksnprintf(buf + i, n - i, "{.st_%s=%'ld", "size", st->st_size);
diff --git a/libc/intrin/describetimespec.greg.c b/libc/intrin/describetimespec.c
similarity index 90%
rename from libc/intrin/describetimespec.greg.c
rename to libc/intrin/describetimespec.c
index e9470461b..2eae307cd 100644
--- a/libc/intrin/describetimespec.greg.c
+++ b/libc/intrin/describetimespec.c
@@ -21,15 +21,15 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
-const char *DescribeTimespec(char *buf, size_t bufsize, int rc,
- const struct timespec *ts) {
+const char *(DescribeTimespec)(char buf[45], int rc,
+ const struct timespec *ts) {
if (rc == -1) return "n/a";
if (!ts) return "NULL";
if ((!IsAsan() && kisdangerous(ts)) ||
(IsAsan() && !__asan_is_valid(ts, sizeof(*ts)))) {
- ksnprintf(buf, bufsize, "%p", ts);
+ ksnprintf(buf, 45, "%p", ts);
} else {
- ksnprintf(buf, bufsize, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec);
+ ksnprintf(buf, 45, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec);
}
return buf;
}
diff --git a/libc/intrin/deviceiocontrol.greg.c b/libc/intrin/deviceiocontrol.c
similarity index 100%
rename from libc/intrin/deviceiocontrol.greg.c
rename to libc/intrin/deviceiocontrol.c
diff --git a/libc/intrin/dos2errno.greg.c b/libc/intrin/dos2errno.c
similarity index 100%
rename from libc/intrin/dos2errno.greg.c
rename to libc/intrin/dos2errno.c
diff --git a/libc/intrin/exit1.greg.c b/libc/intrin/exit1.greg.c
index 4d582eda7..115a58a6a 100644
--- a/libc/intrin/exit1.greg.c
+++ b/libc/intrin/exit1.greg.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
+#include "libc/intrin/kprintf.h"
#include "libc/nt/thread.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/nr.h"
diff --git a/libc/intrin/findfirstfile.c b/libc/intrin/findfirstfile.c
index 02a431208..ed7afc317 100644
--- a/libc/intrin/findfirstfile.c
+++ b/libc/intrin/findfirstfile.c
@@ -35,15 +35,14 @@ textwindows int64_t FindFirstFile(const char16_t *lpFileName,
int64_t hFindFile;
hFindFile = __imp_FindFirstFileW(lpFileName, out_lpFindFileData);
if (hFindFile != -1) {
- NTTRACE(
- "FindFirstFile(%#hs, [{"
- ".cFileName=%#hs, "
- ".dwFileAttributes=%s, "
- ".dwFileType=%s"
- "}]) → %ld% m",
- lpFileName, out_lpFindFileData->cFileName,
- DescribeNtFileFlagsAndAttributes(out_lpFindFileData->dwFileAttributes),
- DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), hFindFile);
+ NTTRACE("FindFirstFile(%#hs, [{"
+ ".cFileName=%#hs, "
+ ".dwFileAttributes=%s, "
+ ".dwFileType=%s"
+ "}]) → %ld% m",
+ lpFileName, out_lpFindFileData->cFileName,
+ DescribeNtFileFlagAttr(out_lpFindFileData->dwFileAttributes),
+ DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), hFindFile);
} else {
__winerr();
NTTRACE("FindFirstFile(%#hs, [n/a]) → %ld% m", lpFileName, hFindFile);
diff --git a/libc/intrin/findnextfile.c b/libc/intrin/findnextfile.c
index 5f3f0b08b..d940ae1bb 100644
--- a/libc/intrin/findnextfile.c
+++ b/libc/intrin/findnextfile.c
@@ -37,15 +37,14 @@ textwindows bool32 FindNextFile(int64_t hFindFile,
bool32 ok;
ok = __imp_FindNextFileW(hFindFile, out_lpFindFileData);
if (ok) {
- NTTRACE(
- "FindNextFile(%ld, [{"
- ".cFileName=%#hs, "
- ".dwFileAttributes=%s, "
- ".dwFileType=%s"
- "}]) → %hhhd% m",
- hFindFile, out_lpFindFileData->cFileName,
- DescribeNtFileFlagsAndAttributes(out_lpFindFileData->dwFileAttributes),
- DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), ok);
+ NTTRACE("FindNextFile(%ld, [{"
+ ".cFileName=%#hs, "
+ ".dwFileAttributes=%s, "
+ ".dwFileType=%s"
+ "}]) → %hhhd% m",
+ hFindFile, out_lpFindFileData->cFileName,
+ DescribeNtFileFlagAttr(out_lpFindFileData->dwFileAttributes),
+ DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), ok);
} else {
if (GetLastError() != kNtErrorNoMoreFiles) __winerr();
NTTRACE("FindNextFile(%ld) → %hhhd% m", hFindFile, ok);
diff --git a/libc/intrin/futex.S b/libc/intrin/futex.S
new file mode 100644
index 000000000..b071ddee4
--- /dev/null
+++ b/libc/intrin/futex.S
@@ -0,0 +1,28 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/sysv/consts/nr.h"
+#include "libc/macros.internal.h"
+
+_futex: mov __NR_futex,%eax
+ clc
+ syscall
+ jnc 1f
+ neg %eax
+1: ret
+ .endfn _futex,globl,hidden
diff --git a/libc/intrin/futex.internal.h b/libc/intrin/futex.internal.h
index cb4d4714a..1dd8f0573 100644
--- a/libc/intrin/futex.internal.h
+++ b/libc/intrin/futex.internal.h
@@ -4,8 +4,9 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
-int _futex_wait(void *, int, struct timespec *);
-int _futex_wake(void *, int);
+int _futex(void *, int, int, struct timespec *, int *) hidden;
+int _futex_wait(void *, int, struct timespec *) hidden;
+int _futex_wake(void *, int) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
diff --git a/libc/intrin/futex_wait.c b/libc/intrin/futex_wait.c
index 10259f05e..96cabc701 100644
--- a/libc/intrin/futex_wait.c
+++ b/libc/intrin/futex_wait.c
@@ -16,29 +16,29 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/bits/asmflag.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/timespec.h"
+#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/futex.internal.h"
+#include "libc/mem/alloca.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/futex.h"
-#include "libc/sysv/consts/nr.h"
-privileged int _futex_wait(void *addr, int expect, struct timespec *timeout) {
+static const char *DescribeFutexWaitResult(char buf[12], int ax) {
+ const char *s;
+ if (ax && ((s = strerrno(ax)) || (s = strerrno(-ax)))) {
+ return s;
+ } else {
+ FormatInt32(buf, ax);
+ return buf;
+ }
+}
+
+int _futex_wait(void *addr, int expect, struct timespec *timeout) {
int ax;
- bool cf;
- char buf[45];
- asm volatile(CFLAG_ASM("mov\t%6,%%r10\n\t"
- "clc\n\t"
- "syscall")
- : CFLAG_CONSTRAINT(cf), "=a"(ax)
- : "1"(__NR_futex), "D"(addr), "S"(FUTEX_WAIT), "d"(expect),
- "g"(timeout)
- : "rcx", "r10", "r11", "memory");
- if (cf) ax = -ax;
- STRACE("futex(%p, FUTEX_WAIT, %d, %s) → %s", addr, expect,
- DescribeTimespec(buf, sizeof(buf), 0, timeout),
- ax ? strerrno(-ax) : "0");
+ ax = _futex(addr, FUTEX_WAIT, expect, timeout, 0);
+ STRACE("futex(%t[%p], FUTEX_WAIT, %d, %s) → %s", addr, addr, expect,
+ DescribeTimespec(0, timeout), DescribeFutexWaitResult(alloca(12), ax));
return ax;
}
diff --git a/libc/intrin/futex_wake.c b/libc/intrin/futex_wake.c
index 974125299..bbfaf0d3f 100644
--- a/libc/intrin/futex_wake.c
+++ b/libc/intrin/futex_wake.c
@@ -19,31 +19,27 @@
#include "libc/bits/asmflag.h"
#include "libc/calls/strace.internal.h"
#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/futex.internal.h"
+#include "libc/mem/alloca.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/futex.h"
#include "libc/sysv/consts/nr.h"
-static const char *FormatFutexWakeResult(char buf[12], int ax) {
- if (ax >= 0) {
+static const char *DescribeFutexWakeResult(char buf[12], int ax) {
+ const char *s;
+ if (ax < 0 && (s = strerrno(ax))) {
+ return s;
+ } else {
FormatInt32(buf, ax);
return buf;
- } else {
- return strerrno(-ax);
}
}
-privileged int _futex_wake(void *addr, int count) {
+int _futex_wake(void *addr, int count) {
int ax;
- bool cf;
- char buf[12];
- asm volatile(CFLAG_ASM("clc\n\t"
- "syscall")
- : CFLAG_CONSTRAINT(cf), "=a"(ax)
- : "1"(__NR_futex), "D"(addr), "S"(FUTEX_WAKE), "d"(count)
- : "rcx", "r11", "memory");
- if (cf) ax = -ax;
- STRACE("futex(%p, FUTEX_WAKE, %d) → %s", addr, count,
- FormatFutexWakeResult(buf, ax));
+ ax = _futex(addr, FUTEX_WAKE, count, 0, 0);
+ STRACE("futex(%t[%p], FUTEX_WAKE, %d) → %s", addr, addr, count,
+ DescribeFutexWakeResult(alloca(12), ax));
return ax;
}
diff --git a/libc/intrin/getfileattributes.c b/libc/intrin/getfileattributes.c
index 943ce0f9e..10f878149 100644
--- a/libc/intrin/getfileattributes.c
+++ b/libc/intrin/getfileattributes.c
@@ -36,6 +36,6 @@ textwindows uint32_t GetFileAttributes(const char16_t *lpPathName) {
flags = __imp_GetFileAttributesW(lpPathName);
if (flags == -1u) __winerr();
NTTRACE("GetFileAttributes(%#hs) → %s% m", lpPathName,
- DescribeNtFileFlagsAndAttributes(flags));
+ DescribeNtFileFlagAttr(flags));
return flags;
}
diff --git a/libc/intrin/getmagnumstr.greg.c b/libc/intrin/getmagnumstr.c
similarity index 96%
rename from libc/intrin/getmagnumstr.greg.c
rename to libc/intrin/getmagnumstr.c
index 7bcbbc542..20834e936 100644
--- a/libc/intrin/getmagnumstr.greg.c
+++ b/libc/intrin/getmagnumstr.c
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/magnumstrs.internal.h"
-privileged char *GetMagnumStr(const struct MagnumStr *ms, int x) {
+char *GetMagnumStr(const struct MagnumStr *ms, int x) {
int i;
for (i = 0; ms[i].x != MAGNUM_TERMINATOR; ++i) {
if (x == MAGNUM_NUMBER(ms, i)) {
diff --git a/libc/intrin/gettid.greg.c b/libc/intrin/gettid.greg.c
index ad4cb6c01..3e5f32368 100644
--- a/libc/intrin/gettid.greg.c
+++ b/libc/intrin/gettid.greg.c
@@ -16,15 +16,12 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/calls/calls.h"
+#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/threaded.h"
-#include "libc/nt/thread.h"
-#include "libc/nt/thunk/msabi.h"
-#include "libc/runtime/internal.h"
-
-__msabi extern typeof(GetCurrentThreadId) *const __imp_GetCurrentThreadId;
/**
* Returns current thread id.
@@ -54,60 +51,10 @@ __msabi extern typeof(GetCurrentThreadId) *const __imp_GetCurrentThreadId;
* @threadsafe
*/
privileged int gettid(void) {
- int rc;
- int64_t wut;
- struct WinThread *wt;
-
+ int tid;
if (__tls_enabled) {
- rc = *(int *)(__get_tls_inline() + 0x38);
- return rc;
+ tid = *(int *)(__get_tls_inline() + 0x38);
+ if (tid > 0) return tid;
}
-
- if (IsWindows()) {
- return __imp_GetCurrentThreadId();
- }
-
- if (IsLinux()) {
- asm("syscall"
- : "=a"(rc) // man says always succeeds
- : "0"(186) // __NR_gettid
- : "rcx", "r11", "memory");
- return rc;
- }
-
- if (IsXnu()) {
- asm("syscall" // xnu/osfmk/kern/ipc_tt.c
- : "=a"(rc) // assume success
- : "0"(0x1000000 | 27) // Mach thread_self_trap()
- : "rcx", "r11", "memory", "cc");
- return rc;
- }
-
- if (IsOpenbsd()) {
- asm("syscall"
- : "=a"(rc) // man says always succeeds
- : "0"(299) // getthrid()
- : "rcx", "r11", "memory", "cc");
- return rc;
- }
-
- if (IsNetbsd()) {
- asm("syscall"
- : "=a"(rc) // man says always succeeds
- : "0"(311) // _lwp_self()
- : "rcx", "rdx", "r11", "memory", "cc");
- return rc;
- }
-
- if (IsFreebsd()) {
- asm("syscall"
- : "=a"(rc), // only fails w/ EFAULT, which isn't possible
- "=m"(wut) // must be 64-bit
- : "0"(432), // thr_self()
- "D"(&wut) // but not actually 64-bit
- : "rcx", "r11", "memory", "cc");
- return wut; // narrowing intentional
- }
-
- return __pid;
+ return sys_gettid();
}
diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk
index dc5434378..6928d282a 100644
--- a/libc/intrin/intrin.mk
+++ b/libc/intrin/intrin.mk
@@ -28,7 +28,8 @@ LIBC_INTRIN_A_DIRECTDEPS = \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_NEXGEN32E \
- LIBC_NT_KERNEL32
+ LIBC_NT_KERNEL32 \
+ LIBC_NT_WS2_32
LIBC_INTRIN_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x))))
@@ -76,6 +77,7 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: \
o/$(MODE)/libc/intrin/futex_wait.o \
o/$(MODE)/libc/intrin/futex_wake.o \
o/$(MODE)/libc/intrin/gettid.greg.o \
+o/$(MODE)/libc/intrin/sys_gettid.greg.o \
o/$(MODE)/libc/intrin/pthread_mutex_lock.o \
o/$(MODE)/libc/intrin/pthread_mutex_unlock.o \
o/$(MODE)/libc/intrin/pthread_mutex_trylock.o \
@@ -97,18 +99,21 @@ o/$(MODE)/libc/intrin/restorewintty.o: \
OVERRIDE_CFLAGS += \
-fno-sanitize=all
+# we can't use asan because:
+# sys_mmap() calls these which sets up shadow memory
+o/$(MODE)/libc/intrin/describeflags.o \
+o/$(MODE)/libc/intrin/describeframe.o \
+o/$(MODE)/libc/intrin/describemapflags.o \
+o/$(MODE)/libc/intrin/describeprotflags.o: \
+ OVERRIDE_CFLAGS += \
+ -fno-sanitize=address
+
o/$(MODE)/libc/intrin/tls.greg.o \
o/$(MODE)/libc/intrin/exit.greg.o \
o/$(MODE)/libc/intrin/exit1.greg.o \
o/$(MODE)/libc/intrin/getenv.greg.o \
-o/$(MODE)/libc/intrin/assertfail.greg.o \
-o/$(MODE)/libc/intrin/describeiov.greg.o \
-o/$(MODE)/libc/intrin/describestat.greg.o \
-o/$(MODE)/libc/intrin/describeflags.greg.o \
-o/$(MODE)/libc/intrin/describerlimit.greg.o \
-o/$(MODE)/libc/intrin/deviceiocontrol.greg.o \
-o/$(MODE)/libc/intrin/describemapflags.greg.o \
-o/$(MODE)/libc/intrin/describetimespec.greg.o \
+o/$(MODE)/libc/intrin/wsarecv.o \
+o/$(MODE)/libc/intrin/wsarecvfrom.o \
o/$(MODE)/libc/intrin/createfile.o \
o/$(MODE)/libc/intrin/reopenfile.o \
o/$(MODE)/libc/intrin/deletefile.o \
@@ -140,6 +145,7 @@ o/$(MODE)/libc/intrin/createfilemapping.o \
o/$(MODE)/libc/intrin/createfilemappingnuma.o \
o/$(MODE)/libc/intrin/waitformultipleobjects.o \
o/$(MODE)/libc/intrin/generateconsolectrlevent.o \
+o/$(MODE)/libc/intrin/wsawaitformultipleevents.o \
o/$(MODE)/libc/intrin/kstarttsc.o \
o/$(MODE)/libc/intrin/nomultics.o \
o/$(MODE)/libc/intrin/ntconsolemode.o: \
@@ -150,10 +156,6 @@ o/$(MODE)/libc/intrin/ntconsolemode.o: \
-fno-stack-protector \
-fno-sanitize=all
-o/$(MODE)/libc/intrin/describeopenflags.greg.o: \
- OVERRIDE_CPPFLAGS += \
- -DSTACK_FRAME_UNLIMITED
-
o//libc/intrin/memmove.o: \
OVERRIDE_CFLAGS += \
-fno-toplevel-reorder
diff --git a/libc/calls/kclocknames.S b/libc/intrin/kclocknames.S
similarity index 100%
rename from libc/calls/kclocknames.S
rename to libc/intrin/kclocknames.S
diff --git a/libc/sock/kipoptnames.S b/libc/intrin/kipoptnames.S
similarity index 100%
rename from libc/sock/kipoptnames.S
rename to libc/intrin/kipoptnames.S
diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c
index 2e94ea839..dcddd6bc2 100644
--- a/libc/intrin/kprintf.greg.c
+++ b/libc/intrin/kprintf.greg.c
@@ -23,6 +23,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/state.internal.h"
+#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/divmod10.internal.h"
diff --git a/libc/str/ksignalnames.S b/libc/intrin/ksignalnames.S
similarity index 73%
rename from libc/str/ksignalnames.S
rename to libc/intrin/ksignalnames.S
index 0e58a1b70..881a08575 100644
--- a/libc/str/ksignalnames.S
+++ b/libc/intrin/ksignalnames.S
@@ -31,41 +31,41 @@
.align 4
.underrun
kSignalNames:
- .e SIGHUP,"HUP"
- .e SIGINT,"INT"
- .e SIGQUIT,"QUIT"
- .e SIGILL,"ILL"
- .e SIGTRAP,"TRAP"
- .e SIGABRT,"ABRT"
- .e SIGBUS,"BUS"
- .e SIGFPE,"FPE"
- .e SIGKILL,"KILL"
- .e SIGUSR1,"USR1"
- .e SIGSEGV,"SEGV"
- .e SIGUSR2,"USR2"
- .e SIGPIPE,"PIPE"
- .e SIGALRM,"ALRM"
- .e SIGTERM,"TERM"
- .e SIGSTKFLT,"STKFLT"
- .e SIGCHLD,"CHLD"
- .e SIGCONT,"CONT"
- .e SIGSTOP,"STOP"
- .e SIGTSTP,"TSTP"
- .e SIGTTIN,"TTIN"
- .e SIGTTOU,"TTOU"
- .e SIGURG,"URG"
- .e SIGXCPU,"XCPU"
- .e SIGXFSZ,"XFSZ"
- .e SIGVTALRM,"VTALRM"
- .e SIGPROF,"PROF"
- .e SIGWINCH,"WINCH"
- .e SIGIO,"IO"
- .e SIGSYS,"SYS"
- .e SIGINFO,"INFO"
- .e SIGRTMAX,"RTMAX"
- .e SIGRTMIN,"RTMIN"
- .e SIGEMT,"EMT"
- .e SIGPWR,"PWR"
+ .e SIGHUP,"SIGHUP"
+ .e SIGINT,"SIGINT"
+ .e SIGQUIT,"SIGQUIT"
+ .e SIGILL,"SIGILL"
+ .e SIGTRAP,"SIGTRAP"
+ .e SIGABRT,"SIGABRT"
+ .e SIGBUS,"SIGBUS"
+ .e SIGFPE,"SIGFPE"
+ .e SIGKILL,"SIGKILL"
+ .e SIGUSR1,"SIGUSR1"
+ .e SIGSEGV,"SIGSEGV"
+ .e SIGUSR2,"SIGUSR2"
+ .e SIGPIPE,"SIGPIPE"
+ .e SIGALRM,"SIGALRM"
+ .e SIGTERM,"SIGTERM"
+ .e SIGSTKFLT,"SIGSTKFLT"
+ .e SIGCHLD,"SIGCHLD"
+ .e SIGCONT,"SIGCONT"
+ .e SIGSTOP,"SIGSTOP"
+ .e SIGTSTP,"SIGTSTP"
+ .e SIGTTIN,"SIGTTIN"
+ .e SIGTTOU,"SIGTTOU"
+ .e SIGURG,"SIGURG"
+ .e SIGXCPU,"SIGXCPU"
+ .e SIGXFSZ,"SIGXFSZ"
+ .e SIGVTALRM,"SIGVTALRM"
+ .e SIGPROF,"SIGPROF"
+ .e SIGWINCH,"SIGWINCH"
+ .e SIGIO,"SIGIO"
+ .e SIGSYS,"SIGSYS"
+ .e SIGINFO,"SIGINFO"
+ .e SIGRTMAX,"SIGRTMAX"
+ .e SIGRTMIN,"SIGRTMIN"
+ .e SIGEMT,"SIGEMT"
+ .e SIGPWR,"SIGPWR"
.long MAGNUM_TERMINATOR
.endobj kSignalNames,globl,hidden
.overrun
diff --git a/libc/sock/ksockoptnames.S b/libc/intrin/ksockoptnames.S
similarity index 100%
rename from libc/sock/ksockoptnames.S
rename to libc/intrin/ksockoptnames.S
diff --git a/libc/sock/ktcpoptnames.S b/libc/intrin/ktcpoptnames.S
similarity index 100%
rename from libc/sock/ktcpoptnames.S
rename to libc/intrin/ktcpoptnames.S
diff --git a/libc/intrin/movefileex.c b/libc/intrin/movefileex.c
index 5eb10ab26..7975516cf 100644
--- a/libc/intrin/movefileex.c
+++ b/libc/intrin/movefileex.c
@@ -35,6 +35,6 @@ textwindows bool32 MoveFileEx(const char16_t *lpExistingFileName,
ok = __imp_MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags);
if (!ok) __winerr();
NTTRACE("MoveFileEx(%#hs, %#hs, %s) → %hhhd% m", lpExistingFileName,
- lpNewFileName, DescribeNtMoveFileInputFlags(dwFlags), ok);
+ lpNewFileName, DescribeNtMovFileInpFlags(dwFlags), ok);
return ok;
}
diff --git a/libc/intrin/openprocess.c b/libc/intrin/openprocess.c
index 44f570c19..d6463a28c 100644
--- a/libc/intrin/openprocess.c
+++ b/libc/intrin/openprocess.c
@@ -40,7 +40,7 @@ textwindows int64_t OpenProcess(uint32_t dwDesiredAccess, bool32 bInheritHandle,
hHandle = __imp_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
if (!hHandle) __winerr();
NTTRACE("OpenProcess(%s, %hhhd, %u) → %ld% m",
- DescribeNtProcessAccessFlags(dwDesiredAccess), bInheritHandle,
+ DescribeNtProcAccessFlags(dwDesiredAccess), bInheritHandle,
dwProcessId, hHandle);
return hHandle;
}
diff --git a/libc/intrin/pthread.h b/libc/intrin/pthread.h
index 684fa29a4..1e47e0143 100644
--- a/libc/intrin/pthread.h
+++ b/libc/intrin/pthread.h
@@ -126,16 +126,15 @@ void *pthread_getspecific(pthread_key_t);
!atomic_exchange(&(mutex)->lock, 1)) \
? 0 \
: pthread_mutex_lock(mutex))
-/*
+
#define pthread_mutex_unlock(mutex) \
((mutex)->attr == PTHREAD_MUTEX_NORMAL \
? (atomic_store_explicit(&(mutex)->lock, 0, memory_order_relaxed), \
- ((IsLinux() || IsOpenbsd()) && \
+ ((IsLinux() /* || IsOpenbsd() */) && \
atomic_load_explicit(&(mutex)->waits, memory_order_relaxed) && \
_pthread_mutex_wake(mutex)), \
0) \
: pthread_mutex_unlock(mutex))
-*/
#endif
int _pthread_mutex_wake(pthread_mutex_t *) hidden;
diff --git a/libc/intrin/pthread_mutex_destroy.c b/libc/intrin/pthread_mutex_destroy.c
index 5633c7780..18c8636dc 100644
--- a/libc/intrin/pthread_mutex_destroy.c
+++ b/libc/intrin/pthread_mutex_destroy.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/errno.h"
#include "libc/intrin/pthread.h"
#include "libc/str/str.h"
@@ -29,6 +30,7 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex) {
if (!mutex->lock && !mutex->waits) {
rc = 0;
} else {
+ assert(!"dead lock");
rc = EDEADLK;
}
bzero(mutex, sizeof(*mutex));
diff --git a/libc/intrin/pthread_mutex_lock.c b/libc/intrin/pthread_mutex_lock.c
index b0399f583..6720e39a4 100644
--- a/libc/intrin/pthread_mutex_lock.c
+++ b/libc/intrin/pthread_mutex_lock.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/bits/asmflag.h"
#include "libc/bits/atomic.h"
#include "libc/calls/calls.h"
@@ -29,15 +30,16 @@
#include "libc/sysv/consts/futex.h"
#include "libc/sysv/consts/nr.h"
-static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int tries) {
+static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int expect,
+ int tries) {
volatile int i;
if (tries < 7) {
for (i = 0; i != 1 << tries; i++) {
}
tries++;
- } else if (IsLinux() || IsOpenbsd()) {
+ } else if (IsLinux() /* || IsOpenbsd() */) {
atomic_fetch_add(&mutex->waits, 1);
- _futex_wait(&mutex->lock, 1, &(struct timespec){1});
+ _futex_wait(&mutex->lock, expect, &(struct timespec){1});
atomic_fetch_sub(&mutex->waits, 1);
} else {
sched_yield();
@@ -64,7 +66,7 @@ int(pthread_mutex_lock)(pthread_mutex_t *mutex) {
!atomic_exchange_explicit(&mutex->lock, 1, memory_order_acquire)) {
break;
}
- tries = pthread_mutex_lock_spin(mutex, tries);
+ tries = pthread_mutex_lock_spin(mutex, 1, tries);
}
return 0;
case PTHREAD_MUTEX_RECURSIVE:
@@ -79,14 +81,16 @@ int(pthread_mutex_lock)(pthread_mutex_t *mutex) {
if (mutex->attr != PTHREAD_MUTEX_ERRORCHECK) {
break;
} else {
+ assert(!"dead lock");
return EDEADLK;
}
}
- tries = pthread_mutex_lock_spin(mutex, tries);
+ tries = pthread_mutex_lock_spin(mutex, owner, tries);
}
++mutex->reent;
return 0;
default:
+ assert(!"inva lock");
return EINVAL;
}
}
diff --git a/libc/intrin/pthread_mutex_unlock.c b/libc/intrin/pthread_mutex_unlock.c
index 2556c045f..ab6e399cf 100644
--- a/libc/intrin/pthread_mutex_unlock.c
+++ b/libc/intrin/pthread_mutex_unlock.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/bits/atomic.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
@@ -33,19 +34,23 @@ int(pthread_mutex_unlock)(pthread_mutex_t *mutex) {
case PTHREAD_MUTEX_ERRORCHECK:
me = gettid();
owner = atomic_load_explicit(&mutex->lock, memory_order_relaxed);
- if (owner != me) return EPERM;
+ if (owner != me) {
+ assert(!"perm lock");
+ return EPERM;
+ }
// fallthrough
case PTHREAD_MUTEX_RECURSIVE:
if (--mutex->reent) return 0;
// fallthrough
case PTHREAD_MUTEX_NORMAL:
atomic_store_explicit(&mutex->lock, 0, memory_order_relaxed);
- if ((IsLinux() || IsOpenbsd()) &&
+ if ((IsLinux() /* || IsOpenbsd() */) &&
atomic_load_explicit(&mutex->waits, memory_order_relaxed) > 0) {
_pthread_mutex_wake(mutex);
}
return 0;
default:
+ assert(!"inva lock");
return EINVAL;
}
}
diff --git a/libc/intrin/pthread_mutex_wake.c b/libc/intrin/pthread_mutex_wake.c
index e6d0d40dd..0a2b5e3b0 100644
--- a/libc/intrin/pthread_mutex_wake.c
+++ b/libc/intrin/pthread_mutex_wake.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/atomic.h"
#include "libc/intrin/futex.internal.h"
#include "libc/intrin/pthread.h"
diff --git a/libc/intrin/reopenfile.c b/libc/intrin/reopenfile.c
index 2aef55ebd..5abc149fe 100644
--- a/libc/intrin/reopenfile.c
+++ b/libc/intrin/reopenfile.c
@@ -39,6 +39,6 @@ int64_t ReOpenFile(int64_t hOriginalFile, uint32_t dwDesiredAccess,
NTTRACE("ReOpenFile(%ld, %s, %s, %s) → %ld% m", hOriginalFile,
DescribeNtFileAccessFlags(dwDesiredAccess),
DescribeNtFileShareFlags(dwShareMode),
- DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes), hHandle);
+ DescribeNtFileFlagAttr(dwFlagsAndAttributes), hHandle);
return hHandle;
}
diff --git a/libc/calls/sigaddset.c b/libc/intrin/sigaddset.c
similarity index 100%
rename from libc/calls/sigaddset.c
rename to libc/intrin/sigaddset.c
diff --git a/libc/calls/sigdelset.c b/libc/intrin/sigdelset.c
similarity index 100%
rename from libc/calls/sigdelset.c
rename to libc/intrin/sigdelset.c
diff --git a/libc/calls/sigemptyset.c b/libc/intrin/sigemptyset.c
similarity index 100%
rename from libc/calls/sigemptyset.c
rename to libc/intrin/sigemptyset.c
diff --git a/libc/calls/sigfillset.c b/libc/intrin/sigfillset.c
similarity index 100%
rename from libc/calls/sigfillset.c
rename to libc/intrin/sigfillset.c
diff --git a/libc/calls/sigismember.c b/libc/intrin/sigismember.c
similarity index 100%
rename from libc/calls/sigismember.c
rename to libc/intrin/sigismember.c
diff --git a/libc/str/strsignal.greg.c b/libc/intrin/strsignal.c
similarity index 88%
rename from libc/str/strsignal.greg.c
rename to libc/intrin/strsignal.c
index 6339d9da3..019b86d55 100644
--- a/libc/str/strsignal.greg.c
+++ b/libc/intrin/strsignal.c
@@ -21,15 +21,6 @@
static char g_strsignal[12];
-static inline char *StpCpy(char *d, const char *s) {
- size_t i;
- for (i = 0;; ++i) {
- if (!(d[i] = s[i])) {
- return d + i;
- }
- }
-}
-
/**
* Returns string describing signal code.
*
@@ -37,26 +28,24 @@ static inline char *StpCpy(char *d, const char *s) {
* should be available for signals 1 through 32. Signals in the range 33
* and 128 are returned as a `SIG%03d` string. Everything else is SIGWUT
*
+ * This function is thread safe when `sig` is a known signal magnum.
+ * Otherwise a pointer to static memory is returned which is unsafe.
+ *
* @param sig is signal number which should be in range 1 through 128
* @return pointer to static memory that mutates on subsequent calls
* @see sigaction()
+ * @threadsafe
*/
-privileged char *strsignal(int sig) {
- // we need privileged because:
- // kprintf is privileged and it depends on this
+char *strsignal(int sig) {
char *p;
const char *s;
+ if (!sig) return "0";
+ if ((s = GetMagnumStr(kSignalNames, sig))) return s;
p = g_strsignal;
p[0] = 'S';
p[1] = 'I';
p[2] = 'G';
p[3] = 0;
- if (sig) {
- if ((s = GetMagnumStr(kSignalNames, sig))) {
- StpCpy(p + 3, s);
- return p;
- }
- }
if (!sig) {
p[3] = 'Z';
p[4] = 'E';
diff --git a/libc/intrin/sys_gettid.greg.c b/libc/intrin/sys_gettid.greg.c
new file mode 100644
index 000000000..eb57853f1
--- /dev/null
+++ b/libc/intrin/sys_gettid.greg.c
@@ -0,0 +1,64 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/syscall-sysv.internal.h"
+#include "libc/dce.h"
+#include "libc/nt/thread.h"
+#include "libc/nt/thunk/msabi.h"
+#include "libc/runtime/internal.h"
+
+__msabi extern typeof(GetCurrentThreadId) *const __imp_GetCurrentThreadId;
+
+privileged int sys_gettid(void) {
+ int tid;
+ int64_t wut;
+ if (IsWindows()) {
+ tid = __imp_GetCurrentThreadId();
+ } else if (IsLinux()) {
+ asm("syscall"
+ : "=a"(tid) // man says always succeeds
+ : "0"(186) // __NR_gettid
+ : "rcx", "r11", "memory");
+ } else if (IsXnu()) {
+ asm("syscall" // xnu/osfmk/kern/ipc_tt.c
+ : "=a"(tid) // assume success
+ : "0"(0x1000000 | 27) // Mach thread_self_trap()
+ : "rcx", "r11", "memory", "cc");
+ } else if (IsOpenbsd()) {
+ asm("syscall"
+ : "=a"(tid) // man says always succeeds
+ : "0"(299) // getthrid()
+ : "rcx", "r11", "memory", "cc");
+ } else if (IsNetbsd()) {
+ asm("syscall"
+ : "=a"(tid) // man says always succeeds
+ : "0"(311) // _lwp_self()
+ : "rcx", "rdx", "r11", "memory", "cc");
+ } else if (IsFreebsd()) {
+ asm("syscall"
+ : "=a"(tid), // only fails w/ EFAULT, which isn't possible
+ "=m"(wut) // must be 64-bit
+ : "0"(432), // thr_self()
+ "D"(&wut) // but not actually 64-bit
+ : "rcx", "r11", "memory", "cc");
+ tid = wut;
+ } else {
+ tid = __pid;
+ }
+ return tid;
+}
diff --git a/libc/intrin/tls.greg.c b/libc/intrin/tls.greg.c
index 6e35fe987..a15bf9575 100644
--- a/libc/intrin/tls.greg.c
+++ b/libc/intrin/tls.greg.c
@@ -49,7 +49,7 @@
*/
privileged void *__initialize_tls(char tib[64]) {
if (tib) {
- *(intptr_t *)tib = (intptr_t)tib;
+ *(intptr_t *)(tib + 0x00) = (intptr_t)tib;
*(intptr_t *)(tib + 0x30) = (intptr_t)tib;
*(int *)(tib + 0x38) = -1; // tid
*(int *)(tib + 0x3c) = 0;
diff --git a/libc/intrin/virtualprotect.c b/libc/intrin/virtualprotect.c
index d43cf2ab3..f7cec63ab 100644
--- a/libc/intrin/virtualprotect.c
+++ b/libc/intrin/virtualprotect.c
@@ -24,11 +24,6 @@
__msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
-static const char *DescribeVpFlags(uint32_t *x) {
- if (!x) return "n/a";
- return DescribeNtPageFlags(*x);
-}
-
/**
* Protects memory on the New Technology.
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
@@ -42,6 +37,6 @@ textwindows bool32 VirtualProtect(void *lpAddress, uint64_t dwSize,
if (!bOk) __winerr();
NTTRACE("VirtualProtect(%p, %'zu, %s, [%s]) → %hhhd% m", lpAddress, dwSize,
DescribeNtPageFlags(flNewProtect),
- DescribeVpFlags(bOk ? lpflOldProtect : 0), bOk);
+ DescribeNtPageFlags(*lpflOldProtect), bOk);
return bOk;
}
diff --git a/libc/intrin/wait0.c b/libc/intrin/wait0.c
index d5ba99673..f48d4d391 100644
--- a/libc/intrin/wait0.c
+++ b/libc/intrin/wait0.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/bits/atomic.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
@@ -30,12 +31,12 @@
* by the clone() system call when a thread terminates. The purpose of
* this operation is to know when it's safe to munmap() a thread stack.
*/
-void _wait0(int *ptid) {
+void _wait0(const int *ptid) {
int x;
for (;;) {
- if (!(x = atomic_load_explicit(ptid, memory_order_relaxed))) {
+ if (!(x = atomic_load_explicit(ptid, memory_order_acquire))) {
break;
- } else if (IsLinux() || IsOpenbsd()) {
+ } else if (IsLinux() /* || IsOpenbsd() */) {
_futex_wait(ptid, x, &(struct timespec){2});
} else {
sched_yield();
diff --git a/libc/intrin/wait0.internal.h b/libc/intrin/wait0.internal.h
index d47cd3e82..70772a853 100644
--- a/libc/intrin/wait0.internal.h
+++ b/libc/intrin/wait0.internal.h
@@ -3,7 +3,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
-void _wait0(int *) hidden;
+void _wait0(const int *) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
diff --git a/libc/intrin/wsarecv.c b/libc/intrin/wsarecv.c
new file mode 100644
index 000000000..a7292ec0d
--- /dev/null
+++ b/libc/intrin/wsarecv.c
@@ -0,0 +1,68 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/strace.internal.h"
+#include "libc/calls/syscall_support-nt.internal.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/intrin/kprintf.h"
+#include "libc/nt/thunk/msabi.h"
+#include "libc/nt/winsock.h"
+
+__msabi extern typeof(WSARecv) *const __imp_WSARecv;
+
+/**
+ * Receives data from Windows socket.
+ *
+ * @return 0 on success, or -1 on failure
+ * @note this wrapper takes care of ABI, STRACE(), and __winerr()
+ */
+textwindows int WSARecv(
+ uint64_t s, const struct NtIovec *inout_lpBuffers, uint32_t dwBufferCount,
+ uint32_t *opt_out_lpNumberOfBytesRecvd, uint32_t *inout_lpFlags,
+ struct NtOverlapped *opt_inout_lpOverlapped,
+ const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine) {
+ int rc;
+#if defined(SYSDEBUG) && _NTTRACE
+ uint32_t NumberOfBytesRecvd;
+ if (opt_out_lpNumberOfBytesRecvd) {
+ NumberOfBytesRecvd = *opt_out_lpNumberOfBytesRecvd;
+ }
+ rc = __imp_WSARecv(s, inout_lpBuffers, dwBufferCount, &NumberOfBytesRecvd,
+ inout_lpFlags, opt_inout_lpOverlapped,
+ opt_lpCompletionRoutine);
+ if (opt_out_lpNumberOfBytesRecvd) {
+ *opt_out_lpNumberOfBytesRecvd = NumberOfBytesRecvd;
+ }
+ if (rc == -1) {
+ __winerr();
+ }
+ if (UNLIKELY(__strace > 0)) {
+ kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s);
+ DescribeIovNt(inout_lpBuffers, dwBufferCount,
+ rc != -1 ? NumberOfBytesRecvd : 0);
+ kprintf("], %u, [%'u], %p, %p, %p) → %d% lm\n", dwBufferCount,
+ NumberOfBytesRecvd, inout_lpFlags, opt_inout_lpOverlapped,
+ opt_lpCompletionRoutine, rc);
+ }
+#else
+ rc = __imp_WSARecv(s, inout_lpBuffers, dwBufferCount,
+ opt_out_lpNumberOfBytesRecvd, inout_lpFlags,
+ opt_inout_lpOverlapped, opt_lpCompletionRoutine);
+#endif
+ return rc;
+}
diff --git a/libc/intrin/wsarecvfrom.c b/libc/intrin/wsarecvfrom.c
new file mode 100644
index 000000000..69ebdd61b
--- /dev/null
+++ b/libc/intrin/wsarecvfrom.c
@@ -0,0 +1,71 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/strace.internal.h"
+#include "libc/calls/syscall_support-nt.internal.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/intrin/kprintf.h"
+#include "libc/nt/thunk/msabi.h"
+#include "libc/nt/winsock.h"
+
+__msabi extern typeof(WSARecvFrom) *const __imp_WSARecvFrom;
+
+/**
+ * Receives data from Windows socket.
+ *
+ * @return 0 on success, or -1 on failure
+ * @note this wrapper takes care of ABI, STRACE(), and __winerr()
+ */
+textwindows int WSARecvFrom(
+ uint64_t s, const struct NtIovec *inout_lpBuffers, uint32_t dwBufferCount,
+ uint32_t *opt_out_lpNumberOfBytesRecvd, uint32_t *inout_lpFlags,
+ void *opt_out_fromsockaddr, uint32_t *opt_inout_fromsockaddrlen,
+ struct NtOverlapped *opt_inout_lpOverlapped,
+ const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine) {
+ int rc;
+#if defined(SYSDEBUG) && _NTTRACE
+ uint32_t NumberOfBytesRecvd;
+ if (opt_out_lpNumberOfBytesRecvd) {
+ NumberOfBytesRecvd = *opt_out_lpNumberOfBytesRecvd;
+ }
+ rc = __imp_WSARecvFrom(s, inout_lpBuffers, dwBufferCount, &NumberOfBytesRecvd,
+ inout_lpFlags, opt_out_fromsockaddr,
+ opt_inout_fromsockaddrlen, opt_inout_lpOverlapped,
+ opt_lpCompletionRoutine);
+ if (opt_out_lpNumberOfBytesRecvd) {
+ *opt_out_lpNumberOfBytesRecvd = NumberOfBytesRecvd;
+ }
+ if (rc == -1) {
+ __winerr();
+ }
+ if (UNLIKELY(__strace > 0)) {
+ kprintf(STRACE_PROLOGUE "WSARecvFrom(%lu, [", s);
+ DescribeIovNt(inout_lpBuffers, dwBufferCount,
+ rc != -1 ? NumberOfBytesRecvd : 0);
+ kprintf("], %u, [%'u], %p, %p, %p, %p, %p) → %d% lm\n", dwBufferCount,
+ NumberOfBytesRecvd, opt_out_fromsockaddr, opt_inout_fromsockaddrlen,
+ inout_lpFlags, opt_inout_lpOverlapped, opt_lpCompletionRoutine, rc);
+ }
+#else
+ rc = __imp_WSARecvFrom(s, inout_lpBuffers, dwBufferCount,
+ opt_out_lpNumberOfBytesRecvd, opt_out_fromsockaddr,
+ opt_inout_fromsockaddrlen, inout_lpFlags,
+ opt_inout_lpOverlapped, opt_lpCompletionRoutine);
+#endif
+ return rc;
+}
diff --git a/libc/intrin/wsawaitformultipleevents.c b/libc/intrin/wsawaitformultipleevents.c
new file mode 100644
index 000000000..879625683
--- /dev/null
+++ b/libc/intrin/wsawaitformultipleevents.c
@@ -0,0 +1,46 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/strace.internal.h"
+#include "libc/calls/syscall_support-nt.internal.h"
+#include "libc/intrin/describeflags.internal.h"
+#include "libc/intrin/kprintf.h"
+#include "libc/nt/thunk/msabi.h"
+#include "libc/nt/winsock.h"
+
+__msabi extern typeof(WSAWaitForMultipleEvents) *const
+ __imp_WSAWaitForMultipleEvents;
+
+/**
+ * Waits for events on Windows sockets.
+ *
+ * @return 0 on success, or -1 on failure
+ * @note this wrapper takes care of ABI, STRACE(), and __winerr()
+ */
+textwindows uint32_t WSAWaitForMultipleEvents(uint32_t cEvents,
+ const int64_t *lphEvents,
+ bool32 fWaitAll,
+ uint32_t dwTimeout_ms,
+ bool32 fAlertable) {
+ uint32_t rc;
+ rc = __imp_WSAWaitForMultipleEvents(cEvents, lphEvents, fWaitAll,
+ dwTimeout_ms, fAlertable);
+ POLLTRACE("WSAWaitForMultipleEvents(%u, %p, %hhhd, %'u, %hhhd) → %u% lm",
+ cEvents, lphEvents, fWaitAll, dwTimeout_ms, fAlertable, rc);
+ return rc;
+}
diff --git a/libc/log/die.c b/libc/log/die.c
index 65340aef7..3281690fd 100644
--- a/libc/log/die.c
+++ b/libc/log/die.c
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
+#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/lockcmpxchgp.h"
@@ -37,7 +38,7 @@ relegated wontreturn void __die(void) {
int me, owner;
static int sync;
owner = 0;
- me = gettid();
+ me = sys_gettid();
if (_lockcmpxchgp(&sync, &owner, me)) {
__restore_tty();
if (IsDebuggerPresent(false)) {
diff --git a/libc/log/oncrash.c b/libc/log/oncrash.c
index f219e09d6..bb5e6f278 100644
--- a/libc/log/oncrash.c
+++ b/libc/log/oncrash.c
@@ -22,6 +22,7 @@
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/utsname.h"
+#include "libc/calls/syscall-sysv.internal.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
@@ -277,7 +278,7 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
--__ftrace;
--__strace;
owner = 0;
- me = gettid();
+ me = sys_gettid();
if (_lockcmpxchgp(&sync, &owner, me)) {
if (!__vforked) {
rip = ctx ? ctx->uc_mcontext.rip : 0;
diff --git a/libc/nt/master.sh b/libc/nt/master.sh
index 5d45e5573..a91abed63 100755
--- a/libc/nt/master.sh
+++ b/libc/nt/master.sh
@@ -3799,9 +3799,7 @@ imp 'WSANSPIoctl' WSANSPIoctl ws2_32 85 8
imp 'WSAPoll' WSAPoll ws2_32 88 3
imp 'WSAProviderCompleteAsyncCall' WSAProviderCompleteAsyncCall ws2_32 89
imp 'WSAProviderConfigChange' WSAProviderConfigChange ws2_32 90 3
-imp 'WSARecv' WSARecv ws2_32 91 7
imp 'WSARecvDisconnect' WSARecvDisconnect ws2_32 92 2
-imp 'WSARecvFrom' WSARecvFrom ws2_32 93 9
imp 'WSARemoveServiceClass' WSARemoveServiceClass ws2_32 94 1
imp 'WSAResetEvent' WSAResetEvent ws2_32 95 1
imp 'WSASend' WSASend ws2_32 96 7
@@ -3817,7 +3815,6 @@ imp 'WSAStartup' WSAStartup ws2_32 115 2
imp 'WSAStringToAddress' WSAStringToAddressW ws2_32 122
imp 'WSAUnadvertiseProvider' WSAUnadvertiseProvider ws2_32 123
imp 'WSAUnhookBlockingHook' WSAUnhookBlockingHook ws2_32 110
-imp 'WSAWaitForMultipleEvents' WSAWaitForMultipleEvents ws2_32 124 5
imp 'WSApSetPostRoutine' WSApSetPostRoutine ws2_32 24
imp 'WSCDeinstallProvider' WSCDeinstallProvider ws2_32 125
imp 'WSCDeinstallProvider32' WSCDeinstallProvider32 ws2_32 126
@@ -3884,6 +3881,9 @@ imp 'sys_getprotobyname_nt' getprotobyname ws2_32 53
imp 'sys_getprotobynumber_nt' getprotobynumber ws2_32 54
imp 'sys_getservbyname_nt' getservbyname ws2_32 55
imp 'sys_getservbyport_nt' getservbyport ws2_32 56
+imp '__WSARecv' WSARecv ws2_32 91 7
+imp '__WSARecvFrom' WSARecvFrom ws2_32 93 9
+imp '__WSAWaitForMultipleEvents' WSAWaitForMultipleEvents ws2_32 124 5
imp '__sys_recv_nt' recv ws2_32 16 4 # we're using WSARecvFrom()
imp '__sys_send_nt' send ws2_32 19 4 # we're using WSASendTo()
diff --git a/libc/nt/struct/fdset.h b/libc/nt/struct/fdset.h
new file mode 100644
index 000000000..73fd089e0
--- /dev/null
+++ b/libc/nt/struct/fdset.h
@@ -0,0 +1,13 @@
+#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_FDSET_H_
+#define COSMOPOLITAN_LIBC_NT_STRUCT_FDSET_H_
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct NtFdSet {
+ uint32_t fd_count;
+ int64_t fd_array[64];
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_FDSET_H_ */
diff --git a/libc/nt/struct/iovec.h b/libc/nt/struct/iovec.h
new file mode 100644
index 000000000..86062bb97
--- /dev/null
+++ b/libc/nt/struct/iovec.h
@@ -0,0 +1,13 @@
+#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_IOVEC_H_
+#define COSMOPOLITAN_LIBC_NT_STRUCT_IOVEC_H_
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct NtIovec {
+ uint32_t len;
+ char *buf;
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_IOVEC_H_ */
diff --git a/libc/nt/struct/timeval.h b/libc/nt/struct/timeval.h
new file mode 100644
index 000000000..9f53ddcc0
--- /dev/null
+++ b/libc/nt/struct/timeval.h
@@ -0,0 +1,13 @@
+#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_TIMEVAL_H_
+#define COSMOPOLITAN_LIBC_NT_STRUCT_TIMEVAL_H_
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct NtTimeval {
+ int32_t tv_sec; /* [sic] */
+ int32_t tv_usec;
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_TIMEVAL_H_ */
diff --git a/libc/nt/winsock.h b/libc/nt/winsock.h
index 8f819fbd7..f7e8af16f 100644
--- a/libc/nt/winsock.h
+++ b/libc/nt/winsock.h
@@ -1,8 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_NT_WINSOCK_H_
#define COSMOPOLITAN_LIBC_NT_WINSOCK_H_
+#include "libc/nt/struct/fdset.h"
#include "libc/nt/struct/guid.h"
+#include "libc/nt/struct/iovec.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/struct/pollfd.h"
+#include "libc/nt/struct/timeval.h"
#include "libc/sock/sock.h"
/* ░▓█████████████████████████████████████████████▓▒
░█▓░░░░░░░░░▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▒░
@@ -69,16 +72,6 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
-struct NtTimeval {
- int32_t tv_sec; /* [sic] */
- int32_t tv_usec;
-};
-
-struct NtIovec {
- uint32_t len;
- char *buf;
-};
-
struct NtMsgHdr {
struct sockaddr *name;
int32_t namelen;
@@ -280,11 +273,6 @@ struct NtWsaCompletion {
} Parameters;
};
-struct NtFdSet {
- uint32_t fd_count;
- int64_t fd_array[64];
-};
-
struct NtInterfaceInfo {
uint64_t iiFlags;
struct sockaddr_in iiAddress;
@@ -377,17 +365,17 @@ int WSASendTo(uint64_t s, const struct NtIovec *lpBuffers,
int WSAPoll(struct sys_pollfd_nt *inout_fdArray, uint32_t nfds,
signed timeout_ms) paramsnonnull();
-int WSARecv(uint64_t s, const struct NtIovec *out_lpBuffers,
+int WSARecv(uint64_t s, const struct NtIovec *inout_lpBuffers,
uint32_t dwBufferCount, uint32_t *opt_out_lpNumberOfBytesRecvd,
uint32_t *inout_lpFlags,
struct NtOverlapped *opt_inout_lpOverlapped,
const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine)
paramsnonnull((2, 5));
-int WSARecvFrom(uint64_t s, const struct NtIovec *out_lpBuffers,
+int WSARecvFrom(uint64_t s, const struct NtIovec *inout_lpBuffers,
uint32_t dwBufferCount, uint32_t *opt_out_lpNumberOfBytesRecvd,
uint32_t *inout_lpFlags, void *out_fromsockaddr,
- uint32_t *inout_fromsockaddrlen,
+ uint32_t *opt_inout_fromsockaddrlen,
struct NtOverlapped *opt_inout_lpOverlapped,
const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine)
paramsnonnull((2, 5));
diff --git a/libc/nt/ws2_32/WSARecv.s b/libc/nt/ws2_32/WSARecv.s
index eab2a8f2c..9920758ec 100644
--- a/libc/nt/ws2_32/WSARecv.s
+++ b/libc/nt/ws2_32/WSARecv.s
@@ -2,11 +2,11 @@
.imp ws2_32,__imp_WSARecv,WSARecv,91
.text.windows
-WSARecv:
+__WSARecv:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_WSARecv(%rip),%rax
jmp __sysv2nt8
- .endfn WSARecv,globl
+ .endfn __WSARecv,globl
.previous
diff --git a/libc/nt/ws2_32/WSARecvFrom.s b/libc/nt/ws2_32/WSARecvFrom.s
index dfacf2c9f..595ce2609 100644
--- a/libc/nt/ws2_32/WSARecvFrom.s
+++ b/libc/nt/ws2_32/WSARecvFrom.s
@@ -2,11 +2,11 @@
.imp ws2_32,__imp_WSARecvFrom,WSARecvFrom,93
.text.windows
-WSARecvFrom:
+__WSARecvFrom:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_WSARecvFrom(%rip),%rax
jmp __sysv2nt10
- .endfn WSARecvFrom,globl
+ .endfn __WSARecvFrom,globl
.previous
diff --git a/libc/nt/ws2_32/WSAWaitForMultipleEvents.s b/libc/nt/ws2_32/WSAWaitForMultipleEvents.s
index 36e963b16..f8e775285 100644
--- a/libc/nt/ws2_32/WSAWaitForMultipleEvents.s
+++ b/libc/nt/ws2_32/WSAWaitForMultipleEvents.s
@@ -2,11 +2,11 @@
.imp ws2_32,__imp_WSAWaitForMultipleEvents,WSAWaitForMultipleEvents,124
.text.windows
-WSAWaitForMultipleEvents:
+__WSAWaitForMultipleEvents:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_WSAWaitForMultipleEvents(%rip),%rax
jmp __sysv2nt6
- .endfn WSAWaitForMultipleEvents,globl
+ .endfn __WSAWaitForMultipleEvents,globl
.previous
diff --git a/libc/runtime/clone-openbsd.S b/libc/runtime/clone-openbsd.S
new file mode 100644
index 000000000..0c40a3704
--- /dev/null
+++ b/libc/runtime/clone-openbsd.S
@@ -0,0 +1,45 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+
+#define SYS___tfork 8
+
+// Creates thread on OpenBSD.
+//
+// @param rdi is params
+// @param rsi is size of params
+// @param rdx is start function
+// @param rcx is start parameter
+// @return thread id or negative errno
+__tfork_thread:
+ mov %rdx,%r8
+ mov %rcx,%r9
+ mov $SYS___tfork,%eax
+ syscall
+ jc 2f
+ test %eax,%eax
+ jz 1f
+ ret
+1: xor %ebp,%ebp
+ mov %r9,%rdi
+ jmp *%r8
+ .unreachable
+2: neg %eax
+ ret
+ .endfn __tfork_thread,globl
diff --git a/libc/runtime/clone.c b/libc/runtime/clone.c
index 42573e404..41bce3b92 100644
--- a/libc/runtime/clone.c
+++ b/libc/runtime/clone.c
@@ -20,12 +20,15 @@
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/ucontext-netbsd.internal.h"
+#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/limits.h"
+#include "libc/macros.internal.h"
+#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thread.h"
@@ -39,6 +42,7 @@
#include "libc/sysv/consts/nrlinux.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/freebsd.internal.h"
+#include "libc/thread/openbsd.internal.h"
#include "libc/thread/xnu.internal.h"
STATIC_YOINK("gettid"); // for kprintf()
@@ -261,35 +265,8 @@ static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
////////////////////////////////////////////////////////////////////////////////
// OPEN BESIYATA DISHMAYA
-struct __tfork {
- void *tf_tcb;
- int32_t *tf_tid;
- void *tf_stack;
-};
-
-int __tfork(struct __tfork *params, size_t psize, struct CloneArgs *wt);
-asm("__tfork:\n\t"
- "push\t$8\n\t"
- "pop\t%rax\n\t"
- "mov\t%rdx,%r8\n\t"
- "syscall\n\t"
- "jc\t1f\n\t"
- "test\t%eax,%eax\n\t"
- "jz\t2f\n\t"
- "ret\n1:\t"
- "neg\t%eax\n\t"
- "ret\n2:\t"
- "xor\t%ebp,%ebp\n\t"
- "mov\t%r8,%rsp\n\t"
- "mov\t%r8,%rdi\n\t"
- "and\t$-16,%rsp\n\t"
- "push\t%rax\n\t"
- "jmp\tOpenbsdThreadMain\n\t"
- ".size\t__tfork,.-__tfork\n\t");
-__attribute__((__used__, __no_reorder__))
-
-static wontreturn void
-OpenbsdThreadMain(struct CloneArgs *wt) {
+static wontreturn void OpenbsdThreadMain(void *p) {
+ struct CloneArgs *wt = p;
wt->func(wt->arg);
// we no longer use the stack after this point. however openbsd
// validates the rsp register too so a race condition can still
@@ -298,14 +275,11 @@ OpenbsdThreadMain(struct CloneArgs *wt) {
// although ideally there should be a better solution.
//
// void __threxit(%rdi = int32_t *notdead);
- asm volatile("mov\t%2,%%rsp\n\t"
+ asm volatile("mov\t%2,%%rsp\n\t" // set stack
"movl\t$0,(%%rdi)\n\t" // *wt->ztid = 0
- "syscall\n\t" // futex()
- "mov\t$302,%%eax\n\t" // __threxit()
- "syscall"
+ "syscall" // __threxit()
: "=m"(*wt->ztid)
- : "a"(83), "m"(wt->pstack), "D"(wt->ztid), "S"(FUTEX_WAKE),
- "d"(INT_MAX)
+ : "a"(302), "m"(wt->pstack), "D"(wt->ztid)
: "rcx", "r11", "memory");
unreachable;
}
@@ -313,20 +287,24 @@ OpenbsdThreadMain(struct CloneArgs *wt) {
static int CloneOpenbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
void *arg, void *tls, size_t tlssz, int *ctid) {
int tid;
+ intptr_t sp;
+ struct __tfork *tf;
struct CloneArgs *wt;
- struct __tfork params;
- wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
- sizeof(struct CloneArgs)) &
- -alignof(struct CloneArgs));
- wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
+ sp = (intptr_t)stk + stksz;
+ sp -= sizeof(struct __tfork);
+ sp &= -alignof(struct __tfork);
+ tf = (struct __tfork *)sp;
+ sp -= sizeof(struct CloneArgs);
+ sp &= -MAX(16, alignof(struct CloneArgs));
+ wt = (struct CloneArgs *)sp;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->pstack = __builtin_frame_address(0);
- wt->func = func;
wt->arg = arg;
- params.tf_stack = wt;
- params.tf_tcb = flags & CLONE_SETTLS ? tls : 0;
- params.tf_tid = flags & CLONE_CHILD_SETTID ? ctid : 0;
- if ((tid = __tfork(¶ms, sizeof(params), wt)) < 0) {
+ wt->func = func;
+ tf->tf_stack = (char *)wt - 8;
+ tf->tf_tcb = flags & CLONE_SETTLS ? tls : 0;
+ tf->tf_tid = flags & CLONE_CHILD_SETTID ? ctid : 0;
+ if ((tid = __tfork_thread(tf, sizeof(*tf), OpenbsdThreadMain, wt)) < 0) {
errno = -tid;
tid = -1;
}
diff --git a/libc/runtime/fork-nt.c b/libc/runtime/fork-nt.c
index ee7047383..8dbe9398b 100644
--- a/libc/runtime/fork-nt.c
+++ b/libc/runtime/fork-nt.c
@@ -82,7 +82,7 @@ static inline textwindows ssize_t ForkIo(int64_t h, char *p, size_t n,
uint32_t x;
for (i = 0; i < n; i += x) {
if (!f(h, p + i, n - i, &x, NULL)) {
- return -1;
+ return __winerr();
}
}
return i;
@@ -91,7 +91,7 @@ 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) {
ssize_t rc = ForkIo(h, buf, n, fn);
- NTTRACE("%s(%ld, %'zu) → %'zd% m", sf, h, n, rc);
+ NTTRACE("%s(%ld, %p, %'zu) → %'zd% m", sf, h, buf, n, rc);
return rc != -1;
}
@@ -202,6 +202,9 @@ textwindows void WinMainForked(void) {
ReadOrDie(reader, __bss_start, __bss_end - __bss_start);
__pid = savepid;
kStartTsc = savetsc;
+ __threaded = false;
+ __tls_index = 0;
+ __tls_enabled = false;
// apply fixups and reapply memory protections
_mmi.p = maps;
@@ -255,6 +258,7 @@ textwindows void WinMainForked(void) {
textwindows int sys_fork_nt(void) {
bool ok;
jmp_buf jb;
+ uint32_t oldprot;
char **args, **args2;
char16_t pipename[64];
int64_t reader, writer;
diff --git a/libc/runtime/ftracer.c b/libc/runtime/ftracer.c
index 3873caa01..6299ca0ce 100644
--- a/libc/runtime/ftracer.c
+++ b/libc/runtime/ftracer.c
@@ -90,7 +90,7 @@ privileged void ftracer(void) {
frame = frame->next;
if (frame->addr != g_ftrace.lastaddr) {
stackuse = (intptr_t)GetStackAddr(0) + GetStackSize() - (intptr_t)frame;
- kprintf("%rFUN %5P %'13T %'*ld %*s%t\n", g_ftrace.stackdigs, stackuse,
+ kprintf("%rFUN %6P %'13T %'*ld %*s%t\n", g_ftrace.stackdigs, stackuse,
GetNestingLevel(frame) * 2, "", frame->addr);
g_ftrace.lastaddr = frame->addr;
}
diff --git a/libc/runtime/memtrack.internal.h b/libc/runtime/memtrack.internal.h
index 9960547c2..183ce51a7 100644
--- a/libc/runtime/memtrack.internal.h
+++ b/libc/runtime/memtrack.internal.h
@@ -62,8 +62,6 @@ void __mmi_lock(void) hidden;
void __mmi_unlock(void) hidden;
bool IsMemtracked(int, int) hidden;
void PrintSystemMappings(int) hidden;
-const char *DescribeFrame(int) hidden;
-char *DescribeMapping(int, int, char[hasatleast 8]) hidden;
bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect hidden;
void PrintMemoryIntervals(int, const struct MemoryIntervals *) hidden;
int TrackMemoryInterval(struct MemoryIntervals *, int, int, long, int, int,
diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c
index 200832f87..d498417fa 100644
--- a/libc/runtime/mmap.c
+++ b/libc/runtime/mmap.c
@@ -237,12 +237,6 @@ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
int fd, int64_t off) {
-#if defined(SYSDEBUG) && (_KERNTRACE || _NTTRACE)
- if (IsWindows()) {
- STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → ...", addr, size,
- DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off);
- }
-#endif
char *p = addr;
struct DirectMap dm;
int a, b, i, f, m, n, x;
@@ -405,7 +399,10 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
if (p != MAP_FAILED) {
if (needguard) {
- mprotect(p, PAGESIZE, PROT_NONE);
+ if (!IsWindows()) {
+ // make windows fork() code simpler
+ mprotect(p, PAGESIZE, PROT_NONE);
+ }
if (IsAsan()) {
__repstosb((void *)(((intptr_t)p >> 3) + 0x7fff8000),
kAsanStackOverflow, PAGESIZE / 8);
@@ -474,10 +471,15 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
* to be 64kb aligned too
* @return virtual base address of new mapping, or MAP_FAILED w/ errno
*/
-noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
- int64_t off) {
+void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
void *res;
size_t toto;
+#if defined(SYSDEBUG) && (_KERNTRACE || _NTTRACE)
+ if (IsWindows()) {
+ STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → ...", addr, size,
+ DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off);
+ }
+#endif
__mmi_lock();
res = Mmap(addr, size, prot, flags, fd, off);
#if SYSDEBUG
diff --git a/libc/runtime/mprotect.greg.c b/libc/runtime/mprotect.c
similarity index 100%
rename from libc/runtime/mprotect.greg.c
rename to libc/runtime/mprotect.c
diff --git a/libc/runtime/munmap.c b/libc/runtime/munmap.c
index 3b7de0163..045dc1d87 100644
--- a/libc/runtime/munmap.c
+++ b/libc/runtime/munmap.c
@@ -161,7 +161,7 @@ static noasan int Munmap(char *p, size_t n) {
* @raises EINVAL if `p+(n-1)` isn't 48-bit
* @raises EINVAL if `p` isn't 65536-byte aligned
*/
-noasan int munmap(void *p, size_t n) {
+int munmap(void *p, size_t n) {
int rc;
size_t toto;
__mmi_lock();
diff --git a/libc/runtime/printargs.greg.c b/libc/runtime/printargs.c
similarity index 97%
rename from libc/runtime/printargs.greg.c
rename to libc/runtime/printargs.c
index 4f3fb22d1..8b93874a5 100644
--- a/libc/runtime/printargs.greg.c
+++ b/libc/runtime/printargs.c
@@ -126,6 +126,17 @@ static const struct AuxiliaryValue *DescribeAuxv(unsigned long x) {
return NULL;
}
+static noasan void PrintDependencies(const char *prologue) {
+ struct NtLinkedList *head = &NtGetPeb()->Ldr->InLoadOrderModuleList;
+ struct NtLinkedList *ldr = head->Next;
+ do {
+ const struct NtLdrDataTableEntry *dll =
+ (const struct NtLdrDataTableEntry *)ldr;
+ PRINT(" ☼ %.*!hs (%'zukb)", dll->FullDllName.Length, dll->FullDllName.Data,
+ dll->SizeOfImage / 1024);
+ } while ((ldr = ldr->Next) && ldr != head);
+}
+
/**
* Prints lots of information about this process, e.g.
*
@@ -283,10 +294,11 @@ textstartup void __printargs(const char *prologue) {
PRINT("RESOURCE LIMITS");
for (i = 0; i < RLIM_NLIMITS; ++i) {
if (!getrlimit(i, &rlim)) {
+ char buf[12];
if (rlim.rlim_cur == RLIM_INFINITY) rlim.rlim_cur = -1;
if (rlim.rlim_max == RLIM_INFINITY) rlim.rlim_max = -1;
- PRINT(" ☼ %-20s %,16ld %,16ld", DescribeRlimitName(i), rlim.rlim_cur,
- rlim.rlim_max);
+ PRINT(" ☼ %-20s %,16ld %,16ld", (DescribeRlimitName)(buf, i),
+ rlim.rlim_cur, rlim.rlim_max);
}
}
@@ -551,14 +563,7 @@ textstartup void __printargs(const char *prologue) {
PRINT("");
PRINT("DEPENDENCIES");
- struct NtLinkedList *head = &NtGetPeb()->Ldr->InLoadOrderModuleList;
- struct NtLinkedList *ldr = head->Next;
- do {
- const struct NtLdrDataTableEntry *dll =
- (const struct NtLdrDataTableEntry *)ldr;
- PRINT(" ☼ %.*!hs (%'zukb)", dll->FullDllName.Length,
- dll->FullDllName.Data, dll->SizeOfImage / 1024);
- } while ((ldr = ldr->Next) && ldr != head);
+ PrintDependencies(prologue);
}
PRINT("");
diff --git a/libc/runtime/printmemoryintervals.c b/libc/runtime/printmemoryintervals.c
index 00a1e5825..49f5912a0 100644
--- a/libc/runtime/printmemoryintervals.c
+++ b/libc/runtime/printmemoryintervals.c
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
@@ -33,7 +34,7 @@ static bool IsNoteworthyHole(unsigned i, const struct MemoryIntervals *mm) {
}
void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
- char *p, mode[8];
+ char *p, mappingbuf[8], framebuf[32];
long i, w, frames, maptally = 0, gaptally = 0;
for (w = i = 0; i < mm->i; ++i) {
w = MAX(w, LengthInt64Thousands(mm->p[i].y + 1 - mm->p[i].x));
@@ -42,8 +43,8 @@ void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
frames = mm->p[i].y + 1 - mm->p[i].x;
maptally += frames;
kprintf("%08x-%08x %s %'*ldx%s", mm->p[i].x, mm->p[i].y,
- DescribeMapping(mm->p[i].prot, mm->p[i].flags, mode), w, frames,
- DescribeFrame(mm->p[i].x));
+ (DescribeMapping)(mappingbuf, mm->p[i].prot, mm->p[i].flags), w,
+ frames, (DescribeFrame)(framebuf, mm->p[i].x));
if (mm->p[i].iscow) kprintf(" cow");
if (mm->p[i].readonlyfile) kprintf(" readonlyfile");
if (mm->p[i].size !=
diff --git a/libc/runtime/threadmode.c b/libc/runtime/threadmode.c
index 24e3fee3d..a0fdb935c 100644
--- a/libc/runtime/threadmode.c
+++ b/libc/runtime/threadmode.c
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
+#include "libc/calls/syscall-sysv.internal.h"
#include "libc/errno.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/internal.h"
@@ -28,7 +29,7 @@ extern int __threadcalls_start[];
void __enable_tls(void) {
__initialize_tls(tibdefault);
- *(int *)((char *)tibdefault + 0x38) = gettid();
+ *(int *)((char *)tibdefault + 0x38) = sys_gettid();
*(int *)((char *)tibdefault + 0x3c) = __errno;
__install_tls(tibdefault);
}
diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c
index a22ce2e6d..9ee8ea6ba 100644
--- a/libc/runtime/winmain.greg.c
+++ b/libc/runtime/winmain.greg.c
@@ -163,6 +163,8 @@ __msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
int64_t h, hand;
uint32_t oldprot;
struct WinArgs *wa;
+ char inflagsbuf[256];
+ char outflagsbuf[128];
const char16_t *env16;
int i, prot, count, version;
intptr_t stackaddr, allocaddr;
@@ -179,13 +181,13 @@ __msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
hand = GetStdHandle(kConsoleHandles[i]);
rc = GetConsoleMode(hand, __ntconsolemode + i);
NTTRACE("GetConsoleMode(%p, [%s]) → %hhhd", hand,
- i ? DescribeNtConsoleModeOutputFlags(__ntconsolemode[i])
- : DescribeNtConsoleModeInputFlags(__ntconsolemode[i]),
+ i ? (DescribeNtConsoleOutFlags)(outflagsbuf, __ntconsolemode[i])
+ : (DescribeNtConsoleInFlags)(inflagsbuf, __ntconsolemode[i]),
rc);
rc = SetConsoleMode(hand, kConsoleModes[i]);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", hand,
- i ? DescribeNtConsoleModeOutputFlags(kConsoleModes[i])
- : DescribeNtConsoleModeInputFlags(kConsoleModes[i]),
+ i ? (DescribeNtConsoleOutFlags)(outflagsbuf, kConsoleModes[i])
+ : (DescribeNtConsoleInFlags)(inflagsbuf, kConsoleModes[i]),
rc);
}
}
diff --git a/libc/sock/accept4.c b/libc/sock/accept4.c
index 94120bfb2..5bd589bb9 100644
--- a/libc/sock/accept4.c
+++ b/libc/sock/accept4.c
@@ -19,9 +19,9 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
-#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@@ -51,7 +51,6 @@ int accept4(int fd, void *out_addr, uint32_t *inout_addrsize, int flags) {
rc = ebadf();
}
STRACE("accept4(%d, [%s]) -> %d% lm", fd,
- __describe_sockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0),
- rc);
+ DescribeSockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0), rc);
return rc;
}
diff --git a/libc/sock/bind.c b/libc/sock/bind.c
index 26726ce13..b3e73f9d2 100644
--- a/libc/sock/bind.c
+++ b/libc/sock/bind.c
@@ -20,14 +20,18 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
-#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
/**
- * Assigns local address and port number to socket.
+ * Assigns local address and port number to socket, e.g.
+ *
+ * struct sockaddr_in in = {AF_INET, htons(12345), {htonl(0x7f000001)}};
+ * int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ * bind(fd, &in, sizeof(in));
*
* @param fd is the file descriptor returned by socket()
* @param addr is usually the binary-encoded ip:port on which to listen
@@ -51,6 +55,6 @@ int bind(int fd, const void *addr, uint32_t addrsize) {
} else {
rc = einval();
}
- STRACE("bind(%d, %s) -> %d% lm", fd, __describe_sockaddr(addr, addrsize), rc);
+ STRACE("bind(%d, %s) -> %d% lm", fd, DescribeSockaddr(addr, addrsize), rc);
return rc;
}
diff --git a/libc/sock/connect-nt.c b/libc/sock/connect-nt.c
index bd66fe80c..8142fed29 100644
--- a/libc/sock/connect-nt.c
+++ b/libc/sock/connect-nt.c
@@ -25,8 +25,11 @@
textwindows int sys_connect_nt(struct Fd *fd, const void *addr,
uint32_t addrsize) {
+ struct SockFd *sockfd;
+ sockfd = (struct SockFd *)fd->extra;
assert(fd->kind == kFdSocket);
return __winsockblock(
fd->handle, FD_CONNECT_BIT,
- WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL));
+ WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL),
+ sockfd->rcvtimeo);
}
diff --git a/libc/sock/connect.c b/libc/sock/connect.c
index 4fb1007d7..ec56fba68 100644
--- a/libc/sock/connect.c
+++ b/libc/sock/connect.c
@@ -19,10 +19,10 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
-#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@@ -51,7 +51,6 @@ int connect(int fd, const void *addr, uint32_t addrsize) {
} else {
rc = efault();
}
- STRACE("connect(%d, %s) -> %d% lm", fd, __describe_sockaddr(addr, addrsize),
- rc);
+ STRACE("connect(%d, %s) -> %d% lm", fd, DescribeSockaddr(addr, addrsize), rc);
return rc;
}
diff --git a/libc/sock/getpeername.c b/libc/sock/getpeername.c
index db25832c0..6e8825bf9 100644
--- a/libc/sock/getpeername.c
+++ b/libc/sock/getpeername.c
@@ -19,9 +19,9 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
-#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@@ -44,6 +44,6 @@ int getpeername(int fd, void *out_addr, uint32_t *out_addrsize) {
rc = ebadf();
}
STRACE("getpeername(%d, [%s]) -> %d% lm", fd,
- __describe_sockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
+ DescribeSockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
return rc;
}
diff --git a/libc/sock/getsockname.c b/libc/sock/getsockname.c
index 9add6709f..83ab168d9 100644
--- a/libc/sock/getsockname.c
+++ b/libc/sock/getsockname.c
@@ -19,9 +19,9 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
-#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@@ -44,6 +44,6 @@ int getsockname(int fd, void *out_addr, uint32_t *out_addrsize) {
rc = ebadf();
}
STRACE("getsockname(%d, [%s]) -> %d% lm", fd,
- __describe_sockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
+ DescribeSockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
return rc;
}
diff --git a/libc/sock/getsockopt-nt.c b/libc/sock/getsockopt-nt.c
index 41e521ed9..07b643d0a 100644
--- a/libc/sock/getsockopt-nt.c
+++ b/libc/sock/getsockopt-nt.c
@@ -26,14 +26,17 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sol.h"
+#include "libc/sysv/errfuns.h"
textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
void *out_opt_optval,
uint32_t *inout_optlen) {
uint64_t ms;
uint32_t in_optlen;
+ struct SockFd *sockfd;
struct linger_nt linger;
assert(fd->kind == kFdSocket);
+ sockfd = (struct SockFd *)fd->extra;
if (out_opt_optval && inout_optlen) {
in_optlen = *inout_optlen;
@@ -41,6 +44,23 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
in_optlen = 0;
}
+ if (level == SOL_SOCKET &&
+ (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
+ if (in_optlen >= sizeof(struct timeval)) {
+ if (optname == SO_RCVTIMEO) {
+ ms = sockfd->rcvtimeo;
+ } else {
+ ms = sockfd->sndtimeo;
+ }
+ ((struct timeval *)out_opt_optval)->tv_sec = ms / 1000;
+ ((struct timeval *)out_opt_optval)->tv_usec = ms % 1000 * 1000;
+ *inout_optlen = sizeof(struct timeval);
+ return 0;
+ } else {
+ return einval();
+ }
+ }
+
// TODO(jart): Use WSAIoctl?
if (__sys_getsockopt_nt(fd->handle, level, optname, out_opt_optval,
inout_optlen) == -1) {
@@ -48,14 +68,7 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
}
if (level == SOL_SOCKET) {
- if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) &&
- in_optlen == sizeof(struct timeval) &&
- *inout_optlen == sizeof(uint32_t)) {
- ms = *(uint32_t *)out_opt_optval;
- ((struct timeval *)out_opt_optval)->tv_sec = ms / 1000;
- ((struct timeval *)out_opt_optval)->tv_usec = ms % 1000 * 1000;
- *inout_optlen = sizeof(struct timeval);
- } else if (optname == SO_LINGER && in_optlen == sizeof(struct linger)) {
+ if (optname == SO_LINGER && in_optlen == sizeof(struct linger)) {
linger = *(struct linger_nt *)out_opt_optval;
((struct linger *)out_opt_optval)->l_onoff = !!linger.l_onoff;
((struct linger *)out_opt_optval)->l_linger = linger.l_linger;
diff --git a/libc/sock/getsockopt.c b/libc/sock/getsockopt.c
index 105d7ff26..a885efc51 100644
--- a/libc/sock/getsockopt.c
+++ b/libc/sock/getsockopt.c
@@ -18,8 +18,8 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
-#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/syscall_fd.internal.h"
diff --git a/libc/sock/internal.h b/libc/sock/internal.h
index f22bd0b04..1d478d0e3 100644
--- a/libc/sock/internal.h
+++ b/libc/sock/internal.h
@@ -72,6 +72,8 @@ struct SockFd {
int family;
int type;
int protocol;
+ uint32_t rcvtimeo;
+ uint32_t sndtimeo;
bool32 (*__msabi ConnectEx)(int64_t s, const struct sockaddr *name,
int namelen, const void *opt_lpSendBuffer,
uint32_t dwSendDataLength,
@@ -144,8 +146,9 @@ ssize_t sys_sendto_nt(int, const struct iovec *, size_t, uint32_t, void *,
void WinSockInit(void) hidden;
int64_t __winsockerr(void) nocallback hidden;
int __fixupnewsockfd(int, int) hidden;
-int __wsablock(int64_t, struct NtOverlapped *, uint32_t *, bool) hidden;
-int64_t __winsockblock(int64_t, unsigned, int64_t) hidden;
+int __wsablock(int64_t, struct NtOverlapped *, uint32_t *, bool,
+ uint32_t) hidden;
+int64_t __winsockblock(int64_t, unsigned, int64_t, uint32_t) hidden;
struct SockFd *_dupsockfd(struct SockFd *) hidden;
int64_t GetNtBaseSocket(int64_t) hidden;
int sys_close_epoll(int) hidden;
diff --git a/libc/sock/recv-nt.c b/libc/sock/recv-nt.c
index 46dc83ebe..c11bd61df 100644
--- a/libc/sock/recv-nt.c
+++ b/libc/sock/recv-nt.c
@@ -16,7 +16,11 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/likely.h"
+#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/iovec.h"
+#include "libc/errno.h"
+#include "libc/intrin/kprintf.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
@@ -31,16 +35,21 @@
*/
textwindows ssize_t sys_recv_nt(struct Fd *fd, const struct iovec *iov,
size_t iovlen, uint32_t flags) {
+ int err;
ssize_t rc;
uint32_t got = 0;
+ struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
+ err = errno;
if (!WSARecv(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got, &flags,
&overlapped, NULL)) {
rc = got;
} else {
- rc = __wsablock(fd->handle, &overlapped, &flags, true);
+ errno = err;
+ sockfd = (struct SockFd *)fd->extra;
+ rc = __wsablock(fd->handle, &overlapped, &flags, true, sockfd->rcvtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;
diff --git a/libc/sock/recvfrom-nt.c b/libc/sock/recvfrom-nt.c
index ba229096d..6eab61a6a 100644
--- a/libc/sock/recvfrom-nt.c
+++ b/libc/sock/recvfrom-nt.c
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/struct/iovec.h"
+#include "libc/errno.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
@@ -33,17 +34,22 @@ textwindows ssize_t sys_recvfrom_nt(struct Fd *fd, const struct iovec *iov,
size_t iovlen, uint32_t flags,
void *opt_out_srcaddr,
uint32_t *opt_inout_srcaddrsize) {
+ int err;
ssize_t rc;
uint32_t got = 0;
+ struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
+ err = errno;
if (!WSARecvFrom(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got,
&flags, opt_out_srcaddr, opt_inout_srcaddrsize, &overlapped,
NULL)) {
rc = got;
} else {
- rc = __wsablock(fd->handle, &overlapped, &flags, true);
+ errno = err;
+ sockfd = (struct SockFd *)fd->extra;
+ rc = __wsablock(fd->handle, &overlapped, &flags, true, sockfd->rcvtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;
diff --git a/libc/sock/send-nt.c b/libc/sock/send-nt.c
index 69af0c438..3cf7f7287 100644
--- a/libc/sock/send-nt.c
+++ b/libc/sock/send-nt.c
@@ -33,6 +33,7 @@ textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
uint32_t flags) {
ssize_t rc;
uint32_t sent = 0;
+ struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
@@ -40,7 +41,9 @@ textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
flags, &overlapped, NULL)) {
rc = sent;
} else {
- rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true);
+ sockfd = (struct SockFd *)g_fds.p[fd].extra;
+ rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true,
+ sockfd->sndtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;
diff --git a/libc/sock/sendfile.c b/libc/sock/sendfile.c
index 11d0d6b13..48c30e3bb 100644
--- a/libc/sock/sendfile.c
+++ b/libc/sock/sendfile.c
@@ -38,7 +38,8 @@
static textwindows int SendfileBlock(int64_t handle,
struct NtOverlapped *overlapped) {
uint32_t i, got, flags = 0;
- if (WSAGetLastError() != kNtErrorIoPending) {
+ if (WSAGetLastError() != kNtErrorIoPending &&
+ WSAGetLastError() != WSAEINPROGRESS) {
NTTRACE("TransmitFile failed %lm");
return __winsockerr();
}
diff --git a/libc/sock/sendto-nt.c b/libc/sock/sendto-nt.c
index 43c716979..d7ec71558 100644
--- a/libc/sock/sendto-nt.c
+++ b/libc/sock/sendto-nt.c
@@ -34,6 +34,7 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
void *opt_in_addr, uint32_t in_addrsize) {
ssize_t rc;
uint32_t sent = 0;
+ struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
@@ -41,7 +42,9 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
&sent, flags, opt_in_addr, in_addrsize, &overlapped, NULL)) {
rc = sent;
} else {
- rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true);
+ sockfd = (struct SockFd *)g_fds.p[fd].extra;
+ rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true,
+ sockfd->sndtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;
diff --git a/libc/sock/setsockopt-nt.c b/libc/sock/setsockopt-nt.c
index 3b4106875..a78980571 100644
--- a/libc/sock/setsockopt-nt.c
+++ b/libc/sock/setsockopt-nt.c
@@ -28,9 +28,10 @@
textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
const void *optval, uint32_t optlen) {
- int64_t ms;
+ int64_t ms, micros;
struct timeval *tv;
struct linger *linger;
+ struct SockFd *sockfd;
union {
uint32_t millis;
struct linger_nt linger;
@@ -47,7 +48,8 @@ textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
optlen == sizeof(struct timeval)) {
tv = optval;
if (__builtin_mul_overflow(tv->tv_sec, 1000, &ms) ||
- __builtin_add_overflow(ms, tv->tv_usec / 1000, &ms) ||
+ __builtin_add_overflow(tv->tv_usec, 999, µs) ||
+ __builtin_add_overflow(ms, micros / 1000, &ms) ||
(ms < 0 || ms > 0xffffffff)) {
u.millis = 0xffffffff;
} else {
@@ -55,6 +57,14 @@ textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
}
optval = &u.millis;
optlen = sizeof(u.millis);
+ sockfd = (struct SockFd *)fd->extra;
+ if (optname == SO_RCVTIMEO) {
+ sockfd->rcvtimeo = u.millis;
+ }
+ if (optname == SO_SNDTIMEO) {
+ sockfd->sndtimeo = u.millis;
+ }
+ return 0;
}
}
diff --git a/libc/sock/setsockopt.c b/libc/sock/setsockopt.c
index 181f67703..171dfaf4b 100644
--- a/libc/sock/setsockopt.c
+++ b/libc/sock/setsockopt.c
@@ -20,8 +20,8 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
-#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
diff --git a/libc/sock/sock.h b/libc/sock/sock.h
index 95c9d7bcc..2426aff32 100644
--- a/libc/sock/sock.h
+++ b/libc/sock/sock.h
@@ -3,6 +3,10 @@
#include "libc/bits/bswap.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
+#include "libc/sock/struct/linger.h"
+#include "libc/sock/struct/msghdr.h"
+#include "libc/sock/struct/pollfd.h"
+#include "libc/sock/struct/sockaddr.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/*───────────────────────────────────────────────────────────────────────────│─╗
@@ -25,62 +29,11 @@ COSMOPOLITAN_C_START_
#define htonl(u32) bswap_32(u32)
#define ntohl(u32) bswap_32(u32)
-struct in_addr { /* ARPA ABI */
- /* e.g. 127|0<<8|0<<16|1<<24 or inet_pton(AF_INET, "127.0.0.1", &s_addr) */
- uint32_t s_addr;
-};
-
-struct sockaddr { /* Linux+NT ABI */
- uint16_t sa_family; /* AF_XXX */
- char sa_data[14];
-};
-
-struct sockaddr_in { /* Linux+NT ABI */
- uint16_t sin_family; /* AF_XXX */
- uint16_t sin_port; /* htons(XXX) i.e. big endian */
- struct in_addr sin_addr;
- uint8_t sin_zero[8];
-};
-
-struct sockaddr_un {
- uint16_t sun_family; /* AF_UNIX */
- char sun_path[108]; /* path */
-};
-
-struct sockaddr_storage {
- union {
- uint16_t ss_family;
- intptr_t __ss_align;
- char __ss_storage[128];
- };
-};
-
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
-struct linger { /* Linux+XNU+BSD ABI */
- int32_t l_onoff; /* on/off */
- int32_t l_linger; /* seconds */
-};
-
-struct pollfd {
- int32_t fd;
- int16_t events;
- int16_t revents;
-};
-
-struct msghdr { /* Linux+NT ABI */
- void *msg_name; /* optional address */
- uint32_t msg_namelen; /* size of msg_name */
- struct iovec *msg_iov; /* scatter/gather array */
- uint64_t msg_iovlen; /* iovec count */
- void *msg_control; /* credentials and stuff */
- uint64_t msg_controllen; /* size of msg_control */
- uint32_t msg_flags; /* MSG_XXX */
-};
-
/*
* Structure used in SIOCGIFCONF request.
* Used to retrieve interface configuration
diff --git a/libc/sock/sock.mk b/libc/sock/sock.mk
index 49205fc56..01a24eac8 100644
--- a/libc/sock/sock.mk
+++ b/libc/sock/sock.mk
@@ -6,7 +6,7 @@ PKGS += LIBC_SOCK
LIBC_SOCK_ARTIFACTS += LIBC_SOCK_A
LIBC_SOCK = $(LIBC_SOCK_A_DEPS) $(LIBC_SOCK_A)
LIBC_SOCK_A = o/$(MODE)/libc/sock/sock.a
-LIBC_SOCK_A_FILES := $(wildcard libc/sock/*)
+LIBC_SOCK_A_FILES := $(wildcard libc/sock/*) $(wildcard libc/sock/struct/*)
LIBC_SOCK_A_HDRS = $(filter %.h,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_INCS = $(filter %.inc,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_SRCS_C = $(filter %.c,$(LIBC_SOCK_A_FILES))
diff --git a/libc/sock/sockdebug.c b/libc/sock/sockdebug.c
index ff52cf07b..c95cabb8c 100644
--- a/libc/sock/sockdebug.c
+++ b/libc/sock/sockdebug.c
@@ -19,69 +19,24 @@
#include "libc/calls/struct/sockaddr6.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/macros.internal.h"
#include "libc/sock/sock.h"
-#include "libc/sock/sockdebug.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/sock.h"
-const char *__describe_socket_family(int family) {
- static char buf[12];
- if (family == AF_UNIX) return "AF_UNIX";
- if (family == AF_INET) return "AF_INET";
- if (family == AF_INET6) return "AF_INET6";
- FormatInt32(buf, family);
- return buf;
-}
-
-const char *__describe_socket_type(int type) {
- int x;
- char *p;
- static char buf[12 + 1 + 12 + 1 + 13 + 1];
- p = buf;
- x = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
- if (x == SOCK_STREAM) {
- p = stpcpy(p, "SOCK_STREAM");
- } else if (x == SOCK_DGRAM) {
- p = stpcpy(p, "SOCK_DGRAM");
- } else if (x == SOCK_RAW) {
- p = stpcpy(p, "SOCK_RAW");
- } else if (x == SOCK_RDM) {
- p = stpcpy(p, "SOCK_RDM");
- } else if (x == SOCK_SEQPACKET) {
- p = stpcpy(p, "SOCK_SEQPACKET");
- } else {
- p = FormatInt32(p, x);
- }
- if (type & SOCK_CLOEXEC) p = stpcpy(p, "|SOCK_CLOEXEC");
- if (type & SOCK_NONBLOCK) p = stpcpy(p, "|SOCK_NONBLOCK");
- return buf;
-}
-
-const char *__describe_socket_protocol(int family) {
- static char buf[12];
- if (family == IPPROTO_IP) return "IPPROTO_IP";
- if (family == IPPROTO_ICMP) return "IPPROTO_ICMP";
- if (family == IPPROTO_TCP) return "IPPROTO_TCP";
- if (family == IPPROTO_UDP) return "IPPROTO_UDP";
- if (family == IPPROTO_RAW) return "IPPROTO_RAW";
- if (family == IPPROTO_IPV6) return "IPPROTO_IPv6";
- FormatInt32(buf, family);
- return buf;
-}
-
-const char *__describe_sockaddr(const struct sockaddr *sa, size_t sasize) {
+const char *(DescribeSockaddr)(char buf[128], const struct sockaddr *sa,
+ size_t sasize) {
int e;
size_t n;
uint16_t port;
char *p, ip[72];
- static char buf[128];
e = errno;
stpcpy(buf, "NULL");
if (sa && sasize >= sizeof(sa->sa_family)) {
- stpcpy(buf, __describe_socket_family(sa->sa_family));
+ stpcpy(buf, DescribeSocketFamily(sa->sa_family));
if (sa->sa_family == AF_INET && sasize >= sizeof(struct sockaddr_in)) {
const struct sockaddr_in *in;
in = (const struct sockaddr_in *)sa;
@@ -108,7 +63,7 @@ const char *__describe_sockaddr(const struct sockaddr *sa, size_t sasize) {
const struct sockaddr_un *unix;
unix = (const struct sockaddr_un *)sa;
n = strnlen(unix->sun_path, sizeof(unix->sun_path));
- n = MIN(n, sizeof(buf) - 1);
+ n = MIN(n, 128 - 1);
memcpy(buf, unix->sun_path, n);
buf[n] = 0;
}
diff --git a/libc/sock/sockdebug.h b/libc/sock/sockdebug.h
deleted file mode 100644
index f85b99bff..000000000
--- a/libc/sock/sockdebug.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_
-#define COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_
-#include "libc/sock/sock.h"
-#if !(__ASSEMBLER__ + __LINKER__ + 0)
-COSMOPOLITAN_C_START_
-
-const char *__describe_sockaddr(const struct sockaddr *, size_t);
-const char *__describe_socket_family(int);
-const char *__describe_socket_type(int);
-const char *__describe_socket_protocol(int);
-
-COSMOPOLITAN_C_END_
-#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
-#endif /* COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_ */
diff --git a/libc/sock/socket.c b/libc/sock/socket.c
index 1e6952f45..8c89e5553 100644
--- a/libc/sock/socket.c
+++ b/libc/sock/socket.c
@@ -18,9 +18,9 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
+#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
-#include "libc/sock/sockdebug.h"
#include "libc/sysv/consts/af.h"
/**
@@ -46,8 +46,7 @@ int socket(int family, int type, int protocol) {
} else {
rc = sys_socket_nt(family, type, protocol);
}
- STRACE("socket(%s, %s, %s) → %d% lm", __describe_socket_family(family),
- __describe_socket_type(type), __describe_socket_protocol(protocol),
- rc);
+ STRACE("socket(%s, %s, %s) → %d% lm", DescribeSocketFamily(family),
+ DescribeSocketType(type), DescribeSocketProtocol(protocol), rc);
return rc;
}
diff --git a/libc/sock/struct/linger.h b/libc/sock/struct/linger.h
new file mode 100644
index 000000000..e5eb952a5
--- /dev/null
+++ b/libc/sock/struct/linger.h
@@ -0,0 +1,13 @@
+#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_LINGER_H_
+#define COSMOPOLITAN_LIBC_SOCK_STRUCT_LINGER_H_
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct linger { /* Linux+XNU+BSD ABI */
+ int32_t l_onoff; /* on/off */
+ int32_t l_linger; /* seconds */
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_LINGER_H_ */
diff --git a/libc/sock/struct/msghdr.h b/libc/sock/struct/msghdr.h
new file mode 100644
index 000000000..874930d3b
--- /dev/null
+++ b/libc/sock/struct/msghdr.h
@@ -0,0 +1,19 @@
+#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_MSGHDR_H_
+#define COSMOPOLITAN_LIBC_SOCK_STRUCT_MSGHDR_H_
+#include "libc/calls/struct/iovec.h"
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct msghdr { /* Linux+NT ABI */
+ void *msg_name; /* optional address */
+ uint32_t msg_namelen; /* size of msg_name */
+ struct iovec *msg_iov; /* scatter/gather array */
+ uint64_t msg_iovlen; /* iovec count */
+ void *msg_control; /* credentials and stuff */
+ uint64_t msg_controllen; /* size of msg_control */
+ uint32_t msg_flags; /* MSG_XXX */
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_MSGHDR_H_ */
diff --git a/libc/sock/struct/pollfd.h b/libc/sock/struct/pollfd.h
new file mode 100644
index 000000000..26753dc2d
--- /dev/null
+++ b/libc/sock/struct/pollfd.h
@@ -0,0 +1,14 @@
+#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
+#define COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct pollfd {
+ int32_t fd;
+ int16_t events;
+ int16_t revents;
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_ */
diff --git a/libc/sock/struct/sockaddr.h b/libc/sock/struct/sockaddr.h
new file mode 100644
index 000000000..681a46d06
--- /dev/null
+++ b/libc/sock/struct/sockaddr.h
@@ -0,0 +1,38 @@
+#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_H_
+#define COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_H_
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct sockaddr { /* Linux+NT ABI */
+ uint16_t sa_family; /* AF_XXX */
+ char sa_data[14];
+};
+
+struct in_addr { /* ARPA ABI */
+ /* e.g. 127|0<<8|0<<16|1<<24 or inet_pton(AF_INET, "127.0.0.1", &s_addr) */
+ uint32_t s_addr;
+};
+
+struct sockaddr_in { /* Linux+NT ABI */
+ uint16_t sin_family; /* AF_XXX */
+ uint16_t sin_port; /* htons(XXX) i.e. big endian */
+ struct in_addr sin_addr;
+ uint8_t sin_zero[8];
+};
+
+struct sockaddr_un {
+ uint16_t sun_family; /* AF_UNIX */
+ char sun_path[108]; /* path */
+};
+
+struct sockaddr_storage {
+ union {
+ uint16_t ss_family;
+ intptr_t __ss_align;
+ char __ss_storage[128];
+ };
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_H_ */
diff --git a/libc/sock/winsockblock.c b/libc/sock/winsockblock.c
index 9ccbe4b3e..63f0298f1 100644
--- a/libc/sock/winsockblock.c
+++ b/libc/sock/winsockblock.c
@@ -23,7 +23,8 @@
#include "libc/sock/sock.h"
#include "libc/str/str.h"
-textwindows int64_t __winsockblock(int64_t fh, unsigned eventbit, int64_t rc) {
+textwindows int64_t __winsockblock(int64_t fh, unsigned eventbit, int64_t rc,
+ uint32_t timeout) {
int64_t eh;
struct NtWsaNetworkEvents ev;
if (rc != -1) return rc;
diff --git a/libc/sock/wsablock.c b/libc/sock/wsablock.c
index d7ac994b3..acbde754d 100644
--- a/libc/sock/wsablock.c
+++ b/libc/sock/wsablock.c
@@ -26,10 +26,11 @@
#include "libc/sysv/errfuns.h"
textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped,
- uint32_t *flags, bool restartable) {
+ uint32_t *flags, bool restartable,
+ uint32_t timeout) {
uint32_t i, got;
if (WSAGetLastError() != kNtErrorIoPending) {
- NTTRACE("WSARecv failed %lm");
+ NTTRACE("sock i/o failed %lm");
return __winsockerr();
}
for (;;) {
@@ -39,10 +40,15 @@ textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped,
NTTRACE("WSAWaitForMultipleEvents failed %lm");
return __winsockerr();
} else if (i == kNtWaitTimeout || i == kNtWaitIoCompletion) {
- if (_check_interrupts(restartable, g_fds.p)) return eintr();
-#if _NTTRACE
- POLLTRACE("WSAWaitForMultipleEvents...");
-#endif
+ if (_check_interrupts(restartable, g_fds.p)) {
+ return eintr();
+ }
+ if (timeout) {
+ if (timeout <= __SIG_POLLING_INTERVAL_MS) {
+ return eagain();
+ }
+ timeout -= __SIG_POLLING_INTERVAL_MS;
+ }
} else {
break;
}
diff --git a/libc/testlib/benchrunner.c b/libc/testlib/benchrunner.c
index 0b4c57937..3ae4e2dd4 100644
--- a/libc/testlib/benchrunner.c
+++ b/libc/testlib/benchrunner.c
@@ -54,7 +54,6 @@ void testlib_benchwarmup(void) {
void testlib_runallbenchmarks(void) {
int e;
e = errno;
- _peekall();
if (!IsWindows()) {
mlockall(MCL_CURRENT);
nice(-1);
diff --git a/libc/thread/openbsd.internal.h b/libc/thread/openbsd.internal.h
new file mode 100644
index 000000000..49c27e66a
--- /dev/null
+++ b/libc/thread/openbsd.internal.h
@@ -0,0 +1,16 @@
+#ifndef COSMOPOLITAN_LIBC_THREAD_OPENBSD_INTERNAL_H_
+#define COSMOPOLITAN_LIBC_THREAD_OPENBSD_INTERNAL_H_
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct __tfork {
+ void *tf_tcb;
+ int32_t *tf_tid;
+ void *tf_stack;
+};
+
+int __tfork_thread(struct __tfork *, size_t, void (*)(void *), void *);
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_THREAD_OPENBSD_INTERNAL_H_ */
diff --git a/test/libc/intrin/pthread_mutex_lock_test.c b/test/libc/intrin/pthread_mutex_lock_test.c
index 76fb4178a..7afd56f78 100644
--- a/test/libc/intrin/pthread_mutex_lock_test.c
+++ b/test/libc/intrin/pthread_mutex_lock_test.c
@@ -16,33 +16,56 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/state.internal.h"
+#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
+#include "libc/intrin/futex.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/intrin/wait0.internal.h"
+#include "libc/log/check.h"
+#include "libc/macros.internal.h"
+#include "libc/math.h"
+#include "libc/mem/mem.h"
#include "libc/nexgen32e/threaded.h"
+#include "libc/runtime/gc.internal.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/consts/clone.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
+#include "libc/sysv/consts/rlimit.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
#include "libc/thread/thread.h"
#define THREADS 8
#define ITERATIONS 512
+#define TLS_SIZE PAGESIZE
+char *tls[THREADS];
char *stack[THREADS];
-char tls[THREADS][64];
+_Alignas(PAGESIZE) char tlsdata[THREADS * 3][TLS_SIZE];
+
+int count;
+_Atomic(int) started;
+_Atomic(int) finished;
+_Alignas(64) char slock;
+pthread_mutex_t mylock;
__attribute__((__constructor__)) void init(void) {
+ int i;
__enable_tls();
__enable_threads();
+ for (i = 0; i < THREADS; ++i) {
+ CHECK_NE(-1, mprotect(tlsdata[i * 3 + 0], TLS_SIZE, PROT_NONE));
+ tls[i] = tlsdata[i * 3 + 1];
+ CHECK_NE(-1, mprotect(tlsdata[i * 3 + 2], TLS_SIZE, PROT_NONE));
+ }
}
TEST(pthread_mutex_lock, normal) {
@@ -79,6 +102,7 @@ TEST(pthread_mutex_lock, recursive) {
TEST(pthread_mutex_lock, errorcheck) {
pthread_mutex_t lock;
pthread_mutexattr_t attr;
+ __assert_disable = true;
ASSERT_EQ(0, pthread_mutexattr_init(&attr));
ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
ASSERT_EQ(0, pthread_mutex_init(&lock, &attr));
@@ -89,20 +113,19 @@ TEST(pthread_mutex_lock, errorcheck) {
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
ASSERT_EQ(EPERM, pthread_mutex_unlock(&lock));
ASSERT_EQ(0, pthread_mutex_destroy(&lock));
+ __assert_disable = false;
}
-int count;
-_Atomic(int) finished;
-_Alignas(64) char slock;
-pthread_mutex_t lock;
-
int MutexWorker(void *p) {
int i;
+ ++started;
for (i = 0; i < ITERATIONS; ++i) {
- pthread_mutex_lock(&lock);
+ pthread_mutex_lock(&mylock);
++count;
- pthread_mutex_unlock(&lock);
+ pthread_mutex_unlock(&mylock);
}
+ ASSERT_NE(0, (int *)(tls[(intptr_t)p] + 0x38));
+ ++finished;
return 0;
}
@@ -111,27 +134,36 @@ TEST(pthread_mutex_lock, contention) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
- pthread_mutex_init(&lock, &attr);
+ pthread_mutex_init(&mylock, &attr);
pthread_mutexattr_destroy(&attr);
count = 0;
+ started = 0;
+ finished = 0;
for (i = 0; i < THREADS; ++i) {
- clone(MutexWorker,
- (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
- MAP_STACK | MAP_ANONYMOUS, -1, 0)),
- GetStackSize(),
- CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS,
- 0, 0, __initialize_tls(tls[i]), sizeof(tls[i]),
- (int *)(tls[i] + 0x38));
+ ASSERT_NE(MAP_FAILED,
+ (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
+ MAP_STACK | MAP_ANONYMOUS, -1, 0)));
+ ASSERT_NE(-1, clone(MutexWorker, stack[i], GetStackSize(),
+ CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_CHILD_SETTID |
+ CLONE_CHILD_CLEARTID | CLONE_SETTLS,
+ (void *)(intptr_t)i, 0, __initialize_tls(tls[i]),
+ TLS_SIZE, (int *)(tls[i] + 0x38)));
}
for (i = 0; i < THREADS; ++i) {
_wait0((int *)(tls[i] + 0x38));
+ ASSERT_EQ(0, *(int *)(tls[i] + 0x38));
}
- ASSERT_EQ(THREADS * ITERATIONS, count);
for (i = 0; i < THREADS; ++i) {
- munmap(stack[i], GetStackSize());
+ ASSERT_EQ(0, *(int *)(tls[i] + 0x38));
}
- EXPECT_EQ(0, pthread_mutex_destroy(&lock));
+ EXPECT_EQ(THREADS, started);
+ EXPECT_EQ(THREADS, finished);
+ EXPECT_EQ(THREADS * ITERATIONS, count);
+ for (i = 0; i < THREADS; ++i) {
+ ASSERT_SYS(0, 0, munmap(stack[i], GetStackSize()));
+ }
+ EXPECT_EQ(0, pthread_mutex_destroy(&mylock));
}
TEST(pthread_mutex_lock, rcontention) {
@@ -139,27 +171,36 @@ TEST(pthread_mutex_lock, rcontention) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&lock, &attr);
+ pthread_mutex_init(&mylock, &attr);
pthread_mutexattr_destroy(&attr);
count = 0;
+ started = 0;
+ finished = 0;
for (i = 0; i < THREADS; ++i) {
- clone(MutexWorker,
- (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
- MAP_STACK | MAP_ANONYMOUS, -1, 0)),
- GetStackSize(),
- CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS,
- 0, 0, __initialize_tls(tls[i]), sizeof(tls[i]),
- (int *)(tls[i] + 0x38));
+ ASSERT_NE(MAP_FAILED,
+ (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
+ MAP_STACK | MAP_ANONYMOUS, -1, 0)));
+ ASSERT_NE(-1, clone(MutexWorker, stack[i], GetStackSize(),
+ CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_CHILD_SETTID |
+ CLONE_CHILD_CLEARTID | CLONE_SETTLS,
+ (void *)(intptr_t)i, 0, __initialize_tls(tls[i]),
+ TLS_SIZE, (int *)(tls[i] + 0x38)));
}
for (i = 0; i < THREADS; ++i) {
_wait0((int *)(tls[i] + 0x38));
+ ASSERT_EQ(0, *(int *)(tls[i] + 0x38));
}
- ASSERT_EQ(THREADS * ITERATIONS, count);
for (i = 0; i < THREADS; ++i) {
- munmap(stack[i], GetStackSize());
+ ASSERT_EQ(0, *(int *)(tls[i] + 0x38));
}
- EXPECT_EQ(0, pthread_mutex_destroy(&lock));
+ EXPECT_EQ(THREADS, started);
+ EXPECT_EQ(THREADS, finished);
+ EXPECT_EQ(THREADS * ITERATIONS, count);
+ for (i = 0; i < THREADS; ++i) {
+ ASSERT_SYS(0, 0, munmap(stack[i], GetStackSize()));
+ }
+ EXPECT_EQ(0, pthread_mutex_destroy(&mylock));
}
TEST(pthread_mutex_lock, econtention) {
@@ -167,36 +208,47 @@ TEST(pthread_mutex_lock, econtention) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
- pthread_mutex_init(&lock, &attr);
+ pthread_mutex_init(&mylock, &attr);
pthread_mutexattr_destroy(&attr);
count = 0;
+ started = 0;
+ finished = 0;
for (i = 0; i < THREADS; ++i) {
- clone(MutexWorker,
- (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
- MAP_STACK | MAP_ANONYMOUS, -1, 0)),
- GetStackSize(),
- CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS,
- 0, 0, __initialize_tls(tls[i]), sizeof(tls[i]),
- (int *)(tls[i] + 0x38));
+ ASSERT_NE(MAP_FAILED,
+ (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
+ MAP_STACK | MAP_ANONYMOUS, -1, 0)));
+ ASSERT_NE(-1, clone(MutexWorker, stack[i], GetStackSize(),
+ CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_CHILD_SETTID |
+ CLONE_CHILD_CLEARTID | CLONE_SETTLS,
+ (void *)(intptr_t)i, 0, __initialize_tls(tls[i]),
+ TLS_SIZE, (int *)(tls[i] + 0x38)));
}
for (i = 0; i < THREADS; ++i) {
_wait0((int *)(tls[i] + 0x38));
+ ASSERT_EQ(0, *(int *)(tls[i] + 0x38));
}
- ASSERT_EQ(THREADS * ITERATIONS, count);
for (i = 0; i < THREADS; ++i) {
- munmap(stack[i], GetStackSize());
+ ASSERT_EQ(0, *(int *)(tls[i] + 0x38));
}
- EXPECT_EQ(0, pthread_mutex_destroy(&lock));
+ EXPECT_EQ(THREADS, started);
+ EXPECT_EQ(THREADS, finished);
+ EXPECT_EQ(THREADS * ITERATIONS, count);
+ for (i = 0; i < THREADS; ++i) {
+ ASSERT_SYS(0, 0, munmap(stack[i], GetStackSize()));
+ }
+ EXPECT_EQ(0, pthread_mutex_destroy(&mylock));
}
int SpinlockWorker(void *p) {
int i;
+ ++started;
for (i = 0; i < ITERATIONS; ++i) {
_spinlock(&slock);
++count;
_spunlock(&slock);
}
+ ASSERT_NE(0, (int *)(tls[(intptr_t)p] + 0x38));
++finished;
return 0;
}
@@ -204,24 +256,27 @@ int SpinlockWorker(void *p) {
TEST(_spinlock, contention) {
int i;
count = 0;
+ started = 0;
finished = 0;
for (i = 0; i < THREADS; ++i) {
- clone(SpinlockWorker,
- (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
- MAP_STACK | MAP_ANONYMOUS, -1, 0)),
- GetStackSize(),
- CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS,
- 0, 0, __initialize_tls(tls[i]), sizeof(tls[i]),
- (int *)(tls[i] + 0x38));
+ ASSERT_NE(MAP_FAILED,
+ (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
+ MAP_STACK | MAP_ANONYMOUS, -1, 0)));
+ ASSERT_NE(-1, clone(SpinlockWorker, stack[i], GetStackSize(),
+ CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_CHILD_SETTID |
+ CLONE_CHILD_CLEARTID | CLONE_SETTLS,
+ (void *)(intptr_t)i, 0, __initialize_tls(tls[i]),
+ TLS_SIZE, (int *)(tls[i] + 0x38)));
}
for (i = 0; i < THREADS; ++i) {
_wait0((int *)(tls[i] + 0x38));
}
- ASSERT_EQ(THREADS, finished);
- ASSERT_EQ(THREADS * ITERATIONS, count);
+ EXPECT_EQ(THREADS, started);
+ EXPECT_EQ(THREADS, finished);
+ EXPECT_EQ(THREADS * ITERATIONS, count);
for (i = 0; i < THREADS; ++i) {
- munmap(stack[i], GetStackSize());
+ ASSERT_SYS(0, 0, munmap(stack[i], GetStackSize()));
}
}
diff --git a/test/libc/str/strsignal_test.c b/test/libc/intrin/strsignal_test.c
similarity index 98%
rename from test/libc/str/strsignal_test.c
rename to test/libc/intrin/strsignal_test.c
index 0a00bd4c0..fda99638d 100644
--- a/test/libc/str/strsignal_test.c
+++ b/test/libc/intrin/strsignal_test.c
@@ -21,7 +21,7 @@
#include "libc/testlib/testlib.h"
TEST(strsignal, test) {
- EXPECT_STREQ("SIGZERO", strsignal(0));
+ EXPECT_STREQ("0", strsignal(0));
EXPECT_STREQ("SIGINT", strsignal(SIGINT));
EXPECT_STREQ("SIGQUIT", strsignal(SIGQUIT));
EXPECT_STREQ("SIGALRM", strsignal(SIGALRM));
diff --git a/test/libc/runtime/clone_test.c b/test/libc/runtime/clone_test.c
index b7b6b0a44..24ebdd99c 100644
--- a/test/libc/runtime/clone_test.c
+++ b/test/libc/runtime/clone_test.c
@@ -79,7 +79,8 @@ TEST(clone, testNullFunc_raisesEinval) {
int CloneTest1(void *arg) {
intptr_t rsp, top, bot;
CheckStackIsAligned();
- PrintBacktraceUsingSymbols(2, __builtin_frame_address(0), GetSymbolTable());
+ // PrintBacktraceUsingSymbols(2, __builtin_frame_address(0),
+ // GetSymbolTable());
rsp = (intptr_t)__builtin_frame_address(0);
bot = (intptr_t)stack;
top = bot + GetStackSize();
diff --git a/test/libc/sock/setsockopt_test.c b/test/libc/sock/setsockopt_test.c
new file mode 100644
index 000000000..85a3147d9
--- /dev/null
+++ b/test/libc/sock/setsockopt_test.c
@@ -0,0 +1,39 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2022 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/calls/struct/timeval.h"
+#include "libc/sock/sock.h"
+#include "libc/sock/struct/sockaddr.h"
+#include "libc/sysv/consts/af.h"
+#include "libc/sysv/consts/ipproto.h"
+#include "libc/sysv/consts/so.h"
+#include "libc/sysv/consts/sock.h"
+#include "libc/sysv/consts/sol.h"
+#include "libc/testlib/testlib.h"
+
+TEST(setsockopt, SO_RCVTIMEO) {
+ char buf[32];
+ struct timeval tv = {0, 10000};
+ struct sockaddr_in sa = {AF_INET};
+ EXPECT_SYS(0, 3, socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
+ EXPECT_SYS(0, 0, setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));
+ EXPECT_SYS(0, 0, bind(3, &sa, sizeof(struct sockaddr_in)));
+ EXPECT_SYS(EAGAIN, -1, read(3, buf, sizeof(buf)));
+ EXPECT_SYS(0, 0, close(3));
+}
diff --git a/third_party/linenoise/linenoise.c b/third_party/linenoise/linenoise.c
index 051004ab6..197d4edd1 100644
--- a/third_party/linenoise/linenoise.c
+++ b/third_party/linenoise/linenoise.c
@@ -773,7 +773,9 @@ static ssize_t linenoiseRead(int fd, char *buf, size_t size,
}
if (gotcont && rawmode != -1) {
rawmode = -1;
+ --__strace;
linenoiseEnableRawMode(0);
+ ++__strace;
if (l) refreshme = 1;
}
if (l && gotwinch) refreshme = 1;
diff --git a/third_party/lua/lunix.c b/third_party/lua/lunix.c
index c7c9c92e0..3340f9cff 100644
--- a/third_party/lua/lunix.c
+++ b/third_party/lua/lunix.c
@@ -2586,7 +2586,7 @@ int LuaUnix(lua_State *L) {
LoadMagnums(L, kErrnoNames, "");
LoadMagnums(L, kOpenFlags, "O_");
- LoadMagnums(L, kSignalNames, "SIG");
+ LoadMagnums(L, kSignalNames, "");
LoadMagnums(L, kIpOptnames, "IP_");
LoadMagnums(L, kTcpOptnames, "TCP_");
LoadMagnums(L, kSockOptnames, "SO_");
diff --git a/third_party/make/make.mk b/third_party/make/make.mk
index 98e0648b1..9570f1cf5 100644
--- a/third_party/make/make.mk
+++ b/third_party/make/make.mk
@@ -62,7 +62,6 @@ THIRD_PARTY_MAKE_SRCS_BASE = \
third_party/make/remake.c \
third_party/make/remote-stub.c \
third_party/make/rule.c \
- third_party/make/signame.c \
third_party/make/strcache.c \
third_party/make/variable.c \
third_party/make/version.c \
diff --git a/third_party/make/signame.c b/third_party/make/signame.c
deleted file mode 100644
index 461f2e5f4..000000000
--- a/third_party/make/signame.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/* clang-format off */
-/* Convert between signal names and numbers.
-Copyright (C) 1990-2020 Free Software Foundation, Inc.
-This file is part of GNU Make.
-
-GNU Make is free software; you can redistribute it and/or modify it under the
-terms of the GNU General Public License as published by the Free Software
-Foundation; either version 3 of the License, or (at your option) any later
-version.
-
-GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program. If not, see . */
-
-#include "third_party/make/makeint.inc"
-
-/* If the system provides strsignal, we don't need it. */
-
-#if !HAVE_STRSIGNAL
-
-/* If the system provides sys_siglist, we'll use that.
- Otherwise create our own.
- */
-
-#if !HAVE_DECL_SYS_SIGLIST
-
-/* Some systems do not define NSIG in . */
-#ifndef NSIG
-#ifdef _NSIG
-#define NSIG _NSIG
-#else
-#define NSIG 32
-#endif
-#endif
-
-/* There is too much variation in Sys V signal numbers and names, so
- we must initialize them at runtime. */
-
-static const char *undoc;
-
-static const char *sys_siglist[NSIG];
-
-/* Table of abbreviations for signals. Note: A given number can
- appear more than once with different abbreviations. */
-#define SIG_TABLE_SIZE (NSIG*2)
-
-typedef struct
- {
- int number;
- const char *abbrev;
- } num_abbrev;
-
-static num_abbrev sig_table[SIG_TABLE_SIZE];
-
-/* Number of elements of sig_table used. */
-static int sig_table_nelts = 0;
-
-/* Enter signal number NUMBER into the tables with ABBREV and NAME. */
-
-static void
-init_sig (int number, const char *abbrev, const char *name)
-{
- /* If this value is ever greater than NSIG it seems like it'd be a bug in
- the system headers, but... better safe than sorry. We know, for
- example, that this isn't always true on VMS. */
-
- if (number >= 0 && number < NSIG)
- sys_siglist[number] = name;
-
- if (sig_table_nelts < SIG_TABLE_SIZE)
- {
- sig_table[sig_table_nelts].number = number;
- sig_table[sig_table_nelts++].abbrev = abbrev;
- }
-}
-
-static int
-signame_init (void)
-{
- int i;
-
- undoc = xstrdup (_("unknown signal"));
-
- /* Initialize signal names. */
- for (i = 0; i < NSIG; i++)
- sys_siglist[i] = undoc;
-
- /* Initialize signal names. */
-#if defined (SIGHUP)
- init_sig (SIGHUP, "HUP", _("Hangup"));
-#endif
-#if defined (SIGINT)
- init_sig (SIGINT, "INT", _("Interrupt"));
-#endif
-#if defined (SIGQUIT)
- init_sig (SIGQUIT, "QUIT", _("Quit"));
-#endif
-#if defined (SIGILL)
- init_sig (SIGILL, "ILL", _("Illegal Instruction"));
-#endif
-#if defined (SIGTRAP)
- init_sig (SIGTRAP, "TRAP", _("Trace/breakpoint trap"));
-#endif
- /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because
- SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't. */
-#if defined (SIGABRT)
- init_sig (SIGABRT, "ABRT", _("Aborted"));
-#endif
-#if defined (SIGIOT)
- init_sig (SIGIOT, "IOT", _("IOT trap"));
-#endif
-#if defined (SIGEMT)
- init_sig (SIGEMT, "EMT", _("EMT trap"));
-#endif
-#if defined (SIGFPE)
- init_sig (SIGFPE, "FPE", _("Floating point exception"));
-#endif
-#if defined (SIGKILL)
- init_sig (SIGKILL, "KILL", _("Killed"));
-#endif
-#if defined (SIGBUS)
- init_sig (SIGBUS, "BUS", _("Bus error"));
-#endif
-#if defined (SIGSEGV)
- init_sig (SIGSEGV, "SEGV", _("Segmentation fault"));
-#endif
-#if defined (SIGSYS)
- init_sig (SIGSYS, "SYS", _("Bad system call"));
-#endif
-#if defined (SIGPIPE)
- init_sig (SIGPIPE, "PIPE", _("Broken pipe"));
-#endif
-#if defined (SIGALRM)
- init_sig (SIGALRM, "ALRM", _("Alarm clock"));
-#endif
-#if defined (SIGTERM)
- init_sig (SIGTERM, "TERM", _("Terminated"));
-#endif
-#if defined (SIGUSR1)
- init_sig (SIGUSR1, "USR1", _("User defined signal 1"));
-#endif
-#if defined (SIGUSR2)
- init_sig (SIGUSR2, "USR2", _("User defined signal 2"));
-#endif
- /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that
- is what is in POSIX.1. */
-#if defined (SIGCHLD)
- init_sig (SIGCHLD, "CHLD", _("Child exited"));
-#endif
-#if defined (SIGCLD)
- init_sig (SIGCLD, "CLD", _("Child exited"));
-#endif
-#if defined (SIGPWR)
- init_sig (SIGPWR, "PWR", _("Power failure"));
-#endif
-#if defined (SIGTSTP)
- init_sig (SIGTSTP, "TSTP", _("Stopped"));
-#endif
-#if defined (SIGTTIN)
- init_sig (SIGTTIN, "TTIN", _("Stopped (tty input)"));
-#endif
-#if defined (SIGTTOU)
- init_sig (SIGTTOU, "TTOU", _("Stopped (tty output)"));
-#endif
-#if defined (SIGSTOP)
- init_sig (SIGSTOP, "STOP", _("Stopped (signal)"));
-#endif
-#if defined (SIGXCPU)
- init_sig (SIGXCPU, "XCPU", _("CPU time limit exceeded"));
-#endif
-#if defined (SIGXFSZ)
- init_sig (SIGXFSZ, "XFSZ", _("File size limit exceeded"));
-#endif
-#if defined (SIGVTALRM)
- init_sig (SIGVTALRM, "VTALRM", _("Virtual timer expired"));
-#endif
-#if defined (SIGPROF)
- init_sig (SIGPROF, "PROF", _("Profiling timer expired"));
-#endif
-#if defined (SIGWINCH)
- /* "Window size changed" might be more accurate, but even if that
- is all that it means now, perhaps in the future it will be
- extended to cover other kinds of window changes. */
- init_sig (SIGWINCH, "WINCH", _("Window changed"));
-#endif
-#if defined (SIGCONT)
- init_sig (SIGCONT, "CONT", _("Continued"));
-#endif
-#if defined (SIGURG)
- init_sig (SIGURG, "URG", _("Urgent I/O condition"));
-#endif
-#if defined (SIGIO)
- /* "I/O pending" has also been suggested. A disadvantage is that signal
- only happens when the process has asked for it, not every time I/O is
- pending. Another disadvantage is the confusion from giving it a
- different name than under Unix. */
- init_sig (SIGIO, "IO", _("I/O possible"));
-#endif
-#if defined (SIGWIND)
- init_sig (SIGWIND, "WIND", _("SIGWIND"));
-#endif
-#if defined (SIGPHONE)
- init_sig (SIGPHONE, "PHONE", _("SIGPHONE"));
-#endif
-#if defined (SIGPOLL)
- init_sig (SIGPOLL, "POLL", _("I/O possible"));
-#endif
-#if defined (SIGLOST)
- init_sig (SIGLOST, "LOST", _("Resource lost"));
-#endif
-#if defined (SIGDANGER)
- init_sig (SIGDANGER, "DANGER", _("Danger signal"));
-#endif
-#if defined (SIGINFO)
- init_sig (SIGINFO, "INFO", _("Information request"));
-#endif
-#if defined (SIGNOFP)
- init_sig (SIGNOFP, "NOFP", _("Floating point co-processor not available"));
-#endif
-
- return 1;
-}
-
-#endif /* HAVE_DECL_SYS_SIGLIST */
-
-
-char *
-strsignal (int sig)
-{
- static char buf[] = "Signal 12345678901234567890";
-
-#if ! HAVE_DECL_SYS_SIGLIST
-# if HAVE_DECL__SYS_SIGLIST
-# define sys_siglist _sys_siglist
-# elif HAVE_DECL___SYS_SIGLIST
-# define sys_siglist __sys_siglist
-# else
- static int sig_initted = 0;
-
- if (!sig_initted)
- sig_initted = signame_init ();
-# endif
-#endif
-
- if (sig > 0 && sig < NSIG)
- return (char *) sys_siglist[sig];
-
- sprintf (buf, "Signal %d", sig);
- return buf;
-}
-
-#endif /* HAVE_STRSIGNAL */
diff --git a/third_party/stb/stb_truetype.c b/third_party/stb/stb_truetype.c
index 24563fb39..3ab18baa9 100644
--- a/third_party/stb/stb_truetype.c
+++ b/third_party/stb/stb_truetype.c
@@ -405,6 +405,7 @@ static wontreturn void stbtt__assert_fail(const char *x, int line) {
longjmp(stbtt_jmpbuf, line);
} else {
__assert_fail(x, __FILE__, line);
+ abort();
}
}
diff --git a/tool/net/redbean.c b/tool/net/redbean.c
index 4d918f67c..c7f9c6e64 100644
--- a/tool/net/redbean.c
+++ b/tool/net/redbean.c
@@ -43,6 +43,7 @@
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/alloca.h"
+#include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/nexgen32e/nt2sysv.h"
@@ -56,6 +57,7 @@
#include "libc/runtime/gc.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/internal.h"
+#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/sock/goodsocket.internal.h"
#include "libc/sock/sock.h"
@@ -158,20 +160,28 @@ STATIC_YOINK("ShowCrashReportsEarly");
#define HeaderEqualCase(H, S) \
SlicesEqualCase(S, strlen(S), HeaderData(H), HeaderLength(H))
-#define TRACE_BEGIN \
- do { \
- if (!IsTiny()) { \
- if (funtrace) ++__ftrace; \
- if (systrace) ++__strace; \
- } \
+#define TRACE_BEGIN \
+ do { \
+ if (!IsTiny()) { \
+ if (funtrace) { \
+ atomic_fetch_add_explicit(&__ftrace, 1, memory_order_relaxed); \
+ } \
+ if (systrace) { \
+ atomic_fetch_add_explicit(&__strace, 1, memory_order_relaxed); \
+ } \
+ } \
} while (0)
-#define TRACE_END \
- do { \
- if (!IsTiny()) { \
- if (funtrace) --__ftrace; \
- if (systrace) --__strace; \
- } \
+#define TRACE_END \
+ do { \
+ if (!IsTiny()) { \
+ if (funtrace) { \
+ atomic_fetch_sub_explicit(&__ftrace, 1, memory_order_relaxed); \
+ } \
+ if (systrace) { \
+ atomic_fetch_sub_explicit(&__strace, 1, memory_order_relaxed); \
+ } \
+ } \
} while (0)
// letters not used: EINOQYnoqwxy
@@ -399,9 +409,6 @@ static int statuscode;
static int shutdownsig;
static int sslpskindex;
static int oldloglevel;
-static int *monitortid;
-static char *monitortls;
-static char *monitorstack;
static int maxpayloadsize;
static int messageshandled;
static int sslticketlifetime;
@@ -413,17 +420,21 @@ static lua_State *GL;
static lua_State *YL;
static char *content;
static uint8_t *zmap;
+static char *repltls;
static uint8_t *zbase;
static uint8_t *zcdir;
static size_t hdrsize;
static size_t msgsize;
static size_t amtread;
+static char *replstack;
static reader_f reader;
static writer_f writer;
static char *extrahdrs;
+static char *monitortls;
static char *luaheaderp;
static const char *zpath;
static const char *brand;
+static char *monitorstack;
static char gzip_footer[8];
static const char *pidpath;
static const char *logpath;
@@ -5014,151 +5025,151 @@ static const char *const kDontAutoComplete[] = {
//
static const luaL_Reg kLuaFuncs[] = {
- {"Benchmark", LuaBenchmark}, //
- {"Bsf", LuaBsf}, //
- {"Bsr", LuaBsr}, //
- {"CategorizeIp", LuaCategorizeIp}, //
- {"Compress", LuaCompress}, //
- {"Crc32", LuaCrc32}, //
- {"Crc32c", LuaCrc32c}, //
- {"Decimate", LuaDecimate}, //
- {"DecodeBase64", LuaDecodeBase64}, //
- {"DecodeLatin1", LuaDecodeLatin1}, //
- {"EncodeBase64", LuaEncodeBase64}, //
- {"EncodeJson", LuaEncodeJson}, //
- {"EncodeLatin1", LuaEncodeLatin1}, //
- {"EncodeLua", LuaEncodeLua}, //
- {"EncodeUrl", LuaEncodeUrl}, //
- {"EscapeFragment", LuaEscapeFragment}, //
- {"EscapeHost", LuaEscapeHost}, //
- {"EscapeHtml", LuaEscapeHtml}, //
- {"EscapeIp", LuaEscapeIp}, //
- {"EscapeLiteral", LuaEscapeLiteral}, //
- {"EscapeParam", LuaEscapeParam}, //
- {"EscapePass", LuaEscapePass}, //
- {"EscapePath", LuaEscapePath}, //
- {"EscapeSegment", LuaEscapeSegment}, //
- {"EscapeUser", LuaEscapeUser}, //
- {"Fetch", LuaFetch}, //
- {"FormatHttpDateTime", LuaFormatHttpDateTime}, //
- {"FormatIp", LuaFormatIp}, //
- {"GetAssetComment", LuaGetAssetComment}, //
+ {"Benchmark", LuaBenchmark}, //
+ {"Bsf", LuaBsf}, //
+ {"Bsr", LuaBsr}, //
+ {"CategorizeIp", LuaCategorizeIp}, //
+ {"Compress", LuaCompress}, //
+ {"Crc32", LuaCrc32}, //
+ {"Crc32c", LuaCrc32c}, //
+ {"Decimate", LuaDecimate}, //
+ {"DecodeBase64", LuaDecodeBase64}, //
+ {"DecodeLatin1", LuaDecodeLatin1}, //
+ {"EncodeBase64", LuaEncodeBase64}, //
+ {"EncodeJson", LuaEncodeJson}, //
+ {"EncodeLatin1", LuaEncodeLatin1}, //
+ {"EncodeLua", LuaEncodeLua}, //
+ {"EncodeUrl", LuaEncodeUrl}, //
+ {"EscapeFragment", LuaEscapeFragment}, //
+ {"EscapeHost", LuaEscapeHost}, //
+ {"EscapeHtml", LuaEscapeHtml}, //
+ {"EscapeIp", LuaEscapeIp}, //
+ {"EscapeLiteral", LuaEscapeLiteral}, //
+ {"EscapeParam", LuaEscapeParam}, //
+ {"EscapePass", LuaEscapePass}, //
+ {"EscapePath", LuaEscapePath}, //
+ {"EscapeSegment", LuaEscapeSegment}, //
+ {"EscapeUser", LuaEscapeUser}, //
+ {"Fetch", LuaFetch}, //
+ {"FormatHttpDateTime", LuaFormatHttpDateTime}, //
+ {"FormatIp", LuaFormatIp}, //
+ {"GetAssetComment", LuaGetAssetComment}, //
{"GetAssetLastModifiedTime", LuaGetAssetLastModifiedTime}, //
- {"GetAssetMode", LuaGetAssetMode}, //
- {"GetAssetSize", LuaGetAssetSize}, //
- {"GetBody", LuaGetBody}, //
- {"GetClientAddr", LuaGetClientAddr}, //
- {"GetClientFd", LuaGetClientFd}, //
- {"GetCookie", LuaGetCookie}, //
- {"GetCpuCore", LuaGetCpuCore}, //
- {"GetCpuCount", LuaGetCpuCount}, //
- {"GetCpuNode", LuaGetCpuNode}, //
- {"GetCryptoHash", LuaGetCryptoHash}, //
- {"GetDate", LuaGetDate}, //
- {"GetEffectivePath", LuaGetEffectivePath}, //
- {"GetFragment", LuaGetFragment}, //
- {"GetHeader", LuaGetHeader}, //
- {"GetHeaders", LuaGetHeaders}, //
- {"GetHost", LuaGetHost}, //
- {"GetHostOs", LuaGetHostOs}, //
- {"GetHttpReason", LuaGetHttpReason}, //
- {"GetHttpVersion", LuaGetHttpVersion}, //
- {"GetLogLevel", LuaGetLogLevel}, //
- {"GetMethod", LuaGetMethod}, //
- {"GetMonospaceWidth", LuaGetMonospaceWidth}, //
- {"GetParam", LuaGetParam}, //
- {"GetParams", LuaGetParams}, //
- {"GetPass", LuaGetPass}, //
- {"GetPath", LuaGetPath}, //
- {"GetPort", LuaGetPort}, //
- {"GetRandomBytes", LuaGetRandomBytes}, //
- {"GetRedbeanVersion", LuaGetRedbeanVersion}, //
- {"GetRemoteAddr", LuaGetRemoteAddr}, //
- {"GetScheme", LuaGetScheme}, //
- {"GetServerAddr", LuaGetServerAddr}, //
- {"GetStatus", LuaGetStatus}, //
- {"GetTime", LuaGetTime}, //
- {"GetUrl", LuaGetUrl}, //
- {"GetUser", LuaGetUser}, //
- {"GetZipPaths", LuaGetZipPaths}, //
- {"HasControlCodes", LuaHasControlCodes}, //
- {"HasParam", LuaHasParam}, //
- {"HidePath", LuaHidePath}, //
- {"IndentLines", LuaIndentLines}, //
- {"IsAcceptableHost", LuaIsAcceptableHost}, //
- {"IsAcceptablePath", LuaIsAcceptablePath}, //
- {"IsAcceptablePort", LuaIsAcceptablePort}, //
- {"IsClientUsingSsl", LuaIsClientUsingSsl}, //
- {"IsAssetCompressed", LuaIsAssetCompressed}, //
- {"IsDaemon", LuaIsDaemon}, //
- {"IsHeaderRepeatable", LuaIsHeaderRepeatable}, //
- {"IsHiddenPath", LuaIsHiddenPath}, //
- {"IsLoopbackIp", LuaIsLoopbackIp}, //
- {"IsPrivateIp", LuaIsPrivateIp}, //
- {"IsPublicIp", LuaIsPublicIp}, //
- {"IsReasonablePath", LuaIsReasonablePath}, //
- {"IsValidHttpToken", LuaIsValidHttpToken}, //
- {"LaunchBrowser", LuaLaunchBrowser}, //
- {"Lemur64", LuaLemur64}, //
- {"LoadAsset", LuaLoadAsset}, //
- {"Log", LuaLog}, //
- {"Md5", LuaMd5}, //
- {"MeasureEntropy", LuaMeasureEntropy}, //
- {"ParseHost", LuaParseHost}, //
- {"ParseHttpDateTime", LuaParseHttpDateTime}, //
- {"ParseIp", LuaParseIp}, //
- {"ParseParams", LuaParseParams}, //
- {"ParseUrl", LuaParseUrl}, //
- {"Popcnt", LuaPopcnt}, //
- {"ProgramAddr", LuaProgramAddr}, //
- {"ProgramBrand", LuaProgramBrand}, //
- {"ProgramCache", LuaProgramCache}, //
- {"ProgramDirectory", LuaProgramDirectory}, //
- {"ProgramGid", LuaProgramGid}, //
- {"ProgramHeader", LuaProgramHeader}, //
- {"ProgramLogBodies", LuaProgramLogBodies}, //
- {"ProgramLogMessages", LuaProgramLogMessages}, //
- {"ProgramLogPath", LuaProgramLogPath}, //
- {"ProgramMaxPayloadSize", LuaProgramMaxPayloadSize}, //
- {"ProgramPidPath", LuaProgramPidPath}, //
- {"ProgramPort", LuaProgramPort}, //
- {"ProgramRedirect", LuaProgramRedirect}, //
- {"ProgramTimeout", LuaProgramTimeout}, //
- {"ProgramUid", LuaProgramUid}, //
- {"ProgramUniprocess", LuaProgramUniprocess}, //
- {"Rand64", LuaRand64}, //
- {"Rdrand", LuaRdrand}, //
- {"Rdseed", LuaRdseed}, //
- {"Rdtsc", LuaRdtsc}, //
- {"ResolveIp", LuaResolveIp}, //
- {"Route", LuaRoute}, //
- {"RouteHost", LuaRouteHost}, //
- {"RoutePath", LuaRoutePath}, //
- {"ServeAsset", LuaServeAsset}, //
- {"ServeError", LuaServeError}, //
- {"ServeIndex", LuaServeIndex}, //
- {"ServeListing", LuaServeListing}, //
- {"ServeRedirect", LuaServeRedirect}, //
- {"ServeStatusz", LuaServeStatusz}, //
- {"SetCookie", LuaSetCookie}, //
- {"SetHeader", LuaSetHeader}, //
- {"SetLogLevel", LuaSetLogLevel}, //
- {"SetStatus", LuaSetStatus}, //
- {"Sha1", LuaSha1}, //
- {"Sha224", LuaSha224}, //
- {"Sha256", LuaSha256}, //
- {"Sha384", LuaSha384}, //
- {"Sha512", LuaSha512}, //
- {"Sleep", LuaSleep}, //
- {"Slurp", LuaSlurp}, //
- {"StoreAsset", LuaStoreAsset}, //
- {"Uncompress", LuaUncompress}, //
- {"Underlong", LuaUnderlong}, //
- {"VisualizeControlCodes", LuaVisualizeControlCodes}, //
- {"Write", LuaWrite}, //
- {"bin", LuaBin}, //
- {"hex", LuaHex}, //
- {"oct", LuaOct}, //
+ {"GetAssetMode", LuaGetAssetMode}, //
+ {"GetAssetSize", LuaGetAssetSize}, //
+ {"GetBody", LuaGetBody}, //
+ {"GetClientAddr", LuaGetClientAddr}, //
+ {"GetClientFd", LuaGetClientFd}, //
+ {"GetCookie", LuaGetCookie}, //
+ {"GetCpuCore", LuaGetCpuCore}, //
+ {"GetCpuCount", LuaGetCpuCount}, //
+ {"GetCpuNode", LuaGetCpuNode}, //
+ {"GetCryptoHash", LuaGetCryptoHash}, //
+ {"GetDate", LuaGetDate}, //
+ {"GetEffectivePath", LuaGetEffectivePath}, //
+ {"GetFragment", LuaGetFragment}, //
+ {"GetHeader", LuaGetHeader}, //
+ {"GetHeaders", LuaGetHeaders}, //
+ {"GetHost", LuaGetHost}, //
+ {"GetHostOs", LuaGetHostOs}, //
+ {"GetHttpReason", LuaGetHttpReason}, //
+ {"GetHttpVersion", LuaGetHttpVersion}, //
+ {"GetLogLevel", LuaGetLogLevel}, //
+ {"GetMethod", LuaGetMethod}, //
+ {"GetMonospaceWidth", LuaGetMonospaceWidth}, //
+ {"GetParam", LuaGetParam}, //
+ {"GetParams", LuaGetParams}, //
+ {"GetPass", LuaGetPass}, //
+ {"GetPath", LuaGetPath}, //
+ {"GetPort", LuaGetPort}, //
+ {"GetRandomBytes", LuaGetRandomBytes}, //
+ {"GetRedbeanVersion", LuaGetRedbeanVersion}, //
+ {"GetRemoteAddr", LuaGetRemoteAddr}, //
+ {"GetScheme", LuaGetScheme}, //
+ {"GetServerAddr", LuaGetServerAddr}, //
+ {"GetStatus", LuaGetStatus}, //
+ {"GetTime", LuaGetTime}, //
+ {"GetUrl", LuaGetUrl}, //
+ {"GetUser", LuaGetUser}, //
+ {"GetZipPaths", LuaGetZipPaths}, //
+ {"HasControlCodes", LuaHasControlCodes}, //
+ {"HasParam", LuaHasParam}, //
+ {"HidePath", LuaHidePath}, //
+ {"IndentLines", LuaIndentLines}, //
+ {"IsAcceptableHost", LuaIsAcceptableHost}, //
+ {"IsAcceptablePath", LuaIsAcceptablePath}, //
+ {"IsAcceptablePort", LuaIsAcceptablePort}, //
+ {"IsClientUsingSsl", LuaIsClientUsingSsl}, //
+ {"IsAssetCompressed", LuaIsAssetCompressed}, //
+ {"IsDaemon", LuaIsDaemon}, //
+ {"IsHeaderRepeatable", LuaIsHeaderRepeatable}, //
+ {"IsHiddenPath", LuaIsHiddenPath}, //
+ {"IsLoopbackIp", LuaIsLoopbackIp}, //
+ {"IsPrivateIp", LuaIsPrivateIp}, //
+ {"IsPublicIp", LuaIsPublicIp}, //
+ {"IsReasonablePath", LuaIsReasonablePath}, //
+ {"IsValidHttpToken", LuaIsValidHttpToken}, //
+ {"LaunchBrowser", LuaLaunchBrowser}, //
+ {"Lemur64", LuaLemur64}, //
+ {"LoadAsset", LuaLoadAsset}, //
+ {"Log", LuaLog}, //
+ {"Md5", LuaMd5}, //
+ {"MeasureEntropy", LuaMeasureEntropy}, //
+ {"ParseHost", LuaParseHost}, //
+ {"ParseHttpDateTime", LuaParseHttpDateTime}, //
+ {"ParseIp", LuaParseIp}, //
+ {"ParseParams", LuaParseParams}, //
+ {"ParseUrl", LuaParseUrl}, //
+ {"Popcnt", LuaPopcnt}, //
+ {"ProgramAddr", LuaProgramAddr}, //
+ {"ProgramBrand", LuaProgramBrand}, //
+ {"ProgramCache", LuaProgramCache}, //
+ {"ProgramDirectory", LuaProgramDirectory}, //
+ {"ProgramGid", LuaProgramGid}, //
+ {"ProgramHeader", LuaProgramHeader}, //
+ {"ProgramLogBodies", LuaProgramLogBodies}, //
+ {"ProgramLogMessages", LuaProgramLogMessages}, //
+ {"ProgramLogPath", LuaProgramLogPath}, //
+ {"ProgramMaxPayloadSize", LuaProgramMaxPayloadSize}, //
+ {"ProgramPidPath", LuaProgramPidPath}, //
+ {"ProgramPort", LuaProgramPort}, //
+ {"ProgramRedirect", LuaProgramRedirect}, //
+ {"ProgramTimeout", LuaProgramTimeout}, //
+ {"ProgramUid", LuaProgramUid}, //
+ {"ProgramUniprocess", LuaProgramUniprocess}, //
+ {"Rand64", LuaRand64}, //
+ {"Rdrand", LuaRdrand}, //
+ {"Rdseed", LuaRdseed}, //
+ {"Rdtsc", LuaRdtsc}, //
+ {"ResolveIp", LuaResolveIp}, //
+ {"Route", LuaRoute}, //
+ {"RouteHost", LuaRouteHost}, //
+ {"RoutePath", LuaRoutePath}, //
+ {"ServeAsset", LuaServeAsset}, //
+ {"ServeError", LuaServeError}, //
+ {"ServeIndex", LuaServeIndex}, //
+ {"ServeListing", LuaServeListing}, //
+ {"ServeRedirect", LuaServeRedirect}, //
+ {"ServeStatusz", LuaServeStatusz}, //
+ {"SetCookie", LuaSetCookie}, //
+ {"SetHeader", LuaSetHeader}, //
+ {"SetLogLevel", LuaSetLogLevel}, //
+ {"SetStatus", LuaSetStatus}, //
+ {"Sha1", LuaSha1}, //
+ {"Sha224", LuaSha224}, //
+ {"Sha256", LuaSha256}, //
+ {"Sha384", LuaSha384}, //
+ {"Sha512", LuaSha512}, //
+ {"Sleep", LuaSleep}, //
+ {"Slurp", LuaSlurp}, //
+ {"StoreAsset", LuaStoreAsset}, //
+ {"Uncompress", LuaUncompress}, //
+ {"Underlong", LuaUnderlong}, //
+ {"VisualizeControlCodes", LuaVisualizeControlCodes}, //
+ {"Write", LuaWrite}, //
+ {"bin", LuaBin}, //
+ {"hex", LuaHex}, //
+ {"oct", LuaOct}, //
#ifndef UNSECURE
{"EvadeDragnetSurveillance", LuaEvadeDragnetSurveillance}, //
{"GetSslIdentity", LuaGetSslIdentity}, //
@@ -5173,11 +5184,11 @@ static const luaL_Reg kLuaFuncs[] = {
{"ProgramSslTicketLifetime", LuaProgramSslTicketLifetime}, //
#endif
// deprecated
- {"GetPayload", LuaGetBody}, //
- {"GetComment", LuaGetAssetComment}, //
- {"GetVersion", LuaGetHttpVersion}, //
- {"IsCompressed", LuaIsAssetCompressed}, //
- {"GetLastModifiedTime", LuaGetAssetLastModifiedTime}, //
+ {"GetPayload", LuaGetBody}, //
+ {"GetComment", LuaGetAssetComment}, //
+ {"GetVersion", LuaGetHttpVersion}, //
+ {"IsCompressed", LuaIsAssetCompressed}, //
+ {"GetLastModifiedTime", LuaGetAssetLastModifiedTime}, //
};
static const luaL_Reg kLuaLibs[] = {
@@ -5291,6 +5302,20 @@ static void LuaPrint(lua_State *L) {
}
}
+static void EnableRawMode(void) {
+ if (lua_repl_isterminal) {
+ --__strace;
+ linenoiseEnableRawMode(0);
+ ++__strace;
+ }
+}
+
+static void DisableRawMode(void) {
+ --__strace;
+ linenoiseDisableRawMode();
+ ++__strace;
+}
+
static void LuaInterpreter(lua_State *L) {
int i, n, sig, status;
const char *script;
@@ -5312,9 +5337,7 @@ static void LuaInterpreter(lua_State *L) {
lua_repl_blocking = true;
lua_repl_completions_callback = HandleCompletions;
lua_initrepl(GL, "redbean");
- if (lua_repl_isterminal) {
- linenoiseEnableRawMode(0);
- }
+ EnableRawMode();
for (;;) {
status = lua_loadline(L);
if (status == -1) break; // eof
@@ -5338,7 +5361,7 @@ static void LuaInterpreter(lua_State *L) {
lua_report(GL, status);
}
}
- linenoiseDisableRawMode();
+ DisableRawMode();
lua_freerepl();
lua_settop(GL, 0); // clear stack
if ((sig = linenoiseGetInterrupt())) {
@@ -5552,7 +5575,7 @@ static void HandleForkFailure(void) {
EnterMeltdownMode();
SendServiceUnavailable();
close(client);
- DIEF("(srvr) too many processes: %m");
+ WARNF("(srvr) too many processes: %m");
}
static void HandleFrag(size_t got) {
@@ -6364,7 +6387,7 @@ static int ExitWorker(void) {
}
if (monitortty) {
terminatemonitor = true;
- _wait0(monitortid);
+ _wait0((int *)(monitortls + 0x38));
}
_Exit(0);
}
@@ -6620,15 +6643,15 @@ static int MemoryMonitor(void *arg) {
}
static void MonitorMemory(void) {
- if ((monitortls = __initialize_tls(malloc(64)))) {
+ if ((monitortls = malloc(64))) {
if ((monitorstack = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
MAP_STACK | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) {
- monitortid = (int *)(monitortls + 0x38);
- if ((*monitortid =
- clone(MemoryMonitor, monitorstack, GetStackSize(),
- CLONE_VM | CLONE_THREAD | CLONE_FS | CLONE_FILES |
- CLONE_SIGHAND | CLONE_SETTLS | CLONE_CHILD_CLEARTID,
- 0, 0, monitortls, 64, monitortid)) != -1) {
+ if (clone(MemoryMonitor, monitorstack, GetStackSize(),
+ CLONE_VM | CLONE_THREAD | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_SETTLS | CLONE_CHILD_SETTID |
+ CLONE_CHILD_CLEARTID,
+ 0, 0, __initialize_tls(monitortls), 64,
+ (int *)(monitortls + 0x38)) != -1) {
return;
}
munmap(monitorstack, GetStackSize());
@@ -6810,7 +6833,7 @@ static int HandleReadline(void) {
return 0;
}
}
- linenoiseDisableRawMode();
+ DisableRawMode();
LUA_REPL_LOCK;
if (status == LUA_OK) {
status = lua_runchunk(L, 0, LUA_MULTRET);
@@ -6821,9 +6844,7 @@ static int HandleReadline(void) {
lua_report(L, status);
}
LUA_REPL_UNLOCK;
- if (lua_repl_isterminal) {
- linenoiseEnableRawMode(0);
- }
+ EnableRawMode();
}
}
@@ -6862,7 +6883,9 @@ static int HandlePoll(int ms) {
rc = HandleReadline();
if (rc < 0) return rc;
} else {
+ --__strace;
linenoiseRefreshLine(lua_repl_linenoise);
+ ++__strace;
}
#endif
}
@@ -6993,32 +7016,28 @@ static void ReplEventLoop(void) {
polls[0].fd = 0;
lua_repl_completions_callback = HandleCompletions;
lua_initrepl(L, "redbean");
- if (lua_repl_isterminal) {
- linenoiseEnableRawMode(0);
- }
+ EnableRawMode();
EventLoop(100);
- linenoiseDisableRawMode();
+ DisableRawMode();
lua_freerepl();
lua_settop(L, 0); // clear stack
polls[0].fd = -1;
}
-static uint32_t WindowsReplThread(void *arg) {
+static int WindowsReplThread(void *arg) {
int sig;
lua_State *L = GL;
DEBUGF("(repl) started windows thread");
lua_repl_blocking = true;
lua_repl_completions_callback = HandleCompletions;
lua_initrepl(L, "redbean");
- if (lua_repl_isterminal) {
- linenoiseEnableRawMode(0);
- }
- for (;;) {
+ EnableRawMode();
+ while (!terminated) {
if (HandleReadline() == -1) {
break;
}
}
- linenoiseDisableRawMode();
+ DisableRawMode();
lua_freerepl();
LUA_REPL_LOCK;
lua_settop(L, 0); // clear stack
@@ -7283,8 +7302,16 @@ void RedBean(int argc, char *argv[]) {
if (daemonize || uniprocess || !linenoiseIsTerminal()) {
EventLoop(HEARTBEAT);
} else if (IsWindows()) {
- uint32_t tid;
- CreateThread(0, 0, NT2SYSV(WindowsReplThread), 0, 0, &tid);
+ CHECK_NE(MAP_FAILED, (repltls = malloc(64)));
+ CHECK_NE(MAP_FAILED,
+ (replstack = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
+ MAP_STACK | MAP_ANONYMOUS, -1, 0)));
+ CHECK_NE(
+ -1,
+ clone(WindowsReplThread, replstack, GetStackSize(),
+ CLONE_VM | CLONE_THREAD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_SETTLS | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID,
+ 0, 0, __initialize_tls(repltls), 64, (int *)(repltls + 0x38)));
EventLoop(100);
} else {
ReplEventLoop();
@@ -7299,13 +7326,22 @@ void RedBean(int argc, char *argv[]) {
TlsDestroy();
MemDestroy();
}
- if (!IsTiny()) {
- if (monitortty) {
- terminatemonitor = true;
- _wait0(monitortid);
- munmap(monitorstack, GetStackSize());
- free(monitortls);
+ if (!isexitingworker) {
+ if (!IsTiny()) {
+ if (monitortty) {
+ terminatemonitor = true;
+ _wait0((int *)(monitortls + 0x38));
+ munmap(monitorstack, GetStackSize());
+ free(monitortls);
+ }
}
+#ifndef STATIC
+ if (repltls) {
+ _wait0((int *)(repltls + 0x38));
+ munmap(replstack, GetStackSize());
+ free(repltls);
+ }
+#endif
}
if (!isexitingworker) {
INFOF("(srvr) shutdown complete");