From fbc053e018833aa1ec153357ea05696486b6b041 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sat, 25 Jun 2022 18:17:31 -0700 Subject: [PATCH] Make fixes and improvements - Introduce __assert_disable global - Improve strsignal() thread safety - Make system call tracing thread safe - Fix SO_RCVTIMEO / SO_SNDTIMEO on Windows - Refactor DescribeFoo() functions into one place - Fix fork() on Windows when TLS and MAP_STACK exist - Round upwards in setsockopt(SO_RCVTIMEO) on Windows - Disable futexes on OpenBSD which seem extremely broken - Implement a better kludge for monotonic time on Windows --- Makefile | 1 - README.md | 6 +- build/definitions.mk | 2 +- libc/assert.h | 3 +- libc/calls/clock_gettime-nt.c | 42 +- libc/calls/clock_gettime.c | 6 +- libc/calls/directmap.c | 4 +- libc/calls/faccessat.c | 5 +- libc/calls/fchmodat.c | 5 +- libc/calls/fchownat.c | 5 +- libc/calls/fstatat.c | 9 +- libc/calls/getrlimit.c | 3 +- libc/calls/ioctl_tcsets-nt.c | 4 +- libc/calls/linkat.c | 6 +- libc/calls/mkdirat.c | 4 +- libc/calls/munmap-sysv.c | 1 + libc/calls/nanosleep.c | 6 +- libc/calls/now.c | 12 +- libc/calls/openat.c | 4 +- libc/calls/poll.c | 8 +- libc/calls/prctl.c | 14 +- libc/calls/readlinkat.c | 3 +- libc/calls/renameat.c | 5 +- libc/calls/samplepids.c | 5 + libc/calls/seccomp.c | 15 - libc/calls/setrlimit.c | 3 +- libc/calls/sigaction.c | 6 +- libc/calls/sigaltstack.c | 6 +- libc/calls/sigprocmask.c | 15 +- libc/calls/sigsuspend.c | 3 +- libc/calls/symlinkat.c | 5 +- libc/calls/unlinkat.c | 5 +- libc/calls/utimensat.c | 7 +- libc/fmt/magnumstrs.internal.h | 6 +- libc/intrin/asan.c | 11 +- libc/intrin/assertdisable.c | 23 + libc/intrin/assertfail.greg.c | 48 +- libc/intrin/createfile.c | 4 +- libc/intrin/createsymboliclink.c | 2 +- libc/{calls => intrin}/describeclockname.c | 24 +- .../{describedirfd.greg.c => describedirfd.c} | 2 +- .../{describeflags.greg.c => describeflags.c} | 1 + libc/intrin/describeflags.internal.h | 112 +++-- libc/intrin/describeframe.c | 6 +- libc/intrin/describehow.c | 29 ++ .../{describeiov.greg.c => describeiov.c} | 0 libc/intrin/describeiovnt.c | 42 ++ ...ribemapflags.greg.c => describemapflags.c} | 6 +- ...scribemapping.greg.c => describemapping.c} | 9 +- ...eg.c => describentconsolemodeinputflags.c} | 8 +- ...g.c => describentconsolemodeoutputflags.c} | 6 +- ...greg.c => describentcreationdisposition.c} | 0 ...ags.greg.c => describentfileaccessflags.c} | 7 +- ...ibutes.greg.c => describentfileflagattr.c} | 7 +- ...pflags.greg.c => describentfilemapflags.c} | 7 +- ...lags.greg.c => describentfileshareflags.c} | 6 +- ...flags.greg.c => describentfiletypeflags.c} | 7 +- ...ags.greg.c => describentmovfileinpflags.c} | 8 +- ...pageflags.greg.c => describentpageflags.c} | 6 +- ...flags.greg.c => describentpipemodeflags.c} | 7 +- ...flags.greg.c => describentpipeopenflags.c} | 7 +- ...ags.greg.c => describentprocaccessflags.c} | 8 +- ....greg.c => describentsecurityattributes.c} | 0 ...artflags.greg.c => describentstartflags.c} | 7 +- ...kflags.greg.c => describentsymlinkflags.c} | 8 +- ...beopenflags.greg.c => describeopenflags.c} | 20 +- libc/intrin/describepersonalityflags.c | 7 +- ...bepollflags.greg.c => describepollflags.c} | 4 +- libc/intrin/describeprctloperation.c | 33 ++ ...beprotflags.greg.c => describeprotflags.c} | 6 +- ...remapflags.greg.c => describeremapflags.c} | 7 +- ...describerlimit.greg.c => describerlimit.c} | 7 +- ...imit_name.greg.c => describerlimit_name.c} | 3 +- libc/intrin/describeseccompoperation.c | 35 ++ .../describesigaction.c} | 12 +- .../describesigaltstack.c} | 10 +- .../describesigset.c} | 7 +- libc/intrin/describesocketfamily.c | 29 ++ libc/intrin/describesocketprotocol.c | 32 ++ libc/intrin/describesockettype.c | 54 +++ .../describesocklevel.c} | 4 +- .../describesockoptname.c} | 44 +- .../{describestat.greg.c => describestat.c} | 7 +- ...ribetimespec.greg.c => describetimespec.c} | 8 +- ...viceiocontrol.greg.c => deviceiocontrol.c} | 0 libc/intrin/{dos2errno.greg.c => dos2errno.c} | 0 libc/intrin/exit1.greg.c | 1 + libc/intrin/findfirstfile.c | 17 +- libc/intrin/findnextfile.c | 17 +- libc/intrin/futex.S | 28 ++ libc/intrin/futex.internal.h | 5 +- libc/intrin/futex_wait.c | 32 +- libc/intrin/futex_wake.c | 26 +- libc/intrin/getfileattributes.c | 2 +- .../{getmagnumstr.greg.c => getmagnumstr.c} | 2 +- libc/intrin/gettid.greg.c | 65 +-- libc/intrin/intrin.mk | 28 +- libc/{calls => intrin}/kclocknames.S | 0 libc/{sock => intrin}/kipoptnames.S | 0 libc/intrin/kprintf.greg.c | 1 + libc/{str => intrin}/ksignalnames.S | 70 +-- libc/{sock => intrin}/ksockoptnames.S | 0 libc/{sock => intrin}/ktcpoptnames.S | 0 libc/intrin/movefileex.c | 2 +- libc/intrin/openprocess.c | 2 +- libc/intrin/pthread.h | 5 +- libc/intrin/pthread_mutex_destroy.c | 2 + libc/intrin/pthread_mutex_lock.c | 14 +- libc/intrin/pthread_mutex_unlock.c | 9 +- libc/intrin/pthread_mutex_wake.c | 1 + libc/intrin/reopenfile.c | 2 +- libc/{calls => intrin}/sigaddset.c | 0 libc/{calls => intrin}/sigdelset.c | 0 libc/{calls => intrin}/sigemptyset.c | 0 libc/{calls => intrin}/sigfillset.c | 0 libc/{calls => intrin}/sigismember.c | 0 .../strsignal.greg.c => intrin/strsignal.c} | 25 +- libc/intrin/sys_gettid.greg.c | 64 +++ libc/intrin/tls.greg.c | 2 +- libc/intrin/virtualprotect.c | 7 +- libc/intrin/wait0.c | 7 +- libc/intrin/wait0.internal.h | 2 +- libc/intrin/wsarecv.c | 68 +++ libc/intrin/wsarecvfrom.c | 71 +++ libc/intrin/wsawaitformultipleevents.c | 46 ++ libc/log/die.c | 3 +- libc/log/oncrash.c | 3 +- libc/nt/master.sh | 6 +- libc/nt/struct/fdset.h | 13 + libc/nt/struct/iovec.h | 13 + libc/nt/struct/timeval.h | 13 + libc/nt/winsock.h | 24 +- libc/nt/ws2_32/WSARecv.s | 4 +- libc/nt/ws2_32/WSARecvFrom.s | 4 +- libc/nt/ws2_32/WSAWaitForMultipleEvents.s | 4 +- libc/runtime/clone-openbsd.S | 45 ++ libc/runtime/clone.c | 68 +-- libc/runtime/fork-nt.c | 8 +- libc/runtime/ftracer.c | 2 +- libc/runtime/memtrack.internal.h | 2 - libc/runtime/mmap.c | 20 +- libc/runtime/{mprotect.greg.c => mprotect.c} | 0 libc/runtime/munmap.c | 2 +- .../runtime/{printargs.greg.c => printargs.c} | 25 +- libc/runtime/printmemoryintervals.c | 7 +- libc/runtime/threadmode.c | 3 +- libc/runtime/winmain.greg.c | 10 +- libc/sock/accept4.c | 5 +- libc/sock/bind.c | 10 +- libc/sock/connect-nt.c | 5 +- libc/sock/connect.c | 5 +- libc/sock/getpeername.c | 4 +- libc/sock/getsockname.c | 4 +- libc/sock/getsockopt-nt.c | 29 +- libc/sock/getsockopt.c | 2 +- libc/sock/internal.h | 7 +- libc/sock/recv-nt.c | 11 +- libc/sock/recvfrom-nt.c | 8 +- libc/sock/send-nt.c | 5 +- libc/sock/sendfile.c | 3 +- libc/sock/sendto-nt.c | 5 +- libc/sock/setsockopt-nt.c | 14 +- libc/sock/setsockopt.c | 2 +- libc/sock/sock.h | 55 +-- libc/sock/sock.mk | 2 +- libc/sock/sockdebug.c | 55 +-- libc/sock/sockdebug.h | 14 - libc/sock/socket.c | 7 +- libc/sock/struct/linger.h | 13 + libc/sock/struct/msghdr.h | 19 + libc/sock/struct/pollfd.h | 14 + libc/sock/struct/sockaddr.h | 38 ++ libc/sock/winsockblock.c | 3 +- libc/sock/wsablock.c | 18 +- libc/testlib/benchrunner.c | 1 - libc/thread/openbsd.internal.h | 16 + test/libc/intrin/pthread_mutex_lock_test.c | 165 ++++--- test/libc/{str => intrin}/strsignal_test.c | 2 +- test/libc/runtime/clone_test.c | 3 +- test/libc/sock/setsockopt_test.c | 39 ++ third_party/linenoise/linenoise.c | 2 + third_party/lua/lunix.c | 2 +- third_party/make/make.mk | 1 - third_party/make/signame.c | 255 ---------- third_party/stb/stb_truetype.c | 1 + tool/net/redbean.c | 434 ++++++++++-------- 186 files changed, 1836 insertions(+), 1325 deletions(-) create mode 100644 libc/intrin/assertdisable.c rename libc/{calls => intrin}/describeclockname.c (84%) rename libc/intrin/{describedirfd.greg.c => describedirfd.c} (96%) rename libc/intrin/{describeflags.greg.c => describeflags.c} (97%) create mode 100644 libc/intrin/describehow.c rename libc/intrin/{describeiov.greg.c => describeiov.c} (100%) create mode 100644 libc/intrin/describeiovnt.c rename libc/intrin/{describemapflags.greg.c => describemapflags.c} (93%) rename libc/intrin/{describemapping.greg.c => describemapping.c} (92%) rename libc/intrin/{describentconsolemodeinputflags.greg.c => describentconsolemodeinputflags.c} (89%) rename libc/intrin/{describentconsolemodeoutputflags.greg.c => describentconsolemodeoutputflags.c} (91%) rename libc/intrin/{describentcreationdisposition.greg.c => describentcreationdisposition.c} (100%) rename libc/intrin/{describentfileaccessflags.greg.c => describentfileaccessflags.c} (94%) rename libc/intrin/{describentfileflagsandattributes.greg.c => describentfileflagattr.c} (94%) rename libc/intrin/{describentfilemapflags.greg.c => describentfilemapflags.c} (91%) rename libc/intrin/{describentfileshareflags.greg.c => describentfileshareflags.c} (90%) rename libc/intrin/{describentfiletypeflags.greg.c => describentfiletypeflags.c} (90%) rename libc/intrin/{describentmovefileflags.greg.c => describentmovfileinpflags.c} (89%) rename libc/intrin/{describentpageflags.greg.c => describentpageflags.c} (93%) rename libc/intrin/{describentpipemodeflags.greg.c => describentpipemodeflags.c} (91%) rename libc/intrin/{describentpipeopenflags.greg.c => describentpipeopenflags.c} (90%) rename libc/intrin/{describentprocessaccessflags.greg.c => describentprocaccessflags.c} (90%) rename libc/intrin/{describentsecurityattributes.greg.c => describentsecurityattributes.c} (100%) rename libc/intrin/{describentstartflags.greg.c => describentstartflags.c} (92%) rename libc/intrin/{describentsymboliclinkflags.greg.c => describentsymlinkflags.c} (87%) rename libc/intrin/{describeopenflags.greg.c => describeopenflags.c} (85%) rename libc/intrin/{describepollflags.greg.c => describepollflags.c} (94%) create mode 100644 libc/intrin/describeprctloperation.c rename libc/intrin/{describeprotflags.greg.c => describeprotflags.c} (91%) rename libc/intrin/{describeremapflags.greg.c => describeremapflags.c} (90%) rename libc/intrin/{describerlimit.greg.c => describerlimit.c} (90%) rename libc/intrin/{describerlimit_name.greg.c => describerlimit_name.c} (97%) create mode 100644 libc/intrin/describeseccompoperation.c rename libc/{calls/describesigaction.greg.c => intrin/describesigaction.c} (84%) rename libc/{calls/describesigaltstack.greg.c => intrin/describesigaltstack.c} (88%) rename libc/{calls/describesigset.greg.c => intrin/describesigset.c} (94%) create mode 100644 libc/intrin/describesocketfamily.c create mode 100644 libc/intrin/describesocketprotocol.c create mode 100644 libc/intrin/describesockettype.c rename libc/{sock/describesocklevel.greg.c => intrin/describesocklevel.c} (95%) rename libc/{sock/describesockoptname.greg.c => intrin/describesockoptname.c} (78%) rename libc/intrin/{describestat.greg.c => describestat.c} (95%) rename libc/intrin/{describetimespec.greg.c => describetimespec.c} (90%) rename libc/intrin/{deviceiocontrol.greg.c => deviceiocontrol.c} (100%) rename libc/intrin/{dos2errno.greg.c => dos2errno.c} (100%) create mode 100644 libc/intrin/futex.S rename libc/intrin/{getmagnumstr.greg.c => getmagnumstr.c} (96%) rename libc/{calls => intrin}/kclocknames.S (100%) rename libc/{sock => intrin}/kipoptnames.S (100%) rename libc/{str => intrin}/ksignalnames.S (73%) rename libc/{sock => intrin}/ksockoptnames.S (100%) rename libc/{sock => intrin}/ktcpoptnames.S (100%) rename libc/{calls => intrin}/sigaddset.c (100%) rename libc/{calls => intrin}/sigdelset.c (100%) rename libc/{calls => intrin}/sigemptyset.c (100%) rename libc/{calls => intrin}/sigfillset.c (100%) rename libc/{calls => intrin}/sigismember.c (100%) rename libc/{str/strsignal.greg.c => intrin/strsignal.c} (88%) create mode 100644 libc/intrin/sys_gettid.greg.c create mode 100644 libc/intrin/wsarecv.c create mode 100644 libc/intrin/wsarecvfrom.c create mode 100644 libc/intrin/wsawaitformultipleevents.c create mode 100644 libc/nt/struct/fdset.h create mode 100644 libc/nt/struct/iovec.h create mode 100644 libc/nt/struct/timeval.h create mode 100644 libc/runtime/clone-openbsd.S rename libc/runtime/{mprotect.greg.c => mprotect.c} (100%) rename libc/runtime/{printargs.greg.c => printargs.c} (97%) delete mode 100644 libc/sock/sockdebug.h create mode 100644 libc/sock/struct/linger.h create mode 100644 libc/sock/struct/msghdr.h create mode 100644 libc/sock/struct/pollfd.h create mode 100644 libc/sock/struct/sockaddr.h create mode 100644 libc/thread/openbsd.internal.h rename test/libc/{str => intrin}/strsignal_test.c (98%) create mode 100644 test/libc/sock/setsockopt_test.c delete mode 100644 third_party/make/signame.c 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");