mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Make improvements
- Document redbean's argon2 module - Fix regressions in cthreads library - Make testlib work better with threads - Give the cthreads library lots of love - Remove some of the stdio assembly code - Implement getloadavg() across platforms - Code size optimizations for errnos, etc. - Only check for signals in main thread on Windows - Make errnos for dup2 / dup3 consistent with posix This change also fixes a bug in the argon2 module, where the NUL terminator was being included in the hash encoded ascii string. This shouldn't require any database migrations to folks who found this module and productionized it, since the argon2 library treats it as a c string.
This commit is contained in:
parent
cb67223051
commit
de5de19004
234 changed files with 1728 additions and 1993 deletions
53
ape/ape.lds
53
ape/ape.lds
|
@ -185,10 +185,12 @@
|
|||
ENTRY(_start)
|
||||
|
||||
PHDRS {
|
||||
Head PT_LOAD FLAGS(5);
|
||||
Rom PT_LOAD FLAGS(5);
|
||||
Ram PT_LOAD FLAGS(6);
|
||||
stack PT_GNU_STACK FLAGS(6);
|
||||
Head PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Rom PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Ram PT_LOAD FLAGS(PF_W|PF_R);
|
||||
Tls PT_TLS FLAGS(PF_W|PF_R);
|
||||
Bss PT_LOAD FLAGS(PF_W|PF_R);
|
||||
stack PT_GNU_STACK FLAGS(PF_W|PF_R);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
|
@ -348,20 +350,7 @@ SECTIONS {
|
|||
/*END: Read Only Data */
|
||||
} :Rom
|
||||
|
||||
.tdata . : {
|
||||
_tdata_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
_tdata_end = .;
|
||||
}
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
_tbss_end = .;
|
||||
}
|
||||
|
||||
.data . : {
|
||||
.data ALIGN(PAGESIZE) : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*)))
|
||||
/*BEGIN: NT FORK COPYING */
|
||||
|
@ -387,18 +376,29 @@ SECTIONS {
|
|||
KEEP(*(.piro.pad.data))
|
||||
KEEP(*(.dataepilogue))
|
||||
/*END: NT FORK COPYING */
|
||||
. = ALIGN(PAGESIZE);
|
||||
HIDDEN(_edata = .);
|
||||
PROVIDE_HIDDEN(edata = .);
|
||||
KEEP(*(SORT_BY_NAME(.zip.*)))
|
||||
HIDDEN(_ezip = .);
|
||||
} :Ram
|
||||
|
||||
.tdata . : {
|
||||
_tdata_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
_tdata_end = .;
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Tls
|
||||
|
||||
/*END: file content that's loaded by o/s */
|
||||
/*BEGIN: bss memory void */
|
||||
|
||||
.zip . : {
|
||||
KEEP(*(SORT_BY_NAME(.zip.*)))
|
||||
HIDDEN(_ezip = .);
|
||||
}
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
_tbss_end = .;
|
||||
} :Tls
|
||||
|
||||
/*END: file content */
|
||||
/*BEGIN: bss memory that's addressable */
|
||||
|
@ -425,7 +425,7 @@ SECTIONS {
|
|||
. = ALIGN(FRAMESIZE); /* for brk()/sbrk() allocation */
|
||||
HIDDEN(_end = .);
|
||||
PROVIDE_HIDDEN(end = .);
|
||||
}
|
||||
} :Bss
|
||||
|
||||
/*END: nt addressability guarantee */
|
||||
/*END: bsd addressability guarantee */
|
||||
|
@ -481,6 +481,9 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
|
|||
PFSTUB4(ape_elf_shnum, 0);
|
||||
PFSTUB4(ape_elf_shstrndx, 0);
|
||||
|
||||
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
|
||||
HIDDEN(_tls_size = _tbss_end - _tdata_start);
|
||||
|
||||
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
||||
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
|
||||
ROUNDDOWN(__privileged_start, PAGESIZE)));
|
||||
|
@ -496,7 +499,7 @@ HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
|
|||
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
|
||||
HIDDEN(ape_ram_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_ram_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
|
||||
HIDDEN(ape_ram_align = PAGESIZE);
|
||||
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
|
||||
|
|
|
@ -303,9 +303,9 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
MakePrompt(p);
|
||||
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
} else {
|
||||
fprintf(stderr, "%s: %s: command not found\n", argv[0], args[0]);
|
||||
}
|
||||
|
|
|
@ -8,56 +8,58 @@
|
|||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/thread/create.h"
|
||||
#include "libc/thread/self.h"
|
||||
#include "libc/thread/detach.h"
|
||||
#include "libc/thread/join.h"
|
||||
#include "libc/thread/self.h"
|
||||
#include "libc/thread/sem.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
cthread_sem_t semaphore;
|
||||
_Thread_local int test_tls = 0x12345678;
|
||||
|
||||
__thread int test_tls = 0x12345678;
|
||||
|
||||
int worker(void* arg) {
|
||||
void* p;
|
||||
arch_prctl(ARCH_GET_FS, &p);
|
||||
static void *worker(void *arg) {
|
||||
int tid;
|
||||
cthread_t self;
|
||||
cthread_sem_signal(&semaphore);
|
||||
|
||||
cthread_t self = cthread_self();
|
||||
int tid = self->tid;
|
||||
sleep(1);
|
||||
//sleep(10000);
|
||||
printf("[%p] %d -> 0x%x\n", self, tid, test_tls);
|
||||
(void)arg;
|
||||
return 4;
|
||||
self = cthread_self();
|
||||
tid = self->tid;
|
||||
printf("[%p] %d -> %#x\n", self, tid, test_tls);
|
||||
if (test_tls != 0x12345678) {
|
||||
printf(".tdata test #2 failed\n");
|
||||
}
|
||||
return (void *)4;
|
||||
}
|
||||
|
||||
int main() {
|
||||
cthread_t self = cthread_self();
|
||||
int tid = self->tid;
|
||||
printf("[%p] %d -> 0x%x\n", self, tid, test_tls);
|
||||
int rc, tid;
|
||||
void *exitcode;
|
||||
cthread_t self, thread;
|
||||
self = cthread_self();
|
||||
tid = self->tid;
|
||||
printf("[%p] %d -> %#x\n", self, tid, test_tls);
|
||||
if (test_tls != 0x12345678) {
|
||||
printf(".tdata test #1 failed\n");
|
||||
}
|
||||
cthread_sem_init(&semaphore, 0);
|
||||
|
||||
cthread_t thread;
|
||||
int rc = cthread_create(&thread, NULL, &worker, NULL);
|
||||
rc = cthread_create(&thread, NULL, &worker, NULL);
|
||||
if (rc == 0) {
|
||||
cthread_sem_wait(&semaphore, 0, NULL);
|
||||
//printf("thread created: %p\n", thread);
|
||||
sleep(1);
|
||||
printf("thread created: %p\n", thread);
|
||||
#if 1
|
||||
cthread_join(thread, &rc);
|
||||
cthread_join(thread, &exitcode);
|
||||
#else
|
||||
rc = cthread_detach(thread);
|
||||
sleep(2);
|
||||
exitcode = cthread_detach(thread);
|
||||
#endif
|
||||
cthread_sem_signal(&semaphore);
|
||||
cthread_sem_wait(&semaphore, 0, NULL);
|
||||
//printf("thread joined: %p -> %d\n", thread, rc);
|
||||
printf("thread joined: %p -> %p\n", thread, exitcode);
|
||||
} else {
|
||||
printf("ERROR: thread could not be started: %d\n", rc);
|
||||
fprintf(stderr, "ERROR: thread could not be started: %d\n", rc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
15
examples/tls.c
Normal file
15
examples/tls.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#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
|
||||
|
||||
_Thread_local int foo;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
foo = 1;
|
||||
}
|
|
@ -248,6 +248,7 @@ void sync(void);
|
|||
|
||||
int clone(int (*)(void *), void *, size_t, int, void *, int *, void *, size_t,
|
||||
int *);
|
||||
int futex(uint32_t *, int, int, const struct timespec *, uint32_t *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » formatting ─╬─│┼
|
||||
|
|
|
@ -54,7 +54,7 @@ int close(int fd) {
|
|||
} else if (fd < 0) {
|
||||
rc = einval();
|
||||
} else {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
if (__isfdkind(fd, kFdZip)) {
|
||||
rc = weaken(__zipos_close)(fd);
|
||||
} else {
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
|
@ -62,16 +62,16 @@ int close(int fd) {
|
|||
} else if (IsMetal()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
|
||||
if (__isfdkind(fd, kFdEpoll)) {
|
||||
rc = weaken(sys_close_epoll_nt)(fd);
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = weaken(sys_closesocket_nt)(g_fds.p + fd);
|
||||
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdFile ||
|
||||
g_fds.p[fd].kind == kFdConsole ||
|
||||
g_fds.p[fd].kind == kFdProcess)) {
|
||||
} else if (__isfdkind(fd, kFdFile) || //
|
||||
__isfdkind(fd, kFdConsole) || //
|
||||
__isfdkind(fd, kFdProcess)) { //
|
||||
rc = sys_close_nt(g_fds.p + fd);
|
||||
} else {
|
||||
STRACE("close(%d) unknown kind: %d", fd, g_fds.p[fd].kind);
|
||||
STRACE("close(%d) unknown kind", fd);
|
||||
rc = ebadf();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
@ -37,7 +38,7 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
|
|||
int64_t rc, proc, handle;
|
||||
|
||||
// validate the api usage
|
||||
if (oldfd < 0) return einval();
|
||||
if (oldfd < 0) return ebadf();
|
||||
if (flags & ~O_CLOEXEC) return einval();
|
||||
|
||||
_spinlock(&__fds_lock);
|
||||
|
|
|
@ -17,26 +17,35 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Duplicates file descriptor/handle.
|
||||
* Duplicates file descriptor.
|
||||
*
|
||||
* The `O_CLOEXEC` flag shall be cleared from the resulting file
|
||||
* descriptor; see dup3() to preserve it.
|
||||
*
|
||||
* @param fd remains open afterwards
|
||||
* @return some arbitrary new number for fd
|
||||
* @raise EOPNOTSUPP if zipos file
|
||||
* @raise EBADF if fd isn't open
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int dup(int fd) {
|
||||
int fd2;
|
||||
if (!IsWindows()) {
|
||||
fd2 = sys_dup(fd);
|
||||
int rc;
|
||||
if (__isfdkind(fd, kFdZip)) {
|
||||
rc = eopnotsupp();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_dup(fd);
|
||||
} else {
|
||||
fd2 = sys_dup_nt(fd, -1, 0, -1);
|
||||
rc = sys_dup_nt(fd, -1, 0, -1);
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "dup", fd, fd2);
|
||||
return fd2;
|
||||
STRACE("%s(%d) → %d% m", "dup", fd, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,27 +17,47 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Duplicates file descriptor, granting it specific number.
|
||||
*
|
||||
* The `O_CLOEXEC` flag shall be cleared from the resulting file
|
||||
* descriptor; see dup3() to preserve it.
|
||||
*
|
||||
* Unlike dup3(), the dup2() function permits oldfd and newfd to be the
|
||||
* same, in which case the only thing this function does is test if
|
||||
* oldfd is open.
|
||||
*
|
||||
* @param oldfd isn't closed afterwards
|
||||
* @param newfd if already assigned, is silently closed beforehand;
|
||||
* unless it's equal to oldfd, in which case dup2() is a no-op
|
||||
* @return new file descriptor, or -1 w/ errno
|
||||
* @raise EBADF is oldfd isn't open
|
||||
* @raise EBADF is newfd negative or too big
|
||||
* @raise EINTR if a signal handler was called
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int dup2(int oldfd, int newfd) {
|
||||
int rc;
|
||||
if (oldfd == newfd) {
|
||||
rc = newfd;
|
||||
if (__isfdkind(oldfd, kFdZip)) {
|
||||
rc = eopnotsupp();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_dup3(oldfd, newfd, 0);
|
||||
rc = sys_dup2(oldfd, newfd);
|
||||
} else if (newfd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (oldfd == newfd) {
|
||||
if (__isfdopen(oldfd)) {
|
||||
rc = newfd;
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
} else {
|
||||
rc = sys_dup_nt(oldfd, newfd, 0, -1);
|
||||
}
|
||||
|
|
|
@ -19,11 +19,18 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define F_DUP2FD 10
|
||||
#define F_DUP2FD_CLOEXEC 18
|
||||
|
||||
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
||||
static bool once, demodernize;
|
||||
int olderr, fd;
|
||||
static bool once;
|
||||
static bool demodernize;
|
||||
int olderr, how, fd;
|
||||
if (!once) {
|
||||
olderr = errno;
|
||||
fd = __sys_dup3(oldfd, newfd, flags);
|
||||
|
@ -39,5 +46,12 @@ int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
|||
} else if (!demodernize) {
|
||||
return __sys_dup3(oldfd, newfd, flags);
|
||||
}
|
||||
return __fixupnewfd(sys_dup2(oldfd, newfd), flags);
|
||||
if (oldfd == newfd) return einval();
|
||||
if (flags & ~O_CLOEXEC) return einval();
|
||||
if (IsFreebsd()) {
|
||||
how = flags & O_CLOEXEC ? F_DUP2FD_CLOEXEC : F_DUP2FD;
|
||||
return __sys_fcntl(oldfd, how, newfd);
|
||||
} else {
|
||||
return __fixupnewfd(sys_dup2(oldfd, newfd), flags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
|
@ -33,13 +34,26 @@
|
|||
* @param oldfd isn't closed afterwards
|
||||
* @param newfd if already assigned, is silently closed beforehand;
|
||||
* unless it's equal to oldfd, in which case dup2() is a no-op
|
||||
* @param flags can have O_CLOEXEC
|
||||
* @param flags may have O_CLOEXEC which is needed to preserve the
|
||||
* close-on-execve() state after file descriptor duplication
|
||||
* @return newfd on success, or -1 w/ errno
|
||||
* @raise EINVAL if flags has unsupported bits
|
||||
* @raise EINVAL if newfd equals oldfd
|
||||
* @raise EBADF is oldfd isn't open
|
||||
* @raise EBADF is newfd negative or too big
|
||||
* @raise EINTR if a signal handler was called
|
||||
* @see dup(), dup2()
|
||||
*/
|
||||
int dup3(int oldfd, int newfd, int flags) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
if (__isfdkind(oldfd, kFdZip)) {
|
||||
rc = eopnotsupp();
|
||||
} else if (oldfd == newfd) {
|
||||
rc = einval();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_dup3(oldfd, newfd, flags);
|
||||
} else if (newfd < 0) {
|
||||
rc = ebadf();
|
||||
} else {
|
||||
rc = sys_dup_nt(oldfd, newfd, flags, -1);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
_Alignas(64) int __sig_lock;
|
||||
unsigned __sighandrvas[NSIG];
|
||||
unsigned __sighandflags[NSIG];
|
||||
_Alignas(64) int __sig_lock_obj;
|
||||
|
|
71
libc/calls/getloadavg-nt.c
Normal file
71
libc/calls/getloadavg-nt.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- 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/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
|
||||
#define FT(x) (x.dwLowDateTime | (uint64_t)x.dwHighDateTime << 32)
|
||||
|
||||
static int cpus;
|
||||
static double load;
|
||||
_Alignas(64) static int lock;
|
||||
static struct NtFileTime idle1, kern1, user1;
|
||||
|
||||
textwindows int sys_getloadavg_nt(double *a, int n) {
|
||||
int i, rc;
|
||||
uint64_t elapsed, used;
|
||||
struct NtFileTime idle, kern, user;
|
||||
_spinlock(&lock);
|
||||
if (GetSystemTimes(&idle, &kern, &user)) {
|
||||
elapsed = (FT(kern) - FT(kern1)) + (FT(user) - FT(user1));
|
||||
if (elapsed) {
|
||||
used = elapsed - (FT(idle) - FT(idle1));
|
||||
load = (double)used / elapsed * cpus;
|
||||
load = MIN(MAX(load, 0), cpus * 2);
|
||||
idle1 = idle, kern1 = kern, user1 = user;
|
||||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
a[i] = load;
|
||||
}
|
||||
rc = n;
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
_spunlock(&lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static textstartup void sys_getloadavg_nt_init(void) {
|
||||
double a[3];
|
||||
if (IsWindows()) {
|
||||
load = 1;
|
||||
cpus = GetCpuCount() / 2;
|
||||
cpus = MAX(1, cpus);
|
||||
GetSystemTimes(&idle1, &kern1, &user1);
|
||||
}
|
||||
}
|
||||
|
||||
const void *const sys_getloadavg_nt_ctor[] initarray = {
|
||||
sys_getloadavg_nt_init,
|
||||
};
|
|
@ -17,24 +17,60 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sysinfo.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define CTL_VM 2
|
||||
#define VM_LOADAVG 2
|
||||
|
||||
struct loadavg {
|
||||
uint32_t ldavg[3];
|
||||
int64_t fscale;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns system load average.
|
||||
* @note work in progress
|
||||
*
|
||||
* @param a should be array of 3 doubles
|
||||
* @param n should be 3
|
||||
* @return number of items placed in `a` or -1 w/ errno
|
||||
* @raise ENOSYS on metal
|
||||
*/
|
||||
int getloadavg(double *a, int n) {
|
||||
/* cat /proc/loadavg */
|
||||
int i;
|
||||
struct sysinfo si;
|
||||
if (!n) return 0;
|
||||
if (n < 0) return einval();
|
||||
if (sysinfo(&si) == -1) return -1;
|
||||
int i, rc;
|
||||
if (n > 3) n = 3;
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i] = 1. / 65536 * si.loads[i];
|
||||
if (!n) {
|
||||
rc = 0;
|
||||
} else if (n < 0) {
|
||||
rc = einval();
|
||||
} else if (IsWindows()) {
|
||||
return sys_getloadavg_nt(a, n);
|
||||
} else if (IsLinux()) {
|
||||
struct sysinfo si;
|
||||
if ((rc = sysinfo(&si)) != -1) {
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i] = 1. / 65536 * si.loads[i];
|
||||
}
|
||||
rc = n;
|
||||
}
|
||||
} else if (IsFreebsd() || IsNetbsd() || IsOpenbsd() || IsXnu()) {
|
||||
size_t size;
|
||||
struct loadavg loadinfo;
|
||||
int mib[2] = {CTL_VM, VM_LOADAVG};
|
||||
size = sizeof(loadinfo);
|
||||
if ((rc = sysctl(mib, 2, &loadinfo, &size, 0, 0)) != -1) {
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i] = (double)loadinfo.ldavg[i] / loadinfo.fscale;
|
||||
}
|
||||
rc = n;
|
||||
}
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
return n;
|
||||
STRACE("getloadavg(%p, %d) → %d% m", a, n, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -49,9 +49,9 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
|||
!GetProcessIoCounters(me, &iocount)) {
|
||||
return __winerr();
|
||||
}
|
||||
_spinlock(&__sig_lock);
|
||||
__sig_lock();
|
||||
nsignals = __sig_count;
|
||||
_spunlock(&__sig_lock);
|
||||
__sig_unlock();
|
||||
*usage = (struct rusage){
|
||||
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
|
||||
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
|
||||
|
|
|
@ -29,35 +29,13 @@
|
|||
#include "libc/intrin/lockcmpxchgp.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
|
||||
_Alignas(64) static int rlock;
|
||||
|
||||
// return 0 on success, or tid of other owner
|
||||
static privileged inline int AcquireInterruptPollLock(void) {
|
||||
// any thread can poll for interrupts
|
||||
// but it's wasteful to have every single thread doing it
|
||||
int me, owner = 0;
|
||||
if (__threaded) {
|
||||
me = gettid();
|
||||
if (!_lockcmpxchgp(&rlock, &owner, me) && owner == me) {
|
||||
owner = 0;
|
||||
}
|
||||
}
|
||||
return owner;
|
||||
}
|
||||
|
||||
static textwindows inline void ReleaseInterruptPollLock(void) {
|
||||
int zero = 0;
|
||||
__atomic_store(&rlock, &zero, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
textwindows bool _check_interrupts(bool restartable, struct Fd *fd) {
|
||||
bool res;
|
||||
if (__time_critical) return false;
|
||||
if (AcquireInterruptPollLock()) return false;
|
||||
if (__threaded && __threaded != gettid()) return false;
|
||||
if (weaken(_check_sigalrm)) weaken(_check_sigalrm)();
|
||||
if (weaken(_check_sigchld)) weaken(_check_sigchld)();
|
||||
if (fd && weaken(_check_sigwinch)) weaken(_check_sigwinch)(fd);
|
||||
res = weaken(__sig_check) && weaken(__sig_check)(restartable);
|
||||
ReleaseInterruptPollLock();
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -1,97 +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 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/loadavg.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/pdh.h"
|
||||
#include "libc/nt/enum/securityimpersonationlevel.h"
|
||||
#include "libc/nt/enum/wt.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/events.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/pdh.h"
|
||||
#include "libc/nt/privilege.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/luid.h"
|
||||
#include "libc/nt/struct/pdhfmtcountervalue.h"
|
||||
#include "libc/nt/struct/tokenprivileges.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* @fileoverview sysinfo() on the new technology
|
||||
* @kudos Giampaolo Rodola for teaching how to do load average
|
||||
*/
|
||||
|
||||
#define LOAD_SAMPLING_INTERVAL 1 // in seconds
|
||||
|
||||
// https://github.com/torvalds/linux/blob/345671ea0f9258f410eb057b9ced9cefbbe5dc78/include/linux/sched/loadavg.h#L20-L23
|
||||
#define LOAD1F .9200444146293232478931553241
|
||||
#define LOAD5F .9834714538216174894737477501
|
||||
#define LOAD15F .9944598480048967508795473394
|
||||
|
||||
double __ntloadavg[3];
|
||||
|
||||
static void LoadavgNtPoll(int64_t hCounter, bool32 timedOut) {
|
||||
struct NtPdhFmtCountervalue c;
|
||||
if (!PdhGetFormattedCounterValue(hCounter, kNtPdhFmtDouble, 0, &c)) {
|
||||
__ntloadavg[0] = __ntloadavg[0] * LOAD1F + c.doubleValue * (1 - LOAD1F);
|
||||
__ntloadavg[1] = __ntloadavg[1] * LOAD5F + c.doubleValue * (1 - LOAD5F);
|
||||
__ntloadavg[2] = __ntloadavg[2] * LOAD15F + c.doubleValue * (1 - LOAD15F);
|
||||
} else {
|
||||
STRACE("PdhGetFormattedCounterValue(%ld) failed", hCounter);
|
||||
}
|
||||
}
|
||||
|
||||
static textstartup void LoadavgNtInit(void) {
|
||||
int64_t hQuery, hCounter, hEvent, hWaiter;
|
||||
if (!IsWindows()) return;
|
||||
STRACE("LoadavgNtInit()");
|
||||
if (PdhOpenQuery(0, 0, &hQuery)) {
|
||||
STRACE("PdhOpenQuery failed");
|
||||
return;
|
||||
}
|
||||
if (PdhAddEnglishCounter(hQuery, u"\\System\\Processor Queue Length", 0,
|
||||
&hCounter)) {
|
||||
STRACE("PdhAddEnglishCounter() failed");
|
||||
return;
|
||||
}
|
||||
if (!(hEvent = CreateEvent(0, 0, 0, u"LoadUpdateEvent"))) {
|
||||
STRACE("CreateEvent() failed");
|
||||
return;
|
||||
}
|
||||
if (PdhCollectQueryDataEx(hQuery, LOAD_SAMPLING_INTERVAL, hEvent)) {
|
||||
STRACE("PdhCollectQueryDataEx() failed");
|
||||
return;
|
||||
}
|
||||
if (!RegisterWaitForSingleObject(
|
||||
&hWaiter, hEvent, (void *)NT2SYSV(LoadavgNtPoll),
|
||||
(void *)(intptr_t)hCounter, -1, kNtWtExecutedefault)) {
|
||||
STRACE("RegisterWaitForSingleObject() failed");
|
||||
return;
|
||||
}
|
||||
LoadavgNtPoll(hCounter, 0);
|
||||
}
|
||||
|
||||
const void *const LoadavgNtCtor[] initarray = {
|
||||
LoadavgNtInit,
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_LOADAVG_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_LOADAVG_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern double __ntloadavg[3];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_LOADAVG_INTERNAL_H_ */
|
|
@ -38,7 +38,7 @@ textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
|||
int i;
|
||||
uint64_t a, b;
|
||||
if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) {
|
||||
_spinlock(&__sig_lock);
|
||||
__sig_lock();
|
||||
if (old) {
|
||||
*old = __sig.mask;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
|||
}
|
||||
__sig.mask.__bits[0] &= ~(SIGKILL | SIGSTOP);
|
||||
}
|
||||
_spunlock(&__sig_lock);
|
||||
__sig_unlock();
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
|
|
|
@ -26,6 +26,8 @@ struct Signals {
|
|||
extern struct Signals __sig; // TODO(jart): Need TLS
|
||||
extern long __sig_count;
|
||||
|
||||
void __sig_lock(void) hidden;
|
||||
void __sig_unlock(void) hidden;
|
||||
bool __sig_check(bool) hidden;
|
||||
bool __sig_handle(bool, int, int, ucontext_t *) hidden;
|
||||
int __sig_add(int, int) hidden;
|
||||
|
|
|
@ -66,7 +66,7 @@ static textwindows void __sig_free(struct Signal *mem) {
|
|||
static textwindows struct Signal *__sig_remove(void) {
|
||||
struct Signal *prev, *res;
|
||||
if (__sig.queue) {
|
||||
_spinlock(&__sig_lock);
|
||||
__sig_lock();
|
||||
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
|
||||
if (!sigismember(&__sig.mask, res->sig)) {
|
||||
if (res == __sig.queue) {
|
||||
|
@ -80,7 +80,7 @@ static textwindows struct Signal *__sig_remove(void) {
|
|||
STRACE("%G is masked", res->sig);
|
||||
}
|
||||
}
|
||||
_spunlock(&__sig_lock);
|
||||
__sig_unlock();
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ static privileged bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
STRACE("delivering %G", sig);
|
||||
|
||||
// enter the signal
|
||||
_spinlock(&__sig_lock);
|
||||
__sig_lock();
|
||||
rva = __sighandrvas[sig];
|
||||
flags = __sighandflags[sig];
|
||||
if ((~flags & SA_NODEFER) || (flags & SA_RESETHAND)) {
|
||||
|
@ -110,7 +110,7 @@ static privileged bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
// signal handler. in that case you must use SA_NODEFER.
|
||||
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
|
||||
}
|
||||
_spunlock(&__sig_lock);
|
||||
__sig_unlock();
|
||||
|
||||
// setup the somewhat expensive information args
|
||||
// only if they're requested by the user in sigaction()
|
||||
|
@ -196,9 +196,9 @@ privileged bool __sig_handle(bool restartable, int sig, int si_code,
|
|||
textwindows int __sig_raise(int sig, int si_code) {
|
||||
int rc;
|
||||
int candeliver;
|
||||
_spinlock(&__sig_lock);
|
||||
__sig_lock();
|
||||
candeliver = !sigismember(&__sig.mask, sig);
|
||||
_spunlock(&__sig_lock);
|
||||
__sig_unlock();
|
||||
switch (candeliver) {
|
||||
case 1:
|
||||
__sig_handle(false, sig, si_code, 0);
|
||||
|
@ -213,26 +213,31 @@ textwindows int __sig_raise(int sig, int si_code) {
|
|||
|
||||
/**
|
||||
* Enqueues generic signal for delivery on New Technology.
|
||||
* @return 0 if enqueued, otherwise -1 w/ errno
|
||||
* @return 0 on success, otherwise -1 w/ errno
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows int __sig_add(int sig, int si_code) {
|
||||
int rc;
|
||||
struct Signal *mem;
|
||||
if (1 <= sig && sig <= NSIG) {
|
||||
STRACE("enqueuing %G", sig);
|
||||
_spinlock(&__sig_lock);
|
||||
++__sig_count;
|
||||
if ((mem = __sig_alloc())) {
|
||||
mem->sig = sig;
|
||||
mem->si_code = si_code;
|
||||
mem->next = __sig.queue;
|
||||
__sig.queue = mem;
|
||||
__sig_lock();
|
||||
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
|
||||
STRACE("ignoring %G", sig);
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enomem();
|
||||
STRACE("enqueuing %G", sig);
|
||||
++__sig_count;
|
||||
if ((mem = __sig_alloc())) {
|
||||
mem->sig = sig;
|
||||
mem->si_code = si_code;
|
||||
mem->next = __sig.queue;
|
||||
__sig.queue = mem;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
}
|
||||
_spunlock(&__sig_lock);
|
||||
__sig_unlock();
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
@ -448,9 +449,9 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
|||
if (sig == SIGKILL || sig == SIGSTOP) {
|
||||
rc = einval();
|
||||
} else {
|
||||
_spinlock(&__sig_lock);
|
||||
__sig_lock();
|
||||
rc = __sigaction(sig, act, oldact);
|
||||
_spunlock(&__sig_lock);
|
||||
__sig_unlock();
|
||||
}
|
||||
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig,
|
||||
DescribeSigaction(buf[0], sizeof(buf[0]), 0, act),
|
||||
|
|
30
libc/calls/siglock.c
Normal file
30
libc/calls/siglock.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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/intrin/spinlock.h"
|
||||
|
||||
void __sig_lock(void) {
|
||||
_spinlock(&__sig_lock_obj);
|
||||
}
|
||||
|
||||
void __sig_unlock(void) {
|
||||
_spunlock(&__sig_lock_obj);
|
||||
}
|
|
@ -5,7 +5,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
hidden extern int __vforked;
|
||||
hidden extern int __fds_lock;
|
||||
hidden extern int __sig_lock;
|
||||
hidden extern int __sig_lock_obj;
|
||||
hidden extern bool __time_critical;
|
||||
hidden extern unsigned __sighandrvas[NSIG];
|
||||
hidden extern unsigned __sighandflags[NSIG];
|
||||
|
|
|
@ -18,6 +18,7 @@ int sys_fdatasync_nt(int) hidden;
|
|||
int sys_flock_nt(int, int) hidden;
|
||||
int sys_fork_nt(void) 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));
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/loadavg.internal.h"
|
||||
#include "libc/calls/struct/sysinfo.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
|
@ -33,9 +32,6 @@ textwindows int sys_sysinfo_nt(struct sysinfo *info) {
|
|||
info->totalram = memstat.ullTotalPhys;
|
||||
info->freeram = memstat.ullAvailPhys;
|
||||
info->procs = sysinfo.dwNumberOfProcessors;
|
||||
info->loads[0] = __ntloadavg[0] * 65536;
|
||||
info->loads[1] = __ntloadavg[1] * 65536;
|
||||
info->loads[2] = __ntloadavg[2] * 65536;
|
||||
info->mem_unit = 1;
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 │
|
||||
│ 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 │
|
||||
|
@ -18,8 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/setjmp.internal.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
@ -36,10 +34,6 @@ privileged wontreturn void _Exit1(int rc) {
|
|||
jmp_buf *jb;
|
||||
struct WinThread *wt;
|
||||
STRACE("_Exit1(%d)", rc);
|
||||
if (__tls_enabled) {
|
||||
jb = (jmp_buf *)(__get_tls() + 0x08);
|
||||
longjmp(*jb, rc);
|
||||
}
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
asm volatile("xor\t%%r10d,%%r10d\n\t"
|
||||
"syscall"
|
||||
|
|
|
@ -25,7 +25,12 @@
|
|||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/sysv/consts/nrlinux.h"
|
||||
|
||||
#define __NR_sysarch 0x000000a5
|
||||
#define __NR_sysarch 0x000000a5 // freebsd+netbsd
|
||||
#define AMD64_SET_GSBASE 131 // freebsd
|
||||
#define AMD64_SET_FSBASE 129 // freebsd
|
||||
#define X86_SET_GSBASE 16 // netbsd
|
||||
#define X86_SET_FSBASE 17 // netbsd
|
||||
|
||||
#define __NR___set_tcb 0x00000149
|
||||
#define __NR__lwp_setprivate 0x0000013d
|
||||
#define __NR_thread_fast_set_cthread_self 0x03000003
|
||||
|
@ -37,8 +42,6 @@
|
|||
*
|
||||
* offset size description
|
||||
* 0x0000 0x08 linear address pointer
|
||||
* 0x0008 0x08 jmp_buf *exiter
|
||||
* 0x0010 0x04 exit code
|
||||
* 0x0030 0x08 linear address pointer
|
||||
* 0x0038 0x04 tid
|
||||
* 0x003c 0x04 errno
|
||||
|
@ -47,8 +50,6 @@
|
|||
privileged void *__initialize_tls(char tib[64]) {
|
||||
if (tib) {
|
||||
*(intptr_t *)tib = (intptr_t)tib;
|
||||
*(intptr_t *)(tib + 0x08) = 0;
|
||||
*(int *)(tib + 0x10) = -1; // exit code
|
||||
*(intptr_t *)(tib + 0x30) = (intptr_t)tib;
|
||||
*(int *)(tib + 0x38) = -1; // tid
|
||||
*(int *)(tib + 0x3c) = 0;
|
||||
|
@ -72,7 +73,12 @@ privileged void __install_tls(char tib[64]) {
|
|||
} else if (IsFreebsd()) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(__NR_sysarch), "D"(129), "S"(tib)
|
||||
: "0"(__NR_sysarch), "D"(AMD64_SET_FSBASE), "S"(tib)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
} else if (IsNetbsd()) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax), "=d"(dx)
|
||||
: "0"(__NR_sysarch), "D"(X86_SET_FSBASE), "S"(tib)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
} else if (IsXnu()) {
|
||||
asm volatile("syscall"
|
||||
|
@ -85,11 +91,6 @@ privileged void __install_tls(char tib[64]) {
|
|||
: "=a"(ax)
|
||||
: "0"(__NR___set_tcb), "D"(tib)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
} else if (IsNetbsd()) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax), "=d"(dx)
|
||||
: "0"(__NR__lwp_setprivate), "D"(tib)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
} else {
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
|
|
|
@ -17,14 +17,22 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.privileged
|
||||
|
||||
// Reads byte from stream.
|
||||
// Loads previously saved processor state.
|
||||
//
|
||||
// @param rdi has stream object pointer
|
||||
// @return byte in range 0..255, or -1 w/ errno
|
||||
// @see fgetc_unlocked()
|
||||
// @threadsafe
|
||||
fgetc: mov %rdi,%r11
|
||||
ezlea fgetc_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn fgetc,globl
|
||||
// @param rdi points to the jmp_buf
|
||||
// @param rsi is returned by setlongerjmp() invocation
|
||||
// @noreturn
|
||||
longerjmp:
|
||||
mov $1,%eax
|
||||
mov %rsi,%rdx
|
||||
mov (%rdi),%rsp
|
||||
mov 8(%rdi),%rbx
|
||||
mov 16(%rdi),%rbp
|
||||
mov 24(%rdi),%r12
|
||||
mov 32(%rdi),%r13
|
||||
mov 40(%rdi),%r14
|
||||
mov 48(%rdi),%r15
|
||||
jmp *56(%rdi)
|
||||
.endfn longerjmp,globl
|
41
libc/nexgen32e/setlongerjmp.S
Normal file
41
libc/nexgen32e/setlongerjmp.S
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/macros.internal.h"
|
||||
|
||||
// Saves caller CPU state to cacheline.
|
||||
//
|
||||
// @param rdi points to jmp_buf
|
||||
// @return eax contains 0 when set, and 1 if jumped
|
||||
// @return rdx contains value passed to longerjmp()
|
||||
// @returnstwice
|
||||
setlongerjmp:
|
||||
lea 8(%rsp),%rax
|
||||
mov %rax,(%rdi)
|
||||
mov %rbx,8(%rdi)
|
||||
mov %rbp,16(%rdi)
|
||||
mov %r12,24(%rdi)
|
||||
mov %r13,32(%rdi)
|
||||
mov %r14,40(%rdi)
|
||||
mov %r15,48(%rdi)
|
||||
mov (%rsp),%rax
|
||||
mov %rax,56(%rdi)
|
||||
xor %eax,%eax
|
||||
xor %edx,%edx
|
||||
ret
|
||||
.endfn setlongerjmp,globl
|
|
@ -18,6 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
|
||||
bool __threaded;
|
||||
/**
|
||||
* Contains TID of main thread or 0 if threading isn't enabled.
|
||||
*/
|
||||
int __threaded;
|
||||
|
||||
bool __tls_enabled;
|
||||
|
||||
unsigned __tls_index;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern bool __threaded;
|
||||
extern int __threaded;
|
||||
extern bool __tls_enabled;
|
||||
extern unsigned __tls_index;
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ int GetUserName(char16_t (*buf)[257], uint32_t *in_out_size);
|
|||
bool32 GlobalMemoryStatusEx(struct NtMemoryStatusEx *lpBuffer);
|
||||
int32_t GetExitCodeProcess(int64_t hProcess, uint32_t *lpExitCode);
|
||||
int32_t GetProcessHandleCount(int64_t hProcess, uint32_t *pdwHandleCount);
|
||||
bool32 GetSystemTimes(struct NtFileTime *opt_out_lpIdleTime,
|
||||
struct NtFileTime *opt_out_lpKernelTime,
|
||||
struct NtFileTime *opt_out_lpUserTime);
|
||||
bool32 GetProcessTimes(int64_t hProcess,
|
||||
struct NtFileTime *out_lpCreationFileTime,
|
||||
struct NtFileTime *out_lpExitFileTime,
|
||||
|
|
|
@ -1,2 +1,12 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp kernel32,__imp_GetSystemTimes,GetSystemTimes,0
|
||||
|
||||
.text.windows
|
||||
GetSystemTimes:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_GetSystemTimes(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn GetSystemTimes,globl
|
||||
.previous
|
||||
|
|
|
@ -664,7 +664,7 @@ imp 'GetSystemTime' GetSystemTime kernel32 0 1
|
|||
imp 'GetSystemTimeAdjustment' GetSystemTimeAdjustment kernel32 0 3
|
||||
imp 'GetSystemTimeAsFileTime' GetSystemTimeAsFileTime kernel32 0 1
|
||||
imp 'GetSystemTimePreciseAsFileTime' GetSystemTimePreciseAsFileTime kernel32 0 1
|
||||
imp 'GetSystemTimes' GetSystemTimes kernel32 0
|
||||
imp 'GetSystemTimes' GetSystemTimes kernel32 0 3
|
||||
imp 'GetSystemWindowsDirectory' GetSystemWindowsDirectoryW kernel32 0
|
||||
imp 'GetSystemWindowsDirectoryA' GetSystemWindowsDirectoryA kernel32 0
|
||||
imp 'GetSystemWow64Directory' GetSystemWow64DirectoryW kernel32 0
|
||||
|
|
|
@ -23,13 +23,16 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/futex.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/nrlinux.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -121,7 +124,7 @@ static textwindows int CloneWindows(int (*func)(void *), char *stk,
|
|||
wt->func = func;
|
||||
wt->arg = arg;
|
||||
wt->tls = flags & CLONE_SETTLS ? tls : 0;
|
||||
if ((h = CreateThread(0, 0, (void *)WinThreadEntry, wt, 0, &wt->utid))) {
|
||||
if ((h = CreateThread(0, 4096, (void *)WinThreadEntry, wt, 0, &wt->utid))) {
|
||||
CloseHandle(h);
|
||||
return wt->tid;
|
||||
} else {
|
||||
|
@ -134,8 +137,7 @@ static textwindows int CloneWindows(int (*func)(void *), char *stk,
|
|||
|
||||
void XnuThreadThunk(void *pthread, int machport, void *(*func)(void *),
|
||||
void *arg, intptr_t *stack, unsigned xnuflags);
|
||||
asm(".local\tXnuThreadThunk\n"
|
||||
"XnuThreadThunk:\n\t"
|
||||
asm("XnuThreadThunk:\n\t"
|
||||
"xor\t%ebp,%ebp\n\t"
|
||||
"mov\t%r8,%rsp\n\t"
|
||||
"and\t$-16,%rsp\n\t"
|
||||
|
@ -168,7 +170,7 @@ XnuThreadMain(void *pthread, int tid, int (*func)(void *arg), void *arg,
|
|||
// %r10 = uint32_t sem);
|
||||
asm volatile("movl\t$0,%0\n\t" // *wt->ztid = 0
|
||||
"xor\t%%r10d,%%r10d\n\t" // sem = 0
|
||||
"syscall\n\t" // _Exit1()
|
||||
"syscall\n\t" // __bsdthread_terminate()
|
||||
"ud2"
|
||||
: "=m"(*wt->ztid)
|
||||
: "a"(0x2000000 | 361), "D"(0), "S"(0), "d"(0)
|
||||
|
@ -218,7 +220,7 @@ static wontreturn void FreebsdThreadMain(void *p) {
|
|||
// we no longer use the stack after this point
|
||||
// void thr_exit(%rdi = long *state);
|
||||
asm volatile("movl\t$0,%0\n\t" // *wt->ztid = 0
|
||||
"syscall" // _Exit1()
|
||||
"syscall" // thr_exit()
|
||||
: "=m"(*wt->ztid)
|
||||
: "a"(431), "D"(0)
|
||||
: "rcx", "r11", "memory");
|
||||
|
@ -294,11 +296,14 @@ OpenbsdThreadMain(struct CloneArgs *wt) {
|
|||
// although ideally there should be a better solution.
|
||||
//
|
||||
// void __threxit(%rdi = int32_t *notdead);
|
||||
asm volatile("mov\t%3,%%rsp\n\t"
|
||||
"movl\t$0,%0\n\t" // *wt->ztid = 0
|
||||
"syscall" // _Exit1()
|
||||
asm volatile("mov\t%2,%%rsp\n\t"
|
||||
"movl\t$0,(%%rdi)\n\t" // *wt->ztid = 0
|
||||
"syscall\n\t" // futex()
|
||||
"mov\t$302,%%eax\n\t" // __threxit()
|
||||
"syscall"
|
||||
: "=m"(*wt->ztid)
|
||||
: "a"(302), "D"(0), "r"(wt->pstack)
|
||||
: "a"(83), "m"(wt->pstack), "D"(wt->ztid), "S"(FUTEX_WAKE),
|
||||
"d"(INT_MAX)
|
||||
: "rcx", "r11", "memory");
|
||||
unreachable;
|
||||
}
|
||||
|
@ -337,7 +342,7 @@ static wontreturn void NetbsdThreadMain(void *arg, int (*func)(void *arg),
|
|||
// we no longer use the stack after this point
|
||||
// %eax = int __lwp_exit(void);
|
||||
asm volatile("movl\t$0,%2\n\t" // *wt->ztid = 0
|
||||
"syscall\n\t" // _Exit1()
|
||||
"syscall\n\t" // __lwp_exit()
|
||||
"ud2"
|
||||
: "=a"(ax), "=d"(dx), "=m"(*ztid)
|
||||
: "0"(310)
|
||||
|
@ -504,7 +509,7 @@ int sys_clone_linux(int flags, char *stk, int *ptid, int *ctid, void *tls,
|
|||
*/
|
||||
int clone(int (*func)(void *), void *stk, size_t stksz, int flags, void *arg,
|
||||
int *ptid, void *tls, size_t tlssz, int *ctid) {
|
||||
int rc;
|
||||
int rc, maintid;
|
||||
struct CloneArgs *wt;
|
||||
|
||||
// transition program to threaded state
|
||||
|
@ -517,13 +522,14 @@ int clone(int (*func)(void *), void *stk, size_t stksz, int flags, void *arg,
|
|||
STRACE("clone() tls/non-tls mixed order");
|
||||
return einval();
|
||||
}
|
||||
maintid = gettid();
|
||||
__initialize_tls(tibdefault);
|
||||
*(int *)((char *)tibdefault + 0x38) = gettid();
|
||||
*(int *)((char *)tibdefault + 0x38) = maintid;
|
||||
*(int *)((char *)tibdefault + 0x3c) = __errno;
|
||||
__install_tls(tibdefault);
|
||||
__threaded = true;
|
||||
__threaded = maintid;
|
||||
} else if (flags & CLONE_THREAD) {
|
||||
__threaded = true;
|
||||
__threaded = gettid();
|
||||
}
|
||||
|
||||
if (IsAsan() &&
|
||||
|
|
|
@ -18,6 +18,13 @@ extern const char v_ntsubsystem[] __attribute__((__weak__));
|
|||
extern const uintptr_t __fini_array_end[] __attribute__((__weak__));
|
||||
extern const uintptr_t __fini_array_start[] __attribute__((__weak__));
|
||||
|
||||
extern unsigned char _tdata_start[];
|
||||
extern unsigned char _tdata_end[];
|
||||
extern unsigned char _tdata_size[];
|
||||
extern unsigned char _tbss_start[];
|
||||
extern unsigned char _tbss_end[];
|
||||
extern unsigned char _tls_size[];
|
||||
|
||||
void _init(void) hidden;
|
||||
void __restorewintty(void) hidden;
|
||||
void *__cxa_finalize(void *) hidden;
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
@ -84,6 +86,7 @@ static noasan inline bool OverlapsExistingMapping(char *p, size_t n) {
|
|||
}
|
||||
|
||||
static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
|
||||
// TODO: improve performance
|
||||
int i, start, end;
|
||||
assert(align > 0);
|
||||
if (_mmi.i) {
|
||||
|
@ -327,15 +330,7 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
return VIP(einval());
|
||||
}
|
||||
|
||||
// if size is a two power then automap will use it as alignment
|
||||
if (IS2POW(size)) {
|
||||
a = size >> 16;
|
||||
if (!a) {
|
||||
a = 1;
|
||||
}
|
||||
} else {
|
||||
a = 1;
|
||||
}
|
||||
a = max(1, rounddown2pow(size) >> 16);
|
||||
|
||||
f = (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED;
|
||||
if (flags & MAP_FIXED) {
|
||||
|
|
|
@ -48,6 +48,8 @@ unsigned long getauxval(unsigned long);
|
|||
void *mapanon(size_t) attributeallocsize((1));
|
||||
int setjmp(jmp_buf) libcesque returnstwice paramsnonnull();
|
||||
void longjmp(jmp_buf, int) libcesque wontreturn paramsnonnull();
|
||||
axdx_t setlongerjmp(jmp_buf) libcesque returnstwice paramsnonnull();
|
||||
void longerjmp(jmp_buf, intptr_t) libcesque wontreturn paramsnonnull();
|
||||
int _setjmp(jmp_buf) libcesque returnstwice paramsnonnull();
|
||||
void _longjmp(jmp_buf, int) libcesque wontreturn paramsnonnull();
|
||||
void exit(int) wontreturn;
|
||||
|
|
|
@ -18,6 +18,15 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
void clearerr_unlocked(FILE *f) {
|
||||
f->state = 0;
|
||||
/**
|
||||
* Clears error state on stream.
|
||||
*
|
||||
* @param f is file object stream pointer
|
||||
* @see clearerr_unlocked()
|
||||
* @threadsafe
|
||||
*/
|
||||
void clearerr(FILE *f) {
|
||||
flockfile(f);
|
||||
clearerr_unlocked(f);
|
||||
funlockfile(f);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
|
@ -16,15 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
// Returns true if stream is in end-of-file state.
|
||||
//
|
||||
// @param rdi has file stream object pointer
|
||||
// @note EOF doesn't count
|
||||
// @see feof_unlocked()
|
||||
// @threadsafe
|
||||
feof: mov %rdi,%r11
|
||||
ezlea feof_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn feof,globl
|
||||
void clearerr_unlocked(FILE *f) {
|
||||
f->state = 0;
|
||||
}
|
|
@ -20,7 +20,15 @@
|
|||
|
||||
/**
|
||||
* Returns true if stream is in end-of-file state.
|
||||
*
|
||||
* @param f is file object stream pointer
|
||||
* @see feof_unlocked()
|
||||
* @threadsafe
|
||||
*/
|
||||
int feof_unlocked(FILE *f) {
|
||||
return f->state == -1;
|
||||
int feof(FILE *f) {
|
||||
int rc;
|
||||
flockfile(f);
|
||||
rc = feof_unlocked(f);
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- 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=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
|
@ -16,15 +16,14 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
// Returns nonzero if stream is in error state.
|
||||
//
|
||||
// @param rdi has file stream object pointer
|
||||
// @note EOF doesn't count
|
||||
// @see ferror_unlocked()
|
||||
// @threadsafe
|
||||
ferror: mov %rdi,%r11
|
||||
ezlea ferror_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn ferror,globl
|
||||
/**
|
||||
* Returns true if stream is in end-of-file state.
|
||||
*
|
||||
* @param f is file object stream pointer
|
||||
* @see feof()
|
||||
*/
|
||||
int feof_unlocked(FILE *f) {
|
||||
return f->state == -1;
|
||||
}
|
|
@ -21,9 +21,16 @@
|
|||
/**
|
||||
* Returns nonzero if stream is in error state.
|
||||
*
|
||||
* @param f is file stream pointer
|
||||
* @return non-zero if and only if it's an error state
|
||||
* @see ferror_unlocked(), feof()
|
||||
* @note EOF doesn't count
|
||||
* @see feof()
|
||||
* @threadsafe
|
||||
*/
|
||||
errno_t ferror_unlocked(FILE *f) {
|
||||
return f->state > 0 ? f->state : 0;
|
||||
errno_t ferror(FILE *f) {
|
||||
int rc;
|
||||
flockfile(f);
|
||||
rc = ferror_unlocked(f);
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
31
libc/stdio/ferror_unlocked.c
Normal file
31
libc/stdio/ferror_unlocked.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 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/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Returns nonzero if stream is in error state.
|
||||
*
|
||||
* @param f is file stream pointer
|
||||
* @return non-zero if and only if it's an error state
|
||||
* @note EOF doesn't count
|
||||
* @see ferror(), feof()
|
||||
*/
|
||||
errno_t ferror_unlocked(FILE *f) {
|
||||
return f->state > 0 ? f->state : 0;
|
||||
}
|
|
@ -20,14 +20,16 @@
|
|||
|
||||
/**
|
||||
* Reads byte from stream.
|
||||
*
|
||||
* @param f is non-null file object stream pointer
|
||||
* @return byte in range 0..255, or -1 w/ errno
|
||||
* @see fgetc_unlocked()
|
||||
* @threadsafe
|
||||
*/
|
||||
int fgetc_unlocked(FILE *f) {
|
||||
unsigned char b[1];
|
||||
if (f->beg < f->end) {
|
||||
return f->buf[f->beg++] & 0xff;
|
||||
} else {
|
||||
if (!fread_unlocked(b, 1, 1, f)) return -1;
|
||||
return b[0];
|
||||
}
|
||||
int fgetc(FILE *f) {
|
||||
int rc;
|
||||
flockfile(f);
|
||||
rc = fgetc_unlocked(f);
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
36
libc/stdio/fgetc_unlocked.c
Normal file
36
libc/stdio/fgetc_unlocked.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 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/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Reads byte from stream.
|
||||
*
|
||||
* @param f is file object stream pointer
|
||||
* @return byte in range 0..255, or -1 w/ errno
|
||||
* @see fgetc()
|
||||
*/
|
||||
int fgetc_unlocked(FILE *f) {
|
||||
unsigned char b[1];
|
||||
if (f->beg < f->end) {
|
||||
return f->buf[f->beg++] & 0xff;
|
||||
} else {
|
||||
if (!fread_unlocked(b, 1, 1, f)) return -1;
|
||||
return b[0];
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
|
@ -31,24 +30,13 @@
|
|||
* @param f is non-null file oject stream pointer
|
||||
* @return s on success, NULL on error, or NULL if EOF happens when
|
||||
* zero characters have been read
|
||||
* @see fgets_unlocked()
|
||||
* @threadsafe
|
||||
*/
|
||||
char *fgets_unlocked(char *s, int size, FILE *f) {
|
||||
int c;
|
||||
char *p;
|
||||
p = s;
|
||||
if (size > 0) {
|
||||
while (--size > 0) {
|
||||
if ((c = fgetc_unlocked(f)) == -1) {
|
||||
if (ferror_unlocked(f) == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p++ = c & 255;
|
||||
if (c == '\n') break;
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
return p > s ? s : NULL;
|
||||
char *fgets(char *s, int size, FILE *f) {
|
||||
char *res;
|
||||
flockfile(f);
|
||||
res = fgets_unlocked(s, size, f);
|
||||
funlockfile(f);
|
||||
return res;
|
||||
}
|
||||
|
|
54
libc/stdio/fgets_unlocked.c
Normal file
54
libc/stdio/fgets_unlocked.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/errno.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Reads line from stream.
|
||||
*
|
||||
* This function is similar to getline() except it'll truncate lines
|
||||
* exceeding size. The line ending marker is included and may be removed
|
||||
* using _chomp().
|
||||
*
|
||||
* @param s is output buffer
|
||||
* @param size is capacity of s
|
||||
* @param f is non-null file oject stream pointer
|
||||
* @return s on success, NULL on error, or NULL if EOF happens when
|
||||
* zero characters have been read
|
||||
*/
|
||||
char *fgets_unlocked(char *s, int size, FILE *f) {
|
||||
int c;
|
||||
char *p;
|
||||
p = s;
|
||||
if (size > 0) {
|
||||
while (--size > 0) {
|
||||
if ((c = fgetc_unlocked(f)) == -1) {
|
||||
if (ferror_unlocked(f) == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p++ = c & 255;
|
||||
if (c == '\n') break;
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
return p > s ? s : NULL;
|
||||
}
|
|
@ -17,35 +17,19 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/str/tpdecodecb.internal.h"
|
||||
|
||||
/**
|
||||
* Reads UTF-8 character from stream.
|
||||
*
|
||||
* @param f is non-null file object stream pointer
|
||||
* @return wide character or -1 on EOF or error
|
||||
* @see fgetwc_unlocked()
|
||||
* @threadsafe
|
||||
*/
|
||||
wint_t fgetwc_unlocked(FILE *f) {
|
||||
int c, n;
|
||||
wint_t b, x, y;
|
||||
if (f->beg < f->end) {
|
||||
b = f->buf[f->beg++] & 0xff;
|
||||
} else if ((c = fgetc_unlocked(f)) != -1) {
|
||||
b = c;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (b < 0300) return b;
|
||||
n = ThomPikeLen(b);
|
||||
x = ThomPikeByte(b);
|
||||
while (--n) {
|
||||
if ((c = fgetc_unlocked(f)) == -1) return -1;
|
||||
y = c;
|
||||
if (ThomPikeCont(y)) {
|
||||
x = ThomPikeMerge(x, y);
|
||||
} else {
|
||||
ungetc_unlocked(y, f);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
wint_t fgetwc(FILE *f) {
|
||||
wint_t wc;
|
||||
flockfile(f);
|
||||
wc = fgetwc_unlocked(f);
|
||||
funlockfile(f);
|
||||
return wc;
|
||||
}
|
||||
|
|
51
libc/stdio/fgetwc_unlocked.c
Normal file
51
libc/stdio/fgetwc_unlocked.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*-*- 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/stdio/stdio.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/str/tpdecodecb.internal.h"
|
||||
|
||||
/**
|
||||
* Reads UTF-8 character from stream.
|
||||
* @return wide character or -1 on EOF or error
|
||||
*/
|
||||
wint_t fgetwc_unlocked(FILE *f) {
|
||||
int c, n;
|
||||
wint_t b, x, y;
|
||||
if (f->beg < f->end) {
|
||||
b = f->buf[f->beg++] & 0xff;
|
||||
} else if ((c = fgetc_unlocked(f)) != -1) {
|
||||
b = c;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (b < 0300) return b;
|
||||
n = ThomPikeLen(b);
|
||||
x = ThomPikeByte(b);
|
||||
while (--n) {
|
||||
if ((c = fgetc_unlocked(f)) == -1) return -1;
|
||||
y = c;
|
||||
if (ThomPikeCont(y)) {
|
||||
x = ThomPikeMerge(x, y);
|
||||
} else {
|
||||
ungetc_unlocked(y, f);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/macros.internal.h"
|
||||
|
||||
// Reads line from stream.
|
||||
//
|
||||
// This function is similar to getline() except it'll truncate
|
||||
// lines exceeding size. The line ending marker is included
|
||||
// and may be removed using _chomp().
|
||||
//
|
||||
// @param rdi is output buffer
|
||||
// @param rsi is size of rdi buffer
|
||||
// @param rdx is file stream object pointer
|
||||
// @return rax has rdi on success, NULL on error or
|
||||
// NULL if EOF happens with zero chars read
|
||||
// @see fgets_unlocked()
|
||||
// @threadsafe
|
||||
fgets: mov %rdx,%r11
|
||||
ezlea fgets_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn fgets,globl
|
|
@ -1,30 +0,0 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/macros.internal.h"
|
||||
|
||||
// Reads UTF-8 wide character from stream.
|
||||
//
|
||||
// @param rdi has stream object pointer
|
||||
// @return wide character or -1 on EOF or error
|
||||
// @see fgetwc_unlocked()
|
||||
// @threadsafe
|
||||
fgetwc: mov %rdi,%r11
|
||||
ezlea fgetwc_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn fgetwc,globl
|
|
@ -44,10 +44,12 @@
|
|||
|
||||
// Thread local boundaries defined by linker script
|
||||
// @see ape/ape.lds
|
||||
_tbss_start = 0
|
||||
_tbss_end = 0
|
||||
_tdata_start = 0
|
||||
_tdata_end = 0
|
||||
_tdata_size = 0
|
||||
_tbss_start = 0
|
||||
_tbss_end = 0
|
||||
_tls_size = 0
|
||||
|
||||
.globl _base
|
||||
.globl ape_xlm
|
||||
|
@ -63,10 +65,12 @@
|
|||
.globl _end
|
||||
.globl _ereal
|
||||
.globl _etext
|
||||
.globl _tbss_start
|
||||
.globl _tbss_end
|
||||
.globl _tdata_start
|
||||
.globl _tdata_end
|
||||
.globl _tdata_size
|
||||
.globl _tbss_start
|
||||
.globl _tbss_end
|
||||
.globl _tls_size
|
||||
.globl __data_start
|
||||
.globl __data_end
|
||||
.globl __bss_start
|
||||
|
@ -86,10 +90,12 @@
|
|||
.weak _end
|
||||
.weak _ereal
|
||||
.weak _etext
|
||||
.weak _tbss_start
|
||||
.weak _tbss_end
|
||||
.weak _tdata_start
|
||||
.weak _tdata_end
|
||||
.weak _tdata_size
|
||||
.weak _tbss_start
|
||||
.weak _tbss_end
|
||||
.weak _tls_size
|
||||
.weak __data_start
|
||||
.weak __data_end
|
||||
.weak __bss_start
|
||||
|
|
|
@ -1285,6 +1285,14 @@ syscon rusage RUSAGE_THREAD 1 99 1 1 1 1 # faked nt & unavailable
|
|||
syscon rusage RUSAGE_CHILDREN -1 -1 -1 -1 -1 99 # unix consensus & unavailable on nt
|
||||
syscon rusage RUSAGE_BOTH -2 99 99 99 99 99 # woop
|
||||
|
||||
# fast userspace mutexes
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon futex FUTEX_WAIT 0 0 0 1 0 0
|
||||
syscon futex FUTEX_WAKE 1 0 0 2 0 0
|
||||
syscon futex FUTEX_REQUEUE 3 0 0 3 0 0
|
||||
syscon futex FUTEX_PRIVATE_FLAG 128 0 0 128 0 0
|
||||
|
||||
# Teletypewriter Control, e.g.
|
||||
#
|
||||
# TCSETS → About 70,800 results (0.31 seconds)
|
||||
|
@ -1817,14 +1825,6 @@ syscon misc DAY_5 0x02000b 11 11 10 10 0
|
|||
syscon misc DAY_6 0x02000c 12 12 11 11 0
|
||||
syscon misc DAY_7 0x02000d 13 13 12 12 0
|
||||
|
||||
syscon misc FUTEX_PRIVATE_FLAG 128 0 0 0x80 0x80 0
|
||||
syscon misc FUTEX_REQUEUE 3 0 0 3 3 0
|
||||
syscon misc FUTEX_REQUEUE_PRIVATE 131 0 0 131 131 0
|
||||
syscon misc FUTEX_WAIT 0 0 0 1 1 0
|
||||
syscon misc FUTEX_WAIT_PRIVATE 128 0 0 129 129 0
|
||||
syscon misc FUTEX_WAKE 1 0 0 2 2 0
|
||||
syscon misc FUTEX_WAKE_PRIVATE 129 0 0 130 130 0
|
||||
|
||||
syscon misc HOST_NOT_FOUND 1 1 1 1 1 0x2af9 # unix consensus
|
||||
syscon misc HOST_NAME_MAX 0x40 0 0 255 255 0
|
||||
|
||||
|
@ -1880,7 +1880,7 @@ syscon misc FALLOC_FL_UNSHARE_RANGE 0x40 -1 -1 -1 -1 -1 # bsd cons
|
|||
# System Call Numbers.
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology
|
||||
syscon nr __NR_exit 0x003c 0x2000169 0x01af 0x012e 0x136 0xfff # __bsdthread_terminate() on XNU, thr_exit() on FreeBSD, sys___threxit() on OpenBSD, __lwp_exit() on NetBSD
|
||||
syscon nr __NR_exit 0x003c 0x2000169 0x01af 0x012e 0x136 0xfff # __bsdthread_terminate() on XNU, thr_exit() on FreeBSD, __threxit() on OpenBSD, __lwp_exit() on NetBSD
|
||||
syscon nr __NR_exit_group 0x00e7 0x2000001 0x0001 0x0001 0x001 0xfff
|
||||
syscon nr __NR_read 0x0000 0x2000003 0x0003 0x0003 0x003 0xfff
|
||||
syscon nr __NR_write 0x0001 0x2000004 0x0004 0x0004 0x004 0xfff
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,FUTEX_PRIVATE_FLAG,128,0,0,0x80,0x80,0
|
||||
.syscon futex,FUTEX_PRIVATE_FLAG,128,0,0,128,0,0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,FUTEX_REQUEUE,3,0,0,3,3,0
|
||||
.syscon futex,FUTEX_REQUEUE,3,0,0,3,0,0
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,FUTEX_REQUEUE_PRIVATE,131,0,0,131,131,0
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,FUTEX_WAIT,0,0,0,1,1,0
|
||||
.syscon futex,FUTEX_WAIT,0,0,0,1,0,0
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,FUTEX_WAIT_PRIVATE,128,0,0,129,129,0
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,FUTEX_WAKE,1,0,0,2,2,0
|
||||
.syscon futex,FUTEX_WAKE,1,0,0,2,0,0
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,FUTEX_WAKE_PRIVATE,129,0,0,130,130,0
|
|
@ -2,24 +2,21 @@
|
|||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_FUTEX_H_
|
||||
#include "libc/runtime/symbolic.h"
|
||||
|
||||
#define FUTEX_PRIVATE_FLAG SYMBOLIC(FUTEX_PRIVATE_FLAG)
|
||||
#define FUTEX_REQUEUE SYMBOLIC(FUTEX_REQUEUE)
|
||||
#define FUTEX_REQUEUE_PRIVATE SYMBOLIC(FUTEX_REQUEUE_PRIVATE)
|
||||
#define FUTEX_WAIT SYMBOLIC(FUTEX_WAIT)
|
||||
#define FUTEX_WAIT_PRIVATE SYMBOLIC(FUTEX_WAIT_PRIVATE)
|
||||
#define FUTEX_WAKE SYMBOLIC(FUTEX_WAKE)
|
||||
#define FUTEX_WAKE_PRIVATE SYMBOLIC(FUTEX_WAKE_PRIVATE)
|
||||
#define FUTEX_REQUEUE SYMBOLIC(FUTEX_REQUEUE)
|
||||
#define FUTEX_PRIVATE_FLAG SYMBOLIC(FUTEX_PRIVATE_FLAG)
|
||||
#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
|
||||
#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
|
||||
#define FUTEX_REQUEUE_PRIVATE (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const long FUTEX_PRIVATE_FLAG;
|
||||
extern const long FUTEX_REQUEUE;
|
||||
extern const long FUTEX_REQUEUE_PRIVATE;
|
||||
extern const long FUTEX_WAIT;
|
||||
extern const long FUTEX_WAIT_PRIVATE;
|
||||
extern const long FUTEX_WAKE;
|
||||
extern const long FUTEX_WAKE_PRIVATE;
|
||||
extern const long FUTEX_REQUEUE;
|
||||
extern const long FUTEX_PRIVATE_FLAG;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -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│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ 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 │
|
||||
|
@ -17,14 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
// Clears error state on stream.
|
||||
//
|
||||
// @param rdi has stream pointer
|
||||
// @see clearerr_unlocked()
|
||||
// @threadsafe
|
||||
clearerr:
|
||||
mov %rdi,%r11
|
||||
ezlea clearerr_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn clearerr,globl
|
||||
__errfun:
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
.endfn __errfun,globl,hidden
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
e2big: .leafprologue
|
||||
.profilable
|
||||
mov E2BIG(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn e2big,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eacces: .leafprologue
|
||||
.profilable
|
||||
mov EACCES(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eacces,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eaddrinuse:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EADDRINUSE(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eaddrinuse,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eaddrnotavail:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EADDRNOTAVAIL(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eaddrnotavail,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eadv: .leafprologue
|
||||
.profilable
|
||||
mov EADV(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eadv,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eafnosupport:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EAFNOSUPPORT(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eafnosupport,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eagain: .leafprologue
|
||||
.profilable
|
||||
mov EAGAIN(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eagain,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ealready:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EALREADY(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ealready,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebade: .leafprologue
|
||||
.profilable
|
||||
mov EBADE(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebade,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebadf: .leafprologue
|
||||
.profilable
|
||||
mov EBADF(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebadf,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebadfd: .leafprologue
|
||||
.profilable
|
||||
mov EBADFD(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebadfd,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebadmsg:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EBADMSG(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebadmsg,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebadr: .leafprologue
|
||||
.profilable
|
||||
mov EBADR(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebadr,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebadrqc:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EBADRQC(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebadrqc,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebadslt:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EBADSLT(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebadslt,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ebusy: .leafprologue
|
||||
.profilable
|
||||
mov EBUSY(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ebusy,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ecanceled:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov ECANCELED(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ecanceled,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
echild: .leafprologue
|
||||
.profilable
|
||||
mov ECHILD(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn echild,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
echrng: .leafprologue
|
||||
.profilable
|
||||
mov ECHRNG(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn echrng,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ecomm: .leafprologue
|
||||
.profilable
|
||||
mov ECOMM(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ecomm,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
econnaborted:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov ECONNABORTED(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn econnaborted,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
econnrefused:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov ECONNREFUSED(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn econnrefused,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
econnreset:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov ECONNRESET(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn econnreset,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
edeadlk:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EDEADLK(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn edeadlk,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
edestaddrreq:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EDESTADDRREQ(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn edestaddrreq,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
edom: .leafprologue
|
||||
.profilable
|
||||
mov EDOM(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn edom,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
edotdot:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EDOTDOT(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn edotdot,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
edquot: .leafprologue
|
||||
.profilable
|
||||
mov EDQUOT(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn edquot,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eexist: .leafprologue
|
||||
.profilable
|
||||
mov EEXIST(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eexist,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
efault: .leafprologue
|
||||
.profilable
|
||||
mov EFAULT(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn efault,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
efbig: .leafprologue
|
||||
.profilable
|
||||
mov EFBIG(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn efbig,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ehostdown:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EHOSTDOWN(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ehostdown,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ehostunreach:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EHOSTUNREACH(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ehostunreach,globl,hidden
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
ehwpoison:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov EHWPOISON(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn ehwpoison,globl,hidden
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
|
||||
.section .privileged,"ax",@progbits
|
||||
|
||||
eidrm: .leafprologue
|
||||
.profilable
|
||||
mov EIDRM(%rip),%ecx
|
||||
.errno
|
||||
mov %ecx,(%rax)
|
||||
push $-1
|
||||
pop %rax
|
||||
.leafepilogue
|
||||
jmp __errfun
|
||||
.endfn eidrm,globl,hidden
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue