<div dir="ltr">There's so much copy-paste (from ASan) it hurts.<div><br></div><div>Why didn't you use ThreadRegistry as well? We'd get LSan support for free.</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Fri, Apr 4, 2014 at 1:47 PM, Evgeniy Stepanov <span dir="ltr"><<a href="mailto:eugeni.stepanov@gmail.com" target="_blank">eugeni.stepanov@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: eugenis<br>
Date: Fri Apr  4 04:47:41 2014<br>
New Revision: 205618<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=205618&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=205618&view=rev</a><br>
Log:<br>
[msan] Introduce MsanThread. Move thread-local allocator cache out of TLS.<br>
<br>
This reduces .tbss from 109K down to almost nothing.<br>
<br>
Added:<br>
    compiler-rt/trunk/lib/msan/msan_allocator.h   (with props)<br>
    compiler-rt/trunk/lib/msan/msan_thread.cc   (with props)<br>
    compiler-rt/trunk/lib/msan/msan_thread.h   (with props)<br>
Modified:<br>
    compiler-rt/trunk/lib/msan/CMakeLists.txt<br>
    compiler-rt/trunk/lib/msan/msan.cc<br>
    compiler-rt/trunk/lib/msan/msan.h<br>
    compiler-rt/trunk/lib/msan/msan_allocator.cc<br>
    compiler-rt/trunk/lib/msan/msan_interceptors.cc<br>
    compiler-rt/trunk/lib/msan/msan_linux.cc<br>
    compiler-rt/trunk/lib/msan/tests/msan_test.cc<br>
<br>
Modified: compiler-rt/trunk/lib/msan/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/CMakeLists.txt?rev=205618&r1=205617&r2=205618&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/CMakeLists.txt?rev=205618&r1=205617&r2=205618&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/CMakeLists.txt (original)<br>
+++ compiler-rt/trunk/lib/msan/CMakeLists.txt Fri Apr  4 04:47:41 2014<br>
@@ -8,6 +8,7 @@ set(MSAN_RTL_SOURCES<br>
   msan_linux.cc<br>
   msan_new_delete.cc<br>
   msan_report.cc<br>
+  msan_thread.cc<br>
   )<br>
<br>
 set(MSAN_RTL_CFLAGS ${SANITIZER_COMMON_CFLAGS})<br>
<br>
Modified: compiler-rt/trunk/lib/msan/msan.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=205618&r1=205617&r2=205618&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=205618&r1=205617&r2=205618&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/msan.cc Fri Apr  4 04:47:41 2014<br>
@@ -13,6 +13,7 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "msan.h"<br>
+#include "msan_thread.h"<br>
 #include "sanitizer_common/sanitizer_atomic.h"<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
@@ -59,8 +60,6 @@ THREADLOCAL u64 __msan_va_arg_overflow_s<br>
 SANITIZER_INTERFACE_ATTRIBUTE<br>
 THREADLOCAL u32 __msan_origin_tls;<br>
<br>
-THREADLOCAL MsanStackBounds msan_stack_bounds;<br>
-<br>
 static THREADLOCAL int is_in_symbolizer;<br>
 static THREADLOCAL int is_in_loader;<br>
<br>
@@ -154,14 +153,14 @@ static void InitializeFlags(Flags *f, co<br>
<br>
 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,<br>
                    bool request_fast_unwind) {<br>
-  if (!StackTrace::WillUseFastUnwind(request_fast_unwind)) {<br>
+  MsanThread *t = GetCurrentThread();<br>
+  if (!t || !StackTrace::WillUseFastUnwind(request_fast_unwind)) {<br>
     // Block reports from our interceptors during _Unwind_Backtrace.<br>
     SymbolizerScope sym_scope;<br>
     return stack->Unwind(max_s, pc, bp, 0, 0, 0, request_fast_unwind);<br>
   }<br>
-  uptr stack_bottom = msan_stack_bounds.stack_addr;<br>
-  uptr stack_top = stack_bottom + msan_stack_bounds.stack_size;<br>
-  stack->Unwind(max_s, pc, bp, 0, stack_top, stack_bottom, request_fast_unwind);<br>
+  stack->Unwind(max_s, pc, bp, 0, t->stack_top(), t->stack_bottom(),<br>
+                request_fast_unwind);<br>
 }<br>
<br>
 void PrintWarning(uptr pc, uptr bp) {<br>
@@ -315,10 +314,12 @@ void __msan_init() {<br>
   Symbolizer::Init(common_flags()->external_symbolizer_path);<br>
   Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer);<br>
<br>
-  GetThreadStackAndTls(/* main */ true, &msan_stack_bounds.stack_addr,<br>
-                       &msan_stack_bounds.stack_size,<br>
-                       &msan_stack_bounds.tls_addr,<br>
-                       &msan_stack_bounds.tls_size);<br>
+  MsanTSDInit(MsanTSDDtor);<br>
+<br>
+  MsanThread *main_thread = MsanThread::Create(0, 0);<br>
+  SetCurrentThread(main_thread);<br>
+  main_thread->ThreadStart();<br>
+<br>
   VPrintf(1, "MemorySanitizer init done\n");<br>
<br>
   msan_init_is_running = 0;<br>
<br>
Modified: compiler-rt/trunk/lib/msan/msan.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=205618&r1=205617&r2=205618&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=205618&r1=205617&r2=205618&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan.h (original)<br>
+++ compiler-rt/trunk/lib/msan/msan.h Fri Apr  4 04:47:41 2014<br>
@@ -128,6 +128,11 @@ class ScopedThreadLocalStateBackup {<br>
<br>
 extern void (*death_callback)(void);<br>
<br>
+void MsanTSDInit(void (*destructor)(void *tsd));<br>
+void *MsanTSDGet();<br>
+void MsanTSDSet(void *tsd);<br>
+void MsanTSDDtor(void *tsd);<br>
+<br>
 }  // namespace __msan<br>
<br>
 #define MSAN_MALLOC_HOOK(ptr, size) \<br>
@@ -135,11 +140,4 @@ extern void (*death_callback)(void);<br>
 #define MSAN_FREE_HOOK(ptr) \<br>
   if (&__msan_free_hook) __msan_free_hook(ptr)<br>
<br>
-struct MsanStackBounds {<br>
-  uptr stack_addr, stack_size;<br>
-  uptr tls_addr, tls_size;<br>
-};<br>
-<br>
-extern THREADLOCAL MsanStackBounds msan_stack_bounds;<br>
-<br>
 #endif  // MSAN_H<br>
<br>
Modified: compiler-rt/trunk/lib/msan/msan_allocator.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.cc?rev=205618&r1=205617&r2=205618&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.cc?rev=205618&r1=205617&r2=205618&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan_allocator.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/msan_allocator.cc Fri Apr  4 04:47:41 2014<br>
@@ -15,6 +15,8 @@<br>
 #include "sanitizer_common/sanitizer_allocator.h"<br>
 #include "sanitizer_common/sanitizer_stackdepot.h"<br>
 #include "msan.h"<br>
+#include "msan_allocator.h"<br>
+#include "msan_thread.h"<br>
<br>
 namespace __msan {<br>
<br>
@@ -48,8 +50,9 @@ typedef LargeMmapAllocator<MsanMapUnmapC<br>
 typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,<br>
                           SecondaryAllocator> Allocator;<br>
<br>
-static THREADLOCAL AllocatorCache cache;<br>
 static Allocator allocator;<br>
+static AllocatorCache fallback_allocator_cache;<br>
+static SpinMutex fallback_mutex;<br>
<br>
 static int inited = 0;<br>
<br>
@@ -60,35 +63,51 @@ static inline void Init() {<br>
   allocator.Init();<br>
 }<br>
<br>
-void MsanAllocatorThreadFinish() {<br>
-  allocator.SwallowCache(&cache);<br>
+AllocatorCache *GetAllocatorCache(MsanThreadLocalMallocStorage *ms) {<br>
+  CHECK(ms);<br>
+  CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache));<br>
+  return reinterpret_cast<AllocatorCache *>(ms->allocator_cache);<br>
 }<br>
<br>
-static void *MsanAllocate(StackTrace *stack, uptr size,<br>
-                          uptr alignment, bool zeroise) {<br>
+void MsanThreadLocalMallocStorage::CommitBack() {<br>
+  allocator.SwallowCache(GetAllocatorCache(this));<br>
+}<br>
+<br>
+static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,<br>
+                          bool zeroise) {<br>
   Init();<br>
   if (size > kMaxAllowedMallocSize) {<br>
     Report("WARNING: MemorySanitizer failed to allocate %p bytes\n",<br>
            (void *)size);<br>
     return AllocatorReturnNull();<br>
   }<br>
-  void *res = allocator.Allocate(&cache, size, alignment, false);<br>
-  Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(res));<br>
+  MsanThread *t = GetCurrentThread();<br>
+  void *allocated;<br>
+  if (t) {<br>
+    AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());<br>
+    allocated = allocator.Allocate(cache, size, alignment, false);<br>
+  } else {<br>
+    SpinMutexLock l(&fallback_mutex);<br>
+    AllocatorCache *cache = &fallback_allocator_cache;<br>
+    allocated = allocator.Allocate(cache, size, alignment, false);<br>
+  }<br>
+  Metadata *meta =<br>
+      reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));<br>
   meta->requested_size = size;<br>
   if (zeroise) {<br>
-    __msan_clear_and_unpoison(res, size);<br>
+    __msan_clear_and_unpoison(allocated, size);<br>
   } else if (flags()->poison_in_malloc) {<br>
-    __msan_poison(res, size);<br>
+    __msan_poison(allocated, size);<br>
     if (__msan_get_track_origins()) {<br>
       u32 stack_id = StackDepotPut(stack->trace, stack->size);<br>
       CHECK(stack_id);<br>
       CHECK_EQ((stack_id >> 31),<br>
                0);  // Higher bit is occupied by stack origins.<br>
-      __msan_set_origin(res, size, stack_id);<br>
+      __msan_set_origin(allocated, size, stack_id);<br>
     }<br>
   }<br>
-  MSAN_MALLOC_HOOK(res, size);<br>
-  return res;<br>
+  MSAN_MALLOC_HOOK(allocated, size);<br>
+  return allocated;<br>
 }<br>
<br>
 void MsanDeallocate(StackTrace *stack, void *p) {<br>
@@ -110,7 +129,15 @@ void MsanDeallocate(StackTrace *stack, v<br>
       __msan_set_origin(p, size, stack_id);<br>
     }<br>
   }<br>
-  allocator.Deallocate(&cache, p);<br>
+  MsanThread *t = GetCurrentThread();<br>
+  if (t) {<br>
+    AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());<br>
+    allocator.Deallocate(cache, p);<br>
+  } else {<br>
+    SpinMutexLock l(&fallback_mutex);<br>
+    AllocatorCache *cache = &fallback_allocator_cache;<br>
+    allocator.Deallocate(cache, p);<br>
+  }<br>
 }<br>
<br>
 void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size,<br>
<br>
Added: compiler-rt/trunk/lib/msan/msan_allocator.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.h?rev=205618&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.h?rev=205618&view=auto</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan_allocator.h (added)<br>
+++ compiler-rt/trunk/lib/msan/msan_allocator.h Fri Apr  4 04:47:41 2014<br>
@@ -0,0 +1,33 @@<br>
+//===-- msan_allocator.h ----------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file is a part of MemorySanitizer.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef MSAN_ALLOCATOR_H<br>
+#define MSAN_ALLOCATOR_H<br>
+<br>
+#include "sanitizer_common/sanitizer_common.h"<br>
+<br>
+namespace __msan {<br>
+<br>
+struct MsanThreadLocalMallocStorage {<br>
+  uptr quarantine_cache[16];<br>
+  // Allocator cache contains atomic_uint64_t which must be 8-byte aligned.<br>
+  ALIGNED(8) uptr allocator_cache[96 * (512 * 8 + 16)];  // Opaque.<br>
+  void CommitBack();<br>
+<br>
+ private:<br>
+  // These objects are allocated via mmap() and are zero-initialized.<br>
+  MsanThreadLocalMallocStorage() {}<br>
+};<br>
+<br>
+} // namespace __msan<br>
+#endif // MSAN_ALLOCATOR_H<br>
<br>
Propchange: compiler-rt/trunk/lib/msan/msan_allocator.h<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = LF<br>
<br>
Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=205618&r1=205617&r2=205618&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=205618&r1=205617&r2=205618&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Fri Apr  4 04:47:41 2014<br>
@@ -16,6 +16,7 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "msan.h"<br>
+#include "msan_thread.h"<br>
 #include "sanitizer_common/sanitizer_platform_limits_posix.h"<br>
 #include "sanitizer_common/sanitizer_allocator.h"<br>
 #include "sanitizer_common/sanitizer_allocator_internal.h"<br>
@@ -37,8 +38,6 @@ using __sanitizer::atomic_load;<br>
 using __sanitizer::atomic_store;<br>
 using __sanitizer::atomic_uintptr_t;<br>
<br>
-static unsigned g_thread_finalize_key;<br>
-<br>
 // True if this is a nested interceptor.<br>
 static THREADLOCAL int in_interceptor_scope;<br>
<br>
@@ -1038,48 +1037,11 @@ INTERCEPTOR(int, signal, int signo, uptr<br>
<br>
 extern "C" int pthread_attr_init(void *attr);<br>
 extern "C" int pthread_attr_destroy(void *attr);<br>
-extern "C" int pthread_setspecific(unsigned key, const void *v);<br>
-extern "C" int pthread_yield();<br>
-<br>
-static void thread_finalize(void *v) {<br>
-  uptr iter = (uptr)v;<br>
-  if (iter > 1) {<br>
-    if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {<br>
-      Printf("MemorySanitizer: failed to set thread key\n");<br>
-      Die();<br>
-    }<br>
-    return;<br>
-  }<br>
-  MsanAllocatorThreadFinish();<br>
-  __msan_unpoison((void *)msan_stack_bounds.stack_addr,<br>
-                  msan_stack_bounds.stack_size);<br>
-  if (msan_stack_bounds.tls_size)<br>
-    __msan_unpoison((void *)msan_stack_bounds.tls_addr,<br>
-                    msan_stack_bounds.tls_size);<br>
-}<br>
-<br>
-struct ThreadParam {<br>
-  void* (*callback)(void *arg);<br>
-  void *param;<br>
-  atomic_uintptr_t done;<br>
-};<br>
<br>
 static void *MsanThreadStartFunc(void *arg) {<br>
-  ThreadParam *p = (ThreadParam *)arg;<br>
-  void* (*callback)(void *arg) = p->callback;<br>
-  void *param = p->param;<br>
-  if (pthread_setspecific(g_thread_finalize_key,<br>
-          (void *)kPthreadDestructorIterations)) {<br>
-    Printf("MemorySanitizer: failed to set thread key\n");<br>
-    Die();<br>
-  }<br>
-  atomic_store(&p->done, 1, memory_order_release);<br>
-<br>
-  GetThreadStackAndTls(/* main */ false, &msan_stack_bounds.stack_addr,<br>
-                       &msan_stack_bounds.stack_size,<br>
-                       &msan_stack_bounds.tls_addr,<br>
-                       &msan_stack_bounds.tls_size);<br>
-  return IndirectExternCall(callback)(param);<br>
+  MsanThread *t = (MsanThread *)arg;<br>
+  SetCurrentThread(t);<br>
+  return t->ThreadStart();<br>
 }<br>
<br>
 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),<br>
@@ -1093,16 +1055,9 @@ INTERCEPTOR(int, pthread_create, void *t<br>
<br>
   AdjustStackSize(attr);<br>
<br>
-  ThreadParam p;<br>
-  p.callback = callback;<br>
-  p.param = param;<br>
-  atomic_store(&p.done, 0, memory_order_relaxed);<br>
+  MsanThread *t = MsanThread::Create(callback, param);<br>
<br>
-  int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, (void *)&p);<br>
-  if (res == 0) {<br>
-    while (atomic_load(&p.done, memory_order_acquire) != 1)<br>
-      pthread_yield();<br>
-  }<br>
+  int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);<br>
<br>
   if (attr == &myattr)<br>
     pthread_attr_destroy(&myattr);<br>
@@ -1114,6 +1069,7 @@ INTERCEPTOR(int, pthread_create, void *t<br>
<br>
 INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,<br>
             void (*dtor)(void *value)) {<br>
+  if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);<br>
   ENSURE_MSAN_INITED();<br>
   int res = REAL(pthread_key_create)(key, dtor);<br>
   if (!res && key)<br>
@@ -1368,6 +1324,8 @@ void __msan_clear_and_unpoison(void *a,<br>
 }<br>
<br>
 void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {<br>
+  if (!msan_inited) return internal_memcpy(dest, src, n);<br>
+  if (msan_init_is_running) return REAL(memcpy)(dest, src, n);<br>
   ENSURE_MSAN_INITED();<br>
   GET_STORE_STACK_TRACE;<br>
   void *res = fast_memcpy(dest, src, n);<br>
@@ -1376,6 +1334,8 @@ void *__msan_memcpy(void *dest, const vo<br>
 }<br>
<br>
 void *__msan_memset(void *s, int c, SIZE_T n) {<br>
+  if (!msan_inited) return internal_memset(s, c, n);<br>
+  if (msan_init_is_running) return REAL(memset)(s, c, n);<br>
   ENSURE_MSAN_INITED();<br>
   void *res = fast_memset(s, c, n);<br>
   __msan_unpoison(s, n);<br>
@@ -1383,6 +1343,8 @@ void *__msan_memset(void *s, int c, SIZE<br>
 }<br>
<br>
 void *__msan_memmove(void *dest, const void *src, SIZE_T n) {<br>
+  if (!msan_inited) return internal_memmove(dest, src, n);<br>
+  if (msan_init_is_running) return REAL(memmove)(dest, src, n);<br>
   ENSURE_MSAN_INITED();<br>
   GET_STORE_STACK_TRACE;<br>
   void *res = REAL(memmove)(dest, src, n);<br>
@@ -1603,11 +1565,6 @@ void InitializeInterceptors() {<br>
   INTERCEPT_FUNCTION(__cxa_atexit);<br>
   INTERCEPT_FUNCTION(shmat);<br>
<br>
-  if (REAL(pthread_key_create)(&g_thread_finalize_key, &thread_finalize)) {<br>
-    Printf("MemorySanitizer: failed to create thread key\n");<br>
-    Die();<br>
-  }<br>
-<br>
   inited = 1;<br>
 }<br>
 }  // namespace __msan<br>
<br>
Modified: compiler-rt/trunk/lib/msan/msan_linux.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_linux.cc?rev=205618&r1=205617&r2=205618&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_linux.cc?rev=205618&r1=205617&r2=205618&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan_linux.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/msan_linux.cc Fri Apr  4 04:47:41 2014<br>
@@ -16,9 +16,11 @@<br>
 #if SANITIZER_LINUX<br>
<br>
 #include "msan.h"<br>
+#include "msan_thread.h"<br>
<br>
 #include <elf.h><br>
 #include <link.h><br>
+#include <pthread.h><br>
 #include <stdio.h><br>
 #include <stdlib.h><br>
 #include <signal.h><br>
@@ -97,6 +99,36 @@ void InstallAtExitHandler() {<br>
   atexit(MsanAtExit);<br>
 }<br>
<br>
+// ---------------------- TSD ---------------- {{{1<br>
+<br>
+static pthread_key_t tsd_key;<br>
+static bool tsd_key_inited = false;<br>
+void MsanTSDInit(void (*destructor)(void *tsd)) {<br>
+  CHECK(!tsd_key_inited);<br>
+  tsd_key_inited = true;<br>
+  CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));<br>
+}<br>
+<br>
+void *MsanTSDGet() {<br>
+  CHECK(tsd_key_inited);<br>
+  return pthread_getspecific(tsd_key);<br>
+}<br>
+<br>
+void MsanTSDSet(void *tsd) {<br>
+  CHECK(tsd_key_inited);<br>
+  pthread_setspecific(tsd_key, tsd);<br>
+}<br>
+<br>
+void MsanTSDDtor(void *tsd) {<br>
+  MsanThread *t = (MsanThread*)tsd;<br>
+  if (t->destructor_iterations_ > 1) {<br>
+    t->destructor_iterations_--;<br>
+    CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));<br>
+    return;<br>
+  }<br>
+  MsanThread::TSDDtor(tsd);<br>
+}<br>
+<br>
 }  // namespace __msan<br>
<br>
 #endif  // __linux__<br>
<br>
Added: compiler-rt/trunk/lib/msan/msan_thread.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_thread.cc?rev=205618&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_thread.cc?rev=205618&view=auto</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan_thread.cc (added)<br>
+++ compiler-rt/trunk/lib/msan/msan_thread.cc Fri Apr  4 04:47:41 2014<br>
@@ -0,0 +1,86 @@<br>
+<br>
+#include "msan.h"<br>
+#include "msan_thread.h"<br>
+#include "msan_interface_internal.h"<br>
+<br>
+namespace __msan {<br>
+<br>
+MsanThread *MsanThread::Create(thread_callback_t start_routine,<br>
+                               void *arg) {<br>
+  uptr PageSize = GetPageSizeCached();<br>
+  uptr size = RoundUpTo(sizeof(MsanThread), PageSize);<br>
+  MsanThread *thread = (MsanThread*)MmapOrDie(size, __func__);<br>
+  thread->start_routine_ = start_routine;<br>
+  thread->arg_ = arg;<br>
+  thread->destructor_iterations_ = kPthreadDestructorIterations;<br>
+<br>
+  return thread;<br>
+}<br>
+<br>
+void MsanThread::SetThreadStackAndTls() {<br>
+  uptr tls_size = 0;<br>
+  uptr stack_size = 0;<br>
+  GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size,<br>
+                       &tls_begin_, &tls_size);<br>
+  stack_top_ = stack_bottom_ + stack_size;<br>
+  tls_end_ = tls_begin_ + tls_size;<br>
+<br>
+  int local;<br>
+  CHECK(AddrIsInStack((uptr)&local));<br>
+}<br>
+<br>
+void MsanThread::ClearShadowForThreadStackAndTLS() {<br>
+  __msan_unpoison((void *)stack_bottom_, stack_top_ - stack_bottom_);<br>
+  if (tls_begin_ != tls_end_)<br>
+    __msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_);<br>
+}<br>
+<br>
+void MsanThread::Init() {<br>
+  SetThreadStackAndTls();<br>
+  CHECK(MEM_IS_APP(stack_bottom_));<br>
+  CHECK(MEM_IS_APP(stack_top_ - 1));<br>
+  ClearShadowForThreadStackAndTLS();<br>
+}<br>
+<br>
+void MsanThread::TSDDtor(void *tsd) {<br>
+  MsanThread *t = (MsanThread*)tsd;<br>
+  t->Destroy();<br>
+}<br>
+<br>
+void MsanThread::Destroy() {<br>
+  malloc_storage().CommitBack();<br>
+  // We also clear the shadow on thread destruction because<br>
+  // some code may still be executing in later TSD destructors<br>
+  // and we don't want it to have any poisoned stack.<br>
+  ClearShadowForThreadStackAndTLS();<br>
+  uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());<br>
+  UnmapOrDie(this, size);<br>
+}<br>
+<br>
+thread_return_t MsanThread::ThreadStart() {<br>
+  Init();<br>
+<br>
+  if (!start_routine_) {<br>
+    // start_routine_ == 0 if we're on the main thread or on one of the<br>
+    // OS X libdispatch worker threads. But nobody is supposed to call<br>
+    // ThreadStart() for the worker threads.<br>
+    return 0;<br>
+  }<br>
+<br>
+  thread_return_t res = IndirectExternCall(start_routine_)(arg_);<br>
+<br>
+  return res;<br>
+}<br>
+<br>
+MsanThread *GetCurrentThread() {<br>
+  return reinterpret_cast<MsanThread *>(MsanTSDGet());<br>
+}<br>
+<br>
+void SetCurrentThread(MsanThread *t) {<br>
+  // Make sure we do not reset the current MsanThread.<br>
+  CHECK_EQ(0, MsanTSDGet());<br>
+  MsanTSDSet(t);<br>
+  CHECK_EQ(t, MsanTSDGet());<br>
+}<br>
+<br>
+} // namespace __msan<br>
<br>
Propchange: compiler-rt/trunk/lib/msan/msan_thread.cc<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = LF<br>
<br>
Added: compiler-rt/trunk/lib/msan/msan_thread.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_thread.h?rev=205618&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_thread.h?rev=205618&view=auto</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan_thread.h (added)<br>
+++ compiler-rt/trunk/lib/msan/msan_thread.h Fri Apr  4 04:47:41 2014<br>
@@ -0,0 +1,65 @@<br>
+//===-- msan_thread.h -------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file is a part of MemorySanitizer.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef MSAN_THREAD_H<br>
+#define MSAN_THREAD_H<br>
+<br>
+#include "msan_allocator.h"<br>
+#include "sanitizer_common/sanitizer_common.h"<br>
+<br>
+namespace __msan {<br>
+<br>
+class MsanThread {<br>
+ public:<br>
+  static MsanThread *Create(thread_callback_t start_routine, void *arg);<br>
+  static void TSDDtor(void *tsd);<br>
+  void Destroy();<br>
+<br>
+  void Init();  // Should be called from the thread itself.<br>
+  thread_return_t ThreadStart();<br>
+<br>
+  uptr stack_top() { return stack_top_; }<br>
+  uptr stack_bottom() { return stack_bottom_; }<br>
+  uptr tls_begin() { return tls_begin_; }<br>
+  uptr tls_end() { return tls_end_; }<br>
+  bool IsMainThread() { return start_routine_ == 0; }<br>
+<br>
+  bool AddrIsInStack(uptr addr) {<br>
+    return addr >= stack_bottom_ && addr < stack_top_;<br>
+  }<br>
+<br>
+  MsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }<br>
+<br>
+  int destructor_iterations_;<br>
+<br>
+ private:<br>
+  // NOTE: There is no MsanThread constructor. It is allocated<br>
+  // via mmap() and *must* be valid in zero-initialized state.<br>
+  void SetThreadStackAndTls();<br>
+  void ClearShadowForThreadStackAndTLS();<br>
+  thread_callback_t start_routine_;<br>
+  void *arg_;<br>
+  uptr stack_top_;<br>
+  uptr stack_bottom_;<br>
+  uptr tls_begin_;<br>
+  uptr tls_end_;<br>
+<br>
+  MsanThreadLocalMallocStorage malloc_storage_;<br>
+};<br>
+<br>
+MsanThread *GetCurrentThread();<br>
+void SetCurrentThread(MsanThread *t);<br>
+<br>
+} // namespace __msan<br>
+<br>
+#endif // MSAN_THREAD_H<br>
<br>
Propchange: compiler-rt/trunk/lib/msan/msan_thread.h<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = LF<br>
<br>
Modified: compiler-rt/trunk/lib/msan/tests/msan_test.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/tests/msan_test.cc?rev=205618&r1=205617&r2=205618&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/tests/msan_test.cc?rev=205618&r1=205617&r2=205618&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/tests/msan_test.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/tests/msan_test.cc Fri Apr  4 04:47:41 2014<br>
@@ -2818,22 +2818,22 @@ TEST(MemorySanitizer, SmallStackThread)<br>
   ASSERT_EQ(0, res);<br>
 }<br>
<br>
-TEST(MemorySanitizer, PreAllocatedStackThread) {<br>
+TEST(MemorySanitizer, SmallPreAllocatedStackThread) {<br>
   pthread_attr_t attr;<br>
   pthread_t t;<br>
   int res;<br>
   res = pthread_attr_init(&attr);<br>
   ASSERT_EQ(0, res);<br>
   void *stack;<br>
-  const size_t kStackSize = 64 * 1024;<br>
+  const size_t kStackSize = 16 * 1024;<br>
   res = posix_memalign(&stack, 4096, kStackSize);<br>
   ASSERT_EQ(0, res);<br>
   res = pthread_attr_setstack(&attr, stack, kStackSize);<br>
   ASSERT_EQ(0, res);<br>
-  // A small self-allocated stack can not be extended by the tool.<br>
-  // In this case pthread_create is expected to fail.<br>
   res = pthread_create(&t, &attr, SmallStackThread_threadfn, NULL);<br>
-  EXPECT_NE(0, res);<br>
+  EXPECT_EQ(0, res);<br>
+  res = pthread_join(t, NULL);<br>
+  ASSERT_EQ(0, res);<br>
   res = pthread_attr_destroy(&attr);<br>
   ASSERT_EQ(0, res);<br>
 }<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>