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:
Justine Tunney 2022-05-19 16:57:49 -07:00
parent 6e52cba37a
commit ec2cb88058
68 changed files with 1211 additions and 431 deletions

View 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();
}
}
}
}

View 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();
}
}
}
}

View file

@ -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) {

View file

@ -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)) {

View file

@ -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();
}

View file

@ -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
View 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
View 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

View file

@ -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;

View 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_ */

View file

@ -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_ */

View 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;
}
}

View 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;
}
}

View 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;
}

View file

@ -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;
}