diff options
Diffstat (limited to 'lib/Support/PrettyStackTrace.cpp')
-rw-r--r-- | lib/Support/PrettyStackTrace.cpp | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp index 987778a..f9f8cab 100644 --- a/lib/Support/PrettyStackTrace.cpp +++ b/lib/Support/PrettyStackTrace.cpp @@ -16,9 +16,8 @@ #include "llvm-c/Core.h" #include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" // Get autoconf configuration settings -#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Signals.h" -#include "llvm/Support/ThreadLocal.h" #include "llvm/Support/Watchdog.h" #include "llvm/Support/raw_ostream.h" @@ -28,7 +27,17 @@ using namespace llvm; -static ManagedStatic<sys::ThreadLocal<const PrettyStackTraceEntry> > PrettyStackTraceHead; +// If backtrace support is not enabled, compile out support for pretty stack +// traces. This has the secondary effect of not requiring thread local storage +// when backtrace support is disabled. +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + +// We need a thread local pointer to manage the stack of our stack trace +// objects, but we *really* cannot tolerate destructors running and do not want +// to pay any overhead of synchronizing. As a consequence, we use a raw +// thread-local variable. +static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead = + nullptr; static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ unsigned NextID = 0; @@ -46,12 +55,12 @@ static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ /// PrintCurStackTrace - Print the current stack trace to the specified stream. static void PrintCurStackTrace(raw_ostream &OS) { // Don't print an empty trace. - if (!PrettyStackTraceHead->get()) return; + if (!PrettyStackTraceHead) return; // If there are pretty stack frames registered, walk and emit them. OS << "Stack dump:\n"; - PrintStack(PrettyStackTraceHead->get(), OS); + PrintStack(PrettyStackTraceHead, OS); OS.flush(); } @@ -99,28 +108,23 @@ static void CrashHandler(void *) { #endif } +// defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#endif + PrettyStackTraceEntry::PrettyStackTraceEntry() { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) // Link ourselves. - NextEntry = PrettyStackTraceHead->get(); - PrettyStackTraceHead->set(this); + NextEntry = PrettyStackTraceHead; + PrettyStackTraceHead = this; +#endif } PrettyStackTraceEntry::~PrettyStackTraceEntry() { - // Do nothing if PrettyStackTraceHead is uninitialized. This can only happen - // if a shutdown occurred after we created the PrettyStackTraceEntry. That - // does occur in the following idiom: - // - // PrettyStackTraceProgram X(...); - // llvm_shutdown_obj Y; - // - // Without this check, we may end up removing ourselves from the stack trace - // after PrettyStackTraceHead has already been destroyed. - if (!PrettyStackTraceHead.isConstructed()) - return; - - assert(PrettyStackTraceHead->get() == this && +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + assert(PrettyStackTraceHead == this && "Pretty stack trace entry destruction is out of order"); - PrettyStackTraceHead->set(getNextEntry()); + PrettyStackTraceHead = getNextEntry(); +#endif } void PrettyStackTraceString::print(raw_ostream &OS) const { @@ -135,15 +139,19 @@ void PrettyStackTraceProgram::print(raw_ostream &OS) const { OS << '\n'; } +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) static bool RegisterCrashPrinter() { sys::AddSignalHandler(CrashHandler, nullptr); return false; } +#endif void llvm::EnablePrettyStackTrace() { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) // The first time this is called, we register the crash printer. static bool HandlerRegistered = RegisterCrashPrinter(); (void)HandlerRegistered; +#endif } void LLVMEnablePrettyStackTrace() { |