mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Make important improvements
- Fix preadv() and pwritev() for old distros - Introduce _npassert() and _unassert() macros - Prove that file locks work properly on Windows - Support fcntl(F_DUPFD_CLOEXEC) on more systems
This commit is contained in:
parent
1ad2f530f9
commit
3f49889841
130 changed files with 1225 additions and 431 deletions
|
@ -152,6 +152,10 @@ CONFIG_CCFLAGS += \
|
|||
-fomit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
|
@ -180,6 +184,10 @@ CONFIG_CPPFLAGS += \
|
|||
-DSUPPORT_VECTOR=1
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
|
@ -212,6 +220,10 @@ CONFIG_CPPFLAGS += \
|
|||
-DSUPPORT_VECTOR=113
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
|
@ -249,6 +261,10 @@ CONFIG_CCFLAGS += \
|
|||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
@ -278,6 +294,10 @@ CONFIG_CCFLAGS += \
|
|||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
|
56
examples/clock_getres.c
Normal file
56
examples/clock_getres.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
#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/calls/struct/timespec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
|
||||
int n;
|
||||
int shown[64];
|
||||
|
||||
void show(int clock) {
|
||||
int i;
|
||||
struct timespec ts;
|
||||
if (clock == 127) return;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (shown[i] == clock) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
shown[n++] = clock;
|
||||
if (clock_getres(clock, &ts) != -1) {
|
||||
kprintf("%s %'ld ns\n", DescribeClockName(clock), _timespec_tonanos(ts));
|
||||
} else {
|
||||
kprintf("%s %s\n", DescribeClockName(clock), _strerrno(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
show(CLOCK_REALTIME);
|
||||
show(CLOCK_REALTIME_FAST);
|
||||
show(CLOCK_REALTIME_PRECISE);
|
||||
show(CLOCK_MONOTONIC);
|
||||
show(CLOCK_MONOTONIC_RAW);
|
||||
show(CLOCK_MONOTONIC_FAST);
|
||||
show(CLOCK_MONOTONIC_PRECISE);
|
||||
show(CLOCK_PROCESS_CPUTIME_ID);
|
||||
show(CLOCK_THREAD_CPUTIME_ID);
|
||||
show(CLOCK_PROF);
|
||||
show(CLOCK_BOOTTIME);
|
||||
show(CLOCK_REALTIME_ALARM);
|
||||
show(CLOCK_BOOTTIME_ALARM);
|
||||
show(CLOCK_TAI);
|
||||
show(CLOCK_UPTIME);
|
||||
show(CLOCK_UPTIME_PRECISE);
|
||||
show(CLOCK_UPTIME_FAST);
|
||||
show(CLOCK_SECOND);
|
||||
}
|
|
@ -7,16 +7,29 @@ extern bool __assert_disable;
|
|||
void __assert_fail(const char *, const char *, int) hidden relegated;
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert(EXPR) ((void)0)
|
||||
#define assert(x) ((void)0)
|
||||
#else
|
||||
#define assert(EXPR) \
|
||||
((void)((EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0)))
|
||||
#define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__), 0)))
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define static_assert _Static_assert
|
||||
#endif
|
||||
|
||||
#define _unassert(x) \
|
||||
do { \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
unreachable; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _npassert(x) \
|
||||
do { \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
notpossible; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_ASSERT_H_ */
|
||||
|
|
|
@ -26,35 +26,36 @@
|
|||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_chdir_nt(const char *path) {
|
||||
textwindows int sys_chdir_nt_impl(char16_t path[hasatleast PATH_MAX],
|
||||
uint32_t len) {
|
||||
uint32_t n;
|
||||
int e, ms, err, len;
|
||||
char16_t path16[PATH_MAX], var[4];
|
||||
if ((len = __mkntpath(path, path16)) == -1) return -1;
|
||||
if (!len) return enoent();
|
||||
if (len && path16[len - 1] != u'\\') {
|
||||
int e, ms, err;
|
||||
char16_t var[4];
|
||||
|
||||
if (len && path[len - 1] != u'\\') {
|
||||
if (len + 2 > PATH_MAX) return enametoolong();
|
||||
path16[len + 0] = u'\\';
|
||||
path16[len + 1] = u'\0';
|
||||
path[len + 0] = u'\\';
|
||||
path[len + 1] = u'\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* chdir() seems flaky on windows 7
|
||||
* in a similar way to rmdir() sigh
|
||||
*/
|
||||
for (err = errno, ms = 1;; ms *= 2) {
|
||||
if (SetCurrentDirectory(path16)) {
|
||||
if (SetCurrentDirectory(path)) {
|
||||
/*
|
||||
* Now we need to set a magic environment variable.
|
||||
*/
|
||||
if ((n = GetCurrentDirectory(ARRAYLEN(path16), path16))) {
|
||||
if (n < ARRAYLEN(path16)) {
|
||||
if (!((path16[0] == '/' && path16[1] == '/') ||
|
||||
(path16[0] == '\\' && path16[1] == '\\'))) {
|
||||
if ((n = GetCurrentDirectory(PATH_MAX, path))) {
|
||||
if (n < PATH_MAX) {
|
||||
if (!((path[0] == '/' && path[1] == '/') ||
|
||||
(path[0] == '\\' && path[1] == '\\'))) {
|
||||
var[0] = '=';
|
||||
var[1] = path16[0];
|
||||
var[1] = path[0];
|
||||
var[2] = ':';
|
||||
var[3] = 0;
|
||||
if (!SetEnvironmentVariable(var, path16)) {
|
||||
if (!SetEnvironmentVariable(var, path)) {
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
@ -77,5 +78,13 @@ textwindows int sys_chdir_nt(const char *path) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return __fix_enotdir(-1, path16);
|
||||
return __fix_enotdir(-1, path);
|
||||
}
|
||||
|
||||
textwindows int sys_chdir_nt(const char *path) {
|
||||
int len;
|
||||
char16_t path16[PATH_MAX];
|
||||
if ((len = __mkntpath(path, path16)) == -1) return -1;
|
||||
if (!len) return enoent();
|
||||
return sys_chdir_nt_impl(path16, len);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
|
@ -32,10 +33,9 @@
|
|||
*/
|
||||
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
|
||||
int64_t rc, proc, handle;
|
||||
|
||||
// validate the api usage
|
||||
if (oldfd < 0) return ebadf();
|
||||
if (flags & ~O_CLOEXEC) return einval();
|
||||
_unassert(oldfd >= 0);
|
||||
_unassert(newfd >= -1);
|
||||
_unassert(!(flags & ~O_CLOEXEC));
|
||||
|
||||
__fds_lock();
|
||||
|
||||
|
|
|
@ -16,41 +16,52 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#define F_DUP2FD 10
|
||||
#define F_DUP2FD_CLOEXEC 18
|
||||
|
||||
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
||||
static bool once;
|
||||
static bool demodernize;
|
||||
int olderr, how, fd;
|
||||
if (!once) {
|
||||
olderr = errno;
|
||||
fd = __sys_dup3(oldfd, newfd, flags);
|
||||
if (fd == -1 && errno == ENOSYS) {
|
||||
STRACE("demodernizing %s() due to %s", "dup3", "RHEL5:CVE-2010-3301");
|
||||
demodernize = true;
|
||||
once = true;
|
||||
errno = olderr;
|
||||
} else {
|
||||
once = true;
|
||||
return fd;
|
||||
}
|
||||
} else if (!demodernize) {
|
||||
return __sys_dup3(oldfd, newfd, flags);
|
||||
static struct Dup3 {
|
||||
pthread_once_t once;
|
||||
bool demodernize;
|
||||
} g_dup3;
|
||||
|
||||
static void sys_dup3_test(void) {
|
||||
int e = errno;
|
||||
__sys_dup3(-1, -1, 0);
|
||||
if ((g_dup3.demodernize = errno == ENOSYS)) {
|
||||
STRACE("demodernizing %s() due to %s", "dup3", "ENOSYS");
|
||||
}
|
||||
if (oldfd == newfd) return einval();
|
||||
if (flags & ~O_CLOEXEC) return einval();
|
||||
errno = e;
|
||||
}
|
||||
|
||||
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
||||
int how;
|
||||
_unassert(oldfd >= 0);
|
||||
_unassert(newfd >= 0);
|
||||
_unassert(!(flags & ~O_CLOEXEC));
|
||||
|
||||
if (IsFreebsd()) {
|
||||
how = flags & O_CLOEXEC ? F_DUP2FD_CLOEXEC : F_DUP2FD;
|
||||
if (flags & O_CLOEXEC) {
|
||||
how = F_DUP2FD_CLOEXEC;
|
||||
} else {
|
||||
how = F_DUP2FD;
|
||||
}
|
||||
return __sys_fcntl(oldfd, how, newfd);
|
||||
}
|
||||
|
||||
pthread_once(&g_dup3.once, sys_dup3_test);
|
||||
|
||||
if (!g_dup3.demodernize) {
|
||||
return __sys_dup3(oldfd, newfd, flags);
|
||||
} else {
|
||||
return __fixupnewfd(sys_dup2(oldfd, newfd), flags);
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -46,14 +47,14 @@
|
|||
*/
|
||||
int dup3(int oldfd, int newfd, int flags) {
|
||||
int rc;
|
||||
if (__isfdkind(oldfd, kFdZip)) {
|
||||
if (oldfd == newfd || (flags & ~O_CLOEXEC)) {
|
||||
rc = einval(); // NetBSD doesn't do this
|
||||
} else if (oldfd < 0 || newfd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (__isfdkind(oldfd, kFdZip)) {
|
||||
rc = eopnotsupp();
|
||||
} else if (oldfd == newfd) {
|
||||
rc = einval();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_dup3(oldfd, newfd, flags);
|
||||
} else if (newfd < 0) {
|
||||
rc = ebadf();
|
||||
} else {
|
||||
rc = sys_dup_nt(oldfd, newfd, flags, -1);
|
||||
}
|
||||
|
|
|
@ -23,20 +23,12 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_chdir_nt_impl(char16_t[hasatleast PATH_MAX], uint32_t);
|
||||
|
||||
textwindows int sys_fchdir_nt(int dirfd) {
|
||||
uint32_t len;
|
||||
char16_t dir[PATH_MAX];
|
||||
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
|
||||
len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos);
|
||||
if (len + 1 + 1 > ARRAYLEN(dir)) return enametoolong();
|
||||
if (dir[len - 1] != u'\\') {
|
||||
dir[len + 0] = u'\\';
|
||||
dir[len + 1] = u'\0';
|
||||
}
|
||||
if (SetCurrentDirectory(dir)) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
return sys_chdir_nt_impl(
|
||||
dir, GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos));
|
||||
}
|
||||
|
|
|
@ -24,42 +24,47 @@
|
|||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/calls/wincrash.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/byhandlefileinformation.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
bool __force_sqlite_to_work_until_we_can_fix_it;
|
||||
|
||||
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
|
||||
if (start < 0) return einval();
|
||||
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
|
||||
}
|
||||
|
||||
static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
||||
int e;
|
||||
struct flock *l;
|
||||
uint32_t flags, err;
|
||||
struct NtOverlapped ov;
|
||||
int64_t pos, off, len, size;
|
||||
struct NtByHandleFileInformation info;
|
||||
if (!GetFileInformationByHandle(f->handle, &info)) return __winerr();
|
||||
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) return __winerr();
|
||||
|
||||
if (!GetFileInformationByHandle(f->handle, &info)) {
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) {
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
l = (struct flock *)arg;
|
||||
len = l->l_len;
|
||||
off = l->l_start;
|
||||
size = (uint64_t)info.nFileSizeHigh << 32 | info.nFileSizeLow;
|
||||
|
||||
switch (l->l_whence) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
|
@ -72,37 +77,60 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
|||
default:
|
||||
return einval();
|
||||
}
|
||||
if (!len) len = size - off;
|
||||
if (off < 0 || len < 0) return einval();
|
||||
_offset2overlap(f->handle, off, &ov);
|
||||
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
|
||||
flags = 0;
|
||||
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately;
|
||||
/* TODO: How can we make SQLite locks on Windows to work? */
|
||||
/* if (l->l_type == F_WRLCK) flags |= kNtLockfileExclusiveLock; */
|
||||
if (LockFileEx(f->handle, flags, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
err = GetLastError();
|
||||
if (err == kNtErrorLockViolation) err = EAGAIN;
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
} else if (l->l_type == F_UNLCK) {
|
||||
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
err = GetLastError();
|
||||
if (err == kNtErrorNotLocked) {
|
||||
return 0;
|
||||
} else {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!len) {
|
||||
len = size - off;
|
||||
}
|
||||
|
||||
if (off < 0 || len < 0) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
bool32 ok;
|
||||
struct NtOverlapped ov = {.hEvent = f->handle,
|
||||
.Pointer = (void *)(uintptr_t)off};
|
||||
|
||||
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
|
||||
flags = 0;
|
||||
if (cmd != F_SETLKW) {
|
||||
flags |= kNtLockfileFailImmediately;
|
||||
}
|
||||
if (l->l_type == F_WRLCK) {
|
||||
flags |= kNtLockfileExclusiveLock;
|
||||
}
|
||||
ok = LockFileEx(f->handle, flags, 0, len, len >> 32, &ov);
|
||||
if (cmd == F_GETLK) {
|
||||
if (ok) {
|
||||
l->l_type = F_UNLCK;
|
||||
if (!UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
|
||||
notpossible;
|
||||
}
|
||||
} else {
|
||||
l->l_pid = -1;
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
if (ok || __force_sqlite_to_work_until_we_can_fix_it) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (l->l_type == F_UNLCK) {
|
||||
if (cmd == F_GETLK) return einval();
|
||||
e = errno;
|
||||
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else if (errno == ENOLCK) {
|
||||
errno = e;
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return einval();
|
||||
}
|
||||
|
||||
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_fcntl(int fd, int cmd, uintptr_t arg) {
|
||||
int rc;
|
||||
int e, rc;
|
||||
bool islock;
|
||||
if ((islock = cmd == F_GETLK || //
|
||||
cmd == F_SETLK || //
|
||||
|
@ -37,9 +39,13 @@ int sys_fcntl(int fd, int cmd, uintptr_t arg) {
|
|||
}
|
||||
cosmo2flock(arg);
|
||||
}
|
||||
e = errno;
|
||||
rc = __sys_fcntl(fd, cmd, arg);
|
||||
if (islock) {
|
||||
flock2cosmo(arg);
|
||||
} else if (rc == -1 && cmd == F_DUPFD_CLOEXEC && errno == EINVAL) {
|
||||
errno = e;
|
||||
rc = __fixupnewfd(__sys_fcntl(fd, F_DUPFD, arg), O_CLOEXEC);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -37,11 +37,9 @@
|
|||
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD, 3)), 3);
|
||||
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD_CLOEXEC, 3)), 3);
|
||||
*
|
||||
* This function implements POSIX Advisory Locks, e.g.
|
||||
*
|
||||
* CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK}));
|
||||
* // ...
|
||||
* CHECK_NE(-1, fcntl(zfd, F_SETLK, &(struct flock){F_UNLCK}));
|
||||
* This function implements POSIX Advisory Locks, which let independent
|
||||
* processes (and on Windows, threads too!) read/write lock byte ranges
|
||||
* of files. See `test/libc/calls/lock_test.c` for an example.
|
||||
*
|
||||
* Please be warned that locks currently do nothing on Windows since
|
||||
* figuring out how to polyfill them correctly is a work in progress.
|
||||
|
|
|
@ -16,19 +16,19 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
/**
|
||||
* Applies file descriptor fixups on XNU or old Linux.
|
||||
* @see __fixupnewsockfd() for socket file descriptors
|
||||
*/
|
||||
// Applies file descriptor fixups on XNU or old Linux.
|
||||
// See __fixupnewsockfd() for socket file descriptors.
|
||||
int __fixupnewfd(int fd, int flags) {
|
||||
if (fd != -1) {
|
||||
if (flags & O_CLOEXEC) {
|
||||
__sys_fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
_npassert(!__sys_fcntl(fd, F_SETFD, FD_CLOEXEC));
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
|
|
|
@ -17,28 +17,49 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/byhandlefileinformation.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/lock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define _LOCK_SH 0
|
||||
#define _LOCK_EX kNtLockfileExclusiveLock
|
||||
#define _LOCK_NB kNtLockfileFailImmediately
|
||||
#define _LOCK_UN 8
|
||||
|
||||
textwindows int sys_flock_nt(int fd, int op) {
|
||||
struct NtOverlapped ov;
|
||||
int64_t h;
|
||||
struct NtByHandleFileInformation info;
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
bzero(&ov, sizeof(ov));
|
||||
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
|
||||
((!(op & LOCK_UN) &&
|
||||
LockFileEx(g_fds.p[fd].handle, op, 0, info.nFileSizeLow,
|
||||
info.nFileSizeHigh, &ov)) ||
|
||||
((op & LOCK_UN) && UnlockFileEx(g_fds.p[fd].handle, 0, info.nFileSizeLow,
|
||||
info.nFileSizeHigh, &ov)))) {
|
||||
return 0;
|
||||
} else {
|
||||
h = g_fds.p[fd].handle;
|
||||
struct NtOverlapped ov = {.hEvent = h};
|
||||
|
||||
if (!GetFileInformationByHandle(h, &info)) {
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
if (op & _LOCK_UN) {
|
||||
if (op & ~_LOCK_UN) {
|
||||
return einval();
|
||||
}
|
||||
if (UnlockFileEx(h, 0, info.nFileSizeLow, info.nFileSizeHigh, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (op & ~(_LOCK_SH | _LOCK_EX | _LOCK_NB)) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (LockFileEx(h, op, 0, info.nFileSizeLow, info.nFileSizeHigh, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,16 +24,18 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int32_t sys_pipe2(int pipefd[hasatleast 2], unsigned flags) {
|
||||
int rc, olderr;
|
||||
int e, rc;
|
||||
if (!flags) goto OldSkool;
|
||||
olderr = errno;
|
||||
e = errno;
|
||||
rc = __sys_pipe2(pipefd, flags);
|
||||
if (rc == -1 && errno == ENOSYS) {
|
||||
errno = olderr;
|
||||
errno = e;
|
||||
OldSkool:
|
||||
if ((rc = sys_pipe(pipefd)) != -1) {
|
||||
__fixupnewfd(pipefd[0], flags);
|
||||
__fixupnewfd(pipefd[1], flags);
|
||||
if (flags) {
|
||||
__fixupnewfd(pipefd[0], flags);
|
||||
__fixupnewfd(pipefd[1], flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
|
|
@ -46,8 +46,11 @@
|
|||
*/
|
||||
ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
||||
ssize_t rc;
|
||||
if (fd == -1 || offset < 0) return einval();
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
if (offset < 0) {
|
||||
rc = einval();
|
||||
} else if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
rc = _weaken(__zipos_read)(
|
||||
|
@ -60,7 +63,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
|||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
assert(rc == -1 || (size_t)rc <= size);
|
||||
_npassert(rc == -1 || (size_t)rc <= size);
|
||||
DATATRACE("pread(%d, [%#.*hhs%s], %'zu, %'zd) → %'zd% m", fd,
|
||||
MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, offset, rc);
|
||||
return rc;
|
||||
|
|
|
@ -16,91 +16,104 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/iov.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||
static bool once, demodernize;
|
||||
int i, err;
|
||||
ssize_t rc;
|
||||
size_t got, toto;
|
||||
int e, i;
|
||||
size_t got;
|
||||
bool masked;
|
||||
ssize_t rc, toto;
|
||||
sigset_t mask, oldmask;
|
||||
|
||||
if (fd < 0) {
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
if (iovlen < 0) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
return efault();
|
||||
}
|
||||
|
||||
if (fd < 0) return einval();
|
||||
if (iovlen < 0) return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return _weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
|
||||
} else if (IsWindows()) {
|
||||
}
|
||||
|
||||
if (IsMetal()) {
|
||||
return espipe(); // must be serial or console if not zipos
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
if (fd < g_fds.n) {
|
||||
return sys_read_nt(g_fds.p + fd, iov, iovlen, off);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
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
|
||||
*/
|
||||
if (!__vforked && !once) {
|
||||
err = errno;
|
||||
rc = sys_preadv(fd, iov, iovlen, off, off);
|
||||
if (rc == -1 && errno == ENOSYS) {
|
||||
errno = err;
|
||||
once = true;
|
||||
demodernize = true;
|
||||
STRACE("demodernizing %s() due to %s", "preadv", "ENOSYS");
|
||||
} else {
|
||||
once = true;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!demodernize) {
|
||||
return sys_preadv(fd, iov, iovlen, off, off);
|
||||
while (iovlen && !iov->iov_len) {
|
||||
--iovlen;
|
||||
++iov;
|
||||
}
|
||||
|
||||
if (!iovlen) {
|
||||
return sys_pread(fd, NULL, 0, off, off);
|
||||
return sys_pread(fd, 0, 0, off, off);
|
||||
}
|
||||
|
||||
if (iovlen == 1) {
|
||||
return sys_pread(fd, iov->iov_base, iov->iov_len, off, off);
|
||||
}
|
||||
|
||||
e = errno;
|
||||
rc = sys_preadv(fd, iov, iovlen, off, off);
|
||||
if (rc != -1 || errno != ENOSYS) return rc;
|
||||
errno = e;
|
||||
|
||||
for (toto = i = 0; i < iovlen; ++i) {
|
||||
rc = sys_pread(fd, iov[i].iov_base, iov[i].iov_len, off, off);
|
||||
if (rc == -1) {
|
||||
if (toto && (errno == EINTR || errno == EAGAIN)) {
|
||||
return toto;
|
||||
} else {
|
||||
return -1;
|
||||
if (!toto) {
|
||||
toto = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
got = rc;
|
||||
toto += got;
|
||||
off += got;
|
||||
if (got != iov[i].iov_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!masked) {
|
||||
sigfillset(&mask);
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
|
||||
masked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (masked) {
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
|
||||
}
|
||||
|
||||
return toto;
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -46,9 +46,11 @@
|
|||
ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
||||
ssize_t rc;
|
||||
size_t wrote;
|
||||
if (fd == -1 || offset < 0) return einval();
|
||||
size = MIN(size, 0x7ffff000);
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
if (offset < 0) {
|
||||
rc = einval();
|
||||
} else if (fd == -1) {
|
||||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pwrite(fd, buf, size, offset, offset);
|
||||
|
@ -59,10 +61,10 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
}
|
||||
if (rc != -1) {
|
||||
wrote = (size_t)rc;
|
||||
if (wrote == 0) {
|
||||
assert(size == 0);
|
||||
if (!wrote) {
|
||||
_npassert(size == 0);
|
||||
} else {
|
||||
assert(wrote <= size);
|
||||
_npassert(wrote <= size);
|
||||
}
|
||||
}
|
||||
DATATRACE("pwrite(%d, %#.*hhs%s, %'zu, %'zd) → %'zd% m", fd,
|
||||
|
|
|
@ -16,90 +16,105 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/iov.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
|
||||
int64_t off) {
|
||||
static bool once, demodernize;
|
||||
int i, err;
|
||||
ssize_t rc;
|
||||
size_t sent, toto;
|
||||
int i, e;
|
||||
bool masked;
|
||||
size_t sent;
|
||||
ssize_t rc, toto;
|
||||
sigset_t mask, oldmask;
|
||||
|
||||
if (fd < 0) {
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
if (iovlen < 0) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
return efault();
|
||||
}
|
||||
|
||||
if (fd < 0) return einval();
|
||||
if (iovlen < 0) return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return _weaken(__zipos_write)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
|
||||
} else if (IsWindows()) {
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
if (fd < g_fds.n) {
|
||||
return sys_write_nt(fd, iov, iovlen, off);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return enosys();
|
||||
}
|
||||
|
||||
if (iovlen == 1) {
|
||||
return sys_pwrite(fd, iov[0].iov_base, iov[0].iov_len, off, off);
|
||||
if (IsMetal()) {
|
||||
return espipe(); // must be serial or console if not zipos
|
||||
}
|
||||
|
||||
/*
|
||||
* NT, 2018-era XNU, and 2007-era Linux don't support this system call
|
||||
*/
|
||||
if (!once) {
|
||||
err = errno;
|
||||
rc = sys_pwritev(fd, iov, iovlen, off, off);
|
||||
if (rc == -1 && errno == ENOSYS) {
|
||||
errno = err;
|
||||
once = true;
|
||||
demodernize = true;
|
||||
STRACE("demodernizing %s() due to %s", "pwritev", "ENOSYS");
|
||||
} else {
|
||||
once = true;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!demodernize) {
|
||||
return sys_pwritev(fd, iov, iovlen, off, off);
|
||||
while (iovlen && !iov->iov_len) {
|
||||
--iovlen;
|
||||
++iov;
|
||||
}
|
||||
|
||||
if (!iovlen) {
|
||||
return sys_pwrite(fd, NULL, 0, off, off);
|
||||
return sys_pwrite(fd, 0, 0, off, off);
|
||||
}
|
||||
|
||||
if (iovlen == 1) {
|
||||
return sys_pwrite(fd, iov->iov_base, iov->iov_len, off, off);
|
||||
}
|
||||
|
||||
e = errno;
|
||||
rc = sys_pwritev(fd, iov, iovlen, off, off);
|
||||
if (rc != -1 || errno != ENOSYS) return rc;
|
||||
errno = e;
|
||||
|
||||
for (toto = i = 0; i < iovlen; ++i) {
|
||||
rc = sys_pwrite(fd, iov[i].iov_base, iov[i].iov_len, off, off);
|
||||
if (rc == -1) {
|
||||
if (toto && (errno == EINTR || errno == EAGAIN)) {
|
||||
return toto;
|
||||
} else {
|
||||
return -1;
|
||||
if (!toto) {
|
||||
toto = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
sent = rc;
|
||||
toto += sent;
|
||||
off += sent;
|
||||
if (sent != iov[i].iov_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!masked) {
|
||||
sigfillset(&mask);
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
|
||||
masked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (masked) {
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
|
||||
}
|
||||
|
||||
return toto;
|
||||
|
|
|
@ -16,14 +16,16 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/calls/wincrash.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
@ -35,8 +37,10 @@
|
|||
|
||||
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||
size_t size, ssize_t offset) {
|
||||
int64_t p;
|
||||
uint32_t got, avail;
|
||||
struct NtOverlapped overlap;
|
||||
|
||||
if (GetFileType(fd->handle) == kNtFileTypePipe) {
|
||||
for (;;) {
|
||||
if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break;
|
||||
|
@ -52,10 +56,20 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
|||
}
|
||||
POLLTRACE("sys_read_nt ready to read");
|
||||
}
|
||||
|
||||
if (offset != -1) {
|
||||
// windows changes the file pointer even if overlapped is passed
|
||||
_npassert(SetFilePointerEx(fd->handle, 0, &p, SEEK_CUR));
|
||||
}
|
||||
|
||||
if (ReadFile(fd->handle, data, _clampio(size), &got,
|
||||
_offset2overlap(fd->handle, offset, &overlap))) {
|
||||
if (offset != -1) {
|
||||
_npassert(SetFilePointerEx(fd->handle, p, 0, SEEK_SET));
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
switch (GetLastError()) {
|
||||
case kNtErrorBrokenPipe: // broken pipe
|
||||
case kNtErrorNoData: // closing named pipe
|
||||
|
@ -73,6 +87,7 @@ textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov,
|
|||
ssize_t rc;
|
||||
uint32_t size;
|
||||
size_t i, total;
|
||||
if (opt_offset < -1) return einval();
|
||||
if (_check_interrupts(true, fd)) return eintr();
|
||||
while (iovlen && !iov[0].iov_len) iov++, iovlen--;
|
||||
if (iovlen) {
|
||||
|
|
|
@ -18,7 +18,7 @@ int sys_sched_setscheduler(int, int, const struct sched_param *);
|
|||
int sys_sched_yield(void) hidden;
|
||||
int64_t sys_sched_getaffinity(int, uint64_t, void *) hidden;
|
||||
|
||||
int sys_sched_getscheduler_netbsd(int);
|
||||
int sys_sched_getscheduler_netbsd(int, struct sched_param *);
|
||||
int sys_sched_setparam_netbsd(int, int, int, const struct sched_param *) //
|
||||
asm("sys_sched_setparam");
|
||||
int sys_sched_getparam_netbsd(int, int, int *, struct sched_param *) //
|
||||
|
|
|
@ -16,11 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/cpuset.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thread.h"
|
||||
|
@ -52,7 +54,7 @@ static textwindows int sys_sched_getaffinity_nt(int tid, size_t size,
|
|||
* @param bitset receives bitset and should be uint64_t[16] in order to
|
||||
* work on older versions of Linux
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS on non-Linux
|
||||
* @raise ENOSYS if not Linux, NetBSD, or Windows
|
||||
*/
|
||||
int sched_getaffinity(int tid, size_t size, cpu_set_t *bitset) {
|
||||
int rc;
|
||||
|
@ -60,6 +62,12 @@ int sched_getaffinity(int tid, size_t size, cpu_set_t *bitset) {
|
|||
rc = einval();
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_sched_getaffinity_nt(tid, size, bitset);
|
||||
} else if (IsNetbsd()) {
|
||||
if (!sys_sched_getaffinity_netbsd(0, tid, MIN(size, 32), bitset)) {
|
||||
rc = MIN(size, 32);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
} else {
|
||||
rc = sys_sched_getaffinity(tid, size, bitset);
|
||||
}
|
||||
|
|
|
@ -18,13 +18,31 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Gets scheduler policy parameter.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS on XNU, Windows
|
||||
* @raise ENOSYS on XNU, Windows, OpenBSD
|
||||
*/
|
||||
int sched_getparam(int pid, struct sched_param *param) {
|
||||
return sys_sched_getparam(pid, param);
|
||||
int rc;
|
||||
struct sched_param p;
|
||||
if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) {
|
||||
rc = efault();
|
||||
} else if (IsNetbsd()) {
|
||||
if (!(rc = sys_sched_getscheduler_netbsd(pid, &p))) {
|
||||
*param = p;
|
||||
}
|
||||
} else {
|
||||
rc = sys_sched_getparam(pid, param);
|
||||
}
|
||||
STRACE("sched_getparam(%d, [%s]) → %d% m", pid, DescribeSchedParam(param),
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -20,10 +20,9 @@
|
|||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
|
||||
int sys_sched_getscheduler_netbsd(int pid) {
|
||||
int sys_sched_getscheduler_netbsd(int pid, struct sched_param *sp) {
|
||||
int policy;
|
||||
struct sched_param sp;
|
||||
if (sys_sched_getparam_netbsd(pid, P_ALL_LWPS, &policy, &sp) != -1) {
|
||||
if (sys_sched_getparam_netbsd(pid, P_ALL_LWPS, &policy, sp) != -1) {
|
||||
return policy;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Gets scheduler policy for `pid`.
|
||||
|
@ -40,7 +40,8 @@
|
|||
int sched_getscheduler(int pid) {
|
||||
int rc;
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_getscheduler_netbsd(pid);
|
||||
struct sched_param p;
|
||||
rc = sys_sched_getscheduler_netbsd(pid, &p);
|
||||
} else {
|
||||
rc = sys_sched_getscheduler(pid);
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/cpuset.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/processaccess.h"
|
||||
#include "libc/nt/enum/threadaccess.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
@ -34,14 +35,14 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows dontinline int sys_sched_setaffinity_nt(int pid,
|
||||
uint64_t bitsetsize,
|
||||
uint64_t size,
|
||||
const void *bitset) {
|
||||
int rc;
|
||||
uintptr_t mask;
|
||||
int64_t handle;
|
||||
uintptr_t mask;
|
||||
typeof(SetThreadAffinityMask) *SetAffinityMask = SetThreadAffinityMask;
|
||||
mask = 0;
|
||||
memcpy(&mask, bitset, min(bitsetsize, sizeof(uintptr_t)));
|
||||
memcpy(&mask, bitset, min(size, sizeof(uintptr_t)));
|
||||
handle = 0;
|
||||
if (!pid) pid = GetCurrentThreadId();
|
||||
if (0 < pid && pid <= UINT32_MAX) {
|
||||
|
@ -69,19 +70,21 @@ static textwindows dontinline int sys_sched_setaffinity_nt(int pid,
|
|||
* Asks kernel to only schedule thread on particular CPUs.
|
||||
*
|
||||
* @param tid is the process or thread id (or 0 for caller)
|
||||
* @param bitsetsize is byte length of bitset, which should be 128
|
||||
* @param size is byte length of bitset, which should be 128
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS if not Linux or Windows
|
||||
* @raise ENOSYS if not Linux, NetBSD, or Windows
|
||||
*/
|
||||
int sched_setaffinity(int tid, size_t bitsetsize, const cpu_set_t *bitset) {
|
||||
int sched_setaffinity(int tid, size_t size, const cpu_set_t *bitset) {
|
||||
int rc;
|
||||
if (bitsetsize != 128) {
|
||||
if (size != 128) {
|
||||
rc = einval();
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_sched_setaffinity_nt(tid, bitsetsize, bitset);
|
||||
rc = sys_sched_setaffinity_nt(tid, size, bitset);
|
||||
} else if (IsNetbsd()) {
|
||||
rc = sys_sched_setaffinity_netbsd(0, tid, MIN(size, 32), bitset);
|
||||
} else {
|
||||
rc = sys_sched_setaffinity(tid, bitsetsize, bitset);
|
||||
rc = sys_sched_setaffinity(tid, size, bitset);
|
||||
}
|
||||
STRACE("sched_setaffinity(%d, %'zu, %p) → %d% m", tid, bitsetsize, bitset);
|
||||
STRACE("sched_setaffinity(%d, %'zu, %p) → %d% m", tid, size, bitset);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,30 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets scheduler policy parameter.
|
||||
* @raise ENOSYS on XNU, Windows
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS on XNU, Windows, OpenBSD
|
||||
*/
|
||||
int sched_setparam(int pid, const struct sched_param *param) {
|
||||
return sys_sched_setparam(pid, param);
|
||||
int rc, policy;
|
||||
struct sched_param p;
|
||||
if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) {
|
||||
rc = efault();
|
||||
} else if (IsNetbsd()) {
|
||||
if ((rc = policy = sys_sched_getscheduler_netbsd(pid, &p)) != -1) {
|
||||
rc = sys_sched_setparam_netbsd(pid, P_ALL_LWPS, policy, param);
|
||||
}
|
||||
} else {
|
||||
rc = sys_sched_setparam(pid, param);
|
||||
}
|
||||
STRACE("sched_setparam(%d, %s) → %d% m", pid, DescribeSchedParam(param), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
* Sets scheduling policy of process, e.g.
|
||||
|
@ -94,9 +94,10 @@
|
|||
*/
|
||||
int sched_setscheduler(int pid, int policy, const struct sched_param *param) {
|
||||
int rc, old;
|
||||
struct sched_param p;
|
||||
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_getscheduler_netbsd(pid);
|
||||
rc = sys_sched_getscheduler_netbsd(pid, &p);
|
||||
} else {
|
||||
rc = sys_sched_getscheduler(pid);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
|
@ -26,6 +28,7 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -35,12 +38,25 @@
|
|||
|
||||
static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
||||
ssize_t offset) {
|
||||
int64_t h, p;
|
||||
uint32_t err, sent;
|
||||
struct NtOverlapped overlap;
|
||||
if (WriteFile(g_fds.p[fd].handle, data, _clampio(size), &sent,
|
||||
_offset2overlap(g_fds.p[fd].handle, offset, &overlap))) {
|
||||
|
||||
h = g_fds.p[fd].handle;
|
||||
|
||||
if (offset != -1) {
|
||||
// windows changes the file pointer even if overlapped is passed
|
||||
_npassert(SetFilePointerEx(h, 0, &p, SEEK_CUR));
|
||||
}
|
||||
|
||||
if (WriteFile(h, data, _clampio(size), &sent,
|
||||
_offset2overlap(h, offset, &overlap))) {
|
||||
if (offset != -1) {
|
||||
_npassert(SetFilePointerEx(h, p, 0, SEEK_SET));
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
switch (GetLastError()) {
|
||||
// case kNtErrorInvalidHandle:
|
||||
// return ebadf(); /* handled by consts.sh */
|
||||
|
@ -68,6 +84,7 @@ textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen,
|
|||
size_t i, total;
|
||||
uint32_t size, wrote;
|
||||
struct NtOverlapped overlap;
|
||||
if (opt_offset < -1) return einval();
|
||||
while (iovlen && !iov[0].iov_len) iov++, iovlen--;
|
||||
if (iovlen) {
|
||||
for (total = i = 0; i < iovlen; ++i) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/fmt/bing.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Turns binary octet into unicode glyph representation.
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/fmt.internal.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
|
@ -26,6 +25,7 @@
|
|||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/strwidth.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/str/unicode.h"
|
||||
#include "libc/str/utf16.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes 128-bit signed integer from ASCII string.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes intmax_t from ASCII string.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes signed integer from ASCII string.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes 128-bit unsigned integer from ASCII string.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes unsigned integer from ASCII string.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes uintmax_t from ASCII string.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
static const int kCp437iMultimappings[] = {
|
||||
u'\n' << 8 | '\n', // NEWLINE
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/oldutf16.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/str/tpdecodecb.internal.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes 128-bit signed integer from wide string.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes intmax_t from wide string.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes signed long integer from wide string.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes signed long long integer from wide string.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes 128-bit unsigned integer from wide string.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes unsigned integer from wide string.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes unsigned long long integer from wide string.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/strtol.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Decodes uintmax_t from wide string.
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ const char *DescribeNtFileFlagAttr(char[256], uint32_t);
|
|||
const char *DescribeNtFileMapFlags(char[64], uint32_t);
|
||||
const char *DescribeNtFileShareFlags(char[64], uint32_t);
|
||||
const char *DescribeNtFiletypeFlags(char[64], uint32_t);
|
||||
const char *DescribeNtLockFileFlags(char[64], uint32_t);
|
||||
const char *DescribeNtMovFileInpFlags(char[256], uint32_t);
|
||||
const char *DescribeNtPageFlags(char[64], uint32_t);
|
||||
const char *DescribeNtPipeModeFlags(char[64], uint32_t);
|
||||
|
@ -72,6 +73,7 @@ const char *DescribeWhence(char[12], int);
|
|||
#define DescribeNtFileMapFlags(x) DescribeNtFileMapFlags(alloca(64), x)
|
||||
#define DescribeNtFileShareFlags(x) DescribeNtFileShareFlags(alloca(64), x)
|
||||
#define DescribeNtFiletypeFlags(x) DescribeNtFiletypeFlags(alloca(64), x)
|
||||
#define DescribeNtLockFileFlags(x) DescribeNtLockFileFlags(alloca(64), x)
|
||||
#define DescribeNtMovFileInpFlags(x) DescribeNtMovFileInpFlags(alloca(256), x)
|
||||
#define DescribeNtPageFlags(x) DescribeNtPageFlags(alloca(64), x)
|
||||
#define DescribeNtPipeModeFlags(x) DescribeNtPipeModeFlags(alloca(64), x)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
char *DescribeMagnum(char *b, const struct MagnumStr *m, const char *p, int x) {
|
||||
char *s;
|
||||
if (x == 127) return "CLOCK_INVALID";
|
||||
if ((s = GetMagnumStr(m, x))) {
|
||||
stpcpy(stpcpy(b, p), s);
|
||||
return b;
|
||||
|
|
31
libc/intrin/describentlockfileflags.c
Normal file
31
libc/intrin/describentlockfileflags.c
Normal 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/intrin/describeflags.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
|
||||
static const struct DescribeFlags kNtLockFileFlags[] = {
|
||||
{kNtLockfileFailImmediately, "FailImmediately"}, //
|
||||
{kNtLockfileExclusiveLock, "ExclusiveLock"}, //
|
||||
};
|
||||
|
||||
const char *(DescribeNtLockFileFlags)(char buf[64], uint32_t x) {
|
||||
return DescribeFlags(buf, 64, kNtLockFileFlags, ARRAYLEN(kNtLockFileFlags),
|
||||
"kNtLockfile", x);
|
||||
}
|
49
libc/intrin/describentoverlapped.c
Normal file
49
libc/intrin/describentoverlapped.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
const char *(DescribeNtOverlapped)(char b[128], struct NtOverlapped *o) {
|
||||
int i = 0, n = 128;
|
||||
bool gotsome = false;
|
||||
if (!o) return "NULL";
|
||||
i += ksnprintf(b + i, MAX(0, n - i), "{");
|
||||
|
||||
if (o->hEvent) {
|
||||
if (gotsome) {
|
||||
i += ksnprintf(b + i, MAX(0, n - i), ", ");
|
||||
} else {
|
||||
gotsome = true;
|
||||
}
|
||||
i += ksnprintf(b + i, MAX(0, n - i), ".hEvent = %ld", o->hEvent);
|
||||
}
|
||||
|
||||
if (o->Pointer) {
|
||||
if (gotsome) {
|
||||
i += ksnprintf(b + i, MAX(0, n - i), ", ");
|
||||
} else {
|
||||
gotsome = true;
|
||||
}
|
||||
i += ksnprintf(b + i, MAX(0, n - i), ".Pointer = (void *)%p", o->Pointer);
|
||||
}
|
||||
|
||||
i += ksnprintf(b + i, MAX(0, n - i), "}");
|
||||
return b;
|
||||
}
|
13
libc/intrin/describentoverlapped.internal.h
Normal file
13
libc/intrin/describentoverlapped.internal.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
const char *DescribeNtOverlapped(char[128], struct NtOverlapped *);
|
||||
#define DescribeNtOverlapped(x) DescribeNtOverlapped(alloca(128), x)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_ */
|
|
@ -16,8 +16,9 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
@ -40,8 +41,9 @@ textwindows bool32 DeviceIoControl(int64_t hDevice, uint32_t dwIoControlCode,
|
|||
nInBufferSize, lpOutBuffer, nOutBufferSize,
|
||||
lpBytesReturned, lpOverlapped);
|
||||
if (!ok) __winerr();
|
||||
NTTRACE("DeviceIoControl(%ld, %#x, %p, %'zu, %p, %'zu, %p, %p) → %hhhd% m",
|
||||
NTTRACE("DeviceIoControl(%ld, %#x, %p, %'zu, %p, %'zu, %p, %s) → %hhhd% m",
|
||||
hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
|
||||
nOutBufferSize, lpBytesReturned, lpOverlapped, ok);
|
||||
nOutBufferSize, lpBytesReturned, DescribeNtOverlapped(lpOverlapped),
|
||||
ok);
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -33,17 +33,24 @@
|
|||
kClockNames:
|
||||
.e CLOCK_REALTIME,"REALTIME"
|
||||
.e CLOCK_REALTIME_FAST,"REALTIME_FAST"
|
||||
.e CLOCK_REALTIME_PRECISE,"REALTIME_PRECISE"
|
||||
.e CLOCK_MONOTONIC,"MONOTONIC"
|
||||
.e CLOCK_MONOTONIC_FAST,"MONOTONIC_FAST"
|
||||
.e CLOCK_MONOTONIC_RAW,"MONOTONIC_RAW"
|
||||
.e CLOCK_MONOTONIC_PRECISE,"MONOTONIC_PRECISE"
|
||||
.e CLOCK_REALTIME_COARSE,"REALTIME_COARSE"
|
||||
.e CLOCK_MONOTONIC_COARSE,"MONOTONIC_COARSE"
|
||||
.e CLOCK_PROCESS_CPUTIME_ID,"PROCESS_CPUTIME_ID"
|
||||
.e CLOCK_THREAD_CPUTIME_ID,"THREAD_CPUTIME_ID"
|
||||
.e CLOCK_TAI,"TAI"
|
||||
.e CLOCK_PROF,"PROF"
|
||||
.e CLOCK_BOOTTIME,"BOOTTIME"
|
||||
.e CLOCK_REALTIME_ALARM,"REALTIME_ALARM"
|
||||
.e CLOCK_BOOTTIME_ALARM,"BOOTTIME_ALARM"
|
||||
.e CLOCK_UPTIME,"UPTIME"
|
||||
.e CLOCK_UPTIME_FAST,"UPTIME_FAST"
|
||||
.e CLOCK_UPTIME_PRECISE,"UPTIME_PRECISE"
|
||||
.e CLOCK_SECOND,"SECOND"
|
||||
.long MAGNUM_TERMINATOR
|
||||
.endobj kClockNames,globl,hidden
|
||||
.overrun
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
|
50
libc/intrin/lockfileex.c
Normal file
50
libc/intrin/lockfileex.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
__msabi extern typeof(LockFileEx) *const __imp_LockFileEx;
|
||||
|
||||
/**
|
||||
* Locks file on the New Technology.
|
||||
*
|
||||
* @return handle, or -1 on failure
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
bool32 LockFileEx(int64_t hFile, uint32_t dwFlags, uint32_t dwReserved,
|
||||
uint32_t nNumberOfBytesToLockLow,
|
||||
uint32_t nNumberOfBytesToLockHigh,
|
||||
struct NtOverlapped *lpOverlapped) {
|
||||
bool32 ok;
|
||||
STRACE("LockFileEx(%ld, %s, %#x, %'zu, %s) → ...", hFile,
|
||||
DescribeNtLockFileFlags(dwFlags), dwReserved,
|
||||
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
|
||||
DescribeNtOverlapped(lpOverlapped));
|
||||
ok = __imp_LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow,
|
||||
nNumberOfBytesToLockHigh, lpOverlapped);
|
||||
if (!ok) __winerr();
|
||||
STRACE("LockFileEx(%ld, %s, %#x, %'zu, [%s]) → %hhhd% m", hFile,
|
||||
DescribeNtLockFileFlags(dwFlags), dwReserved,
|
||||
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
|
||||
DescribeNtOverlapped(lpOverlapped), ok);
|
||||
return ok;
|
||||
}
|
50
libc/intrin/unlockfileex.c
Normal file
50
libc/intrin/unlockfileex.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
__msabi extern typeof(UnlockFileEx) *const __imp_UnlockFileEx;
|
||||
|
||||
/**
|
||||
* Unlocks file on the New Technology.
|
||||
*
|
||||
* @return handle, or -1 on failure
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
bool32 UnlockFileEx(int64_t hFile, uint32_t dwReserved,
|
||||
uint32_t nNumberOfBytesToUnlockLow,
|
||||
uint32_t nNumberOfBytesToUnlockHigh,
|
||||
struct NtOverlapped *lpOverlapped) {
|
||||
bool32 ok;
|
||||
STRACE("UnlockFileEx(%ld, %#x, %'zu, %s) → ...", hFile, dwReserved,
|
||||
(uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow,
|
||||
DescribeNtOverlapped(lpOverlapped));
|
||||
ok = __imp_UnlockFileEx(hFile, dwReserved, nNumberOfBytesToUnlockLow,
|
||||
nNumberOfBytesToUnlockHigh, lpOverlapped);
|
||||
if (!ok) __winerr();
|
||||
STRACE("UnlockFileEx(%ld, %#x, %'zu, [%s]) → %hhhd% m", hFile, dwReserved,
|
||||
(uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow,
|
||||
DescribeNtOverlapped(lpOverlapped), ok);
|
||||
return ok;
|
||||
}
|
|
@ -16,10 +16,11 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
|
||||
|
@ -55,8 +56,9 @@ textwindows int WSARecv(
|
|||
kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s);
|
||||
DescribeIovNt(inout_lpBuffers, dwBufferCount,
|
||||
rc != -1 ? NumberOfBytesRecvd : 0);
|
||||
kprintf("], %u, [%'u], %p, %p, %p) → %d% lm\n", dwBufferCount,
|
||||
NumberOfBytesRecvd, inout_lpFlags, opt_inout_lpOverlapped,
|
||||
kprintf("], %u, [%'u], %p, %s, %p) → %d% lm\n", dwBufferCount,
|
||||
NumberOfBytesRecvd, inout_lpFlags,
|
||||
DescribeNtOverlapped(opt_inout_lpOverlapped),
|
||||
opt_lpCompletionRoutine, rc);
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
|
||||
|
@ -57,9 +58,10 @@ textwindows int WSARecvFrom(
|
|||
kprintf(STRACE_PROLOGUE "WSARecvFrom(%lu, [", s);
|
||||
DescribeIovNt(inout_lpBuffers, dwBufferCount,
|
||||
rc != -1 ? NumberOfBytesRecvd : 0);
|
||||
kprintf("], %u, [%'u], %p, %p, %p, %p, %p) → %d% lm\n", dwBufferCount,
|
||||
kprintf("], %u, [%'u], %p, %p, %p, %s, %p) → %d% lm\n", dwBufferCount,
|
||||
NumberOfBytesRecvd, opt_out_fromsockaddr, opt_inout_fromsockaddrlen,
|
||||
inout_lpFlags, opt_inout_lpOverlapped, opt_lpCompletionRoutine, rc);
|
||||
inout_lpFlags, DescribeNtOverlapped(opt_inout_lpOverlapped),
|
||||
opt_lpCompletionRoutine, rc);
|
||||
}
|
||||
#else
|
||||
rc = __imp_WSARecvFrom(s, inout_lpBuffers, dwBufferCount,
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
#define kNtErrorTooManyTcbs 155
|
||||
#define kNtErrorSignalRefused 156
|
||||
#define kNtErrorDiscarded 157
|
||||
#define kNtErrorNotLocked 158
|
||||
#define kNtErrorNotLocked 158 /* ENOLCK */
|
||||
#define kNtErrorBadThreadidAddr 159
|
||||
#define kNtErrorBadArguments 160
|
||||
#define kNtErrorBadPathname 161
|
||||
|
@ -1531,7 +1531,7 @@
|
|||
#define kNtErrorLogSectorParityInvalid 6601
|
||||
#define kNtErrorLogSectorRemapped 6602
|
||||
#define kNtErrorLogBlockIncomplete 6603
|
||||
#define kNtErrorLogInvalidRange 6604
|
||||
#define kNtErrorLogInvalidRange 6604 /* ERANGE */
|
||||
#define kNtErrorLogBlocksExhausted 6605
|
||||
#define kNtErrorLogReadContextInvalid 6606
|
||||
#define kNtErrorLogRestartInvalid 6607
|
||||
|
|
|
@ -116,13 +116,13 @@ bool32 DeviceIoControl(int64_t hDevice, uint32_t dwIoControlCode,
|
|||
bool32 LockFile(int64_t hFile, uint32_t dwFileOffsetLow,
|
||||
uint32_t dwFileOffsetHigh, uint32_t nNumberOfBytesToLockLow,
|
||||
uint32_t nNumberOfBytesToLockHigh);
|
||||
bool32 UnlockFile(int64_t hFile, uint32_t dwFileOffsetLow,
|
||||
uint32_t dwFileOffsetHigh, uint32_t nNumberOfBytesToUnlockLow,
|
||||
uint32_t nNumberOfBytesToUnlockHigh);
|
||||
bool32 LockFileEx(int64_t hFile, uint32_t dwFlags, uint32_t dwReserved,
|
||||
uint32_t nNumberOfBytesToLockLow,
|
||||
uint32_t nNumberOfBytesToLockHigh,
|
||||
struct NtOverlapped *lpOverlapped) paramsnonnull();
|
||||
bool32 UnlockFile(int64_t hFile, uint32_t dwFileOffsetLow,
|
||||
uint32_t dwFileOffsetHigh, uint32_t nNumberOfBytesToUnlockLow,
|
||||
uint32_t nNumberOfBytesToUnlockHigh);
|
||||
bool32 UnlockFileEx(int64_t hFile, uint32_t dwReserved,
|
||||
uint32_t nNumberOfBytesToUnlockLow,
|
||||
uint32_t nNumberOfBytesToUnlockHigh,
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
.imp kernel32,__imp_LockFileEx,LockFileEx,0
|
||||
|
||||
.text.windows
|
||||
LockFileEx:
|
||||
__LockFileEx:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_LockFileEx(%rip),%rax
|
||||
jmp __sysv2nt6
|
||||
.endfn LockFileEx,globl
|
||||
.endfn __LockFileEx,globl
|
||||
.previous
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
.imp kernel32,__imp_UnlockFileEx,UnlockFileEx,0
|
||||
|
||||
.text.windows
|
||||
UnlockFileEx:
|
||||
__UnlockFileEx:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_UnlockFileEx(%rip),%rax
|
||||
jmp __sysv2nt6
|
||||
.endfn UnlockFileEx,globl
|
||||
.endfn __UnlockFileEx,globl
|
||||
.previous
|
||||
|
|
|
@ -700,7 +700,6 @@ imp 'LocalUnlock' LocalUnlock kernel32 0
|
|||
imp 'LocaleNameToLCID' LocaleNameToLCID kernel32 0
|
||||
imp 'LocateXStateFeature' LocateXStateFeature kernel32 0
|
||||
imp 'LockFile' LockFile kernel32 0 5
|
||||
imp 'LockFileEx' LockFileEx kernel32 0 6
|
||||
imp 'LockResource' LockResource kernel32 0 1
|
||||
imp 'MapUserPhysicalPages' MapUserPhysicalPages kernel32 0
|
||||
imp 'MapUserPhysicalPagesScatter' MapUserPhysicalPagesScatter kernel32 986
|
||||
|
@ -1024,7 +1023,6 @@ imp 'UTUnRegister' UTUnRegister kernel32 1459
|
|||
imp 'UmsThreadYield' UmsThreadYield kernel32 1460
|
||||
imp 'UnhandledExceptionFilter' UnhandledExceptionFilter kernel32 0
|
||||
imp 'UnlockFile' UnlockFile kernel32 0 5
|
||||
imp 'UnlockFileEx' UnlockFileEx kernel32 0 5
|
||||
imp 'UnmapViewOfFile2' UnmapViewOfFile2 kernel32 0 2
|
||||
imp 'UnmapViewOfFileEx' UnmapViewOfFileEx kernel32 0 3
|
||||
imp 'UnregisterApplicationRecoveryCallback' UnregisterApplicationRecoveryCallback kernel32 1466
|
||||
|
@ -1120,6 +1118,7 @@ imp '__FlushViewOfFile' FlushViewOfFile kernel32 0 2
|
|||
imp '__GenerateConsoleCtrlEvent' GenerateConsoleCtrlEvent kernel32 0 2
|
||||
imp '__GetExitCodeProcess' GetExitCodeProcess kernel32 0 2
|
||||
imp '__GetFileAttributes' GetFileAttributesW kernel32 0 1
|
||||
imp '__LockFileEx' LockFileEx kernel32 0 6
|
||||
imp '__MapViewOfFileEx' MapViewOfFileEx kernel32 0 6
|
||||
imp '__MapViewOfFileExNuma' MapViewOfFileExNuma kernel32 0 7
|
||||
imp '__MoveFileEx' MoveFileExW kernel32 0 3
|
||||
|
@ -1128,6 +1127,7 @@ imp '__ReOpenFile' ReOpenFile kernel32 0 4 # TODO(jart): 6.2 and highe
|
|||
imp '__RemoveDirectory' RemoveDirectoryW kernel32 0 1
|
||||
imp '__SetCurrentDirectory' SetCurrentDirectoryW kernel32 0 1
|
||||
imp '__TerminateProcess' TerminateProcess kernel32 0 2
|
||||
imp '__UnlockFileEx' UnlockFileEx kernel32 0 5
|
||||
imp '__UnmapViewOfFile' UnmapViewOfFile kernel32 0 1
|
||||
imp '__VirtualProtect' VirtualProtect kernel32 0 4
|
||||
imp '__WaitForMultipleObjects' WaitForMultipleObjects kernel32 0 4
|
||||
|
|
|
@ -38,7 +38,7 @@ FILE *fdopen(int fd, const char *mode) {
|
|||
f->fd = fd;
|
||||
f->bufmode = ischardev(fd) ? _IOLBF : _IOFBF;
|
||||
f->iomode = fopenflags(mode);
|
||||
f->lock._type = PTHREAD_MUTEX_RECURSIVE;
|
||||
((pthread_mutex_t *)f->lock)->_type = PTHREAD_MUTEX_RECURSIVE;
|
||||
f->size = BUFSIZ;
|
||||
if ((f->buf = malloc(f->size))) {
|
||||
if ((f->iomode & O_ACCMODE) != O_RDONLY) {
|
||||
|
|
|
@ -23,5 +23,5 @@
|
|||
* Acquires reentrant lock on stdio object, blocking if needed.
|
||||
*/
|
||||
void(flockfile)(FILE *f) {
|
||||
pthread_mutex_lock(&f->lock);
|
||||
pthread_mutex_lock((pthread_mutex_t *)f->lock);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ FILE *fmemopen(void *buf, size_t size, const char *mode) {
|
|||
f->end = size;
|
||||
f->size = size;
|
||||
f->iomode = fopenflags(mode);
|
||||
f->lock._type = PTHREAD_MUTEX_RECURSIVE;
|
||||
((pthread_mutex_t *)f->lock)->_type = PTHREAD_MUTEX_RECURSIVE;
|
||||
if (f->iomode & O_APPEND) {
|
||||
if ((p = memchr(buf, '\0', size))) {
|
||||
f->beg = p - (char *)buf;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/lock.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
|
@ -24,5 +25,5 @@
|
|||
* @return 0 on success, or non-zero if another thread owns the lock
|
||||
*/
|
||||
int(ftrylockfile)(FILE *f) {
|
||||
return pthread_mutex_trylock(&f->lock);
|
||||
return pthread_mutex_trylock((pthread_mutex_t *)f->lock);
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/lock.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Releases lock on stdio object.
|
||||
*/
|
||||
void(funlockfile)(FILE *f) {
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
pthread_mutex_unlock((pthread_mutex_t *)f->lock);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,6 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
compatfn char *gets(char *s) {
|
||||
char *gets(char *s) {
|
||||
return fgets(s, INT_MAX, stdin);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STDIO_STDIO_H_
|
||||
#define COSMOPOLITAN_LIBC_STDIO_STDIO_H_
|
||||
#include "libc/fmt/pflink.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H
|
||||
#include "libc/fmt/pflink.h"
|
||||
|
||||
#define L_ctermid 20
|
||||
#define FILENAME_MAX PATH_MAX
|
||||
#define FOPEN_MAX 1000
|
||||
|
@ -17,19 +15,19 @@ COSMOPOLITAN_C_START_
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
typedef struct FILE {
|
||||
uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */
|
||||
bool noclose; /* 0x01 for fake dup() todo delete! */
|
||||
uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */
|
||||
int32_t state; /* 0x08 0=OK, -1=EOF, >0=errno */
|
||||
int fd; /* 0x0c ≥0=fd, -1=closed|buffer */
|
||||
uint32_t beg; /* 0x10 */
|
||||
uint32_t end; /* 0x14 */
|
||||
char *buf; /* 0x18 */
|
||||
uint32_t size; /* 0x20 */
|
||||
uint32_t nofree; /* 0x24 */
|
||||
int pid; /* 0x28 */
|
||||
char *getln; /* 0x30 */
|
||||
pthread_mutex_t lock; /* 0x38 */
|
||||
uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */
|
||||
bool noclose; /* 0x01 for fake dup() todo delete! */
|
||||
uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */
|
||||
int32_t state; /* 0x08 0=OK, -1=EOF, >0=errno */
|
||||
int fd; /* 0x0c ≥0=fd, -1=closed|buffer */
|
||||
uint32_t beg; /* 0x10 */
|
||||
uint32_t end; /* 0x14 */
|
||||
char *buf; /* 0x18 */
|
||||
uint32_t size; /* 0x20 */
|
||||
uint32_t nofree; /* 0x24 */
|
||||
int pid; /* 0x28 */
|
||||
char *getln; /* 0x30 */
|
||||
char lock[16]; /* 0x38 */
|
||||
} FILE;
|
||||
|
||||
extern FILE *stdin;
|
||||
|
@ -91,9 +89,9 @@ char *ctermid(char *);
|
|||
void perror(const char *) relegated;
|
||||
|
||||
typedef uint64_t fpos_t;
|
||||
compatfn char *gets(char *) paramsnonnull();
|
||||
compatfn int fgetpos(FILE *, fpos_t *) paramsnonnull();
|
||||
compatfn int fsetpos(FILE *, const fpos_t *) paramsnonnull();
|
||||
char *gets(char *) paramsnonnull();
|
||||
int fgetpos(FILE *, fpos_t *) paramsnonnull();
|
||||
int fsetpos(FILE *, const fpos_t *) paramsnonnull();
|
||||
|
||||
int system(const char *);
|
||||
int systemexec(const char *);
|
||||
|
@ -195,4 +193,4 @@ int vfprintf_unlocked(FILE *, const char *, va_list)
|
|||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STDIO_STDIO_H_ */
|
||||
#endif /* _STDIO_H */
|
||||
|
|
|
@ -18,40 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
void djbsort_avx2(int32_t *, long);
|
||||
|
||||
static dontinline void intsort(int *x, size_t n, size_t t) {
|
||||
int a, b, c;
|
||||
size_t i, p, q;
|
||||
for (p = t; p > 0; p >>= 1) {
|
||||
for (i = 0; i < n - p; ++i) {
|
||||
if (!(i & p)) {
|
||||
a = x[i + 0];
|
||||
b = x[i + p];
|
||||
if (a > b) c = a, a = b, b = c;
|
||||
x[i + 0] = a;
|
||||
x[i + p] = b;
|
||||
}
|
||||
}
|
||||
for (q = t; q > p; q >>= 1) {
|
||||
for (i = 0; i < n - q; ++i) {
|
||||
if (!(i & p)) {
|
||||
a = x[i + p];
|
||||
b = x[i + q];
|
||||
if (a > b) c = a, a = b, b = c;
|
||||
x[i + p] = a;
|
||||
x[i + q] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* D.J. Bernstein's outrageously fast integer sorting algorithm.
|
||||
*/
|
||||
|
@ -65,7 +36,7 @@ void djbsort(int32_t *a, size_t n) {
|
|||
if (X86_HAVE(AVX2)) {
|
||||
djbsort_avx2(a, n);
|
||||
} else {
|
||||
intsort(a, n, 1ul << _bsrl(n - 1));
|
||||
_intsort(a, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Compares memory case-insensitively.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
bool _startswithi(const char *s, const char *prefix) {
|
||||
for (;;) {
|
||||
|
|
|
@ -6,13 +6,6 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const int8_t kHexToInt[256];
|
||||
extern const uint8_t gperf_downcase[256];
|
||||
extern const uint8_t kToLower[256];
|
||||
extern const uint8_t kToUpper[256];
|
||||
extern const uint8_t kBase36[256];
|
||||
extern const char16_t kCp437[256];
|
||||
|
||||
int isascii(int);
|
||||
int isspace(int);
|
||||
int isalpha(int);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Compares NUL-terminated strings ascii case-insensitively.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
/**
|
||||
* Compares NUL-terminated strings case-insensitively w/ limit.
|
||||
|
|
15
libc/str/tab.internal.h
Normal file
15
libc/str/tab.internal.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TAB_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TAB_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const int8_t kHexToInt[256];
|
||||
extern const uint8_t gperf_downcase[256];
|
||||
extern const uint8_t kToLower[256];
|
||||
extern const uint8_t kToUpper[256];
|
||||
extern const uint8_t kBase36[256];
|
||||
extern const char16_t kCp437[256];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TAB_INTERNAL_H_ */
|
|
@ -57,11 +57,11 @@ syscon errno ESPIPE 29 29 29 29 29 25 # invalid seek; unix conse
|
|||
syscon errno EROFS 30 30 30 30 30 6009 # read-only filesystem; unix consensus; kNtErrorFileReadOnly; raised by access(2), acct(2), bind(2), chmod(2), chown(2), link(2), mkdir(2), mknod(2), mount(2), open(2), rename(2), rmdir(2), symlink(2), truncate(2), unlink(2), utime(2), utimensat(2)
|
||||
syscon errno EMLINK 31 31 31 31 31 1142 # too many links; unix consensus; kNtErrorTooManyLinks; raised by link(2), mkdir(2), rename(2)
|
||||
syscon errno EPIPE 32 32 32 32 32 109 # broken pipe; unix consensus; kNtErrorBrokenPipe; raised by send(2), write(2), tcp(7), unix(7), ip(7)
|
||||
syscon errno EDOM 33 33 33 33 33 33 # mathematics argument out of domain of function; bsd consensus; fudged on NT; returned by cos(3), fmod(3), log1p(3), sin(3), tan(3), tgamma(3)
|
||||
syscon errno ERANGE 34 34 34 34 34 34 # result too large; bsd consensus; fudged on NT; raised by getxattr(2), listxattr(2), lookup_dcookie(2), prctl(2), quotactl(2), semctl(2), semop(2), setxattr(2)
|
||||
syscon errno EDOM 33 33 33 33 33 20000 # mathematics argument out of domain of function; bsd consensus; made up on NT; returned by cos(3), fmod(3), log1p(3), sin(3), tan(3), tgamma(3)
|
||||
syscon errno ERANGE 34 34 34 34 34 6604 # result too large; bsd consensus; kNtErrorLogInvalidRange; raised by getxattr(2), listxattr(2), lookup_dcookie(2), prctl(2), quotactl(2), semctl(2), semop(2), setxattr(2)
|
||||
syscon errno EDEADLK 35 11 11 11 11 1131 # resource deadlock avoided; bsd consensus; kNtErrorPossibleDeadlock; raised by fcntl(2), keyctl(2)
|
||||
syscon errno ENAMETOOLONG 36 63 63 63 63 10063 # filename too long; bsd consensus; WSAENAMETOOLONG; raised by access(2), acct(2), bind(2), chdir(2), chmod(2), chown(2), chroot(2), execve(2), gethostname(2), inotify_add_watch(2), link(2), lookup_dcookie(2), mkdir(2), mknod(2), mount(2), open(2), readlink(2), rename(2), rmdir(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), truncate(2), umount(2), unlink(2), utimensat(2)
|
||||
syscon errno ENOLCK 37 77 77 77 77 0 # no locks available; bsd consensus; raised by fcntl(2), flock(2)
|
||||
syscon errno ENOLCK 37 77 77 77 77 158 # no locks available; kNtErrorNotLocked; bsd consensus; raised by fcntl(2), flock(2)
|
||||
syscon errno ENOTEMPTY 39 66 66 66 66 145 # directory not empty; bsd consensus; kNtErrorDirNotEmpty (TODO: What is WSAENOTEMPTY? 10066); raised by rmdir(2)
|
||||
syscon errno ELOOP 40 62 62 62 62 1921 # too many levels of symbolic links; bsd consensus; kNtErrorCantResolveFilename; raised by access(2), acct(2), bind(2), chdir(2), chmod(2), chown(2), chroot(2), epoll_ctl(2), execve(2), execveat(2), keyctl(2), link(2), mkdir(2), mknod(2), mount(2), open(2), open_by_handle_at(2), openat2(2), readlink(2), rename(2), rmdir(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), truncate(2), unlink(2), utimensat(2)
|
||||
syscon errno ENOMSG 42 91 83 90 83 0 # raised by msgop(2)
|
||||
|
@ -328,10 +328,10 @@ syscon access R_OK 4 4 4 4 4 0x80000000 # unix consensus and kNtG
|
|||
# flock() flags
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon lock LOCK_SH 1 1 1 1 1 0 # shared [unix consensus]
|
||||
syscon lock LOCK_SH 1 1 1 1 1 0 # shared [unix consensus]; hard-coded into flock-nt.c too
|
||||
syscon lock LOCK_EX 2 2 2 2 2 2 # exclusive [consensus!] a.k.a. kNtLockfileExclusiveLock
|
||||
syscon lock LOCK_NB 4 4 4 4 4 1 # non-blocking [unix consensus] a.k.a. kNtLockfileFailImmediately
|
||||
syscon lock LOCK_UN 8 8 8 8 8 8 # unlock [unix consensus & faked NT]
|
||||
syscon lock LOCK_UN 8 8 8 8 8 8 # unlock [unix consensus & faked NT]; hard-coded into flock-nt.c too
|
||||
|
||||
# waitpid() / wait4() options
|
||||
#
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,EAGAIN,11,35,35,35,35,10035
|
||||
.yoink kDos2Errno.EAGAIN
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,EDOM,33,33,33,33,33,33
|
||||
.syscon errno,EDOM,33,33,33,33,33,20000
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,ENOLCK,37,77,77,77,77,0
|
||||
.syscon errno,ENOLCK,37,77,77,77,77,158
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,ERANGE,34,34,34,34,34,34
|
||||
.syscon errno,ERANGE,34,34,34,34,34,6604
|
||||
|
|
|
@ -129,7 +129,7 @@ dos kNtErrorInvalidFunction EINVAL
|
|||
dos kNtErrorInvalidNetname EADDRNOTAVAIL
|
||||
dos kNtErrorInvalidUserBuffer EMSGSIZE
|
||||
dos kNtErrorIoPending EINPROGRESS
|
||||
dos kNtErrorLockViolation EACCES
|
||||
dos kNtErrorLockViolation EAGAIN
|
||||
dos kNtErrorMoreData EMSGSIZE
|
||||
dos kNtErrorNetnameDeleted ECONNABORTED
|
||||
dos kNtErrorNetworkAccessDenied EACCES
|
||||
|
@ -139,7 +139,6 @@ dos kNtErrorNonpagedSystemResources ENOMEM
|
|||
dos kNtErrorNotEnoughMemory ENOMEM
|
||||
dos kNtErrorNotEnoughQuota ENOMEM
|
||||
dos kNtErrorNotFound ENOENT
|
||||
dos kNtErrorNotLocked EACCES
|
||||
dos kNtErrorNotReady EACCES
|
||||
dos kNtErrorNotSupported ENOTSUP
|
||||
dos kNtErrorNoMoreFiles ENOENT
|
||||
|
|
|
@ -13,9 +13,7 @@ kDos2Errno.EACCES:
|
|||
.e kNtErrorCannotMake,EACCES
|
||||
.e kNtErrorCrc,EACCES
|
||||
.e kNtErrorGenFailure,EACCES
|
||||
.e kNtErrorLockViolation,EACCES
|
||||
.e kNtErrorNetworkAccessDenied,EACCES
|
||||
.e kNtErrorNotLocked,EACCES
|
||||
.e kNtErrorNotReady,EACCES
|
||||
.e kNtErrorOutOfPaper,EACCES
|
||||
.e kNtErrorSectorNotFound,EACCES
|
||||
|
|
11
libc/sysv/dos2errno/EAGAIN.S
Normal file
11
libc/sysv/dos2errno/EAGAIN.S
Normal file
|
@ -0,0 +1,11 @@
|
|||
// generated by libc/sysv/dos2errno.sh
|
||||
#include "libc/nt/errors.h"
|
||||
.macro .e doscode systemv
|
||||
.short \doscode
|
||||
.long \systemv
|
||||
.endm
|
||||
.section .sort.rodata.dos2errno.2,"a",@progbits
|
||||
.globl kDos2Errno.EAGAIN
|
||||
.type kDos2Errno.EAGAIN,@object
|
||||
kDos2Errno.EAGAIN:
|
||||
.e kNtErrorLockViolation,EAGAIN
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/url.h"
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/intrin/bswap.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
static const struct ContentTypeExtension {
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#line 1 "gethttpheader.gperf"
|
||||
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "net/http/http.h"
|
||||
#define GPERF_DOWNCASE
|
||||
#line 12 "gethttpheader.gperf"
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#line 1 "gethttpmethod.gperf"
|
||||
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "net/http/http.h"
|
||||
#define GPERF_DOWNCASE
|
||||
#line 12 "gethttpmethod.gperf"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/url.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/http.h"
|
||||
|
|
|
@ -30,8 +30,29 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
int Lock(int fd, int type, long start, long len) {
|
||||
int e;
|
||||
struct flock lock = {
|
||||
.l_type = type,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = start,
|
||||
.l_len = len,
|
||||
};
|
||||
e = errno;
|
||||
while (fcntl(fd, F_SETLK, &lock)) {
|
||||
if (errno == EAGAIN || errno == EACCES) {
|
||||
errno = e;
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
TEST(fcntl_getfl, testRemembersAccessMode) {
|
||||
|
@ -70,59 +91,15 @@ TEST(fcntl, getfd) {
|
|||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
void OnSig(int sig) {
|
||||
TEST(fcntl, F_DUPFD_CLOEXEC) {
|
||||
ASSERT_SYS(0, 3, open("/dev/null", O_RDWR));
|
||||
ASSERT_SYS(0, 5, fcntl(3, F_DUPFD_CLOEXEC, 5));
|
||||
ASSERT_SYS(0, FD_CLOEXEC, fcntl(5, F_GETFD));
|
||||
ASSERT_SYS(0, 0, close(5));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(posixAdvisoryLocks, oneProcess_unlockedFromOwnPerspectiveHuh) {
|
||||
struct flock lock;
|
||||
ASSERT_SYS(0, 3, open("foo", O_RDWR | O_CREAT | O_TRUNC, 0644));
|
||||
ASSERT_SYS(0, 5, write(3, "hello", 5));
|
||||
|
||||
// set lock
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 1;
|
||||
lock.l_len = 3;
|
||||
lock.l_pid = -2;
|
||||
ASSERT_SYS(0, 0, fcntl(3, F_SETLK, &lock));
|
||||
EXPECT_EQ(F_WRLCK, lock.l_type);
|
||||
EXPECT_EQ(SEEK_SET, lock.l_whence);
|
||||
EXPECT_EQ(1, lock.l_start);
|
||||
EXPECT_EQ(3, lock.l_len);
|
||||
EXPECT_EQ(-2, lock.l_pid);
|
||||
|
||||
ASSERT_SYS(0, 4, open("foo", O_RDWR));
|
||||
|
||||
// try lock
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
lock.l_pid = -1;
|
||||
ASSERT_SYS(0, 0, fcntl(4, F_SETLK, &lock));
|
||||
EXPECT_EQ(F_WRLCK, lock.l_type);
|
||||
EXPECT_EQ(SEEK_SET, lock.l_whence);
|
||||
EXPECT_EQ(0, lock.l_start);
|
||||
EXPECT_EQ(0, lock.l_len);
|
||||
EXPECT_EQ(-1, lock.l_pid);
|
||||
|
||||
// get lock information
|
||||
if (!IsWindows()) {
|
||||
lock.l_type = F_RDLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
lock.l_pid = -7;
|
||||
ASSERT_SYS(0, 0, fcntl(4, F_GETLK, &lock));
|
||||
EXPECT_EQ(F_UNLCK, lock.l_type);
|
||||
EXPECT_EQ(SEEK_SET, lock.l_whence);
|
||||
EXPECT_EQ(0, lock.l_start);
|
||||
EXPECT_EQ(0, lock.l_len);
|
||||
EXPECT_EQ(-7, lock.l_pid); // doesn't change due to F_UNLCK
|
||||
}
|
||||
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
void OnSig(int sig) {
|
||||
}
|
||||
|
||||
TEST(posixAdvisoryLocks, twoProcesses) {
|
||||
|
|
186
test/libc/calls/lock_test.c
Normal file
186
test/libc/calls/lock_test.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* @fileoverview POSIX Advisory Locks Test
|
||||
*/
|
||||
|
||||
#define PROCESSES 8
|
||||
#define THREADS (IsWindows() ? 8 : 0)
|
||||
#define RATIO 3
|
||||
#define ITERATIONS 10
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
_Thread_local const char *kind;
|
||||
|
||||
void Log(const char *fmt, ...) {
|
||||
#if 0
|
||||
va_list va;
|
||||
char b[512];
|
||||
int i, n = sizeof(b);
|
||||
va_start(va, fmt);
|
||||
i = ksnprintf(b, n, "%s pid=%d tid=%d ", kind, getpid(), gettid());
|
||||
i += kvsnprintf(b + i, MAX(0, n - i), fmt, va);
|
||||
i += ksnprintf(b + i, MAX(0, n - i), "\n");
|
||||
write(2, b, MIN(i, n));
|
||||
va_end(va);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Lock(int fd, int type, long start, long len) {
|
||||
int e;
|
||||
struct flock lock = {
|
||||
.l_type = type,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = start,
|
||||
.l_len = len,
|
||||
};
|
||||
e = errno;
|
||||
while (fcntl(fd, F_SETLK, &lock)) {
|
||||
ASSERT_TRUE(errno == EAGAIN || errno == EACCES);
|
||||
errno = e;
|
||||
Log("flock spinning on %d", fd);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLock(int fd, long start, long len) {
|
||||
Lock(fd, F_WRLCK, start, len);
|
||||
Log("acquired write lock on %d", fd);
|
||||
}
|
||||
|
||||
void ReadLock(int fd, long start, long len) {
|
||||
Lock(fd, F_RDLCK, start, len);
|
||||
Log("acquired read lock on %d", fd);
|
||||
}
|
||||
|
||||
void Unlock(int fd, long start, long len) {
|
||||
Lock(fd, F_UNLCK, start, len);
|
||||
Log("released lock on %d", fd);
|
||||
}
|
||||
|
||||
void *Reader(void *arg) {
|
||||
int i, j, fd;
|
||||
char buf[10];
|
||||
kind = arg;
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDONLY)));
|
||||
for (j = 0; j < ITERATIONS; ++j) {
|
||||
ReadLock(fd, 10, 10);
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i));
|
||||
ASSERT_EQ(buf[0], buf[i]);
|
||||
}
|
||||
Unlock(fd, 10, 10);
|
||||
sched_yield();
|
||||
}
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *Writer(void *arg) {
|
||||
int i, j, fd;
|
||||
char buf[10];
|
||||
kind = arg;
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
for (j = 0; j < ITERATIONS; ++j) {
|
||||
WriteLock(fd, 10, 10);
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i));
|
||||
ASSERT_EQ(buf[0], buf[i]);
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
buf[i]++;
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pwrite(fd, buf + i, 1, 10 + i));
|
||||
}
|
||||
Unlock(fd, 10, 10);
|
||||
sched_yield();
|
||||
}
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(posixAdvisoryLocks, threadsAndProcessesFightingForLock) {
|
||||
int i, rc, pid, fd, ws;
|
||||
pthread_t th[THREADS + 1];
|
||||
|
||||
ASSERT_SYS(0, 3, creat("db", 0644));
|
||||
ASSERT_SYS(0, 0, ftruncate(3, 30));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
if (i % RATIO == 0) {
|
||||
ASSERT_EQ(0, pthread_create(th + i, 0, Reader, "reader thread"));
|
||||
} else {
|
||||
ASSERT_EQ(0, pthread_create(th + i, 0, Writer, "writer thread"));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < PROCESSES; ++i) {
|
||||
ASSERT_NE(-1, (rc = fork()));
|
||||
if (!rc) {
|
||||
if (i % RATIO == 0) {
|
||||
Writer("writer process");
|
||||
} else {
|
||||
Reader("reader process");
|
||||
}
|
||||
_Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
Lock(fd, F_WRLCK, 0, 10);
|
||||
Lock(fd, F_WRLCK, 20, 10);
|
||||
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
ASSERT_EQ(0, pthread_join(th[i], 0));
|
||||
}
|
||||
|
||||
kind = "main process";
|
||||
for (;;) {
|
||||
int e = errno;
|
||||
if ((pid = waitpid(0, &ws, 0)) != -1) {
|
||||
if (WIFSIGNALED(ws)) {
|
||||
Log("process %d terminated with %G", pid, WTERMSIG(ws));
|
||||
testlib_incrementfailed();
|
||||
} else if (WEXITSTATUS(ws)) {
|
||||
Log("process %d exited with %d", pid, WEXITSTATUS(ws));
|
||||
testlib_incrementfailed();
|
||||
}
|
||||
} else {
|
||||
ASSERT_EQ(ECHILD, errno);
|
||||
errno = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
}
|
|
@ -560,7 +560,7 @@ TEST(pledge_openbsd, bigSyscalls) {
|
|||
|
||||
int LockWorker(void *arg, int tid) {
|
||||
flockfile(stdout);
|
||||
ASSERT_EQ(gettid(), stdout->lock._owner);
|
||||
ASSERT_EQ(gettid(), ((pthread_mutex_t *)stdout->lock)->_owner);
|
||||
funlockfile(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue