Fix preload instruction isel. Only v7 supports pli, and only v7 with mp extension...
[oota-llvm.git] / lib / Support / CrashRecoveryContext.cpp
index c079182bd1c51b8d8e4812b7b501294c80ce9403..93af79bc0f564df3d360b42c5b116cac557099f2 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/Config/config.h"
+#include "llvm/System/Mutex.h"
 #include "llvm/System/ThreadLocal.h"
 #include <setjmp.h>
 #include <cstdio>
@@ -21,19 +23,25 @@ struct CrashRecoveryContextImpl;
 static sys::ThreadLocal<const CrashRecoveryContextImpl> CurrentContext;
 
 struct CrashRecoveryContextImpl {
+  CrashRecoveryContext *CRC;
   std::string Backtrace;
   ::jmp_buf JumpBuffer;
   volatile unsigned Failed : 1;
 
 public:
-  CrashRecoveryContextImpl() : Failed(false) {
+  CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC),
+                                                        Failed(false) {
     CurrentContext.set(this);
   }
   ~CrashRecoveryContextImpl() {
-    CurrentContext.set(0);
+    CurrentContext.erase();
   }
 
   void HandleCrash() {
+    // Eliminate the current context entry, to avoid re-entering in case the
+    // cleanup code crashes.
+    CurrentContext.erase();
+
     assert(!Failed && "Crash recovery context already failed!");
     Failed = true;
 
@@ -46,6 +54,7 @@ public:
 
 }
 
+static sys::Mutex gCrashRecoveryContexMutex;
 static bool gCrashRecoveryEnabled = false;
 
 CrashRecoveryContext::~CrashRecoveryContext() {
@@ -53,11 +62,21 @@ CrashRecoveryContext::~CrashRecoveryContext() {
   delete CRCI;
 }
 
+CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
+  const CrashRecoveryContextImpl *CRCI = CurrentContext.get();
+  if (!CRCI)
+    return 0;
+
+  return CRCI->CRC;
+}
+
 #ifdef LLVM_ON_WIN32
 
 // FIXME: No real Win32 implementation currently.
 
 void CrashRecoveryContext::Enable() {
+  sys::ScopedLock L(gCrashRecoveryContexMutex);
+
   if (gCrashRecoveryEnabled)
     return;
 
@@ -65,6 +84,8 @@ void CrashRecoveryContext::Enable() {
 }
 
 void CrashRecoveryContext::Disable() {
+  sys::ScopedLock L(gCrashRecoveryContexMutex);
+
   if (!gCrashRecoveryEnabled)
     return;
 
@@ -86,18 +107,9 @@ void CrashRecoveryContext::Disable() {
 
 #include <signal.h>
 
-static struct {
-  int Signal;
-  struct sigaction PrevAction;
-} SignalInfo[] = {
-  { SIGABRT, {} },
-  { SIGBUS,  {} },
-  { SIGFPE,  {} },
-  { SIGILL,  {} },
-  { SIGSEGV, {} },
-  { SIGTRAP, {} },
-};
-static const unsigned NumSignals = sizeof(SignalInfo) / sizeof(SignalInfo[0]);
+static int Signals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
+static const unsigned NumSignals = sizeof(Signals) / sizeof(Signals[0]);
+static struct sigaction PrevActions[NumSignals];
 
 static void CrashRecoverySignalHandler(int Signal) {
   // Lookup the current thread local recovery object.
@@ -116,6 +128,9 @@ static void CrashRecoverySignalHandler(int Signal) {
     // This call of Disable isn't thread safe, but it doesn't actually matter.
     CrashRecoveryContext::Disable();
     raise(Signal);
+
+    // The signal will be thrown once the signal mask is restored.
+    return;
   }
 
   // Unblock the signal we received.
@@ -129,6 +144,8 @@ static void CrashRecoverySignalHandler(int Signal) {
 }
 
 void CrashRecoveryContext::Enable() {
+  sys::ScopedLock L(gCrashRecoveryContexMutex);
+
   if (gCrashRecoveryEnabled)
     return;
 
@@ -141,12 +158,13 @@ void CrashRecoveryContext::Enable() {
   sigemptyset(&Handler.sa_mask);
 
   for (unsigned i = 0; i != NumSignals; ++i) {
-    sigaction(SignalInfo[i].Signal, &Handler,
-              &SignalInfo[i].PrevAction);
+    sigaction(Signals[i], &Handler, &PrevActions[i]);
   }
 }
 
 void CrashRecoveryContext::Disable() {
+  sys::ScopedLock L(gCrashRecoveryContexMutex);
+
   if (!gCrashRecoveryEnabled)
     return;
 
@@ -154,7 +172,7 @@ void CrashRecoveryContext::Disable() {
 
   // Restore the previous signal handlers.
   for (unsigned i = 0; i != NumSignals; ++i)
-    sigaction(SignalInfo[i].Signal, &SignalInfo[i].PrevAction, 0);
+    sigaction(Signals[i], &PrevActions[i], 0);
 }
 
 #endif
@@ -163,7 +181,7 @@ bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) {
   // If crash recovery is disabled, do nothing.
   if (gCrashRecoveryEnabled) {
     assert(!Impl && "Crash recovery context already initialized!");
-    CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl;
+    CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
     Impl = CRCI;
 
     if (setjmp(CRCI->JumpBuffer) != 0) {