Fix bugs with recent change

This change makes further effort towards improving our poll()
implementation on the New Technology. The stdin worker didn't work out
so well for Python so it's not being used for now. System call tracing
with the --strace flag should now be less noisy now on Windows unless
you modify the strace.internal.h defines to turn on some optional ones
that are most useful for debugging the system call wrappers.
This commit is contained in:
Justine Tunney 2022-04-16 10:40:23 -07:00
parent 933411ba99
commit dc0ea6640e
127 changed files with 1354 additions and 866 deletions

View file

@ -29,14 +29,6 @@ textwindows int sys_close_nt(struct Fd *fd) {
int e;
bool ok = true;
// if this file descriptor is wrapped in a named pipe worker thread
// then we need to close our copy of the worker thread handle. it's
// also required that whatever install a worker use malloc, so free
if (fd->worker) {
if (!weaken(UnrefNtStdinWorker)(fd->worker)) ok = false;
fd->worker = 0;
}
if (fd->kind == kFdFile && ((fd->flags & O_ACCMODE) != O_RDONLY &&
GetFileType(fd->handle) == kNtFileTypeDisk)) {
// Like Linux, closing a file on Windows doesn't guarantee it's
@ -47,8 +39,15 @@ textwindows int sys_close_nt(struct Fd *fd) {
errno = e;
}
// now we can close the handle
if (!CloseHandle(fd->handle)) ok = false;
// if this file descriptor is wrapped in a named pipe worker thread
// then we need to close our copy of the worker thread handle. it's
// also required that whatever install a worker use malloc, so free
if (fd->worker) {
if (!weaken(UnrefNtStdinWorker)(fd->worker)) ok = false;
fd->worker = 0;
} else {
if (!CloseHandle(fd->handle)) ok = false;
}
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
if (!CloseHandle(fd->extra)) ok = false;
}

View file

@ -40,14 +40,13 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
struct DirectMap dm;
struct ProtectNt fl;
const struct NtSecurityAttributes *sec;
struct NtProcessMemoryCountersEx memcount;
#ifndef NDEBUG
struct NtProcessMemoryCountersEx memcount = {
.cb = sizeof(struct NtProcessMemoryCountersEx),
};
#if _NT_RLIMIT_PWSS_MB
if (GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
if (memcount.PeakWorkingSetSize > 5ull * 1024 * 1024 * 1024) {
kprintf("error: exceeded 5gb memory limit%n");
if (memcount.PeakWorkingSetSize > _NT_RLIMIT_PWSS_MB * 1048576ull) {
kprintf("error: PeakWorkingSetSize %'ldmb exceeded %'ldmb limit%n",
memcount.PeakWorkingSetSize / 1048576, (long)_NT_RLIMIT_PWSS_MB);
_Exit(201);
}
}

View file

@ -45,8 +45,8 @@ struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
} else {
d = sys_mmap_nt(addr, size, prot, flags, fd, off);
}
STRACE("sys_mmap(%.12p%s, %'zu, %s, %s, %d, %'ld) → {%.12p, %p}% m", addr,
DescribeFrame((intptr_t)addr >> 16), size, DescribeProtFlags(prot),
DescribeMapFlags(flags), fd, off, d.addr, d.maphandle);
KERNTRACE("sys_mmap(%.12p%s, %'zu, %s, %s, %d, %'ld) → {%.12p, %p}% m", addr,
DescribeFrame((intptr_t)addr >> 16), size, DescribeProtFlags(prot),
DescribeMapFlags(flags), fd, off, d.addr, d.maphandle);
return d;
}

View file

@ -68,6 +68,6 @@ int fcntl(int fd, int cmd, ...) {
} else {
rc = einval();
}
STRACE("fcntl(%d, %d, %p) → %d% m", fd, cmd, arg);
STRACE("fcntl(%d, %d, %p) → %#x% m", fd, cmd, arg, rc);
return rc;
}

View file

@ -41,7 +41,7 @@ int fstat(int fd, struct stat *st) {
} else if (!__isfdkind(fd, kFdFile)) {
rc = ebadf();
} else {
rc = sys_fstat_nt(g_fds.p[fd].handle, st);
rc = sys_fstat_nt(__getfdhandleactual(fd), st);
}
STRACE("fstat(%d, [%s]) → %d% m", fd, __strace_stat(rc, st), rc);
return rc;

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/o.h"
STATIC_YOINK("_init_g_fds");
@ -48,4 +49,7 @@ textstartup void InitializeFileDescriptors(void) {
fds->__init_p[1].handle = GetStdHandle(pushpop(kNtStdOutputHandle));
fds->__init_p[2].handle = GetStdHandle(pushpop(kNtStdErrorHandle));
}
fds->__init_p[0].flags = O_RDONLY;
fds->__init_p[1].flags = O_WRONLY | O_APPEND;
fds->__init_p[2].flags = O_WRONLY | O_APPEND;
}

View file

@ -39,8 +39,5 @@ unsigned long getauxval(unsigned long at) {
return ap[1];
}
}
if (at == AT_EXECFN) {
return (intptr_t)__argv[0];
}
return 0;
}

31
libc/calls/getegid.c Normal file
View file

@ -0,0 +1,31 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Returns effective group ID of calling process.
*/
uint32_t getegid(void) {
int rc;
rc = sys_getegid();
STRACE("%s() → %d% m", "getegid", rc);
return rc;
}

View file

@ -27,6 +27,8 @@
*
* pheidippides.domain.example
* ^^^^^^^^^^^^
*
* @return 0 on success or -1 w/ errno
*/
int gethostname(char *name, size_t len) {
if (len < 1) return einval();

36
libc/calls/getpgrp.c Normal file
View file

@ -0,0 +1,36 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
* Returns process group id of calling process.
*/
uint32_t getpgrp(void) {
int rc;
if (!IsWindows()) {
rc = sys_getpgrp();
} else {
rc = getpid();
}
STRACE("%s() → %d% m", "getpgrp", rc);
return rc;
}

View file

@ -30,30 +30,22 @@
#include "libc/sysv/errfuns.h"
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
struct NtFileTime CreationFileTime;
struct NtFileTime ExitFileTime;
struct NtFileTime KernelFileTime;
struct NtFileTime UserFileTime;
struct NtProcessMemoryCountersEx memcount;
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
if (!usage) return efault();
if (who == 99) return enosys(); /* @see libc/sysv/consts.sh */
bzero(usage, sizeof(*usage));
if ((who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
if (who == 99) return enosys(); // @see libc/sysv/consts.sh
if (!usage) return 0;
if (!(who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
&CreationFileTime, &ExitFileTime, &KernelFileTime, &UserFileTime)) {
/* xxx: shouldn't clobber memory on failure below */
usage->ru_utime = WindowsDurationToTimeVal(ReadFileTime(UserFileTime));
usage->ru_stime = WindowsDurationToTimeVal(ReadFileTime(KernelFileTime));
} else {
return __winerr();
}
bzero(&memcount, sizeof(memcount));
memcount.cb = sizeof(struct NtProcessMemoryCountersEx);
if (GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
usage->ru_maxrss = memcount.PeakWorkingSetSize / 1024;
usage->ru_majflt = memcount.PageFaultCount;
} else {
&ftCreation, &ftExit, &ftKernel, &ftUser) ||
!GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
return __winerr();
}
*usage = (struct rusage){
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
.ru_maxrss = memcount.PeakWorkingSetSize / 1024,
.ru_majflt = memcount.PageFaultCount,
};
return 0;
}

View file

@ -157,6 +157,7 @@ i32 sys_futimes(i32, const struct timeval *) hidden;
i32 sys_futimesat(i32, const char *, const struct timeval *) hidden;
i32 sys_getitimer(i32, struct itimerval *) hidden;
i32 sys_getpgid(i32) hidden;
i32 sys_getpgrp(void) hidden;
i32 sys_getppid(void) hidden;
i32 sys_getpriority(i32, u32) hidden;
i32 sys_getrlimit(i32, struct rlimit *) hidden;
@ -223,6 +224,7 @@ i64 sys_sendfile(i32, i32, i64 *, u64) hidden;
i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden;
i64 sys_write(i32, const void *, u64) hidden;
u32 sys_getegid(void) hidden;
u32 sys_geteuid(void) hidden;
u32 sys_getgid(void) hidden;
u32 sys_getsid(int) hidden;

View file

@ -35,7 +35,7 @@ int ioctl_default(int fd, uint64_t request, ...) {
return sys_ioctl(fd, request, arg);
} else if (__isfdopen(fd)) {
if (g_fds.p[fd].kind == kFdSocket) {
handle = g_fds.p[fd].handle;
handle = __getfdhandleactual(fd);
if ((rc = weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) {
return rc;
} else {

View file

@ -31,8 +31,8 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
int64_t in, out;
bool32 inok, outok;
uint32_t inmode, outmode;
inok = GetConsoleMode((in = g_fds.p[0].handle), &inmode);
outok = GetConsoleMode((out = g_fds.p[1].handle), &outmode);
inok = GetConsoleMode((in = __getfdhandleactual(0)), &inmode);
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
if (inok | outok) {
bzero(tio, sizeof(*tio));
if (inok) {

View file

@ -31,8 +31,8 @@ textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
int64_t in, out;
bool32 inok, outok;
uint32_t inmode, outmode;
inok = GetConsoleMode((in = g_fds.p[0].handle), &inmode);
outok = GetConsoleMode((out = g_fds.p[1].handle), &outmode);
inok = GetConsoleMode((in = __getfdhandleactual(0)), &inmode);
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
if (inok | outok) {
if (inok) {
if (request == TCSETSF) {

View file

@ -42,10 +42,10 @@ textwindows int ioctl_tiocgwinsz_nt(struct Fd *fd, struct winsize *ws) {
GetStartupInfo(&startinfo);
for (i = 0; i < ARRAYLEN(fds); ++i) {
if (fds[i]->kind == kFdFile || fds[i]->kind == kFdConsole) {
if (GetConsoleMode(fds[i]->handle, &mode)) {
if (GetConsoleMode(__getfdhandleactual(i), &mode)) {
bzero(&sbinfo, sizeof(sbinfo));
sbinfo.cbSize = sizeof(sbinfo);
if (GetConsoleScreenBufferInfoEx(fds[i]->handle, &sbinfo)) {
if (GetConsoleScreenBufferInfoEx(__getfdhandleactual(i), &sbinfo)) {
ws->ws_col = sbinfo.srWindow.Right - sbinfo.srWindow.Left + 1;
ws->ws_row = sbinfo.srWindow.Bottom - sbinfo.srWindow.Top + 1;
ws->ws_xpixel = 0;

View file

@ -29,9 +29,10 @@ textwindows int ioctl_tiocswinsz_nt(int fd, const struct winsize *ws) {
struct NtCoord coord;
if (!ws) return efault();
if (!__isfdkind(fd, kFdFile)) return ebadf();
if (!GetConsoleMode(g_fds.p[fd].handle, &mode)) return enotty();
if (!GetConsoleMode(__getfdhandleactual(fd), &mode)) return enotty();
coord.X = ws->ws_col;
coord.Y = ws->ws_row;
if (!SetConsoleScreenBufferSize(g_fds.p[fd].handle, coord)) return __winerr();
if (!SetConsoleScreenBufferSize(__getfdhandleactual(fd), coord))
return __winerr();
return 0;
}

View file

@ -24,5 +24,5 @@
textwindows bool32 sys_isatty_nt(int fd) {
return __isfdkind(fd, kFdConsole) ||
(__isfdkind(fd, kFdFile) &&
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
GetFileType(__getfdhandleactual(fd)) == kNtFileTypeChar);
}

View file

@ -66,6 +66,6 @@ bool32 ischardev(int fd) {
} else {
return __isfdkind(fd, kFdConsole) ||
(__isfdkind(fd, kFdFile) &&
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
GetFileType(__getfdhandleactual(fd)) == kNtFileTypeChar);
}
}

View file

@ -60,6 +60,6 @@ privileged void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) {
} else {
rax = enosys();
}
STRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p% m", p, n, m, f, q, rax);
KERNTRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p% m", p, n, m, f, q, rax);
return (void *)rax;
}

View file

@ -28,7 +28,7 @@ int sys_munmap(void *p, size_t n) {
} else {
rc = sys_munmap_metal(p, n);
}
STRACE("sys_munmap(%p%s, %'zu) → %d", p, DescribeFrame((intptr_t)p >> 16), n,
rc);
KERNTRACE("sys_munmap(%p%s, %'zu) → %d", p, DescribeFrame((intptr_t)p >> 16),
n, rc);
return rc;
}

View file

@ -29,8 +29,9 @@
textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
struct timespec *rem) {
int rc;
int64_t sec, nsec;
uint64_t ms, slice;
bool alertable;
uint32_t slice;
int64_t ms, sec, nsec;
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
__builtin_add_overflow(ms, req->tv_nsec / 1000000, &ms)) {
ms = -1;
@ -44,18 +45,20 @@ textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
rc = eintr();
break;
}
if (ms > __SIG_POLLING_INTERVAL_MS) {
slice = __SIG_POLLING_INTERVAL_MS;
slice = MIN(__SIG_POLLING_INTERVAL_MS, ms);
if (__time_critical) {
alertable = false;
} else {
slice = ms;
alertable = true;
POLLTRACE("sys_nanosleep_nt polling for %'ldms of %'ld");
}
if (SleepEx(slice, true) == kNtWaitIoCompletion) {
STRACE("IOCP TRIGGERED EINTR");
rc = eintr();
break;
if (SleepEx(slice, alertable) == kNtWaitIoCompletion) {
POLLTRACE("IOCP EINTR");
continue;
}
ms -= slice;
} while (ms);
} while (ms > 0);
ms = MAX(ms, 0);
if (rem) {
sec = ms / 1000;
nsec = ms % 1000 * 1000000000;

View file

@ -61,6 +61,10 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
return enosys();
}
if (iovlen == 1) {
return sys_pread(fd, iov[0].iov_base, iov[0].iov_len, off, off);
}
/*
* NT, 2018-era XNU, and 2007-era Linux don't support this system call
*/

View file

@ -65,6 +65,10 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
return enosys();
}
if (iovlen == 1) {
return sys_pwrite(fd, iov[0].iov_base, iov[0].iov_len, off, off);
}
/*
* NT, 2018-era XNU, and 2007-era Linux don't support this system call
*/

View file

@ -65,10 +65,7 @@ int raise(int sig) {
// groups potentially. We just shouldn't use this because it
// doesn't make any sense and it's so evil.
if (GenerateConsoleCtrlEvent(event, 0)) {
// XXX: we shouldn't need to sleep here ctrl-c is evil on nt
if (SleepEx(100, true) == kNtWaitIoCompletion) {
STRACE("IOCP TRIGGERED EINTR");
}
SleepEx(100, true);
__sig_check(false);
rc = 0;
} else {

View file

@ -26,6 +26,7 @@
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/nt/enum/filetype.h"
#include "libc/nt/enum/wait.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
@ -40,15 +41,20 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
size_t size, ssize_t offset) {
uint32_t err, got, avail;
struct NtOverlapped overlap;
if (fd->worker) {
if (GetFileType(fd->handle) == kNtFileTypePipe) {
for (;;) {
if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break;
if (avail) break;
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion ||
_check_interrupts(true, g_fds.p)) {
POLLTRACE("sys_read_nt polling");
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion) {
POLLTRACE("IOCP EINTR");
}
if (_check_interrupts(true, g_fds.p)) {
POLLTRACE("sys_read_nt interrupted");
return eintr();
}
}
POLLTRACE("sys_read_nt ready to read");
}
if (ReadFile(fd->handle, data, _clampio(size), &got,
_offset2overlap(fd->handle, offset, &overlap))) {

View file

@ -61,7 +61,7 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
rdb = (struct NtReparseDataBuffer *)buf;
freeme = 0;
} else {
STRACE("sys_readlinkat_nt() needs bigger buffer malloc() to be yoinked");
NTTRACE("sys_readlinkat_nt() needs bigger buffer malloc() to be yoinked");
return enomem();
}
if ((h = CreateFile(path16, 0, 0, 0, kNtOpenExisting,
@ -102,11 +102,11 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
if (freeme || (intptr_t)(buf + j) <= (intptr_t)(p + i)) {
rc = j;
} else {
STRACE("sys_readlinkat_nt() too many astral codepoints");
NTTRACE("sys_readlinkat_nt() too many astral codepoints");
rc = enametoolong();
}
} else {
STRACE("sys_readlinkat_nt() should have kNtIoReparseTagSymlink");
NTTRACE("sys_readlinkat_nt() should have kNtIoReparseTagSymlink");
rc = einval();
}
} else {

View file

@ -29,6 +29,13 @@
/**
* Reads data to multiple buffers.
*
* This is the same thing as read() except it has multiple buffers.
* This yields a performance boost in situations where it'd be expensive
* to stitch data together using memcpy() or issuing multiple syscalls.
* This wrapper is implemented so that readv() calls where iovlen<2 may
* be passed to the kernel as read() instead. This yields a 100 cycle
* performance boost in the case of a single small iovec.
*
* @return number of bytes actually read, or -1 w/ errno
* @restartable
*/
@ -41,7 +48,11 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
rc = weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (!IsWindows() && !IsMetal()) {
rc = sys_readv(fd, iov, iovlen);
if (iovlen == 1) {
rc = sys_read(fd, iov[0].iov_base, iov[0].iov_len);
} else {
rc = sys_readv(fd, iov, iovlen);
}
} else if (fd >= g_fds.n) {
rc = ebadf();
} else if (IsMetal()) {

View file

@ -90,7 +90,7 @@ int __reservefd(int start) {
*/
static void __freefds(void) {
int i;
STRACE("__freefds()");
NTTRACE("__freefds()");
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind) {
close(i);

View file

@ -42,6 +42,10 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#ifdef SYSDEBUG
STATIC_YOINK("strsignal"); // for kprintf()
#endif
#define SA_RESTORER 0x04000000
#ifndef SWITCHEROO

View file

@ -78,15 +78,14 @@ int sigsuspend(const sigset_t *ignore) {
break;
}
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion) {
STRACE("IOCP TRIGGERED EINTR");
rc = eintr();
break;
POLLTRACE("IOCP EINTR");
continue;
}
#ifdef SYSDEBUG
#if defined(SYSDEBUG) && defined(_POLLTRACE)
ms += __SIG_POLLING_INTERVAL_MS;
if (ms >= __SIG_LOGGING_INTERVAL_MS) {
totoms += ms, ms = 0;
STRACE("... sigsuspending for %'lums...", totoms);
POLLTRACE("... sigsuspending for %'lums...", totoms);
}
#endif
} while (1);

View file

@ -4,6 +4,11 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h"
#define _NT_RLIMIT_PWSS_MB 1000 /* nocommit */
#define _KERNTRACE 0 /* not configurable w/ flag yet */
#define _POLLTRACE 0 /* not configurable w/ flag yet */
#define _NTTRACE 0 /* not configurable w/ flag yet */
#define STRACE_PROLOGUE "%rSYS %5P %'18T "
#if !(__ASSEMBLER__ + __LINKER__ + 0)
@ -20,6 +25,24 @@ COSMOPOLITAN_C_START_
#define STRACE(FMT, ...) (void)0
#endif
#if defined(SYSDEBUG) && _POLLTRACE
#define POLLTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__)
#else
#define POLLTRACE(FMT, ...) (void)0
#endif
#if defined(SYSDEBUG) && _KERNTRACE
#define KERNTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__)
#else
#define KERNTRACE(FMT, ...) (void)0
#endif
#if defined(SYSDEBUG) && _NTTRACE
#define NTTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__)
#else
#define NTTRACE(FMT, ...) (void)0
#endif
extern int __strace;
void __stracef(const char *, ...);

View file

@ -86,7 +86,7 @@ int uname(struct utsname *lool) {
}
} else {
v = NtGetVersion();
p = lool->version;
p = lool->release;
p = FormatUint32(p, NtGetMajorVersion()), *p++ = '.';
p = FormatUint32(p, NtGetMinorVersion()), *p++ = '-';
p = FormatUint32(p, NtGetBuildNumber());

View file

@ -28,6 +28,13 @@
/**
* Writes data from multiple buffers.
*
* This is the same thing as write() except it has multiple buffers.
* This yields a performance boost in situations where it'd be expensive
* to stitch data together using memcpy() or issuing multiple syscalls.
* This wrapper is implemented so that writev() calls where iovlen<2 may
* be passed to the kernel as write() instead. This yields a 100 cycle
* performance boost in the case of a single small iovec.
*
* Please note that it's not an error for a short write to happen. This
* can happen in the kernel if EINTR happens after some of the write has
* been committed. It can also happen if we need to polyfill this system
@ -45,7 +52,11 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
rc = weaken(__zipos_write)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (!IsWindows() && !IsMetal()) {
rc = sys_writev(fd, iov, iovlen);
if (iovlen == 1) {
rc = sys_write(fd, iov[0].iov_base, iov[0].iov_len);
} else {
rc = sys_writev(fd, iov, iovlen);
}
} else if (fd >= g_fds.n) {
rc = ebadf();
} else if (IsMetal()) {