summaryrefslogtreecommitdiff
path: root/lib/asan/asan_thread.cc
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2013-09-12 08:34:50 +0000
committerKostya Serebryany <kcc@google.com>2013-09-12 08:34:50 +0000
commitc98fc1f8e52812cfaf5b19a29db5ed56acb0a682 (patch)
treec90e96b56b5a6a608fe37000297c40afb2bef68e /lib/asan/asan_thread.cc
parent96a575f05b2a45774170a118ea69ddae3659b645 (diff)
[asan] hopefully make the FakeStack async-signal safe, enable the related test
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@190592 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/asan/asan_thread.cc')
-rw-r--r--lib/asan/asan_thread.cc21
1 files changed, 21 insertions, 0 deletions
diff --git a/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc
index 64d07ca0d..5bea433fb 100644
--- a/lib/asan/asan_thread.cc
+++ b/lib/asan/asan_thread.cc
@@ -107,6 +107,27 @@ void AsanThread::Destroy() {
UnmapOrDie(this, size);
}
+// We want to create the FakeStack lazyly on the first use, but not eralier
+// than the stack size is known and the procedure has to be async-signal safe.
+FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
+ uptr stack_size = this->stack_size();
+ if (stack_size == 0) // stack_size is not yet available, don't use FakeStack.
+ return 0;
+ uptr old_val = 0;
+ // fake_stack_ has 3 states:
+ // 0 -- not initialized
+ // 1 -- being initialized
+ // ptr -- initialized
+ // This CAS checks if the state was 0 and if so changes it to state 1,
+ // 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)));
+ return 0;
+}
+
void AsanThread::Init() {
SetThreadStackAndTls();
CHECK(AddrIsInMem(stack_bottom_));