mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Elevate Windows production worthiness
- SQLite file locking now works on Windows - SQLite will now use fdatasync() on non-Apple platforms - Fix Ctrl-C handler on Windows to not crash with TLS - Signals now work in multithreaded apps on Windows - fcntl() will now accurately report EINVAL errors - fcntl() now has excellent --strace logging - Token bucket replenish now go 100x faster - *NSYNC cancellations now work on Windows - Support closefrom() on NetBSD
This commit is contained in:
parent
d38700687a
commit
997ce29ddc
95 changed files with 959 additions and 418 deletions
21
libc/calls/__sig.c
Normal file
21
libc/calls/__sig.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*-*- 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/sig.internal.h"
|
||||
|
||||
struct Signals __sig;
|
|
@ -16,26 +16,22 @@
|
|||
│ 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/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* @fileoverview UNIX signals for the New Technology, Part 2.
|
||||
* @threadsafe
|
||||
*/
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
* Allocates piece of memory for storing pending signal.
|
||||
|
@ -61,16 +57,30 @@ static textwindows void __sig_free(struct Signal *mem) {
|
|||
mem->used = false;
|
||||
}
|
||||
|
||||
static inline textwindows int __sig_is_masked(int sig) {
|
||||
if (__tls_enabled) {
|
||||
return __get_tls()->tib_sigmask & (1ull << (sig - 1));
|
||||
} else {
|
||||
return __sig.sigmask & (1ull << (sig - 1));
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int __sig_is_applicable(struct Signal *s) {
|
||||
return (s->tid <= 0 || s->tid == gettid()) && !__sig_is_masked(s->sig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues signal that isn't masked.
|
||||
* @return signal or null if empty or none unmasked
|
||||
*/
|
||||
static textwindows struct Signal *__sig_remove(void) {
|
||||
int tid;
|
||||
struct Signal *prev, *res;
|
||||
if (__sig.queue) {
|
||||
tid = gettid();
|
||||
__sig_lock();
|
||||
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
|
||||
if (!sigismember(&__sig.mask, res->sig)) {
|
||||
if (__sig_is_applicable(res)) {
|
||||
if (res == __sig.queue) {
|
||||
__sig.queue = res->next;
|
||||
} else if (prev) {
|
||||
|
@ -78,8 +88,6 @@ static textwindows struct Signal *__sig_remove(void) {
|
|||
}
|
||||
res->next = 0;
|
||||
break;
|
||||
} else {
|
||||
STRACE("%G is masked", res->sig);
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
|
@ -117,7 +125,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
// setup the somewhat expensive information args
|
||||
// only if they're requested by the user in sigaction()
|
||||
if (flags & SA_SIGINFO) {
|
||||
__repstosb(&info, 0, sizeof(info));
|
||||
bzero(&info, sizeof(info));
|
||||
info.si_signo = sig;
|
||||
info.si_code = si_code;
|
||||
infop = &info;
|
||||
|
@ -134,7 +142,11 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
// since sigaction() is @asyncsignalsafe we only restore it if the
|
||||
// user didn't change it during the signal handler. we also don't
|
||||
// need to do anything if this was a oneshot signal or nodefer.
|
||||
_lockcmpxchg(__sighandrvas + sig, (int32_t)(intptr_t)SIG_DFL, rva);
|
||||
__sig_lock();
|
||||
if (__sighandrvas[sig] == (int32_t)(intptr_t)SIG_DFL) {
|
||||
__sighandrvas[sig] = rva;
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
|
||||
if (!restartable) {
|
||||
|
@ -150,7 +162,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
/**
|
||||
* Returns true if signal default action is to end process.
|
||||
*/
|
||||
static textwindows bool __sig_isfatal(int sig) {
|
||||
static textwindows bool __sig_is_fatal(int sig) {
|
||||
if (sig == SIGCHLD || sig == SIGURG || sig == SIGWINCH) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -168,7 +180,7 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
|
|||
bool delivered;
|
||||
switch (__sighandrvas[sig]) {
|
||||
case (intptr_t)SIG_DFL:
|
||||
if (__sig_isfatal(sig)) {
|
||||
if (__sig_is_fatal(sig)) {
|
||||
STRACE("terminating on %G", sig);
|
||||
_Exitr(128 + sig);
|
||||
}
|
||||
|
@ -194,20 +206,17 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
|
|||
* @threadsafe
|
||||
*/
|
||||
textwindows int __sig_raise(int sig, int si_code) {
|
||||
int rc;
|
||||
int candeliver;
|
||||
__sig_lock();
|
||||
candeliver = !sigismember(&__sig.mask, sig);
|
||||
__sig_unlock();
|
||||
switch (candeliver) {
|
||||
case 1:
|
||||
if (1 <= sig && sig <= 64) {
|
||||
if (!__sig_is_masked(sig)) {
|
||||
++__sig_count;
|
||||
__sig_handle(false, sig, si_code, 0);
|
||||
return 0;
|
||||
case 0:
|
||||
} else {
|
||||
STRACE("%G is masked", sig);
|
||||
return __sig_add(sig, si_code);
|
||||
default:
|
||||
return -1; // sigismember() validates `sig`
|
||||
return __sig_add(gettid(), sig, si_code);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,10 +225,10 @@ textwindows int __sig_raise(int sig, int si_code) {
|
|||
* @return 0 on success, otherwise -1 w/ errno
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows int __sig_add(int sig, int si_code) {
|
||||
textwindows int __sig_add(int tid, int sig, int si_code) {
|
||||
int rc;
|
||||
struct Signal *mem;
|
||||
if (1 <= sig && sig <= NSIG) {
|
||||
if (1 <= sig && sig <= 64) {
|
||||
__sig_lock();
|
||||
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
|
||||
STRACE("ignoring %G", sig);
|
||||
|
@ -228,6 +237,7 @@ textwindows int __sig_add(int sig, int si_code) {
|
|||
STRACE("enqueuing %G", sig);
|
||||
++__sig_count;
|
||||
if ((mem = __sig_alloc())) {
|
||||
mem->tid = tid;
|
||||
mem->sig = sig;
|
||||
mem->si_code = si_code;
|
||||
mem->next = __sig.queue;
|
||||
|
@ -276,7 +286,7 @@ textwindows bool __sig_check(bool restartable) {
|
|||
textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
|
||||
struct Signal *cur, *prev, *next;
|
||||
if (rva != (unsigned)(intptr_t)SIG_IGN &&
|
||||
(rva != (unsigned)(intptr_t)SIG_DFL || __sig_isfatal(sig))) {
|
||||
(rva != (unsigned)(intptr_t)SIG_DFL || __sig_is_fatal(sig))) {
|
||||
return;
|
||||
}
|
||||
if (__sig.queue) {
|
||||
|
@ -298,25 +308,3 @@ textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
|
|||
__sig_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the pending signals on New Technology.
|
||||
*
|
||||
* @param pending is to hold the pending signals
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows void __sig_pending(sigset_t *pending) {
|
||||
struct Signal *cur;
|
||||
sigemptyset(pending);
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (cur = __sig.queue; cur; cur = cur->next) {
|
||||
if (__sighandrvas[cur->sig] != (unsigned)(intptr_t)SIG_IGN) {
|
||||
pending->__bits[(cur->sig - 1) >> 6] |= (1ull << ((cur->sig - 1) & 63));
|
||||
} else {
|
||||
STRACE("%G is ignored", cur->sig);
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
}
|
|
@ -17,49 +17,39 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
* @fileoverview UNIX signals for the New Technology, Part 1.
|
||||
* @threadsafe
|
||||
*/
|
||||
#define GetSigBit(x) (1ull << (((x)-1) & 63))
|
||||
|
||||
struct Signals __sig; // TODO(jart): Need TLS
|
||||
|
||||
#define GetSigBit(XXSIG) (1ull << (((XXSIG)-1) & 63))
|
||||
|
||||
/**
|
||||
* Changes signal mask for main thread.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
||||
int i;
|
||||
uint64_t a, b;
|
||||
uint64_t x, y, *mask;
|
||||
if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) {
|
||||
__sig_lock();
|
||||
if (__tls_enabled) {
|
||||
mask = &__get_tls()->tib_sigmask;
|
||||
} else {
|
||||
mask = &__sig.sigmask;
|
||||
}
|
||||
if (old) {
|
||||
*old = __sig.mask;
|
||||
old->__bits[0] = *mask;
|
||||
old->__bits[1] = 0;
|
||||
}
|
||||
if (neu) {
|
||||
for (i = 0; i < ARRAYLEN(__sig.mask.__bits); ++i) {
|
||||
x = *mask;
|
||||
y = neu->__bits[0];
|
||||
if (how == SIG_BLOCK) {
|
||||
__sig.mask.__bits[i] |= neu->__bits[i];
|
||||
x |= y;
|
||||
} else if (how == SIG_UNBLOCK) {
|
||||
__sig.mask.__bits[i] &= ~neu->__bits[i];
|
||||
x &= ~y;
|
||||
} else {
|
||||
__sig.mask.__bits[i] = neu->__bits[i];
|
||||
x = y;
|
||||
}
|
||||
x &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP) | GetSigBit(SIGABRT));
|
||||
*mask = x;
|
||||
}
|
||||
__sig.mask.__bits[0] &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP));
|
||||
}
|
||||
__sig_unlock();
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
#undef GetSigBit
|
43
libc/calls/__sig_pending.c
Normal file
43
libc/calls/__sig_pending.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
|
||||
/**
|
||||
* Determines the pending signals on New Technology.
|
||||
*
|
||||
* @param pending is to hold the pending signals
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows void __sig_pending(sigset_t *pending) {
|
||||
struct Signal *s;
|
||||
sigemptyset(pending);
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (s = __sig.queue; s; s = s->next) {
|
||||
if (__sig_is_applicable(s) &&
|
||||
__sighandrvas[s->sig] != (unsigned)(intptr_t)SIG_IGN) {
|
||||
sigaddset(pending, s->sig);
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
}
|
|
@ -95,7 +95,6 @@ int fchownat(int, const char *, uint32_t, uint32_t, int);
|
|||
int fcntl(int, int, ...);
|
||||
int fdatasync(int);
|
||||
int flock(int, int);
|
||||
int lockf(int, int, int64_t);
|
||||
int fork(void);
|
||||
int fsync(int);
|
||||
int ftruncate(int, int64_t);
|
||||
|
|
|
@ -35,27 +35,29 @@
|
|||
* }
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error EBADF if `first` is negative
|
||||
* @error EBADF on OpenBSD if `first` is greater than highest fd
|
||||
* @error EINVAL if flags are bad or first is greater than last
|
||||
* @error EMFILE if a weird race condition happens on Linux
|
||||
* @error ENOSYS if not Linux 5.9+, FreeBSD 8+, or OpenBSD
|
||||
* @error EINTR possibly on OpenBSD
|
||||
* @error ENOMEM on Linux maybe
|
||||
* @raise EBADF if `first` is negative
|
||||
* @raise ENOSYS if not Linux 5.9+, FreeBSD 8+, OpenBSD, or NetBSD
|
||||
* @raise EBADF on OpenBSD if `first` is greater than highest fd
|
||||
* @raise EINVAL if flags are bad or first is greater than last
|
||||
* @raise EMFILE if a weird race condition happens on Linux
|
||||
* @raise EINTR possibly on OpenBSD
|
||||
* @raise ENOMEM on Linux maybe
|
||||
*/
|
||||
int closefrom(int first) {
|
||||
int rc, err;
|
||||
if (IsNetbsd() || IsWindows() || IsMetal()) {
|
||||
rc = enosys();
|
||||
} else if (first < 0) {
|
||||
if (first < 0) {
|
||||
// consistent with openbsd
|
||||
// freebsd allows this but it's dangerous
|
||||
// necessary on linux due to type signature
|
||||
rc = ebadf();
|
||||
} else if (IsFreebsd() || IsOpenbsd()) {
|
||||
rc = sys_closefrom(first);
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_close_range(first, 0xffffffffu, 0);
|
||||
} else if (IsNetbsd()) {
|
||||
rc = __sys_fcntl(first, 10 /*F_CLOSEM*/, first);
|
||||
} else {
|
||||
rc = sys_closefrom(first);
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("closefrom(%d) → %d% m", first, rc);
|
||||
return rc;
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
#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);
|
||||
|
@ -110,11 +108,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
|||
ok = true;
|
||||
}
|
||||
}
|
||||
if (ok || __force_sqlite_to_work_until_we_can_fix_it) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return ok ? 0 : -1;
|
||||
}
|
||||
|
||||
if (l->l_type == F_UNLCK) {
|
||||
|
|
|
@ -18,11 +18,15 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/struct/flock.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -44,9 +48,49 @@
|
|||
* Please be warned that locks currently do nothing on Windows since
|
||||
* figuring out how to polyfill them correctly is a work in progress.
|
||||
*
|
||||
* @param cmd can be F_{GET,SET}{FD,FL}, etc.
|
||||
* @param fd is the file descriptor
|
||||
* @param cmd can be one of:
|
||||
* - `F_GETFD` gets `FD_CLOEXEC` status of `fd
|
||||
* - `F_SETFD` sets `FD_CLOEXEC` status of `arg` file descriptor
|
||||
* - `F_GETFL` returns file descriptor status flags
|
||||
* - `F_SETFL` sets file descriptor status flags
|
||||
* - `F_DUPFD` is like dup() but `arg` is a minimum result, e.g. 3
|
||||
* - `F_DUPFD_CLOEXEC` ditto but sets `O_CLOEXEC` on returned fd
|
||||
* - `F_SETLK` for record locking where `arg` is `struct flock`
|
||||
* - `F_SETLKW` ditto but waits (i.e. blocks) for lock
|
||||
* - `F_GETLK` to retrieve information about a record lock
|
||||
* - `F_OFD_SETLK` for better locks on Linux and XNU
|
||||
* - `F_OFD_SETLKW` for better locks on Linux and XNU
|
||||
* - `F_OFD_GETLK` for better locks on Linux and XNU
|
||||
* - `F_FULLFSYNC` on MacOS for fsync() with release barrier
|
||||
* - `F_BARRIERFSYNC` on MacOS for fsync() with even more barriers
|
||||
* - `F_SETNOSIGPIPE` on MacOS and NetBSD to control `SIGPIPE`
|
||||
* - `F_GETNOSIGPIPE` on MacOS and NetBSD to control `SIGPIPE`
|
||||
* - `F_GETPATH` on MacOS and NetBSD where arg is `char[PATH_MAX]`
|
||||
* - `F_MAXFD` on NetBSD to get max open file descriptor
|
||||
* - `F_NOCACHE` on MacOS to toggle data caching
|
||||
* - `F_GETPIPE_SZ` on Linux to get pipe size
|
||||
* - `F_SETPIPE_SZ` on Linux to set pipe size
|
||||
* - `F_NOTIFY` raise `SIGIO` upon `fd` events in `arg` on Linux
|
||||
* - `DN_ACCESS` for file access
|
||||
* - `DN_MODIFY` for file modifications
|
||||
* - `DN_CREATE` for file creations
|
||||
* - `DN_DELETE` for file deletions
|
||||
* - `DN_RENAME` for file renames
|
||||
* - `DN_ATTRIB` for file attribute changes
|
||||
* - `DN_MULTISHOT` bitwise or for realtime signals (non-coalesced)
|
||||
* @param arg can be FD_CLOEXEC, etc. depending
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EBADF if `fd` isn't a valid open file descriptor
|
||||
* @raise EINVAL if `cmd` is unknown or unsupported by os
|
||||
* @raise EINVAL if `cmd` is invalid or unsupported by os
|
||||
* @raise EPERM if pledge() is in play w/o `stdio` or `flock` promise
|
||||
* @raise ENOLCK if `F_SETLKW` would have exceeded `RLIMIT_LOCKS`
|
||||
* @raise EPERM if `cmd` is `F_SETOWN` and we weren't authorized
|
||||
* @raise ESRCH if `cmd` is `F_SETOWN` and process group not found
|
||||
* @raise EDEADLK if `cmd` was `F_SETLKW` and waiting would deadlock
|
||||
* @raise EMFILE if `cmd` is `F_DUPFD` or `F_DUPFD_CLOEXEC` and
|
||||
* `RLIMIT_NOFILE` would be exceeded
|
||||
* @asyncsignalsafe
|
||||
* @restartable
|
||||
*/
|
||||
|
@ -54,10 +98,13 @@ int fcntl(int fd, int cmd, ...) {
|
|||
int rc;
|
||||
va_list va;
|
||||
uintptr_t arg;
|
||||
|
||||
va_start(va, cmd);
|
||||
arg = va_arg(va, uintptr_t);
|
||||
va_end(va);
|
||||
|
||||
if (fd >= 0) {
|
||||
if (cmd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = _weaken(__zipos_fcntl)(fd, cmd, arg);
|
||||
} else if (!IsWindows()) {
|
||||
|
@ -68,6 +115,41 @@ int fcntl(int fd, int cmd, ...) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("fcntl(%d, %d, %p) → %#x% m", fd, cmd, arg, rc);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
|
||||
#ifdef SYSDEBUG
|
||||
if (cmd == F_GETFD || //
|
||||
cmd == F_GETOWN || //
|
||||
cmd == F_FULLFSYNC || //
|
||||
cmd == F_BARRIERFSYNC || //
|
||||
cmd == F_MAXFD) {
|
||||
STRACE("fcntl(%d, %s) → %d% m", fd, DescribeFcntlCmd(cmd), rc);
|
||||
} else if (cmd == F_GETFL) {
|
||||
STRACE("fcntl(%d, %s) → %s% m", fd, DescribeFcntlCmd(cmd),
|
||||
DescribeOpenFlags(rc));
|
||||
} else if (cmd == F_SETLK || //
|
||||
cmd == F_SETLKW || //
|
||||
cmd == F_GETLK || //
|
||||
((SupportsLinux() || SupportsXnu()) && //
|
||||
cmd != -1 && //
|
||||
(cmd == F_OFD_SETLK || //
|
||||
cmd == F_OFD_SETLKW || //
|
||||
cmd == F_OFD_GETLK))) {
|
||||
STRACE("fcntl(%d, %s, %s) → %d% m", fd, DescribeFcntlCmd(cmd),
|
||||
DescribeFlock(cmd, (struct flock *)arg), rc);
|
||||
} else if ((SupportsNetbsd() || SupportsXnu()) && cmd != -1 &&
|
||||
cmd == F_GETPATH) {
|
||||
STRACE("fcntl(%d, %s, [%s]) → %d% m", fd, DescribeFcntlCmd(cmd),
|
||||
!rc ? (const char *)arg : "n/a", rc);
|
||||
} else if (SupportsLinux() && cmd != -1 && cmd == F_NOTIFY) {
|
||||
STRACE("fcntl(%d, %s, %s) → %d% m", fd, DescribeFcntlCmd(cmd),
|
||||
DescribeDnotifyFlags(arg), rc);
|
||||
} else {
|
||||
STRACE("fcntl(%d, %s, %ld) → %#x% m", fd, DescribeFcntlCmd(cmd), arg, rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/stat.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/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
|
@ -33,6 +34,7 @@
|
|||
*/
|
||||
int fdatasync(int fd) {
|
||||
int rc;
|
||||
struct stat st;
|
||||
if (__nosync != 0x5453455454534146) {
|
||||
if (!IsWindows()) {
|
||||
rc = sys_fdatasync(fd);
|
||||
|
@ -41,8 +43,8 @@ int fdatasync(int fd) {
|
|||
}
|
||||
STRACE("fdatasync(%d) → %d% m", fd, rc);
|
||||
} else {
|
||||
rc = 0;
|
||||
STRACE("fdatasync(%d) → disabled% m", fd);
|
||||
rc = fstat(fd, &st);
|
||||
STRACE("fdatasync_fake(%d) → %d% m", fd, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/stat.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/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
|
@ -33,6 +34,7 @@
|
|||
*/
|
||||
int fsync(int fd) {
|
||||
int rc;
|
||||
struct stat st;
|
||||
if (__nosync != 0x5453455454534146) {
|
||||
if (!IsWindows()) {
|
||||
rc = sys_fsync(fd);
|
||||
|
@ -41,8 +43,8 @@ int fsync(int fd) {
|
|||
}
|
||||
STRACE("fysnc(%d) → %d% m", fd, rc);
|
||||
} else {
|
||||
rc = 0;
|
||||
STRACE("fsync(%d) → disabled% m", fd);
|
||||
rc = fstat(fd, &st);
|
||||
STRACE("fsync_fake(%d) → %d% m", fd, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
||||
int64_t me, nsignals;
|
||||
int64_t me;
|
||||
struct NtIoCounters iocount;
|
||||
struct NtProcessMemoryCountersEx memcount;
|
||||
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
|
||||
|
@ -48,9 +48,6 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
|||
!GetProcessIoCounters(me, &iocount)) {
|
||||
return __winerr();
|
||||
}
|
||||
__sig_lock();
|
||||
nsignals = __sig_count;
|
||||
__sig_unlock();
|
||||
*usage = (struct rusage){
|
||||
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
|
||||
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
|
||||
|
|
|
@ -31,9 +31,8 @@
|
|||
|
||||
textwindows bool _check_interrupts(bool restartable, struct Fd *fd) {
|
||||
bool res;
|
||||
if (__threaded && __threaded != gettid()) return false;
|
||||
if (_weaken(_check_sigalrm)) _weaken(_check_sigalrm)();
|
||||
if (!(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
|
||||
if (!__tls_enabled || !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
|
||||
if (_weaken(_check_sigchld)) _weaken(_check_sigchld)();
|
||||
if (fd && _weaken(_check_sigwinch)) _weaken(_check_sigwinch)(fd);
|
||||
}
|
||||
|
|
|
@ -17,25 +17,44 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nt/enum/ctrlevent.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/tls2.h"
|
||||
|
||||
textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
|
||||
struct CosmoTib tib;
|
||||
struct StackFrame *fr;
|
||||
|
||||
// win32 spawns a thread on its own just to deliver sigint
|
||||
// TODO(jart): make signal code lockless so we can delete!
|
||||
if (__tls_enabled && !__get_tls_win32()) {
|
||||
bzero(&tib, sizeof(tib));
|
||||
tib.tib_self = &tib;
|
||||
tib.tib_self2 = &tib;
|
||||
atomic_store_explicit(&tib.tib_tid, GetCurrentThreadId(),
|
||||
memory_order_relaxed);
|
||||
__set_tls_win32(&tib);
|
||||
}
|
||||
|
||||
STRACE("__onntconsoleevent(%u)", dwCtrlType);
|
||||
switch (dwCtrlType) {
|
||||
case kNtCtrlCEvent:
|
||||
__sig_add(SIGINT, SI_KERNEL);
|
||||
__sig_add(0, SIGINT, SI_KERNEL);
|
||||
return true;
|
||||
case kNtCtrlBreakEvent:
|
||||
__sig_add(SIGQUIT, SI_KERNEL);
|
||||
__sig_add(0, SIGQUIT, SI_KERNEL);
|
||||
return true;
|
||||
case kNtCtrlCloseEvent:
|
||||
case kNtCtrlLogoffEvent: // only received by services
|
||||
case kNtCtrlShutdownEvent: // only received by services
|
||||
__sig_add(SIGHUP, SI_KERNEL);
|
||||
__sig_add(0, SIGHUP, SI_KERNEL);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -1256,16 +1256,18 @@ static privileged void AllowIoctlTty(struct Filter *f) {
|
|||
// - TCP_FASTOPEN (0x17)
|
||||
// - TCP_FASTOPEN_CONNECT (0x1e)
|
||||
// - IPV6_V6ONLY (0x1a)
|
||||
// - TCP_QUICKACK (0x0c)
|
||||
//
|
||||
static privileged void AllowSetsockoptRestrict(struct Filter *f) {
|
||||
static const struct sock_filter fragment[] = {
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_setsockopt, 0, 24),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_setsockopt, 0, 25),
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 41, 3, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 2, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 1, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 0, 18),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 0, 19),
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0c, 16, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x1a, 15, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 14, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0f, 13, 0),
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/xnu.internal.h"
|
||||
|
||||
static textwindows inline bool HasWorkingConsole(void) {
|
||||
|
@ -59,7 +59,7 @@ static noubsan void RaiseSigFpe(void) {
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int raise(int sig) {
|
||||
int rc, event;
|
||||
int rc, tid, event;
|
||||
STRACE("raise(%G) → ...", sig);
|
||||
if (sig == SIGTRAP) {
|
||||
DebugBreak();
|
||||
|
@ -67,7 +67,7 @@ int raise(int sig) {
|
|||
} else if (sig == SIGFPE) {
|
||||
RaiseSigFpe();
|
||||
rc = 0;
|
||||
} else if (!IsWindows()) {
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
rc = sys_tkill(gettid(), sig, 0);
|
||||
} else {
|
||||
rc = __sig_raise(sig, SI_TKILL);
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
|
@ -68,7 +68,7 @@ textwindows void _check_sigalrm(void) {
|
|||
now = nowl();
|
||||
elapsed = now - __lastalrm;
|
||||
if (elapsed > __interval) {
|
||||
__sig_add(SIGALRM, SI_TIMER);
|
||||
__sig_add(0, SIGALRM, SI_TIMER);
|
||||
if (__singleshot) {
|
||||
__hastimer = false;
|
||||
} else {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
|
||||
#define __SIG_QUEUE_LENGTH 8
|
||||
#define __SIG_QUEUE_LENGTH 32
|
||||
#define __SIG_POLLING_INTERVAL_MS 50
|
||||
#define __SIG_LOGGING_INTERVAL_MS 1700
|
||||
|
||||
|
@ -13,26 +14,28 @@ COSMOPOLITAN_C_START_
|
|||
struct Signal {
|
||||
struct Signal *next;
|
||||
bool used;
|
||||
int tid;
|
||||
int sig;
|
||||
int si_code;
|
||||
};
|
||||
|
||||
struct Signals {
|
||||
sigset_t mask;
|
||||
uint64_t sigmask; /* only if tls is disabled */
|
||||
struct Signal *queue;
|
||||
struct Signal mem[__SIG_QUEUE_LENGTH];
|
||||
};
|
||||
|
||||
extern long __sig_count;
|
||||
extern struct Signals __sig;
|
||||
extern atomic_long __sig_count;
|
||||
|
||||
bool __sig_check(bool) hidden;
|
||||
bool __sig_handle(bool, int, int, ucontext_t *) hidden;
|
||||
int __sig_add(int, int) hidden;
|
||||
int __sig_add(int, int, int) hidden;
|
||||
int __sig_mask(int, const sigset_t *, sigset_t *) hidden;
|
||||
int __sig_raise(int, int) hidden;
|
||||
void __sig_check_ignore(const int, const unsigned) hidden;
|
||||
void __sig_pending(sigset_t *) hidden;
|
||||
int __sig_is_applicable(struct Signal *) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/wait.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
|
@ -65,5 +65,5 @@ void _check_sigchld(void) {
|
|||
__fds_lock();
|
||||
g_fds.p[pids[i]].zombie = true;
|
||||
__fds_unlock();
|
||||
__sig_add(SIGCHLD, CLD_EXITED);
|
||||
__sig_add(0, SIGCHLD, CLD_EXITED);
|
||||
}
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sig.internal.h"
|
||||
|
||||
long __sig_count;
|
||||
atomic_long __sig_count;
|
||||
|
|
|
@ -19,17 +19,18 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/winsize.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/struct/consolescreenbufferinfoex.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
static struct winsize __ws;
|
||||
|
||||
|
@ -38,6 +39,7 @@ textwindows void _check_sigwinch(struct Fd *fd) {
|
|||
siginfo_t si;
|
||||
struct winsize ws, old;
|
||||
struct NtConsoleScreenBufferInfoEx sbinfo;
|
||||
if (__tls_enabled && __threaded != gettid()) return;
|
||||
old = __ws;
|
||||
e = errno;
|
||||
if (old.ws_row != 0xffff) {
|
||||
|
@ -45,7 +47,7 @@ textwindows void _check_sigwinch(struct Fd *fd) {
|
|||
if (old.ws_col != ws.ws_col || old.ws_row != ws.ws_row) {
|
||||
__ws = ws;
|
||||
if (old.ws_col | old.ws_row) {
|
||||
__sig_add(SIGWINCH, SI_KERNEL);
|
||||
__sig_add(0, SIGWINCH, SI_KERNEL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
13
libc/calls/struct/flock.internal.h
Normal file
13
libc/calls/struct/flock.internal.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_FLOCK_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_FLOCK_INTERNAL_H_
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
const char *DescribeFlock(char[300], int, const struct flock *);
|
||||
#define DescribeFlock(c, l) DescribeFlock(alloca(300), c, l)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_FLOCK_INTERNAL_H_ */
|
|
@ -17,30 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/threadaccess.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows int sys_tkill_nt(int tid, int sig) {
|
||||
int rc;
|
||||
int64_t hand;
|
||||
if ((hand = OpenThread(kNtThreadTerminate, false, tid))) {
|
||||
if (TerminateThread(hand, 128 + sig)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
CloseHandle(hand);
|
||||
} else {
|
||||
rc = esrch();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
|
||||
/**
|
||||
* Kills thread.
|
||||
|
@ -56,10 +37,10 @@ static textwindows int sys_tkill_nt(int tid, int sig) {
|
|||
*/
|
||||
int tkill(int tid, int sig) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
rc = sys_tkill(tid, sig, 0);
|
||||
} else {
|
||||
rc = sys_tkill_nt(tid, sig);
|
||||
rc = __sig_add(tid, sig, SI_TKILL);
|
||||
}
|
||||
STRACE("tkill(%d, %G) → %d% m", tid, sig, rc);
|
||||
return rc;
|
||||
|
|
|
@ -19,6 +19,7 @@ struct MagnumStr {
|
|||
hidden extern const struct MagnumStr kClockNames[];
|
||||
hidden extern const struct MagnumStr kErrnoDocs[];
|
||||
hidden extern const struct MagnumStr kErrnoNames[];
|
||||
hidden extern const struct MagnumStr kFcntlCmds[];
|
||||
hidden extern const struct MagnumStr kIpOptnames[];
|
||||
hidden extern const struct MagnumStr kOpenFlags[];
|
||||
hidden extern const struct MagnumStr kRlimitNames[];
|
||||
|
|
37
libc/intrin/describednotify.c
Normal file
37
libc/intrin/describednotify.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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/processaccess.h"
|
||||
#include "libc/sysv/consts/dn.h"
|
||||
|
||||
static const struct DescribeFlags kDnotifyFlags[] = {
|
||||
{DN_ACCESS, "ACCESS"}, //
|
||||
{DN_MODIFY, "MODIFY"}, //
|
||||
{DN_CREATE, "CREATE"}, //
|
||||
{DN_DELETE, "DELETE"}, //
|
||||
{DN_RENAME, "RENAME"}, //
|
||||
{DN_ATTRIB, "ATTRIB"}, //
|
||||
{DN_MULTISHOT, "MULTISHOT"}, //
|
||||
};
|
||||
|
||||
const char *(DescribeDnotifyFlags)(char buf[80], int x) {
|
||||
return DescribeFlags(buf, 80, kDnotifyFlags, ARRAYLEN(kDnotifyFlags), "DN_",
|
||||
x);
|
||||
}
|
34
libc/intrin/describefcntlcmd.c
Normal file
34
libc/intrin/describefcntlcmd.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
const char *(DescribeFcntlCmd)(char buf[20], int x) {
|
||||
const char *s;
|
||||
if (x >= 0 && (s = GetMagnumStr(kFcntlCmds, x))) {
|
||||
buf[0] = 'F';
|
||||
buf[1] = '_';
|
||||
strcpy(buf + 2, s);
|
||||
} else {
|
||||
FormatInt32(buf, x);
|
||||
}
|
||||
return buf;
|
||||
}
|
|
@ -16,8 +16,11 @@ const char *DescribeArchPrctlCode(char[12], int);
|
|||
const char *DescribeCapability(char[20], int);
|
||||
const char *DescribeClockName(char[32], int);
|
||||
const char *DescribeDirfd(char[12], int);
|
||||
const char *DescribeDnotifyFlags(char[80], int);
|
||||
const char *DescribeErrno(char[12], int);
|
||||
const char *DescribeErrnoResult(char[12], int);
|
||||
const char *DescribeFcntlCmd(char[20], int);
|
||||
const char *DescribeFlockType(char[12], int);
|
||||
const char *DescribeFrame(char[32], int);
|
||||
const char *DescribeFutexOp(char[64], int);
|
||||
const char *DescribeHow(char[12], int);
|
||||
|
@ -68,6 +71,8 @@ const char *DescribeWhichPrio(char[12], int);
|
|||
#define DescribeDirfd(x) DescribeDirfd(alloca(12), x)
|
||||
#define DescribeErrno(x) DescribeErrno(alloca(12), x)
|
||||
#define DescribeErrnoResult(x) DescribeErrnoResult(alloca(12), x)
|
||||
#define DescribeFcntlCmd(x) DescribeFcntlCmd(alloca(20), x)
|
||||
#define DescribeFlockType(x) DescribeFlockType(alloca(12), x)
|
||||
#define DescribeFrame(x) DescribeFrame(alloca(32), x)
|
||||
#define DescribeFutexOp(x) DescribeFutexOp(alloca(64), x)
|
||||
#define DescribeHow(x) DescribeHow(alloca(12), x)
|
||||
|
@ -108,6 +113,7 @@ const char *DescribeWhichPrio(char[12], int);
|
|||
#define DescribeStdioState(x) DescribeStdioState(alloca(12), x)
|
||||
#define DescribeWhence(x) DescribeWhence(alloca(12), x)
|
||||
#define DescribeWhichPrio(x) DescribeWhichPrio(alloca(12), x)
|
||||
#define DescribeDnotifyFlags(x) DescribeDnotifyFlags(alloca(80), x)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
66
libc/intrin/describeflock.c
Normal file
66
libc/intrin/describeflock.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/struct/flock.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
|
||||
#define N 300
|
||||
|
||||
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
|
||||
|
||||
const char *(DescribeFlock)(char buf[N], int cmd, const struct flock *l) {
|
||||
int o = 0;
|
||||
|
||||
if (!l) return "NULL";
|
||||
if ((!IsAsan() && kisdangerous(l)) ||
|
||||
(IsAsan() && !__asan_is_valid(l, sizeof(*l)))) {
|
||||
ksnprintf(buf, N, "%p", l);
|
||||
return buf;
|
||||
}
|
||||
|
||||
append("{.l_type=%s", DescribeFlockType(l->l_type));
|
||||
|
||||
if (l->l_whence) {
|
||||
append(", .l_whence=%s", DescribeWhence(l->l_whence));
|
||||
}
|
||||
|
||||
if (l->l_start) {
|
||||
append(", .l_start=%#lx", l->l_start);
|
||||
}
|
||||
|
||||
if (l->l_len) {
|
||||
append(", .l_len=%'ld", l->l_len);
|
||||
}
|
||||
|
||||
if (l->l_pid && (cmd == F_GETLK || cmd == F_OFD_GETLK)) {
|
||||
append(", .l_pid=%d", l->l_pid);
|
||||
}
|
||||
|
||||
if (l->l_sysid) {
|
||||
append(", .l_sysid=%d", l->l_sysid);
|
||||
}
|
||||
|
||||
append("}");
|
||||
|
||||
return buf;
|
||||
}
|
28
libc/intrin/describeflocktype.c
Normal file
28
libc/intrin/describeflocktype.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
|
||||
const char *(DescribeFlockType)(char buf[12], int x) {
|
||||
if (x == F_RDLCK) return "F_RDLCK";
|
||||
if (x == F_WRLCK) return "F_WRLCK";
|
||||
if (x == F_UNLCK) return "F_UNLCK";
|
||||
FormatInt32(buf, x);
|
||||
return buf;
|
||||
}
|
|
@ -32,6 +32,7 @@ const char *(DescribeOpenFlags)(char buf[128], int x) {
|
|||
char *s;
|
||||
int i, n;
|
||||
struct DescribeFlags d[N];
|
||||
if (x == -1) return "-1";
|
||||
// TODO(jart): unify DescribeFlags and MagnumStr data structures
|
||||
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) {
|
||||
if (n == N) notpossible;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
|
@ -36,7 +37,7 @@
|
|||
int gettid(void) {
|
||||
int tid;
|
||||
if (__tls_enabled && !__vforked) {
|
||||
tid = __get_tls()->tib_tid;
|
||||
tid = atomic_load_explicit(&__get_tls()->tib_tid, memory_order_relaxed);
|
||||
if (tid > 0) {
|
||||
return tid;
|
||||
}
|
||||
|
|
57
libc/intrin/kfcntlcmds.S
Normal file
57
libc/intrin/kfcntlcmds.S
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e s
|
||||
.long \e - kFcntlCmds
|
||||
.long .L\@ - kFcntlCmds
|
||||
.rodata.str1.1
|
||||
.L\@: .string "\s"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.section .rodata,"a",@progbits
|
||||
.align 4
|
||||
.underrun
|
||||
kFcntlCmds:
|
||||
.e F_GETFD,"GETFD"
|
||||
.e F_SETFD,"SETFD"
|
||||
.e F_GETFL,"GETFL"
|
||||
.e F_SETFL,"SETFL"
|
||||
.e F_DUPFD,"DUPFD"
|
||||
.e F_DUPFD_CLOEXEC,"DUPFD_CLOEXEC"
|
||||
.e F_GETLK,"GETLK"
|
||||
.e F_SETLK,"SETLK"
|
||||
.e F_SETLKW,"SETLKW"
|
||||
.e F_GETOWN,"GETOWN"
|
||||
.e F_SETOWN,"SETOWN"
|
||||
.e F_GETPATH,"GETPATH"
|
||||
.e F_NOCACHE,"NOCACHE"
|
||||
.e F_FULLFSYNC,"FULLFSYNC"
|
||||
.e F_OFD_GETLK,"OFD_GETLK"
|
||||
.e F_OFD_SETLK,"OFD_SETLK"
|
||||
.e F_OFD_SETLKW,"OFD_SETLKW"
|
||||
.e F_BARRIERFSYNC,"BARRIERFSYNC"
|
||||
.e F_SETNOSIGPIPE,"SETNOSIGPIPE"
|
||||
.e F_GETNOSIGPIPE,"GETNOSIGPIPE"
|
||||
.e F_MAXFD,"MAXFD"
|
||||
.long MAGNUM_TERMINATOR
|
||||
.endobj kFcntlCmds,globl,hidden
|
||||
.overrun
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
@ -326,7 +327,8 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
if (!__tls_enabled) {
|
||||
x = __pid;
|
||||
} else {
|
||||
x = __get_tls_privileged()->tib_tid;
|
||||
x = atomic_load_explicit(&__get_tls_privileged()->tib_tid,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
if (!__nocolor && p + 7 <= e) {
|
||||
*p++ = '\e';
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
__msabi extern typeof(LockFileEx) *const __imp_LockFileEx;
|
||||
|
@ -35,14 +36,16 @@ bool32 LockFileEx(int64_t hFile, uint32_t dwFlags, uint32_t dwReserved,
|
|||
uint32_t nNumberOfBytesToLockHigh,
|
||||
struct NtOverlapped *lpOverlapped) {
|
||||
bool32 ok;
|
||||
STRACE("LockFileEx(%ld, %s, %#x, %'zu, %s) → ...", hFile,
|
||||
if (~dwFlags & kNtLockfileFailImmediately) {
|
||||
NTTRACE("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,
|
||||
NTTRACE("LockFileEx(%ld, %s, %#x, %'zu, [%s]) → %hhhd% m", hFile,
|
||||
DescribeNtLockFileFlags(dwFlags), dwReserved,
|
||||
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
|
||||
DescribeNtOverlapped(lpOverlapped), ok);
|
||||
|
|
|
@ -37,13 +37,11 @@ bool32 UnlockFileEx(int64_t hFile, uint32_t dwReserved,
|
|||
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,
|
||||
NTTRACE(
|
||||
"UnlockFileEx(%ld, %#x, %'zu, [%s]) → %hhhd% m", hFile, dwReserved,
|
||||
(uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow,
|
||||
DescribeNtOverlapped(lpOverlapped), ok);
|
||||
return ok;
|
||||
|
|
|
@ -2,5 +2,7 @@
|
|||
#define COSMOPOLITAN_LIBC_ISYSTEM_SYS_FCNTL_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/dn.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "third_party/musl/lockf.h"
|
||||
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_FCNTL_H_ */
|
||||
|
|
|
@ -12,4 +12,5 @@
|
|||
#include "libc/time/time.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/musl/crypt.h"
|
||||
#include "third_party/musl/lockf.h"
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
|
@ -229,7 +230,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
|||
ShowFunctionCalls(ctx);
|
||||
}
|
||||
kprintf("\n");
|
||||
__print_maps();
|
||||
if (!IsWindows()) __print_maps();
|
||||
/* PrintSystemMappings(2); */
|
||||
if (__argv) {
|
||||
for (i = 0; i < __argc; ++i) {
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
#define kNtErrorSemIsSet 102
|
||||
#define kNtErrorTooManySemRequests 103
|
||||
#define kNtErrorInvalidAtInterruptTime 104
|
||||
#define kNtErrorSemOwnerDied 105
|
||||
#define kNtErrorSemOwnerDied 105 /* EOWNERDEAD */
|
||||
#define kNtErrorSemUserLimit 106
|
||||
#define kNtErrorDiskChange 107
|
||||
#define kNtErrorDriveLocked 108
|
||||
|
@ -336,7 +336,7 @@
|
|||
#define kNtErrorVrfCfgEnabled 1183
|
||||
#define kNtErrorPartitionTerminating 1184
|
||||
#define kNtErrorUserProfileLoad 500
|
||||
#define kNtErrorArithmeticOverflow 534
|
||||
#define kNtErrorArithmeticOverflow 534 /* EOVERFLOW */
|
||||
#define kNtErrorPipeConnected 535
|
||||
#define kNtErrorPipeListening 536
|
||||
#define kNtErrorVerifierStop 537
|
||||
|
@ -383,7 +383,7 @@
|
|||
#define kNtErrorIllegalFloatContext 579
|
||||
#define kNtErrorNoEventPair 580
|
||||
#define kNtErrorDomainCtrlrConfigError 581
|
||||
#define kNtErrorIllegalCharacter 582
|
||||
#define kNtErrorIllegalCharacter 582 /* EILSEQ */
|
||||
#define kNtErrorUndefinedCharacter 583
|
||||
#define kNtErrorFloppyVolume 584
|
||||
#define kNtErrorBiosFailedToConnectInterrupt 585
|
||||
|
@ -761,7 +761,7 @@
|
|||
#define kNtErrorRemoteSessionLimitExceeded 1220
|
||||
#define kNtErrorDupDomainname 1221
|
||||
#define kNtErrorNoNetwork 1222
|
||||
#define kNtErrorCancelled 1223
|
||||
#define kNtErrorCancelled 1223 /* ECANCELED */
|
||||
#define kNtErrorUserMappedFile 1224
|
||||
#define kNtErrorConnectionRefused 1225
|
||||
#define kNtErrorGracefulDisconnect 1226
|
||||
|
@ -1217,7 +1217,7 @@
|
|||
#define kNtErrorDriveMediaMismatch 4303
|
||||
#define kNtErrorMediaOffline 4304
|
||||
#define kNtErrorLibraryOffline 4305
|
||||
#define kNtErrorEmpty 4306
|
||||
#define kNtErrorEmpty 4306 /* ENOMSG */
|
||||
#define kNtErrorNotEmpty 4307
|
||||
#define kNtErrorMediaUnavailable 4308
|
||||
#define kNtErrorResourceDisabled 4309
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "libc/thread/openbsd.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/tls2.h"
|
||||
#include "libc/thread/xnu.internal.h"
|
||||
|
||||
#define __NR_thr_new 455
|
||||
|
@ -97,11 +98,7 @@ WinThreadEntry(int rdi, // rcx
|
|||
int rdx, // r8
|
||||
struct CloneArgs *wt) { // r9
|
||||
int rc;
|
||||
if (wt->tls) {
|
||||
asm("mov\t%1,%%gs:%0"
|
||||
: "=m"(*((long *)0x1480 + __tls_index))
|
||||
: "r"(wt->tls));
|
||||
}
|
||||
if (wt->tls) __set_tls_win32(wt->tls);
|
||||
*wt->ptid = wt->tid;
|
||||
*wt->ctid = wt->tid;
|
||||
rc = WinThreadLaunch(wt->arg, wt->tid, wt->func, (intptr_t)wt & -16);
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#define STATE_QUOTED_VAR 4
|
||||
#define STATE_WHITESPACE 5
|
||||
|
||||
#define READ24LE(s) READ32LE(s "\0")
|
||||
#define READ24(s) READ32LE(s "\0")
|
||||
|
||||
struct Env {
|
||||
char *s;
|
||||
|
@ -333,16 +333,16 @@ static int Test(void) {
|
|||
if (n == 4) {
|
||||
w = READ32LE(args[2]) & 0x00ffffff;
|
||||
if ((w & 65535) == READ16LE("=")) return !!strcmp(args[1], args[3]);
|
||||
if (w == READ24LE("==")) return !!strcmp(args[1], args[3]);
|
||||
if (w == READ24LE("!=")) return !strcmp(args[1], args[3]);
|
||||
if (w == READ24("==")) return !!strcmp(args[1], args[3]);
|
||||
if (w == READ24("!=")) return !strcmp(args[1], args[3]);
|
||||
} else if (n == 3) {
|
||||
w = READ32LE(args[1]) & 0x00ffffff;
|
||||
if (w == READ24LE("-n")) return !(strlen(args[2]) > 0);
|
||||
if (w == READ24LE("-z")) return !(strlen(args[2]) == 0);
|
||||
if (w == READ24LE("-e")) return !!stat(args[2], &st);
|
||||
if (w == READ24LE("-f")) return !stat(args[2], &st) && S_ISREG(st.st_mode);
|
||||
if (w == READ24LE("-d")) return !stat(args[2], &st) && S_ISDIR(st.st_mode);
|
||||
if (w == READ24LE("-h")) return !stat(args[2], &st) && S_ISLNK(st.st_mode);
|
||||
if (w == READ24("-n")) return !(strlen(args[2]) > 0);
|
||||
if (w == READ24("-z")) return !(strlen(args[2]) == 0);
|
||||
if (w == READ24("-e")) return !!stat(args[2], &st);
|
||||
if (w == READ24("-f")) return !(!stat(args[2], &st) && S_ISREG(st.st_mode));
|
||||
if (w == READ24("-d")) return !(!stat(args[2], &st) && S_ISDIR(st.st_mode));
|
||||
if (w == READ24("-h")) return !(!stat(args[2], &st) && S_ISLNK(st.st_mode));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -19,17 +19,15 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
extern int __threadcalls_end[];
|
||||
extern int __threadcalls_start[];
|
||||
#pragma weak __threadcalls_start
|
||||
#pragma weak __threadcalls_end
|
||||
|
||||
privileged void __enable_threads(void) {
|
||||
if (__threaded) return;
|
||||
STRACE("__enable_threads()");
|
||||
static privileged dontinline void FixupLocks(void) {
|
||||
__morph_begin();
|
||||
/*
|
||||
* _NOPL("__threadcalls", func)
|
||||
|
@ -55,5 +53,11 @@ privileged void __enable_threads(void) {
|
|||
_base[*p + 2] = 0xe8;
|
||||
}
|
||||
__morph_end();
|
||||
}
|
||||
|
||||
void __enable_threads(void) {
|
||||
if (__threaded) return;
|
||||
STRACE("__enable_threads()");
|
||||
FixupLocks();
|
||||
__threaded = gettid();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
|
@ -99,6 +100,7 @@ _Alignas(TLS_ALIGNMENT) static char __static_tls[5008];
|
|||
* and your `errno` variable also won't be thread safe anymore.
|
||||
*/
|
||||
privileged void __enable_tls(void) {
|
||||
int tid;
|
||||
size_t siz;
|
||||
struct CosmoTib *tib;
|
||||
char *mem, *tls;
|
||||
|
@ -133,12 +135,13 @@ privileged void __enable_tls(void) {
|
|||
if (IsLinux()) {
|
||||
// gnu/systemd guarantees pid==tid for the main thread so we can
|
||||
// avoid issuing a superfluous system call at startup in program
|
||||
tib->tib_tid = __pid;
|
||||
tid = __pid;
|
||||
} else {
|
||||
tib->tib_tid = sys_gettid();
|
||||
tid = sys_gettid();
|
||||
}
|
||||
atomic_store_explicit(&tib->tib_tid, tid, memory_order_relaxed);
|
||||
_pthread_main.tib = tib;
|
||||
_pthread_main.tid = tib->tib_tid;
|
||||
_pthread_main.tid = tid;
|
||||
_pthread_main.flags = PT_MAINTHREAD;
|
||||
__repmovsb(tls, _tdata_start, _TLDZ);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
|
@ -56,7 +57,9 @@ int _fork(uint32_t dwCreationFlags) {
|
|||
parent = __pid;
|
||||
__pid = dx;
|
||||
if (__tls_enabled) {
|
||||
__get_tls()->tib_tid = IsLinux() ? dx : sys_gettid();
|
||||
atomic_store_explicit(&__get_tls()->tib_tid,
|
||||
IsLinux() ? dx : sys_gettid(),
|
||||
memory_order_relaxed);
|
||||
}
|
||||
if (!IsWindows()) sys_sigprocmask(SIG_SETMASK, &old, 0);
|
||||
STRACE("fork() → 0 (child of %d)", parent);
|
||||
|
|
|
@ -64,11 +64,11 @@ syscon errno ENAMETOOLONG 36 63 63 63 63 10063 # filename too lon
|
|||
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)
|
||||
syscon errno ENOMSG 42 91 83 90 83 4306 # kNtErrorEmpty; raised by msgop(2)
|
||||
syscon errno EIDRM 43 90 82 89 82 0 # identifier removed; raised by msgctl(2), msgget(2), msgop(2), semctl(2), semop(2), shmctl(2), shmget(2), shmop(2)
|
||||
syscon errno EPROTO 71 100 92 95 96 0 # raised by accept(2), connect(2), socket(2), socketpair(2)
|
||||
syscon errno EOVERFLOW 75 84 84 87 84 0 # raised by aio_read(2), copy_file_range(2), ctime(2), fanotify_init(2), lseek(2), mmap(2), open(2), open_by_handle_at(2), sem_post(2), sendfile(2), shmctl(2), stat(2), statfs(2), statvfs(2), time(2), timegm(2)
|
||||
syscon errno EILSEQ 84 92 86 84 85 0 # returned by fgetwc(3), fputwc(3), getwchar(3), putwchar(3), scanf(3), ungetwc(3)
|
||||
syscon errno EOVERFLOW 75 84 84 87 84 534 # kNtErrorArithmeticOverflow; raised by aio_read(2), copy_file_range(2), ctime(2), fanotify_init(2), lseek(2), mmap(2), open(2), open_by_handle_at(2), sem_post(2), sendfile(2), shmctl(2), stat(2), statfs(2), statvfs(2), time(2), timegm(2)
|
||||
syscon errno EILSEQ 84 92 86 84 85 582 # kNtErrorIllegalCharacter; returned by fgetwc(3), fputwc(3), getwchar(3), putwchar(3), scanf(3), ungetwc(3)
|
||||
syscon errno EUSERS 87 68 68 68 68 10068 # too many users; bsd consensus; WSAEUSERS; raised by acct(2)
|
||||
syscon errno ENOTSOCK 88 38 38 38 38 10038 # not a socket; bsd consensus; WSAENOTSOCK; raised by accept(2), bind(2), connect(2), getpeername(2), getsockname(2), getsockopt(2), listen(2), recv(2), send(2), shutdown(2)
|
||||
syscon errno EDESTADDRREQ 89 39 39 39 39 10039 # destination address required; bsd consensus; WSAEDESTADDRREQ; raised by send(2), write(2)
|
||||
|
@ -94,7 +94,7 @@ syscon errno ENOTCONN 107 57 57 57 57 10057 # socket is not conne
|
|||
syscon errno ESHUTDOWN 108 58 58 58 58 10058 # cannot send after transport endpoint shutdown; note that shutdown write is an EPIPE; bsd consensus; WSAESHUTDOWN
|
||||
syscon errno ETOOMANYREFS 109 59 59 59 59 10059 # too many references: cannot splice; bsd consensus; WSAETOOMANYREFS; raised by sendmsg(2), unix(7)
|
||||
syscon errno ETIMEDOUT 110 60 60 60 60 1460 # connection timed out; kNtErrorTimeout; bsd consensus; WSAETIMEDOUT; raised by connect(2), futex(2), keyctl(2), tcp(7)
|
||||
syscon errno ETIME 62 101 60 60 92 0 # timer expired (POSIX.1 XSI STREAMS)
|
||||
syscon errno ETIME 62 101 60 60 92 1460 # timer expired (POSIX.1 XSI STREAMS)
|
||||
syscon errno ECONNREFUSED 111 61 61 61 61 10061 # bsd consensus; WSAECONNREFUSED; raised by connect(2), listen(2), recv(2), unix(7), udp(7)system-imposed limit on the number of threads was encountered.
|
||||
syscon errno EHOSTDOWN 112 64 64 64 64 10064 # bsd consensus; WSAEHOSTDOWN; raised by accept(2)
|
||||
syscon errno EHOSTUNREACH 113 65 65 65 65 10065 # bsd consensus; WSAEHOSTUNREACH; raised by accept(2), ip(7)
|
||||
|
@ -120,8 +120,8 @@ syscon errno ESHLIBVERS 0 87 0 0 0 0 # shiver me timbers
|
|||
syscon errno EBADMACHO 0 88 0 0 0 0 #
|
||||
syscon errno ENOPOLICY 0 103 0 0 0 0 #
|
||||
syscon errno EBADMSG 74 94 89 92 88 0 # raised by ioctl_getfsmap(2)
|
||||
syscon errno ECANCELED 125 89 85 88 87 0 # raised by timerfd_create(2)
|
||||
syscon errno EOWNERDEAD 130 105 96 94 97 0 # raised by pthread_cond_timedwait(3), pthread_mutex_consistent(3), pthread_mutex_getprioceiling(3), pthread_mutex_lock(3), pthread_mutex_timedlock(3), pthread_mutexattr_getrobust(3), pthread_mutexattr_setrobust(3)
|
||||
syscon errno ECANCELED 125 89 85 88 87 1223 # kNtErrorCancelled; raised by timerfd_create(2)
|
||||
syscon errno EOWNERDEAD 130 105 96 94 97 105 # kNtErrorSemOwnerDied; raised by pthread_cond_timedwait(3), pthread_mutex_consistent(3), pthread_mutex_getprioceiling(3), pthread_mutex_lock(3), pthread_mutex_timedlock(3), pthread_mutexattr_getrobust(3), pthread_mutexattr_setrobust(3)
|
||||
syscon errno ENOTRECOVERABLE 131 104 95 93 98 0 # raised by pthread_cond_timedwait(3), pthread_mutex_consistent(3), pthread_mutex_getprioceiling(3), pthread_mutex_lock(3), pthread_mutex_timedlock(3), pthread_mutexattr_getrobust(3), pthread_mutexattr_setrobust(3)
|
||||
syscon errno ENONET 64 0 0 0 0 0 # unilateral; raised by accept(2)
|
||||
syscon errno ERESTART 85 -1 -1 -1 -3 0 # should only be seen in ptrace()
|
||||
|
@ -356,15 +356,22 @@ syscon fcntl2 F_GETFD 1 1 1 1 1 1 # unix consensus & faked nt
|
|||
syscon fcntl2 F_SETFD 2 2 2 2 2 2 # unix consensus & faked nt
|
||||
syscon fcntl2 F_GETFL 3 3 3 3 3 3 # unix consensus & faked nt
|
||||
syscon fcntl2 F_SETFL 4 4 4 4 4 4 # unix consensus & faked nt
|
||||
syscon fcntl2 F_SETOWN 8 6 6 6 6 0 # bsd consensus
|
||||
syscon fcntl2 F_GETOWN 9 5 5 5 5 0 # bsd consensus
|
||||
syscon fcntl2 F_FULLFSYNC 0 51 0 0 0 0 #
|
||||
syscon fcntl2 F_NOCACHE 0 48 0 0 0 0 #
|
||||
syscon fcntl2 F_SETOWN 8 6 6 6 6 -1 # bsd consensus
|
||||
syscon fcntl2 F_GETOWN 9 5 5 5 5 -1 # bsd consensus
|
||||
syscon fcntl2 F_FULLFSYNC -1 51 -1 -1 -1 -1 #
|
||||
syscon fcntl2 F_BARRIERFSYNC -1 85 -1 -1 -1 -1 #
|
||||
syscon fcntl2 F_NOCACHE -1 48 -1 -1 -1 -1 #
|
||||
syscon fcntl3 F_SETNOSIGPIPE -1 73 -1 -1 14 -1 #
|
||||
syscon fcntl3 F_GETNOSIGPIPE -1 74 -1 -1 13 -1 #
|
||||
syscon fcntl3 F_GETPATH -1 50 -1 -1 15 -1 # geth path associated with fd into buffer with PATH_MAX (1024) bytes
|
||||
syscon fcntl3 FD_CLOEXEC 1 1 1 1 1 1 # unix consensus & faked nt
|
||||
syscon fcntl F_DUPFD_CLOEXEC 0x0406 67 17 10 12 0x0406 # Linux 2.6.24+; faked nt
|
||||
syscon fcntl F_MAXFD 0 0 0 0 11 0 #
|
||||
syscon fcntl FREAD 0 1 1 1 1 0 #
|
||||
syscon fcntl FWRITE 0 2 2 2 2 0 #
|
||||
syscon fcntl F_MAXFD -1 -1 -1 -1 11 -1 #
|
||||
syscon fcntl F_NOTIFY 0x0402 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_SETPIPE_SZ 0x0407 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_GETPIPE_SZ 0x0408 -1 -1 -1 -1 -1
|
||||
syscon fcntl FREAD 0 1 1 1 1 0 # wut is it
|
||||
syscon fcntl FWRITE 0 2 2 2 2 0 # wut is it
|
||||
|
||||
# fcntl3 O_NONBLOCK
|
||||
# fcntl3 O_APPEND
|
||||
|
@ -376,31 +383,24 @@ syscon fcntl FWRITE 0 2 2 2 2 0 #
|
|||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon fcntl F_SETLK 6 8 12 8 8 6 # polyfilled nt
|
||||
syscon compat F_SETLK64 6 8 12 8 8 6 # polyfilled nt
|
||||
syscon fcntl F_SETLKW 7 9 13 9 9 7
|
||||
syscon compat F_SETLKW64 7 9 13 9 9 7
|
||||
syscon fcntl F_SETLKW 7 9 13 9 9 7 # polyfilled nt
|
||||
syscon fcntl F_GETLK 5 7 11 7 7 5 # polyfilled nt
|
||||
syscon compat F_GETLK64 5 7 11 7 7 5 # polyfilled nt
|
||||
syscon fcntl F_OFD_SETLK 37 90 -1 -1 -1 6
|
||||
syscon fcntl F_OFD_SETLKW 38 91 -1 -1 -1 7
|
||||
syscon fcntl F_OFD_GETLK 36 92 -1 -1 -1 5
|
||||
syscon fcntl F_RDLCK 0 1 1 1 1 0 # polyfilled nt; bsd consensus
|
||||
syscon fcntl F_WRLCK 1 3 3 3 3 1 # polyfilled nt; bsd consensus
|
||||
syscon fcntl F_UNLCK 2 2 2 2 2 2 # polyfilled nt; unix consensus
|
||||
syscon compat F_SETLK64 6 8 12 8 8 6 # polyfilled nt
|
||||
syscon compat F_SETLKW64 7 9 13 9 9 7
|
||||
syscon compat F_GETLK64 5 7 11 7 7 5 # polyfilled nt
|
||||
|
||||
syscon fcntl F_ULOCK 0 0 0 0 0 0 # TODO: specified by posix but not kernels?
|
||||
syscon fcntl F_LOCK 1 1 1 1 1 0 # unix consensus
|
||||
syscon fcntl F_TLOCK 2 2 2 2 2 0 # unix consensus
|
||||
syscon fcntl F_TEST 3 3 3 3 3 0 # unix consensus
|
||||
syscon fcntl F_SETSIG 10 0 0 0 0 0
|
||||
syscon fcntl F_GETSIG 11 0 0 0 0 0
|
||||
syscon fcntl F_SETOWN_EX 15 0 0 0 0 0
|
||||
syscon fcntl F_GETOWN_EX 0x10 0 0 0 0 0
|
||||
syscon fcntl F_OFD_GETLK 36 0 0 0 0 0
|
||||
syscon fcntl F_OFD_SETLK 37 0 0 0 0 0
|
||||
syscon fcntl F_OFD_SETLKW 38 0 0 0 0 0
|
||||
syscon fcntl F_SETLEASE 0x0400 0 0 0 0 0
|
||||
syscon fcntl F_GETLEASE 0x0401 0 0 0 0 0
|
||||
syscon fcntl F_NOTIFY 0x0402 0 0 0 0 0
|
||||
syscon fcntl F_SETPIPE_SZ 0x0407 0 0 0 0 0
|
||||
syscon fcntl F_GETPIPE_SZ 0x0408 0 0 0 0 0
|
||||
syscon fcntl F_SETSIG 10 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_GETSIG 11 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_SETOWN_EX 15 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_GETOWN_EX 0x10 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_SETLEASE 0x0400 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_GETLEASE 0x0401 -1 -1 -1 -1 -1
|
||||
|
||||
syscon ioctl FIONBIO 0x5421 0x8004667e 0x8004667e 0x8004667e 0x8004667e 0x8004667e # BSD-The New Technology consensus; FIONBIO is traditional O_NONBLOCK; see F_SETFL for re-imagined api
|
||||
syscon ioctl FIOASYNC 0x5452 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d # BSD-The New Technology consensus
|
||||
|
@ -763,9 +763,9 @@ syscon tcp TCP_CORK 3 4 4 16 4 0 # nagle's algorithm strikes agai
|
|||
syscon tcp TCP_MAXSEG 2 2 2 2 2 0 # reduces tcp segment size; see also tcp offloading
|
||||
syscon tcp TCP_FASTOPEN 23 0 0x0401 0 0 15 # reduces roundtrips; for listener; Linux 3.7+ (c. 2012) / or is windows it 0x22? /proc/sys/net/ipv4/tcp_fastopen TODO(jart): MSG_FASTOPEN; XNU sources say 261 but not sure if that's true
|
||||
syscon tcp TCP_FASTOPEN_CONNECT 30 0 0 0 0 0 # reduces roundtrips; for listener; Linux 3.7+ (c. 2012) / or is windows it 0x22? /proc/sys/net/ipv4/tcp_fastopen TODO(jart): MSG_FASTOPEN; XNU sources say 261 but not sure if that's true
|
||||
syscon tcp TCP_KEEPIDLE 4 0 0x100 0 3 0 # keepalives
|
||||
syscon tcp TCP_KEEPINTVL 5 0x101 0x200 0 5 0 # keepalives
|
||||
syscon tcp TCP_KEEPCNT 6 0x102 0x400 0 6 0 # keepalives
|
||||
syscon tcp TCP_KEEPIDLE 4 0 0x100 0 3 0 # start keepalives after this period
|
||||
syscon tcp TCP_KEEPINTVL 5 0x101 0x200 0 5 0 # interval between keepalives
|
||||
syscon tcp TCP_KEEPCNT 6 0x102 0x400 0 6 0 # number of keepalives before death
|
||||
syscon tcp TCP_SYNCNT 7 0 0 0 0 0 # how hard to syn packet the enemy
|
||||
syscon tcp TCP_ULP 31 0 0 0 0 0 # setsockopt(sock, IPPROTO_TCP, TCP_ULP, "tls", 4)
|
||||
syscon tcp TCP_COOKIE_TRANSACTIONS 15 0 0 0 0 0 # defense against the syn packets
|
||||
|
@ -778,7 +778,7 @@ syscon tcp TCP_MD5SIG 14 0 0x10 4 16 0 # what is it (rfc2385)
|
|||
syscon tcp TCP_MD5SIG_MAXKEYLEN 80 0 0 0 0 0 # what is it
|
||||
syscon tcp TCP_TIMESTAMP 24 0 0 0 0 0 # what is it
|
||||
syscon tcp TCP_USER_TIMEOUT 18 0 0 0 0 0 # what is it
|
||||
syscon tcp TCP_QUICKACK 12 0 0 0 0 0 # what is it
|
||||
syscon tcp TCP_QUICKACK 12 0 0 0 0 0 # disables optimization that lets kernel merge response data into ack packets
|
||||
syscon tcp TCP_SAVE_SYN 27 0 0 0 0 0 # record syn packets
|
||||
syscon tcp TCP_SAVED_SYN 28 0 0 0 0 0 # get recorded syn packets
|
||||
syscon tcp TCP_THIN_DUPACK 17 0 0 0 0 0 # what is it
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,ECANCELED,125,89,85,88,87,0
|
||||
.syscon errno,ECANCELED,125,89,85,88,87,1223
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,EILSEQ,84,92,86,84,85,0
|
||||
.syscon errno,EILSEQ,84,92,86,84,85,582
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,ENOMSG,42,91,83,90,83,0
|
||||
.syscon errno,ENOMSG,42,91,83,90,83,4306
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,EOVERFLOW,75,84,84,87,84,0
|
||||
.syscon errno,EOVERFLOW,75,84,84,87,84,534
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,EOWNERDEAD,130,105,96,94,97,0
|
||||
.syscon errno,EOWNERDEAD,130,105,96,94,97,105
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon errno,ETIME,62,101,60,60,92,0
|
||||
.syscon errno,ETIME,62,101,60,60,92,1460
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_ULOCK,0,0,0,0,0,0
|
||||
.syscon fcntl2,F_BARRIERFSYNC,-1,85,-1,-1,-1,-1
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl2,F_FULLFSYNC,0,51,0,0,0,0
|
||||
.syscon fcntl2,F_FULLFSYNC,-1,51,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_GETLEASE,0x0401,0,0,0,0,0
|
||||
.syscon fcntl,F_GETLEASE,0x0401,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_LOCK,1,1,1,1,1,0
|
||||
.syscon fcntl3,F_GETNOSIGPIPE,-1,74,-1,-1,13,-1
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl2,F_GETOWN,9,5,5,5,5,0
|
||||
.syscon fcntl2,F_GETOWN,9,5,5,5,5,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_GETOWN_EX,0x10,0,0,0,0,0
|
||||
.syscon fcntl,F_GETOWN_EX,0x10,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_TLOCK,2,2,2,2,2,0
|
||||
.syscon fcntl3,F_GETPATH,-1,50,-1,-1,15,-1
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_GETPIPE_SZ,0x0408,0,0,0,0,0
|
||||
.syscon fcntl,F_GETPIPE_SZ,0x0408,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_GETSIG,11,0,0,0,0,0
|
||||
.syscon fcntl,F_GETSIG,11,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_MAXFD,0,0,0,0,11,0
|
||||
.syscon fcntl,F_MAXFD,-1,-1,-1,-1,11,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl2,F_NOCACHE,0,48,0,0,0,0
|
||||
.syscon fcntl2,F_NOCACHE,-1,48,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_NOTIFY,0x0402,0,0,0,0,0
|
||||
.syscon fcntl,F_NOTIFY,0x0402,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_OFD_GETLK,36,0,0,0,0,0
|
||||
.syscon fcntl,F_OFD_GETLK,36,92,-1,-1,-1,5
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_OFD_SETLK,37,0,0,0,0,0
|
||||
.syscon fcntl,F_OFD_SETLK,37,90,-1,-1,-1,6
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_OFD_SETLKW,38,0,0,0,0,0
|
||||
.syscon fcntl,F_OFD_SETLKW,38,91,-1,-1,-1,7
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_SETLEASE,0x0400,0,0,0,0,0
|
||||
.syscon fcntl,F_SETLEASE,0x0400,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_TEST,3,3,3,3,3,0
|
||||
.syscon fcntl3,F_SETNOSIGPIPE,-1,73,-1,-1,14,-1
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl2,F_SETOWN,8,6,6,6,6,0
|
||||
.syscon fcntl2,F_SETOWN,8,6,6,6,6,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_SETOWN_EX,15,0,0,0,0,0
|
||||
.syscon fcntl,F_SETOWN_EX,15,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_SETPIPE_SZ,0x0407,0,0,0,0,0
|
||||
.syscon fcntl,F_SETPIPE_SZ,0x0407,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon fcntl,F_SETSIG,10,0,0,0,0,0
|
||||
.syscon fcntl,F_SETSIG,10,-1,-1,-1,-1,-1
|
||||
|
|
12
libc/sysv/consts/dn.h
Normal file
12
libc/sysv/consts/dn.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_DN_H_
|
||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_DN_H_
|
||||
|
||||
#define DN_ACCESS 0x00000001 /* file accessed */
|
||||
#define DN_MODIFY 0x00000002 /* file modified */
|
||||
#define DN_CREATE 0x00000004 /* file created */
|
||||
#define DN_DELETE 0x00000008 /* file removed */
|
||||
#define DN_RENAME 0x00000010 /* file renamed */
|
||||
#define DN_ATTRIB 0x00000020 /* file changed attibutes */
|
||||
#define DN_MULTISHOT 0x80000000 /* don't remove notifier */
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_DN_H_ */
|
|
@ -4,6 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const int F_BARRIERFSYNC;
|
||||
extern const int F_DUPFD;
|
||||
extern const int F_DUPFD_CLOEXEC;
|
||||
extern const int F_FULLFSYNC;
|
||||
|
@ -12,11 +13,14 @@ extern const int F_GETFL;
|
|||
extern const int F_GETLEASE;
|
||||
extern const int F_GETLK64;
|
||||
extern const int F_GETLK;
|
||||
extern const int F_GETNOSIGPIPE;
|
||||
extern const int F_GETOWN;
|
||||
extern const int F_GETOWN_EX;
|
||||
extern const int F_GETPATH;
|
||||
extern const int F_GETPIPE_SZ;
|
||||
extern const int F_GETSIG;
|
||||
extern const int F_LOCK;
|
||||
extern const int F_MAXFD;
|
||||
extern const int F_NOCACHE;
|
||||
extern const int F_NOTIFY;
|
||||
extern const int F_OFD_GETLK;
|
||||
|
@ -30,13 +34,11 @@ extern const int F_SETLK64;
|
|||
extern const int F_SETLK;
|
||||
extern const int F_SETLKW64;
|
||||
extern const int F_SETLKW;
|
||||
extern const int F_SETNOSIGPIPE;
|
||||
extern const int F_SETOWN;
|
||||
extern const int F_SETOWN_EX;
|
||||
extern const int F_SETPIPE_SZ;
|
||||
extern const int F_SETSIG;
|
||||
extern const int F_TEST;
|
||||
extern const int F_TLOCK;
|
||||
extern const int F_ULOCK;
|
||||
extern const int F_UNLCK;
|
||||
extern const int F_WRLCK;
|
||||
|
||||
|
@ -50,20 +52,17 @@ COSMOPOLITAN_C_END_
|
|||
#define F_SETFL LITERALLY(4)
|
||||
|
||||
#define F_DUPFD_CLOEXEC SYMBOLIC(F_DUPFD_CLOEXEC)
|
||||
#define F_FULLFSYNC SYMBOLIC(F_FULLFSYNC)
|
||||
#define F_GETLEASE SYMBOLIC(F_GETLEASE)
|
||||
#define F_GETLK SYMBOLIC(F_GETLK)
|
||||
#define F_GETLK64 SYMBOLIC(F_GETLK64)
|
||||
#define F_GETOWN SYMBOLIC(F_GETOWN)
|
||||
#define F_GETOWN_EX SYMBOLIC(F_GETOWN_EX)
|
||||
#define F_GETPATH SYMBOLIC(F_GETPATH)
|
||||
#define F_GETPIPE_SZ SYMBOLIC(F_GETPIPE_SZ)
|
||||
#define F_GETSIG SYMBOLIC(F_GETSIG)
|
||||
#define F_LOCK SYMBOLIC(F_LOCK)
|
||||
#define F_MAXFD SYMBOLIC(F_MAXFD)
|
||||
#define F_NOCACHE SYMBOLIC(F_NOCACHE)
|
||||
#define F_NOTIFY SYMBOLIC(F_NOTIFY)
|
||||
#define F_OFD_GETLK SYMBOLIC(F_OFD_GETLK)
|
||||
#define F_OFD_SETLK SYMBOLIC(F_OFD_SETLK)
|
||||
#define F_OFD_SETLKW SYMBOLIC(F_OFD_SETLKW)
|
||||
#define F_RDLCK SYMBOLIC(F_RDLCK)
|
||||
#define F_SETLEASE SYMBOLIC(F_SETLEASE)
|
||||
#define F_SETLK SYMBOLIC(F_SETLK)
|
||||
|
@ -74,10 +73,16 @@ COSMOPOLITAN_C_END_
|
|||
#define F_SETOWN_EX SYMBOLIC(F_SETOWN_EX)
|
||||
#define F_SETPIPE_SZ SYMBOLIC(F_SETPIPE_SZ)
|
||||
#define F_SETSIG SYMBOLIC(F_SETSIG)
|
||||
#define F_TEST SYMBOLIC(F_TEST)
|
||||
#define F_TLOCK SYMBOLIC(F_TLOCK)
|
||||
#define F_ULOCK SYMBOLIC(F_ULOCK)
|
||||
#define F_UNLCK SYMBOLIC(F_UNLCK)
|
||||
#define F_WRLCK SYMBOLIC(F_WRLCK)
|
||||
|
||||
/* avoid leading #ifdef astray */
|
||||
/* #define F_FULLFSYNC SYMBOLIC(F_FULLFSYNC) */
|
||||
/* #define F_BARRIERFSYNC SYMBOLIC(F_BARRIERFSYNC) */
|
||||
/* #define F_OFD_GETLK SYMBOLIC(F_OFD_GETLK) */
|
||||
/* #define F_OFD_SETLK SYMBOLIC(F_OFD_SETLK) */
|
||||
/* #define F_OFD_SETLKW SYMBOLIC(F_OFD_SETLKW) */
|
||||
/* #define F_SETNOSIGPIPE SYMBOLIC(F_SETNOSIGPIPE) */
|
||||
/* #define F_GETNOSIGPIPE SYMBOLIC(F_GETNOSIGPIPE) */
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_F_H_ */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
|
@ -57,7 +58,8 @@ char *_mktls(struct CosmoTib **out_tib) {
|
|||
tib = (struct CosmoTib *)(tls + I(_tls_size));
|
||||
tib->tib_self = tib;
|
||||
tib->tib_self2 = tib;
|
||||
tib->tib_tid = -1;
|
||||
tib->tib_sigmask = __get_tls()->tib_sigmask;
|
||||
atomic_store_explicit(&tib->tib_tid, -1, memory_order_relaxed);
|
||||
|
||||
if (out_tib) {
|
||||
*out_tib = tib;
|
||||
|
|
|
@ -26,7 +26,7 @@ struct CosmoTib {
|
|||
int32_t tib_errno; /* 0x3c */
|
||||
void *tib_nsync;
|
||||
uint64_t tib_flags;
|
||||
void *tib_reserved2;
|
||||
uint64_t tib_sigmask;
|
||||
void *tib_reserved3;
|
||||
void *tib_reserved4;
|
||||
void *tib_reserved5;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "libc/thread/tls.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
/**
|
||||
* Returns location of thread information block.
|
||||
*
|
||||
|
@ -24,8 +24,19 @@ static noasan inline struct CosmoTib *__get_tls_privileged(void) {
|
|||
}
|
||||
return (struct CosmoTib *)tib;
|
||||
}
|
||||
#endif /* GNU x86-64 */
|
||||
|
||||
static noasan inline struct CosmoTib *__get_tls_win32(void) {
|
||||
char *tib, *lin = (char *)0x30;
|
||||
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
tib = *(char **)(tib + 0x1480 + __tls_index * 8);
|
||||
return (struct CosmoTib *)tib;
|
||||
}
|
||||
|
||||
static noasan inline void __set_tls_win32(void *tls) {
|
||||
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tls));
|
||||
}
|
||||
|
||||
#endif /* GNU x86-64 */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_TLS2_H_ */
|
||||
|
|
|
@ -19,62 +19,64 @@
|
|||
#include "libc/intrin/atomic.h"
|
||||
#include "net/http/tokenbucket.h"
|
||||
|
||||
/**
|
||||
* Returns byte comparison mask w/ 0xff if equal otherwise 0x00.
|
||||
*/
|
||||
static inline uint64_t CompareEq(uint64_t x, uint64_t y) {
|
||||
uint64_t mask, zoro = x ^ y;
|
||||
mask = ((((zoro >> 1) | 0x8080808080808080) - zoro) & 0x8080808080808080);
|
||||
return (mask << 1) - (mask >> 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments all signed bytes in array without overflow.
|
||||
*
|
||||
* This function should be called periodically so buckets have tokens.
|
||||
* While many threads can consumes tokens, only a single thread can use
|
||||
* the replenish operation.
|
||||
*
|
||||
* This function implements a SWAR algorithm offering the best possible
|
||||
* performance under the constraint that operations happen atomically.
|
||||
* This function should take 2ms to add a token to 2**22 buckets which
|
||||
* need a 4mb array that has one bucket for every 1024 IPv4 addresses.
|
||||
* However that doesn't matter since no locks are held during that 2ms
|
||||
* therefore replenishing doesn't block threads that acquire tokens.
|
||||
* Under the token bucket model, operations are denied by default unless
|
||||
* tokens exist to allow them. This function must be called periodically
|
||||
* from a single background thread to replenish the buckets with tokens.
|
||||
* For example, this function may be called once per second which allows
|
||||
* one operation per second on average with bursts up to 127 per second.
|
||||
* This policy needn't be applied uniformly. For example, you might find
|
||||
* out that a large corporation funnels all their traffic through one ip
|
||||
* address, so you could replenish their tokens multiple times a second.
|
||||
*
|
||||
* @param w is word array that aliases byte token array
|
||||
* @param n is number of 64-bit words in `w` array
|
||||
*/
|
||||
void ReplenishTokens(atomic_uint_fast64_t *w, size_t n) {
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
uint64_t x = atomic_load_explicit(w + i, memory_order_relaxed);
|
||||
atomic_fetch_add_explicit(
|
||||
w + i, 0x0101010101010101 & ~CompareEq(x, 0x7f7f7f7f7f7f7f7f),
|
||||
memory_order_acq_rel);
|
||||
uint64_t a = atomic_load_explicit(w + i, memory_order_relaxed);
|
||||
if (a == 0x7f7f7f7f7f7f7f7f) continue;
|
||||
uint64_t b = 0x8080808080808080;
|
||||
uint64_t c = a ^ 0x7f7f7f7f7f7f7f7f;
|
||||
uint64_t d = ((c >> 1 | b) - c & b ^ b) >> 7;
|
||||
atomic_fetch_add_explicit(w + i, d, memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements signed byte index if it's positive.
|
||||
*
|
||||
* This function should be called to take a token from the right bucket
|
||||
* whenever a client wants to use some type of resource. This routine
|
||||
* discriminates based on `c` which is the netmask bit count. There must
|
||||
* exist `1 << c` signed bytes (or buckets) in the `b` array.
|
||||
* Multiple threads may call this method to determine if sufficient
|
||||
* tokens exist to perform an operation. Return values greater than zero
|
||||
* mean a token was atomically acquired. Values less than or equal zero
|
||||
* means the bucket is empty. There must exist `1 << c` signed bytes (or
|
||||
* buckets) in the `b` array.
|
||||
*
|
||||
* Tokens are considered available if the bucket corresponding `x` has a
|
||||
* positive number. This function returns true of a token was atomically
|
||||
* acquired using a lockeless spinless algorithm. Buckets are allowed to
|
||||
* drift into a slightly negative state, but overflow is impractical.
|
||||
* Since this design uses signed bytes, the returned number may be used
|
||||
* to control how much burstiness is allowed. For example:
|
||||
*
|
||||
* int t = AcquireToken(tok.b, ip, 22);
|
||||
* if (t < 64) {
|
||||
* if (t > 8) write(client, "HTTP/1.1 429 \r\n\r\n", 17);
|
||||
* close(client);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* May be used to send a rejection to clients who've exceeded their
|
||||
* tokens whereas clients who've grossly exceeded their tokens will
|
||||
* simply be dropped.
|
||||
*
|
||||
* @param w is array of token buckets
|
||||
* @param n is ipv4 address
|
||||
* @param c is cidr
|
||||
*/
|
||||
bool AcquireToken(atomic_schar *b, uint32_t x, int c) {
|
||||
int AcquireToken(atomic_schar *b, uint32_t x, int c) {
|
||||
uint32_t i = x >> (32 - c);
|
||||
return atomic_load_explicit(b + i, memory_order_relaxed) > 0 &&
|
||||
atomic_fetch_add_explicit(b + i, -1, memory_order_acq_rel) > 0;
|
||||
int t = atomic_load_explicit(b + i, memory_order_relaxed);
|
||||
if (t <= 0) return t;
|
||||
return atomic_fetch_add_explicit(b + i, -1, memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
void ReplenishTokens(atomic_uint_fast64_t *, size_t);
|
||||
bool AcquireToken(atomic_schar *, uint32_t, int);
|
||||
int AcquireToken(atomic_schar *, uint32_t, int);
|
||||
int CountTokens(atomic_schar *, uint32_t, int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -729,7 +729,9 @@ void ServeStatusz(int client, char *outbuf) {
|
|||
|
||||
void *ListenWorker(void *arg) {
|
||||
int server;
|
||||
int no = 0;
|
||||
int yes = 1;
|
||||
int fastopen = 5;
|
||||
struct Client client;
|
||||
struct timeval timeo = {g_keepalive / 1000, g_keepalive % 1000};
|
||||
struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(g_port)};
|
||||
|
@ -740,10 +742,11 @@ void *ListenWorker(void *arg) {
|
|||
setsockopt(server, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
|
||||
setsockopt(server, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo));
|
||||
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
|
||||
setsockopt(server, SOL_TCP, TCP_FASTOPEN, &yes, sizeof(yes));
|
||||
setsockopt(server, SOL_TCP, TCP_QUICKACK, &yes, sizeof(yes));
|
||||
setsockopt(server, SOL_TCP, TCP_FASTOPEN, &fastopen, sizeof(fastopen));
|
||||
setsockopt(server, SOL_TCP, TCP_QUICKACK, &no, sizeof(no));
|
||||
setsockopt(server, SOL_TCP, TCP_CORK, &no, sizeof(no));
|
||||
setsockopt(server, SOL_TCP, TCP_NODELAY, &yes, sizeof(yes));
|
||||
CHECK_NE(-1, bind(server, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
bind(server, (struct sockaddr *)&addr, sizeof(addr));
|
||||
CHECK_NE(-1, listen(server, 1));
|
||||
while (!nsync_note_is_notified(g_shutdown[0])) {
|
||||
client.size = sizeof(client.addr);
|
||||
|
@ -791,7 +794,7 @@ void *HttpWorker(void *arg) {
|
|||
struct Url url;
|
||||
ssize_t got, sent;
|
||||
uint32_t ip, clientip;
|
||||
int inmsglen, outmsglen;
|
||||
int tok, inmsglen, outmsglen;
|
||||
char ipbuf[32], *p, *q, cashbuf[64];
|
||||
|
||||
clientip = ntohl(client.addr.sin_addr.s_addr);
|
||||
|
@ -861,6 +864,19 @@ void *HttpWorker(void *arg) {
|
|||
ksnprintf(ipbuf, sizeof(ipbuf), "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16,
|
||||
ip >> 8, ip);
|
||||
|
||||
if ((tok = AcquireToken(g_tok.b, ip, TB_CIDR)) < 64) {
|
||||
if (tok > 8) {
|
||||
LOG("%s rate limiting client\n", ipbuf, msg->version);
|
||||
Write(client.sock, "HTTP/1.1 429 Too Many Requests\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n"
|
||||
"429 Too Many Requests\n");
|
||||
}
|
||||
++g_ratelimits;
|
||||
break;
|
||||
}
|
||||
|
||||
// we don't support http/1.0 and http/0.9 right now
|
||||
if (msg->version != 11) {
|
||||
LOG("%s used unsupported http/%d version\n", ipbuf, msg->version);
|
||||
|
@ -873,19 +889,8 @@ void *HttpWorker(void *arg) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (!AcquireToken(g_tok.b, ip, TB_CIDR)) {
|
||||
LOG("%s rate limiting client\n", ipbuf, msg->version);
|
||||
Write(client.sock, "HTTP/1.1 429 Too Many Requests\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n"
|
||||
"429 Too Many Requests\n");
|
||||
++g_ratelimits;
|
||||
break;
|
||||
}
|
||||
|
||||
// access log
|
||||
LOG("%16s %.*s %.*s %.*s %.*s %#.*s\n", ipbuf,
|
||||
LOG("%6P %16s %.*s %.*s %.*s %.*s %#.*s\n", ipbuf,
|
||||
msg->xmethod.b - msg->xmethod.a, inbuf + msg->xmethod.a,
|
||||
msg->uri.b - msg->uri.a, inbuf + msg->uri.a,
|
||||
HeaderLength(kHttpCfIpcountry), HeaderData(kHttpCfIpcountry),
|
||||
|
@ -1765,7 +1770,12 @@ OnError:
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// ShowCrashReports();
|
||||
ShowCrashReports();
|
||||
|
||||
if (IsLinux()) {
|
||||
Write(2, "Enabling TCP_FASTOPEN for server sockets...\n");
|
||||
system("sudo sh -c 'echo 2 >/proc/sys/net/ipv4/tcp_fastopen'");
|
||||
}
|
||||
|
||||
// we don't have proper futexes on these platforms
|
||||
// we'll be somewhat less aggressive about workers
|
||||
|
|
|
@ -250,7 +250,7 @@ TEST(pledge, stdio_fcntl_allowsSomeFirstArgs) {
|
|||
ASSERT_SYS(0, 3, fcntl(2, F_DUPFD_CLOEXEC, 3));
|
||||
ASSERT_SYS(0, 0, ioctl(0, FIOCLEX, 0));
|
||||
ASSERT_SYS(EPERM, 0, isatty(0));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, -1));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, 777));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, F_GETLK, &lk));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, F_NOTIFY));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
|
|
32
test/libc/intrin/gettid_test.c
Normal file
32
test/libc/intrin/gettid_test.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/intrin/intrin.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
void OnSig(int sig) {
|
||||
kprintf("got sig\n");
|
||||
}
|
||||
|
||||
TEST(gettid, test) {
|
||||
signal(SIGTRAP, OnSig);
|
||||
DebugBreak();
|
||||
}
|
54
test/libc/thread/pthread_kill_test.c
Normal file
54
test/libc/thread/pthread_kill_test.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
int fds[2];
|
||||
_Thread_local sig_atomic_t gotsig;
|
||||
|
||||
void OnSig(int sig) {
|
||||
gotsig = 1;
|
||||
}
|
||||
|
||||
void *ReadWorker(void *arg) {
|
||||
char buf[8];
|
||||
ASSERT_SYS(EINTR, -1, read(fds[0], buf, 8));
|
||||
ASSERT_TRUE(gotsig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(pthread_kill, canCancelReadOperation) {
|
||||
pthread_t t;
|
||||
struct sigaction oldsa;
|
||||
struct sigaction sa = {.sa_handler = OnSig};
|
||||
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &sa, &oldsa));
|
||||
ASSERT_SYS(0, 0, pipe(fds));
|
||||
ASSERT_EQ(0, pthread_create(&t, 0, ReadWorker, 0));
|
||||
ASSERT_SYS(0, 0, usleep(100000)); // potentially flaky
|
||||
ASSERT_EQ(0, pthread_kill(t, SIGUSR1));
|
||||
ASSERT_EQ(0, pthread_join(t, 0));
|
||||
ASSERT_FALSE(gotsig);
|
||||
ASSERT_SYS(0, 0, close(fds[0]));
|
||||
ASSERT_SYS(0, 0, close(fds[1]));
|
||||
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &oldsa, 0));
|
||||
}
|
|
@ -21,7 +21,6 @@
|
|||
#include "libc/log/check.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
@ -147,6 +146,14 @@ TEST(ParseHttpMessage, testHttp09) {
|
|||
EXPECT_EQ(9, req->version);
|
||||
}
|
||||
|
||||
TEST(ParseHttpMessage, testTinyResponse) {
|
||||
static const char m[] = "HTTP/1.1 429 \r\n\r\n";
|
||||
InitHttpMessage(req, kHttpResponse);
|
||||
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
|
||||
EXPECT_EQ(429, req->status);
|
||||
EXPECT_STREQ("", gc(slice(m, req->message)));
|
||||
}
|
||||
|
||||
TEST(ParseHttpMessage, testLeadingLineFeeds_areIgnored) {
|
||||
static const char m[] = "\
|
||||
\r\n\
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
|
@ -47,27 +48,52 @@ void TearDown(void) {
|
|||
}
|
||||
|
||||
TEST(tokenbucket, test) {
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
ASSERT_EQ(2, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(2, AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_EQ(3, AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
for (int i = 0; i < 130; ++i) ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_EQ(127, AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
}
|
||||
|
||||
void NaiveReplenishTokens(atomic_schar *b, size_t n) {
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
int x = atomic_load_explicit(b + i, memory_order_relaxed);
|
||||
if (x == 127) continue;
|
||||
atomic_fetch_add_explicit(b + i, 1, memory_order_acq_rel);
|
||||
}
|
||||
}
|
||||
|
||||
BENCH(tokenbucket, bench) {
|
||||
struct timespec t1, t2;
|
||||
|
||||
clock_gettime(0, &t1);
|
||||
NaiveReplenishTokens(tok.b, TB_BYTES);
|
||||
clock_gettime(0, &t2);
|
||||
kprintf("NaiveReplenishTokens took %'ld us\n",
|
||||
_timespec_tomicros(_timespec_sub(t2, t1)));
|
||||
|
||||
clock_gettime(0, &t1);
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
clock_gettime(0, &t2);
|
||||
kprintf("token bucket replenish took %'ld us\n",
|
||||
kprintf("ReplenishTokens empty took %'ld us\n",
|
||||
_timespec_tomicros(_timespec_sub(t2, t1)));
|
||||
|
||||
memset(tok.b, 127, TB_BYTES);
|
||||
clock_gettime(0, &t1);
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
clock_gettime(0, &t2);
|
||||
kprintf("ReplenishTokens full took %'ld us\n",
|
||||
_timespec_tomicros(_timespec_sub(t2, t1)));
|
||||
}
|
||||
|
|
21
third_party/musl/lockf.c
vendored
21
third_party/musl/lockf.c
vendored
|
@ -30,6 +30,8 @@
|
|||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "third_party/musl/lockf.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
Musl libc (MIT License)\\n\
|
||||
|
@ -44,25 +46,20 @@ int lockf(int fd, int op, off_t size)
|
|||
.l_whence = SEEK_CUR,
|
||||
.l_len = size,
|
||||
};
|
||||
if (op == F_TEST){
|
||||
switch (op) {
|
||||
case F_TEST:
|
||||
l.l_type = F_RDLCK;
|
||||
if (fcntl(fd, F_GETLK, &l) < 0)
|
||||
return -1;
|
||||
if (l.l_type == F_UNLCK || l.l_pid == getpid())
|
||||
return 0;
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
if (op == F_ULOCK) {
|
||||
return eacces();
|
||||
case F_ULOCK:
|
||||
l.l_type = F_UNLCK;
|
||||
case F_TLOCK:
|
||||
return fcntl(fd, F_SETLK, &l);
|
||||
}
|
||||
if (op == F_TLOCK) {
|
||||
return fcntl(fd, F_SETLK, &l);
|
||||
}
|
||||
if (op == F_LOCK) {
|
||||
case F_LOCK:
|
||||
return fcntl(fd, F_SETLKW, &l);
|
||||
}
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return einval();
|
||||
}
|
||||
|
|
16
third_party/musl/lockf.h
vendored
Normal file
16
third_party/musl/lockf.h
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_LOCKF_H_
|
||||
#define COSMOPOLITAN_THIRD_PARTY_MUSL_LOCKF_H_
|
||||
|
||||
#define F_ULOCK 0
|
||||
#define F_LOCK 1
|
||||
#define F_TLOCK 2
|
||||
#define F_TEST 3
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int lockf(int, int, int64_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_LOCKF_H_ */
|
7
third_party/nsync/futex.c
vendored
7
third_party/nsync/futex.c
vendored
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
|
@ -166,6 +167,9 @@ int nsync_futex_wait_ (int *p, int expect, char pshare, struct timespec *timeout
|
|||
if (pshare) {
|
||||
goto Polyfill;
|
||||
}
|
||||
if (_check_interrupts (false, 0)) {
|
||||
rc = -EINTR;
|
||||
} else {
|
||||
if (timeout) {
|
||||
ms = _timespec_tomillis (*timeout);
|
||||
} else {
|
||||
|
@ -176,6 +180,7 @@ int nsync_futex_wait_ (int *p, int expect, char pshare, struct timespec *timeout
|
|||
} else {
|
||||
rc = -GetLastError ();
|
||||
}
|
||||
}
|
||||
} else if (IsFreebsd ()) {
|
||||
rc = sys_umtx_timedwait_uint (
|
||||
p, expect, pshare, timeout);
|
||||
|
@ -193,7 +198,7 @@ int nsync_futex_wait_ (int *p, int expect, char pshare, struct timespec *timeout
|
|||
__get_tls()->tib_flags &= ~TIB_FLAG_TIME_CRITICAL;
|
||||
}
|
||||
|
||||
STRACE ("futex(%t, %s, %d, %s) → %s",
|
||||
STRACE ("futex(%t, %s, %#x, %s) → %s",
|
||||
p, DescribeFutexOp (op), expect,
|
||||
DescribeTimespec (0, timeout),
|
||||
DescribeErrnoResult (rc));
|
||||
|
|
3
third_party/nsync/mem/nsync_sem_wait.c
vendored
3
third_party/nsync/mem/nsync_sem_wait.c
vendored
|
@ -16,6 +16,7 @@
|
|||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/nsync/atomic.h"
|
||||
#include "third_party/nsync/atomic.internal.h"
|
||||
#include "third_party/nsync/common.internal.h"
|
||||
|
@ -81,5 +82,3 @@ int nsync_sem_wait_with_cancel_ (waiter *w, nsync_time abs_deadline,
|
|||
}
|
||||
return (sem_outcome);
|
||||
}
|
||||
|
||||
|
||||
|
|
33
third_party/nsync/mem/nsync_sem_wait_no_note.c
vendored
33
third_party/nsync/mem/nsync_sem_wait_no_note.c
vendored
|
@ -1,33 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2016 Google Inc. │
|
||||
│ │
|
||||
│ Licensed under the Apache License, Version 2.0 (the "License"); │
|
||||
│ you may not use this file except in compliance with the License. │
|
||||
│ You may obtain a copy of the License at │
|
||||
│ │
|
||||
│ http://www.apache.org/licenses/LICENSE-2.0 │
|
||||
│ │
|
||||
│ Unless required by applicable law or agreed to in writing, software │
|
||||
│ distributed under the License is distributed on an "AS IS" BASIS, │
|
||||
│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
|
||||
│ See the License for the specific language governing permissions and │
|
||||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "third_party/nsync/common.internal.h"
|
||||
#include "third_party/nsync/mu_semaphore.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
*NSYNC (Apache 2.0)\\n\
|
||||
Copyright 2016 Google, Inc.\\n\
|
||||
https://github.com/google/nsync\"");
|
||||
// clang-format off
|
||||
|
||||
/* Wait until one of:
|
||||
w->sem is non-zero----decrement it and return 0.
|
||||
abs_deadline expires---return ETIMEDOUT.
|
||||
Ignores cancel_note. */
|
||||
int nsync_sem_wait_with_cancel_ (waiter *w, nsync_time abs_deadline, nsync_note cancel_note) {
|
||||
return (nsync_mu_semaphore_p_with_deadline (&w->sem, abs_deadline));
|
||||
}
|
7
third_party/python/Modules/posixmodule.c
vendored
7
third_party/python/Modules/posixmodule.c
vendored
|
@ -62,6 +62,7 @@
|
|||
#include "libc/time/struct/utimbuf.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/musl/lockf.h"
|
||||
#include "third_party/musl/passwd.h"
|
||||
#include "third_party/python/Include/abstract.h"
|
||||
#include "third_party/python/Include/boolobject.h"
|
||||
|
@ -11894,10 +11895,10 @@ all_ins(PyObject *m)
|
|||
if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
|
||||
|
||||
/* constants for lockf */
|
||||
if (F_LOCK && PyModule_AddIntMacro(m, F_LOCK)) return -1;
|
||||
if (F_TLOCK && PyModule_AddIntMacro(m, F_TLOCK)) return -1;
|
||||
if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
|
||||
if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
|
||||
if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
|
||||
if (F_TEST && PyModule_AddIntMacro(m, F_TEST)) return -1;
|
||||
if (PyModule_AddIntMacro(m, F_TEST)) return -1;
|
||||
|
||||
#ifdef HAVE_SPAWNV
|
||||
if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
|
||||
|
|
2
third_party/python/pyconfig.h
vendored
2
third_party/python/pyconfig.h
vendored
|
@ -227,7 +227,7 @@
|
|||
/* #undef HAVE_LINUX_CAN_RAW_FD_FRAMES */
|
||||
|
||||
/* Define to 1 if you have the 'lockf' function and the F_LOCK macro. */
|
||||
/* #undef HAVE_LOCKF */
|
||||
#define HAVE_LOCKF 1
|
||||
|
||||
/* #define HAVE_DEVICE_MACROS 1 */
|
||||
#define HAVE_MAKEDEV 1
|
||||
|
|
4
third_party/sqlite3/README.cosmo
vendored
4
third_party/sqlite3/README.cosmo
vendored
|
@ -10,3 +10,7 @@ ORIGIN
|
|||
LICENSE
|
||||
|
||||
Public Domain or MIT
|
||||
|
||||
LOCAL CHANGES
|
||||
|
||||
- Changed the fsync() code to be configured at runtime.
|
||||
|
|
4
third_party/sqlite3/main.c
vendored
4
third_party/sqlite3/main.c
vendored
|
@ -3105,10 +3105,6 @@ static int openDatabase(
|
|||
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
|
||||
int i; /* Loop counter */
|
||||
|
||||
// TODO(jart): Fix SQLite.
|
||||
extern bool __force_sqlite_to_work_until_we_can_fix_it;
|
||||
__force_sqlite_to_work_until_we_can_fix_it = true;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
|
|
15
third_party/sqlite3/os_unix.c
vendored
15
third_party/sqlite3/os_unix.c
vendored
|
@ -53,6 +53,8 @@
|
|||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#include "third_party/sqlite3/mutex.internal.h"
|
||||
#include "third_party/sqlite3/mutex.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/dce.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#if SQLITE_OS_UNIX /* This file is used on unix only */
|
||||
|
||||
|
@ -3612,8 +3614,9 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
|
|||
struct stat buf;
|
||||
rc = osFstat(fd, &buf);
|
||||
}
|
||||
#elif HAVE_FULLFSYNC
|
||||
if( fullSync ){
|
||||
#elif HAVE_FULLFSYNC || defined(__COSMOPOLITAN__)
|
||||
/* [jart] use runtime os detection */
|
||||
if( fullSync && F_FULLFSYNC != -1 ){
|
||||
rc = osFcntl(fd, F_FULLFSYNC, 0);
|
||||
}else{
|
||||
rc = 1;
|
||||
|
@ -3626,7 +3629,13 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
|
|||
** It'd be better to detect fullfsync support once and avoid
|
||||
** the fcntl call every time sync is called.
|
||||
*/
|
||||
if( rc ) rc = fsync(fd);
|
||||
if( rc ) {
|
||||
if( IsXnu() ){
|
||||
rc = fsync(fd);
|
||||
}else{
|
||||
rc = fdatasync(fd);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
/* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
|
||||
|
|
2
third_party/sqlite3/shell.c
vendored
2
third_party/sqlite3/shell.c
vendored
|
@ -59,6 +59,7 @@
|
|||
#include "libc/sysv/consts/rusage.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/errno.h"
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
#include "third_party/sqlite3/sqlite3userauth.inc"
|
||||
#endif
|
||||
|
@ -10573,6 +10574,7 @@ static void process_sqliterc(
|
|||
p->in = inSaved;
|
||||
p->lineno = savedLineno;
|
||||
sqlite3_free(zBuf);
|
||||
errno = 0; /* [jart] clear error */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue