Compare commits

...
13 Commits
Author SHA1 Message Date
Justine Tunney 17a85e4790 Release Cosmopolitan v3.9.3 2024-10-08 19:58:32 -07:00
Justine Tunney ad11fc32ad Avoid an --ftrace crash on Windows 2024-10-07 18:39:25 -07:00
Justine Tunney dcf9596620 Make more fixups and quality assurance 2024-10-07 15:29:53 -07:00
Justine Tunney 85c58be942 Fix an async signal delivery flake on Windows 2024-10-02 04:55:06 -07:00
Justine Tunney e4d6eb382a Make memchr() and memccpy() faster 2024-09-30 05:54:34 -07:00
Justine Tunney fef24d622a Work around copy_file_range() bug in eCryptFs
When programs like ar.ape and compile.ape are run on eCryptFs partitions
on Linux, copy_file_range() will fail with EINVAL which is wrong because
eCryptFs which doesn't support this system call, should raise EOPNOTSUPP

See https://github.com/jart/cosmopolitan/discussions/1305
2024-09-29 16:35:38 -07:00
Justine Tunney 12cc2de22e Make contended mutexes 30% faster on aarch64
On Raspberry Pi 5, benchmark_mu_contended takes 359µs in *NSYNC upstream
and in Cosmopolitan it takes 272µs.
2024-09-26 09:24:25 -07:00
Justine Tunney 70603fa6ea Fix makedev() prototype
Fixes #1281
2024-09-26 04:42:41 -07:00
Justine Tunney 9255113011 Delete some magic numbers 2024-09-26 04:27:51 -07:00
Gabriel Ravier 333c3d1f0a Add the uppercase B conversion specifier to printf (#1300)
The (uppercase) B conversion specifier is specified by the C standard to
have the same behavior as the (lowercase) b conversion specifier, except
that whenever the # flag is used, the (uppercase) B conversion specifier
alters a nonzero result by prefixing it with "0B", instead of with "0b".

This commit adds this conversion specifier alongside a few tests for it.
2024-09-26 04:27:45 -07:00
Justine Tunney 518eabadf5 Further optimize poll() on Windows 2024-09-22 22:28:59 -07:00
Justine Tunney 556a294363 Improve Windows mode bits
We were too zealous about security before by only setting the owner bits
and that would cause issues for projects like redbean that check "other"
bits to determine if it's safe to serve a file. Since that doesn't exist
on Windows, it's better to have things work than not work. So what we'll
do instead is return modes like 0664 for files and 0775 for directories.
2024-09-22 16:51:57 -07:00
Justine Tunney 80804ccfff Upgrade to cosmocc v3.9.2 2024-09-22 03:57:35 -07:00
123 changed files with 606 additions and 716 deletions

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
{
"C_Cpp.default.compilerPath": ".cosmocc/3.8.0/bin/aarch64-linux-cosmo-c++",
"C_Cpp.default.compilerPath": ".cosmocc/3.9.2/bin/aarch64-linux-cosmo-c++",
"C_Cpp.default.compilerArgs": [
"-nostdinc",
"-nostdlib",
+53 -55
View File
@@ -147,10 +147,10 @@ export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
COSMOCC = .cosmocc/3.8.0
COSMOCC = .cosmocc/3.9.2
BOOTSTRAP = $(COSMOCC)/bin
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.8.0 813c6b2f95062d2e0a845307a79505424cb98cb038e8013334f8a22e3b92a474)
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.9.2 f4ff13af65fcd309f3f1cfd04275996fb7f72a4897726628a8c9cf732e850193)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
@@ -433,64 +433,62 @@ loc: o/$(MODE)/tool/build/summy
find -name \*.h -or -name \*.hpp -or -name \*.c -or -name \*.cc -or -name \*.cpp -or -name \*.S -or -name \*.mk | \
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
# FROM HIGHEST LEVEL TO LOWEST LEVEL
COSMOPOLITAN_OBJECTS = \
COSMOPOLITAN = \
CTL \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_OPENMP \
TOOL_ARGS \
NET_HTTP \
DSP_AUDIO \
LIBC_SOCK \
LIBC_NT_WS2_32 \
LIBC_NT_IPHLPAPI \
LIBC_X \
THIRD_PARTY_GETOPT \
LIBC_LOG \
THIRD_PARTY_TZ \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
LIBC_STDIO \
THIRD_PARTY_GDTOA \
THIRD_PARTY_REGEX \
LIBC_THREAD \
LIBC_PROC \
THIRD_PARTY_NSYNC_MEM \
LIBC_MEM \
THIRD_PARTY_DLMALLOC \
LIBC_DLOPEN \
LIBC_RUNTIME \
THIRD_PARTY_NSYNC \
LIBC_ELF \
LIBC_IRQ \
LIBC_CALLS \
LIBC_SYSV_CALLS \
LIBC_VGA \
LIBC_NT_REALTIME \
LIBC_NT_PSAPI \
LIBC_NT_POWRPROF \
LIBC_NT_PDH \
LIBC_NT_GDI32 \
LIBC_NT_COMDLG32 \
LIBC_NT_USER32 \
LIBC_NT_NTDLL \
LIBC_NT_ADVAPI32 \
LIBC_NT_SYNCHRONIZATION \
LIBC_DLOPEN \
LIBC_ELF \
LIBC_FMT \
THIRD_PARTY_ZLIB \
THIRD_PARTY_PUFF \
THIRD_PARTY_COMPILER_RT \
LIBC_TINYMATH \
THIRD_PARTY_XED \
LIBC_INTRIN \
LIBC_IRQ \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_BCRYPTPRIMITIVES \
LIBC_NT_COMDLG32 \
LIBC_NT_GDI32 \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_PDH \
LIBC_NT_POWRPROF \
LIBC_NT_PSAPI \
LIBC_NT_REALTIME \
LIBC_NT_SYNCHRONIZATION \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_INTRIN \
LIBC_NT_BCRYPTPRIMITIVES \
LIBC_NT_KERNEL32 \
LIBC_NEXGEN32E
LIBC_SYSV_CALLS \
LIBC_THREAD \
LIBC_TINYMATH \
LIBC_VGA \
LIBC_X \
NET_HTTP \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_OPENMP \
THIRD_PARTY_PUFF \
THIRD_PARTY_REGEX \
THIRD_PARTY_TZ \
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \
THIRD_PARTY_ZLIB_GZ \
TOOL_ARGS \
COSMOPOLITAN_H_PKGS = \
APE \
@@ -538,7 +536,7 @@ COSMOCC_PKGS = \
THIRD_PARTY_INTEL
o/$(MODE)/cosmopolitan.a: \
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
$(call uniq,$(foreach x,$(COSMOPOLITAN),$($(x))))
COSMOCC_HDRS = \
$(wildcard libc/integral/*) \
+8 -8
View File
@@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then
fi
find_objdump() {
if [ -x .cosmocc/3.8.0/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=.cosmocc/3.8.0/bin/$1-linux-cosmo-objdump
elif [ -x .cosmocc/3.8.0/bin/$1-linux-musl-objdump ]; then
OBJDUMP=.cosmocc/3.8.0/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/.cosmocc/3.8.0/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.8.0/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/.cosmocc/3.8.0/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.8.0/bin/$1-linux-musl-objdump"
if [ -x .cosmocc/3.9.2/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump
elif [ -x .cosmocc/3.9.2/bin/$1-linux-musl-objdump ]; then
OBJDUMP=.cosmocc/3.9.2/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/.cosmocc/3.9.2/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.9.2/bin/$1-linux-musl-objdump"
else
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
exit 1
+2
View File
@@ -83,9 +83,11 @@ static void copy_file_range_init(void) {
* @return number of bytes transferred, or -1 w/ errno
* @raise EXDEV if source and destination are on different filesystems
* @raise EBADF if `infd` or `outfd` aren't open files or append-only
* @raise EOPNOTSUPP if filesystem doesn't support this operation
* @raise EPERM if `fdout` refers to an immutable file on Linux
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EINVAL if ranges overlap or `flags` is non-zero
* @raise EINVAL on eCryptFs filesystems that have a bug
* @raise EFBIG if `setrlimit(RLIMIT_FSIZE)` is exceeded
* @raise EFAULT if one of the pointers memory is bad
* @raise ERANGE if overflow happens computing ranges
+8 -13
View File
@@ -122,34 +122,29 @@ textwindows int sys_fstat_nt_handle(int64_t handle, const char16_t *path,
st.st_blksize = 4096;
st.st_gid = st.st_uid = sys_getuid_nt();
// We'll use the "umask" to fake out the mode bits.
uint32_t umask = atomic_load_explicit(&__umask, memory_order_acquire);
switch (GetFileType(handle)) {
case kNtFileTypeUnknown:
break;
case kNtFileTypeChar:
st.st_mode = S_IFCHR | (0666 & ~umask);
st.st_mode = S_IFCHR | 0664;
st.st_dev = 0x66666666;
st.st_ino = handle;
break;
case kNtFileTypePipe:
st.st_mode = S_IFIFO | (0666 & ~umask);
st.st_mode = S_IFIFO | 0664;
st.st_dev = 0x55555555;
st.st_ino = handle;
break;
case kNtFileTypeDisk: {
struct NtByHandleFileInformation wst;
if (GetFileInformationByHandle(handle, &wst)) {
st.st_mode = 0444 & ~umask;
st.st_mode = 0444;
if ((wst.dwFileAttributes & kNtFileAttributeDirectory) ||
IsWindowsExecutable(handle, path)) {
st.st_mode |= 0111 & ~umask;
}
IsWindowsExecutable(handle, path))
st.st_mode |= 0111;
st.st_flags = wst.dwFileAttributes;
if (!(wst.dwFileAttributes & kNtFileAttributeReadonly)) {
st.st_mode |= 0222 & ~umask;
}
if (!(wst.dwFileAttributes & kNtFileAttributeReadonly))
st.st_mode |= 0220;
if (wst.dwFileAttributes & kNtFileAttributeReparsePoint) {
st.st_mode |= S_IFLNK;
} else if (wst.dwFileAttributes & kNtFileAttributeDirectory) {
@@ -195,7 +190,7 @@ textwindows int sys_fstat_nt_handle(int64_t handle, const char16_t *path,
} else if (GetVolumeInformationByHandle(
handle, 0, 0, &wst.dwVolumeSerialNumber, 0, 0, 0, 0)) {
st.st_dev = wst.dwVolumeSerialNumber;
st.st_mode = S_IFDIR | (0444 & ~umask);
st.st_mode = S_IFDIR | 0555;
} else {
// both GetFileInformationByHandle and
// GetVolumeInformationByHandle failed
-1
View File
@@ -21,7 +21,6 @@
#include "libc/dce.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
/**
+2
View File
@@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_
#define COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_
COSMOPOLITAN_C_START_
uint64_t makedev(uint32_t, uint32_t) libcesque;
uint32_t major(uint64_t) libcesque;
@@ -9,4 +10,5 @@ uint32_t minor(uint64_t) libcesque;
#define minor(x) minor(x)
#define makedev(x, y) makedev(x, y)
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_ */
+1 -1
View File
@@ -57,7 +57,7 @@ textwindows static int _park_thread(uint32_t msdelay, sigset_t waitmask,
CloseHandle(sigev);
// recursion is now safe
if (ws == -1)
if (ws == -1u)
return __winerr();
int handler_was_called = 0;
if (sig)
-3
View File
@@ -56,7 +56,6 @@ static textwindows int sys_pipe_nt_impl(int pipefd[2], unsigned flags) {
__fds_unlock();
hin = CreateNamedPipe(pipename, kNtPipeAccessInbound | kNtFileFlagOverlapped,
mode, 1, PIPE_BUF, PIPE_BUF, 0, &kNtIsInheritable);
__fds_lock();
if (hin != -1) {
if ((hout = CreateFile(
pipename, kNtGenericWrite,
@@ -73,7 +72,6 @@ static textwindows int sys_pipe_nt_impl(int pipefd[2], unsigned flags) {
g_fds.p[writer].handle = hout;
pipefd[0] = reader;
pipefd[1] = writer;
__fds_unlock();
return 0;
} else {
CloseHandle(hin);
@@ -81,7 +79,6 @@ static textwindows int sys_pipe_nt_impl(int pipefd[2], unsigned flags) {
}
__releasefd(writer);
__releasefd(reader);
__fds_unlock();
return -1;
}
+37 -14
View File
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/sigset.internal.h"
@@ -25,6 +26,7 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/fds.h"
#include "libc/intrin/weaken.h"
#include "libc/macros.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/filetype.h"
@@ -41,6 +43,7 @@
#include "libc/sock/internal.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/posixthread.internal.h"
#ifdef __x86_64__
@@ -84,7 +87,7 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds,
struct PosixThread *pt;
int i, rc, ev, kind, gotsocks;
struct sys_pollfd_nt sockfds[64];
uint32_t cm, fi, wi, sn, pn, avail, waitfor, already_slept;
uint32_t cm, fi, sn, pn, avail, waitfor, already_slept;
// ensure revents is cleared
for (i = 0; i < nfds; ++i)
@@ -228,22 +231,36 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds,
// this ensures low latency for apps like emacs which with no sock
// here we shall actually report that something can be written too
if (!already_slept) {
if (__sigcheck(waitmask, false))
return -1;
intptr_t sigev;
if (!(sigev = CreateEvent(0, 0, 0, 0)))
return __winerr();
filehands[pn] = sigev;
pt = _pthread_self();
filehands[pn] = pt->pt_event = CreateEvent(0, 0, 0, 0);
pt->pt_event = sigev;
pt->pt_blkmask = waitmask;
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_EVENT,
memory_order_release);
wi = WaitForMultipleObjects(pn + 1, filehands, 0, waitfor);
//!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!//
int sig = 0;
uint32_t wi = pn;
if (!_is_canceled() &&
!(_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))))
wi = WaitForMultipleObjects(pn + 1, filehands, 0, waitfor);
//!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!//
atomic_store_explicit(&pt->pt_blocker, 0, memory_order_release);
CloseHandle(filehands[pn]);
if (wi == -1u) {
CloseHandle(sigev);
if (wi == -1u)
// win32 wait failure
return __winerr();
} else if (wi == pn) {
if (wi == pn) {
// our signal event was signalled
if (__sigcheck(waitmask, false))
int handler_was_called = 0;
if (sig)
handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask);
if (_check_cancel() == -1)
return -1;
if (handler_was_called)
return eintr();
} else if ((wi ^ kNtWaitAbandoned) < pn) {
// this is possibly because a process or thread was killed
fds[fileindices[wi ^ kNtWaitAbandoned]].revents = POLLERR_;
@@ -287,8 +304,6 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds,
} else {
// should only be possible on kNtWaitTimeout or semaphore abandoned
// keep looping for events and we'll catch timeout when appropriate
if (__sigcheck(waitmask, false))
return -1;
}
}
@@ -306,6 +321,13 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
uint32_t waitms;
int i, n, rc, got = 0;
// we normally don't check for signals until we decide to wait, since
// it's nice to have functions like write() be unlikely to EINTR, but
// ppoll is a function where users are surely thinking about signals,
// since ppoll actually allows them to block signals everywhere else.
if (__sigcheck(waitmask, false))
return -1;
// fast path
if (nfds <= 63)
return sys_poll_nt_actual(fds, nfds, deadline, waitmask);
@@ -329,13 +351,14 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
}
}
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds,
const struct timespec *relative,
const sigset_t *sigmask) {
int rc;
struct timespec now, timeout, deadline;
BLOCK_SIGNALS;
now = ms ? sys_clock_gettime_monotonic_nt() : timespec_zero;
timeout = ms ? timespec_frommillis(*ms) : timespec_max;
now = relative ? sys_clock_gettime_monotonic_nt() : timespec_zero;
timeout = relative ? *relative : timespec_max;
deadline = timespec_add(now, timeout);
rc = sys_poll_nt_impl(fds, nfds, deadline, sigmask ? *sigmask : _SigMask);
ALLOW_SIGNALS;
+8 -12
View File
@@ -25,6 +25,7 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.h"
#include "libc/limits.h"
#include "libc/runtime/stack.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
@@ -76,10 +77,13 @@ static int ppoll_impl(struct pollfd *fds, size_t nfds,
}
fdcount = sys_ppoll(fds, nfds, tsp, sigmask, 8);
if (fdcount == -1 && errno == ENOSYS) {
int ms;
int64_t ms;
errno = e;
if (!timeout || ckd_add(&ms, timeout->tv_sec,
(timeout->tv_nsec + 999999) / 1000000)) {
if (timeout) {
ms = timespec_tomillis(*timeout);
if (ms > INT_MAX)
ms = -1;
} else {
ms = -1;
}
if (sigmask)
@@ -89,15 +93,7 @@ static int ppoll_impl(struct pollfd *fds, size_t nfds,
sys_sigprocmask(SIG_SETMASK, &oldmask, 0);
}
} else {
uint32_t ms;
uint32_t *msp;
if (timeout &&
!ckd_add(&ms, timeout->tv_sec, (timeout->tv_nsec + 999999) / 1000000)) {
msp = &ms;
} else {
msp = 0;
}
fdcount = sys_poll_nt(fds, nfds, msp, sigmask);
fdcount = sys_poll_nt(fds, nfds, timeout, sigmask);
}
if (IsOpenbsd() && fdcount != -1) {
+4 -12
View File
@@ -67,7 +67,6 @@
int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
const struct timespec *timeout, const sigset_t *sigmask) {
int rc;
struct timeval tv, *tvp;
struct timespec ts, *tsp;
struct {
const sigset_t *s;
@@ -111,24 +110,17 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
rc = sys_pselect(nfds, readfds, writefds, exceptfds,
(struct timespec *)timeout, sigmask);
} else {
if (timeout) {
tv.tv_sec = timeout->tv_sec;
tv.tv_usec = timeout->tv_nsec / 1000;
tvp = &tv;
} else {
tvp = 0;
}
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, tvp, sigmask);
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, timeout, sigmask);
}
}
END_CANCELATION_POINT;
STRACE("pselect(%d, %s → [%s], %s → [%s], %s → [%s], %s, %s) → %d% m", nfds,
DescribeFdSet(rc, nfds, old_readfds_ptr),
DescribeFdSet(0, nfds, old_readfds_ptr),
DescribeFdSet(rc, nfds, readfds),
DescribeFdSet(rc, nfds, old_writefds_ptr),
DescribeFdSet(0, nfds, old_writefds_ptr),
DescribeFdSet(rc, nfds, writefds),
DescribeFdSet(rc, nfds, old_exceptfds_ptr),
DescribeFdSet(0, nfds, old_exceptfds_ptr),
DescribeFdSet(rc, nfds, exceptfds), //
DescribeTimespec(0, timeout), //
DescribeSigset(0, sigmask), rc);
+2 -20
View File
@@ -25,7 +25,6 @@
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/errfuns.h"
#ifdef __x86_64__
@@ -44,7 +43,7 @@
// </sync libc/sysv/consts.sh>
int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask) {
int pfds = 0;
@@ -68,21 +67,8 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
}
}
// convert the wait time to a word
uint32_t millis;
if (!timeout) {
millis = -1u;
} else {
int64_t ms = timeval_tomillis(*timeout);
if (ms < 0 || ms > UINT32_MAX) {
millis = -1u;
} else {
millis = ms;
}
}
// call our nt poll implementation
int fdcount = sys_poll_nt(fds, pfds, &millis, sigmask);
int fdcount = sys_poll_nt(fds, pfds, timeout, sigmask);
if (fdcount == -1)
return -1;
@@ -115,10 +101,6 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
}
}
// store remaining time back in caller's timeval
if (timeout)
*timeout = timeval_frommillis(millis);
return bits;
}
+1 -4
View File
@@ -31,10 +31,7 @@
* such as out-of-band data on a socket; it is equivalent to POLLPRI
* in the revents of poll()
* @param timeout may be null which means to block indefinitely; cosmo's
* implementation of select() never modifies this parameter which is
* how most platforms except Linux work which modifies it to reflect
* elapsed time, noting that POSIX permits either behavior therefore
* portable code should assume that timeout memory becomes undefined
* implementation of select() never modifies this parameter
* @raise E2BIG if we exceeded the 64 socket limit on Windows
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EINTR if signal was delivered
-1
View File
@@ -21,7 +21,6 @@
#include "libc/dce.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
/**
+82 -27
View File
@@ -136,21 +136,22 @@ static textwindows wontreturn void __sig_terminate(int sig) {
TerminateThisProcess(sig);
}
textwindows static void __sig_wake(struct PosixThread *pt, int sig) {
textwindows static bool __sig_wake(struct PosixThread *pt, int sig) {
atomic_int *blocker;
blocker = atomic_load_explicit(&pt->pt_blocker, memory_order_acquire);
if (!blocker)
return;
return false;
// threads can create semaphores on an as-needed basis
if (blocker == PT_BLOCKER_EVENT) {
STRACE("%G set %d's event object", sig, _pthread_tid(pt));
SetEvent(pt->pt_event);
return;
return !!atomic_load_explicit(&pt->pt_blocker, memory_order_acquire);
}
// all other blocking ops that aren't overlap should use futexes
// we force restartable futexes to churn by waking w/o releasing
STRACE("%G waking %d's futex", sig, _pthread_tid(pt));
WakeByAddressSingle(blocker);
return !!atomic_load_explicit(&pt->pt_blocker, memory_order_acquire);
}
textwindows static bool __sig_start(struct PosixThread *pt, int sig,
@@ -302,17 +303,48 @@ static textwindows int __sig_killer(struct PosixThread *pt, int sig, int sic) {
return 0;
}
// we can't preempt threads that masked sigs or are blocked. we also
// need to ensure we don't overflow the target thread's stack if many
// signals need to be delivered at once. we also need to make sure two
// threads can't deadlock by killing each other at the same time.
if ((atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire) &
(1ull << (sig - 1))) ||
atomic_exchange_explicit(&pt->pt_intoff, 1, memory_order_acquire)) {
atomic_fetch_or_explicit(&pt->tib->tib_sigpending, 1ull << (sig - 1),
memory_order_relaxed);
__sig_wake(pt, sig);
return 0;
// we can't preempt threads that masked sigs or are blocked on i/o
while ((atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire) &
(1ull << (sig - 1)))) {
if (atomic_fetch_or_explicit(&pt->tib->tib_sigpending, 1ull << (sig - 1),
memory_order_acq_rel) &
(1ull << (sig - 1)))
// we believe signal was already enqueued
return 0;
if (__sig_wake(pt, sig))
// we believe i/o routine will handle signal
return 0;
if (atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire) &
(1ull << (sig - 1)))
// we believe ALLOW_SIGNALS will handle signal
return 0;
if (!(atomic_fetch_and_explicit(&pt->tib->tib_sigpending,
~(1ull << (sig - 1)),
memory_order_acq_rel) &
(1ull << (sig - 1))))
// we believe another thread sniped our signal
return 0;
break;
}
// avoid race conditions and deadlocks with thread suspend process
if (atomic_exchange_explicit(&pt->pt_intoff, 1, memory_order_acquire)) {
// we believe another thread is asynchronously waking the mark
if (atomic_fetch_or_explicit(&pt->tib->tib_sigpending, 1ull << (sig - 1),
memory_order_acq_rel) &
(1ull << (sig - 1)))
// we believe our signal is already being delivered
return 0;
if (atomic_load_explicit(&pt->pt_intoff, memory_order_acquire) ||
atomic_exchange_explicit(&pt->pt_intoff, 1, memory_order_acquire))
// we believe __sig_tramp will deliver our signal
return 0;
if (!(atomic_fetch_and_explicit(&pt->tib->tib_sigpending,
~(1ull << (sig - 1)),
memory_order_acq_rel) &
(1ull << (sig - 1))))
// we believe another thread sniped our signal
return 0;
}
// if there's no handler then killing a thread kills the process
@@ -321,17 +353,10 @@ static textwindows int __sig_killer(struct PosixThread *pt, int sig, int sic) {
__sig_terminate(sig);
}
// ignore signals already pending
uintptr_t th = _pthread_syshand(pt);
if (atomic_load_explicit(&pt->tib->tib_sigpending, memory_order_acquire) &
(1ull << (sig - 1))) {
atomic_store_explicit(&pt->pt_intoff, 0, memory_order_release);
return 0;
}
// take control of thread
// suspending the thread happens asynchronously
// however getting the context blocks until it's frozen
uintptr_t th = _pthread_syshand(pt);
if (SuspendThread(th) == -1u) {
STRACE("SuspendThread failed w/ %d", GetLastError());
atomic_store_explicit(&pt->pt_intoff, 0, memory_order_release);
@@ -349,9 +374,7 @@ static textwindows int __sig_killer(struct PosixThread *pt, int sig, int sic) {
// we can't preempt threads that masked sig or are blocked
// we can't preempt threads that are running in win32 code
// so we shall unblock the thread and let it signal itself
if ((atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire) &
(1ull << (sig - 1))) ||
!((uintptr_t)__executable_start <= nc.Rip &&
if (!((uintptr_t)__executable_start <= nc.Rip &&
nc.Rip < (uintptr_t)__privileged_start)) {
atomic_fetch_or_explicit(&pt->tib->tib_sigpending, 1ull << (sig - 1),
memory_order_relaxed);
@@ -424,7 +447,6 @@ textwindows void __sig_generate(int sig, int sic) {
(1ull << (sig - 1))) {
return;
}
BLOCK_SIGNALS;
_pthread_lock();
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
pt = POSIXTHREAD_CONTAINER(e);
@@ -462,7 +484,6 @@ textwindows void __sig_generate(int sig, int sic) {
atomic_fetch_or_explicit(__sig.process, 1ull << (sig - 1),
memory_order_relaxed);
}
ALLOW_SIGNALS;
}
static textwindows char *__sig_stpcpy(char *d, const char *s) {
@@ -636,6 +657,7 @@ textwindows dontinstrument static uint32_t __sig_worker(void *arg) {
__maps_track((char *)(((uintptr_t)sp + __pagesize - 1) & -__pagesize) - STKSZ,
STKSZ);
for (;;) {
// dequeue all pending signals and fire them off. if there's no
// thread that can handle them then __sig_generate will requeue
// those signals back to __sig.process; hence the need for xchg
@@ -646,6 +668,39 @@ textwindows dontinstrument static uint32_t __sig_worker(void *arg) {
sigs &= ~(1ull << (sig - 1));
__sig_generate(sig, SI_KERNEL);
}
// unblock stalled asynchronous signals in threads
_pthread_lock();
for (struct Dll *e = dll_first(_pthread_list); e;
e = dll_next(_pthread_list, e)) {
struct PosixThread *pt = POSIXTHREAD_CONTAINER(e);
if (atomic_load_explicit(&pt->pt_status, memory_order_acquire) >=
kPosixThreadTerminated) {
break;
}
sigset_t pending =
atomic_load_explicit(&pt->tib->tib_sigpending, memory_order_acquire);
sigset_t mask =
atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire);
if (pending & ~mask) {
_pthread_ref(pt);
_pthread_unlock();
while (!atomic_compare_exchange_weak_explicit(
&pt->tib->tib_sigpending, &pending, pending & ~mask,
memory_order_acq_rel, memory_order_relaxed)) {
}
while ((pending = pending & ~mask)) {
int sig = bsfl(pending) + 1;
pending &= ~(1ull << (sig - 1));
__sig_killer(pt, sig, SI_KERNEL);
}
_pthread_lock();
_pthread_unref(pt);
}
}
_pthread_unlock();
// wait until next scheduler quantum
Sleep(POLL_INTERVAL_MS);
}
return 0;
+1 -1
View File
@@ -4,7 +4,7 @@
#define __COSMOPOLITAN_MAJOR__ 3
#define __COSMOPOLITAN_MINOR__ 9
#define __COSMOPOLITAN_PATCH__ 2
#define __COSMOPOLITAN_PATCH__ 3
#define __COSMOPOLITAN__ \
(100000000 * __COSMOPOLITAN_MAJOR__ + 1000000 * __COSMOPOLITAN_MINOR__ + \
__COSMOPOLITAN_PATCH__)
+2
View File
@@ -31,6 +31,8 @@ const char *_DescribeFdSet(char buf[N], ssize_t rc, int nfds, fd_set *fds) {
if (!fds)
return "NULL";
if (rc == -1)
return "n/a";
if (kisdangerous(fds)) {
ksnprintf(buf, N, "%p", fds);
return buf;
+19 -6
View File
@@ -40,9 +40,11 @@
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h"
#include "libc/nt/errors.h"
#include "libc/nt/events.h"
#include "libc/nt/files.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.internal.h"
@@ -113,10 +115,13 @@
}
// clang-format off
__msabi extern typeof(CloseHandle) *const __imp_CloseHandle;
__msabi extern typeof(CreateEvent) *const __imp_CreateEventW;
__msabi extern typeof(CreateFile) *const __imp_CreateFileW;
__msabi extern typeof(DuplicateHandle) *const __imp_DuplicateHandle;
__msabi extern typeof(GetEnvironmentVariable) *const __imp_GetEnvironmentVariableW;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
__msabi extern typeof(GetOverlappedResult) *const __imp_GetOverlappedResult;
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
__msabi extern typeof(SetLastError) *const __imp_SetLastError;
__msabi extern typeof(WriteFile) *const __imp_WriteFile;
@@ -283,7 +288,7 @@ privileged long kloghandle(void) {
hand = __imp_CreateFileW(
path, kNtFileAppendData,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
kNtOpenAlways, kNtFileAttributeNormal, 0);
kNtOpenAlways, kNtFileAttributeNormal | kNtFileFlagOverlapped, 0);
} else {
hand = -1; // KPRINTF_LOG was empty string or too long
}
@@ -359,7 +364,6 @@ privileged void _klog_serial(const char *b, size_t n) {
privileged void klog(const char *b, size_t n) {
#ifdef __x86_64__
int e;
long h;
uint32_t wrote;
long rax, rdi, rsi, rdx;
@@ -367,11 +371,20 @@ privileged void klog(const char *b, size_t n) {
return;
}
if (IsWindows()) {
e = __imp_GetLastError();
if (!__imp_WriteFile(h, b, n, &wrote, 0)) {
__imp_SetLastError(e);
__klog_handle = 0;
bool32 ok;
intptr_t ev;
int e = __imp_GetLastError();
if ((ev = __imp_CreateEventW(0, 0, 0, 0))) {
struct NtOverlapped overlap = {.hEvent = ev};
ok = !!__imp_WriteFile(h, b, n, 0, &overlap);
if (!ok && __imp_GetLastError() == kNtErrorIoPending)
ok = true;
ok &= !!__imp_GetOverlappedResult(h, &overlap, &wrote, true);
if (!ok)
__klog_handle = 0;
__imp_CloseHandle(ev);
}
__imp_SetLastError(e);
} else if (IsMetal()) {
if (_weaken(_klog_vga)) {
_weaken(_klog_vga)(b, n);
+22 -17
View File
@@ -19,10 +19,10 @@
#include "libc/dce.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/str.h"
#include "third_party/aarch64/arm_neon.internal.h"
#include "third_party/intel/immintrin.internal.h"
#ifndef __aarch64__
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
static inline const unsigned char *memchr_pure(const unsigned char *s,
unsigned char c, size_t n) {
size_t i;
@@ -35,22 +35,27 @@ static inline const unsigned char *memchr_pure(const unsigned char *s,
}
#if defined(__x86_64__) && !defined(__chibicc__)
static __vex const unsigned char *memchr_sse(const unsigned char *s,
unsigned char c, size_t n) {
size_t i;
unsigned m;
xmm_t v, t = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
for (; n >= 16; n -= 16, s += 16) {
v = *(const xmm_t *)s;
m = __builtin_ia32_pmovmskb128(v == t);
if (m) {
m = __builtin_ctzll(m);
return s + m;
}
static const char *memchr_sse(const char *s, char c, size_t n) {
const char *e = s + n;
__m128i t = _mm_set1_epi8(c);
unsigned m, k = (uintptr_t)s & 15;
m = _mm_movemask_epi8(
_mm_cmpeq_epi8(_mm_load_si128((const __m128i *)((uintptr_t)s & -16)), t));
m >>= k;
if (m) {
s += __builtin_ctz(m);
if (s < e)
return s;
return 0;
}
for (i = 0; i < n; ++i) {
if (s[i] == c) {
return s + i;
for (s += 16 - k; s < e; s += 16) {
m = _mm_movemask_epi8(
_mm_cmpeq_epi8(_mm_load_si128((const __m128i *)s), t));
if (m) {
s += __builtin_ctz(m);
if (s < e)
return s;
return 0;
}
}
return 0;
+1 -1
View File
@@ -19,4 +19,4 @@
#include "libc/atomic.h"
#include "libc/calls/internal.h"
atomic_int __umask;
atomic_int __umask = 0777;
+3
View File
@@ -17,5 +17,8 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/runtime/internal.h"
#ifndef __x86_64__
int __pid;
#endif
+5 -8
View File
@@ -102,14 +102,14 @@ textwindows int __proc_harvest(struct Proc *pr, bool iswait4) {
pr->handle = status & 0x00FFFFFF;
} else {
// handle child _Exit()
if (status == 0xc9af3d51u) {
if (status == 0xc9af3d51u)
status = kNtStillActive;
}
pr->wstatus = status;
if (!iswait4 && !pr->waiters && !__proc.waiters &&
(__sighandrvas[SIGCHLD] == (uintptr_t)SIG_IGN ||
(__sighandflags[SIGCHLD] & SA_NOCLDWAIT))) {
// perform automatic zombie reaping
STRACE("automatically reaping zombie");
dll_remove(&__proc.list, &pr->elem);
dll_make_first(&__proc.free, &pr->elem);
CloseHandle(pr->handle);
@@ -192,9 +192,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
continue;
if (j == i)
continue;
if (!--objects[j]->waiters && objects[j]->status == PROC_UNDEAD) {
if (!--objects[j]->waiters && objects[j]->status == PROC_UNDEAD)
__proc_free(objects[j]);
}
}
// check if we need to churn due to >64 processes
@@ -219,9 +218,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
case PROC_ZOMBIE:
break;
case PROC_UNDEAD:
if (!objects[i]->waiters) {
if (!objects[i]->waiters)
__proc_free(objects[i]);
}
break;
default:
__builtin_unreachable();
@@ -233,9 +231,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
// 1. wait4() is being used
// 2. SIGCHLD has SIG_IGN handler
// 3. SIGCHLD has SA_NOCLDWAIT flag
if (sic) {
if (sic)
__sig_generate(SIGCHLD, sic);
}
}
return 0;
}
+3 -2
View File
@@ -106,8 +106,9 @@ static long AlignStack(long sp, char *stk, long stksz, int mal) {
////////////////////////////////////////////////////////////////////////////////
// THE NEW TECHNOLOGY
__msabi extern typeof(TlsSetValue) *const __imp_TlsSetValue;
__msabi extern typeof(ExitThread) *const __imp_ExitThread;
__msabi extern typeof(GetCurrentThreadId) *const __imp_GetCurrentThreadId;
__msabi extern typeof(TlsSetValue) *const __imp_TlsSetValue;
__msabi extern typeof(WakeByAddressAll) *const __imp_WakeByAddressAll;
static textwindows dontinstrument wontreturn void //
@@ -118,7 +119,7 @@ WinThreadEntry(int rdi, // rcx
int rc;
if (wt->tls)
__set_tls_win32(wt->tls);
*wt->ctid = GetCurrentThreadId();
*wt->ctid = __imp_GetCurrentThreadId();
rc = __stack_call(wt->arg, wt->tid, 0, 0, wt->func, wt->sp);
// we can now clear ctid directly since we're no longer using our own
// stack memory, which can now be safely free'd by the parent thread.
+2 -3
View File
@@ -69,9 +69,8 @@ uintptr_t GetStackBottom(void) pureconst;
* will also trigger the stack to grow down safely.
*/
forceinline void CheckLargeStackAllocation(void *p, ssize_t n) {
for (; n > 0; n -= 4096) {
((char *)p)[n - 1] = 0;
}
for (; n > 0; n -= 4096)
((volatile char *)p)[n - 1] = 0;
}
void *NewCosmoStack(void) vallocesque;
-1
View File
@@ -316,7 +316,6 @@ abi int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
__imp_GetSystemInfo(&si);
__pagesize = si.dwPageSize;
__gransize = si.dwAllocationGranularity;
__umask = 077;
__pid = __imp_GetCurrentProcessId();
if (!(__sig.process = __sig_map_process(__pid, kNtOpenAlways)))
__sig.process = &fake_process_signals;
+2 -1
View File
@@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_SOCK_INTERNAL_H_
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
@@ -60,7 +61,7 @@ int sys_socketpair_nt_stream(int, int, int, int[2]) ;
int sys_socketpair_nt_dgram(int, int, int, int[2]) ;
*/
int sys_socketpair_nt(int, int, int, int[2]);
int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *,
int sys_select_nt(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
const sigset_t *);
size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, size_t);
+3 -2
View File
@@ -66,8 +66,9 @@ textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
__sig_unblock(waitmask);
if (rc == -1 && errno == WSAESHUTDOWN) { // ESHUTDOWN
errno = kNtErrorBrokenPipe; // EPIPE
if (rc == -1 && (errno == WSAESHUTDOWN || // ESHUTDOWN
errno == WSAECONNABORTED)) { // ECONNABORTED
errno = kNtErrorBrokenPipe; // EPIPE
if (!(flags & _MSG_NOSIGNAL))
__sig_raise(SIGPIPE, SI_KERNEL);
}
+3 -2
View File
@@ -71,8 +71,9 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
__sig_unblock(waitmask);
if (rc == -1 && errno == WSAESHUTDOWN) { // ESHUTDOWN
errno = kNtErrorBrokenPipe; // EPIPE
if (rc == -1 && (errno == WSAESHUTDOWN || // ESHUTDOWN
errno == WSAECONNABORTED)) { // ECONNABORTED
errno = kNtErrorBrokenPipe; // EPIPE
if (!(flags & _MSG_NOSIGNAL))
__sig_raise(SIGPIPE, SI_KERNEL);
}
+2 -1
View File
@@ -11,7 +11,8 @@ int32_t __sys_poll(struct pollfd *, uint64_t, signed);
int sys_ppoll(struct pollfd *, size_t, const struct timespec *,
const sigset_t *, size_t);
int sys_poll_metal(struct pollfd *, size_t, unsigned);
int sys_poll_nt(struct pollfd *, uint64_t, uint32_t *, const sigset_t *);
int sys_poll_nt(struct pollfd *, uint64_t, const struct timespec *,
const sigset_t *);
const char *_DescribePollFds(char[300], ssize_t, struct pollfd *, size_t);
#define DescribePollFds(x, y, z) _DescribePollFds(alloca(300), x, y, z)
+2 -1
View File
@@ -1090,9 +1090,10 @@ int __fmt(void *fn, void *arg, const char *format, va_list va, int *wrote) {
case 'x':
log2base = 4;
goto FormatNumber;
case 'B':
case 'b':
log2base = 1;
alphabet = "0123456789abcdefpb";
alphabet = (d == 'b' ? "0123456789abcdefpb" : "0123456789ABCDEFPB");
goto FormatNumber;
case 'o':
log2base = 3;
+1 -2
View File
@@ -74,9 +74,8 @@ size_t fwrite_unlocked(const void *data, size_t stride, size_t count, FILE *f) {
size_t n, m;
const char *p;
struct iovec iov[2];
if (!stride || !count) {
if (!stride || !count)
return 0;
}
if ((f->iomode & O_ACCMODE) == O_RDONLY) {
f->state = errno = EBADF;
return 0;
+4 -7
View File
@@ -19,6 +19,7 @@
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/fmt/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/stdckdint.h"
#include "libc/stdio/internal.h"
#include "libc/stdio/stdio.h"
@@ -46,9 +47,8 @@ static int __vfprintf_flbuf(const char *s, struct state *t, size_t n) {
} else {
rc = -1;
}
if (ckd_add(&t->n, t->n, n)) {
if (ckd_add(&t->n, t->n, n))
rc = eoverflow();
}
} else {
rc = 0;
}
@@ -60,9 +60,8 @@ static int __vfprintf_nbuf(const char *s, struct state *t, size_t n) {
for (i = 0; i < n; ++i) {
t->b.p[t->b.n++] = s[i];
if (t->b.n == sizeof(t->b.p)) {
if (!fwrite_unlocked(t->b.p, 1, t->b.n, t->f)) {
if (!fwrite_unlocked(t->b.p, 1, t->b.n, t->f))
return -1;
}
t->b.n = 0;
} else if (ckd_add(&t->n, t->n, 1)) {
return eoverflow();
@@ -91,9 +90,7 @@ int vfprintf_unlocked(FILE *f, const char *fmt, va_list va) {
if (!st.b.n) {
rc = st.n;
} else if (fwrite_unlocked(st.b.p, 1, st.b.n, st.f)) {
if (ckd_add(&rc, st.n, st.b.n)) {
rc = eoverflow();
}
rc = st.n;
} else {
rc = -1;
}
+8 -7
View File
@@ -45,13 +45,14 @@
* @asyncsignalsafe
*/
void *memccpy(void *dst, const void *src, int c, size_t n) {
char *d;
size_t i;
const char *s;
for (d = dst, s = src, i = 0; i < n; ++i) {
if (((d[i] = s[i]) & 255) == (c & 255)) {
return d + i + 1;
}
const char *p;
// this memchr() call is only correct if your memchr() implementation
// offers the same readahead safety guarantees as cosmopolitan's does
if ((p = memchr(src, c, n))) {
size_t m = p + 1 - (const char *)src;
memmove(dst, src, m);
return (char *)dst + m;
}
memmove(dst, src, n);
return 0;
}
+1 -94
View File
@@ -1415,16 +1415,6 @@ syscon shm SHM_NORESERVE 0x1000 0x1000 0 0 0 0 0 0
syscon shm SHM_REMAP 0x4000 0x4000 0 0 0 0 0 0
syscon shm SHM_ANON 0 0 0 0 1 0 0 0
syscon lock LOCK_UNLOCK_CACHE 54 54 0 0 0 0 0 0 # wut
syscon misc IP6F_MORE_FRAG 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 # consensus
syscon misc IP6F_OFF_MASK 0xf8ff 0xf8ff 0xf8ff 0xf8ff 0xf8ff 0xf8ff 0xf8ff 0xf8ff # consensus
syscon misc IP6F_RESERVED_MASK 0x0600 0x0600 0x0600 0x0600 0x0600 0x0600 0x0600 0x0600 # consensus
syscon misc L_SET 0 0 0 0 0 0 0 0 # consensus
syscon misc L_INCR 1 1 1 1 1 1 1 0 # unix consensus
syscon misc L_XTND 2 2 2 2 2 2 2 0 # unix consensus
syscon misc SHUT_RD 0 0 0 0 0 0 0 0 # consensus (SD_RECEIVE)
syscon misc SHUT_WR 1 1 1 1 1 1 1 1 # consensus (SD_SEND)
syscon misc SHUT_RDWR 2 2 2 2 2 2 2 2 # consensus (SD_BOTH)
@@ -1470,11 +1460,6 @@ syscon misc ACCT_COMM 0x10 0x10 0 0 0 0 0 0
syscon misc COMMAND_COMPLETE 0 0 0 0 0 0 0 0 # consensus
syscon misc COMMAND_TERMINATED 17 17 0 0 0 0 0 0
syscon select FD_SETSIZE 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 # forced consensus (0x40 on NT)
syscon misc MATH_ERREXCEPT 2 2 2 2 2 2 2 0 # unix consensus
syscon misc MATH_ERRNO 1 1 1 1 1 1 1 0 # unix consensus
syscon misc MCAST_BLOCK_SOURCE 43 43 84 84 84 0 0 43
syscon misc MCAST_JOIN_GROUP 42 42 80 80 80 0 0 41
syscon misc MCAST_JOIN_SOURCE_GROUP 46 46 82 82 82 0 0 45
@@ -1943,86 +1928,8 @@ syscon junkerr EKEYREJECTED 129 129 -1 -1 -1 -1 -1 -1
syscon junkerr ERFKILL 132 132 -1 -1 -1 -1 -1 -1
syscon junkerr EHWPOISON 133 133 -1 -1 -1 -1 -1 -1
syscon misc FIFOTYPE 54 54 54 54 54 54 54 0 # unix consensus
syscon misc GRPQUOTA 1 1 1 1 1 1 1 0 # unix consensus
syscon misc IF_NAMESIZE 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0 # unix consensus
syscon misc INTERMEDIATE_C_GOOD 10 10 0 0 0 0 0 0
syscon misc INTERMEDIATE_GOOD 8 8 0 0 0 0 0 0
syscon select FD_SETSIZE 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 # forced consensus (0x40 on NT)
syscon misc IOV_MAX 1024 1024 1024 1024 1024 1024 1024 16 # unix consensus & MSG_MAXIOVLEN
syscon misc LINE_MAX 0x0800 0x0800 0x0800 0x0800 0x0800 0x0800 0x0800 0 # unix consensus
syscon misc LINKED_CMD_COMPLETE 10 10 0 0 0 0 0 0
syscon misc LINKED_FLG_CMD_COMPLETE 11 11 0 0 0 0 0 0
syscon misc LNKTYPE 49 49 49 49 49 49 49 0 # unix consensus
syscon misc MAXNAMLEN 255 255 255 255 255 255 255 0 # unix consensus
syscon misc MAXQUOTAS 2 2 2 2 2 2 2 0 # unix consensus
syscon misc MEDIUM_ERROR 3 3 0 0 0 0 0 0
syscon misc MEDIUM_SCAN 56 56 0 0 0 0 0 0
syscon misc NBBY 8 8 8 8 8 8 8 0 # unix consensus
syscon misc NR_DQHASH 43 43 0 0 0 0 0 0
syscon misc NR_DQUOTS 0x0100 0x0100 0 0 0 0 0 0
syscon misc PERSISTENT_RESERVE_IN 94 94 0 0 0 0 0 0
syscon misc PERSISTENT_RESERVE_OUT 95 95 0 0 0 0 0 0
syscon misc PRELIM 1 1 1 1 1 1 1 0 # unix consensus
syscon misc REGTYPE 48 48 48 48 48 48 48 0 # unix consensus
syscon misc RES_PRF_CLASS 4 4 4 4 4 4 4 0 # unix consensus
syscon misc RHF_GUARANTEE_START_INIT 0x80 0x80 0 0 0 0 0 0
syscon misc RHF_NO_LIBRARY_REPLACEMENT 4 4 0 0 0 0 0 0
syscon misc RRQ 1 1 1 1 1 1 1 0 # unix consensus
syscon misc RTF_NOFORWARD 0x1000 0x1000 0 0 0 0 0 0
syscon misc RTF_NOPMTUDISC 0x4000 0x4000 0 0 0 0 0 0
syscon misc SARMAG 8 8 8 8 8 8 8 0 # unix consensus
syscon misc SEGSIZE 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 0 # unix consensus
syscon misc SEND_DIAGNOSTIC 29 29 0 0 0 0 0 0
syscon misc SEND_VOLUME_TAG 182 182 0 0 0 0 0 0
syscon misc SET_LIMITS 51 51 0 0 0 0 0 0
syscon misc SET_WINDOW 36 36 0 0 0 0 0 0
syscon misc SFD_CLOEXEC 0x080000 0x080000 0 0 0 0 0 0
syscon misc SFD_NONBLOCK 0x0800 0x0800 0 0 0 0 0 0
syscon misc SUBCMDMASK 255 255 255 255 255 255 255 0 # unix consensus
syscon misc SUBCMDSHIFT 8 8 8 8 8 8 8 0 # unix consensus
syscon misc SYMTYPE 50 50 50 50 50 50 50 0 # unix consensus
syscon misc TGEXEC 8 8 8 8 8 8 8 0 # unix consensus
syscon misc TGREAD 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0 # unix consensus
syscon misc TGWRITE 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0 # unix consensus
syscon misc TMAGLEN 6 6 6 6 6 6 6 0 # unix consensus
syscon misc TOEXEC 1 1 1 1 1 1 1 0 # unix consensus
syscon misc TOREAD 4 4 4 4 4 4 4 0 # unix consensus
syscon misc TOWRITE 2 2 2 2 2 2 2 0 # unix consensus
syscon misc TRANSIENT 4 4 4 4 4 4 4 0 # unix consensus
syscon misc TSGID 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0 # unix consensus
syscon misc TSUID 0x0800 0x0800 0x0800 0x0800 0x0800 0x0800 0x0800 0 # unix consensus
syscon misc TSVTX 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 0 # unix consensus
syscon misc TUEXEC 0x40 0x40 0x40 0x40 0x40 0x40 0x40 0 # unix consensus
syscon misc TUREAD 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 0 # unix consensus
syscon misc TUWRITE 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0 # unix consensus
syscon misc TVERSLEN 2 2 2 2 2 2 2 0 # unix consensus
syscon misc WORD_BIT 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0 # unix consensus
syscon misc WRQ 2 2 2 2 2 2 2 0 # unix consensus
syscon misc SIGEV_THREAD 2 2 3 3 2 0 2 0
syscon misc SIGEV_SIGNAL 0 0 1 1 1 0 1 0
syscon misc SIGEV_NONE 1 1 0 0 0 0 0 0
syscon misc BC_BASE_MAX 99 99 99 99 99 0x7fffffff 0x7fffffff 0
syscon misc BC_DIM_MAX 0x0800 0x0800 0x0800 0x0800 0x0800 0xffff 0xffff 0
syscon misc BC_SCALE_MAX 99 99 99 99 99 0x7fffffff 0x7fffffff 0
syscon misc BC_STRING_MAX 0x03e8 0x03e8 0x03e8 0x03e8 0x03e8 0x7fffffff 0x7fffffff 0
syscon misc ABORTED_COMMAND 11 11 0 0 0 0 0 0
syscon misc ACORE 0 0 8 8 8 8 8 0 # bsd consensus
syscon misc AFORK 0 0 1 1 1 1 1 0 # bsd consensus
syscon misc AIO_ALLDONE 2 2 1 1 3 0 0 0
syscon misc AIO_NOTCANCELED 1 1 4 4 2 0 0 0
syscon misc AIO_CANCELED 0 0 2 2 1 0 0 0
# baud rates
#
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,ABORTED_COMMAND,11,11,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,ACORE,0,0,8,8,8,8,8,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AFORK,0,0,1,1,1,1,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AIO_ALLDONE,2,2,1,1,3,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AIO_CANCELED,0,0,2,2,1,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AIO_NOTCANCELED,1,1,4,4,2,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,BC_BASE_MAX,99,99,99,99,99,0x7fffffff,0x7fffffff,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,BC_DIM_MAX,0x0800,0x0800,0x0800,0x0800,0x0800,0xffff,0xffff,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,BC_SCALE_MAX,99,99,99,99,99,0x7fffffff,0x7fffffff,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,BC_STRING_MAX,0x03e8,0x03e8,0x03e8,0x03e8,0x03e8,0x7fffffff,0x7fffffff,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FIFOTYPE,54,54,54,54,54,54,54,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,GRPQUOTA,1,1,1,1,1,1,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,IF_NAMESIZE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,INTERMEDIATE_C_GOOD,10,10,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,INTERMEDIATE_GOOD,8,8,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,IP6F_MORE_FRAG,0x0100,0x0100,0x0100,0x0100,0x0100,0x0100,0x0100,0x0100
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,IP6F_OFF_MASK,0xf8ff,0xf8ff,0xf8ff,0xf8ff,0xf8ff,0xf8ff,0xf8ff,0xf8ff
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,IP6F_RESERVED_MASK,0x0600,0x0600,0x0600,0x0600,0x0600,0x0600,0x0600,0x0600
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,LINE_MAX,0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,LINKED_CMD_COMPLETE,10,10,0,0,0,0,0,0
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,LINKED_FLG_CMD_COMPLETE,11,11,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,LNKTYPE,49,49,49,49,49,49,49,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon lock,LOCK_UNLOCK_CACHE,54,54,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,L_INCR,1,1,1,1,1,1,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,L_SET,0,0,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,L_XTND,2,2,2,2,2,2,2,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,MATH_ERREXCEPT,2,2,2,2,2,2,2,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,MATH_ERRNO,1,1,1,1,1,1,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,MAXNAMLEN,255,255,255,255,255,255,255,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,MAXQUOTAS,2,2,2,2,2,2,2,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,MEDIUM_ERROR,3,3,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,MEDIUM_SCAN,56,56,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,NBBY,8,8,8,8,8,8,8,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,NR_DQHASH,43,43,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,NR_DQUOTS,0x0100,0x0100,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,PERSISTENT_RESERVE_IN,94,94,0,0,0,0,0,0
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,PERSISTENT_RESERVE_OUT,95,95,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,PRELIM,1,1,1,1,1,1,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,REGTYPE,48,48,48,48,48,48,48,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RES_PRF_CLASS,4,4,4,4,4,4,4,0
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RHF_GUARANTEE_START_INIT,0x80,0x80,0,0,0,0,0,0
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RHF_NO_LIBRARY_REPLACEMENT,4,4,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RRQ,1,1,1,1,1,1,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTF_NOFORWARD,0x1000,0x1000,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTF_NOPMTUDISC,0x4000,0x4000,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SARMAG,8,8,8,8,8,8,8,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SEGSIZE,0x0200,0x0200,0x0200,0x0200,0x0200,0x0200,0x0200,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SEND_DIAGNOSTIC,29,29,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SEND_VOLUME_TAG,182,182,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SET_LIMITS,51,51,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SET_WINDOW,36,36,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SFD_CLOEXEC,0x080000,0x080000,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SFD_NONBLOCK,0x0800,0x0800,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SIGEV_NONE,1,1,0,0,0,0,0,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SIGEV_SIGNAL,0,0,1,1,1,0,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SIGEV_THREAD,2,2,3,3,2,0,2,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SUBCMDMASK,255,255,255,255,255,255,255,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SUBCMDSHIFT,8,8,8,8,8,8,8,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,SYMTYPE,50,50,50,50,50,50,50,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,TGEXEC,8,8,8,8,8,8,8,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,TGREAD,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,TGWRITE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,TMAGLEN,6,6,6,6,6,6,6,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,TOEXEC,1,1,1,1,1,1,1,0
-2
View File
@@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,TOREAD,4,4,4,4,4,4,4,0
Loaded 100 of 123 files, more files were not shown because too many files have changed in this diff. Show more