diff --git a/examples/portscan.c b/examples/portscan.c new file mode 100644 index 000000000..fc2ad8adc --- /dev/null +++ b/examples/portscan.c @@ -0,0 +1,127 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/assert.h" +#include "libc/calls/calls.h" +#include "libc/calls/struct/timeval.h" +#include "libc/errno.h" +#include "libc/fmt/conv.h" +#include "libc/fmt/fmt.h" +#include "libc/mem/alloca.h" +#include "libc/runtime/runtime.h" +#include "libc/sock/sock.h" +#include "libc/sock/struct/sockaddr.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.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 "net/http/ip.h" + +/** + * @fileoverview fast local network port scanner, e.g. + * + * make -j8 o//examples/portscan.com + * o//examples/portscan.com 10.10.10.0/24 22 + */ + +const char *FormatIp(char buf[16], uint32_t ip) { + snprintf(buf, 16, "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16, ip >> 8, ip); + return buf; +} + +#define FormatIp(x) FormatIp(alloca(16), x) + +int main(int argc, char *argv[]) { + int port; + struct Cidr in; + uint32_t netmask; + const char *status; + struct timeval timeout; + uint32_t network_address; + uint32_t last_host_address; + uint32_t first_host_address; + + if (argc != 3) { + PrintUsage: + fprintf(stderr, + "usage: %s IP/CIDR PORT\n" + "example: %s 192.168.0.0/24 22\n", + argv[0], argv[0]); + return 1; + } + + in = ParseCidr(argv[1], -1); + if (in.addr == -1) { + fprintf(stderr, "error: bad ip/cidr\n"); + goto PrintUsage; + } + + port = atoi(argv[2]); + if (!(1 <= port && port <= 65535)) { + fprintf(stderr, "error: bad port\n"); + goto PrintUsage; + } + + if (in.cidr > 30) { + fprintf(stderr, "error: maximum supported cidr is 30\n"); + goto PrintUsage; + } + + if (in.cidr < 22) { + fprintf(stderr, "error: minimum cidr support right now is 22\n"); + goto PrintUsage; + } + + netmask = -1u << (32 - in.cidr); + network_address = in.addr & netmask; + first_host_address = network_address + 1; + last_host_address = (network_address | ~netmask) - 1; + + assert(last_host_address > first_host_address); + assert(last_host_address - first_host_address < 1024); + + fprintf(stderr, "scanning %s through %s\n", FormatIp(first_host_address), + FormatIp(last_host_address)); + + timeout = timeval_frommillis(100); + for (int64_t ip = first_host_address; ip <= last_host_address; ++ip) { + if (!fork()) { + socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + if (!connect(3, + (struct sockaddr *)&(struct sockaddr_in){ + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(ip), + .sin_port = htons(port), + }, + sizeof(struct sockaddr_in))) { + status = "open"; + } else if (errno == ECONNREFUSED) { + status = "closed"; + } else if (errno != EINPROGRESS) { + status = _strerrno(errno); + } else { + status = 0; + } + if (status) { + printf("%-15s %s\n", FormatIp(ip), status); + } + _Exit(0); + } + } + for (;;) { + if (wait(0) == -1 && errno == ECHILD) { + break; + } + } +} diff --git a/libc/calls/calls.mk b/libc/calls/calls.mk index 5d638cde8..eae3c1fac 100644 --- a/libc/calls/calls.mk +++ b/libc/calls/calls.mk @@ -184,7 +184,10 @@ o/$(MODE)/libc/calls/timespec_tomicros.o \ o/$(MODE)/libc/calls/timespec_totimeval.o \ o/$(MODE)/libc/calls/timespec_fromnanos.o \ o/$(MODE)/libc/calls/timespec_frommillis.o \ -o/$(MODE)/libc/calls/timespec_frommicros.o: private \ +o/$(MODE)/libc/calls/timespec_frommicros.o \ +o/$(MODE)/libc/calls/timeval_tomillis.o \ +o/$(MODE)/libc/calls/timeval_frommillis.o \ +o/$(MODE)/libc/calls/timeval_frommicros.o: private \ OVERRIDE_CFLAGS += \ -O2 diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index 74a8cb46c..b45b98420 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -22,11 +22,6 @@ #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" #include "libc/calls/state.internal.h" -#include "libc/calls/struct/sigaction-freebsd.internal.h" -#include "libc/calls/struct/sigaction-linux.internal.h" -#include "libc/calls/struct/sigaction-netbsd.h" -#include "libc/calls/struct/sigaction-openbsd.internal.h" -#include "libc/calls/struct/sigaction-xnu.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.internal.h" #include "libc/calls/struct/siginfo.internal.h" @@ -46,6 +41,7 @@ #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" +#include "libc/sysv/consts/limits.h" #include "libc/sysv/consts/sa.h" #include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" @@ -58,110 +54,111 @@ STATIC_YOINK("strsignal"); // for kprintf() #define SA_RESTORER 0x04000000 -#ifndef SWITCHEROO -#define SWITCHEROO(S1, S2, A, B, C, D) \ - do { \ - autotype((S2).A) a = (typeof((S2).A))(S1).A; \ - autotype((S2).B) b = (typeof((S2).B))(S1).B; \ - autotype((S2).C) c = (typeof((S2).C))(S1).C; \ - typeof((S2).D) d; \ - bzero(&d, sizeof(d)); \ - memcpy(&d, &((S1).D), MIN(sizeof(d), sizeof((S1).D))); \ - (S2).A = a; \ - (S2).B = b; \ - (S2).C = c; \ - bzero(&((S2).D), sizeof((S2).D)); \ - memcpy(&((S2).D), &d, MIN(sizeof(d), sizeof((S2).D))); \ - } while (0); -#endif - -union metasigaction { - struct sigaction cosmo; - struct sigaction_linux linux; - struct sigaction_freebsd freebsd; - struct sigaction_openbsd openbsd; - struct sigaction_netbsd netbsd; - struct sigaction_xnu_in xnu_in; - struct sigaction_xnu_out xnu_out; -}; - -void __sigenter_xnu(int, struct siginfo *, void *) hidden; -void __sigenter_linux(int, struct siginfo *, void *) hidden; -void __sigenter_netbsd(int, struct siginfo *, void *) hidden; -void __sigenter_freebsd(int, struct siginfo *, void *) hidden; -void __sigenter_openbsd(int, struct siginfo *, void *) hidden; - static void sigaction_cosmo2native(union metasigaction *sa) { + void *handler; + uint64_t flags; + void *restorer; + uint32_t mask[4]; if (!sa) return; - switch (__hostos) { - case _HOSTLINUX: - SWITCHEROO(sa->cosmo, sa->linux, sa_handler, sa_flags, sa_restorer, - sa_mask); - break; - case _HOSTXNU: - SWITCHEROO(sa->cosmo, sa->xnu_in, sa_handler, sa_flags, sa_restorer, - sa_mask); - break; - case _HOSTFREEBSD: - SWITCHEROO(sa->cosmo, sa->freebsd, sa_handler, sa_flags, sa_flags, - sa_mask); - break; - case _HOSTOPENBSD: - SWITCHEROO(sa->cosmo, sa->openbsd, sa_handler, sa_flags, sa_flags, - sa_mask); - break; - case _HOSTNETBSD: - SWITCHEROO(sa->cosmo, sa->netbsd, sa_handler, sa_flags, sa_flags, - sa_mask); - break; - default: - break; + flags = sa->cosmo.sa_flags; + handler = sa->cosmo.sa_handler; + restorer = sa->cosmo.sa_restorer; + mask[0] = sa->cosmo.sa_mask.__bits[0]; + mask[1] = sa->cosmo.sa_mask.__bits[0] >> 32; + mask[2] = sa->cosmo.sa_mask.__bits[1]; + mask[3] = sa->cosmo.sa_mask.__bits[1] >> 32; + if (IsLinux()) { + sa->linux.sa_flags = flags; + sa->linux.sa_handler = handler; + sa->linux.sa_restorer = restorer; + sa->linux.sa_mask[0] = mask[0]; + sa->linux.sa_mask[1] = mask[1]; + } else if (IsXnu()) { + sa->xnu_in.sa_flags = flags; + sa->xnu_in.sa_handler = handler; + sa->xnu_in.sa_restorer = restorer; + sa->xnu_in.sa_mask[0] = mask[0]; + } else if (IsFreebsd()) { + sa->freebsd.sa_flags = flags; + sa->freebsd.sa_handler = handler; + sa->freebsd.sa_mask[0] = mask[0]; + sa->freebsd.sa_mask[1] = mask[1]; + sa->freebsd.sa_mask[2] = mask[2]; + sa->freebsd.sa_mask[3] = mask[3]; + } else if (IsOpenbsd()) { + sa->openbsd.sa_flags = flags; + sa->openbsd.sa_handler = handler; + sa->openbsd.sa_mask[0] = mask[0]; + } else if (IsNetbsd()) { + sa->netbsd.sa_flags = flags; + sa->netbsd.sa_handler = handler; + sa->netbsd.sa_mask[0] = mask[0]; + sa->netbsd.sa_mask[1] = mask[1]; + sa->netbsd.sa_mask[2] = mask[2]; + sa->netbsd.sa_mask[3] = mask[3]; } } static void sigaction_native2cosmo(union metasigaction *sa) { + void *handler; + uint64_t flags; + void *restorer = 0; + uint32_t mask[4] = {0}; if (!sa) return; - switch (__hostos) { - case _HOSTLINUX: - SWITCHEROO(sa->linux, sa->cosmo, sa_handler, sa_flags, sa_restorer, - sa_mask); - break; - case _HOSTXNU: - SWITCHEROO(sa->xnu_out, sa->cosmo, sa_handler, sa_flags, sa_flags, - sa_mask); - break; - case _HOSTFREEBSD: - SWITCHEROO(sa->freebsd, sa->cosmo, sa_handler, sa_flags, sa_flags, - sa_mask); - break; - case _HOSTOPENBSD: - SWITCHEROO(sa->openbsd, sa->cosmo, sa_handler, sa_flags, sa_flags, - sa_mask); - break; - case _HOSTNETBSD: - SWITCHEROO(sa->netbsd, sa->cosmo, sa_handler, sa_flags, sa_flags, - sa_mask); - break; - default: - break; + if (IsLinux()) { + flags = sa->linux.sa_flags; + handler = sa->linux.sa_handler; + restorer = sa->linux.sa_restorer; + mask[0] = sa->linux.sa_mask[0]; + mask[1] = sa->linux.sa_mask[1]; + } else if (IsXnu()) { + flags = sa->xnu_out.sa_flags; + handler = sa->xnu_out.sa_handler; + mask[0] = sa->xnu_out.sa_mask[0]; + } else if (IsFreebsd()) { + flags = sa->freebsd.sa_flags; + handler = sa->freebsd.sa_handler; + mask[0] = sa->freebsd.sa_mask[0]; + mask[1] = sa->freebsd.sa_mask[1]; + mask[2] = sa->freebsd.sa_mask[2]; + mask[3] = sa->freebsd.sa_mask[3]; + } else if (IsOpenbsd()) { + flags = sa->openbsd.sa_flags; + handler = sa->openbsd.sa_handler; + mask[0] = sa->openbsd.sa_mask[0]; + } else if (IsNetbsd()) { + flags = sa->netbsd.sa_flags; + handler = sa->netbsd.sa_handler; + mask[0] = sa->netbsd.sa_mask[0]; + mask[1] = sa->netbsd.sa_mask[1]; + mask[2] = sa->netbsd.sa_mask[2]; + mask[3] = sa->netbsd.sa_mask[3]; + } else { + return; } + sa->cosmo.sa_flags = flags; + sa->cosmo.sa_handler = handler; + sa->cosmo.sa_restorer = restorer; + sa->cosmo.sa_mask.__bits[0] = mask[0] | (uint64_t)mask[1] << 32; + sa->cosmo.sa_mask.__bits[1] = mask[2] | (uint64_t)mask[3] << 32; } static int __sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) { - _Static_assert((sizeof(struct sigaction) > sizeof(struct sigaction_linux) && - sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) && - sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) && - sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) && - sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) && - sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)), - "sigaction cosmo abi needs tuning"); + _Static_assert( + (sizeof(struct sigaction) >= sizeof(struct sigaction_linux) && + sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_in) && + sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_out) && + sizeof(struct sigaction) >= sizeof(struct sigaction_freebsd) && + sizeof(struct sigaction) >= sizeof(struct sigaction_openbsd) && + sizeof(struct sigaction) >= sizeof(struct sigaction_netbsd)), + "sigaction cosmo abi needs tuning"); int64_t arg4, arg5; int rc, rva, oldrva; sigaction_f sigenter; struct sigaction *ap, copy; if (IsMetal()) return enosys(); /* TODO: Signals on Metal */ - if (!(0 < sig && sig < NSIG)) return einval(); + if (!(1 <= sig && sig <= _NSIG)) return einval(); if (sig == SIGKILL || sig == SIGSTOP) return einval(); if (IsAsan() && ((act && !__asan_is_valid(act, sizeof(*act))) || (oldact && !__asan_is_valid(oldact, sizeof(*oldact))))) { @@ -184,18 +181,23 @@ static int __sigaction(int sig, const struct sigaction *act, if (act) { memcpy(©, act, sizeof(copy)); ap = © - if (IsXnu()) { + + if (IsLinux()) { + if (!(ap->sa_flags & SA_RESTORER)) { + ap->sa_flags |= SA_RESTORER; + ap->sa_restorer = &__restore_rt; + } + if (IsWsl1()) { + sigenter = __sigenter_wsl; + } else { + sigenter = ap->sa_sigaction; + } + } else if (IsXnu()) { ap->sa_restorer = (void *)&__sigenter_xnu; sigenter = __sigenter_xnu; // mitigate Rosetta signal handling strangeness // https://github.com/jart/cosmopolitan/issues/455 ap->sa_flags |= SA_SIGINFO; - } else if (IsLinux()) { - if (!(ap->sa_flags & SA_RESTORER)) { - ap->sa_flags |= SA_RESTORER; - ap->sa_restorer = &__restore_rt; - } - sigenter = __sigenter_linux; } else if (IsNetbsd()) { sigenter = __sigenter_netbsd; } else if (IsFreebsd()) { diff --git a/libc/calls/sigenter-freebsd.c b/libc/calls/sigenter-freebsd.c index c4d3c4d14..f5d989096 100644 --- a/libc/calls/sigenter-freebsd.c +++ b/libc/calls/sigenter-freebsd.c @@ -20,7 +20,6 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" -#include "libc/calls/struct/sigaction-freebsd.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/siginfo-freebsd.internal.h" #include "libc/calls/struct/siginfo-meta.internal.h" @@ -51,7 +50,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo, g.uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp; g.uc.uc_stack.ss_size = ctx->uc_stack.ss_size; g.uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags; - __repmovsb(&g.uc.uc_sigmask, &ctx->uc_sigmask, + __repmovsb(&g.uc.uc_sigmask, ctx->uc_sigmask, MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask))); g.uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8; g.uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9; @@ -82,7 +81,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo, ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size; ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags; ctx->uc_flags = g.uc.uc_flags; - __repmovsb(&ctx->uc_sigmask, &g.uc.uc_sigmask, + __repmovsb(ctx->uc_sigmask, &g.uc.uc_sigmask, MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask))); ctx->uc_mcontext.mc_rdi = g.uc.uc_mcontext.rdi; ctx->uc_mcontext.mc_rsi = g.uc.uc_mcontext.rsi; diff --git a/libc/calls/sigenter-linux.c b/libc/calls/sigenter-linux.c index f0e5152bb..fcdc9d2b8 100644 --- a/libc/calls/sigenter-linux.c +++ b/libc/calls/sigenter-linux.c @@ -28,8 +28,7 @@ #include "libc/str/str.h" #include "libc/sysv/consts/sa.h" -privileged void __sigenter_linux(int sig, struct siginfo *info, - ucontext_t *ctx) { +privileged void __sigenter_wsl(int sig, struct siginfo *info, ucontext_t *ctx) { int i, rva, flags; rva = __sighandrvas[sig & (NSIG - 1)]; if (rva >= kSigactionMinRva) { diff --git a/libc/calls/sigenter-netbsd.c b/libc/calls/sigenter-netbsd.c index 14ecaa7fc..74b0c4801 100644 --- a/libc/calls/sigenter-netbsd.c +++ b/libc/calls/sigenter-netbsd.c @@ -20,7 +20,6 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" -#include "libc/calls/struct/sigaction-freebsd.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/siginfo-meta.internal.h" #include "libc/calls/struct/siginfo-netbsd.internal.h" diff --git a/libc/calls/sigenter-openbsd.c b/libc/calls/sigenter-openbsd.c index b99b3abfb..4563a0b4d 100644 --- a/libc/calls/sigenter-openbsd.c +++ b/libc/calls/sigenter-openbsd.c @@ -20,7 +20,6 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" -#include "libc/calls/struct/sigaction-freebsd.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/siginfo-meta.internal.h" #include "libc/calls/struct/siginfo-openbsd.internal.h" diff --git a/libc/calls/struct/sigaction-freebsd.internal.h b/libc/calls/struct/sigaction-freebsd.internal.h deleted file mode 100644 index ee111086a..000000000 --- a/libc/calls/struct/sigaction-freebsd.internal.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_FREEBSD_H_ -#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_FREEBSD_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) - -struct sigset_freebsd { - uint32_t sig[4]; -}; - -struct sigaction_freebsd { - intptr_t sa_handler; - uint32_t sa_flags; - struct sigset_freebsd sa_mask; -}; - -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_FREEBSD_H_ */ diff --git a/libc/calls/struct/sigaction-linux.internal.h b/libc/calls/struct/sigaction-linux.internal.h deleted file mode 100644 index b5f09de6a..000000000 --- a/libc/calls/struct/sigaction-linux.internal.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_LINUX_H_ -#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_LINUX_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) - -struct sigset_linux { - uint32_t sig[2]; -}; - -struct sigaction_linux { - intptr_t sa_handler; - uint64_t sa_flags; - void (*sa_restorer)(void); - struct sigset_linux sa_mask; -}; - -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_LINUX_H_ */ diff --git a/libc/calls/struct/sigaction-netbsd.h b/libc/calls/struct/sigaction-netbsd.h deleted file mode 100644 index 0264f2515..000000000 --- a/libc/calls/struct/sigaction-netbsd.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_NETBSD_H_ -#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_NETBSD_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct sigset_netbsd { - uint32_t sig[4]; -}; - -struct sigaction_netbsd { - intptr_t sa_handler; - struct sigset_netbsd sa_mask; - uint32_t sa_flags; -}; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_NETBSD_H_ */ diff --git a/libc/calls/struct/sigaction-openbsd.internal.h b/libc/calls/struct/sigaction-openbsd.internal.h deleted file mode 100644 index 226883f5a..000000000 --- a/libc/calls/struct/sigaction-openbsd.internal.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_OPENBSD_H_ -#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_OPENBSD_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) - -struct sigset_openbsd { - uint32_t sig[1]; -}; - -struct sigaction_openbsd { - intptr_t sa_handler; - struct sigset_openbsd sa_mask; - int32_t sa_flags; -}; - -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_OPENBSD_H_ */ diff --git a/libc/calls/struct/sigaction-xnu.internal.h b/libc/calls/struct/sigaction-xnu.internal.h deleted file mode 100644 index 24ab6ffc7..000000000 --- a/libc/calls/struct/sigaction-xnu.internal.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_XNU_H_ -#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_XNU_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) - -struct __darwin_ucontext; -struct __darwin_siginfo; - -struct sigset_xnu { - uint32_t sig[1]; -}; - -struct sigaction_xnu_in { - intptr_t sa_handler; - void (*sa_restorer)(void *, int, int, const struct __darwin_siginfo *, - const struct __darwin_ucontext *); - struct sigset_xnu sa_mask; - int32_t sa_flags; -}; - -struct sigaction_xnu_out { - intptr_t sa_handler; - struct sigset_xnu sa_mask; - int32_t sa_flags; -}; - -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_XNU_H_ */ diff --git a/libc/calls/struct/sigaction.h b/libc/calls/struct/sigaction.h index 4c10d64f6..51e93380d 100644 --- a/libc/calls/struct/sigaction.h +++ b/libc/calls/struct/sigaction.h @@ -20,7 +20,6 @@ struct sigaction { /* cosmo abi */ uint64_t sa_flags; void (*sa_restorer)(void); struct sigset sa_mask; - int64_t __pad; }; sighandler_t signal(int, sighandler_t); diff --git a/libc/calls/struct/sigaction.internal.h b/libc/calls/struct/sigaction.internal.h index 0443291ec..e033a4f3f 100644 --- a/libc/calls/struct/sigaction.internal.h +++ b/libc/calls/struct/sigaction.internal.h @@ -1,10 +1,65 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_INTERNAL_H_ #include "libc/calls/struct/sigaction.h" +#include "libc/calls/struct/siginfo.h" #include "libc/mem/alloca.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ +struct sigaction_linux { + void *sa_handler; + uint64_t sa_flags; + void *sa_restorer; + uint32_t sa_mask[2]; +}; + +struct sigaction_freebsd { + void *sa_handler; + uint32_t sa_flags; + uint32_t sa_mask[4]; +}; + +struct sigaction_openbsd { + void *sa_handler; + uint32_t sa_mask[1]; + uint32_t sa_flags; +}; + +struct sigaction_netbsd { + void *sa_handler; + uint32_t sa_mask[4]; + uint32_t sa_flags; +}; + +struct sigaction_xnu_in { + void *sa_handler; + void *sa_restorer; + uint32_t sa_mask[1]; + uint32_t sa_flags; +}; + +struct sigaction_xnu_out { + void *sa_handler; + uint32_t sa_mask[1]; + uint32_t sa_flags; +}; + +union metasigaction { + struct sigaction cosmo; + struct sigaction_linux linux; + struct sigaction_freebsd freebsd; + struct sigaction_openbsd openbsd; + struct sigaction_netbsd netbsd; + struct sigaction_xnu_in xnu_in; + struct sigaction_xnu_out xnu_out; +}; + +void __sigenter_xnu(int, struct siginfo *, void *) hidden; +void __sigenter_wsl(int, struct siginfo *, void *) hidden; +void __sigenter_netbsd(int, struct siginfo *, void *) hidden; +void __sigenter_freebsd(int, struct siginfo *, void *) hidden; +void __sigenter_openbsd(int, struct siginfo *, void *) hidden; + const char *DescribeSigaction(char[256], int, const struct sigaction *); #define DescribeSigaction(rc, sa) DescribeSigaction(alloca(256), rc, sa) diff --git a/libc/calls/struct/siginfo.internal.h b/libc/calls/struct/siginfo.internal.h index b9fe0e71e..83d1509ee 100644 --- a/libc/calls/struct/siginfo.internal.h +++ b/libc/calls/struct/siginfo.internal.h @@ -1,7 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_INTERNAL_H_ -#include "libc/calls/struct/sigaction-xnu.internal.h" -#include "libc/calls/struct/siginfo-xnu.internal.h" #include "libc/calls/struct/siginfo.h" #include "libc/mem/alloca.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) diff --git a/libc/calls/struct/timespec.internal.h b/libc/calls/struct/timespec.internal.h index 61f260d9c..768549b7b 100644 --- a/libc/calls/struct/timespec.internal.h +++ b/libc/calls/struct/timespec.internal.h @@ -14,12 +14,13 @@ int sys_clock_gettime_nt(int, struct timespec *) hidden; int sys_clock_gettime_xnu(int, struct timespec *) hidden; int sys_clock_nanosleep(int, int, const struct timespec *, struct timespec *) hidden; int sys_clock_nanosleep_nt(int, int, const struct timespec *, struct timespec *) hidden; -int sys_clock_nanosleep_xnu(int, int, const struct timespec *, struct timespec *) hidden; int sys_clock_nanosleep_openbsd(int, int, const struct timespec *, struct timespec *) hidden; +int sys_clock_nanosleep_xnu(int, int, const struct timespec *, struct timespec *) hidden; int sys_futimens(int, const struct timespec[2]) hidden; int sys_nanosleep(const struct timespec *, struct timespec *) hidden; int sys_nanosleep_nt(const struct timespec *, struct timespec *) hidden; int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden; +int sys_sem_timedwait(int64_t, const struct timespec *) hidden; int sys_utimensat(int, const char *, const struct timespec[2], int) hidden; int sys_utimensat_nt(int, const char *, const struct timespec[2], int) hidden; int sys_utimensat_xnu(int, const char *, const struct timespec[2], int) hidden; diff --git a/libc/calls/struct/timeval.h b/libc/calls/struct/timeval.h index 384093411..01e6f4638 100644 --- a/libc/calls/struct/timeval.h +++ b/libc/calls/struct/timeval.h @@ -17,6 +17,8 @@ int lutimes(const char *, const struct timeval[2]); int utimes(const char *, const struct timeval[2]); int timeval_cmp(struct timeval, struct timeval) pureconst; +struct timeval timeval_frommicros(int64_t) pureconst; +struct timeval timeval_frommillis(int64_t) pureconst; struct timeval timeval_add(struct timeval, struct timeval) pureconst; struct timeval timeval_sub(struct timeval, struct timeval) pureconst; struct timeval timespec_totimeval(struct timespec) pureconst; diff --git a/libc/calls/struct/ucontext-freebsd.internal.h b/libc/calls/struct/ucontext-freebsd.internal.h index f48bbafa2..f0b6f07e6 100644 --- a/libc/calls/struct/ucontext-freebsd.internal.h +++ b/libc/calls/struct/ucontext-freebsd.internal.h @@ -1,6 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_FREEBSD_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_FREEBSD_INTERNAL_H_ -#include "libc/calls/struct/sigaction-freebsd.internal.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -52,7 +51,7 @@ struct mcontext_freebsd { }; struct ucontext_freebsd { - struct sigset_freebsd uc_sigmask; + uint32_t uc_sigmask[4]; struct mcontext_freebsd uc_mcontext; struct ucontext_freebsd *uc_link; struct stack_freebsd uc_stack; diff --git a/libc/calls/syscall-sysv.internal.h b/libc/calls/syscall-sysv.internal.h index b8b37ac45..7c86332f7 100644 --- a/libc/calls/syscall-sysv.internal.h +++ b/libc/calls/syscall-sysv.internal.h @@ -83,6 +83,15 @@ i32 sys_pivot_root(const char *, const char *) hidden; i32 sys_pledge(const char *, const char *) hidden; i32 sys_posix_openpt(i32) hidden; i32 sys_renameat(i32, const char *, i32, const char *) hidden; +i32 sys_sem_close(i64) hidden; +i32 sys_sem_destroy(i64) hidden; +i32 sys_sem_getvalue(i64, u32 *) hidden; +i32 sys_sem_init(u32, i64 *) hidden; +i32 sys_sem_open(const char *, int, u32, i64 *) hidden; +i32 sys_sem_post(i64) hidden; +i32 sys_sem_trywait(i64) hidden; +i32 sys_sem_unlink(const char *) hidden; +i32 sys_sem_wait(i64) hidden; i32 sys_setfsgid(i32) hidden; i32 sys_setfsuid(i32) hidden; i32 sys_setgid(i32) hidden; diff --git a/libc/calls/timespec_tonanos.c b/libc/calls/timespec_tonanos.c index 2e7ed66b9..b2192f166 100644 --- a/libc/calls/timespec_tonanos.c +++ b/libc/calls/timespec_tonanos.c @@ -22,8 +22,9 @@ /** * Converts timespec to scalar. * - * This function will detect overflow in which case `INT64_MAX` or - * `INT64_MIN` may be returned. The `errno` variable isn't changed. +. * This returns the absolute number of nanoseconds in a timespec. If + * overflow happens, then `INT64_MAX` or `INT64_MIN` is returned. The + * `errno` variable isn't changed. * * @return 64-bit integer holding nanoseconds since epoch */ diff --git a/libc/calls/timeval_frommicros.c b/libc/calls/timeval_frommicros.c new file mode 100644 index 000000000..031120663 --- /dev/null +++ b/libc/calls/timeval_frommicros.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/calls/struct/timeval.h" + +/** + * Converts timeval interval from microseconds. + */ +struct timeval timeval_frommicros(int64_t x) { + struct timeval tv; + tv.tv_sec = x / 1000000; + tv.tv_usec = x % 1000000; + return tv; +} diff --git a/libc/calls/timeval_frommillis.c b/libc/calls/timeval_frommillis.c new file mode 100644 index 000000000..27e50ae3c --- /dev/null +++ b/libc/calls/timeval_frommillis.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/calls/struct/timeval.h" + +/** + * Converts timeval interval from milliseconds. + */ +struct timeval timeval_frommillis(int64_t x) { + struct timeval tv; + tv.tv_sec = x / 1000; + tv.tv_usec = x % 1000 * 1000; + return tv; +} diff --git a/libc/calls/timeval_tomicros.c b/libc/calls/timeval_tomicros.c new file mode 100644 index 000000000..d3b936dac --- /dev/null +++ b/libc/calls/timeval_tomicros.c @@ -0,0 +1,41 @@ +/*-*- 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/timeval.h" +#include "libc/limits.h" + +/** + * Converts timeval to scalar. + * + * This returns the absolute number of microseconds in a timeval. If + * overflow happens, then `INT64_MAX` or `INT64_MIN` is returned. The + * `errno` variable isn't changed. + * + * @return 64-bit integer holding microseconds since epoch + */ +int64_t timeval_tomicros(struct timeval x) { + int64_t ns; + if (!__builtin_mul_overflow(x.tv_sec, 1000000ul, &ns) && + !__builtin_add_overflow(ns, x.tv_usec, &ns)) { + return ns; + } else if (x.tv_sec < 0) { + return INT64_MIN; + } else { + return INT64_MAX; + } +} diff --git a/libc/calls/timeval_tomillis.c b/libc/calls/timeval_tomillis.c new file mode 100644 index 000000000..7026f1473 --- /dev/null +++ b/libc/calls/timeval_tomillis.c @@ -0,0 +1,56 @@ +/*-*- 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/timeval.h" +#include "libc/limits.h" + +/** + * Reduces `ts` from 1e-6 to 1e-3 granularity w/ ceil rounding. + * + * This function returns the absolute number of milliseconds in a + * timeval. Ceiling rounding is used. For example, if `ts` is one + * nanosecond, then one millisecond will be returned. Ceil rounding is + * needed by many interfaces, e.g. setitimer(), because the zero + * timestamp has a valial meaning. + * + * This function also detects overflow in which case `INT64_MAX` or + * `INT64_MIN` may be returned. The `errno` variable isn't changed. + * + * @return 64-bit scalar milliseconds since epoch + */ +int64_t timeval_tomillis(struct timeval ts) { + int64_t ms; + // reduce precision from micros to millis + if (ts.tv_usec <= 999000) { + ts.tv_usec = (ts.tv_usec + 999) / 1000; + } else { + ts.tv_usec = 0; + if (ts.tv_sec < INT64_MAX) { + ts.tv_sec += 1; + } + } + // convert to scalar result + if (!__builtin_mul_overflow(ts.tv_sec, 1000ul, &ms) && + !__builtin_add_overflow(ms, ts.tv_usec, &ms)) { + return ms; + } else if (ts.tv_sec < 0) { + return INT64_MIN; + } else { + return INT64_MAX; + } +} diff --git a/libc/integral/c.inc b/libc/integral/c.inc index 9931953b7..92eaf283f 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -608,10 +608,10 @@ typedef struct { #endif #endif -#define notpossible \ - do { \ - asm("ud2\n\tnop"); \ - unreachable; \ +#define notpossible \ + do { \ + asm("nop\n\tud2\n\tnop"); \ + unreachable; \ } while (0) #define donothing \ diff --git a/libc/intrin/describetimespec.c b/libc/intrin/describetimespec.c index c7f4d77f6..73cb887d0 100644 --- a/libc/intrin/describetimespec.c +++ b/libc/intrin/describetimespec.c @@ -21,6 +21,7 @@ #include "libc/intrin/asan.internal.h" #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/kprintf.h" +#include "libc/str/str.h" const char *(DescribeTimespec)(char buf[45], int rc, const struct timespec *ts) { @@ -30,7 +31,11 @@ const char *(DescribeTimespec)(char buf[45], int rc, (IsAsan() && !__asan_is_valid(ts, sizeof(*ts)))) { ksnprintf(buf, 45, "%p", ts); } else { - ksnprintf(buf, 45, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec); + if (!memcmp(ts, ×pec_max, sizeof(*ts))) { + strcpy(buf, "timespec_max"); + } else { + ksnprintf(buf, 45, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec); + } } return buf; } diff --git a/libc/intrin/gettid.c b/libc/intrin/gettid.c index afc8f219b..9f90c2c1f 100644 --- a/libc/intrin/gettid.c +++ b/libc/intrin/gettid.c @@ -20,6 +20,7 @@ #include "libc/calls/state.internal.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/intrin/atomic.h" +#include "libc/intrin/likely.h" #include "libc/thread/tls.h" /** @@ -36,9 +37,9 @@ */ int gettid(void) { int tid; - if (__tls_enabled && !__vforked) { - tid = atomic_load_explicit(&__get_tls()->tib_tid, memory_order_relaxed); - if (tid > 0) { + if (VERY_LIKELY(__tls_enabled && !__vforked)) { + tid = atomic_load_explicit(&__get_tls()->tib_tid, memory_order_acquire); + if (VERY_LIKELY(tid > 0)) { return tid; } } diff --git a/libc/intrin/intrin.h b/libc/intrin/intrin.h new file mode 100755 index 000000000..e69de29bb diff --git a/libc/sysv/calls/sys_sem_close.s b/libc/sysv/calls/sys_sem_close.s new file mode 100644 index 000000000..823358516 --- /dev/null +++ b/libc/sysv/calls/sys_sem_close.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_close,0x0fafff190210dfff,globl diff --git a/libc/sysv/calls/sys_sem_destroy.s b/libc/sysv/calls/sys_sem_destroy.s new file mode 100644 index 000000000..ab3606761 --- /dev/null +++ b/libc/sysv/calls/sys_sem_destroy.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_destroy,0x0fffff198fffffff,globl diff --git a/libc/sysv/calls/sys_sem_getvalue.s b/libc/sysv/calls/sys_sem_getvalue.s new file mode 100644 index 000000000..9d0b0ca1f --- /dev/null +++ b/libc/sysv/calls/sys_sem_getvalue.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_getvalue,0x0fefff197fffffff,globl diff --git a/libc/sysv/calls/sys_sem_init.s b/libc/sysv/calls/sys_sem_init.s new file mode 100644 index 000000000..f53f208af --- /dev/null +++ b/libc/sysv/calls/sys_sem_init.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_init,0x0f7fff194fffffff,globl diff --git a/libc/sysv/calls/sys_sem_open.s b/libc/sysv/calls/sys_sem_open.s new file mode 100644 index 000000000..ba9a8e674 --- /dev/null +++ b/libc/sysv/calls/sys_sem_open.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_open,0x0f8fff195210cfff,globl diff --git a/libc/sysv/calls/sys_sem_post.s b/libc/sysv/calls/sys_sem_post.s new file mode 100644 index 000000000..e1cb3ec70 --- /dev/null +++ b/libc/sysv/calls/sys_sem_post.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_post,0x0fbfff1912111fff,globl diff --git a/libc/sysv/calls/sys_sem_timedwait.s b/libc/sysv/calls/sys_sem_timedwait.s new file mode 100644 index 000000000..8c2f3cf7d --- /dev/null +++ b/libc/sysv/calls/sys_sem_timedwait.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_timedwait,0x900fff9b9fffffff,globl diff --git a/libc/sysv/calls/sys_sem_trywait.s b/libc/sysv/calls/sys_sem_trywait.s new file mode 100644 index 000000000..2be4af737 --- /dev/null +++ b/libc/sysv/calls/sys_sem_trywait.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_trywait,0x0fdfff1932110fff,globl diff --git a/libc/sysv/calls/sys_sem_unlink.s b/libc/sysv/calls/sys_sem_unlink.s new file mode 100644 index 000000000..85b721124 --- /dev/null +++ b/libc/sysv/calls/sys_sem_unlink.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_unlink,0x0f9fff196210efff,globl diff --git a/libc/sysv/calls/sys_sem_wait.s b/libc/sysv/calls/sys_sem_wait.s new file mode 100644 index 000000000..93af765a6 --- /dev/null +++ b/libc/sysv/calls/sys_sem_wait.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_wait,0x8fcfff992290ffff,globl diff --git a/libc/sysv/calls/sys_sem_wait_nocancel.s b/libc/sysv/calls/sys_sem_wait_nocancel.s new file mode 100644 index 000000000..a6de54e1d --- /dev/null +++ b/libc/sysv/calls/sys_sem_wait_nocancel.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sem_wait_nocancel,0xfffffffff21a4fff,globl diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index b747bd913..ce41bc21d 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -2094,44 +2094,44 @@ syscon nr __NR_ktrace 0xfff 0xfff 0x002d 0x002d 0x02d 0xfff # unilateral undocumented errnos # # group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary -syscon junkerr ECHRNG 44 0 0 0 0 0 -syscon junkerr EL2NSYNC 45 0 0 0 0 0 -syscon junkerr EL3HLT 46 0 0 0 0 0 -syscon junkerr EL3RST 47 0 0 0 0 0 -syscon junkerr ELNRNG 48 0 0 0 0 0 -syscon junkerr EUNATCH 49 0 0 0 0 0 -syscon junkerr ENOCSI 50 0 0 0 0 0 -syscon junkerr EL2HLT 51 0 0 0 0 0 -syscon junkerr EBADE 52 0 0 0 0 0 -syscon junkerr EBADR 53 0 0 0 0 0 -syscon junkerr EXFULL 54 0 0 0 0 0 -syscon junkerr ENOANO 55 0 0 0 0 0 -syscon junkerr EBADRQC 56 0 0 0 0 0 -syscon junkerr EBADSLT 57 0 0 0 0 0 -syscon junkerr ENOPKG 65 0 0 0 0 0 -syscon junkerr EADV 68 0 0 0 0 0 -syscon junkerr ESRMNT 69 0 0 0 0 0 -syscon junkerr ECOMM 70 0 0 0 0 0 -syscon junkerr EDOTDOT 73 0 0 0 0 0 -syscon junkerr ENOTUNIQ 76 0 0 0 0 0 -syscon junkerr EREMCHG 78 0 0 0 0 0 -syscon junkerr ELIBACC 79 0 0 0 0 0 -syscon junkerr ELIBBAD 80 0 0 0 0 0 -syscon junkerr ELIBSCN 81 0 0 0 0 0 -syscon junkerr ELIBMAX 82 0 0 0 0 0 -syscon junkerr ELIBEXEC 83 0 0 0 0 0 -syscon junkerr ESTRPIPE 86 0 0 0 0 0 -syscon junkerr EUCLEAN 117 0 0 0 0 0 -syscon junkerr ENOTNAM 118 0 0 0 0 0 -syscon junkerr ENAVAIL 119 0 0 0 0 0 -syscon junkerr EISNAM 120 0 0 0 0 0 -syscon junkerr EREMOTEIO 121 0 0 0 0 0 -syscon junkerr ENOKEY 126 0 0 0 0 0 -syscon junkerr EKEYEXPIRED 127 0 0 0 0 0 -syscon junkerr EKEYREVOKED 128 0 0 0 0 0 -syscon junkerr EKEYREJECTED 129 0 0 0 0 0 -syscon junkerr ERFKILL 132 0 0 0 0 0 -syscon junkerr EHWPOISON 133 0 0 0 0 0 +syscon junkerr ECHRNG 44 -1 -1 -1 -1 -1 +syscon junkerr EL2NSYNC 45 -1 -1 -1 -1 -1 +syscon junkerr EL3HLT 46 -1 -1 -1 -1 -1 +syscon junkerr EL3RST 47 -1 -1 -1 -1 -1 +syscon junkerr ELNRNG 48 -1 -1 -1 -1 -1 +syscon junkerr EUNATCH 49 -1 -1 -1 -1 -1 +syscon junkerr ENOCSI 50 -1 -1 -1 -1 -1 +syscon junkerr EL2HLT 51 -1 -1 -1 -1 -1 +syscon junkerr EBADE 52 -1 -1 -1 -1 -1 +syscon junkerr EBADR 53 -1 -1 -1 -1 -1 +syscon junkerr EXFULL 54 -1 -1 -1 -1 -1 +syscon junkerr ENOANO 55 -1 -1 -1 -1 -1 +syscon junkerr EBADRQC 56 -1 -1 -1 -1 -1 +syscon junkerr EBADSLT 57 -1 -1 -1 -1 -1 +syscon junkerr ENOPKG 65 -1 -1 -1 -1 -1 +syscon junkerr EADV 68 -1 -1 -1 -1 -1 +syscon junkerr ESRMNT 69 -1 -1 -1 -1 -1 +syscon junkerr ECOMM 70 -1 -1 -1 -1 -1 +syscon junkerr EDOTDOT 73 -1 -1 -1 -1 -1 +syscon junkerr ENOTUNIQ 76 -1 -1 -1 -1 -1 +syscon junkerr EREMCHG 78 -1 -1 -1 -1 -1 +syscon junkerr ELIBACC 79 -1 -1 -1 -1 -1 +syscon junkerr ELIBBAD 80 -1 -1 -1 -1 -1 +syscon junkerr ELIBSCN 81 -1 -1 -1 -1 -1 +syscon junkerr ELIBMAX 82 -1 -1 -1 -1 -1 +syscon junkerr ELIBEXEC 83 -1 -1 -1 -1 -1 +syscon junkerr ESTRPIPE 86 -1 -1 -1 -1 -1 +syscon junkerr EUCLEAN 117 -1 -1 -1 -1 -1 +syscon junkerr ENOTNAM 118 -1 -1 -1 -1 -1 +syscon junkerr ENAVAIL 119 -1 -1 -1 -1 -1 +syscon junkerr EISNAM 120 -1 -1 -1 -1 -1 +syscon junkerr EREMOTEIO 121 -1 -1 -1 -1 -1 +syscon junkerr ENOKEY 126 -1 -1 -1 -1 -1 +syscon junkerr EKEYEXPIRED 127 -1 -1 -1 -1 -1 +syscon junkerr EKEYREVOKED 128 -1 -1 -1 -1 -1 +syscon junkerr EKEYREJECTED 129 -1 -1 -1 -1 -1 +syscon junkerr ERFKILL 132 -1 -1 -1 -1 -1 +syscon junkerr EHWPOISON 133 -1 -1 -1 -1 -1 # arpanet fork combating human-induced exhaustion of our ipv4 address space # diff --git a/libc/sysv/consts/EADV.s b/libc/sysv/consts/EADV.s index e83103342..d6b57a875 100644 --- a/libc/sysv/consts/EADV.s +++ b/libc/sysv/consts/EADV.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EADV,68,0,0,0,0,0 +.syscon junkerr,EADV,68,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EBADE.s b/libc/sysv/consts/EBADE.s index 805ad64de..0c2747a27 100644 --- a/libc/sysv/consts/EBADE.s +++ b/libc/sysv/consts/EBADE.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EBADE,52,0,0,0,0,0 +.syscon junkerr,EBADE,52,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EBADR.s b/libc/sysv/consts/EBADR.s index 32dcacfb7..8bec26cc3 100644 --- a/libc/sysv/consts/EBADR.s +++ b/libc/sysv/consts/EBADR.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EBADR,53,0,0,0,0,0 +.syscon junkerr,EBADR,53,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EBADRQC.s b/libc/sysv/consts/EBADRQC.s index d5717bf0d..2e046c2f2 100644 --- a/libc/sysv/consts/EBADRQC.s +++ b/libc/sysv/consts/EBADRQC.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EBADRQC,56,0,0,0,0,0 +.syscon junkerr,EBADRQC,56,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EBADSLT.s b/libc/sysv/consts/EBADSLT.s index ecbbaf518..00e7264dd 100644 --- a/libc/sysv/consts/EBADSLT.s +++ b/libc/sysv/consts/EBADSLT.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EBADSLT,57,0,0,0,0,0 +.syscon junkerr,EBADSLT,57,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ECHRNG.s b/libc/sysv/consts/ECHRNG.s index bb7650fe2..af8260269 100644 --- a/libc/sysv/consts/ECHRNG.s +++ b/libc/sysv/consts/ECHRNG.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ECHRNG,44,0,0,0,0,0 +.syscon junkerr,ECHRNG,44,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ECOMM.s b/libc/sysv/consts/ECOMM.s index 24dceb368..1b07ba85e 100644 --- a/libc/sysv/consts/ECOMM.s +++ b/libc/sysv/consts/ECOMM.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ECOMM,70,0,0,0,0,0 +.syscon junkerr,ECOMM,70,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EDOTDOT.s b/libc/sysv/consts/EDOTDOT.s index 7632d9314..172751c08 100644 --- a/libc/sysv/consts/EDOTDOT.s +++ b/libc/sysv/consts/EDOTDOT.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EDOTDOT,73,0,0,0,0,0 +.syscon junkerr,EDOTDOT,73,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EHWPOISON.s b/libc/sysv/consts/EHWPOISON.s index 34ec3acc0..df6d391d4 100644 --- a/libc/sysv/consts/EHWPOISON.s +++ b/libc/sysv/consts/EHWPOISON.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EHWPOISON,133,0,0,0,0,0 +.syscon junkerr,EHWPOISON,133,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EISNAM.s b/libc/sysv/consts/EISNAM.s index 7b17515d1..1cbfffb19 100644 --- a/libc/sysv/consts/EISNAM.s +++ b/libc/sysv/consts/EISNAM.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EISNAM,120,0,0,0,0,0 +.syscon junkerr,EISNAM,120,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EKEYEXPIRED.s b/libc/sysv/consts/EKEYEXPIRED.s index fac92d550..a02dac016 100644 --- a/libc/sysv/consts/EKEYEXPIRED.s +++ b/libc/sysv/consts/EKEYEXPIRED.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EKEYEXPIRED,127,0,0,0,0,0 +.syscon junkerr,EKEYEXPIRED,127,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EKEYREJECTED.s b/libc/sysv/consts/EKEYREJECTED.s index 69de1e210..2c353deef 100644 --- a/libc/sysv/consts/EKEYREJECTED.s +++ b/libc/sysv/consts/EKEYREJECTED.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EKEYREJECTED,129,0,0,0,0,0 +.syscon junkerr,EKEYREJECTED,129,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EKEYREVOKED.s b/libc/sysv/consts/EKEYREVOKED.s index b1b0873fc..59be76e70 100644 --- a/libc/sysv/consts/EKEYREVOKED.s +++ b/libc/sysv/consts/EKEYREVOKED.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EKEYREVOKED,128,0,0,0,0,0 +.syscon junkerr,EKEYREVOKED,128,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EL2HLT.s b/libc/sysv/consts/EL2HLT.s index 98276b0bb..5a8cf2cc2 100644 --- a/libc/sysv/consts/EL2HLT.s +++ b/libc/sysv/consts/EL2HLT.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EL2HLT,51,0,0,0,0,0 +.syscon junkerr,EL2HLT,51,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EL2NSYNC.s b/libc/sysv/consts/EL2NSYNC.s index 041cf5288..2e1bf3583 100644 --- a/libc/sysv/consts/EL2NSYNC.s +++ b/libc/sysv/consts/EL2NSYNC.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EL2NSYNC,45,0,0,0,0,0 +.syscon junkerr,EL2NSYNC,45,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EL3HLT.s b/libc/sysv/consts/EL3HLT.s index 0fcc00adb..1bd1211fb 100644 --- a/libc/sysv/consts/EL3HLT.s +++ b/libc/sysv/consts/EL3HLT.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EL3HLT,46,0,0,0,0,0 +.syscon junkerr,EL3HLT,46,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EL3RST.s b/libc/sysv/consts/EL3RST.s index ecafe52b7..f7c4c3d02 100644 --- a/libc/sysv/consts/EL3RST.s +++ b/libc/sysv/consts/EL3RST.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EL3RST,47,0,0,0,0,0 +.syscon junkerr,EL3RST,47,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ELIBACC.s b/libc/sysv/consts/ELIBACC.s index 170bff519..5bd3cdd93 100644 --- a/libc/sysv/consts/ELIBACC.s +++ b/libc/sysv/consts/ELIBACC.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ELIBACC,79,0,0,0,0,0 +.syscon junkerr,ELIBACC,79,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ELIBBAD.s b/libc/sysv/consts/ELIBBAD.s index 0ac7c2e80..f670ad514 100644 --- a/libc/sysv/consts/ELIBBAD.s +++ b/libc/sysv/consts/ELIBBAD.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ELIBBAD,80,0,0,0,0,0 +.syscon junkerr,ELIBBAD,80,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ELIBEXEC.s b/libc/sysv/consts/ELIBEXEC.s index 04a047df6..d0bddc3ec 100644 --- a/libc/sysv/consts/ELIBEXEC.s +++ b/libc/sysv/consts/ELIBEXEC.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ELIBEXEC,83,0,0,0,0,0 +.syscon junkerr,ELIBEXEC,83,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ELIBMAX.s b/libc/sysv/consts/ELIBMAX.s index a6fb0056c..107e64053 100644 --- a/libc/sysv/consts/ELIBMAX.s +++ b/libc/sysv/consts/ELIBMAX.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ELIBMAX,82,0,0,0,0,0 +.syscon junkerr,ELIBMAX,82,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ELIBSCN.s b/libc/sysv/consts/ELIBSCN.s index 7679b4e61..ad0cf33ed 100644 --- a/libc/sysv/consts/ELIBSCN.s +++ b/libc/sysv/consts/ELIBSCN.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ELIBSCN,81,0,0,0,0,0 +.syscon junkerr,ELIBSCN,81,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ELNRNG.s b/libc/sysv/consts/ELNRNG.s index cc958c058..88d4ecbca 100644 --- a/libc/sysv/consts/ELNRNG.s +++ b/libc/sysv/consts/ELNRNG.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ELNRNG,48,0,0,0,0,0 +.syscon junkerr,ELNRNG,48,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ENAVAIL.s b/libc/sysv/consts/ENAVAIL.s index 196dca966..602c07cf7 100644 --- a/libc/sysv/consts/ENAVAIL.s +++ b/libc/sysv/consts/ENAVAIL.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ENAVAIL,119,0,0,0,0,0 +.syscon junkerr,ENAVAIL,119,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ENOANO.s b/libc/sysv/consts/ENOANO.s index ef1dd3d6d..3f5da5dec 100644 --- a/libc/sysv/consts/ENOANO.s +++ b/libc/sysv/consts/ENOANO.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ENOANO,55,0,0,0,0,0 +.syscon junkerr,ENOANO,55,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ENOCSI.s b/libc/sysv/consts/ENOCSI.s index b07b6914e..f1f6feb08 100644 --- a/libc/sysv/consts/ENOCSI.s +++ b/libc/sysv/consts/ENOCSI.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ENOCSI,50,0,0,0,0,0 +.syscon junkerr,ENOCSI,50,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ENOKEY.s b/libc/sysv/consts/ENOKEY.s index 757acdf80..f80902a4b 100644 --- a/libc/sysv/consts/ENOKEY.s +++ b/libc/sysv/consts/ENOKEY.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ENOKEY,126,0,0,0,0,0 +.syscon junkerr,ENOKEY,126,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ENOPKG.s b/libc/sysv/consts/ENOPKG.s index d7d266381..003b171c0 100644 --- a/libc/sysv/consts/ENOPKG.s +++ b/libc/sysv/consts/ENOPKG.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ENOPKG,65,0,0,0,0,0 +.syscon junkerr,ENOPKG,65,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ENOTNAM.s b/libc/sysv/consts/ENOTNAM.s index 0785870f1..eed775c7c 100644 --- a/libc/sysv/consts/ENOTNAM.s +++ b/libc/sysv/consts/ENOTNAM.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ENOTNAM,118,0,0,0,0,0 +.syscon junkerr,ENOTNAM,118,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ENOTUNIQ.s b/libc/sysv/consts/ENOTUNIQ.s index 8d846c8d9..e86d994b9 100644 --- a/libc/sysv/consts/ENOTUNIQ.s +++ b/libc/sysv/consts/ENOTUNIQ.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ENOTUNIQ,76,0,0,0,0,0 +.syscon junkerr,ENOTUNIQ,76,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EREMCHG.s b/libc/sysv/consts/EREMCHG.s index 128909b6b..e43334af0 100644 --- a/libc/sysv/consts/EREMCHG.s +++ b/libc/sysv/consts/EREMCHG.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EREMCHG,78,0,0,0,0,0 +.syscon junkerr,EREMCHG,78,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EREMOTEIO.s b/libc/sysv/consts/EREMOTEIO.s index 5fb43d1a4..706a2d3fd 100644 --- a/libc/sysv/consts/EREMOTEIO.s +++ b/libc/sysv/consts/EREMOTEIO.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EREMOTEIO,121,0,0,0,0,0 +.syscon junkerr,EREMOTEIO,121,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ERFKILL.s b/libc/sysv/consts/ERFKILL.s index 439aa0f10..43ca85ada 100644 --- a/libc/sysv/consts/ERFKILL.s +++ b/libc/sysv/consts/ERFKILL.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ERFKILL,132,0,0,0,0,0 +.syscon junkerr,ERFKILL,132,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ESRMNT.s b/libc/sysv/consts/ESRMNT.s index eea8e946a..94b6acf55 100644 --- a/libc/sysv/consts/ESRMNT.s +++ b/libc/sysv/consts/ESRMNT.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ESRMNT,69,0,0,0,0,0 +.syscon junkerr,ESRMNT,69,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/ESTRPIPE.s b/libc/sysv/consts/ESTRPIPE.s index 70fcb4045..8ae1f74f1 100644 --- a/libc/sysv/consts/ESTRPIPE.s +++ b/libc/sysv/consts/ESTRPIPE.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,ESTRPIPE,86,0,0,0,0,0 +.syscon junkerr,ESTRPIPE,86,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EUCLEAN.s b/libc/sysv/consts/EUCLEAN.s index e87b8c058..4a134de17 100644 --- a/libc/sysv/consts/EUCLEAN.s +++ b/libc/sysv/consts/EUCLEAN.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EUCLEAN,117,0,0,0,0,0 +.syscon junkerr,EUCLEAN,117,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EUNATCH.s b/libc/sysv/consts/EUNATCH.s index 8397f5360..9e2b08712 100644 --- a/libc/sysv/consts/EUNATCH.s +++ b/libc/sysv/consts/EUNATCH.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EUNATCH,49,0,0,0,0,0 +.syscon junkerr,EUNATCH,49,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/EXFULL.s b/libc/sysv/consts/EXFULL.s index d54315dcc..3a9c7fa16 100644 --- a/libc/sysv/consts/EXFULL.s +++ b/libc/sysv/consts/EXFULL.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon junkerr,EXFULL,54,0,0,0,0,0 +.syscon junkerr,EXFULL,54,-1,-1,-1,-1,-1 diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index fda997452..631fb7aaf 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -428,6 +428,18 @@ scall sys_issetugid 0xfff0fd0fd2147fff globl hidden scall sys_minherit 0x1110fa0fa20fafff globl # no wrapper scall sys_pathconf 0x0bf0bf0bf20bffff globl # no wrapper scall sys_sysctl 0x0ca0ca0ca20cafff globl # no wrapper +#──────────────────XNU & FREEBSD & NETBSD──────────────────── +scall sys_sem_init 0x0f7fff194fffffff globl +scall sys_sem_destroy 0x0fffff198fffffff globl +scall sys_sem_open 0x0f8fff195210cfff globl +scall sys_sem_close 0x0fafff190210dfff globl +scall sys_sem_unlink 0x0f9fff196210efff globl +scall sys_sem_post 0x0fbfff1912111fff globl +scall sys_sem_wait 0x8fcfff992290ffff globl +scall sys_sem_trywait 0x0fdfff1932110fff globl +scall sys_sem_timedwait 0x900fff9b9fffffff globl +scall sys_sem_wait_nocancel 0xfffffffff21a4fff globl # no wrapper +scall sys_sem_getvalue 0x0fefff197fffffff globl #───────────────────────XNU & FREEBSD──────────────────────── scall sys_ntp_adjtime 0x0b0fff0b0220ffff globl # no wrapper scall sys_ntp_gettime 0x1c0fff0f82210fff globl # no wrapper @@ -597,13 +609,6 @@ scall sys_bsdthread_register 0xfffffffff216efff globl hidden #scall renameatx_np 0xfffffffff21e8fff globl #scall searchfs 0xfffffffff20e1fff globl #scall select_nocancel 0xfffffffff2197fff globl -#scall sem_close 0xfffffffff210dfff globl -#scall sem_open 0xfffffffff210cfff globl -#scall sem_post 0xfffffffff2111fff globl -#scall sem_trywait 0xfffffffff2110fff globl -#scall sem_unlink 0xfffffffff210efff globl -#scall sem_wait 0xfffffffff210ffff globl -#scall sem_wait_nocancel 0xfffffffff21a4fff globl #scall sendmsg_nocancel 0xfffffffff2192fff globl #scall sendmsg_x 0xfffffffff21e1fff globl #scall sendto_nocancel 0xfffffffff219dfff globl @@ -711,16 +716,6 @@ scall getpagesize_freebsd 0xffffff040fffffff globl hidden #scall kmq_timedreceive 0xffffff1cbfffffff globl #scall kmq_timedsend 0xffffff1ccfffffff globl #scall kmq_unlink 0xffffff1cefffffff globl -#scall ksem_close 0xffffff190fffffff globl -#scall ksem_destroy 0xffffff198fffffff globl -#scall ksem_getvalue 0xffffff197fffffff globl -#scall ksem_init 0xffffff194fffffff globl -#scall ksem_open 0xffffff195fffffff globl -#scall ksem_post 0xffffff191fffffff globl -#scall ksem_timedwait 0xffffff1b9fffffff globl -#scall ksem_trywait 0xffffff193fffffff globl -#scall ksem_unlink 0xffffff196fffffff globl -#scall ksem_wait 0xffffff192fffffff globl #scall lchflags 0x130fff187fffffff globl #scall lchmod 0x112fff112fffffff globl #scall lgetfh 0xffffff0a0fffffff globl diff --git a/libc/thread/pthread_cancel.c b/libc/thread/pthread_cancel.c index ec2285824..3c6339245 100644 --- a/libc/thread/pthread_cancel.c +++ b/libc/thread/pthread_cancel.c @@ -51,10 +51,10 @@ int _pthread_cancel_sys(void) { return ecanceled(); } -static void OnSigCancel(int sig, siginfo_t *si, void *ctx) { +static void OnSigThr(int sig, siginfo_t *si, void *ctx) { ucontext_t *uc = ctx; - struct CosmoTib *tib = __get_tls(); - struct PosixThread *pt = (struct PosixThread *)tib->tib_pthread; + struct CosmoTib *t = __get_tls(); + struct PosixThread *pt = (struct PosixThread *)t->tib_pthread; if (pt && !(pt->flags & PT_NOCANCEL) && atomic_load_explicit(&pt->cancelled, memory_order_acquire)) { sigaddset(&uc->uc_sigmask, sig); @@ -64,15 +64,14 @@ static void OnSigCancel(int sig, siginfo_t *si, void *ctx) { } else if (pt->flags & PT_ASYNC) { pthread_exit(PTHREAD_CANCELED); } else { - __tkill(atomic_load_explicit(&tib->tib_tid, memory_order_relaxed), sig, - tib); + __tkill(atomic_load_explicit(&t->tib_tid, memory_order_relaxed), sig, t); } } } -static void ListenForSigCancel(void) { +static void ListenForSigThr(void) { struct sigaction sa; - sa.sa_sigaction = OnSigCancel; + sa.sa_sigaction = OnSigThr; sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; memset(&sa.sa_mask, -1, sizeof(sa.sa_mask)); _npassert(!sigaction(SIGTHR, &sa, 0)); @@ -262,7 +261,7 @@ errno_t pthread_cancel(pthread_t thread) { int e, rc, tid; static bool once; struct PosixThread *pt; - if (!once) ListenForSigCancel(), once = true; + if (!once) ListenForSigThr(), once = true; pt = (struct PosixThread *)thread; switch (atomic_load_explicit(&pt->status, memory_order_acquire)) { case kPosixThreadZombie: diff --git a/libc/thread/sem_init.c b/libc/thread/sem_init.c index 69346e86d..c7371f380 100644 --- a/libc/thread/sem_init.c +++ b/libc/thread/sem_init.c @@ -35,13 +35,9 @@ * @param value is initial count of semaphore * @return 0 on success, or -1 w/ errno * @raise EINVAL if `value` exceeds `SEM_VALUE_MAX` - * @raise EPERM on OpenBSD if `pshared` is true */ int sem_init(sem_t *sem, int pshared, unsigned value) { if (value > SEM_VALUE_MAX) return einval(); - // OpenBSD MAP_ANONYMOUS|MAP_SHARED memory is kind of busted. - // The OpenBSD implementation of sem_init() also EPERMs here. - if (IsOpenbsd() && pshared) return eperm(); sem->sem_magic = SEM_MAGIC_UNNAMED; atomic_store_explicit(&sem->sem_value, value, memory_order_relaxed); sem->sem_pshared = !!pshared; diff --git a/libc/thread/sem_open.c b/libc/thread/sem_open.c index f235d026e..1f90d4af2 100644 --- a/libc/thread/sem_open.c +++ b/libc/thread/sem_open.c @@ -209,7 +209,7 @@ sem_t *sem_open(const char *name, int oflag, ...) { sem = SEM_FAILED; } else if (~oflag & O_EXCL) { sem = s->sem; - atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acquire); + atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acq_rel); ++s->refs; } else { eexist(); @@ -218,7 +218,7 @@ sem_t *sem_open(const char *name, int oflag, ...) { } else if ((s = calloc(1, sizeof(struct Semaphore)))) { if ((s->path = strdup(path))) { if ((sem = sem_open_impl(path, oflag, mode, value)) != SEM_FAILED) { - atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_relaxed); + atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acq_rel); s->next = g_semaphores.list; s->sem = sem; s->refs = 1; @@ -260,7 +260,7 @@ int sem_close(sem_t *sem) { sem_open_init(); sem_open_lock(); _npassert((s = sem_open_get(sem, &p))); - prefs = atomic_fetch_add_explicit(&sem->sem_prefs, -1, memory_order_release); + prefs = atomic_fetch_add_explicit(&sem->sem_prefs, -1, memory_order_acq_rel); _npassert(s->refs > 0); if ((unmap = !--s->refs)) { _npassert(prefs > 0); diff --git a/libc/thread/sem_timedwait.c b/libc/thread/sem_timedwait.c index ea1f295fa..bc3fa15c2 100644 --- a/libc/thread/sem_timedwait.c +++ b/libc/thread/sem_timedwait.c @@ -33,26 +33,6 @@ static void sem_delay(int n) { for (i = 0; i != 1 << n; i++) donothing; } -// TODO(jart): This should be abstracted by polyfill. -static struct timespec *sem_timeout(struct timespec *memory, - const struct timespec *abstime) { - struct timespec now; - if (!abstime) { - return 0; - } else if (FUTEX_TIMEOUT_IS_ABSOLUTE) { - *memory = *abstime; - return memory; - } else { - now = timespec_real(); - if (timespec_cmp(now, *abstime) > 0) { - *memory = (struct timespec){0}; - } else { - *memory = timespec_sub(*abstime, now); - } - return memory; - } -} - static void sem_timedwait_cleanup(void *arg) { sem_t *sem = arg; _unassert(atomic_fetch_add_explicit(&sem->sem_waiters, -1, @@ -95,8 +75,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime) { do { if (!(v = atomic_load_explicit(&sem->sem_value, memory_order_relaxed))) { - rc = nsync_futex_wait_(&sem->sem_value, v, sem->sem_pshared, - sem_timeout(&ts, abstime)); + rc = nsync_futex_wait_(&sem->sem_value, v, sem->sem_pshared, abstime); if (rc == -EINTR || rc == -ECANCELED) { errno = -rc; rc = -1; diff --git a/net/http/http.h b/net/http/http.h index de3ab7e09..aa12ffe90 100644 --- a/net/http/http.h +++ b/net/http/http.h @@ -209,7 +209,6 @@ bool IsAcceptablePath(const char *, size_t); bool IsAcceptableHost(const char *, size_t); bool IsAcceptablePort(const char *, size_t); bool IsReasonablePath(const char *, size_t); -int64_t ParseIp(const char *, size_t); int ParseForwarded(const char *, size_t, uint32_t *, uint16_t *); bool IsMimeType(const char *, size_t, const char *); ssize_t Unchunk(struct HttpUnchunker *, char *, size_t, size_t *); diff --git a/net/http/ip.h b/net/http/ip.h index 622b7bf66..ade85f37e 100644 --- a/net/http/ip.h +++ b/net/http/ip.h @@ -25,6 +25,13 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ +struct Cidr { + int64_t addr; + int cidr; +}; + +int64_t ParseIp(const char *, size_t); +struct Cidr ParseCidr(const char *, size_t); bool IsDodIp(uint32_t); bool IsArinIp(uint32_t); bool IsRipeIp(uint32_t); diff --git a/net/http/parsecidr.c b/net/http/parsecidr.c new file mode 100644 index 000000000..de5198b38 --- /dev/null +++ b/net/http/parsecidr.c @@ -0,0 +1,67 @@ +/*-*- 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/str/str.h" +#include "net/http/ip.h" + +/** + * Parse IPv4 network address. + * + * For example, a router address might be `10.10.10.1/24` in which case + * the IP address word `0x0a0a0a01` would be returned, whose CIDR would + * be 24. That means your IP address is on a network with 24 bits which + * converts to a netmask `0xffffff00` by using `1u << (32 - res.cidr)`. + * You may specify the IP address portion as an integer. As an example, + * the value `168430081/1` would be the same as `10.10.10.1/1` + * + * @param n if -1 implies strlen + * @return ip is uint32 IPv4 address, or -1 on failure + * @return cidr is number of bits in network, on interval [1,32]; it + * defaults to 32; if the return ip is -1 then cidr is undefined + */ +struct Cidr ParseCidr(const char *s, size_t n) { + size_t i; + const char *p; + struct Cidr c; + if (n == -1) n = s ? strlen(s) : 0; + if ((p = strchr(s, '/'))) { + if ((c.addr = ParseIp(s, (i = p - s))) != -1) { + c.cidr = 0; + for (++i; i < n; ++i) { + if (isdigit(s[i])) { + c.cidr *= 10; + c.cidr += s[i] - '0'; + if (c.cidr > 32) { + c.cidr = -1; + break; + } + } else { + c.cidr = -1; + break; + } + } + if (c.cidr <= 0) { + c.addr = -1; + } + } + } else { + c.addr = ParseIp(s, n); + c.cidr = 32; + } + return c; +} diff --git a/net/http/parseip.c b/net/http/parseip.c index 63c596e7b..d9a6aeb0f 100644 --- a/net/http/parseip.c +++ b/net/http/parseip.c @@ -17,27 +17,33 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/str/str.h" -#include "net/http/http.h" +#include "net/http/ip.h" /** - * Parse IPv4 address. + * Parse IPv4 host address. * * @param n if -1 implies strlen * @return -1 on failure, otherwise 32-bit host-order unsigned integer + * @see ParseCidr() */ int64_t ParseIp(const char *s, size_t n) { + int c, j; size_t i; - uint32_t x; - int b, c, j; + unsigned b, x; + bool dotted = false; if (n == -1) n = s ? strlen(s) : 0; if (!n) return -1; for (b = x = j = i = 0; i < n; ++i) { c = s[i] & 255; if (isdigit(c)) { - b *= 10; - b += c - '0'; + if (__builtin_mul_overflow(b, 10, &b) || // + __builtin_add_overflow(b, c - '0', &b) || // + (b > 255 && dotted)) { + return -1; + } } else if (c == '.') { if (b > 255) return -1; + dotted = true; x <<= 8; x |= b; b = 0; diff --git a/net/turfwar/blackhole.c b/net/turfwar/blackhole.c index a57eac330..bc1c82b45 100644 --- a/net/turfwar/blackhole.c +++ b/net/turfwar/blackhole.c @@ -28,6 +28,7 @@ #include "libc/sysv/consts/ex.h" #include "libc/sysv/consts/sock.h" #include "net/http/http.h" +#include "net/http/ip.h" int main(int argc, char *argv[]) { diff --git a/test/libc/calls/sigaction_test.c b/test/libc/calls/sigaction_test.c index fb102d7bf..a1c73a424 100644 --- a/test/libc/calls/sigaction_test.c +++ b/test/libc/calls/sigaction_test.c @@ -228,11 +228,13 @@ TEST(uc_sigmask, signalHandlerCanChangeSignalMaskOfTrappedThread) { struct sigaction oldsa; struct sigaction sa = {.sa_sigaction = OnSigMask, .sa_flags = SA_SIGINFO}; sigemptyset(&want); - ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &want, 0)); + ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &want, &got)); + ASSERT_FALSE(sigismember(&got, SIGUSR1)); ASSERT_SYS(0, 0, sigaction(SIGUSR1, &sa, &oldsa)); ASSERT_SYS(0, 0, raise(SIGUSR1)); ASSERT_TRUE(gotusr1); ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, 0, &got)); + ASSERT_TRUE(sigismember(&got, SIGUSR1)); sigaddset(&want, SIGUSR1); ASSERT_STREQ(DescribeSigset(0, &want), DescribeSigset(0, &got)); ASSERT_SYS(0, 0, sigaction(SIGUSR1, &oldsa, 0)); diff --git a/test/libc/intrin/test.mk b/test/libc/intrin/test.mk index 081cb5581..e4789b625 100644 --- a/test/libc/intrin/test.mk +++ b/test/libc/intrin/test.mk @@ -34,6 +34,7 @@ TEST_LIBC_INTRIN_DIRECTDEPS = \ LIBC_STR \ LIBC_STUBS \ LIBC_SYSV \ + LIBC_SYSV_CALLS \ LIBC_THREAD \ LIBC_TESTLIB \ LIBC_TINYMATH \ diff --git a/test/libc/stdio/popen_test.c b/test/libc/stdio/popen_test.c index 7de492dff..b5c6d221f 100644 --- a/test/libc/stdio/popen_test.c +++ b/test/libc/stdio/popen_test.c @@ -22,7 +22,9 @@ #include "libc/errno.h" #include "libc/fmt/fmt.h" #include "libc/fmt/itoa.h" +#include "libc/intrin/kprintf.h" #include "libc/limits.h" +#include "libc/log/log.h" #include "libc/mem/gc.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" @@ -39,6 +41,23 @@ FILE *f; char buf[32]; char testlib_enable_tmp_setup_teardown; +void CheckForFdLeaks(void) { + int rc, i, l = 0, e = errno; + for (i = 3; i < 16; ++i) { + rc = fcntl(i, F_GETFL); + if (rc == -1) { + ASSERT_EQ(EBADF, errno); + errno = e; + } else { + kprintf("file descriptor %d leaked!\n", i); + ++l; + } + } + if (l) { + __die(); + } +} + TEST(popen, command) { char foo[6]; testlib_extract("/zip/echo.com", "echo.com", 0755); @@ -46,6 +65,7 @@ TEST(popen, command) { ASSERT_NE(NULL, fgets(foo, sizeof(foo), f)); ASSERT_STREQ("hello", foo); ASSERT_EQ(0, pclose(f)); + CheckForFdLeaks(); } TEST(popen, semicolon) { @@ -53,6 +73,7 @@ TEST(popen, semicolon) { ASSERT_STREQ("hello\n", fgets(buf, sizeof(buf), f)); ASSERT_STREQ("there\n", fgets(buf, sizeof(buf), f)); ASSERT_EQ(0, pclose(f)); + CheckForFdLeaks(); } TEST(popen, singleQuotes) { @@ -61,6 +82,7 @@ TEST(popen, singleQuotes) { ASSERT_STREQ("hello $there\n", fgets(buf, sizeof(buf), f)); ASSERT_STREQ("yo\n", fgets(buf, sizeof(buf), f)); ASSERT_EQ(0, pclose(f)); + CheckForFdLeaks(); } TEST(popen, doubleQuotes) { @@ -68,6 +90,7 @@ TEST(popen, doubleQuotes) { ASSERT_NE(NULL, (f = popen("echo -l \"$hello there\"", "r"))); ASSERT_STREQ("a b c there\n", fgets(buf, sizeof(buf), f)); ASSERT_EQ(0, pclose(f)); + CheckForFdLeaks(); } TEST(popen, quoteless) { @@ -77,6 +100,7 @@ TEST(popen, quoteless) { ASSERT_STREQ("aa b c\n", fgets(buf, sizeof(buf), f)); // mixed feelings ASSERT_STREQ("yo\n", fgets(buf, sizeof(buf), f)); ASSERT_EQ(0, pclose(f)); + CheckForFdLeaks(); } TEST(popen, pipe) { @@ -84,6 +108,7 @@ TEST(popen, pipe) { ASSERT_NE(NULL, (f = popen("echo hello | toupper", "r"))); ASSERT_STREQ("HELLO\n", fgets(buf, sizeof(buf), f)); ASSERT_EQ(0, pclose(f)); + CheckForFdLeaks(); } sig_atomic_t gotsig; @@ -102,6 +127,7 @@ TEST(popen, complicated) { ASSERT_EQ(0, pclose(f)); ASSERT_EQ(1, gotsig); signal(SIGUSR1, SIG_DFL); + CheckForFdLeaks(); } void *Worker(void *arg) { @@ -129,10 +155,10 @@ void *Worker(void *arg) { } TEST(popen, torture) { - int i, n = 8; + int i, n = 4; pthread_t *t = _gc(malloc(sizeof(pthread_t) * n)); testlib_extract("/zip/echo.com", "echo.com", 0755); for (i = 0; i < n; ++i) ASSERT_EQ(0, pthread_create(t + i, 0, Worker, 0)); for (i = 0; i < n; ++i) ASSERT_EQ(0, pthread_join(t[i], 0)); - for (i = 3; i < 16; ++i) ASSERT_SYS(EBADF, -1, fcntl(i, F_GETFL)); + CheckForFdLeaks(); } diff --git a/test/libc/thread/sem_timedwait_test.c b/test/libc/thread/sem_timedwait_test.c index cc31de3da..7fa087d2d 100644 --- a/test/libc/thread/sem_timedwait_test.c +++ b/test/libc/thread/sem_timedwait_test.c @@ -170,12 +170,6 @@ TEST(sem_timedwait, threads) { TEST(sem_timedwait, processes) { int i, r, rc, n = 4, pshared = 1; sem_t *sm = _mapshared(FRAMESIZE), *s[2] = {sm, sm + 1}; - if (IsOpenbsd()) { - // TODO(jart): why? - ASSERT_SYS(EPERM, -1, sem_init(s[0], pshared, 0)); - ASSERT_SYS(0, 0, munmap(sm, FRAMESIZE)); - return; - } ASSERT_SYS(0, 0, sem_init(s[0], pshared, 0)); ASSERT_SYS(0, 0, sem_init(s[1], pshared, 0)); for (i = 0; i < n; ++i) { diff --git a/test/net/http/parsecidr_test.c b/test/net/http/parsecidr_test.c new file mode 100644 index 000000000..216e6cbb1 --- /dev/null +++ b/test/net/http/parsecidr_test.c @@ -0,0 +1,59 @@ +/*-*- 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/testlib/testlib.h" +#include "net/http/ip.h" + +TEST(ParseCidr, test) { + struct Cidr in; + in = ParseCidr("10.10.10.1/24", -1); + EXPECT_EQ(0x0a0a0a01, in.addr); + EXPECT_EQ(24, in.cidr); + in = ParseCidr("168430081/1", -1); + EXPECT_EQ(0x0a0a0a01, in.addr); + EXPECT_EQ(1, in.cidr); +} + +TEST(ParseCidr, noCidr_defaultsTo32) { + struct Cidr in; + in = ParseCidr("10.10.10.255", -1); + EXPECT_EQ(0x0a0a0aff, in.addr); + EXPECT_EQ(32, in.cidr); +} + +TEST(ParseCidr, badIp_returnsNeg1) { + struct Cidr in; + in = ParseCidr("10.10.10.a", -1); + EXPECT_EQ(-1, in.addr); + in = ParseCidr("10.10.10.256", -1); + EXPECT_EQ(-1, in.addr); + in = ParseCidr("10.10.10.256/24", -1); + EXPECT_EQ(-1, in.addr); +} + +TEST(ParseCidr, badCidr_returnsNeg1) { + struct Cidr in; + in = ParseCidr("10.10.10.1/", -1); + EXPECT_EQ(-1, in.addr); + in = ParseCidr("10.10.10.1/a", -1); + EXPECT_EQ(-1, in.addr); + in = ParseCidr("10.10.10.1/0", -1); + EXPECT_EQ(-1, in.addr); + in = ParseCidr("10.10.10.1/33", -1); + EXPECT_EQ(-1, in.addr); +} diff --git a/test/net/http/parseip_test.c b/test/net/http/parseip_test.c index 9fe334193..cda459cfe 100644 --- a/test/net/http/parseip_test.c +++ b/test/net/http/parseip_test.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/testlib/testlib.h" -#include "net/http/http.h" +#include "net/http/ip.h" TEST(ParseIp, test) { EXPECT_EQ(-1, ParseIp("", -1)); @@ -30,6 +30,8 @@ TEST(ParseIp, test) { EXPECT_EQ(0x00000000, ParseIp("...", -1)); /* meh */ EXPECT_EQ(0x80000304, ParseIp("128.0.3.4", -1)); EXPECT_EQ(0x80000304, ParseIp("128..3.4", -1)); + EXPECT_EQ(-1, ParseIp("4294967296", -1)); + EXPECT_EQ(-1, ParseIp("255.255.255.256", -1)); EXPECT_EQ(-1, ParseIp("256.255.255.255", -1)); EXPECT_EQ(-1, ParseIp("hello", -1)); EXPECT_EQ(-1, ParseIp("hello\177", -1)); diff --git a/test/net/http/parseurl_test.c b/test/net/http/parseurl_test.c index fb0db51e9..78df73b17 100644 --- a/test/net/http/parseurl_test.c +++ b/test/net/http/parseurl_test.c @@ -26,6 +26,7 @@ #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" #include "net/http/http.h" +#include "net/http/ip.h" #include "net/http/url.h" TEST(ParseUrl, testEmpty) { diff --git a/third_party/lua/lunix.c b/third_party/lua/lunix.c index 5973ca113..af3e54cb7 100644 --- a/third_party/lua/lunix.c +++ b/third_party/lua/lunix.c @@ -2847,14 +2847,6 @@ static int LuaUnixMemoryWait(lua_State *L) { } else { ts.tv_sec = luaL_checkinteger(L, 4); ts.tv_nsec = luaL_optinteger(L, 5, 0); - if (!FUTEX_TIMEOUT_IS_ABSOLUTE) { - now = timespec_real(); - if (timespec_cmp(now, ts) > 0) { - ts = (struct timespec){0}; - } else { - ts = timespec_sub(ts, now); - } - } deadline = &ts; } BEGIN_CANCELLATION_POINT; diff --git a/third_party/mbedtls/x509_crt.c b/third_party/mbedtls/x509_crt.c index 01a3f0027..26e8e502b 100644 --- a/third_party/mbedtls/x509_crt.c +++ b/third_party/mbedtls/x509_crt.c @@ -15,17 +15,18 @@ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/bits.h" #include "libc/calls/calls.h" #include "libc/calls/struct/dirent.h" #include "libc/calls/struct/stat.h" #include "libc/fmt/fmt.h" +#include "libc/intrin/bits.h" #include "libc/limits.h" #include "libc/log/log.h" #include "libc/mem/mem.h" #include "libc/stdio/stdio.h" #include "libc/sysv/consts/s.h" #include "net/http/http.h" +#include "net/http/ip.h" #include "third_party/mbedtls/common.h" #include "third_party/mbedtls/error.h" #include "third_party/mbedtls/oid.h" diff --git a/third_party/nsync/futex.c b/third_party/nsync/futex.c index 1da653a97..b432e8531 100644 --- a/third_party/nsync/futex.c +++ b/third_party/nsync/futex.c @@ -28,7 +28,6 @@ #include "libc/errno.h" #include "libc/intrin/atomic.h" #include "libc/intrin/describeflags.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" #include "libc/limits.h" @@ -56,8 +55,8 @@ int sys_futex_cp (atomic_int *, int, int, const struct timespec *, int *, int); static int FUTEX_WAIT_; static int FUTEX_PRIVATE_FLAG_; -static bool FUTEX_IS_SUPPORTED; -bool FUTEX_TIMEOUT_IS_ABSOLUTE; +static bool futex_is_supported; +static bool futex_timeout_is_relative; __attribute__((__constructor__)) static void nsync_futex_init_ (void) { atomic_int x; @@ -65,20 +64,17 @@ __attribute__((__constructor__)) static void nsync_futex_init_ (void) { FUTEX_WAIT_ = FUTEX_WAIT; if (IsWindows ()) { - FUTEX_IS_SUPPORTED = true; - FUTEX_TIMEOUT_IS_ABSOLUTE = true; + futex_is_supported = true; return; } if (IsFreebsd ()) { - FUTEX_IS_SUPPORTED = true; - FUTEX_TIMEOUT_IS_ABSOLUTE = true; + futex_is_supported = true; FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG; return; } - if (!(FUTEX_IS_SUPPORTED = IsLinux () || IsOpenbsd ())) { - FUTEX_TIMEOUT_IS_ABSOLUTE = true; + if (!(futex_is_supported = IsLinux () || IsOpenbsd ())) { return; } @@ -98,20 +94,20 @@ __attribute__((__constructor__)) static void nsync_futex_init_ (void) { 1, 0, 0, FUTEX_BITSET_MATCH_ANY) == -EAGAIN) { FUTEX_WAIT_ = FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME; FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG; - FUTEX_TIMEOUT_IS_ABSOLUTE = true; } else if (!IsTiny () && IsLinux () && _futex (&x, FUTEX_WAIT_BITSET, 1, 0, 0, FUTEX_BITSET_MATCH_ANY) == -EAGAIN) { FUTEX_WAIT_ = FUTEX_WAIT_BITSET; FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG; - FUTEX_TIMEOUT_IS_ABSOLUTE = true; } else if (IsOpenbsd () || (!IsTiny () && IsLinux () && !_futex_wake (&x, FUTEX_WAKE_PRIVATE, 1))) { FUTEX_WAIT_ = FUTEX_WAIT; FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG; + futex_timeout_is_relative = true; } else { FUTEX_WAIT_ = FUTEX_WAIT; + futex_timeout_is_relative = true; } } @@ -123,10 +119,8 @@ static int nsync_futex_polyfill_ (atomic_int *w, int expect, struct timespec *ti ts = timespec_real (); if (!timeout) { deadline = timespec_max; - } else if (FUTEX_TIMEOUT_IS_ABSOLUTE) { - deadline = *timeout; } else { - deadline = timespec_add (ts, *timeout); + deadline = *timeout; } nanos = 100; @@ -186,9 +180,29 @@ static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare, stru return rc; } -int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec *timeout) { +static struct timespec *nsync_futex_timeout_ (struct timespec *memory, + const struct timespec *abstime) { + struct timespec now; + if (!abstime) { + return 0; + } else if (!futex_timeout_is_relative) { + *memory = *abstime; + return memory; + } else { + now = timespec_real (); + if (timespec_cmp (now, *abstime) > 0) { + *memory = (struct timespec){0}; + } else { + *memory = timespec_sub (*abstime, now); + } + return memory; + } +} + +int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec *abstime) { int e, rc, op, fop; struct PosixThread *pt = 0; + struct timespec tsmem, *timeout; if (atomic_load_explicit (w, memory_order_acquire) != expect) { return -EAGAIN; @@ -199,12 +213,14 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec * op |= FUTEX_PRIVATE_FLAG_; } + timeout = nsync_futex_timeout_ (&tsmem, abstime); + LOCKTRACE ("futex(%t [%d], %s, %#x, %s) → ...", w, atomic_load_explicit (w, memory_order_relaxed), DescribeFutexOp (op), expect, DescribeTimespec (0, timeout)); - if (FUTEX_IS_SUPPORTED) { + if (futex_is_supported) { e = errno; if (IsWindows ()) { // Windows 8 futexes don't support multiple processes :( @@ -270,7 +286,7 @@ int nsync_futex_wake_ (atomic_int *w, int count, char pshare) { op |= FUTEX_PRIVATE_FLAG_; } - if (FUTEX_IS_SUPPORTED) { + if (futex_is_supported) { if (IsWindows ()) { if (pshare) { goto Polyfill; diff --git a/third_party/nsync/futex.internal.h b/third_party/nsync/futex.internal.h index 1d4af73a0..ead218947 100644 --- a/third_party/nsync/futex.internal.h +++ b/third_party/nsync/futex.internal.h @@ -5,8 +5,6 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -extern bool FUTEX_TIMEOUT_IS_ABSOLUTE; - int nsync_futex_wake_(_Atomic(int) *, int, char); int nsync_futex_wait_(_Atomic(int) *, int, char, struct timespec *); diff --git a/third_party/nsync/mu_semaphore.c b/third_party/nsync/mu_semaphore.c index 8a903c5b6..0b128bc98 100644 --- a/third_party/nsync/mu_semaphore.c +++ b/third_party/nsync/mu_semaphore.c @@ -15,16 +15,9 @@ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" -#include "libc/errno.h" -#include "libc/intrin/kprintf.h" -#include "libc/intrin/weaken.h" -#include "libc/str/str.h" -#include "libc/thread/thread.h" -#include "third_party/nsync/atomic.h" -#include "third_party/nsync/atomic.internal.h" -#include "third_party/nsync/futex.internal.h" +#include "libc/dce.h" #include "third_party/nsync/mu_semaphore.h" +#include "third_party/nsync/mu_semaphore.internal.h" asm(".ident\t\"\\n\\n\ *NSYNC (Apache 2.0)\\n\ @@ -32,108 +25,40 @@ Copyright 2016 Google, Inc.\\n\ https://github.com/google/nsync\""); // clang-format off -#define ASSERT(x) _npassert(x) - -/* Check that atomic operations on nsync_atomic_uint32_ can be applied to int. */ -static const int assert_int_size = 1 / - (sizeof (assert_int_size) == sizeof (uint32_t) && - sizeof (nsync_atomic_uint32_) == sizeof (uint32_t)); - -struct futex { - int i; /* lo half=count; hi half=waiter count */ -}; - -static nsync_semaphore *sem_big_enough_for_futex = (nsync_semaphore *) (uintptr_t)(1 / - (sizeof (struct futex) <= sizeof (*sem_big_enough_for_futex))); - /* Initialize *s; the initial value is 0. */ void nsync_mu_semaphore_init (nsync_semaphore *s) { - struct futex *f = (struct futex *) s; - f->i = 0; + if (IsNetbsd ()) { + return nsync_mu_semaphore_init_sem (s); + } else { + return nsync_mu_semaphore_init_futex (s); + } } /* Wait until the count of *s exceeds 0, and decrement it. */ errno_t nsync_mu_semaphore_p (nsync_semaphore *s) { - struct futex *f = (struct futex *) s; - int i; - int result = 0; - do { - i = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i); - if (i == 0) { - int futex_result = nsync_futex_wait_ ( - (atomic_int *)&f->i, i, PTHREAD_PROCESS_PRIVATE, NULL); - ASSERT (futex_result == 0 || - futex_result == -EINTR || - futex_result == -EAGAIN || - futex_result == -ECANCELED || - futex_result == -EWOULDBLOCK); - if (futex_result == -ECANCELED) { - result = ECANCELED; - } - } - } while (result == 0 && (i == 0 || !ATM_CAS_ACQ ((nsync_atomic_uint32_ *) &f->i, i, i-1))); - return result; + if (IsNetbsd ()) { + return nsync_mu_semaphore_p_sem (s); + } else { + return nsync_mu_semaphore_p_futex (s); + } } /* Wait until one of: the count of *s is non-zero, in which case decrement *s and return 0; or abs_deadline expires, in which case return ETIMEDOUT. */ errno_t nsync_mu_semaphore_p_with_deadline (nsync_semaphore *s, nsync_time abs_deadline) { - struct futex *f = (struct futex *)s; - int i; - int result = 0; - do { - i = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i); - if (i == 0) { - int futex_result; - struct timespec ts_buf; - const struct timespec *ts = NULL; - if (nsync_time_cmp (abs_deadline, nsync_time_no_deadline) != 0) { - memset (&ts_buf, 0, sizeof (ts_buf)); - if (FUTEX_TIMEOUT_IS_ABSOLUTE) { - ts_buf.tv_sec = NSYNC_TIME_SEC (abs_deadline); - ts_buf.tv_nsec = NSYNC_TIME_NSEC (abs_deadline); - } else { - nsync_time now; - now = nsync_time_now (); - if (nsync_time_cmp (now, abs_deadline) > 0) { - ts_buf.tv_sec = 0; - ts_buf.tv_nsec = 0; - } else { - nsync_time rel_deadline; - rel_deadline = nsync_time_sub (abs_deadline, now); - ts_buf.tv_sec = NSYNC_TIME_SEC (rel_deadline); - ts_buf.tv_nsec = NSYNC_TIME_NSEC (rel_deadline); - } - } - ts = &ts_buf; - } - futex_result = nsync_futex_wait_ ((atomic_int *)&f->i, i, PTHREAD_PROCESS_PRIVATE, ts); - ASSERT (futex_result == 0 || - futex_result == -EINTR || - futex_result == -EAGAIN || - futex_result == -ECANCELED || - futex_result == -ETIMEDOUT || - futex_result == -EWOULDBLOCK); - /* Some systems don't wait as long as they are told. */ - if (futex_result == -ETIMEDOUT && - nsync_time_cmp (abs_deadline, nsync_time_now ()) <= 0) { - result = ETIMEDOUT; - } - if (futex_result == -ECANCELED) { - result = ECANCELED; - } - } - } while (result == 0 && (i == 0 || !ATM_CAS_ACQ ((nsync_atomic_uint32_ *) &f->i, i, i - 1))); - return (result); + if (IsNetbsd ()) { + return nsync_mu_semaphore_p_with_deadline_sem (s, abs_deadline); + } else { + return nsync_mu_semaphore_p_with_deadline_futex (s, abs_deadline); + } } /* Ensure that the count of *s is at least 1. */ void nsync_mu_semaphore_v (nsync_semaphore *s) { - struct futex *f = (struct futex *) s; - uint32_t old_value; - do { - old_value = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i); - } while (!ATM_CAS_REL ((nsync_atomic_uint32_ *) &f->i, old_value, old_value+1)); - ASSERT (nsync_futex_wake_ ((atomic_int *)&f->i, 1, PTHREAD_PROCESS_PRIVATE) >= 0); + if (IsNetbsd ()) { + return nsync_mu_semaphore_v_sem (s); + } else { + return nsync_mu_semaphore_v_futex (s); + } } diff --git a/third_party/nsync/mu_semaphore.internal.h b/third_party/nsync/mu_semaphore.internal.h index e69de29bb..390b3b323 100755 --- a/third_party/nsync/mu_semaphore.internal.h +++ b/third_party/nsync/mu_semaphore.internal.h @@ -0,0 +1,20 @@ +#ifndef COSMOPOLITAN_THIRD_PARTY_NSYNC_MU_SEMAPHORE_INTERNAL_H_ +#define COSMOPOLITAN_THIRD_PARTY_NSYNC_MU_SEMAPHORE_INTERNAL_H_ +#include "third_party/nsync/mu_semaphore.h" +#include "third_party/nsync/time.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +void nsync_mu_semaphore_init_futex(nsync_semaphore *); +errno_t nsync_mu_semaphore_p_futex(nsync_semaphore *); +errno_t nsync_mu_semaphore_p_with_deadline_futex(nsync_semaphore *, nsync_time); +void nsync_mu_semaphore_v_futex(nsync_semaphore *); + +void nsync_mu_semaphore_init_sem(nsync_semaphore *); +errno_t nsync_mu_semaphore_p_sem(nsync_semaphore *); +errno_t nsync_mu_semaphore_p_with_deadline_sem(nsync_semaphore *, nsync_time); +void nsync_mu_semaphore_v_sem(nsync_semaphore *); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_THIRD_PARTY_NSYNC_MU_SEMAPHORE_INTERNAL_H_ */ diff --git a/third_party/nsync/mu_semaphore_futex.c b/third_party/nsync/mu_semaphore_futex.c new file mode 100644 index 000000000..71c1ec63e --- /dev/null +++ b/third_party/nsync/mu_semaphore_futex.c @@ -0,0 +1,126 @@ +/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ +│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2016 Google Inc. │ +│ │ +│ Licensed under the Apache License, Version 2.0 (the "License"); │ +│ you may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/errno.h" +#include "libc/str/str.h" +#include "libc/thread/thread.h" +#include "third_party/nsync/atomic.h" +#include "third_party/nsync/atomic.internal.h" +#include "third_party/nsync/futex.internal.h" +#include "third_party/nsync/mu_semaphore.internal.h" + +asm(".ident\t\"\\n\\n\ +*NSYNC (Apache 2.0)\\n\ +Copyright 2016 Google, Inc.\\n\ +https://github.com/google/nsync\""); +// clang-format off + +#define ASSERT(x) _npassert(x) + +/* Check that atomic operations on nsync_atomic_uint32_ can be applied to int. */ +static const int assert_int_size = 1 / + (sizeof (assert_int_size) == sizeof (uint32_t) && + sizeof (nsync_atomic_uint32_) == sizeof (uint32_t)); + +struct futex { + int i; /* lo half=count; hi half=waiter count */ +}; + +static nsync_semaphore *sem_big_enough_for_futex = (nsync_semaphore *) (uintptr_t)(1 / + (sizeof (struct futex) <= sizeof (*sem_big_enough_for_futex))); + +/* Initialize *s; the initial value is 0. */ +void nsync_mu_semaphore_init_futex (nsync_semaphore *s) { + struct futex *f = (struct futex *) s; + f->i = 0; +} + +/* Wait until the count of *s exceeds 0, and decrement it. */ +errno_t nsync_mu_semaphore_p_futex (nsync_semaphore *s) { + struct futex *f = (struct futex *) s; + int e, i; + errno_t result = 0; + do { + i = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i); + if (i == 0) { + int futex_result; + futex_result = -nsync_futex_wait_ ( + (atomic_int *)&f->i, i, + PTHREAD_PROCESS_PRIVATE, 0); + ASSERT (futex_result == 0 || + futex_result == EINTR || + futex_result == EAGAIN || + futex_result == ECANCELED || + futex_result == EWOULDBLOCK); + if (futex_result == ECANCELED) { + result = ECANCELED; + } + } + } while (result == 0 && (i == 0 || !ATM_CAS_ACQ ((nsync_atomic_uint32_ *) &f->i, i, i-1))); + return result; +} + +/* Wait until one of: + the count of *s is non-zero, in which case decrement *s and return 0; + or abs_deadline expires, in which case return ETIMEDOUT. */ +errno_t nsync_mu_semaphore_p_with_deadline_futex (nsync_semaphore *s, nsync_time abs_deadline) { + struct futex *f = (struct futex *)s; + int e, i; + int result = 0; + do { + i = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i); + if (i == 0) { + int futex_result; + struct timespec ts_buf; + const struct timespec *ts = NULL; + if (nsync_time_cmp (abs_deadline, nsync_time_no_deadline) != 0) { + memset (&ts_buf, 0, sizeof (ts_buf)); + ts_buf.tv_sec = NSYNC_TIME_SEC (abs_deadline); + ts_buf.tv_nsec = NSYNC_TIME_NSEC (abs_deadline); + ts = &ts_buf; + } + futex_result = nsync_futex_wait_ ((atomic_int *)&f->i, i, + PTHREAD_PROCESS_PRIVATE, ts); + ASSERT (futex_result == 0 || + futex_result == -EINTR || + futex_result == -EAGAIN || + futex_result == -ECANCELED || + futex_result == -ETIMEDOUT || + futex_result == -EWOULDBLOCK); + /* Some systems don't wait as long as they are told. */ + if (futex_result == -ETIMEDOUT && + nsync_time_cmp (abs_deadline, nsync_time_now ()) <= 0) { + result = ETIMEDOUT; + } + if (futex_result == -ECANCELED) { + result = ECANCELED; + } + } + } while (result == 0 && (i == 0 || !ATM_CAS_ACQ ((nsync_atomic_uint32_ *) &f->i, i, i - 1))); + return (result); +} + +/* Ensure that the count of *s is at least 1. */ +void nsync_mu_semaphore_v_futex (nsync_semaphore *s) { + struct futex *f = (struct futex *) s; + uint32_t old_value; + do { + old_value = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i); + } while (!ATM_CAS_REL ((nsync_atomic_uint32_ *) &f->i, old_value, old_value+1)); + ASSERT (nsync_futex_wake_ ((atomic_int *)&f->i, 1, PTHREAD_PROCESS_PRIVATE) >= 0); +} diff --git a/third_party/nsync/mu_semaphore_sem.c b/third_party/nsync/mu_semaphore_sem.c new file mode 100644 index 000000000..693eb0683 --- /dev/null +++ b/third_party/nsync/mu_semaphore_sem.c @@ -0,0 +1,102 @@ +/*-*- 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/assert.h" +#include "libc/calls/cp.internal.h" +#include "libc/calls/struct/timespec.internal.h" +#include "libc/calls/syscall-sysv.internal.h" +#include "libc/dce.h" +#include "libc/errno.h" +#include "libc/intrin/strace.internal.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/f.h" +#include "third_party/nsync/mu_semaphore.h" +#include "third_party/nsync/time.h" +// clang-format off + +#define ASSERT(x) _npassert(x) + +struct sem { + int64_t id; +}; + +static nsync_semaphore *sem_big_enough_for_sem = (nsync_semaphore *) (uintptr_t)(1 / + (sizeof (struct sem) <= sizeof (*sem_big_enough_for_sem))); + +/* Initialize *s; the initial value is 0. */ +void nsync_mu_semaphore_init_sem (nsync_semaphore *s) { + int newfd; + struct sem *f = (struct sem *) s; + f->id = 0; + ASSERT (!sys_sem_init (0, &f->id)); + STRACE ("sem_init(0, [%ld]) → 0", f->id); + ASSERT ((newfd = __sys_fcntl (f->id, F_DUPFD_CLOEXEC, 100)) != -1); + ASSERT (!sys_sem_destroy (f->id)); + f->id = newfd; +} + +/* Wait until the count of *s exceeds 0, and decrement it. */ +errno_t nsync_mu_semaphore_p_sem (nsync_semaphore *s) { + int e, rc; + errno_t result; + struct sem *f = (struct sem *) s; + e = errno; + BEGIN_CANCELLATION_POINT; + rc = sys_sem_wait (f->id); + END_CANCELLATION_POINT; + STRACE ("sem_wait(%ld) → %d% m", f->id, rc); + if (!rc) { + result = 0; + } else { + result = errno; + errno = e; + ASSERT (result == ECANCELED); + } + return result; +} + +/* Wait until one of: + the count of *s is non-zero, in which case decrement *s and return 0; + or abs_deadline expires, in which case return ETIMEDOUT. */ +errno_t nsync_mu_semaphore_p_with_deadline_sem (nsync_semaphore *s, nsync_time abs_deadline) { + int e, rc; + errno_t result; + struct sem *f = (struct sem *) s; + e = errno; + BEGIN_CANCELLATION_POINT; + rc = sys_sem_timedwait (f->id, &abs_deadline); + END_CANCELLATION_POINT; + STRACE ("sem_timedwait(%ld, %s) → %d% m", f->id, + DescribeTimespec(0, &abs_deadline), rc); + if (!rc) { + result = 0; + } else { + result = errno; + errno = e; + ASSERT (result == ETIMEDOUT || + result == ECANCELED); + } + return result; +} + +/* Ensure that the count of *s is at least 1. */ +void nsync_mu_semaphore_v_sem (nsync_semaphore *s) { + struct sem *f = (struct sem *) s; + ASSERT (!sys_sem_post (f->id)); + STRACE ("sem_post(%ld) → 0% m", f->id); +} diff --git a/third_party/nsync/testing/mu_wait_test.c b/third_party/nsync/testing/mu_wait_test.c index d5c9e1e4d..a3fab948e 100644 --- a/third_party/nsync/testing/mu_wait_test.c +++ b/third_party/nsync/testing/mu_wait_test.c @@ -16,7 +16,6 @@ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" -#include "libc/intrin/kprintf.h" #include "libc/str/str.h" #include "third_party/nsync/mu.h" #include "third_party/nsync/mu_wait.h" diff --git a/third_party/nsync/yield.c b/third_party/nsync/yield.c index 3314c8101..bf7081c66 100644 --- a/third_party/nsync/yield.c +++ b/third_party/nsync/yield.c @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "third_party/nsync/common.internal.h" // clang-format off diff --git a/tool/build/lib/syscall.c b/tool/build/lib/syscall.c index d51cf082f..b253468cf 100644 --- a/tool/build/lib/syscall.c +++ b/tool/build/lib/syscall.c @@ -24,7 +24,6 @@ #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/rlimit.h" #include "libc/calls/struct/rusage.h" -#include "libc/calls/struct/sigaction-linux.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/stat.h" #include "libc/calls/struct/sysinfo.h" diff --git a/tool/net/echo.c b/tool/net/echo.c index 434e9625b..2631bb963 100644 --- a/tool/net/echo.c +++ b/tool/net/echo.c @@ -29,6 +29,7 @@ #include "libc/sysv/consts/ipproto.h" #include "libc/sysv/consts/sock.h" #include "net/http/http.h" +#include "net/http/ip.h" /** * @fileoverview tcp/udp echo servers/clients