mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 15:28:30 +00:00
Make fixes and improvements
- Document more compiler flags - Expose new __print_maps() api - Better overflow checking in mmap() - Improve the shell example somewhat - Fix minor runtime bugs regarding stacks - Make kill() on fork()+execve()'d children work - Support CLONE_CHILD_CLEARTID for proper joining - Fix recent possible deadlock regression with --ftrace
This commit is contained in:
parent
6e52cba37a
commit
ec2cb88058
68 changed files with 1211 additions and 431 deletions
56
libc/intrin/_spinlock_debug_1.c
Normal file
56
libc/intrin/_spinlock_debug_1.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- 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/intrin/kprintf.h"
|
||||
#include "libc/intrin/lockcmpxchgp.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
|
||||
void _spinlock_debug_1(void *lockptr, const char *lockname, const char *file,
|
||||
int line, const char *func) {
|
||||
unsigned i;
|
||||
uint64_t ts1, ts2;
|
||||
int me, owner, *lock = lockptr;
|
||||
me = gettid();
|
||||
owner = 0;
|
||||
if (!_lockcmpxchgp(lock, &owner, me)) {
|
||||
if (owner == me) {
|
||||
kprintf("%s:%d: warning: possible re-entry on lock %s in %s()\n", file,
|
||||
line, lockname, func);
|
||||
}
|
||||
i = 0;
|
||||
ts1 = rdtsc();
|
||||
for (;;) {
|
||||
owner = 0;
|
||||
if (_lockcmpxchgp(lock, &owner, me)) break;
|
||||
ts2 = rdtsc();
|
||||
if (ClocksToNanos(ts1, ts2) > 1000000000ul) {
|
||||
ts1 = ts2;
|
||||
kprintf("%s:%d: warning: slow lock on %s in %s()\n", file, line,
|
||||
lockname, func);
|
||||
}
|
||||
if (++i & 7) {
|
||||
__builtin_ia32_pause();
|
||||
} else {
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
libc/intrin/_spinlock_debug_4.c
Normal file
57
libc/intrin/_spinlock_debug_4.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*-*- 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/intrin/kprintf.h"
|
||||
#include "libc/intrin/lockcmpxchgp.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
|
||||
void _spinlock_debug_4(void *lockptr, const char *lockname, const char *file,
|
||||
int line, const char *func) {
|
||||
unsigned i;
|
||||
uint64_t ts1, ts2;
|
||||
int me, owner, *lock = lockptr;
|
||||
me = gettid();
|
||||
owner = 0;
|
||||
if (!_lockcmpxchgp(lock, &owner, me)) {
|
||||
if (owner == me) {
|
||||
kprintf("%s:%d: warning: lock re-entry on %s in %s()\n", file, line,
|
||||
lockname, func);
|
||||
_Exit(1);
|
||||
}
|
||||
i = 0;
|
||||
ts1 = rdtsc();
|
||||
for (;;) {
|
||||
owner = 0;
|
||||
if (_lockcmpxchgp(lock, &owner, me)) break;
|
||||
ts2 = rdtsc();
|
||||
if (ClocksToNanos(ts1, ts2) > 1000000000ul) {
|
||||
ts1 = ts2;
|
||||
kprintf("%s:%d: warning: slow lock on %s in %s()\n", file, line,
|
||||
lockname, func);
|
||||
}
|
||||
if (++i & 7) {
|
||||
__builtin_ia32_pause();
|
||||
} else {
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,9 +59,21 @@
|
|||
|
||||
STATIC_YOINK("_init_asan");
|
||||
|
||||
#if IsModeDbg()
|
||||
// MODE=dbg
|
||||
// O(32mb) of morgue memory
|
||||
// Θ(64) bytes of malloc overhead
|
||||
#define ASAN_MORGUE_ITEMS 512
|
||||
#define ASAN_MORGUE_THRESHOLD 65536 // morgue memory O(ITEMS*THRESHOLD)
|
||||
#define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin
|
||||
#define ASAN_MORGUE_THRESHOLD 65536
|
||||
#define ASAN_TRACE_ITEMS 16
|
||||
#else
|
||||
// MODE=asan
|
||||
// O(32mb) of morgue memory
|
||||
// Θ(32) bytes of malloc overhead
|
||||
#define ASAN_MORGUE_ITEMS 512
|
||||
#define ASAN_MORGUE_THRESHOLD 65536
|
||||
#define ASAN_TRACE_ITEMS 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Address Sanitizer Runtime.
|
||||
|
@ -853,7 +865,7 @@ static void __asan_morgue_flush(void) {
|
|||
void *p;
|
||||
_spinlock_cooperative(&__asan_lock);
|
||||
for (i = 0; i < ARRAYLEN(__asan_morgue.p); ++i) {
|
||||
if (weaken(dlfree)) {
|
||||
if (__asan_morgue.p[i] && weaken(dlfree)) {
|
||||
weaken(dlfree)(__asan_morgue.p[i]);
|
||||
}
|
||||
__asan_morgue.p[i] = 0;
|
||||
|
@ -1196,9 +1208,9 @@ void __asan_evil(uint8_t *addr, int size, const char *s1, const char *s2) {
|
|||
struct AsanTrace tr;
|
||||
__asan_rawtrace(&tr, __builtin_frame_address(0));
|
||||
kprintf(
|
||||
"WARNING: ASAN %s %s bad %d byte %s at %x bt %x %x %x %x %x\n",
|
||||
"WARNING: ASAN %s %s bad %d byte %s at %x bt %x %x %x\n",
|
||||
__asan_noreentry == gettid() ? "error during" : "multi-threaded crash",
|
||||
s1, size, s2, addr, tr.p[0], tr.p[1], tr.p[2], tr.p[3], tr.p[4], tr.p[5]);
|
||||
s1, size, s2, addr, tr.p[0], tr.p[1], tr.p[2], tr.p[3]);
|
||||
}
|
||||
|
||||
void __asan_report_load(uint8_t *addr, int size) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
|
||||
char *GetMagnumStr(const struct MagnumStr *ms, int x) {
|
||||
privileged char *GetMagnumStr(const struct MagnumStr *ms, int x) {
|
||||
int i;
|
||||
for (i = 0; ms[i].x != MAGNUM_TERMINATOR; ++i) {
|
||||
if (x == MAGNUM_NUMBER(ms, i)) {
|
||||
|
|
|
@ -30,6 +30,13 @@ privileged int gettid(void) {
|
|||
int64_t wut;
|
||||
struct WinThread *wt;
|
||||
|
||||
if (__tls_enabled) {
|
||||
rc = *(int *)(__get_tls() + 0x38);
|
||||
if (rc && rc != -1) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
|
|
@ -58,11 +58,21 @@ o/$(MODE)/libc/intrin/asan.o: \
|
|||
-finline \
|
||||
-finline-functions
|
||||
|
||||
# we can't use compiler magic because:
|
||||
# kprintf() is mission critical to error reporting
|
||||
o/$(MODE)/libc/intrin/getmagnumstr.greg.o \
|
||||
o/$(MODE)/libc/intrin/strerrno.greg.o \
|
||||
o/$(MODE)/libc/intrin/strerrdoc.greg.o \
|
||||
o/$(MODE)/libc/intrin/strerror_wr.greg.o \
|
||||
o/$(MODE)/libc/intrin/kprintf.greg.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fpie \
|
||||
-fwrapv \
|
||||
-x-no-pg \
|
||||
-mno-fentry \
|
||||
-ffreestanding \
|
||||
$(NO_MAGIC)
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector
|
||||
|
||||
o/$(MODE)/libc/intrin/tls.greg.o \
|
||||
o/$(MODE)/libc/intrin/exit.greg.o \
|
||||
|
|
121
libc/intrin/kerrnodocs.S
Normal file
121
libc/intrin/kerrnodocs.S
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e s
|
||||
.long \e - kErrnoDocs
|
||||
.long 1f - kErrnoDocs
|
||||
.rodata.str1.1
|
||||
1: .asciz "\s"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
.underrun
|
||||
kErrnoDocs:
|
||||
.e EINVAL,"Invalid argument"
|
||||
.e ENOSYS,"Function not implemented"
|
||||
.e EPERM,"Operation not permitted"
|
||||
.e ENOENT,"No such file or directory"
|
||||
.e ESRCH,"No such process"
|
||||
.e EINTR,"Interrupted system call"
|
||||
.e EIO,"I/O error"
|
||||
.e ENXIO,"No such device or address"
|
||||
.e E2BIG,"Arg list too long"
|
||||
.e ENOEXEC,"Exec format error"
|
||||
.e EBADF,"Bad file number"
|
||||
.e ECHILD,"No child processes"
|
||||
.e EAGAIN,"Try again"
|
||||
.e ENOMEM,"Out of memory"
|
||||
.e EACCES,"Permission denied"
|
||||
.e EFAULT,"Bad address"
|
||||
.e ENOTBLK,"Block device required"
|
||||
.e EBUSY,"Device or resource busy"
|
||||
.e EEXIST,"File exists"
|
||||
.e EXDEV,"Cross-device link"
|
||||
.e ENODEV,"No such device"
|
||||
.e ENOTDIR,"Not a directory"
|
||||
.e EISDIR,"Is a directory"
|
||||
.e ENFILE,"File table overflow"
|
||||
.e EMFILE,"Too many open files"
|
||||
.e ENOTTY,"Not a typewriter"
|
||||
.e ETXTBSY,"Text file busy"
|
||||
.e EFBIG,"File too large"
|
||||
.e ENOSPC,"No space left on device"
|
||||
.e EDQUOT,"Quota exceeded"
|
||||
.e ESPIPE,"Illegal seek"
|
||||
.e EROFS,"Read-only file system"
|
||||
.e EMLINK,"Too many links"
|
||||
.e EPIPE,"Broken pipe"
|
||||
.e EDOM,"Math argument out of domain of func"
|
||||
.e ERANGE,"Math result not representable"
|
||||
.e EDEADLK,"Resource deadlock would occur"
|
||||
.e ENAMETOOLONG,"File name too long"
|
||||
.e ENOLCK,"No record locks available"
|
||||
.e ENOTEMPTY,"Directory not empty"
|
||||
.e ELOOP,"Too many symbolic links encountered"
|
||||
.e ENOMSG,"No message of desired type"
|
||||
.e EIDRM,"Identifier removed"
|
||||
.e ETIME,"Timer expired"
|
||||
.e EPROTO,"Protocol error"
|
||||
.e EOVERFLOW,"Value too large for defined data type"
|
||||
.e EILSEQ,"Illegal byte sequence"
|
||||
.e EUSERS,"Too many users"
|
||||
.e ENOTSOCK,"Socket operation on non-socket"
|
||||
.e EDESTADDRREQ,"Destination address required"
|
||||
.e EMSGSIZE,"Message too long"
|
||||
.e EPROTOTYPE,"Protocol wrong type for socket"
|
||||
.e ENOPROTOOPT,"Protocol not available"
|
||||
.e EPROTONOSUPPORT,"Protocol not supported"
|
||||
.e ESOCKTNOSUPPORT,"Socket type not supported"
|
||||
.e ENOTSUP,"Operation not supported"
|
||||
.e EOPNOTSUPP,"Operation not supported on transport endpoint"
|
||||
.e EPFNOSUPPORT,"Protocol family not supported"
|
||||
.e EAFNOSUPPORT,"Address family not supported by protocol"
|
||||
.e EADDRINUSE,"Address already in use"
|
||||
.e EADDRNOTAVAIL,"Cannot assign requested address"
|
||||
.e ENETDOWN,"Network is down"
|
||||
.e ENETUNREACH,"Network is unreachable"
|
||||
.e ENETRESET,"Network dropped connection because of reset"
|
||||
.e ECONNABORTED,"Software caused connection abort"
|
||||
.e ECONNRESET,"Connection reset by peer"
|
||||
.e ENOBUFS,"No buffer space available"
|
||||
.e EISCONN,"Transport endpoint is already connected"
|
||||
.e ENOTCONN,"Transport endpoint is not connected"
|
||||
.e ESHUTDOWN,"Cannot send after transport endpoint shutdown"
|
||||
.e ETOOMANYREFS,"Too many references: cannot splice"
|
||||
.e ETIMEDOUT,"Connection timed out"
|
||||
.e ECONNREFUSED,"Connection refused"
|
||||
.e EHOSTDOWN,"Host is down"
|
||||
.e EHOSTUNREACH,"No route to host"
|
||||
.e EALREADY,"Operation already in progress"
|
||||
.e EINPROGRESS,"Operation now in progress"
|
||||
.e ESTALE,"Stale NFS file handle"
|
||||
.e EREMOTE,"Object is remote"
|
||||
.e EBADMSG,"Not a data message"
|
||||
.e ECANCELED,"Operation Canceled"
|
||||
.e EOWNERDEAD,"Owner died"
|
||||
.e ENOTRECOVERABLE,"State not recoverable"
|
||||
.e ENONET,"Machine is not on the network"
|
||||
.e ERESTART,"Interrupted system call should be restarted"
|
||||
.long MAGNUM_TERMINATOR
|
||||
.endobj kErrnoDocs,globl,hidden
|
||||
.overrun
|
122
libc/intrin/kerrnonames.S
Normal file
122
libc/intrin/kerrnonames.S
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e
|
||||
.long \e - kErrnoNames
|
||||
.long 1f - kErrnoNames
|
||||
.rodata.str1.1
|
||||
1: .string "\e"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
.underrun
|
||||
kErrnoNames:
|
||||
.e EINVAL
|
||||
.e ENOSYS
|
||||
.e EPERM
|
||||
.e ENOENT
|
||||
.e ESRCH
|
||||
.e EINTR
|
||||
.e EIO
|
||||
.e ENXIO
|
||||
.e E2BIG
|
||||
.e ENOEXEC
|
||||
.e EBADF
|
||||
.e ECHILD
|
||||
.e EAGAIN
|
||||
.e ENOMEM
|
||||
.e EACCES
|
||||
.e EFAULT
|
||||
.e ENOTBLK
|
||||
.e EBUSY
|
||||
.e EEXIST
|
||||
.e EXDEV
|
||||
.e ENODEV
|
||||
.e ENOTDIR
|
||||
.e EISDIR
|
||||
.e ENFILE
|
||||
.e EMFILE
|
||||
.e ENOTTY
|
||||
.e ETXTBSY
|
||||
.e EFBIG
|
||||
.e ENOSPC
|
||||
.e EDQUOT
|
||||
.e ESPIPE
|
||||
.e EROFS
|
||||
.e EMLINK
|
||||
.e EPIPE
|
||||
.e EDOM
|
||||
.e ERANGE
|
||||
.e EDEADLK
|
||||
.e ENAMETOOLONG
|
||||
.e ENOLCK
|
||||
.e ENOTEMPTY
|
||||
.e ELOOP
|
||||
.e ENOMSG
|
||||
.e EIDRM
|
||||
.e ETIME
|
||||
.e EPROTO
|
||||
.e EOVERFLOW
|
||||
.e EILSEQ
|
||||
.e EUSERS
|
||||
.e ENOTSOCK
|
||||
.e EDESTADDRREQ
|
||||
.e EMSGSIZE
|
||||
.e EPROTOTYPE
|
||||
.e ENOPROTOOPT
|
||||
.e EPROTONOSUPPORT
|
||||
.e ESOCKTNOSUPPORT
|
||||
.e ENOTSUP
|
||||
.e EOPNOTSUPP
|
||||
.e EPFNOSUPPORT
|
||||
.e EAFNOSUPPORT
|
||||
.e EADDRINUSE
|
||||
.e EADDRNOTAVAIL
|
||||
.e ENETDOWN
|
||||
.e ENETUNREACH
|
||||
.e ENETRESET
|
||||
.e ECONNABORTED
|
||||
.e ECONNRESET
|
||||
.e ENOBUFS
|
||||
.e EISCONN
|
||||
.e ENOTCONN
|
||||
.e ESHUTDOWN
|
||||
.e ETOOMANYREFS
|
||||
.e ETIMEDOUT
|
||||
.e ECONNREFUSED
|
||||
.e EHOSTDOWN
|
||||
.e EHOSTUNREACH
|
||||
.e EALREADY
|
||||
.e EINPROGRESS
|
||||
.e ESTALE
|
||||
.e EREMOTE
|
||||
.e EBADMSG
|
||||
.e ECANCELED
|
||||
.e EOWNERDEAD
|
||||
.e ENOTRECOVERABLE
|
||||
.e ENONET
|
||||
.e ERESTART
|
||||
.e ENODATA
|
||||
.long MAGNUM_TERMINATOR
|
||||
.endobj kErrnoNames,globl,hidden
|
||||
.overrun
|
|
@ -52,6 +52,8 @@
|
|||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
|
||||
extern hidden struct SymbolTable *__symtab;
|
||||
|
||||
struct Timestamps {
|
||||
unsigned long long birth;
|
||||
unsigned long long start;
|
||||
|
@ -515,13 +517,19 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
}
|
||||
|
||||
case 't': {
|
||||
// %t will print the &symbol associated with an address. this
|
||||
// requires that some other code linked GetSymbolTable() and
|
||||
// called it beforehand to ensure the symbol table is loaded.
|
||||
// if the symbol table isn't linked or available, then this
|
||||
// routine will display &hexaddr so objdump -dS foo.com.dbg
|
||||
// can be manually consulted to look up the faulting code.
|
||||
int idx;
|
||||
x = va_arg(va, intptr_t);
|
||||
if (weaken(__get_symbol) &&
|
||||
if (weaken(__symtab) && *weaken(__symtab) &&
|
||||
(idx = weaken(__get_symbol)(0, x)) != -1) {
|
||||
if (p + 1 <= e) *p++ = '&';
|
||||
s = weaken(GetSymbolTable)()->name_base +
|
||||
weaken(GetSymbolTable)()->names[idx];
|
||||
s = (*weaken(__symtab))->name_base +
|
||||
(*weaken(__symtab))->names[idx];
|
||||
goto FormatString;
|
||||
}
|
||||
base = 4;
|
||||
|
|
24
libc/intrin/lockcmpxchgp.h
Normal file
24
libc/intrin/lockcmpxchgp.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHGP_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHGP_H_
|
||||
#include "libc/bits/asmflag.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
|
||||
#define _lockcmpxchgp(IN_OUT_IFTHING, IN_OUT_ISEQUALTOME, IN_REPLACEITWITHME) \
|
||||
({ \
|
||||
bool DidIt; \
|
||||
autotype(IN_OUT_IFTHING) IfThing = (IN_OUT_IFTHING); \
|
||||
typeof(IfThing) IsEqualToMe = (IN_OUT_ISEQUALTOME); \
|
||||
typeof(*IfThing) ReplaceItWithMe = (IN_REPLACEITWITHME); \
|
||||
asm volatile(ZFLAG_ASM("lock cmpxchg\t%3,%1") \
|
||||
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(*IsEqualToMe) \
|
||||
: "r"(ReplaceItWithMe) \
|
||||
: "cc"); \
|
||||
DidIt; \
|
||||
})
|
||||
#endif /* GNUC && !ANSI && x86 */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHGP_H_ */
|
|
@ -1,8 +1,9 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/intrin/lockcmpxchgp.h"
|
||||
|
||||
#if IsModeDbg() && !defined(_SPINLOCK_DEBUG)
|
||||
#define _SPINLOCK_DEBUG
|
||||
|
@ -19,63 +20,62 @@
|
|||
#define _spinlock_ndebug(lock) _spinlock_cooperative(lock)
|
||||
#endif
|
||||
|
||||
#define _spunlock(lock) __atomic_clear(lock, __ATOMIC_RELAXED)
|
||||
|
||||
#define _trylock(lock) __atomic_test_and_set(lock, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define _seizelock(lock) \
|
||||
do { \
|
||||
typeof(*(lock)) x = 1; \
|
||||
__atomic_store(lock, &x, __ATOMIC_RELEASE); \
|
||||
#define _spunlock(lock) \
|
||||
do { \
|
||||
autotype(lock) __lock = (lock); \
|
||||
typeof(*__lock) __x = 0; \
|
||||
__atomic_store(__lock, &__x, __ATOMIC_RELAXED); \
|
||||
} while (0)
|
||||
|
||||
#define _spinlock_tiny(lock) \
|
||||
do { \
|
||||
while (_trylock(lock)) { \
|
||||
__builtin_ia32_pause(); \
|
||||
} \
|
||||
#define _seizelock(lock) \
|
||||
do { \
|
||||
autotype(lock) __lock = (lock); \
|
||||
typeof(*__lock) __x = 1; \
|
||||
__atomic_store(__lock, &__x, __ATOMIC_RELEASE); \
|
||||
} while (0)
|
||||
|
||||
#define _spinlock_cooperative(lock) \
|
||||
do { \
|
||||
int __tries = 0; \
|
||||
for (;;) { \
|
||||
typeof(*(lock)) x; \
|
||||
__atomic_load(lock, &x, __ATOMIC_RELAXED); \
|
||||
if (!x && !_trylock(lock)) { \
|
||||
break; \
|
||||
} else if (++__tries & 7) { \
|
||||
__builtin_ia32_pause(); \
|
||||
} else { \
|
||||
sched_yield(); \
|
||||
} \
|
||||
} \
|
||||
#define _spinlock_tiny(lock) \
|
||||
do { \
|
||||
autotype(lock) __lock = (lock); \
|
||||
while (_trylock(__lock)) { \
|
||||
__builtin_ia32_pause(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _spinlock_debug(lock) \
|
||||
do { \
|
||||
typeof(*(lock)) me, owner; \
|
||||
unsigned long warntries = 16777216; \
|
||||
me = gettid(); \
|
||||
if (!_lockcmpxchg(lock, 0, me)) { \
|
||||
__atomic_load(lock, &owner, __ATOMIC_RELAXED); \
|
||||
if (owner == me) { \
|
||||
kprintf("%s:%d: warning: possible re-entry on %s in %s()\n", __FILE__, \
|
||||
__LINE__, #lock, __FUNCTION__); \
|
||||
} \
|
||||
while (!_lockcmpxchg(lock, 0, me)) { \
|
||||
if (!--warntries) { \
|
||||
warntries = -1; \
|
||||
kprintf("%s:%d: warning: possible deadlock on %s in %s()\n", \
|
||||
__FILE__, __LINE__, #lock, __FUNCTION__); \
|
||||
} \
|
||||
if (warntries & 7) { \
|
||||
__builtin_ia32_pause(); \
|
||||
} else { \
|
||||
sched_yield(); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
#define _spinlock_cooperative(lock) \
|
||||
do { \
|
||||
autotype(lock) __lock = (lock); \
|
||||
typeof(*__lock) __x; \
|
||||
int __tries = 0; \
|
||||
for (;;) { \
|
||||
__atomic_load(__lock, &__x, __ATOMIC_RELAXED); \
|
||||
if (!__x && !_trylock(__lock)) { \
|
||||
break; \
|
||||
} else if (++__tries & 7) { \
|
||||
__builtin_ia32_pause(); \
|
||||
} else { \
|
||||
sched_yield(); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void _spinlock_debug_1(void *, const char *, const char *, int, const char *);
|
||||
void _spinlock_debug_4(void *, const char *, const char *, int, const char *);
|
||||
|
||||
#define _spinlock_debug(lock) \
|
||||
do { \
|
||||
switch (sizeof(*(lock))) { \
|
||||
case 1: \
|
||||
_spinlock_debug_1(lock, #lock, __FILE__, __LINE__, __FUNCTION__); \
|
||||
break; \
|
||||
case 4: \
|
||||
_spinlock_debug_4(lock, #lock, __FILE__, __LINE__, __FUNCTION__); \
|
||||
break; \
|
||||
default: \
|
||||
assert(!"unsupported size"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ */
|
||||
|
|
32
libc/intrin/strerdoc.greg.c
Normal file
32
libc/intrin/strerdoc.greg.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to descriptive sentence.
|
||||
* @return non-null rodata string or null if not found
|
||||
*/
|
||||
privileged char *strerdoc(int x) {
|
||||
if (x) {
|
||||
return GetMagnumStr(kErrnoDocs, x);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
32
libc/intrin/strerrno.greg.c
Normal file
32
libc/intrin/strerrno.greg.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to symbolic name.
|
||||
* @return non-null rodata string or null if not found
|
||||
*/
|
||||
privileged char *strerrno(int x) {
|
||||
if (x) {
|
||||
return GetMagnumStr(kErrnoNames, x);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
61
libc/intrin/strerror_wr.greg.c
Normal file
61
libc/intrin/strerror_wr.greg.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*-*- 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/bits/safemacros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/enum/lang.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to string with explicit windows errno too.
|
||||
*
|
||||
* @param err is error number or zero if unknown
|
||||
* @return 0 on success, or error code
|
||||
*/
|
||||
privileged int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int c, n;
|
||||
char16_t winmsg[256];
|
||||
const char *sym, *msg;
|
||||
sym = firstnonnull(strerrno(err), "EUNKNOWN");
|
||||
msg = firstnonnull(strerdoc(err), "No error information");
|
||||
if (IsTiny()) {
|
||||
if (!sym) sym = "EUNKNOWN";
|
||||
for (; (c = *sym++); --size)
|
||||
if (size > 1) *buf++ = c;
|
||||
if (size) *buf = 0;
|
||||
} else if (!IsWindows() || err == winerr || !winerr) {
|
||||
ksnprintf(buf, size, "%s/%d/%s", sym, err, msg);
|
||||
} else {
|
||||
if ((n = FormatMessage(
|
||||
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, 0,
|
||||
winerr, MAKELANGID(kNtLangNeutral, kNtSublangDefault), winmsg,
|
||||
ARRAYLEN(winmsg), 0))) {
|
||||
while ((n && winmsg[n - 1] <= ' ') || winmsg[n - 1] == '.') --n;
|
||||
ksnprintf(buf, size, "%s/%d/%s/%d/%.*hs", sym, err, msg, winerr, n,
|
||||
winmsg);
|
||||
} else {
|
||||
ksnprintf(buf, size, "%s/%d/%s/%d", sym, err, msg, winerr);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -32,10 +32,24 @@
|
|||
|
||||
/**
|
||||
* Initializes thread information block.
|
||||
*
|
||||
* Here's the layout your c library assumes:
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
privileged void *__initialize_tls(char tib[hasatleast 64]) {
|
||||
*(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) = __errno;
|
||||
return tib;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue