mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 15:38:22 +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 │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/calls/state.internal.h"
|
#include "libc/calls/state.internal.h"
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/siginfo.h"
|
#include "libc/calls/struct/siginfo.h"
|
||||||
#include "libc/intrin/cmpxchg.h"
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/intrin/lockcmpxchg.h"
|
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/log/libfatal.internal.h"
|
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/sa.h"
|
#include "libc/sysv/consts/sa.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
/**
|
|
||||||
* @fileoverview UNIX signals for the New Technology, Part 2.
|
|
||||||
* @threadsafe
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates piece of memory for storing pending signal.
|
* Allocates piece of memory for storing pending signal.
|
||||||
|
@ -61,16 +57,30 @@ static textwindows void __sig_free(struct Signal *mem) {
|
||||||
mem->used = false;
|
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.
|
* Dequeues signal that isn't masked.
|
||||||
* @return signal or null if empty or none unmasked
|
* @return signal or null if empty or none unmasked
|
||||||
*/
|
*/
|
||||||
static textwindows struct Signal *__sig_remove(void) {
|
static textwindows struct Signal *__sig_remove(void) {
|
||||||
|
int tid;
|
||||||
struct Signal *prev, *res;
|
struct Signal *prev, *res;
|
||||||
if (__sig.queue) {
|
if (__sig.queue) {
|
||||||
|
tid = gettid();
|
||||||
__sig_lock();
|
__sig_lock();
|
||||||
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
|
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) {
|
if (res == __sig.queue) {
|
||||||
__sig.queue = res->next;
|
__sig.queue = res->next;
|
||||||
} else if (prev) {
|
} else if (prev) {
|
||||||
|
@ -78,8 +88,6 @@ static textwindows struct Signal *__sig_remove(void) {
|
||||||
}
|
}
|
||||||
res->next = 0;
|
res->next = 0;
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
STRACE("%G is masked", res->sig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__sig_unlock();
|
__sig_unlock();
|
||||||
|
@ -117,7 +125,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
||||||
// setup the somewhat expensive information args
|
// setup the somewhat expensive information args
|
||||||
// only if they're requested by the user in sigaction()
|
// only if they're requested by the user in sigaction()
|
||||||
if (flags & SA_SIGINFO) {
|
if (flags & SA_SIGINFO) {
|
||||||
__repstosb(&info, 0, sizeof(info));
|
bzero(&info, sizeof(info));
|
||||||
info.si_signo = sig;
|
info.si_signo = sig;
|
||||||
info.si_code = si_code;
|
info.si_code = si_code;
|
||||||
infop = &info;
|
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
|
// since sigaction() is @asyncsignalsafe we only restore it if the
|
||||||
// user didn't change it during the signal handler. we also don't
|
// 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.
|
// 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) {
|
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.
|
* 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) {
|
if (sig == SIGCHLD || sig == SIGURG || sig == SIGWINCH) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -168,7 +180,7 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
|
||||||
bool delivered;
|
bool delivered;
|
||||||
switch (__sighandrvas[sig]) {
|
switch (__sighandrvas[sig]) {
|
||||||
case (intptr_t)SIG_DFL:
|
case (intptr_t)SIG_DFL:
|
||||||
if (__sig_isfatal(sig)) {
|
if (__sig_is_fatal(sig)) {
|
||||||
STRACE("terminating on %G", sig);
|
STRACE("terminating on %G", sig);
|
||||||
_Exitr(128 + sig);
|
_Exitr(128 + sig);
|
||||||
}
|
}
|
||||||
|
@ -194,20 +206,17 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
|
||||||
* @threadsafe
|
* @threadsafe
|
||||||
*/
|
*/
|
||||||
textwindows int __sig_raise(int sig, int si_code) {
|
textwindows int __sig_raise(int sig, int si_code) {
|
||||||
int rc;
|
if (1 <= sig && sig <= 64) {
|
||||||
int candeliver;
|
if (!__sig_is_masked(sig)) {
|
||||||
__sig_lock();
|
++__sig_count;
|
||||||
candeliver = !sigismember(&__sig.mask, sig);
|
|
||||||
__sig_unlock();
|
|
||||||
switch (candeliver) {
|
|
||||||
case 1:
|
|
||||||
__sig_handle(false, sig, si_code, 0);
|
__sig_handle(false, sig, si_code, 0);
|
||||||
return 0;
|
return 0;
|
||||||
case 0:
|
} else {
|
||||||
STRACE("%G is masked", sig);
|
STRACE("%G is masked", sig);
|
||||||
return __sig_add(sig, si_code);
|
return __sig_add(gettid(), sig, si_code);
|
||||||
default:
|
}
|
||||||
return -1; // sigismember() validates `sig`
|
} else {
|
||||||
|
return einval();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,10 +225,10 @@ textwindows int __sig_raise(int sig, int si_code) {
|
||||||
* @return 0 on success, otherwise -1 w/ errno
|
* @return 0 on success, otherwise -1 w/ errno
|
||||||
* @threadsafe
|
* @threadsafe
|
||||||
*/
|
*/
|
||||||
textwindows int __sig_add(int sig, int si_code) {
|
textwindows int __sig_add(int tid, int sig, int si_code) {
|
||||||
int rc;
|
int rc;
|
||||||
struct Signal *mem;
|
struct Signal *mem;
|
||||||
if (1 <= sig && sig <= NSIG) {
|
if (1 <= sig && sig <= 64) {
|
||||||
__sig_lock();
|
__sig_lock();
|
||||||
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
|
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
|
||||||
STRACE("ignoring %G", sig);
|
STRACE("ignoring %G", sig);
|
||||||
|
@ -228,6 +237,7 @@ textwindows int __sig_add(int sig, int si_code) {
|
||||||
STRACE("enqueuing %G", sig);
|
STRACE("enqueuing %G", sig);
|
||||||
++__sig_count;
|
++__sig_count;
|
||||||
if ((mem = __sig_alloc())) {
|
if ((mem = __sig_alloc())) {
|
||||||
|
mem->tid = tid;
|
||||||
mem->sig = sig;
|
mem->sig = sig;
|
||||||
mem->si_code = si_code;
|
mem->si_code = si_code;
|
||||||
mem->next = __sig.queue;
|
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) {
|
textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
|
||||||
struct Signal *cur, *prev, *next;
|
struct Signal *cur, *prev, *next;
|
||||||
if (rva != (unsigned)(intptr_t)SIG_IGN &&
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (__sig.queue) {
|
if (__sig.queue) {
|
||||||
|
@ -298,25 +308,3 @@ textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
|
||||||
__sig_unlock();
|
__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. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/sig.internal.h"
|
#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/consts/sig.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
/**
|
#define GetSigBit(x) (1ull << (((x)-1) & 63))
|
||||||
* @fileoverview UNIX signals for the New Technology, Part 1.
|
|
||||||
* @threadsafe
|
|
||||||
*/
|
|
||||||
|
|
||||||
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) {
|
textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
||||||
int i;
|
uint64_t x, y, *mask;
|
||||||
uint64_t a, b;
|
|
||||||
if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) {
|
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) {
|
if (old) {
|
||||||
*old = __sig.mask;
|
old->__bits[0] = *mask;
|
||||||
|
old->__bits[1] = 0;
|
||||||
}
|
}
|
||||||
if (neu) {
|
if (neu) {
|
||||||
for (i = 0; i < ARRAYLEN(__sig.mask.__bits); ++i) {
|
x = *mask;
|
||||||
if (how == SIG_BLOCK) {
|
y = neu->__bits[0];
|
||||||
__sig.mask.__bits[i] |= neu->__bits[i];
|
if (how == SIG_BLOCK) {
|
||||||
} else if (how == SIG_UNBLOCK) {
|
x |= y;
|
||||||
__sig.mask.__bits[i] &= ~neu->__bits[i];
|
} else if (how == SIG_UNBLOCK) {
|
||||||
} else {
|
x &= ~y;
|
||||||
__sig.mask.__bits[i] = neu->__bits[i];
|
} else {
|
||||||
}
|
x = y;
|
||||||
}
|
}
|
||||||
__sig.mask.__bits[0] &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP));
|
x &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP) | GetSigBit(SIGABRT));
|
||||||
|
*mask = x;
|
||||||
}
|
}
|
||||||
__sig_unlock();
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return einval();
|
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 fcntl(int, int, ...);
|
||||||
int fdatasync(int);
|
int fdatasync(int);
|
||||||
int flock(int, int);
|
int flock(int, int);
|
||||||
int lockf(int, int, int64_t);
|
|
||||||
int fork(void);
|
int fork(void);
|
||||||
int fsync(int);
|
int fsync(int);
|
||||||
int ftruncate(int, int64_t);
|
int ftruncate(int, int64_t);
|
||||||
|
|
|
@ -35,27 +35,29 @@
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @return 0 on success, or -1 w/ errno
|
* @return 0 on success, or -1 w/ errno
|
||||||
* @error EBADF if `first` is negative
|
* @raise EBADF if `first` is negative
|
||||||
* @error EBADF on OpenBSD if `first` is greater than highest fd
|
* @raise ENOSYS if not Linux 5.9+, FreeBSD 8+, OpenBSD, or NetBSD
|
||||||
* @error EINVAL if flags are bad or first is greater than last
|
* @raise EBADF on OpenBSD if `first` is greater than highest fd
|
||||||
* @error EMFILE if a weird race condition happens on Linux
|
* @raise EINVAL if flags are bad or first is greater than last
|
||||||
* @error ENOSYS if not Linux 5.9+, FreeBSD 8+, or OpenBSD
|
* @raise EMFILE if a weird race condition happens on Linux
|
||||||
* @error EINTR possibly on OpenBSD
|
* @raise EINTR possibly on OpenBSD
|
||||||
* @error ENOMEM on Linux maybe
|
* @raise ENOMEM on Linux maybe
|
||||||
*/
|
*/
|
||||||
int closefrom(int first) {
|
int closefrom(int first) {
|
||||||
int rc, err;
|
int rc, err;
|
||||||
if (IsNetbsd() || IsWindows() || IsMetal()) {
|
if (first < 0) {
|
||||||
rc = enosys();
|
|
||||||
} else if (first < 0) {
|
|
||||||
// consistent with openbsd
|
// consistent with openbsd
|
||||||
// freebsd allows this but it's dangerous
|
// freebsd allows this but it's dangerous
|
||||||
// necessary on linux due to type signature
|
// necessary on linux due to type signature
|
||||||
rc = ebadf();
|
rc = ebadf();
|
||||||
|
} else if (IsFreebsd() || IsOpenbsd()) {
|
||||||
|
rc = sys_closefrom(first);
|
||||||
} else if (IsLinux()) {
|
} else if (IsLinux()) {
|
||||||
rc = sys_close_range(first, 0xffffffffu, 0);
|
rc = sys_close_range(first, 0xffffffffu, 0);
|
||||||
|
} else if (IsNetbsd()) {
|
||||||
|
rc = __sys_fcntl(first, 10 /*F_CLOSEM*/, first);
|
||||||
} else {
|
} else {
|
||||||
rc = sys_closefrom(first);
|
rc = enosys();
|
||||||
}
|
}
|
||||||
STRACE("closefrom(%d) → %d% m", first, rc);
|
STRACE("closefrom(%d) → %d% m", first, rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/errfuns.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) {
|
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
|
||||||
if (start < 0) return einval();
|
if (start < 0) return einval();
|
||||||
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
|
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;
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ok || __force_sqlite_to_work_until_we_can_fix_it) {
|
return ok ? 0 : -1;
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l->l_type == F_UNLCK) {
|
if (l->l_type == F_UNLCK) {
|
||||||
|
|
|
@ -18,11 +18,15 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.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-nt.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
|
#include "libc/sysv/consts/f.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
|
@ -44,9 +48,49 @@
|
||||||
* Please be warned that locks currently do nothing on Windows since
|
* Please be warned that locks currently do nothing on Windows since
|
||||||
* figuring out how to polyfill them correctly is a work in progress.
|
* 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
|
* @param arg can be FD_CLOEXEC, etc. depending
|
||||||
* @return 0 on success, or -1 w/ errno
|
* @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
|
* @asyncsignalsafe
|
||||||
* @restartable
|
* @restartable
|
||||||
*/
|
*/
|
||||||
|
@ -54,20 +98,58 @@ int fcntl(int fd, int cmd, ...) {
|
||||||
int rc;
|
int rc;
|
||||||
va_list va;
|
va_list va;
|
||||||
uintptr_t arg;
|
uintptr_t arg;
|
||||||
|
|
||||||
va_start(va, cmd);
|
va_start(va, cmd);
|
||||||
arg = va_arg(va, uintptr_t);
|
arg = va_arg(va, uintptr_t);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
if (cmd >= 0) {
|
||||||
rc = _weaken(__zipos_fcntl)(fd, cmd, arg);
|
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||||
} else if (!IsWindows()) {
|
rc = _weaken(__zipos_fcntl)(fd, cmd, arg);
|
||||||
rc = sys_fcntl(fd, cmd, arg);
|
} else if (!IsWindows()) {
|
||||||
|
rc = sys_fcntl(fd, cmd, arg);
|
||||||
|
} else {
|
||||||
|
rc = sys_fcntl_nt(fd, cmd, arg);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = sys_fcntl_nt(fd, cmd, arg);
|
rc = einval();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = ebadf();
|
||||||
}
|
}
|
||||||
STRACE("fcntl(%d, %d, %p) → %#x% m", fd, cmd, arg, rc);
|
|
||||||
|
#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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,11 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#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-nt.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
*/
|
*/
|
||||||
int fdatasync(int fd) {
|
int fdatasync(int fd) {
|
||||||
int rc;
|
int rc;
|
||||||
|
struct stat st;
|
||||||
if (__nosync != 0x5453455454534146) {
|
if (__nosync != 0x5453455454534146) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
rc = sys_fdatasync(fd);
|
rc = sys_fdatasync(fd);
|
||||||
|
@ -41,8 +43,8 @@ int fdatasync(int fd) {
|
||||||
}
|
}
|
||||||
STRACE("fdatasync(%d) → %d% m", fd, rc);
|
STRACE("fdatasync(%d) → %d% m", fd, rc);
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = fstat(fd, &st);
|
||||||
STRACE("fdatasync(%d) → disabled% m", fd);
|
STRACE("fdatasync_fake(%d) → %d% m", fd, rc);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,11 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#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-nt.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
*/
|
*/
|
||||||
int fsync(int fd) {
|
int fsync(int fd) {
|
||||||
int rc;
|
int rc;
|
||||||
|
struct stat st;
|
||||||
if (__nosync != 0x5453455454534146) {
|
if (__nosync != 0x5453455454534146) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
rc = sys_fsync(fd);
|
rc = sys_fsync(fd);
|
||||||
|
@ -41,8 +43,8 @@ int fsync(int fd) {
|
||||||
}
|
}
|
||||||
STRACE("fysnc(%d) → %d% m", fd, rc);
|
STRACE("fysnc(%d) → %d% m", fd, rc);
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = fstat(fd, &st);
|
||||||
STRACE("fsync(%d) → disabled% m", fd);
|
STRACE("fsync_fake(%d) → %d% m", fd, rc);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
||||||
int64_t me, nsignals;
|
int64_t me;
|
||||||
struct NtIoCounters iocount;
|
struct NtIoCounters iocount;
|
||||||
struct NtProcessMemoryCountersEx memcount;
|
struct NtProcessMemoryCountersEx memcount;
|
||||||
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
|
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
|
||||||
|
@ -48,9 +48,6 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
||||||
!GetProcessIoCounters(me, &iocount)) {
|
!GetProcessIoCounters(me, &iocount)) {
|
||||||
return __winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
__sig_lock();
|
|
||||||
nsignals = __sig_count;
|
|
||||||
__sig_unlock();
|
|
||||||
*usage = (struct rusage){
|
*usage = (struct rusage){
|
||||||
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
|
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
|
||||||
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
|
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
|
||||||
|
|
|
@ -31,9 +31,8 @@
|
||||||
|
|
||||||
textwindows bool _check_interrupts(bool restartable, struct Fd *fd) {
|
textwindows bool _check_interrupts(bool restartable, struct Fd *fd) {
|
||||||
bool res;
|
bool res;
|
||||||
if (__threaded && __threaded != gettid()) return false;
|
|
||||||
if (_weaken(_check_sigalrm)) _weaken(_check_sigalrm)();
|
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 (_weaken(_check_sigchld)) _weaken(_check_sigchld)();
|
||||||
if (fd && _weaken(_check_sigwinch)) _weaken(_check_sigwinch)(fd);
|
if (fd && _weaken(_check_sigwinch)) _weaken(_check_sigwinch)(fd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,25 +17,44 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nexgen32e/nt2sysv.h"
|
#include "libc/nexgen32e/nt2sysv.h"
|
||||||
#include "libc/nt/enum/ctrlevent.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/sicode.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
|
#include "libc/thread/tls2.h"
|
||||||
|
|
||||||
textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
|
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);
|
STRACE("__onntconsoleevent(%u)", dwCtrlType);
|
||||||
switch (dwCtrlType) {
|
switch (dwCtrlType) {
|
||||||
case kNtCtrlCEvent:
|
case kNtCtrlCEvent:
|
||||||
__sig_add(SIGINT, SI_KERNEL);
|
__sig_add(0, SIGINT, SI_KERNEL);
|
||||||
return true;
|
return true;
|
||||||
case kNtCtrlBreakEvent:
|
case kNtCtrlBreakEvent:
|
||||||
__sig_add(SIGQUIT, SI_KERNEL);
|
__sig_add(0, SIGQUIT, SI_KERNEL);
|
||||||
return true;
|
return true;
|
||||||
case kNtCtrlCloseEvent:
|
case kNtCtrlCloseEvent:
|
||||||
case kNtCtrlLogoffEvent: // only received by services
|
case kNtCtrlLogoffEvent: // only received by services
|
||||||
case kNtCtrlShutdownEvent: // only received by services
|
case kNtCtrlShutdownEvent: // only received by services
|
||||||
__sig_add(SIGHUP, SI_KERNEL);
|
__sig_add(0, SIGHUP, SI_KERNEL);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1256,16 +1256,18 @@ static privileged void AllowIoctlTty(struct Filter *f) {
|
||||||
// - TCP_FASTOPEN (0x17)
|
// - TCP_FASTOPEN (0x17)
|
||||||
// - TCP_FASTOPEN_CONNECT (0x1e)
|
// - TCP_FASTOPEN_CONNECT (0x1e)
|
||||||
// - IPV6_V6ONLY (0x1a)
|
// - IPV6_V6ONLY (0x1a)
|
||||||
|
// - TCP_QUICKACK (0x0c)
|
||||||
//
|
//
|
||||||
static privileged void AllowSetsockoptRestrict(struct Filter *f) {
|
static privileged void AllowSetsockoptRestrict(struct Filter *f) {
|
||||||
static const struct sock_filter fragment[] = {
|
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_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, 41, 3, 0),
|
||||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 2, 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, 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_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, 0x1a, 15, 0),
|
||||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 14, 0),
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 14, 0),
|
||||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0f, 13, 0),
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0f, 13, 0),
|
||||||
|
|
|
@ -18,13 +18,13 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/sysv/consts/sicode.h"
|
#include "libc/sysv/consts/sicode.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
#include "libc/thread/xnu.internal.h"
|
#include "libc/thread/xnu.internal.h"
|
||||||
|
|
||||||
static textwindows inline bool HasWorkingConsole(void) {
|
static textwindows inline bool HasWorkingConsole(void) {
|
||||||
|
@ -59,7 +59,7 @@ static noubsan void RaiseSigFpe(void) {
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
int raise(int sig) {
|
int raise(int sig) {
|
||||||
int rc, event;
|
int rc, tid, event;
|
||||||
STRACE("raise(%G) → ...", sig);
|
STRACE("raise(%G) → ...", sig);
|
||||||
if (sig == SIGTRAP) {
|
if (sig == SIGTRAP) {
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
|
@ -67,7 +67,7 @@ int raise(int sig) {
|
||||||
} else if (sig == SIGFPE) {
|
} else if (sig == SIGFPE) {
|
||||||
RaiseSigFpe();
|
RaiseSigFpe();
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows() && !IsMetal()) {
|
||||||
rc = sys_tkill(gettid(), sig, 0);
|
rc = sys_tkill(gettid(), sig, 0);
|
||||||
} else {
|
} else {
|
||||||
rc = __sig_raise(sig, SI_TKILL);
|
rc = __sig_raise(sig, SI_TKILL);
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
|
||||||
#include "libc/calls/struct/itimerval.h"
|
#include "libc/calls/struct/itimerval.h"
|
||||||
#include "libc/calls/struct/siginfo.h"
|
#include "libc/calls/struct/siginfo.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/math.h"
|
#include "libc/math.h"
|
||||||
#include "libc/nexgen32e/nexgen32e.h"
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
|
@ -68,7 +68,7 @@ textwindows void _check_sigalrm(void) {
|
||||||
now = nowl();
|
now = nowl();
|
||||||
elapsed = now - __lastalrm;
|
elapsed = now - __lastalrm;
|
||||||
if (elapsed > __interval) {
|
if (elapsed > __interval) {
|
||||||
__sig_add(SIGALRM, SI_TIMER);
|
__sig_add(0, SIGALRM, SI_TIMER);
|
||||||
if (__singleshot) {
|
if (__singleshot) {
|
||||||
__hastimer = false;
|
__hastimer = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||||
#define 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/struct/sigset.h"
|
||||||
#include "libc/calls/ucontext.h"
|
#include "libc/calls/ucontext.h"
|
||||||
|
|
||||||
#define __SIG_QUEUE_LENGTH 8
|
#define __SIG_QUEUE_LENGTH 32
|
||||||
#define __SIG_POLLING_INTERVAL_MS 50
|
#define __SIG_POLLING_INTERVAL_MS 50
|
||||||
#define __SIG_LOGGING_INTERVAL_MS 1700
|
#define __SIG_LOGGING_INTERVAL_MS 1700
|
||||||
|
|
||||||
|
@ -13,26 +14,28 @@ COSMOPOLITAN_C_START_
|
||||||
struct Signal {
|
struct Signal {
|
||||||
struct Signal *next;
|
struct Signal *next;
|
||||||
bool used;
|
bool used;
|
||||||
|
int tid;
|
||||||
int sig;
|
int sig;
|
||||||
int si_code;
|
int si_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Signals {
|
struct Signals {
|
||||||
sigset_t mask;
|
uint64_t sigmask; /* only if tls is disabled */
|
||||||
struct Signal *queue;
|
struct Signal *queue;
|
||||||
struct Signal mem[__SIG_QUEUE_LENGTH];
|
struct Signal mem[__SIG_QUEUE_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern long __sig_count;
|
|
||||||
extern struct Signals __sig;
|
extern struct Signals __sig;
|
||||||
|
extern atomic_long __sig_count;
|
||||||
|
|
||||||
bool __sig_check(bool) hidden;
|
bool __sig_check(bool) hidden;
|
||||||
bool __sig_handle(bool, int, int, ucontext_t *) 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_mask(int, const sigset_t *, sigset_t *) hidden;
|
||||||
int __sig_raise(int, int) hidden;
|
int __sig_raise(int, int) hidden;
|
||||||
void __sig_check_ignore(const int, const unsigned) hidden;
|
void __sig_check_ignore(const int, const unsigned) hidden;
|
||||||
void __sig_pending(sigset_t *) hidden;
|
void __sig_pending(sigset_t *) hidden;
|
||||||
|
int __sig_is_applicable(struct Signal *) hidden;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/calls/state.internal.h"
|
#include "libc/calls/state.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
|
||||||
#include "libc/calls/struct/siginfo.h"
|
#include "libc/calls/struct/siginfo.h"
|
||||||
#include "libc/calls/syscall_support-nt.internal.h"
|
#include "libc/calls/syscall_support-nt.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/enum/wait.h"
|
#include "libc/nt/enum/wait.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/synchronization.h"
|
#include "libc/nt/synchronization.h"
|
||||||
|
@ -65,5 +65,5 @@ void _check_sigchld(void) {
|
||||||
__fds_lock();
|
__fds_lock();
|
||||||
g_fds.p[pids[i]].zombie = true;
|
g_fds.p[pids[i]].zombie = true;
|
||||||
__fds_unlock();
|
__fds_unlock();
|
||||||
__sig_add(SIGCHLD, CLD_EXITED);
|
__sig_add(0, SIGCHLD, CLD_EXITED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,4 +18,4 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
|
|
||||||
long __sig_count;
|
atomic_long __sig_count;
|
||||||
|
|
|
@ -19,17 +19,18 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
|
||||||
#include "libc/calls/struct/fd.internal.h"
|
#include "libc/calls/struct/fd.internal.h"
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/winsize.h"
|
#include "libc/calls/struct/winsize.h"
|
||||||
#include "libc/calls/struct/winsize.internal.h"
|
#include "libc/calls/struct/winsize.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/struct/consolescreenbufferinfoex.h"
|
#include "libc/nt/struct/consolescreenbufferinfoex.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/sicode.h"
|
#include "libc/sysv/consts/sicode.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
static struct winsize __ws;
|
static struct winsize __ws;
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ textwindows void _check_sigwinch(struct Fd *fd) {
|
||||||
siginfo_t si;
|
siginfo_t si;
|
||||||
struct winsize ws, old;
|
struct winsize ws, old;
|
||||||
struct NtConsoleScreenBufferInfoEx sbinfo;
|
struct NtConsoleScreenBufferInfoEx sbinfo;
|
||||||
|
if (__tls_enabled && __threaded != gettid()) return;
|
||||||
old = __ws;
|
old = __ws;
|
||||||
e = errno;
|
e = errno;
|
||||||
if (old.ws_row != 0xffff) {
|
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) {
|
if (old.ws_col != ws.ws_col || old.ws_row != ws.ws_row) {
|
||||||
__ws = ws;
|
__ws = ws;
|
||||||
if (old.ws_col | old.ws_row) {
|
if (old.ws_col | old.ws_row) {
|
||||||
__sig_add(SIGWINCH, SI_KERNEL);
|
__sig_add(0, SIGWINCH, SI_KERNEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/calls/syscall_support-nt.internal.h"
|
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/enum/threadaccess.h"
|
#include "libc/sysv/consts/sicode.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kills thread.
|
* Kills thread.
|
||||||
|
@ -56,10 +37,10 @@ static textwindows int sys_tkill_nt(int tid, int sig) {
|
||||||
*/
|
*/
|
||||||
int tkill(int tid, int sig) {
|
int tkill(int tid, int sig) {
|
||||||
int rc;
|
int rc;
|
||||||
if (!IsWindows()) {
|
if (!IsWindows() && !IsMetal()) {
|
||||||
rc = sys_tkill(tid, sig, 0);
|
rc = sys_tkill(tid, sig, 0);
|
||||||
} else {
|
} else {
|
||||||
rc = sys_tkill_nt(tid, sig);
|
rc = __sig_add(tid, sig, SI_TKILL);
|
||||||
}
|
}
|
||||||
STRACE("tkill(%d, %G) → %d% m", tid, sig, rc);
|
STRACE("tkill(%d, %G) → %d% m", tid, sig, rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct MagnumStr {
|
||||||
hidden extern const struct MagnumStr kClockNames[];
|
hidden extern const struct MagnumStr kClockNames[];
|
||||||
hidden extern const struct MagnumStr kErrnoDocs[];
|
hidden extern const struct MagnumStr kErrnoDocs[];
|
||||||
hidden extern const struct MagnumStr kErrnoNames[];
|
hidden extern const struct MagnumStr kErrnoNames[];
|
||||||
|
hidden extern const struct MagnumStr kFcntlCmds[];
|
||||||
hidden extern const struct MagnumStr kIpOptnames[];
|
hidden extern const struct MagnumStr kIpOptnames[];
|
||||||
hidden extern const struct MagnumStr kOpenFlags[];
|
hidden extern const struct MagnumStr kOpenFlags[];
|
||||||
hidden extern const struct MagnumStr kRlimitNames[];
|
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 *DescribeCapability(char[20], int);
|
||||||
const char *DescribeClockName(char[32], int);
|
const char *DescribeClockName(char[32], int);
|
||||||
const char *DescribeDirfd(char[12], int);
|
const char *DescribeDirfd(char[12], int);
|
||||||
|
const char *DescribeDnotifyFlags(char[80], int);
|
||||||
const char *DescribeErrno(char[12], int);
|
const char *DescribeErrno(char[12], int);
|
||||||
const char *DescribeErrnoResult(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 *DescribeFrame(char[32], int);
|
||||||
const char *DescribeFutexOp(char[64], int);
|
const char *DescribeFutexOp(char[64], int);
|
||||||
const char *DescribeHow(char[12], 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 DescribeDirfd(x) DescribeDirfd(alloca(12), x)
|
||||||
#define DescribeErrno(x) DescribeErrno(alloca(12), x)
|
#define DescribeErrno(x) DescribeErrno(alloca(12), x)
|
||||||
#define DescribeErrnoResult(x) DescribeErrnoResult(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 DescribeFrame(x) DescribeFrame(alloca(32), x)
|
||||||
#define DescribeFutexOp(x) DescribeFutexOp(alloca(64), x)
|
#define DescribeFutexOp(x) DescribeFutexOp(alloca(64), x)
|
||||||
#define DescribeHow(x) DescribeHow(alloca(12), 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 DescribeStdioState(x) DescribeStdioState(alloca(12), x)
|
||||||
#define DescribeWhence(x) DescribeWhence(alloca(12), x)
|
#define DescribeWhence(x) DescribeWhence(alloca(12), x)
|
||||||
#define DescribeWhichPrio(x) DescribeWhichPrio(alloca(12), x)
|
#define DescribeWhichPrio(x) DescribeWhichPrio(alloca(12), x)
|
||||||
|
#define DescribeDnotifyFlags(x) DescribeDnotifyFlags(alloca(80), x)
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#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;
|
char *s;
|
||||||
int i, n;
|
int i, n;
|
||||||
struct DescribeFlags d[N];
|
struct DescribeFlags d[N];
|
||||||
|
if (x == -1) return "-1";
|
||||||
// TODO(jart): unify DescribeFlags and MagnumStr data structures
|
// TODO(jart): unify DescribeFlags and MagnumStr data structures
|
||||||
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) {
|
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) {
|
||||||
if (n == N) notpossible;
|
if (n == N) notpossible;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/state.internal.h"
|
#include "libc/calls/state.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
int gettid(void) {
|
int gettid(void) {
|
||||||
int tid;
|
int tid;
|
||||||
if (__tls_enabled && !__vforked) {
|
if (__tls_enabled && !__vforked) {
|
||||||
tid = __get_tls()->tib_tid;
|
tid = atomic_load_explicit(&__get_tls()->tib_tid, memory_order_relaxed);
|
||||||
if (tid > 0) {
|
if (tid > 0) {
|
||||||
return tid;
|
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/fmt/fmt.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/asancodes.h"
|
#include "libc/intrin/asancodes.h"
|
||||||
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/intrin/cmpxchg.h"
|
#include "libc/intrin/cmpxchg.h"
|
||||||
#include "libc/intrin/kprintf.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) {
|
if (!__tls_enabled) {
|
||||||
x = __pid;
|
x = __pid;
|
||||||
} else {
|
} else {
|
||||||
x = __get_tls_privileged()->tib_tid;
|
x = atomic_load_explicit(&__get_tls_privileged()->tib_tid,
|
||||||
|
memory_order_relaxed);
|
||||||
}
|
}
|
||||||
if (!__nocolor && p + 7 <= e) {
|
if (!__nocolor && p + 7 <= e) {
|
||||||
*p++ = '\e';
|
*p++ = '\e';
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/describentoverlapped.internal.h"
|
#include "libc/intrin/describentoverlapped.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
#include "libc/nt/enum/filelockflags.h"
|
||||||
#include "libc/nt/files.h"
|
#include "libc/nt/files.h"
|
||||||
|
|
||||||
__msabi extern typeof(LockFileEx) *const __imp_LockFileEx;
|
__msabi extern typeof(LockFileEx) *const __imp_LockFileEx;
|
||||||
|
@ -35,16 +36,18 @@ bool32 LockFileEx(int64_t hFile, uint32_t dwFlags, uint32_t dwReserved,
|
||||||
uint32_t nNumberOfBytesToLockHigh,
|
uint32_t nNumberOfBytesToLockHigh,
|
||||||
struct NtOverlapped *lpOverlapped) {
|
struct NtOverlapped *lpOverlapped) {
|
||||||
bool32 ok;
|
bool32 ok;
|
||||||
STRACE("LockFileEx(%ld, %s, %#x, %'zu, %s) → ...", hFile,
|
if (~dwFlags & kNtLockfileFailImmediately) {
|
||||||
DescribeNtLockFileFlags(dwFlags), dwReserved,
|
NTTRACE("LockFileEx(%ld, %s, %#x, %'zu, %s) → ...", hFile,
|
||||||
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
|
DescribeNtLockFileFlags(dwFlags), dwReserved,
|
||||||
DescribeNtOverlapped(lpOverlapped));
|
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
|
||||||
|
DescribeNtOverlapped(lpOverlapped));
|
||||||
|
}
|
||||||
ok = __imp_LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow,
|
ok = __imp_LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow,
|
||||||
nNumberOfBytesToLockHigh, lpOverlapped);
|
nNumberOfBytesToLockHigh, lpOverlapped);
|
||||||
if (!ok) __winerr();
|
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,
|
DescribeNtLockFileFlags(dwFlags), dwReserved,
|
||||||
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
|
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
|
||||||
DescribeNtOverlapped(lpOverlapped), ok);
|
DescribeNtOverlapped(lpOverlapped), ok);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,14 +37,12 @@ bool32 UnlockFileEx(int64_t hFile, uint32_t dwReserved,
|
||||||
uint32_t nNumberOfBytesToUnlockHigh,
|
uint32_t nNumberOfBytesToUnlockHigh,
|
||||||
struct NtOverlapped *lpOverlapped) {
|
struct NtOverlapped *lpOverlapped) {
|
||||||
bool32 ok;
|
bool32 ok;
|
||||||
STRACE("UnlockFileEx(%ld, %#x, %'zu, %s) → ...", hFile, dwReserved,
|
|
||||||
(uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow,
|
|
||||||
DescribeNtOverlapped(lpOverlapped));
|
|
||||||
ok = __imp_UnlockFileEx(hFile, dwReserved, nNumberOfBytesToUnlockLow,
|
ok = __imp_UnlockFileEx(hFile, dwReserved, nNumberOfBytesToUnlockLow,
|
||||||
nNumberOfBytesToUnlockHigh, lpOverlapped);
|
nNumberOfBytesToUnlockHigh, lpOverlapped);
|
||||||
if (!ok) __winerr();
|
if (!ok) __winerr();
|
||||||
STRACE("UnlockFileEx(%ld, %#x, %'zu, [%s]) → %hhhd% m", hFile, dwReserved,
|
NTTRACE(
|
||||||
(uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow,
|
"UnlockFileEx(%ld, %#x, %'zu, [%s]) → %hhhd% m", hFile, dwReserved,
|
||||||
DescribeNtOverlapped(lpOverlapped), ok);
|
(uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow,
|
||||||
|
DescribeNtOverlapped(lpOverlapped), ok);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_ISYSTEM_SYS_FCNTL_H_
|
#define COSMOPOLITAN_LIBC_ISYSTEM_SYS_FCNTL_H_
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
|
#include "libc/sysv/consts/dn.h"
|
||||||
#include "libc/sysv/consts/f.h"
|
#include "libc/sysv/consts/f.h"
|
||||||
|
#include "third_party/musl/lockf.h"
|
||||||
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_FCNTL_H_ */
|
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_FCNTL_H_ */
|
||||||
|
|
|
@ -12,4 +12,5 @@
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "third_party/getopt/getopt.h"
|
#include "third_party/getopt/getopt.h"
|
||||||
#include "third_party/musl/crypt.h"
|
#include "third_party/musl/crypt.h"
|
||||||
|
#include "third_party/musl/lockf.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/utsname.h"
|
#include "libc/calls/struct/utsname.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
@ -229,7 +230,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
||||||
ShowFunctionCalls(ctx);
|
ShowFunctionCalls(ctx);
|
||||||
}
|
}
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
__print_maps();
|
if (!IsWindows()) __print_maps();
|
||||||
/* PrintSystemMappings(2); */
|
/* PrintSystemMappings(2); */
|
||||||
if (__argv) {
|
if (__argv) {
|
||||||
for (i = 0; i < __argc; ++i) {
|
for (i = 0; i < __argc; ++i) {
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
#define kNtErrorSemIsSet 102
|
#define kNtErrorSemIsSet 102
|
||||||
#define kNtErrorTooManySemRequests 103
|
#define kNtErrorTooManySemRequests 103
|
||||||
#define kNtErrorInvalidAtInterruptTime 104
|
#define kNtErrorInvalidAtInterruptTime 104
|
||||||
#define kNtErrorSemOwnerDied 105
|
#define kNtErrorSemOwnerDied 105 /* EOWNERDEAD */
|
||||||
#define kNtErrorSemUserLimit 106
|
#define kNtErrorSemUserLimit 106
|
||||||
#define kNtErrorDiskChange 107
|
#define kNtErrorDiskChange 107
|
||||||
#define kNtErrorDriveLocked 108
|
#define kNtErrorDriveLocked 108
|
||||||
|
@ -336,7 +336,7 @@
|
||||||
#define kNtErrorVrfCfgEnabled 1183
|
#define kNtErrorVrfCfgEnabled 1183
|
||||||
#define kNtErrorPartitionTerminating 1184
|
#define kNtErrorPartitionTerminating 1184
|
||||||
#define kNtErrorUserProfileLoad 500
|
#define kNtErrorUserProfileLoad 500
|
||||||
#define kNtErrorArithmeticOverflow 534
|
#define kNtErrorArithmeticOverflow 534 /* EOVERFLOW */
|
||||||
#define kNtErrorPipeConnected 535
|
#define kNtErrorPipeConnected 535
|
||||||
#define kNtErrorPipeListening 536
|
#define kNtErrorPipeListening 536
|
||||||
#define kNtErrorVerifierStop 537
|
#define kNtErrorVerifierStop 537
|
||||||
|
@ -383,7 +383,7 @@
|
||||||
#define kNtErrorIllegalFloatContext 579
|
#define kNtErrorIllegalFloatContext 579
|
||||||
#define kNtErrorNoEventPair 580
|
#define kNtErrorNoEventPair 580
|
||||||
#define kNtErrorDomainCtrlrConfigError 581
|
#define kNtErrorDomainCtrlrConfigError 581
|
||||||
#define kNtErrorIllegalCharacter 582
|
#define kNtErrorIllegalCharacter 582 /* EILSEQ */
|
||||||
#define kNtErrorUndefinedCharacter 583
|
#define kNtErrorUndefinedCharacter 583
|
||||||
#define kNtErrorFloppyVolume 584
|
#define kNtErrorFloppyVolume 584
|
||||||
#define kNtErrorBiosFailedToConnectInterrupt 585
|
#define kNtErrorBiosFailedToConnectInterrupt 585
|
||||||
|
@ -761,7 +761,7 @@
|
||||||
#define kNtErrorRemoteSessionLimitExceeded 1220
|
#define kNtErrorRemoteSessionLimitExceeded 1220
|
||||||
#define kNtErrorDupDomainname 1221
|
#define kNtErrorDupDomainname 1221
|
||||||
#define kNtErrorNoNetwork 1222
|
#define kNtErrorNoNetwork 1222
|
||||||
#define kNtErrorCancelled 1223
|
#define kNtErrorCancelled 1223 /* ECANCELED */
|
||||||
#define kNtErrorUserMappedFile 1224
|
#define kNtErrorUserMappedFile 1224
|
||||||
#define kNtErrorConnectionRefused 1225
|
#define kNtErrorConnectionRefused 1225
|
||||||
#define kNtErrorGracefulDisconnect 1226
|
#define kNtErrorGracefulDisconnect 1226
|
||||||
|
@ -1217,7 +1217,7 @@
|
||||||
#define kNtErrorDriveMediaMismatch 4303
|
#define kNtErrorDriveMediaMismatch 4303
|
||||||
#define kNtErrorMediaOffline 4304
|
#define kNtErrorMediaOffline 4304
|
||||||
#define kNtErrorLibraryOffline 4305
|
#define kNtErrorLibraryOffline 4305
|
||||||
#define kNtErrorEmpty 4306
|
#define kNtErrorEmpty 4306 /* ENOMSG */
|
||||||
#define kNtErrorNotEmpty 4307
|
#define kNtErrorNotEmpty 4307
|
||||||
#define kNtErrorMediaUnavailable 4308
|
#define kNtErrorMediaUnavailable 4308
|
||||||
#define kNtErrorResourceDisabled 4309
|
#define kNtErrorResourceDisabled 4309
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "libc/thread/openbsd.internal.h"
|
#include "libc/thread/openbsd.internal.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
|
#include "libc/thread/tls2.h"
|
||||||
#include "libc/thread/xnu.internal.h"
|
#include "libc/thread/xnu.internal.h"
|
||||||
|
|
||||||
#define __NR_thr_new 455
|
#define __NR_thr_new 455
|
||||||
|
@ -97,11 +98,7 @@ WinThreadEntry(int rdi, // rcx
|
||||||
int rdx, // r8
|
int rdx, // r8
|
||||||
struct CloneArgs *wt) { // r9
|
struct CloneArgs *wt) { // r9
|
||||||
int rc;
|
int rc;
|
||||||
if (wt->tls) {
|
if (wt->tls) __set_tls_win32(wt->tls);
|
||||||
asm("mov\t%1,%%gs:%0"
|
|
||||||
: "=m"(*((long *)0x1480 + __tls_index))
|
|
||||||
: "r"(wt->tls));
|
|
||||||
}
|
|
||||||
*wt->ptid = wt->tid;
|
*wt->ptid = wt->tid;
|
||||||
*wt->ctid = wt->tid;
|
*wt->ctid = wt->tid;
|
||||||
rc = WinThreadLaunch(wt->arg, wt->tid, wt->func, (intptr_t)wt & -16);
|
rc = WinThreadLaunch(wt->arg, wt->tid, wt->func, (intptr_t)wt & -16);
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
#define STATE_QUOTED_VAR 4
|
#define STATE_QUOTED_VAR 4
|
||||||
#define STATE_WHITESPACE 5
|
#define STATE_WHITESPACE 5
|
||||||
|
|
||||||
#define READ24LE(s) READ32LE(s "\0")
|
#define READ24(s) READ32LE(s "\0")
|
||||||
|
|
||||||
struct Env {
|
struct Env {
|
||||||
char *s;
|
char *s;
|
||||||
|
@ -333,16 +333,16 @@ static int Test(void) {
|
||||||
if (n == 4) {
|
if (n == 4) {
|
||||||
w = READ32LE(args[2]) & 0x00ffffff;
|
w = READ32LE(args[2]) & 0x00ffffff;
|
||||||
if ((w & 65535) == READ16LE("=")) return !!strcmp(args[1], args[3]);
|
if ((w & 65535) == READ16LE("=")) 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 == READ24LE("!=")) return !strcmp(args[1], args[3]);
|
if (w == READ24("!=")) return !strcmp(args[1], args[3]);
|
||||||
} else if (n == 3) {
|
} else if (n == 3) {
|
||||||
w = READ32LE(args[1]) & 0x00ffffff;
|
w = READ32LE(args[1]) & 0x00ffffff;
|
||||||
if (w == READ24LE("-n")) return !(strlen(args[2]) > 0);
|
if (w == READ24("-n")) return !(strlen(args[2]) > 0);
|
||||||
if (w == READ24LE("-z")) return !(strlen(args[2]) == 0);
|
if (w == READ24("-z")) return !(strlen(args[2]) == 0);
|
||||||
if (w == READ24LE("-e")) return !!stat(args[2], &st);
|
if (w == READ24("-e")) return !!stat(args[2], &st);
|
||||||
if (w == READ24LE("-f")) return !stat(args[2], &st) && S_ISREG(st.st_mode);
|
if (w == READ24("-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 == READ24("-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("-h")) return !(!stat(args[2], &st) && S_ISLNK(st.st_mode));
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,15 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/thread/tls.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
extern int __threadcalls_end[];
|
extern int __threadcalls_end[];
|
||||||
extern int __threadcalls_start[];
|
extern int __threadcalls_start[];
|
||||||
#pragma weak __threadcalls_start
|
#pragma weak __threadcalls_start
|
||||||
#pragma weak __threadcalls_end
|
#pragma weak __threadcalls_end
|
||||||
|
|
||||||
privileged void __enable_threads(void) {
|
static privileged dontinline void FixupLocks(void) {
|
||||||
if (__threaded) return;
|
|
||||||
STRACE("__enable_threads()");
|
|
||||||
__morph_begin();
|
__morph_begin();
|
||||||
/*
|
/*
|
||||||
* _NOPL("__threadcalls", func)
|
* _NOPL("__threadcalls", func)
|
||||||
|
@ -55,5 +53,11 @@ privileged void __enable_threads(void) {
|
||||||
_base[*p + 2] = 0xe8;
|
_base[*p + 2] = 0xe8;
|
||||||
}
|
}
|
||||||
__morph_end();
|
__morph_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __enable_threads(void) {
|
||||||
|
if (__threaded) return;
|
||||||
|
STRACE("__enable_threads()");
|
||||||
|
FixupLocks();
|
||||||
__threaded = gettid();
|
__threaded = gettid();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/asancodes.h"
|
#include "libc/intrin/asancodes.h"
|
||||||
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
#include "libc/log/libfatal.internal.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.
|
* and your `errno` variable also won't be thread safe anymore.
|
||||||
*/
|
*/
|
||||||
privileged void __enable_tls(void) {
|
privileged void __enable_tls(void) {
|
||||||
|
int tid;
|
||||||
size_t siz;
|
size_t siz;
|
||||||
struct CosmoTib *tib;
|
struct CosmoTib *tib;
|
||||||
char *mem, *tls;
|
char *mem, *tls;
|
||||||
|
@ -133,12 +135,13 @@ privileged void __enable_tls(void) {
|
||||||
if (IsLinux()) {
|
if (IsLinux()) {
|
||||||
// gnu/systemd guarantees pid==tid for the main thread so we can
|
// gnu/systemd guarantees pid==tid for the main thread so we can
|
||||||
// avoid issuing a superfluous system call at startup in program
|
// avoid issuing a superfluous system call at startup in program
|
||||||
tib->tib_tid = __pid;
|
tid = __pid;
|
||||||
} else {
|
} 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.tib = tib;
|
||||||
_pthread_main.tid = tib->tib_tid;
|
_pthread_main.tid = tid;
|
||||||
_pthread_main.flags = PT_MAINTHREAD;
|
_pthread_main.flags = PT_MAINTHREAD;
|
||||||
__repmovsb(tls, _tdata_start, _TLDZ);
|
__repmovsb(tls, _tdata_start, _TLDZ);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/process.h"
|
#include "libc/nt/process.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
|
@ -56,7 +57,9 @@ int _fork(uint32_t dwCreationFlags) {
|
||||||
parent = __pid;
|
parent = __pid;
|
||||||
__pid = dx;
|
__pid = dx;
|
||||||
if (__tls_enabled) {
|
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);
|
if (!IsWindows()) sys_sigprocmask(SIG_SETMASK, &old, 0);
|
||||||
STRACE("fork() → 0 (child of %d)", parent);
|
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 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 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 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 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 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 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 0 # returned by fgetwc(3), fputwc(3), getwchar(3), putwchar(3), scanf(3), ungetwc(3)
|
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 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 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)
|
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 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 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 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 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 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)
|
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 EBADMACHO 0 88 0 0 0 0 #
|
||||||
syscon errno ENOPOLICY 0 103 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 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 ECANCELED 125 89 85 88 87 1223 # kNtErrorCancelled; 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 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 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 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()
|
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_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_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_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_SETOWN 8 6 6 6 6 -1 # bsd consensus
|
||||||
syscon fcntl2 F_GETOWN 9 5 5 5 5 0 # bsd consensus
|
syscon fcntl2 F_GETOWN 9 5 5 5 5 -1 # bsd consensus
|
||||||
syscon fcntl2 F_FULLFSYNC 0 51 0 0 0 0 #
|
syscon fcntl2 F_FULLFSYNC -1 51 -1 -1 -1 -1 #
|
||||||
syscon fcntl2 F_NOCACHE 0 48 0 0 0 0 #
|
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 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_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 F_MAXFD -1 -1 -1 -1 11 -1 #
|
||||||
syscon fcntl FREAD 0 1 1 1 1 0 #
|
syscon fcntl F_NOTIFY 0x0402 -1 -1 -1 -1 -1
|
||||||
syscon fcntl FWRITE 0 2 2 2 2 0 #
|
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_NONBLOCK
|
||||||
# fcntl3 O_APPEND
|
# 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
|
# 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 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 # 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_GETLK 5 7 11 7 7 5 # 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_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_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 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_SETSIG 10 -1 -1 -1 -1 -1
|
||||||
syscon fcntl F_LOCK 1 1 1 1 1 0 # unix consensus
|
syscon fcntl F_GETSIG 11 -1 -1 -1 -1 -1
|
||||||
syscon fcntl F_TLOCK 2 2 2 2 2 0 # unix consensus
|
syscon fcntl F_SETOWN_EX 15 -1 -1 -1 -1 -1
|
||||||
syscon fcntl F_TEST 3 3 3 3 3 0 # unix consensus
|
syscon fcntl F_GETOWN_EX 0x10 -1 -1 -1 -1 -1
|
||||||
syscon fcntl F_SETSIG 10 0 0 0 0 0
|
syscon fcntl F_SETLEASE 0x0400 -1 -1 -1 -1 -1
|
||||||
syscon fcntl F_GETSIG 11 0 0 0 0 0
|
syscon fcntl F_GETLEASE 0x0401 -1 -1 -1 -1 -1
|
||||||
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 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 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
|
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_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 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_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_KEEPIDLE 4 0 0x100 0 3 0 # start keepalives after this period
|
||||||
syscon tcp TCP_KEEPINTVL 5 0x101 0x200 0 5 0 # keepalives
|
syscon tcp TCP_KEEPINTVL 5 0x101 0x200 0 5 0 # interval between keepalives
|
||||||
syscon tcp TCP_KEEPCNT 6 0x102 0x400 0 6 0 # 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_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_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
|
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_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_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_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_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_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
|
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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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"
|
.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)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
extern const int F_BARRIERFSYNC;
|
||||||
extern const int F_DUPFD;
|
extern const int F_DUPFD;
|
||||||
extern const int F_DUPFD_CLOEXEC;
|
extern const int F_DUPFD_CLOEXEC;
|
||||||
extern const int F_FULLFSYNC;
|
extern const int F_FULLFSYNC;
|
||||||
|
@ -12,11 +13,14 @@ extern const int F_GETFL;
|
||||||
extern const int F_GETLEASE;
|
extern const int F_GETLEASE;
|
||||||
extern const int F_GETLK64;
|
extern const int F_GETLK64;
|
||||||
extern const int F_GETLK;
|
extern const int F_GETLK;
|
||||||
|
extern const int F_GETNOSIGPIPE;
|
||||||
extern const int F_GETOWN;
|
extern const int F_GETOWN;
|
||||||
extern const int F_GETOWN_EX;
|
extern const int F_GETOWN_EX;
|
||||||
|
extern const int F_GETPATH;
|
||||||
extern const int F_GETPIPE_SZ;
|
extern const int F_GETPIPE_SZ;
|
||||||
extern const int F_GETSIG;
|
extern const int F_GETSIG;
|
||||||
extern const int F_LOCK;
|
extern const int F_LOCK;
|
||||||
|
extern const int F_MAXFD;
|
||||||
extern const int F_NOCACHE;
|
extern const int F_NOCACHE;
|
||||||
extern const int F_NOTIFY;
|
extern const int F_NOTIFY;
|
||||||
extern const int F_OFD_GETLK;
|
extern const int F_OFD_GETLK;
|
||||||
|
@ -30,13 +34,11 @@ extern const int F_SETLK64;
|
||||||
extern const int F_SETLK;
|
extern const int F_SETLK;
|
||||||
extern const int F_SETLKW64;
|
extern const int F_SETLKW64;
|
||||||
extern const int F_SETLKW;
|
extern const int F_SETLKW;
|
||||||
|
extern const int F_SETNOSIGPIPE;
|
||||||
extern const int F_SETOWN;
|
extern const int F_SETOWN;
|
||||||
extern const int F_SETOWN_EX;
|
extern const int F_SETOWN_EX;
|
||||||
extern const int F_SETPIPE_SZ;
|
extern const int F_SETPIPE_SZ;
|
||||||
extern const int F_SETSIG;
|
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_UNLCK;
|
||||||
extern const int F_WRLCK;
|
extern const int F_WRLCK;
|
||||||
|
|
||||||
|
@ -50,20 +52,17 @@ COSMOPOLITAN_C_END_
|
||||||
#define F_SETFL LITERALLY(4)
|
#define F_SETFL LITERALLY(4)
|
||||||
|
|
||||||
#define F_DUPFD_CLOEXEC SYMBOLIC(F_DUPFD_CLOEXEC)
|
#define F_DUPFD_CLOEXEC SYMBOLIC(F_DUPFD_CLOEXEC)
|
||||||
#define F_FULLFSYNC SYMBOLIC(F_FULLFSYNC)
|
|
||||||
#define F_GETLEASE SYMBOLIC(F_GETLEASE)
|
#define F_GETLEASE SYMBOLIC(F_GETLEASE)
|
||||||
#define F_GETLK SYMBOLIC(F_GETLK)
|
#define F_GETLK SYMBOLIC(F_GETLK)
|
||||||
#define F_GETLK64 SYMBOLIC(F_GETLK64)
|
#define F_GETLK64 SYMBOLIC(F_GETLK64)
|
||||||
#define F_GETOWN SYMBOLIC(F_GETOWN)
|
#define F_GETOWN SYMBOLIC(F_GETOWN)
|
||||||
#define F_GETOWN_EX SYMBOLIC(F_GETOWN_EX)
|
#define F_GETOWN_EX SYMBOLIC(F_GETOWN_EX)
|
||||||
|
#define F_GETPATH SYMBOLIC(F_GETPATH)
|
||||||
#define F_GETPIPE_SZ SYMBOLIC(F_GETPIPE_SZ)
|
#define F_GETPIPE_SZ SYMBOLIC(F_GETPIPE_SZ)
|
||||||
#define F_GETSIG SYMBOLIC(F_GETSIG)
|
#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_NOCACHE SYMBOLIC(F_NOCACHE)
|
||||||
#define F_NOTIFY SYMBOLIC(F_NOTIFY)
|
#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_RDLCK SYMBOLIC(F_RDLCK)
|
||||||
#define F_SETLEASE SYMBOLIC(F_SETLEASE)
|
#define F_SETLEASE SYMBOLIC(F_SETLEASE)
|
||||||
#define F_SETLK SYMBOLIC(F_SETLK)
|
#define F_SETLK SYMBOLIC(F_SETLK)
|
||||||
|
@ -74,10 +73,16 @@ COSMOPOLITAN_C_END_
|
||||||
#define F_SETOWN_EX SYMBOLIC(F_SETOWN_EX)
|
#define F_SETOWN_EX SYMBOLIC(F_SETOWN_EX)
|
||||||
#define F_SETPIPE_SZ SYMBOLIC(F_SETPIPE_SZ)
|
#define F_SETPIPE_SZ SYMBOLIC(F_SETPIPE_SZ)
|
||||||
#define F_SETSIG SYMBOLIC(F_SETSIG)
|
#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_UNLCK SYMBOLIC(F_UNLCK)
|
||||||
#define F_WRLCK SYMBOLIC(F_WRLCK)
|
#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_ */
|
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_F_H_ */
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/asancodes.h"
|
#include "libc/intrin/asancodes.h"
|
||||||
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
|
@ -57,7 +58,8 @@ char *_mktls(struct CosmoTib **out_tib) {
|
||||||
tib = (struct CosmoTib *)(tls + I(_tls_size));
|
tib = (struct CosmoTib *)(tls + I(_tls_size));
|
||||||
tib->tib_self = tib;
|
tib->tib_self = tib;
|
||||||
tib->tib_self2 = 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) {
|
if (out_tib) {
|
||||||
*out_tib = tib;
|
*out_tib = tib;
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct CosmoTib {
|
||||||
int32_t tib_errno; /* 0x3c */
|
int32_t tib_errno; /* 0x3c */
|
||||||
void *tib_nsync;
|
void *tib_nsync;
|
||||||
uint64_t tib_flags;
|
uint64_t tib_flags;
|
||||||
void *tib_reserved2;
|
uint64_t tib_sigmask;
|
||||||
void *tib_reserved3;
|
void *tib_reserved3;
|
||||||
void *tib_reserved4;
|
void *tib_reserved4;
|
||||||
void *tib_reserved5;
|
void *tib_reserved5;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__STRICT_ANSI__)
|
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__STRICT_ANSI__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns location of thread information block.
|
* Returns location of thread information block.
|
||||||
*
|
*
|
||||||
|
@ -24,8 +24,19 @@ static noasan inline struct CosmoTib *__get_tls_privileged(void) {
|
||||||
}
|
}
|
||||||
return (struct CosmoTib *)tib;
|
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_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_THREAD_TLS2_H_ */
|
#endif /* COSMOPOLITAN_LIBC_THREAD_TLS2_H_ */
|
||||||
|
|
|
@ -19,62 +19,64 @@
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
#include "net/http/tokenbucket.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.
|
* Atomically increments all signed bytes in array without overflow.
|
||||||
*
|
*
|
||||||
* This function should be called periodically so buckets have tokens.
|
* Under the token bucket model, operations are denied by default unless
|
||||||
* While many threads can consumes tokens, only a single thread can use
|
* tokens exist to allow them. This function must be called periodically
|
||||||
* the replenish operation.
|
* from a single background thread to replenish the buckets with tokens.
|
||||||
*
|
* For example, this function may be called once per second which allows
|
||||||
* This function implements a SWAR algorithm offering the best possible
|
* one operation per second on average with bursts up to 127 per second.
|
||||||
* performance under the constraint that operations happen atomically.
|
* This policy needn't be applied uniformly. For example, you might find
|
||||||
* This function should take 2ms to add a token to 2**22 buckets which
|
* out that a large corporation funnels all their traffic through one ip
|
||||||
* need a 4mb array that has one bucket for every 1024 IPv4 addresses.
|
* address, so you could replenish their tokens multiple times a second.
|
||||||
* However that doesn't matter since no locks are held during that 2ms
|
|
||||||
* therefore replenishing doesn't block threads that acquire tokens.
|
|
||||||
*
|
*
|
||||||
* @param w is word array that aliases byte token array
|
* @param w is word array that aliases byte token array
|
||||||
* @param n is number of 64-bit words in `w` array
|
* @param n is number of 64-bit words in `w` array
|
||||||
*/
|
*/
|
||||||
void ReplenishTokens(atomic_uint_fast64_t *w, size_t n) {
|
void ReplenishTokens(atomic_uint_fast64_t *w, size_t n) {
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
uint64_t x = atomic_load_explicit(w + i, memory_order_relaxed);
|
uint64_t a = atomic_load_explicit(w + i, memory_order_relaxed);
|
||||||
atomic_fetch_add_explicit(
|
if (a == 0x7f7f7f7f7f7f7f7f) continue;
|
||||||
w + i, 0x0101010101010101 & ~CompareEq(x, 0x7f7f7f7f7f7f7f7f),
|
uint64_t b = 0x8080808080808080;
|
||||||
memory_order_acq_rel);
|
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.
|
* Atomically decrements signed byte index if it's positive.
|
||||||
*
|
*
|
||||||
* This function should be called to take a token from the right bucket
|
* Multiple threads may call this method to determine if sufficient
|
||||||
* whenever a client wants to use some type of resource. This routine
|
* tokens exist to perform an operation. Return values greater than zero
|
||||||
* discriminates based on `c` which is the netmask bit count. There must
|
* mean a token was atomically acquired. Values less than or equal zero
|
||||||
* exist `1 << c` signed bytes (or buckets) in the `b` array.
|
* 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
|
* Since this design uses signed bytes, the returned number may be used
|
||||||
* positive number. This function returns true of a token was atomically
|
* to control how much burstiness is allowed. For example:
|
||||||
* acquired using a lockeless spinless algorithm. Buckets are allowed to
|
*
|
||||||
* drift into a slightly negative state, but overflow is impractical.
|
* 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 w is array of token buckets
|
||||||
* @param n is ipv4 address
|
* @param n is ipv4 address
|
||||||
* @param c is cidr
|
* @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);
|
uint32_t i = x >> (32 - c);
|
||||||
return atomic_load_explicit(b + i, memory_order_relaxed) > 0 &&
|
int t = atomic_load_explicit(b + i, memory_order_relaxed);
|
||||||
atomic_fetch_add_explicit(b + i, -1, memory_order_acq_rel) > 0;
|
if (t <= 0) return t;
|
||||||
|
return atomic_fetch_add_explicit(b + i, -1, memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
void ReplenishTokens(atomic_uint_fast64_t *, size_t);
|
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);
|
int CountTokens(atomic_schar *, uint32_t, int);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
|
|
|
@ -729,7 +729,9 @@ void ServeStatusz(int client, char *outbuf) {
|
||||||
|
|
||||||
void *ListenWorker(void *arg) {
|
void *ListenWorker(void *arg) {
|
||||||
int server;
|
int server;
|
||||||
|
int no = 0;
|
||||||
int yes = 1;
|
int yes = 1;
|
||||||
|
int fastopen = 5;
|
||||||
struct Client client;
|
struct Client client;
|
||||||
struct timeval timeo = {g_keepalive / 1000, g_keepalive % 1000};
|
struct timeval timeo = {g_keepalive / 1000, g_keepalive % 1000};
|
||||||
struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(g_port)};
|
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_RCVTIMEO, &timeo, sizeof(timeo));
|
||||||
setsockopt(server, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo));
|
setsockopt(server, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo));
|
||||||
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
|
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
|
||||||
setsockopt(server, SOL_TCP, TCP_FASTOPEN, &yes, sizeof(yes));
|
setsockopt(server, SOL_TCP, TCP_FASTOPEN, &fastopen, sizeof(fastopen));
|
||||||
setsockopt(server, SOL_TCP, TCP_QUICKACK, &yes, sizeof(yes));
|
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));
|
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));
|
CHECK_NE(-1, listen(server, 1));
|
||||||
while (!nsync_note_is_notified(g_shutdown[0])) {
|
while (!nsync_note_is_notified(g_shutdown[0])) {
|
||||||
client.size = sizeof(client.addr);
|
client.size = sizeof(client.addr);
|
||||||
|
@ -791,7 +794,7 @@ void *HttpWorker(void *arg) {
|
||||||
struct Url url;
|
struct Url url;
|
||||||
ssize_t got, sent;
|
ssize_t got, sent;
|
||||||
uint32_t ip, clientip;
|
uint32_t ip, clientip;
|
||||||
int inmsglen, outmsglen;
|
int tok, inmsglen, outmsglen;
|
||||||
char ipbuf[32], *p, *q, cashbuf[64];
|
char ipbuf[32], *p, *q, cashbuf[64];
|
||||||
|
|
||||||
clientip = ntohl(client.addr.sin_addr.s_addr);
|
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,
|
ksnprintf(ipbuf, sizeof(ipbuf), "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16,
|
||||||
ip >> 8, ip);
|
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
|
// we don't support http/1.0 and http/0.9 right now
|
||||||
if (msg->version != 11) {
|
if (msg->version != 11) {
|
||||||
LOG("%s used unsupported http/%d version\n", ipbuf, msg->version);
|
LOG("%s used unsupported http/%d version\n", ipbuf, msg->version);
|
||||||
|
@ -873,19 +889,8 @@ void *HttpWorker(void *arg) {
|
||||||
break;
|
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
|
// 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->xmethod.b - msg->xmethod.a, inbuf + msg->xmethod.a,
|
||||||
msg->uri.b - msg->uri.a, inbuf + msg->uri.a,
|
msg->uri.b - msg->uri.a, inbuf + msg->uri.a,
|
||||||
HeaderLength(kHttpCfIpcountry), HeaderData(kHttpCfIpcountry),
|
HeaderLength(kHttpCfIpcountry), HeaderData(kHttpCfIpcountry),
|
||||||
|
@ -1765,7 +1770,12 @@ OnError:
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
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 don't have proper futexes on these platforms
|
||||||
// we'll be somewhat less aggressive about workers
|
// 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, 3, fcntl(2, F_DUPFD_CLOEXEC, 3));
|
||||||
ASSERT_SYS(0, 0, ioctl(0, FIOCLEX, 0));
|
ASSERT_SYS(0, 0, ioctl(0, FIOCLEX, 0));
|
||||||
ASSERT_SYS(EPERM, 0, isatty(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_GETLK, &lk));
|
||||||
ASSERT_SYS(EPERM, -1, fcntl(0, F_NOTIFY));
|
ASSERT_SYS(EPERM, -1, fcntl(0, F_NOTIFY));
|
||||||
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
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/log/check.h"
|
||||||
#include "libc/mem/gc.internal.h"
|
#include "libc/mem/gc.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
@ -147,6 +146,14 @@ TEST(ParseHttpMessage, testHttp09) {
|
||||||
EXPECT_EQ(9, req->version);
|
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) {
|
TEST(ParseHttpMessage, testLeadingLineFeeds_areIgnored) {
|
||||||
static const char m[] = "\
|
static const char m[] = "\
|
||||||
\r\n\
|
\r\n\
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "net/http/http.h"
|
#include "net/http/http.h"
|
||||||
|
@ -47,27 +48,52 @@ void TearDown(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(tokenbucket, test) {
|
TEST(tokenbucket, test) {
|
||||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||||
ReplenishTokens(tok.w, TB_WORDS);
|
ReplenishTokens(tok.w, TB_WORDS);
|
||||||
ReplenishTokens(tok.w, TB_WORDS);
|
ReplenishTokens(tok.w, TB_WORDS);
|
||||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
ASSERT_EQ(2, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||||
ASSERT_TRUE(AcquireToken(tok.b, 0x08080808, 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);
|
ReplenishTokens(tok.w, TB_WORDS);
|
||||||
|
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||||
ReplenishTokens(tok.w, TB_WORDS);
|
ReplenishTokens(tok.w, TB_WORDS);
|
||||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
ASSERT_EQ(3, AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||||
ASSERT_TRUE(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) {
|
BENCH(tokenbucket, bench) {
|
||||||
struct timespec t1, t2;
|
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);
|
clock_gettime(0, &t1);
|
||||||
ReplenishTokens(tok.w, TB_WORDS);
|
ReplenishTokens(tok.w, TB_WORDS);
|
||||||
clock_gettime(0, &t2);
|
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)));
|
_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/calls/weirdtypes.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/sysv/consts/f.h"
|
#include "libc/sysv/consts/f.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
#include "third_party/musl/lockf.h"
|
||||||
|
|
||||||
asm(".ident\t\"\\n\\n\
|
asm(".ident\t\"\\n\\n\
|
||||||
Musl libc (MIT License)\\n\
|
Musl libc (MIT License)\\n\
|
||||||
|
@ -44,25 +46,20 @@ int lockf(int fd, int op, off_t size)
|
||||||
.l_whence = SEEK_CUR,
|
.l_whence = SEEK_CUR,
|
||||||
.l_len = size,
|
.l_len = size,
|
||||||
};
|
};
|
||||||
if (op == F_TEST){
|
switch (op) {
|
||||||
|
case F_TEST:
|
||||||
l.l_type = F_RDLCK;
|
l.l_type = F_RDLCK;
|
||||||
if (fcntl(fd, F_GETLK, &l) < 0)
|
if (fcntl(fd, F_GETLK, &l) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (l.l_type == F_UNLCK || l.l_pid == getpid())
|
if (l.l_type == F_UNLCK || l.l_pid == getpid())
|
||||||
return 0;
|
return 0;
|
||||||
errno = EACCES;
|
return eacces();
|
||||||
return -1;
|
case F_ULOCK:
|
||||||
}
|
|
||||||
if (op == F_ULOCK) {
|
|
||||||
l.l_type = F_UNLCK;
|
l.l_type = F_UNLCK;
|
||||||
|
case F_TLOCK:
|
||||||
return fcntl(fd, F_SETLK, &l);
|
return fcntl(fd, F_SETLK, &l);
|
||||||
}
|
case F_LOCK:
|
||||||
if (op == F_TLOCK) {
|
|
||||||
return fcntl(fd, F_SETLK, &l);
|
|
||||||
}
|
|
||||||
if (op == F_LOCK) {
|
|
||||||
return fcntl(fd, F_SETLKW, &l);
|
return fcntl(fd, F_SETLKW, &l);
|
||||||
}
|
}
|
||||||
errno = EINVAL;
|
return einval();
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
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_ */
|
23
third_party/nsync/futex.c
vendored
23
third_party/nsync/futex.c
vendored
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/atomic.h"
|
#include "libc/atomic.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/calls/state.internal.h"
|
#include "libc/calls/state.internal.h"
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
|
@ -166,15 +167,19 @@ int nsync_futex_wait_ (int *p, int expect, char pshare, struct timespec *timeout
|
||||||
if (pshare) {
|
if (pshare) {
|
||||||
goto Polyfill;
|
goto Polyfill;
|
||||||
}
|
}
|
||||||
if (timeout) {
|
if (_check_interrupts (false, 0)) {
|
||||||
ms = _timespec_tomillis (*timeout);
|
rc = -EINTR;
|
||||||
} else {
|
} else {
|
||||||
ms = -1;
|
if (timeout) {
|
||||||
}
|
ms = _timespec_tomillis (*timeout);
|
||||||
if (WaitOnAddress (p, &expect, sizeof(int), ms)) {
|
} else {
|
||||||
rc = 0;
|
ms = -1;
|
||||||
} else {
|
}
|
||||||
rc = -GetLastError ();
|
if (WaitOnAddress (p, &expect, sizeof(int), ms)) {
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
|
rc = -GetLastError ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (IsFreebsd ()) {
|
} else if (IsFreebsd ()) {
|
||||||
rc = sys_umtx_timedwait_uint (
|
rc = sys_umtx_timedwait_uint (
|
||||||
|
@ -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;
|
__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,
|
p, DescribeFutexOp (op), expect,
|
||||||
DescribeTimespec (0, timeout),
|
DescribeTimespec (0, timeout),
|
||||||
DescribeErrnoResult (rc));
|
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. │
|
│ limitations under the License. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "third_party/nsync/atomic.h"
|
#include "third_party/nsync/atomic.h"
|
||||||
#include "third_party/nsync/atomic.internal.h"
|
#include "third_party/nsync/atomic.internal.h"
|
||||||
#include "third_party/nsync/common.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);
|
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/struct/utimbuf.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
|
#include "third_party/musl/lockf.h"
|
||||||
#include "third_party/musl/passwd.h"
|
#include "third_party/musl/passwd.h"
|
||||||
#include "third_party/python/Include/abstract.h"
|
#include "third_party/python/Include/abstract.h"
|
||||||
#include "third_party/python/Include/boolobject.h"
|
#include "third_party/python/Include/boolobject.h"
|
||||||
|
@ -11894,10 +11895,10 @@ all_ins(PyObject *m)
|
||||||
if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
|
if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
|
||||||
|
|
||||||
/* constants for lockf */
|
/* constants for lockf */
|
||||||
if (F_LOCK && PyModule_AddIntMacro(m, F_LOCK)) return -1;
|
if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
|
||||||
if (F_TLOCK && PyModule_AddIntMacro(m, F_TLOCK)) return -1;
|
if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
|
||||||
if (PyModule_AddIntMacro(m, F_ULOCK)) 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
|
#ifdef HAVE_SPAWNV
|
||||||
if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
|
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 */
|
/* #undef HAVE_LINUX_CAN_RAW_FD_FRAMES */
|
||||||
|
|
||||||
/* Define to 1 if you have the 'lockf' function and the F_LOCK macro. */
|
/* 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_DEVICE_MACROS 1 */
|
||||||
#define HAVE_MAKEDEV 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
|
LICENSE
|
||||||
|
|
||||||
Public Domain or MIT
|
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() */
|
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
|
||||||
int i; /* Loop counter */
|
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
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||||
if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
|
if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
|
||||||
#endif
|
#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/sqlite3.h"
|
||||||
#include "third_party/sqlite3/mutex.internal.h"
|
#include "third_party/sqlite3/mutex.internal.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"
|
#include "third_party/sqlite3/sqliteInt.inc"
|
||||||
#if SQLITE_OS_UNIX /* This file is used on unix only */
|
#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;
|
struct stat buf;
|
||||||
rc = osFstat(fd, &buf);
|
rc = osFstat(fd, &buf);
|
||||||
}
|
}
|
||||||
#elif HAVE_FULLFSYNC
|
#elif HAVE_FULLFSYNC || defined(__COSMOPOLITAN__)
|
||||||
if( fullSync ){
|
/* [jart] use runtime os detection */
|
||||||
|
if( fullSync && F_FULLFSYNC != -1 ){
|
||||||
rc = osFcntl(fd, F_FULLFSYNC, 0);
|
rc = osFcntl(fd, F_FULLFSYNC, 0);
|
||||||
}else{
|
}else{
|
||||||
rc = 1;
|
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
|
** It'd be better to detect fullfsync support once and avoid
|
||||||
** the fcntl call every time sync is called.
|
** 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__)
|
#elif defined(__APPLE__)
|
||||||
/* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
|
/* 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/sysv/consts/rusage.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
#if SQLITE_USER_AUTHENTICATION
|
#if SQLITE_USER_AUTHENTICATION
|
||||||
#include "third_party/sqlite3/sqlite3userauth.inc"
|
#include "third_party/sqlite3/sqlite3userauth.inc"
|
||||||
#endif
|
#endif
|
||||||
|
@ -10573,6 +10574,7 @@ static void process_sqliterc(
|
||||||
p->in = inSaved;
|
p->in = inSaved;
|
||||||
p->lineno = savedLineno;
|
p->lineno = savedLineno;
|
||||||
sqlite3_free(zBuf);
|
sqlite3_free(zBuf);
|
||||||
|
errno = 0; /* [jart] clear error */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue