Compare commits

...
22 Commits
Author SHA1 Message Date
Justine Tunney af2ef0d223 Fix the build 2022-10-14 11:18:40 -07:00
Justine Tunney 8111462789 Add posix semaphores support
There's still some bugs to work out on Windows and OpenBSD.
2022-10-14 09:21:02 -07:00
Justine Tunney f52f65b2e3 Make system() and popen() thread safe 2022-10-13 15:54:05 -07:00
Justine Tunney 997ce29ddc 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
2022-10-13 13:44:41 -07:00
tkchia d38700687a [metal] Allow more fine-grained control over page permissions (#663)
- use PAGE_RSRV bit (originally only for blinkenlights),
  rather than PAGE_V bit, to indicate that a virtual address
  page has been reserved — this should allow a program to
  create & reserve inaccessible "guard pages"
- mark page table entries for non-code pages with PAGE_XD bit,
  which should be supported on (circa) post-2004 x86-64 CPUs
2022-10-12 11:07:11 -07:00
Justine Tunney 0f89140882 Further improve cocmd interpreter 2022-10-12 10:44:54 -07:00
Justine Tunney 0cee831da3 Revamp posix_spawn() implementation 2022-10-12 05:26:58 -07:00
Justine Tunney b41f91c658 Greatly expand system() shell code features
The cosmopolitan command interpreter now has 13 builtin commands,
variable support, support for ; / && / || syntax, asynchronous support,
and plenty of unit tests with bug fixes.

This change fixes a bug in posix_spawn() with null envp arg. strace
logging now uses atomic writes for scatter functions. Breaking change
renaming GetCpuCount() to _getcpucount(). TurfWar is now updated to use
the new token bucket algorithm. WIN32 affinity masks now inherit across
fork() and execve().
2022-10-11 21:30:31 -07:00
Justine Tunney e7329b7cba Implement atomic swar token bucket library 2022-10-11 21:22:04 -07:00
Justine Tunney c19ac8729d Reinvent the classic unix wall command 2022-10-11 21:22:03 -07:00
Connor 9d2f993364 Fix make sandboxing logic for .STRICT mode (#661)
Patch segfaults and handle the `.STRICT = 0` case.
2022-10-11 21:16:03 -07:00
tkchia 31dab8a75d [metal] Fix bug: do not initialize IDT & TSS if unneeded (#654)
libc/intrin/interrupts.S should not be linked in unless
an IDT (or TSS) is explicitly requested somewhere (i.e.
it should probably not be a mandatory module).
2022-10-10 20:54:46 -07:00
tkchiaandtkchia 7a06760e6f Rename LINUX to _HOSTLINUX etc. to reduce clashes (#655)
Co-authored-by: tkchia <[email protected]>
2022-10-10 20:31:25 -07:00
Connor 9209ea63a7 Integrate upstream dash changes into unbourne shell (#656) 2022-10-10 20:29:28 -07:00
Malcolm Seyd 84b9b8ed87 Fix ParseHttpMessage failing to store >2 repeatable headers (#657) 2022-10-10 20:17:17 -07:00
Justine Tunney e557058ac8 Improve cosmo's conformance to libc-test
This change addresses various open source compatibility issues, so that
we pass 313/411 of the tests in https://github.com/jart/libc-test where
earlier today we were passing about 30/411 of them, due to header toil.
Please note that Glibc only passes 341/411 so 313 today is pretty good!

- Make the conformance of libc/isystem/ headers nearly perfect
- Import more of the remaining math library routines from Musl
- Fix inconsistencies with type signatures of calls like umask
- Write tests for getpriority/setpriority which work great now
- conform to `struct sockaddr *` on remaining socket functions
- Import a bunch of uninteresting stdlib functions e.g. rand48
- Introduce readdir_r, scandir, pthread_kill, sigsetjmp, etc..

Follow the instructions in our `tool/scripts/cosmocc` toolchain to run
these tests yourself. You use `make CC=cosmocc` on the test repository
2022-10-10 17:52:41 -07:00
Justine Tunney 467a332e38 Introduce sigtimedwait() and sigwaitinfo()
This change also invents sigcountset() and strsignal_r() and improves
the quality of siginfo_t handling.
2022-10-10 07:39:44 -07:00
Justine Tunney 7ae556463a Rename rand64() to _rand64() 2022-10-10 04:12:06 -07:00
Justine Tunney c424352a0a Disable make sandobxing unless .STRICT=1
This change makes Landlock Make backwards compatible.
2022-10-10 03:49:58 -07:00
Justine Tunney d5910e2673 Fix bugs and make code tinier
- Fixed bug where stdio eof wasn't being sticky
- Fixed bug where fseeko() wasn't clearing eof state
- Removed assert() usage from libc favoring _unassert() / _npassert()
2022-10-09 23:21:34 -07:00
Justine Tunney 9b7c8db846 Perform some code maintenance
- Change IDT code so kprintf() isn't mandatory dependency
- Document current intentions around pthread_cancel()
- Make _npassert() an _unassert() in MODE=tiny
2022-10-09 13:00:46 -07:00
Justine Tunney 4a6fd3d910 Make more improvements to threading support
- fix rare thread exit race condition on openbsd
- pthread_getattr_np() now supplies detached status
- child threads may now pthread_join() the main thread
- introduce sigandset(), sigorset(), and sigisemptyset()
- introduce pthread_cleanup_push() and pthread_cleanup_pop()
2022-10-09 00:08:47 -07:00
637 changed files with 12119 additions and 3624 deletions

No files matched your search

+12 -2
View File
@@ -121,6 +121,7 @@ include third_party/compiler_rt/compiler_rt.mk # │
include libc/str/str.mk # │
include third_party/xed/xed.mk # │
include third_party/zlib/zlib.mk # │
include third_party/double-conversion/dc.mk # │
include libc/elf/elf.mk # │
include ape/ape.mk # │
include libc/fmt/fmt.mk # │
@@ -168,7 +169,7 @@ include test/tool/args/test.mk
include third_party/linenoise/linenoise.mk
include third_party/maxmind/maxmind.mk
include net/finger/finger.mk
include third_party/double-conversion/double-conversion.mk
include third_party/double-conversion/test/test.mk
include third_party/lua/lua.mk
include third_party/sed/sed.mk
include third_party/awk/awk.mk
@@ -309,7 +310,7 @@ COSMOPOLITAN_OBJECTS = \
THIRD_PARTY_GDTOA \
THIRD_PARTY_REGEX \
LIBC_THREAD \
THIRD_PARTY_NSYNC_MALLOC \
THIRD_PARTY_NSYNC_MEM \
LIBC_MEM \
THIRD_PARTY_DLMALLOC \
LIBC_RUNTIME \
@@ -402,6 +403,15 @@ $(SRCS): \
libc/integral/lp64arg.inc \
libc/integral/lp64.inc
.PHONY: toolchain
toolchain: o/cosmopolitan.h \
o/$(MODE)/ape/public/ape.lds \
o/$(MODE)/libc/crt/crt.o \
o/$(MODE)/ape/ape.o \
o/$(MODE)/ape/ape-copy-self.o \
o/$(MODE)/ape/ape-no-modify-self.o \
o/$(MODE)/cosmopolitan.a
# UNSPECIFIED PREREQUISITES TUTORIAL
#
# A build rule must exist for all files that make needs to consider in
+6 -6
View File
@@ -874,7 +874,7 @@ ape_macho:
.long (520f-510f)/4 # count
510: .quad 0 # rax
.quad IMAGE_BASE_VIRTUAL # rbx
.quad XNU # rcx
.quad _HOSTXNU # rcx
.quad 0 # rdx
.quad 0 # rdi
.quad 0 # rsi
@@ -1285,8 +1285,8 @@ lcheck: pushf # check for i8086 / i8088 / i80186
jl 10f
mov %edi,%eax
cpuid
mov $1<<29,%edi # need nexgen32e long mode support
and %edi,%edx
mov $1<<29|1<<20,%edi # need nexgen32e long mode support
and %edi,%edx # & nx support
cmp %edi,%edx
jne 10f
xor %ax,%ax
@@ -1415,7 +1415,7 @@ pinit: push %ds
movl $0x79000+PAGE_V+PAGE_RW,0x7b000-SEG # PD←PDT (+)
movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PD←PDT (-)
mov $512,%cx # PD±2MB
mov $PAGE_V+PAGE_RW,%eax
mov $PAGE_V+PAGE_RSRV+PAGE_RW,%eax
xor %di,%di
0: stosl
add $0x1000,%eax
@@ -1438,7 +1438,7 @@ golong: cli
mov %eax,%cr4
movl $EFER,%ecx
rdmsr
or $EFER_LME|EFER_SCE,%eax
or $EFER_LME|EFER_SCE|EFER_NXE,%eax
wrmsr
lgdt REAL(_gdtrphy)
mov %cr0,%eax
@@ -1555,7 +1555,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
.byte 0x0f,0x1f,0207 # nop rdi binbase
.long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512
#endif
push $METAL # sets __hostos in crt.S
push $_HOSTMETAL # sets __hostos in crt.S
pop %rcx
push $0
mov %rsp,%rbp
-2
View File
@@ -569,8 +569,6 @@ HIDDEN(v_ape_realsectors =
HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512));
HIDDEN(v_ape_highsectors =
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors);
PROVIDE_HIDDEN(_tss = 0);
PROVIDE_HIDDEN(_tss_end = 0);
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
#endif
+2 -2
View File
@@ -175,7 +175,7 @@ macho: .long 0xFEEDFACE+1
510: .quad 0 # rax
.quad 0 # rbx
.quad 0 # rcx
.quad XNU # rdx
.quad _HOSTXNU # rdx
.quad 0 # rdi
.quad 0 # rsi
.quad 0 # rbp
@@ -221,7 +221,7 @@ _start:
jne 0f
cmp $+1,%edx
jne 0f
mov $XNU,%dl
mov $_HOSTXNU,%dl
xor %ecx,%ecx
0: mov %rsp,%rsi
+2 -2
View File
@@ -90,7 +90,7 @@ macho: .long 0xFEEDFACE+1
510: .quad 0 # rax
.quad 0 # rbx
.quad 0 # rcx
.quad XNU # rdx
.quad _HOSTXNU # rdx
.quad 0 # rdi
.quad 0 # rsi
.quad 0 # rbp
@@ -121,7 +121,7 @@ _start:
jne 0f
cmp $+1,%edx
jne 0f
mov $XNU,%dl
mov $_HOSTXNU,%dl
xor %ecx,%ecx
0: mov %rsp,%rsi
+8
View File
@@ -182,6 +182,14 @@
// Task State Segment Descriptor Entries.
.macro .tssdescstub name:req
.ifndef \name
.weak \name
.set \name,0
.endif
.ifndef \name\()_end
.weak \name\()_end
.set \name\()_end,0
.endif
.stub \name\()_desc_ent0,quad
.stub \name\()_desc_ent1,quad
.endm
Binary file not shown.
+1
View File
@@ -73,6 +73,7 @@ EXAMPLES_DIRECTDEPS = \
NET_HTTPS \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LIBCXX \
+1 -8
View File
@@ -9,19 +9,12 @@
#endif
#include "libc/calls/calls.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nt/nt/process.h"
#include "libc/mem/gc.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
dontinline void dostuff(const char *s) {
int i, us;
srand(rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
srand(_rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
for (i = 0; i < 5; ++i) {
us = rand() % 500000;
usleep(us);
+2 -2
View File
@@ -8,8 +8,8 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/intrin/kprintf.h"
#include "libc/runtime/sysconf.h"
#include "libc/runtime/runtime.h"
int main() {
kprintf("%d\n", GetCpuCount());
kprintf("%d\n", _getcpucount());
}
+2 -2
View File
@@ -102,7 +102,7 @@ uint64_t rngset64(void) {
static unsigned i;
static uint64_t s;
if (!i) {
s = rand64();
s = _rand64();
i = (s + 1) & (511);
}
return MarsagliaXorshift64(&s);
@@ -215,7 +215,7 @@ const struct Function {
{"moby", moby}, //
{"mt19937", _mt19937}, //
{"python", pythonx2}, //
{"rand64", rand64}, //
{"rand64", _rand64}, //
{"rdrand", rdrand}, //
{"rdrnd", rdrand}, //
{"rdseed", rdseed}, //
+2 -3
View File
@@ -28,7 +28,6 @@
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/sysconf.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/sockaddr.h"
@@ -137,7 +136,7 @@ void *Worker(void *id) {
setsockopt(server, SOL_TCP, TCP_QUICKACK, &yes, sizeof(yes));
errno = 0;
if (bind(server, &addr, sizeof(addr)) == -1) {
if (bind(server, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
kprintf("%s() failed %m\n", "socket");
goto CloseWorker;
}
@@ -299,7 +298,7 @@ int main(int argc, char *argv[]) {
PORT);
}
threads = argc > 1 ? atoi(argv[1]) : GetCpuCount();
threads = argc > 1 ? atoi(argv[1]) : _getcpucount();
if (!(1 <= threads && threads <= 100000)) {
kprintf("error: invalid number of threads: %d\n", threads);
exit(1);
+436 -357
View File
File diff suppressed because it is too large. Load diff
+148
View File
@@ -0,0 +1,148 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/append.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
#include "libc/time/struct/tm.h"
#include "third_party/getopt/getopt.h"
#include "third_party/musl/passwd.h"
/**
* @fileoverview program for broadcasting message to all terminals, e.g.
*
* o//examples/wall.com hello friends
*
* Will place some bold text into the top left corners of all terminals:
*
* Broadcast message from jart@host (pts/4) (Tue Oct 11 03:52:24 2022):
* hello friends
*
* It's useful for having one terminal tab notify your other ones when
* something like a long running job completes. In the old days back
* when unix systems had multiple users, the wall command provided the
* ultimate lulz especially if it's a setuid binary with root privs.
*/
#define GETOPTS "v"
#define USAGE \
"\
Usage: wall.com [-v] [TEXTMSG] [<TEXTMSG]\n\
-v increase verbosity\n\
Examples:\n\
wall.com 'hello my friends'\n\
echo hello my friends | wall.com\n\
"
int g_verbose;
static void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, GETOPTS)) != -1) {
switch (opt) {
case 'v':
g_verbose++;
break;
case '?':
write(1, USAGE, sizeof(USAGE) - 1);
exit(0);
default:
write(2, USAGE, sizeof(USAGE) - 1);
exit(64);
}
}
}
char *GetHost(void) {
static char host[254];
if (gethostname(host, sizeof(host))) {
strcpy(host, "localhost");
}
return host;
}
char *GetTime(void) {
int64_t t;
struct tm tm;
struct timespec ts;
clock_gettime(0, &ts);
localtime_r(&ts.tv_sec, &tm);
return _chomp(asctime(&tm));
}
int main(int argc, char *argv[]) {
GetOpts(argc, argv);
// create broadcast banner
// we use \e[1m so the text is strong & visually distinct
// we use \e[K so it doesn't get lost in a forest of text
// we map \n → \r\n because teletype might be in raw mode
char *msg = 0;
const char *s;
appends(&msg, "\e7"); // save cursor position
appends(&msg, "\e[H"); // goto top left corne
appends(&msg, "\e[K"); // clear line forward
appends(&msg, "\e[1m"); // bold text
appendf(&msg, "Broadcast message from %s@%s", getpwuid(getuid())->pw_name,
GetHost());
if (isatty(0) && (s = ttyname(0))) appendf(&msg, " (%s)", s);
appendf(&msg, " (%s):\r\n", GetTime());
appends(&msg, "\e[K");
// append broadcast message
if (optind < argc) {
// use cli arguments as message if they exist
for (int i = 0; optind + i < argc; ++i) {
if (i) appends(&msg, " ");
for (s = argv[optind + i]; *s; ++s) {
if (*s == '\n') {
appends(&msg, "\r\n\e[K");
} else {
appendw(&msg, *s & 255);
}
}
}
} else {
// otherwise use stdin as message
ssize_t i, rc;
char buf[512];
while ((rc = read(0, buf, sizeof(buf))) > 0) {
for (i = 0; i < rc; ++i) {
if (buf[i] == '\n') {
appends(&msg, "\r\n\e[K"); // clear line forward
} else {
appendw(&msg, buf[i] & 255);
}
}
}
}
appends(&msg, "\r\n\e[K\e[0m\e8"); // restore
// try to send message to all pseudoteletypewriters
for (int i = 0;; ++i) {
int fd;
char pts[32];
snprintf(pts, sizeof(pts), "/dev/pts/%d", i);
if ((fd = open(pts, O_WRONLY | O_NOCTTY)) == -1) {
if (errno == ENOENT) break;
if (g_verbose) perror(pts);
}
write(fd, msg, appendz(msg).i);
close(fd);
}
return 0;
}
+50 -9
View File
@@ -16,19 +16,60 @@ void __assert_fail(const char *, const char *, int) hidden relegated;
#define static_assert _Static_assert
#endif
#define _unassert(x) \
do { \
if (__builtin_expect(!(x), 0)) { \
unreachable; \
} \
} while (0)
#ifdef __GNUC__
#ifndef TINY
/**
* Specifies expression can't possibly be false.
*
* This macro uses the `notpossible` keyword and is intended for things
* like systems integration, where we know for a fact that something is
* never going to happen, but there's no proof. So we don't want to add
* extra bloat for filenames and line numbers, since `ShowCrashReports`
* can print a backtrace if we just embed the UD2 instruction to crash.
* That's useful for systems code, for the following reason. Invariants
* make sense with _unassert() since they usually get placed at the top
* of functions. But if you used _unassert() to test a system call does
* not fail, then check happens at the end of your function usually and
* is therefore likely to result in a failure condition where execution
* falls through into a different function, which is shocking to debug.
*
* In `MODE=tiny` these assertions are redefined as undefined behavior.
*/
#define _npassert(x) \
do { \
({ \
if (__builtin_expect(!(x), 0)) { \
notpossible; \
} \
} while (0)
(void)0; \
})
#else
#define _npassert(x) _unassert(x)
#endif
#endif
#ifdef __GNUC__
/**
* Specifies expression being false is undefined behavior.
*
* This is a good way to tell the compiler about your invariants, which
* leads to smaller faster programs. The expression is never removed by
* the preprocessor so it's recommended that it be free of side-effects
* if you intend for it to be removed. At the same time, this guarantee
* makes this assertion useful for things like system calls, since they
* won't be removed by `NDEBUG` mode.
*
* If this assertion fails, the worst possible things can happen unless
* you've built your binary in `MODE=dbg` since UBSAN is the only thing
* that's capable of debugging this macro.
*/
#define _unassert(x) \
({ \
if (__builtin_expect(!(x), 0)) { \
unreachable; \
} \
(void)0; \
})
#endif
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+5 -11
View File
@@ -1,7 +1,7 @@
/*-*- 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│
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
│ 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 │
@@ -16,12 +16,6 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/calls/sig.internal.h"
// Returns 𝑒^x-1.
//
// @param 𝑥 is double scalar in low half of %xmm0
// @return double scalar in low half of %xmm0
expm1: ezlea expm1l,ax
jmp _d2ld2
.endfn expm1,globl
struct Signals __sig;
+37 -51
View File
@@ -16,26 +16,22 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/lockcmpxchg.h"
#include "libc/calls/struct/sigset.h"
#include "libc/intrin/strace.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
/**
* @fileoverview UNIX signals for the New Technology, Part 2.
* @threadsafe
*/
#include "libc/thread/tls.h"
/**
* Allocates piece of memory for storing pending signal.
@@ -61,6 +57,18 @@ static textwindows void __sig_free(struct Signal *mem) {
mem->used = false;
}
static inline textwindows int __sig_is_masked(int sig) {
if (__tls_enabled) {
return __get_tls()->tib_sigmask & (1ull << (sig - 1));
} else {
return __sig.sigmask & (1ull << (sig - 1));
}
}
textwindows int __sig_is_applicable(struct Signal *s) {
return s->tid <= 0 || s->tid == gettid();
}
/**
* Dequeues signal that isn't masked.
* @return signal or null if empty or none unmasked
@@ -70,7 +78,7 @@ static textwindows struct Signal *__sig_remove(void) {
if (__sig.queue) {
__sig_lock();
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
if (!sigismember(&__sig.mask, res->sig)) {
if (__sig_is_applicable(res) && !__sig_is_masked(res->sig)) {
if (res == __sig.queue) {
__sig.queue = res->next;
} else if (prev) {
@@ -78,8 +86,6 @@ static textwindows struct Signal *__sig_remove(void) {
}
res->next = 0;
break;
} else {
STRACE("%G is masked", res->sig);
}
}
__sig_unlock();
@@ -117,7 +123,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
// setup the somewhat expensive information args
// only if they're requested by the user in sigaction()
if (flags & SA_SIGINFO) {
__repstosb(&info, 0, sizeof(info));
bzero(&info, sizeof(info));
info.si_signo = sig;
info.si_code = si_code;
infop = &info;
@@ -134,7 +140,11 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
// since sigaction() is @asyncsignalsafe we only restore it if the
// user didn't change it during the signal handler. we also don't
// need to do anything if this was a oneshot signal or nodefer.
_lockcmpxchg(__sighandrvas + sig, (int32_t)(intptr_t)SIG_DFL, rva);
__sig_lock();
if (__sighandrvas[sig] == (int32_t)(intptr_t)SIG_DFL) {
__sighandrvas[sig] = rva;
}
__sig_unlock();
}
if (!restartable) {
@@ -150,7 +160,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
/**
* Returns true if signal default action is to end process.
*/
static textwindows bool __sig_isfatal(int sig) {
static textwindows bool __sig_is_fatal(int sig) {
if (sig == SIGCHLD || sig == SIGURG || sig == SIGWINCH) {
return false;
} else {
@@ -168,7 +178,7 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
bool delivered;
switch (__sighandrvas[sig]) {
case (intptr_t)SIG_DFL:
if (__sig_isfatal(sig)) {
if (__sig_is_fatal(sig)) {
STRACE("terminating on %G", sig);
_Exitr(128 + sig);
}
@@ -194,20 +204,17 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
* @threadsafe
*/
textwindows int __sig_raise(int sig, int si_code) {
int rc;
int candeliver;
__sig_lock();
candeliver = !sigismember(&__sig.mask, sig);
__sig_unlock();
switch (candeliver) {
case 1:
if (1 <= sig && sig <= 64) {
if (!__sig_is_masked(sig)) {
++__sig_count;
__sig_handle(false, sig, si_code, 0);
return 0;
case 0:
} else {
STRACE("%G is masked", sig);
return __sig_add(sig, si_code);
default:
return -1; // sigismember() validates `sig`
return __sig_add(gettid(), sig, si_code);
}
} else {
return einval();
}
}
@@ -216,10 +223,10 @@ textwindows int __sig_raise(int sig, int si_code) {
* @return 0 on success, otherwise -1 w/ errno
* @threadsafe
*/
textwindows int __sig_add(int sig, int si_code) {
textwindows int __sig_add(int tid, int sig, int si_code) {
int rc;
struct Signal *mem;
if (1 <= sig && sig <= NSIG) {
if (1 <= sig && sig <= 64) {
__sig_lock();
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
STRACE("ignoring %G", sig);
@@ -228,6 +235,7 @@ textwindows int __sig_add(int sig, int si_code) {
STRACE("enqueuing %G", sig);
++__sig_count;
if ((mem = __sig_alloc())) {
mem->tid = tid;
mem->sig = sig;
mem->si_code = si_code;
mem->next = __sig.queue;
@@ -276,7 +284,7 @@ textwindows bool __sig_check(bool restartable) {
textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
struct Signal *cur, *prev, *next;
if (rva != (unsigned)(intptr_t)SIG_IGN &&
(rva != (unsigned)(intptr_t)SIG_DFL || __sig_isfatal(sig))) {
(rva != (unsigned)(intptr_t)SIG_DFL || __sig_is_fatal(sig))) {
return;
}
if (__sig.queue) {
@@ -298,25 +306,3 @@ textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
__sig_unlock();
}
}
/**
* Determines the pending signals on New Technology.
*
* @param pending is to hold the pending signals
* @threadsafe
*/
textwindows void __sig_pending(sigset_t *pending) {
struct Signal *cur;
sigemptyset(pending);
if (__sig.queue) {
__sig_lock();
for (cur = __sig.queue; cur; cur = cur->next) {
if (__sighandrvas[cur->sig] != (unsigned)(intptr_t)SIG_IGN) {
pending->__bits[(cur->sig - 1) >> 6] |= (1ull << ((cur->sig - 1) & 63));
} else {
STRACE("%G is ignored", cur->sig);
}
}
__sig_unlock();
}
}
+20 -30
View File
@@ -17,49 +17,39 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/macros.internal.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/tls.h"
/**
* @fileoverview UNIX signals for the New Technology, Part 1.
* @threadsafe
*/
#define GetSigBit(x) (1ull << (((x)-1) & 63))
struct Signals __sig; // TODO(jart): Need TLS
#define GetSigBit(XXSIG) (1ull << (((XXSIG)-1) & 63))
/**
* Changes signal mask for main thread.
* @return 0 on success, or -1 w/ errno
*/
textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
int i;
uint64_t a, b;
uint64_t x, y, *mask;
if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) {
__sig_lock();
if (__tls_enabled) {
mask = &__get_tls()->tib_sigmask;
} else {
mask = &__sig.sigmask;
}
if (old) {
*old = __sig.mask;
old->__bits[0] = *mask;
old->__bits[1] = 0;
}
if (neu) {
for (i = 0; i < ARRAYLEN(__sig.mask.__bits); ++i) {
if (how == SIG_BLOCK) {
__sig.mask.__bits[i] |= neu->__bits[i];
} else if (how == SIG_UNBLOCK) {
__sig.mask.__bits[i] &= ~neu->__bits[i];
} else {
__sig.mask.__bits[i] = neu->__bits[i];
}
x = *mask;
y = neu->__bits[0];
if (how == SIG_BLOCK) {
x |= y;
} else if (how == SIG_UNBLOCK) {
x &= ~y;
} else {
x = y;
}
__sig.mask.__bits[0] &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP));
x &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP) | GetSigBit(SIGABRT));
*mask = x;
}
__sig_unlock();
return 0;
} else {
return einval();
}
}
#undef GetSigBit
+43
View 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();
}
}
+1 -3
View File
@@ -32,12 +32,10 @@
* @asyncsignalsafe
*/
unsigned alarm(unsigned seconds) {
int rc;
struct itimerval it;
bzero(&it, sizeof(it));
it.it_value.tv_sec = seconds;
rc = setitimer(ITIMER_REAL, &it, &it);
assert(rc != -1);
_npassert(!setitimer(ITIMER_REAL, &it, &it));
if (!it.it_value.tv_sec && !it.it_value.tv_usec) {
return 0;
} else {
+13 -12
View File
@@ -85,7 +85,7 @@ int execve(const char *, char *const[], char *const[]);
int execvp(const char *, char *const[]);
int execvpe(const char *, char *const[], char *const[]);
int fexecve(int, char *const[], char *const[]);
int faccessat(int, const char *, int, uint32_t);
int faccessat(int, const char *, int, int);
int fadvise(int, uint64_t, uint64_t, int);
int fchdir(int);
int fchmod(int, uint32_t) dontthrow;
@@ -128,8 +128,9 @@ int linkat(int, const char *, int, const char *, int);
int madvise(void *, uint64_t, int);
int memfd_create(const char *, unsigned int);
int mincore(void *, size_t, unsigned char *);
int mkdir(const char *, uint32_t);
int mkdirat(int, const char *, uint32_t);
int mkdir(const char *, unsigned);
int mkdirat(int, const char *, unsigned);
int makedirs(const char *, unsigned);
int mkfifo(const char *, uint32_t);
int mkfifoat(int, const char *, uint32_t);
int mknod(const char *, uint32_t, uint64_t);
@@ -148,7 +149,7 @@ int pipe(int[hasatleast 2]);
int pipe2(int[hasatleast 2], int);
int pivot_root(const char *, const char *);
int pledge(const char *, const char *);
int posix_fadvise(int, uint64_t, uint64_t, int);
int posix_fadvise(int, int64_t, int64_t, int);
int posix_madvise(void *, uint64_t, int);
int prctl(int, ...);
int raise(int);
@@ -162,10 +163,10 @@ int sched_yield(void);
int seccomp(unsigned, unsigned, void *);
int setegid(uint32_t);
int seteuid(uint32_t);
int setfsgid(int);
int setfsuid(int);
int setgid(int);
int setgroups(size_t size, const uint32_t list[]);
int setfsgid(unsigned);
int setfsuid(unsigned);
int setgid(unsigned);
int setgroups(size_t, const uint32_t[]);
int setpgid(int, int);
int setpgrp(void);
int setpriority(int, unsigned, int);
@@ -174,7 +175,7 @@ int setresgid(uint32_t, uint32_t, uint32_t);
int setresuid(uint32_t, uint32_t, uint32_t);
int setreuid(uint32_t, uint32_t);
int setsid(void);
int setuid(int);
int setuid(unsigned);
int sigignore(int);
int siginterrupt(int, int);
int symlink(const char *, const char *);
@@ -187,9 +188,9 @@ int tgkill(int, int, int);
int tkill(int, int);
int tmpfd(void);
int touch(const char *, uint32_t);
int truncate(const char *, uint64_t);
int truncate(const char *, int64_t);
int ttyname_r(int, char *, size_t);
int umask(int);
unsigned umask(unsigned);
int unlink(const char *);
int unlink_s(const char **);
int unlinkat(int, const char *, int);
@@ -204,7 +205,7 @@ long ptrace(int, ...);
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t getfiledescriptorsize(int);
ssize_t lseek(int, int64_t, unsigned);
ssize_t lseek(int, int64_t, int);
ssize_t pread(int, void *, size_t, int64_t);
ssize_t pwrite(int, const void *, size_t, int64_t);
ssize_t read(int, void *, size_t);
+7
View File
@@ -65,6 +65,13 @@ $(LIBC_CALLS_A).pkg: \
$(LIBC_CALLS_A_OBJS) \
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
# we can't use asan because:
# siginfo_t memory is owned by kernels
o/$(MODE)/libc/calls/siginfo2cosmo.o: private \
OVERRIDE_COPTS += \
-ffreestanding \
-fno-sanitize=address
# we can't use asan because:
# ucontext_t memory is owned by xnu kernel
o/$(MODE)/libc/calls/sigenter-xnu.o: private \
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libc/calls/termios.h"
#include "libc/sysv/errfuns.h"
int cfsetispeed(struct termios *t, int speed) {
int cfsetispeed(struct termios *t, unsigned speed) {
if (speed) {
if (CBAUD) {
if (speed & ~CBAUD) return einval();
+1 -1
View File
@@ -20,7 +20,7 @@
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
int cfsetospeed(struct termios *t, int speed) {
int cfsetospeed(struct termios *t, unsigned speed) {
if (CBAUD) {
if (!(speed & ~CBAUD)) {
t->c_cflag &= ~CBAUD;
+1 -1
View File
@@ -75,10 +75,10 @@
* @return 0 on success, or errno on error
* @raise EINTR when a signal got delivered while we were waiting
* @raise ENOTSUP if `clock` is known but we can't use it here
* @raise EFAULT if `req` or null or bad memory was passed
* @raise EINVAL if `clock` is unknown to current platform
* @raise EINVAL if `flags` has an unrecognized value
* @raise EINVAL if `req->tv_nsec ∉ [0,1000000000)`
* @raise EFAULT if bad memory was passed
* @raise ENOSYS on bare metal
* @returnserrno
* @norestart
+13 -11
View File
@@ -35,27 +35,29 @@
* }
*
* @return 0 on success, or -1 w/ errno
* @error EBADF if `first` is negative
* @error EBADF on OpenBSD if `first` is greater than highest fd
* @error EINVAL if flags are bad or first is greater than last
* @error EMFILE if a weird race condition happens on Linux
* @error ENOSYS if not Linux 5.9+, FreeBSD 8+, or OpenBSD
* @error EINTR possibly on OpenBSD
* @error ENOMEM on Linux maybe
* @raise EBADF if `first` is negative
* @raise ENOSYS if not Linux 5.9+, FreeBSD 8+, OpenBSD, or NetBSD
* @raise EBADF on OpenBSD if `first` is greater than highest fd
* @raise EINVAL if flags are bad or first is greater than last
* @raise EMFILE if a weird race condition happens on Linux
* @raise EINTR possibly on OpenBSD
* @raise ENOMEM on Linux maybe
*/
int closefrom(int first) {
int rc, err;
if (IsNetbsd() || IsWindows() || IsMetal()) {
rc = enosys();
} else if (first < 0) {
if (first < 0) {
// consistent with openbsd
// freebsd allows this but it's dangerous
// necessary on linux due to type signature
rc = ebadf();
} else if (IsFreebsd() || IsOpenbsd()) {
rc = sys_closefrom(first);
} else if (IsLinux()) {
rc = sys_close_range(first, 0xffffffffu, 0);
} else if (IsNetbsd()) {
rc = __sys_fcntl(first, 10 /*F_CLOSEM*/, first);
} else {
rc = sys_closefrom(first);
rc = enosys();
}
STRACE("closefrom(%d) → %d% m", first, rc);
return rc;
+1 -1
View File
@@ -99,7 +99,7 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
startinfo.hStdError = __getfdhandleactual(2);
// spawn the process
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
rc = ntspawn(program, argv, envp, 0, 0, 0, true, 0, 0, &startinfo, &procinfo);
if (rc == -1) {
STRACE("panic: unrecoverable ntspawn(%#s) error: %m", program);
__imp_ExitProcess(6543);
+1 -1
View File
@@ -48,7 +48,7 @@
* @note on Linux `flags` is only supported on Linux 5.8+
* @asyncsignalsafe
*/
int faccessat(int dirfd, const char *path, int amode, uint32_t flags) {
int faccessat(int dirfd, const char *path, int amode, int flags) {
int e, rc;
struct ZiposUri zipname;
if (!path || (IsAsan() && !__asan_is_valid(path, 1))) {
+1 -7
View File
@@ -37,8 +37,6 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
bool __force_sqlite_to_work_until_we_can_fix_it;
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
if (start < 0) return einval();
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
@@ -110,11 +108,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
ok = true;
}
}
if (ok || __force_sqlite_to_work_until_we_can_fix_it) {
return 0;
} else {
return -1;
}
return ok ? 0 : -1;
}
if (l->l_type == F_UNLCK) {
+90 -8
View File
@@ -18,11 +18,15 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/flock.h"
#include "libc/calls/struct/flock.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
@@ -44,9 +48,49 @@
* Please be warned that locks currently do nothing on Windows since
* figuring out how to polyfill them correctly is a work in progress.
*
* @param cmd can be F_{GET,SET}{FD,FL}, etc.
* @param fd is the file descriptor
* @param cmd can be one of:
* - `F_GETFD` gets `FD_CLOEXEC` status of `fd
* - `F_SETFD` sets `FD_CLOEXEC` status of `arg` file descriptor
* - `F_GETFL` returns file descriptor status flags
* - `F_SETFL` sets file descriptor status flags
* - `F_DUPFD` is like dup() but `arg` is a minimum result, e.g. 3
* - `F_DUPFD_CLOEXEC` ditto but sets `O_CLOEXEC` on returned fd
* - `F_SETLK` for record locking where `arg` is `struct flock`
* - `F_SETLKW` ditto but waits (i.e. blocks) for lock
* - `F_GETLK` to retrieve information about a record lock
* - `F_OFD_SETLK` for better locks on Linux and XNU
* - `F_OFD_SETLKW` for better locks on Linux and XNU
* - `F_OFD_GETLK` for better locks on Linux and XNU
* - `F_FULLFSYNC` on MacOS for fsync() with release barrier
* - `F_BARRIERFSYNC` on MacOS for fsync() with even more barriers
* - `F_SETNOSIGPIPE` on MacOS and NetBSD to control `SIGPIPE`
* - `F_GETNOSIGPIPE` on MacOS and NetBSD to control `SIGPIPE`
* - `F_GETPATH` on MacOS and NetBSD where arg is `char[PATH_MAX]`
* - `F_MAXFD` on NetBSD to get max open file descriptor
* - `F_NOCACHE` on MacOS to toggle data caching
* - `F_GETPIPE_SZ` on Linux to get pipe size
* - `F_SETPIPE_SZ` on Linux to set pipe size
* - `F_NOTIFY` raise `SIGIO` upon `fd` events in `arg` on Linux
* - `DN_ACCESS` for file access
* - `DN_MODIFY` for file modifications
* - `DN_CREATE` for file creations
* - `DN_DELETE` for file deletions
* - `DN_RENAME` for file renames
* - `DN_ATTRIB` for file attribute changes
* - `DN_MULTISHOT` bitwise or for realtime signals (non-coalesced)
* @param arg can be FD_CLOEXEC, etc. depending
* @return 0 on success, or -1 w/ errno
* @raise EBADF if `fd` isn't a valid open file descriptor
* @raise EINVAL if `cmd` is unknown or unsupported by os
* @raise EINVAL if `cmd` is invalid or unsupported by os
* @raise EPERM if pledge() is in play w/o `stdio` or `flock` promise
* @raise ENOLCK if `F_SETLKW` would have exceeded `RLIMIT_LOCKS`
* @raise EPERM if `cmd` is `F_SETOWN` and we weren't authorized
* @raise ESRCH if `cmd` is `F_SETOWN` and process group not found
* @raise EDEADLK if `cmd` was `F_SETLKW` and waiting would deadlock
* @raise EMFILE if `cmd` is `F_DUPFD` or `F_DUPFD_CLOEXEC` and
* `RLIMIT_NOFILE` would be exceeded
* @asyncsignalsafe
* @restartable
*/
@@ -54,20 +98,58 @@ int fcntl(int fd, int cmd, ...) {
int rc;
va_list va;
uintptr_t arg;
va_start(va, cmd);
arg = va_arg(va, uintptr_t);
va_end(va);
if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = _weaken(__zipos_fcntl)(fd, cmd, arg);
} else if (!IsWindows()) {
rc = sys_fcntl(fd, cmd, arg);
if (cmd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = _weaken(__zipos_fcntl)(fd, cmd, arg);
} else if (!IsWindows()) {
rc = sys_fcntl(fd, cmd, arg);
} else {
rc = sys_fcntl_nt(fd, cmd, arg);
}
} else {
rc = sys_fcntl_nt(fd, cmd, arg);
rc = einval();
}
} 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;
}
+5 -3
View File
@@ -17,10 +17,11 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
/**
@@ -33,6 +34,7 @@
*/
int fdatasync(int fd) {
int rc;
struct stat st;
if (__nosync != 0x5453455454534146) {
if (!IsWindows()) {
rc = sys_fdatasync(fd);
@@ -41,8 +43,8 @@ int fdatasync(int fd) {
}
STRACE("fdatasync(%d) → %d% m", fd, rc);
} else {
rc = 0;
STRACE("fdatasync(%d) → disabled% m", fd);
rc = fstat(fd, &st);
STRACE("fdatasync_fake(%d) → %d% m", fd, rc);
}
return rc;
}
+5 -3
View File
@@ -17,10 +17,11 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
/**
@@ -33,6 +34,7 @@
*/
int fsync(int fd) {
int rc;
struct stat st;
if (__nosync != 0x5453455454534146) {
if (!IsWindows()) {
rc = sys_fsync(fd);
@@ -41,8 +43,8 @@ int fsync(int fd) {
}
STRACE("fysnc(%d) → %d% m", fd, rc);
} else {
rc = 0;
STRACE("fsync(%d) → disabled% m", fd);
rc = fstat(fd, &st);
STRACE("fsync_fake(%d) → %d% m", fd, rc);
}
return rc;
}
+14 -8
View File
@@ -34,7 +34,7 @@
#define HW_NCPUONLINE_NETBSD 16
#define ALL_PROCESSOR_GROUPS 0xffff
static unsigned GetCpuCountLinux(void) {
static unsigned _getcpucount_linux(void) {
cpu_set_t s = {0};
if (sys_sched_getaffinity(0, sizeof(s), &s) != -1) {
return CPU_COUNT(&s);
@@ -43,7 +43,7 @@ static unsigned GetCpuCountLinux(void) {
}
}
static unsigned GetCpuCountBsd(void) {
static unsigned _getcpucount_bsd(void) {
size_t n;
int c, cmd[2];
n = sizeof(c);
@@ -62,12 +62,12 @@ static unsigned GetCpuCountBsd(void) {
}
}
static unsigned GetCpuCountImpl(void) {
static unsigned _getcpucount_impl(void) {
if (!IsWindows()) {
if (!IsBsd()) {
return GetCpuCountLinux();
return _getcpucount_linux();
} else {
return GetCpuCountBsd();
return _getcpucount_bsd();
}
} else {
return GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
@@ -77,18 +77,24 @@ static unsigned GetCpuCountImpl(void) {
static int g_cpucount;
// precompute because process affinity on linux may change later
__attribute__((__constructor__)) static void init(void) {
g_cpucount = GetCpuCountImpl();
__attribute__((__constructor__)) static void _getcpucount_init(void) {
g_cpucount = _getcpucount_impl();
}
/**
* Returns number of CPUs in system.
*
* This is the same as the standard interface:
*
* sysconf(_SC_NPROCESSORS_ONLN);
*
* Except this function isn't a bloated diamond dependency.
*
* On Intel systems with HyperThreading this will return the number of
* cores multiplied by two.
*
* @return cpu count or 0 if it couldn't be determined
*/
unsigned GetCpuCount(void) {
unsigned _getcpucount(void) {
return g_cpucount;
}
+1 -1
View File
@@ -52,7 +52,7 @@ char *getcwd(char *buf, size_t size) {
return 0;
}
} else if (_weaken(malloc)) {
assert(!__vforked);
_unassert(!__vforked);
if (!size) size = PATH_MAX;
if (!(p = _weaken(malloc)(size))) {
STRACE("getcwd(%p, %'zu) %m", buf, size);
+3 -3
View File
@@ -20,10 +20,10 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
#include "libc/thread/thread.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
#include "libc/runtime/sysconf.h"
#include "libc/runtime/runtime.h"
#include "libc/thread/thread.h"
#define FT(x) (x.dwLowDateTime | (uint64_t)x.dwHighDateTime << 32)
@@ -60,7 +60,7 @@ static textstartup void sys_getloadavg_nt_init(void) {
double a[3];
if (IsWindows()) {
load = 1;
cpus = GetCpuCount() / 2;
cpus = _getcpucount() / 2;
cpus = MAX(1, cpus);
GetSystemTimes(&idle1, &kern1, &user1);
}
+58 -19
View File
@@ -16,28 +16,67 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/kntprioritycombos.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/nexgen32e/ffs.h"
#include "libc/nt/enum/processaccess.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thread.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/prio.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_getpriority_nt(int ignored) {
size_t i;
uint32_t tier, lg2tier, wut;
if ((tier = GetPriorityClass(GetCurrentProcess())) != 0 &&
(wut = GetThreadPriority(GetCurrentThread())) != -1u) {
lg2tier = ffs(tier);
for (i = 0; i < kNtPriorityCombosLen; ++i) {
if (kNtPriorityCombos[i].lg2tier == lg2tier &&
kNtPriorityCombos[i].wut == wut) {
return kNtPriorityCombos[i].nice;
}
}
abort();
} else {
return __winerr();
textwindows int sys_getpriority_nt(int which, unsigned pid) {
int rc;
uint32_t tier;
int64_t h, closeme = -1;
if (which != PRIO_PROCESS) {
return einval();
}
if (!pid || pid == getpid()) {
h = GetCurrentProcess();
} else if (__isfdkind(pid, kFdProcess)) {
h = g_fds.p[pid].handle;
} else {
h = OpenProcess(kNtProcessQueryInformation, false, pid);
if (!h) return __winerr();
closeme = h;
}
if ((tier = GetPriorityClass(h))) {
switch (tier) {
case kNtRealtimePriorityClass:
rc = -16;
break;
case kNtHighPriorityClass:
rc = -10;
break;
case kNtAboveNormalPriorityClass:
rc = -5;
break;
case kNtNormalPriorityClass:
rc = 0;
break;
case kNtBelowNormalPriorityClass:
rc = 5;
break;
case kNtIdlePriorityClass:
rc = 15;
break;
default:
notpossible;
}
} else {
rc = __winerr();
}
if (closeme != -1) {
CloseHandle(closeme);
}
return rc;
}
+40 -10
View File
@@ -17,10 +17,13 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asmflag.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/limits.h"
/**
* Returns nice value of thing.
@@ -29,20 +32,47 @@
* to clear `errno` beforehand and see if it changed, in order to truly
* determine if an error happened.
*
* @param which can be PRIO_PROCESS, PRIO_PGRP, PRIO_USER
* On Windows, there's only six priority classes. We define them as -16
* (realtime), -10 (high), -5 (above), 0 (normal), 5 (below), 15 (idle)
* which are the only values that'll roundtrip getpriority/setpriority.
*
* @param which can be one of:
* - `PRIO_PROCESS` is supported universally
* - `PRIO_PGRP` is supported on unix
* - `PRIO_USER` is supported on unix
* @param who is the pid, pgid, or uid (0 means current)
* @return value ∈ [-NZERO,NZERO) or -1 w/ errno
* @see setpriority(), nice()
* @raise EINVAL if `which` was invalid or unsupported
* @raise EPERM if access to process was denied
* @raise ESRCH if no such process existed
* @see setpriority()
*/
int getpriority(int which, unsigned who) {
privileged int getpriority(int which, unsigned who) {
int rc;
if (!IsWindows()) {
if ((rc = sys_getpriority(which, who)) != -1) {
rc = 20 - rc;
char cf;
if (IsLinux()) {
asm volatile("syscall"
: "=a"(rc)
: "0"(140), "D"(which), "S"(who)
: "rcx", "r11", "memory");
if (rc >= 0) {
rc = NZERO - rc;
} else {
errno = -rc;
rc = -1;
}
} else if (IsBsd()) {
asm volatile(CFLAG_ASM("syscall")
: CFLAG_CONSTRAINT(cf), "=a"(rc)
: "1"((IsXnu() ? 0x2000000 : 0) | 100), "D"(which), "S"(who)
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory");
if (cf) {
errno = rc;
rc = -1;
}
} else {
rc = sys_getsetpriority_nt(which, who, 0, sys_getpriority_nt);
rc = sys_getpriority_nt(which, who);
}
STRACE("getpriority(%d, %u) → %d% m", which, who, rc);
STRACE("getpriority(%s, %u) → %d% m", DescribeWhichPrio(which), who, rc);
return rc;
}
+1 -4
View File
@@ -33,7 +33,7 @@
#include "libc/sysv/errfuns.h"
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
int64_t me, nsignals;
int64_t me;
struct NtIoCounters iocount;
struct NtProcessMemoryCountersEx memcount;
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
@@ -48,9 +48,6 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
!GetProcessIoCounters(me, &iocount)) {
return __winerr();
}
__sig_lock();
nsignals = __sig_count;
__sig_unlock();
*usage = (struct rusage){
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
+1 -2
View File
@@ -31,9 +31,8 @@
textwindows bool _check_interrupts(bool restartable, struct Fd *fd) {
bool res;
if (__threaded && __threaded != gettid()) return false;
if (_weaken(_check_sigalrm)) _weaken(_check_sigalrm)();
if (!(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
if (!__tls_enabled || !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
if (_weaken(_check_sigchld)) _weaken(_check_sigchld)();
if (fd && _weaken(_check_sigwinch)) _weaken(_check_sigwinch)(fd);
}
+1 -1
View File
@@ -253,7 +253,7 @@ static int createHostInfo(struct NtIpAdapterAddresses *firstAdapter) {
int count, i;
/* __hostInfo must be empty */
assert(__hostInfo == NULL);
_unassert(__hostInfo == NULL);
for (aa = firstAdapter; aa; aa = aa->Next) {
/* Skip all the interfaces with no address and the ones that are not AF_INET
-56
View File
@@ -1,56 +0,0 @@
/*-*- 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 2020 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/bits.h"
#include "libc/calls/kntprioritycombos.internal.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/ffs.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/enum/threadpriority.h"
hidden const struct NtPriorityCombo kNtPriorityCombos[] = {
{-20, ffs(kNtHighPriorityClass), kNtThreadPriorityHighest, 15},
{-18, ffs(kNtHighPriorityClass), kNtThreadPriorityTimeCritical, 15},
{-17, ffs(kNtNormalPriorityClass), kNtThreadPriorityTimeCritical, 15},
{-15, ffs(kNtIdlePriorityClass), kNtThreadPriorityTimeCritical, 15},
{-13, ffs(kNtHighPriorityClass), kNtThreadPriorityAboveNormal, 14},
{-11, ffs(kNtHighPriorityClass), kNtThreadPriorityNormal, 13},
{-9, ffs(kNtHighPriorityClass), kNtThreadPriorityBelowNormal, 12},
{-7, ffs(kNtNormalPriorityClass), kNtThreadPriorityHighest, 11},
{-5, ffs(kNtHighPriorityClass), kNtThreadPriorityLowest, 11},
{-3, ffs(kNtNormalPriorityClass), kNtThreadPriorityAboveNormal, 10},
{-1, ffs(kNtNormalPriorityClass), kNtThreadPriorityHighest, 9},
{0, ffs(kNtNormalPriorityClass), kNtThreadPriorityNormal, 9},
{1, ffs(kNtNormalPriorityClass), kNtThreadPriorityAboveNormal, 8},
{2, ffs(kNtNormalPriorityClass), kNtThreadPriorityBelowNormal, 8},
{3, ffs(kNtNormalPriorityClass), kNtThreadPriorityNormal, 7},
{4, ffs(kNtNormalPriorityClass), kNtThreadPriorityLowest, 7},
{5, ffs(kNtIdlePriorityClass), kNtThreadPriorityHighest, 6},
{6, ffs(kNtNormalPriorityClass), kNtThreadPriorityBelowNormal, 6},
{7, ffs(kNtIdlePriorityClass), kNtThreadPriorityAboveNormal, 5},
{9, ffs(kNtNormalPriorityClass), kNtThreadPriorityLowest, 5},
{11, ffs(kNtIdlePriorityClass), kNtThreadPriorityNormal, 4},
{13, ffs(kNtIdlePriorityClass), kNtThreadPriorityBelowNormal, 3},
{15, ffs(kNtIdlePriorityClass), kNtThreadPriorityLowest, 2},
{17, ffs(kNtHighPriorityClass), kNtThreadPriorityIdle, 1},
{18, ffs(kNtNormalPriorityClass), kNtThreadPriorityIdle, 1},
{19, ffs(kNtIdlePriorityClass), kNtThreadPriorityIdle, 1},
};
hidden const unsigned kNtPriorityCombosLen = ARRAYLEN(kNtPriorityCombos);
-18
View File
@@ -1,18 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_KNTPRIORITYCOMBOS_H_
#define COSMOPOLITAN_LIBC_CALLS_KNTPRIORITYCOMBOS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtPriorityCombo {
int8_t nice; /* sorted by this */
int8_t lg2tier;
int8_t wut;
int8_t prio;
};
hidden extern const unsigned kNtPriorityCombosLen;
hidden extern const struct NtPriorityCombo kNtPriorityCombos[];
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_KNTPRIORITYCOMBOS_H_ */
+1 -1
View File
@@ -74,7 +74,7 @@
* @threadsafe
* @vforksafe
*/
int64_t lseek(int fd, int64_t offset, unsigned whence) {
int64_t lseek(int fd, int64_t offset, int whence) {
int64_t rc;
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = _weaken(__zipos_lseek)(
+91
View File
@@ -0,0 +1,91 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2021 Justine Alexandra Roberts Tunney │
│ │
│ Permission to use, copy, modify, and/or distribute this software for │
│ any purpose with or without fee is hereby granted, provided that the │
│ above copyright notice and this permission notice appear in all copies. │
│ │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/str/path.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
/**
* Creates directory and parent components.
*
* This function is similar to mkdir() except it iteratively creates
* parent directories and it won't fail if the directory already exists.
*
* @param path is a UTF-8 string, preferably relative w/ forward slashes
* @param mode can be, for example, 0755
* @return 0 on success or -1 w/ errno
* @raise EEXIST if named file already exists as non-directory
* @raise ENOTDIR if directory component in `path` existed as non-directory
* @raise ENAMETOOLONG if symlink-resolved `path` length exceeds `PATH_MAX`
* @raise ENAMETOOLONG if component in `path` exists longer than `NAME_MAX`
* @raise EROFS if parent directory is on read-only filesystem
* @raise ENOSPC if file system or parent directory is full
* @raise EACCES if write permission was denied on parent directory
* @raise EACCES if search permission was denied on component in `path`
* @raise ENOENT if `path` is an empty string
* @raise ELOOP if loop was detected resolving components of `path`
* @asyncsignalsafe
* @threadsafe
*/
int makedirs(const char *path, unsigned mode) {
int c, e, i, n;
struct stat st;
char buf[PATH_MAX];
e = errno;
n = strlen(path);
if (n >= PATH_MAX) return enametoolong();
memcpy(buf, path, n + 1);
i = n;
// descend
while (i) {
if (!mkdir(buf, mode)) break;
if (errno == EEXIST) {
if (i == n) goto CheckTop;
break;
}
if (errno != ENOENT) return -1;
while (i && _isdirsep(buf[i - 1])) buf[--i] = 0;
while (i && !_isdirsep(buf[i - 1])) buf[--i] = 0;
}
// ascend
for (;;) {
if (mkdir(buf, mode)) {
if (errno != EEXIST) return -1;
if (i == n) goto CheckTop;
}
if (i == n) break;
while (i < n && !_isdirsep((c = path[i]))) buf[i++] = c;
while (i < n && _isdirsep((c = path[i]))) buf[i++] = c;
}
Finish:
errno = e;
return 0;
CheckTop:
if (stat(path, &st)) return -1;
if (S_ISDIR(st.st_mode)) goto Finish;
return eexist();
}
+14 -7
View File
@@ -17,12 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/**
* Creates directory a.k.a. folder.
@@ -36,9 +31,21 @@
* @param path is a UTF-8 string, preferably relative w/ forward slashes
* @param mode can be, for example, 0755
* @return 0 on success or -1 w/ errno
* @error ENAMETOOLONG if >246 characters on NT
* @raise EEXIST if named file already exists
* @raise ENOTDIR if directory component in `path` existed as non-directory
* @raise ENAMETOOLONG if symlink-resolved `path` length exceeds `PATH_MAX`
* @raise ENAMETOOLONG if component in `path` exists longer than `NAME_MAX`
* @raise EROFS if parent directory is on read-only filesystem
* @raise ENOSPC if file system or parent directory is full
* @raise EACCES if write permission was denied on parent directory
* @raise EACCES if search permission was denied on component in `path`
* @raise ENOENT if a component within `path` didn't exist
* @raise ENOENT if `path` is an empty string
* @raise ELOOP if loop was detected resolving components of `path`
* @see makedirs() which is higher-level
* @see mkdirat() for modern call
* @asyncsignalsafe
* @see makedirs()
* @threadsafe
*/
int mkdir(const char *path, unsigned mode) {
return mkdirat(AT_FDCWD, path, mode);
+15 -4
View File
@@ -31,12 +31,23 @@
/**
* Creates directory a.k.a. folder.
*
* @param dirfd is normally AT_FDCWD but if it's an open directory and
* @param dirfd is normally `AT_FDCWD` but if it's an open directory and
* path is relative, then path becomes relative to dirfd
* @param path is a UTF-8 string, preferably relative w/ forward slashes
* @param mode can be, for example, 0755
* @return 0 on success or -1 w/ errno
* @error EEXIST, ENOTDIR, ENAMETOOLONG, EACCES, ENOENT
* @param mode is permissions bits, which is usually 0755
* @return 0 on success, or -1 w/ errno
* @raise EEXIST if named file already exists
* @raise EBADF if `path` is relative and `dirfd` isn't `AT_FDCWD` or valid
* @raise ENOTDIR if directory component in `path` existed as non-directory
* @raise ENAMETOOLONG if symlink-resolved `path` length exceeds `PATH_MAX`
* @raise ENAMETOOLONG if component in `path` exists longer than `NAME_MAX`
* @raise EROFS if parent directory is on read-only filesystem
* @raise ENOSPC if file system or parent directory is full
* @raise EACCES if write permission was denied on parent directory
* @raise EACCES if search permission was denied on component in `path`
* @raise ENOENT if a component within `path` didn't exist
* @raise ENOENT if `path` is an empty string
* @raise ELOOP if loop was detected resolving components of `path`
* @asyncsignalsafe
* @see makedirs()
*/
+1
View File
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/sysv/consts/prio.h"
+1 -1
View File
@@ -91,7 +91,7 @@ static long double nowl_art(void) {
static long double nowl_vdso(void) {
long double secs;
struct timespec tv;
assert(__gettime);
_unassert(__gettime);
__gettime(CLOCK_REALTIME_FAST, &tv);
secs = tv.tv_nsec;
secs *= 1 / 1e9L;
+5 -3
View File
@@ -16,10 +16,11 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/intrin/pushpop.h"
#include "libc/calls/ntspawn.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
@@ -87,7 +88,8 @@ textwindows int ntspawn(
mkntenvblock(block->envvars, envp, extravar, block->buf) != -1 &&
CreateProcess(prog16, block->cmdline, opt_lpProcessAttributes,
opt_lpThreadAttributes, bInheritHandles,
dwCreationFlags | kNtCreateUnicodeEnvironment,
dwCreationFlags | kNtCreateUnicodeEnvironment |
kNtInheritParentAffinity,
block->envvars, opt_lpCurrentDirectory, lpStartupInfo,
opt_out_lpProcessInformation)) {
rc = 0;
+22 -3
View File
@@ -17,25 +17,44 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/sig.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nt/enum/ctrlevent.h"
#include "libc/nt/thread.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"
#include "libc/thread/tls.h"
#include "libc/thread/tls2.h"
textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
struct CosmoTib tib;
struct StackFrame *fr;
// win32 spawns a thread on its own just to deliver sigint
// TODO(jart): make signal code lockless so we can delete!
if (__tls_enabled && !__get_tls_win32()) {
bzero(&tib, sizeof(tib));
tib.tib_self = &tib;
tib.tib_self2 = &tib;
atomic_store_explicit(&tib.tib_tid, GetCurrentThreadId(),
memory_order_relaxed);
__set_tls_win32(&tib);
}
STRACE("__onntconsoleevent(%u)", dwCtrlType);
switch (dwCtrlType) {
case kNtCtrlCEvent:
__sig_add(SIGINT, SI_KERNEL);
__sig_add(0, SIGINT, SI_KERNEL);
return true;
case kNtCtrlBreakEvent:
__sig_add(SIGQUIT, SI_KERNEL);
__sig_add(0, SIGQUIT, SI_KERNEL);
return true;
case kNtCtrlCloseEvent:
case kNtCtrlLogoffEvent: // only received by services
case kNtCtrlShutdownEvent: // only received by services
__sig_add(SIGHUP, SI_KERNEL);
__sig_add(0, SIGHUP, SI_KERNEL);
return true;
default:
return false;
+1 -1
View File
@@ -53,7 +53,7 @@ static textwindows int sys_open_nt_console(int dirfd,
-1) {
g_fds.p[fd].extra = sys_open_nt_impl(dirfd, mp->conout,
(flags & ~O_ACCMODE) | O_WRONLY, mode);
assert(g_fds.p[fd].extra != -1);
_npassert(g_fds.p[fd].extra != -1);
} else {
return -1;
}
+2 -1
View File
@@ -133,7 +133,8 @@
* @raise ENOENT if `file` doesn't exist when `O_CREAT` isn't in `flags`
* @raise ENOENT if `file` points to a string that's empty
* @raise ENOMEM if insufficient memory was available
* @raise EMFILE if `RLIMIT_NOFILE` has been reached
* @raise EMFILE if process `RLIMIT_NOFILE` has been reached
* @raise ENFILE if system-wide file limit has been reached
* @raise EOPNOTSUPP if `file` names a named socket
* @raise EFAULT if `file` points to invalid memory
* @raise ETXTBSY if writing is requested on `file` that's being executed
+5 -2
View File
@@ -556,6 +556,7 @@ static const uint16_t kPledgeStdio[] = {
__NR_linux_prlimit | STDIO, //
__NR_linux_sched_getaffinity, //
__NR_linux_sched_setaffinity, //
__NR_linux_sigtimedwait, //
};
static const uint16_t kPledgeFlock[] = {
@@ -1255,16 +1256,18 @@ static privileged void AllowIoctlTty(struct Filter *f) {
// - TCP_FASTOPEN (0x17)
// - TCP_FASTOPEN_CONNECT (0x1e)
// - IPV6_V6ONLY (0x1a)
// - TCP_QUICKACK (0x0c)
//
static privileged void AllowSetsockoptRestrict(struct Filter *f) {
static const struct sock_filter fragment[] = {
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_setsockopt, 0, 24),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_setsockopt, 0, 25),
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 41, 3, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 2, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 1, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 0, 18),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 0, 19),
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0c, 16, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x1a, 15, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 14, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0f, 13, 0),
+1 -1
View File
@@ -44,7 +44,7 @@ int sys_fadvise_netbsd(int, int, int64_t, int64_t, int) asm("sys_fadvise");
* @returnserrno
* @threadsafe
*/
errno_t posix_fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
errno_t posix_fadvise(int fd, int64_t offset, int64_t len, int advice) {
int rc, e = errno;
if (IsLinux()) {
rc = sys_fadvise(fd, offset, len, advice);
+2 -7
View File
@@ -129,12 +129,7 @@ static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
ssize_t rc;
rc = Preadv(fd, iov, iovlen, off);
#if defined(SYSDEBUG) && _DATATRACE
if (UNLIKELY(__strace > 0)) {
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
}
#endif
STRACE("preadv(%d, [%s], %d, %'ld) → %'ld% m", fd,
DescribeIovec(rc, iov, iovlen), iovlen, off, rc);
return rc;
}
+2 -7
View File
@@ -135,12 +135,7 @@ static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
ssize_t rc;
rc = Pwritev(fd, iov, iovlen, off);
#if defined(SYSDEBUG) && _DATATRACE
if (UNLIKELY(__strace > 0)) {
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
}
#endif
STRACE("pwritev(%d, %s, %d, %'ld) → %'ld% m", fd,
DescribeIovec(rc != -1 ? rc : -2, iov, iovlen), iovlen, off, rc);
return rc;
}
+4 -4
View File
@@ -18,13 +18,13 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/sig.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/thread/tls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/internal.h"
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"
#include "libc/thread/tls.h"
#include "libc/thread/xnu.internal.h"
static textwindows inline bool HasWorkingConsole(void) {
@@ -59,7 +59,7 @@ static noubsan void RaiseSigFpe(void) {
* @asyncsignalsafe
*/
int raise(int sig) {
int rc, event;
int rc, tid, event;
STRACE("raise(%G) → ...", sig);
if (sig == SIGTRAP) {
DebugBreak();
@@ -67,7 +67,7 @@ int raise(int sig) {
} else if (sig == SIGFPE) {
RaiseSigFpe();
rc = 0;
} else if (!IsWindows()) {
} else if (!IsWindows() && !IsMetal()) {
rc = sys_tkill(gettid(), sig, 0);
} else {
rc = __sig_raise(sig, SI_TKILL);
-2
View File
@@ -16,7 +16,6 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
@@ -52,7 +51,6 @@ ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
(bytes = __zipos_notat(dirfd, path)) == -1) {
STRACE("TODO: zipos support for readlinkat");
} else if (!IsWindows()) {
assert(bufsiz);
bytes = sys_readlinkat(dirfd, path, buf, bufsiz);
} else {
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
+2 -12
View File
@@ -73,17 +73,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
rc = einval();
}
#if defined(SYSDEBUG) && _DATATRACE
if (UNLIKELY(__strace > 0)) {
if (rc == -1 && errno == EFAULT) {
STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
} else {
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
kprintf("], %d) → %'ld% m\n", iovlen, rc);
}
}
#endif
STRACE("readv(%d, [%s], %d) → %'ld% m", fd, DescribeIovec(rc, iov, iovlen),
iovlen, rc);
return rc;
}
+1 -1
View File
@@ -181,7 +181,7 @@ skip_readlink:
continue;
}
k = rc;
assert(k <= p);
_npassert(k <= p);
if (k==p)
goto toolong;
if (!k) {
+4 -1
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sched-sysv.internal.h"
#include "libc/calls/struct/cpuset.h"
@@ -32,7 +33,7 @@ static dontinline textwindows int sys_sched_setaffinity_nt(
int rc;
int64_t h, closeme = -1;
if (!pid /* || pid == getpid() */) {
if (!pid || pid == getpid()) {
h = GetCurrentProcess();
} else if (__isfdkind(pid, kFdProcess)) {
h = g_fds.p[pid].handle;
@@ -59,6 +60,8 @@ static dontinline textwindows int sys_sched_setaffinity_nt(
/**
* Asks kernel to only schedule process on particular CPUs.
*
* Affinity masks are inherited across fork() and execve() boundaries.
*
* @param pid is the process or process id (or 0 for caller)
* @param size is bytes in bitset, which should be `sizeof(cpuset_t)`
* @return 0 on success, or -1 w/ errno
+1
View File
@@ -29,6 +29,7 @@
*
* @return 0 on success, or -1 w/ errno
* @raise ENOSYS on XNU, Windows, OpenBSD
* @vforksafe
*/
int sched_setparam(int pid, const struct sched_param *param) {
int rc, policy;
+1
View File
@@ -91,6 +91,7 @@
* @raise EINVAL if `param` is NULL
* @raise EINVAL if `policy` is invalid
* @raise EINVAL if `param` has value out of ranges defined by `policy`
* @vforksafe
*/
int sched_setscheduler(int pid, int policy, const struct sched_param *param) {
int rc, old;
+2 -2
View File
@@ -17,15 +17,15 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
/**
* Sets user id of current process for file system ops.
* @return previous filesystem gid
*/
int setfsgid(int gid) {
int setfsgid(unsigned gid) {
int rc;
if (IsLinux()) {
rc = sys_setfsgid(gid);
+2 -2
View File
@@ -17,15 +17,15 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
/**
* Sets user id of current process for file system ops.
* @return previous filesystem uid
*/
int setfsuid(int uid) {
int setfsuid(unsigned uid) {
int rc;
if (IsLinux()) {
rc = sys_setfsuid(uid);
+2 -2
View File
@@ -17,9 +17,9 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
/**
* Sets group id of current process.
@@ -28,7 +28,7 @@
* @raise EINVAL if gid not in legal range
* @raise EPERM if lack privileges
*/
int setgid(int gid) {
int setgid(unsigned gid) {
int rc;
if (IsWindows() && gid == getgid()) {
rc = 0;
+2 -2
View File
@@ -19,13 +19,13 @@
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/sig.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/strace.internal.h"
#include "libc/log/check.h"
#include "libc/math.h"
#include "libc/nexgen32e/nexgen32e.h"
@@ -68,7 +68,7 @@ textwindows void _check_sigalrm(void) {
now = nowl();
elapsed = now - __lastalrm;
if (elapsed > __interval) {
__sig_add(SIGALRM, SI_TIMER);
__sig_add(0, SIGALRM, SI_TIMER);
if (__singleshot) {
__hastimer = false;
} else {
+50 -27
View File
@@ -16,37 +16,60 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/intrin/safemacros.internal.h"
#include "libc/calls/kntprioritycombos.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/nt/enum/processaccess.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thread.h"
#include "libc/sysv/consts/prio.h"
#include "libc/sysv/errfuns.h"
static textwindows struct NtPriorityCombo findntprio(int nice) {
size_t l, r, m;
l = 0;
r = kNtPriorityCombosLen;
while (l < r) {
m = (l + r) >> 1;
if (kNtPriorityCombos[m].nice > nice) {
r = m;
} else {
l = m + 1;
}
}
return kNtPriorityCombos[max(0, l - 1)];
}
textwindows int sys_setpriority_nt(int nice) {
textwindows int sys_setpriority_nt(int which, unsigned pid, int nice) {
int rc;
uint32_t tier;
struct NtPriorityCombo p;
p = findntprio(nice);
tier = 1 << (p.lg2tier - 1);
if (SetPriorityClass(GetCurrentProcess(), tier) &&
SetThreadPriority(GetCurrentThread(), p.wut)) {
return p.nice;
} else {
return __winerr();
int64_t h, closeme = -1;
if (which != PRIO_PROCESS) {
return einval();
}
if (!pid || pid == getpid()) {
h = GetCurrentProcess();
} else if (__isfdkind(pid, kFdProcess)) {
h = g_fds.p[pid].handle;
} else {
h = OpenProcess(kNtProcessSetInformation | kNtProcessQueryInformation,
false, pid);
if (!h) return __winerr();
closeme = h;
}
if (nice <= -15) {
tier = kNtRealtimePriorityClass;
} else if (nice <= -9) {
tier = kNtHighPriorityClass;
} else if (nice <= -3) {
tier = kNtAboveNormalPriorityClass;
} else if (nice <= 3) {
tier = kNtNormalPriorityClass;
} else if (nice <= 12) {
tier = kNtBelowNormalPriorityClass;
} else {
tier = kNtIdlePriorityClass;
}
if (SetPriorityClass(h, tier)) {
rc = 0;
} else {
rc = __winerr();
}
if (closeme != -1) {
CloseHandle(closeme);
}
return rc;
}
+23 -7
View File
@@ -20,22 +20,38 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
/**
* Sets nice value of thing.
*
* @param which can be PRIO_PROCESS, PRIO_PGRP, PRIO_USER
* On Windows, there's only six priority classes. We define them as -16
* (realtime), -10 (high), -5 (above), 0 (normal), 5 (below), 15 (idle)
* which are the only values that'll roundtrip getpriority/setpriority.
*
* @param which can be one of:
* - `PRIO_PROCESS` is supported universally
* - `PRIO_PGRP` is supported on unix
* - `PRIO_USER` is supported on unix
* @param who is the pid, pgid, or uid, 0 meaning current
* @param value ∈ [-NZERO,NZERO) which is clamped automatically
* @return 0 on success or -1 w/ errno
* @error EACCES if lower that RLIMIT_NICE
* @error EACCES on Linux without CAP_SYS_NICE
* @see getpriority(), nice()
* @return 0 on success, or -1 w/ errno
* @raise EINVAL if `which` was invalid or unsupported
* @error EACCES if `value` lower that `RLIMIT_NICE`
* @error EACCES on Linux without `CAP_SYS_NICE`
* @raise EPERM if access to process was denied
* @raise ESRCH if the process didn't exist
* @see getpriority()
*/
int setpriority(int which, unsigned who, int value) {
int rc;
if (!IsWindows()) {
return sys_setpriority(which, who, value);
rc = sys_setpriority(which, who, value);
} else {
return sys_getsetpriority_nt(which, who, value, sys_setpriority_nt);
rc = sys_setpriority_nt(which, who, value);
}
STRACE("setpriority(%s, %u, %d) → %d% m", DescribeWhichPrio(which), who,
value, rc);
return rc;
}
+2 -2
View File
@@ -17,9 +17,9 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
/**
* Sets user id of current process.
@@ -30,7 +30,7 @@
* @raise EAGAIN change would cause `RLIMIT_NPROC` to be exceeded
* @raise EPERM if lack privileges
*/
int setuid(int uid) {
int setuid(unsigned uid) {
int rc;
if (IsWindows() && uid == getuid()) {
rc = 0;
+7 -4
View File
@@ -1,9 +1,10 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
#include "libc/atomic.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/ucontext.h"
#define __SIG_QUEUE_LENGTH 8
#define __SIG_QUEUE_LENGTH 32
#define __SIG_POLLING_INTERVAL_MS 50
#define __SIG_LOGGING_INTERVAL_MS 1700
@@ -13,26 +14,28 @@ COSMOPOLITAN_C_START_
struct Signal {
struct Signal *next;
bool used;
int tid;
int sig;
int si_code;
};
struct Signals {
sigset_t mask;
uint64_t sigmask; /* only if tls is disabled */
struct Signal *queue;
struct Signal mem[__SIG_QUEUE_LENGTH];
};
extern long __sig_count;
extern struct Signals __sig;
extern atomic_long __sig_count;
bool __sig_check(bool) hidden;
bool __sig_handle(bool, int, int, ucontext_t *) hidden;
int __sig_add(int, int) hidden;
int __sig_add(int, int, int) hidden;
int __sig_mask(int, const sigset_t *, sigset_t *) hidden;
int __sig_raise(int, int) hidden;
void __sig_check_ignore(const int, const unsigned) hidden;
void __sig_pending(sigset_t *) hidden;
int __sig_is_applicable(struct Signal *) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+10 -10
View File
@@ -90,23 +90,23 @@ void __sigenter_openbsd(int, void *, void *) hidden;
static void sigaction_cosmo2native(union metasigaction *sa) {
if (!sa) return;
switch (__hostos) {
case LINUX:
case _HOSTLINUX:
SWITCHEROO(sa->cosmo, sa->linux, sa_handler, sa_flags, sa_restorer,
sa_mask);
break;
case XNU:
case _HOSTXNU:
SWITCHEROO(sa->cosmo, sa->xnu_in, sa_handler, sa_flags, sa_restorer,
sa_mask);
break;
case FREEBSD:
case _HOSTFREEBSD:
SWITCHEROO(sa->cosmo, sa->freebsd, sa_handler, sa_flags, sa_flags,
sa_mask);
break;
case OPENBSD:
case _HOSTOPENBSD:
SWITCHEROO(sa->cosmo, sa->openbsd, sa_handler, sa_flags, sa_flags,
sa_mask);
break;
case NETBSD:
case _HOSTNETBSD:
SWITCHEROO(sa->cosmo, sa->netbsd, sa_handler, sa_flags, sa_flags,
sa_mask);
break;
@@ -118,23 +118,23 @@ static void sigaction_cosmo2native(union metasigaction *sa) {
static void sigaction_native2cosmo(union metasigaction *sa) {
if (!sa) return;
switch (__hostos) {
case LINUX:
case _HOSTLINUX:
SWITCHEROO(sa->linux, sa->cosmo, sa_handler, sa_flags, sa_restorer,
sa_mask);
break;
case XNU:
case _HOSTXNU:
SWITCHEROO(sa->xnu_out, sa->cosmo, sa_handler, sa_flags, sa_flags,
sa_mask);
break;
case FREEBSD:
case _HOSTFREEBSD:
SWITCHEROO(sa->freebsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
sa_mask);
break;
case OPENBSD:
case _HOSTOPENBSD:
SWITCHEROO(sa->openbsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
sa_mask);
break;
case NETBSD:
case _HOSTNETBSD:
SWITCHEROO(sa->netbsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
sa_mask);
break;
+6 -1
View File
@@ -16,7 +16,6 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/intrin/strace.internal.h"
#include "libc/calls/struct/metasigaltstack.h"
#include "libc/calls/struct/sigaltstack.h"
#include "libc/calls/struct/sigaltstack.internal.h"
@@ -24,6 +23,8 @@
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/consts/ss.h"
#include "libc/sysv/errfuns.h"
static void sigaltstack2bsd(struct sigaltstack_bsd *bsd,
@@ -76,6 +77,8 @@ static void sigaltstack2linux(struct sigaltstack *linux,
* @param neu if non-null will install new signal alt stack
* @param old if non-null will receive current signal alt stack
* @return 0 on success, or -1 w/ errno
* @raise EFAULT if bad memory was supplied
* @raise ENOMEM if `neu->ss_size` is less than `MINSIGSTKSZ`
*/
int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
int rc;
@@ -86,6 +89,8 @@ int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
(neu && (__asan_check(neu, sizeof(*neu)).kind ||
__asan_check(neu->ss_sp, neu->ss_size).kind)))) {
rc = efault();
} else if (neu && neu->ss_size < MINSIGSTKSZ) {
rc = enomem();
} else if (IsLinux() || IsBsd()) {
if (IsLinux()) {
a = neu;
+2 -2
View File
@@ -21,10 +21,10 @@
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/enum/wait.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
@@ -65,5 +65,5 @@ void _check_sigchld(void) {
__fds_lock();
g_fds.p[pids[i]].zombie = true;
__fds_unlock();
__sig_add(SIGCHLD, CLD_EXITED);
__sig_add(0, SIGCHLD, CLD_EXITED);
}
+1 -1
View File
@@ -18,4 +18,4 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/sig.internal.h"
long __sig_count;
atomic_long __sig_count;
+2 -10
View File
@@ -22,6 +22,7 @@
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo-freebsd.internal.h"
#include "libc/calls/struct/siginfo-meta.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/ucontext-freebsd.internal.h"
#include "libc/calls/ucontext.h"
@@ -75,16 +76,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
g.uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
__repmovsb(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
g.si.si_signo = freebsdinfo->si_signo;
g.si.si_errno = freebsdinfo->si_errno;
g.si.si_code = freebsdinfo->si_code;
if (freebsdinfo->si_pid) {
g.si.si_pid = freebsdinfo->si_pid;
g.si.si_uid = freebsdinfo->si_uid;
} else {
g.si.si_addr = (void *)freebsdinfo->si_addr;
}
g.si.si_value = freebsdinfo->si_value;
__siginfo2cosmo(&g.si, (void *)freebsdinfo);
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc);
ctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp;
ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
+2 -7
View File
@@ -21,6 +21,7 @@
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo-meta.internal.h"
#include "libc/calls/struct/siginfo-netbsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/ucontext-netbsd.internal.h"
@@ -43,13 +44,7 @@ privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
__repstosb(&uc, 0, sizeof(uc));
__repstosb(&si2, 0, sizeof(si2));
si2.si_signo = si->si_signo;
si2.si_code = si->si_code;
si2.si_errno = si->si_errno;
si2.si_pid = si->si_pid;
si2.si_uid = si->si_uid;
si2.si_value = si->si_value;
__siginfo2cosmo(&si2, (void *)si);
uc.uc_mcontext.fpregs = &uc.__fpustate;
uc.uc_flags = ctx->uc_flags;
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
+3 -11
View File
@@ -21,6 +21,7 @@
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo-meta.internal.h"
#include "libc/calls/struct/siginfo-openbsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/ucontext-openbsd.internal.h"
@@ -44,17 +45,8 @@ privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
__repstosb(&g, 0, sizeof(g));
g.si.si_signo = openbsdinfo->si_signo;
g.si.si_code = openbsdinfo->si_code;
g.si.si_errno = openbsdinfo->si_errno;
if (openbsdinfo->si_pid) {
g.si.si_pid = openbsdinfo->si_pid;
g.si.si_uid = openbsdinfo->si_uid;
} else {
g.si.si_addr = (void *)openbsdinfo->si_addr;
}
g.si.si_value = openbsdinfo->si_value;
__repstosb(&g.uc, 0, sizeof(g.uc));
__siginfo2cosmo(&g.si, (void *)openbsdinfo);
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
__repmovsb(&g.uc.uc_sigmask, &ctx->sc_mask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->sc_mask)));
+2 -10
View File
@@ -21,6 +21,7 @@
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/metasigaltstack.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo-meta.internal.h"
#include "libc/calls/struct/siginfo-xnu.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/ucontext.h"
@@ -492,16 +493,7 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
}
}
if (xnuinfo) {
g.si.si_signo = xnuinfo->si_signo;
g.si.si_errno = xnuinfo->si_errno;
g.si.si_code = xnuinfo->si_code;
if (xnuinfo->si_pid) {
g.si.si_pid = xnuinfo->si_pid;
g.si.si_uid = xnuinfo->si_uid;
} else {
g.si.si_addr = (void *)xnuinfo->si_addr;
}
g.si.si_value = xnuinfo->si_value;
__siginfo2cosmo(&g.si, (void *)xnuinfo);
}
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc);
if (xnuctx) {
+106
View File
@@ -0,0 +1,106 @@
/*-*- 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/siginfo-meta.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/dce.h"
#include "libc/sysv/consts/sig.h"
privileged void __siginfo2cosmo(struct siginfo *si,
const union siginfo_meta *m) {
void *si_addr;
int32_t si_signo;
int32_t si_errno;
int32_t si_code;
int32_t si_pid;
int32_t si_uid;
int32_t si_status;
int32_t si_timerid;
int32_t si_overrun;
union sigval si_value;
if (IsLinux()) {
*si = m->linux;
return;
} else if (IsFreebsd()) {
si_signo = m->freebsd.si_signo;
si_errno = m->freebsd.si_errno;
si_code = m->freebsd.si_code;
si_pid = m->freebsd.si_pid;
si_uid = m->freebsd.si_uid;
si_status = m->freebsd.si_status;
si_timerid = m->freebsd.si_timerid;
si_overrun = m->freebsd.si_overrun;
si_addr = m->freebsd.si_addr;
si_value = m->freebsd.si_value;
} else if (IsXnu()) {
si_signo = m->xnu.si_signo;
si_errno = m->xnu.si_errno;
si_code = m->xnu.si_code;
si_pid = m->xnu.si_pid;
si_uid = m->xnu.si_uid;
si_status = m->xnu.si_status;
si_timerid = 0;
si_overrun = 0;
si_addr = m->xnu.si_addr;
si_value = m->xnu.si_value;
} else if (IsOpenbsd()) {
si_signo = m->openbsd.si_signo;
si_errno = m->openbsd.si_errno;
si_code = m->openbsd.si_code;
si_pid = m->openbsd.si_pid;
si_uid = m->openbsd.si_uid;
si_status = m->openbsd.si_status;
si_timerid = 0;
si_overrun = 0;
si_addr = m->openbsd.si_addr;
si_value = m->openbsd.si_value;
} else if (IsNetbsd()) {
si_signo = m->netbsd.si_signo;
si_errno = m->netbsd.si_errno;
si_code = m->netbsd.si_code;
si_pid = m->netbsd.si_pid;
si_uid = m->netbsd.si_uid;
si_status = m->netbsd.si_status;
si_timerid = 0;
si_overrun = 0;
si_addr = m->netbsd.si_addr;
si_value = m->netbsd.si_value;
} else {
notpossible;
}
*si = (struct siginfo){0};
si->si_signo = si_signo;
si->si_errno = si_errno;
si->si_code = si_code;
si->si_value = si_value;
if (si_signo == SIGILL || //
si_signo == SIGFPE || //
si_signo == SIGSEGV || //
si_signo == SIGBUS || //
si_signo == SIGTRAP) {
si->si_addr = si_addr;
} else if (si_signo == SIGALRM) {
si->si_timerid = si_timerid;
si->si_overrun = si_overrun;
} else {
si->si_pid = si_pid;
si->si_uid = si_uid;
}
}
-2
View File
@@ -19,8 +19,6 @@
#include "libc/calls/state.internal.h"
#include "libc/thread/thread.h"
static pthread_mutex_t __sig_lock_obj;
void(__sig_lock)(void) {
pthread_mutex_lock(&__sig_lock_obj);
}
+22
View File
@@ -0,0 +1,22 @@
/*-*- 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/state.internal.h"
#include "libc/thread/thread.h"
pthread_mutex_t __sig_lock_obj;
+16 -9
View File
@@ -17,37 +17,44 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/sig.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Determines the blocked pending signals
*
* @param pending is where the bitset of pending signals is returned,
* may not be NULL.
* @return -1 w/ EFAULT
* which may not be null
* @return 0 on success, or -1 w/ errno
* @raise EFAULT if `pending` points to invalid memory
* @asyncsignalsafe
*/
int sigpending(sigset_t *pending) {
int rc;
if (IsAsan() && !__asan_is_valid(pending, sizeof(*pending))) {
if (!pending || (IsAsan() && !__asan_is_valid(pending, sizeof(*pending)))) {
rc = efault();
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
// 128 signals on NetBSD and FreeBSD, 64 on Linux, 32 on OpenBSD and XNU
rc = sys_sigpending(pending, 8);
// 128 signals on NetBSD and FreeBSD, 64 on Linux, 32 on OpenBSD and XNU.
// OpenBSD passes signal sets in words rather than pointers
if (IsOpenbsd()) {
pending->__bits[0] = (unsigned)rc;
rc = 0;
} else if (IsXnu()) {
pending->__bits[0] &= 0xFFFFFFFF;
}
if (IsLinux() || IsOpenbsd() || IsXnu()) {
pending->__bits[1] = 0;
// only modify memory on success
if (!rc) {
// clear unsupported bits
if (IsXnu()) {
pending->__bits[0] &= 0xFFFFFFFF;
}
if (IsLinux() || IsOpenbsd() || IsXnu()) {
pending->__bits[1] = 0;
}
}
} else if (IsWindows()) {
sigemptyset(pending);
+2
View File
@@ -43,6 +43,8 @@
* @param set is the new mask content (optional)
* @param oldset will receive the old mask (optional) and can't overlap
* @return 0 on success, or -1 w/ errno
* @raise EFAULT if `set` or `oldset` is bad memory
* @raise EINVAL if `how` is invalid
* @asyncsignalsafe
* @restartable
* @vforksafe
+75
View File
@@ -0,0 +1,75 @@
/*-*- 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/asan.internal.h"
#include "libc/calls/sigtimedwait.h"
#include "libc/calls/sigtimedwait.internal.h"
#include "libc/calls/struct/siginfo.internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
/**
* Waits for signal synchronously, w/ timeout.
*
* @param set is signals for which we'll be waiting
* @param info if not null shall receive info about signal
* @param timeout is relative deadline and null means wait forever
* @return signal number on success, or -1 w/ errno
* @raise EINTR if an asynchronous signal was delivered instead
* @raise EINVAL if nanoseconds parameter was out of range
* @raise EAGAIN if deadline expired
* @raise ENOSYS on Windows, XNU, OpenBSD, Metal
* @raise EFAULT if invalid memory was supplied
*/
int sigtimedwait(const sigset_t *set, siginfo_t *info,
const struct timespec *timeout) {
int rc;
char strsig[15];
struct timespec ts;
union siginfo_meta si = {0};
if (IsAsan() && (!__asan_is_valid(set, sizeof(*set)) ||
(info && !__asan_is_valid(info, sizeof(*info))) ||
(timeout && !__asan_is_valid_timespec(timeout)))) {
rc = efault();
} else if (IsLinux() || IsFreebsd() || IsNetbsd()) {
if (timeout) {
// 1. Linux needs its size parameter
// 2. NetBSD modifies timeout argument
ts = *timeout;
rc = sys_sigtimedwait(set, &si, &ts, 8);
} else {
rc = sys_sigtimedwait(set, &si, 0, 8);
}
if (rc != -1 && info) {
__siginfo2cosmo(info, &si);
}
} else {
rc = enosys();
}
STRACE("sigtimedwait(%s, [%s], %s) → %s% m", DescribeSigset(0, set),
DescribeSiginfo(rc, info), DescribeTimespec(0, timeout),
strsignal_r(rc, strsig));
return rc;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_H_
#define COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_H_
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int sigtimedwait(const sigset_t *, siginfo_t *, const struct timespec *);
int sigwaitinfo(const sigset_t *, siginfo_t *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_H_ */
+14
View File
@@ -0,0 +1,14 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_INTERNAL_H_
#include "libc/calls/struct/siginfo-meta.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int sys_sigtimedwait(const sigset_t *, union siginfo_meta *,
const struct timespec *, size_t) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_INTERNAL_H_ */
+33
View File
@@ -0,0 +1,33 @@
/*-*- 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/sigtimedwait.h"
/**
* Waits for signal synchronously.
*
* @param set is signals for which we'll be waiting
* @param info if not null shall receive info about signal
* @return signal number on success, or -1 w/ errno
* @raise EINTR if an asynchronous signal was delivered instead
* @raise ENOSYS on OpenBSD, XNU, and Windows
* @see sigtimedwait()
*/
int sigwaitinfo(const sigset_t *mask, siginfo_t *si) {
return sigtimedwait(mask, si, 0);
}
+4 -2
View File
@@ -19,17 +19,18 @@
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/sig.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/winsize.h"
#include "libc/calls/struct/winsize.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/struct/consolescreenbufferinfoex.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"
#include "libc/thread/tls.h"
static struct winsize __ws;
@@ -38,6 +39,7 @@ textwindows void _check_sigwinch(struct Fd *fd) {
siginfo_t si;
struct winsize ws, old;
struct NtConsoleScreenBufferInfoEx sbinfo;
if (__tls_enabled && __threaded != gettid()) return;
old = __ws;
e = errno;
if (old.ws_row != 0xffff) {
@@ -45,7 +47,7 @@ textwindows void _check_sigwinch(struct Fd *fd) {
if (old.ws_col != ws.ws_col || old.ws_row != ws.ws_row) {
__ws = ws;
if (old.ws_col | old.ws_row) {
__sig_add(SIGWINCH, SI_KERNEL);
__sig_add(0, SIGWINCH, SI_KERNEL);
}
}
} else {
+1
View File
@@ -11,6 +11,7 @@ hidden extern bool __time_critical;
hidden extern unsigned __sighandrvas[NSIG];
hidden extern unsigned __sighandflags[NSIG];
hidden extern pthread_mutex_t __fds_lock_obj;
hidden extern pthread_mutex_t __sig_lock_obj;
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
void __fds_lock(void);
+5
View File
@@ -20,8 +20,13 @@ int closedir(DIR *);
int dirfd(DIR *);
long telldir(DIR *);
struct dirent *readdir(DIR *);
int readdir_r(DIR *, struct dirent *, struct dirent **);
void rewinddir(DIR *);
void seekdir(DIR *, long);
int alphasort(const struct dirent **, const struct dirent **);
int versionsort(const struct dirent **, const struct dirent **);
int scandir(const char *, struct dirent ***, int (*)(const struct dirent *),
int (*)(const struct dirent **, const struct dirent **));
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+13
View 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_ */
-1
View File
@@ -13,7 +13,6 @@ ssize_t pwritev(int, const struct iovec *, int, int64_t);
ssize_t readv(int, const struct iovec *, int);
ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t);
ssize_t writev(int, const struct iovec *, int);
void DescribeIov(const struct iovec *, int, ssize_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+4
View File
@@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_IOVEC_INTERNAL_H_
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/mem/alloca.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@@ -24,6 +25,9 @@ ssize_t sys_send_nt(int, const struct iovec *, size_t, uint32_t) hidden;
ssize_t sys_sendto_nt(int, const struct iovec *, size_t, uint32_t, void *,
uint32_t) hidden;
const char *DescribeIovec(char[300], ssize_t, const struct iovec *, int);
#define DescribeIovec(x, y, z) DescribeIovec(alloca(300), x, y, z)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_IOVEC_INTERNAL_H_ */
+23
View File
@@ -0,0 +1,23 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_
#include "libc/calls/struct/siginfo-freebsd.internal.h"
#include "libc/calls/struct/siginfo-netbsd.internal.h"
#include "libc/calls/struct/siginfo-openbsd.internal.h"
#include "libc/calls/struct/siginfo-xnu.internal.h"
#include "libc/calls/struct/siginfo.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
union siginfo_meta {
struct siginfo linux;
struct siginfo_xnu xnu;
struct siginfo_freebsd freebsd;
struct siginfo_openbsd openbsd;
struct siginfo_netbsd netbsd;
};
void __siginfo2cosmo(struct siginfo *, const union siginfo_meta *) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_ */
+3 -1
View File
@@ -12,11 +12,13 @@ struct siginfo {
struct {
union {
struct {
/* signals sent by kill() and sigqueue() set these */
int32_t si_pid;
uint32_t si_uid;
};
struct {
int32_t si_timerid; /* SIGALRM */
/* SIGALRM sets these */
int32_t si_timerid;
int32_t si_overrun;
};
};
+4
View File
@@ -3,6 +3,7 @@
#include "libc/calls/struct/sigaction-xnu.internal.h"
#include "libc/calls/struct/siginfo-xnu.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/mem/alloca.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@@ -10,6 +11,9 @@ int sys_sigqueueinfo(int, const siginfo_t *) hidden;
void __sigenter_xnu(void *, int, int, struct siginfo_xnu *,
struct __darwin_ucontext *) hidden;
const char *DescribeSiginfo(char[300], int, const siginfo_t *);
#define DescribeSiginfo(x, y) DescribeSiginfo(alloca(300), x, y)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_INTERNAL_H_ */
+5 -1
View File
@@ -11,10 +11,14 @@ int sigaddset(sigset_t *, int) paramsnonnull();
int sigdelset(sigset_t *, int) paramsnonnull();
int sigemptyset(sigset_t *) paramsnonnull();
int sigfillset(sigset_t *) paramsnonnull();
int sigandset(sigset_t *, const sigset_t *, const sigset_t *) paramsnonnull();
int sigorset(sigset_t *, const sigset_t *, const sigset_t *) paramsnonnull();
int sigisemptyset(const sigset_t *) paramsnonnull() nosideeffect;
int sigismember(const sigset_t *, int) paramsnonnull() nosideeffect;
int sigcountset(const sigset_t *) paramsnonnull() nosideeffect;
int sigprocmask(int, const sigset_t *, sigset_t *);
int sigsuspend(const sigset_t *);
int sigpending(sigset_t *) paramsnonnull() nosideeffect;
int sigpending(sigset_t *);
int pthread_sigmask(int, const sigset_t *, sigset_t *);
COSMOPOLITAN_C_END_
+4 -5
View File
@@ -11,11 +11,10 @@
#define st_mtime_nsec st_mtim.tv_nsec
#define st_ctime_nsec st_ctim.tv_nsec
#define st_atimensec st_atim.tv_nsec
#define st_mtimensec st_mtim.tv_nsec
#define st_ctimensec st_ctim.tv_nsec
#define st_birthtime st_birthtim.tv_sec
#define st_birthtimensec st_birthtim.tv_nsec
#define st_atimensec st_atim.tv_nsec
#define st_mtimensec st_mtim.tv_nsec
#define st_ctimensec st_ctim.tv_nsec
#define st_birthtime st_birthtim.tv_sec
#define st_file_attributes st_flags
+3 -4
View File
@@ -16,12 +16,11 @@ int sys_fchmodat_nt(int, const char *, uint32_t, int) hidden;
int sys_fcntl_nt(int, int, uintptr_t) hidden;
int sys_fdatasync_nt(int) hidden;
int sys_flock_nt(int, int) hidden;
int sys_fork_nt(void) hidden;
int sys_fork_nt(uint32_t) hidden;
int sys_ftruncate_nt(int64_t, uint64_t) hidden;
int sys_getloadavg_nt(double *, int) hidden;
int sys_getppid_nt(void) hidden;
int sys_getpriority_nt(int) hidden;
int sys_getsetpriority_nt(int, int, int, int (*)(int));
int sys_getpriority_nt(int, unsigned) hidden;
int sys_kill_nt(int, int) hidden;
int sys_linkat_nt(int, const char *, int, const char *) hidden;
int sys_madvise_nt(void *, size_t, int) hidden;
@@ -31,7 +30,7 @@ int sys_open_nt(int, const char *, uint32_t, int32_t) dontdiscard hidden;
int sys_pipe_nt(int[hasatleast 2], unsigned) hidden;
int sys_renameat_nt(int, const char *, int, const char *) hidden;
int sys_sched_yield_nt(void) hidden;
int sys_setpriority_nt(int) hidden;
int sys_setpriority_nt(int, unsigned, int) hidden;
int sys_symlinkat_nt(const char *, int, const char *) hidden;
int sys_sync_nt(void) hidden;
int sys_truncate_nt(const char *, uint64_t) hidden;
Loaded 100 of 637 files, more files were not shown because too many files have changed in this diff. Show more