[asan] second attempt to use TLS with fake stack. This time it looks (more) async-signal safe.

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@190663 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_fake_stack.cc b/lib/asan/asan_fake_stack.cc
index bcaf0f4..4636650 100644
--- a/lib/asan/asan_fake_stack.cc
+++ b/lib/asan/asan_fake_stack.cc
@@ -122,6 +122,20 @@
   needs_gc_ = false;
 }
 
+#if SANITIZER_LINUX
+static THREADLOCAL FakeStack *fake_stack_tls;
+
+FakeStack *GetTLSFakeStack() {
+  return fake_stack_tls;
+}
+void SetTLSFakeStack(FakeStack *fs) {
+  fake_stack_tls = fs;
+}
+#else
+FakeStack *GetTLSFakeStack() { return 0; }
+void SetTLSFakeStack(FakeStack *fs) { }
+#endif  // SANITIZER_LINUX
+
 static FakeStack *GetFakeStack() {
   AsanThread *t = GetCurrentThread();
   if (!t) return 0;
@@ -129,14 +143,9 @@
 }
 
 static FakeStack *GetFakeStackFast() {
-#if 0 && SANITIZER_LINUX  // breaks with signals...
-  static THREADLOCAL FakeStack *fake_stack;
-  if (!fake_stack)
-    fake_stack = GetFakeStack();
-  return fake_stack;
-#else
+  if (FakeStack *fs = GetTLSFakeStack())
+    return fs;
   return GetFakeStack();
-#endif
 }
 
 ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size, uptr real_stack) {
diff --git a/lib/asan/asan_fake_stack.h b/lib/asan/asan_fake_stack.h
index 62ef1d2..9f1da63 100644
--- a/lib/asan/asan_fake_stack.h
+++ b/lib/asan/asan_fake_stack.h
@@ -168,6 +168,9 @@
   bool needs_gc_;
 };
 
+FakeStack *GetTLSFakeStack();
+void SetTLSFakeStack(FakeStack *fs);
+
 }  // namespace __asan
 
 #endif  // ASAN_FAKE_STACK_H
diff --git a/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc
index 3912e04..322caa8 100644
--- a/lib/asan/asan_thread.cc
+++ b/lib/asan/asan_thread.cc
@@ -122,9 +122,11 @@
   // if that was successfull, it initilizes the pointer.
   if (atomic_compare_exchange_strong(
       reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
-      memory_order_relaxed))
-    return fake_stack_ =
-               FakeStack::Create(Log2(RoundUpToPowerOfTwo(stack_size)));
+      memory_order_relaxed)) {
+    fake_stack_ = FakeStack::Create(Log2(RoundUpToPowerOfTwo(stack_size)));
+    SetTLSFakeStack(fake_stack_);
+    return fake_stack_;
+  }
   return 0;
 }
 
diff --git a/lib/asan/asan_thread.h b/lib/asan/asan_thread.h
index 8633e5d..29e30ff 100644
--- a/lib/asan/asan_thread.h
+++ b/lib/asan/asan_thread.h
@@ -78,7 +78,10 @@
   void DeleteFakeStack() {
     if (!fake_stack_) return;
     fake_stack_->PoisonAll(0);
-    fake_stack_->Destroy();
+    FakeStack *t = fake_stack_;
+    fake_stack_ = 0;
+    SetTLSFakeStack(0);
+    t->Destroy();
   }
 
   bool has_fake_stack() {