tsan: do not call malloc/free in memory access handling routine.
This improves signal-/fork-safety of instrumented programs.

llvm-svn: 158988
diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.cc b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
index b8ee589..ebe7df4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_sync.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
@@ -133,7 +133,16 @@
 
 StackTrace::StackTrace()
     : n_()
-    , s_() {
+    , s_()
+    , c_() {
+}
+
+StackTrace::StackTrace(uptr *buf, uptr cnt)
+    : n_()
+    , s_(buf)
+    , c_(cnt) {
+  CHECK_NE(buf, 0);
+  CHECK_NE(cnt, 0);
 }
 
 StackTrace::~StackTrace() {
@@ -141,21 +150,26 @@
 }
 
 void StackTrace::Reset() {
-  if (s_) {
+  if (s_ && !c_) {
     CHECK_NE(n_, 0);
     internal_free(s_);
     s_ = 0;
-    n_ = 0;
   }
+  n_ = 0;
 }
 
 void StackTrace::Init(const uptr *pcs, uptr cnt) {
   Reset();
   if (cnt == 0)
     return;
+  if (c_) {
+    CHECK_NE(s_, 0);
+    CHECK_LE(cnt, c_);
+  } else {
+    s_ = (uptr*)internal_alloc(MBlockStackTrace, cnt * sizeof(s_[0]));
+  }
   n_ = cnt;
-  s_ = (uptr*)internal_alloc(MBlockStackTrace, cnt * sizeof(s_[0]));
-  REAL(memcpy)(s_, pcs, cnt * sizeof(s_[0]));
+  internal_memcpy(s_, pcs, cnt * sizeof(s_[0]));
 }
 
 void StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) {
@@ -163,7 +177,13 @@
   n_ = thr->shadow_stack_pos - &thr->shadow_stack[0];
   if (n_ + !!toppc == 0)
     return;
-  s_ = (uptr*)internal_alloc(MBlockStackTrace, (n_ + !!toppc) * sizeof(s_[0]));
+  if (c_) {
+    CHECK_NE(s_, 0);
+    CHECK_LE(n_ + !!toppc, c_);
+  } else {
+    s_ = (uptr*)internal_alloc(MBlockStackTrace,
+                               (n_ + !!toppc) * sizeof(s_[0]));
+  }
   for (uptr i = 0; i < n_; i++)
     s_[i] = thr->shadow_stack[i];
   if (toppc) {