Make improvements to locking

This change makes pthread_mutex_lock() as fast as _spinlock() by
default. Thread instability issues on NetBSD have been resolved.
Improvements made to gdtoa thread code. Crash reporting will now
synchronize between threads in a slightly better way.
This commit is contained in:
Justine Tunney 2022-06-19 01:13:03 -07:00
parent 25041b8026
commit d5312b60f7
60 changed files with 890 additions and 629 deletions

View file

@ -103,12 +103,6 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
garbage = weaken(__garbage);
gi = garbage ? garbage->i : 0;
for (frame = bp; frame && i < kBacktraceMaxFrames - 1; frame = frame->next) {
__mmi_lock();
ok = IsValidStackFramePointer(frame);
__mmi_unlock();
if (!ok) {
return -1;
}
addr = frame->addr;
if (addr == weakaddr("__gc")) {
do {

View file

@ -57,13 +57,6 @@ noinstrument noasan int PrintBacktraceUsingSymbols(int fd,
garbage = weaken(__garbage);
gi = garbage ? garbage->i : 0;
for (i = 0, frame = bp; frame; frame = frame->next) {
__mmi_lock();
ok = IsValidStackFramePointer(frame);
__mmi_unlock();
if (!ok) {
kprintf("%p corrupt frame pointer\n", frame);
break;
}
if (++i == LIMIT) {
kprintf("<truncated backtrace>\n");
break;

View file

@ -16,8 +16,10 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/lockcmpxchgp.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/internal.h"
#include "libc/log/libfatal.internal.h"
@ -32,18 +34,30 @@
*/
relegated wontreturn void __die(void) {
/* asan runtime depends on this function */
int rc;
static bool once;
if (_lockcmpxchg(&once, false, true)) {
int me, owner;
static int sync;
owner = 0;
me = gettid();
if (_lockcmpxchgp(&sync, &owner, me)) {
__restore_tty();
if (IsDebuggerPresent(false)) {
DebugBreak();
}
ShowBacktrace(2, NULL);
rc = 77;
if (weaken(ShowBacktrace)) {
weaken(ShowBacktrace)(2, __builtin_frame_address(0));
} else if (weaken(PrintBacktraceUsingSymbols) && weaken(GetSymbolTable)) {
weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0),
weaken(GetSymbolTable)());
} else {
kprintf("can't backtrace b/c `ShowCrashReports` not linked\n");
}
__restorewintty();
_Exit(77);
} else if (owner == me) {
kprintf("die failed while dying\n");
__restorewintty();
_Exit(78);
} else {
rc = 78;
_Exit1(79);
}
__restorewintty();
_Exit(rc);
}

View file

@ -26,6 +26,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/lockcmpxchgp.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/gdb.h"
#include "libc/log/internal.h"
@ -262,15 +263,22 @@ static wontreturn relegated noinstrument void __minicrash(int sig,
* simply print addresses which may be cross-referenced using objdump.
*
* This function never returns, except for traps w/ human supervision.
*
* @threadsafe
* @vforksafe
*/
relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
intptr_t rip;
int me, owner;
int gdbpid, err;
static bool noreentry, notpossible;
static int sync;
static bool notpossible;
STRACE("__oncrash rip %x", ctx->uc_mcontext.rip);
--__ftrace;
--__strace;
if (_lockcmpxchg(&noreentry, false, true)) {
owner = 0;
me = gettid();
if (_lockcmpxchgp(&sync, &owner, me)) {
if (!__vforked) {
rip = ctx ? ctx->uc_mcontext.rip : 0;
err = errno;
@ -292,20 +300,30 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
__restorewintty();
_Exit(128 + sig);
}
sync = 0;
} else {
sync = 0;
__minicrash(sig, si, ctx, "WHILE VFORKED");
}
} else if (sig == SIGTRAP) {
/* chances are IsDebuggerPresent() confused strace w/ gdb */
// chances are IsDebuggerPresent() confused strace w/ gdb
goto ItsATrap;
} else if (_lockcmpxchg(&notpossible, false, true)) {
__minicrash(sig, si, ctx, "WHILE CRASHING");
} else {
for (;;) {
asm("ud2");
} else if (owner == me) {
// we crashed while generating a crash report
if (_lockcmpxchg(&notpossible, false, true)) {
__minicrash(sig, si, ctx, "WHILE CRASHING");
} else {
// somehow __minicrash() crashed not possible
for (;;) {
asm("ud2");
}
}
} else {
// multiple threads have crashed
// kill current thread assuming process dies soon
// TODO(jart): It'd be nice to report on all threads.
_Exit1(8);
}
noreentry = false;
ItsATrap:
++__strace;
++__ftrace;

View file

@ -1,68 +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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/log/color.internal.h"
#include "libc/log/internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/runtime/internal.h"
#include "libc/sysv/consts/termios.h"
/**
* @fileoverview Terminal Restoration Helper for System Five.
*
* This is used by the crash reporting functions, e.g. __die(), to help
* ensure the terminal is in an unborked state after a crash happens.
*/
#define RESET_COLOR "\e[0m"
#define SHOW_CURSOR "\e[?25h"
#define DISABLE_MOUSE "\e[?1000;1002;1015;1006l"
#define ANSI_RESTORE RESET_COLOR SHOW_CURSOR DISABLE_MOUSE
static bool __isrestorable;
static union metatermios __oldtermios;
static textstartup void __oldtermios_init() {
int e;
e = errno;
if (sys_ioctl(0, TCGETS, &__oldtermios) != -1) {
__isrestorable = true;
}
errno = e;
}
const void *const __oldtermios_ctor[] initarray = {
__oldtermios_init,
};
void __restore_tty(void) {
int e;
if (__isrestorable && !__isworker && !__nocolor) {
e = errno;
sys_write(0, ANSI_RESTORE, __strlen(ANSI_RESTORE));
sys_ioctl(0, TCSETSF, &__oldtermios);
errno = e;
}
}

View file

@ -30,9 +30,12 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/ss.h"
STATIC_YOINK("__die"); /* for backtracing */
STATIC_YOINK("malloc_inspect_all"); /* for asan memory origin */
STATIC_YOINK("__get_symbol_by_addr"); /* for asan memory origin */
STATIC_YOINK("__die"); // for backtracing
STATIC_YOINK("ShowBacktrace"); // for backtracing
STATIC_YOINK("GetSymbolTable"); // for backtracing
STATIC_YOINK("PrintBacktraceUsingSymbols"); // for backtracing
STATIC_YOINK("malloc_inspect_all"); // for asan memory origin
STATIC_YOINK("__get_symbol_by_addr"); // for asan memory origin
extern const unsigned char __oncrash_thunks[8][11];
static struct sigaltstack g_oldsigaltstack;