[compiler-rt] r205618 - [msan] Introduce MsanThread. Move thread-local allocator cache out of TLS.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Tue Apr 8 14:48:57 PDT 2014


On Fri, Apr 4, 2014 at 7:28 PM, Sergey Matveev <earthdok at google.com> wrote:
> There's so much copy-paste (from ASan) it hurts.

Well, now that we have similar stuff in all 3 tools, common parts can
be easily factored out.
We could have done it the other way around, too...

> Why didn't you use ThreadRegistry as well? We'd get LSan support for free.

I did not realize the LSan part. Other than that, it's just extra work
(and runtime overhead, the worst kind of it - proportional to the
number of ever-existed threads) without benefits. LSan is a good
reason to do it.

>
>
> On Fri, Apr 4, 2014 at 1:47 PM, Evgeniy Stepanov <eugeni.stepanov at gmail.com>
> wrote:
>>
>> Author: eugenis
>> Date: Fri Apr  4 04:47:41 2014
>> New Revision: 205618
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=205618&view=rev
>> Log:
>> [msan] Introduce MsanThread. Move thread-local allocator cache out of TLS.
>>
>> This reduces .tbss from 109K down to almost nothing.
>>
>> Added:
>>     compiler-rt/trunk/lib/msan/msan_allocator.h   (with props)
>>     compiler-rt/trunk/lib/msan/msan_thread.cc   (with props)
>>     compiler-rt/trunk/lib/msan/msan_thread.h   (with props)
>> Modified:
>>     compiler-rt/trunk/lib/msan/CMakeLists.txt
>>     compiler-rt/trunk/lib/msan/msan.cc
>>     compiler-rt/trunk/lib/msan/msan.h
>>     compiler-rt/trunk/lib/msan/msan_allocator.cc
>>     compiler-rt/trunk/lib/msan/msan_interceptors.cc
>>     compiler-rt/trunk/lib/msan/msan_linux.cc
>>     compiler-rt/trunk/lib/msan/tests/msan_test.cc
>>
>> Modified: compiler-rt/trunk/lib/msan/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/CMakeLists.txt?rev=205618&r1=205617&r2=205618&view=diff
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/CMakeLists.txt (original)
>> +++ compiler-rt/trunk/lib/msan/CMakeLists.txt Fri Apr  4 04:47:41 2014
>> @@ -8,6 +8,7 @@ set(MSAN_RTL_SOURCES
>>    msan_linux.cc
>>    msan_new_delete.cc
>>    msan_report.cc
>> +  msan_thread.cc
>>    )
>>
>>  set(MSAN_RTL_CFLAGS ${SANITIZER_COMMON_CFLAGS})
>>
>> Modified: compiler-rt/trunk/lib/msan/msan.cc
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=205618&r1=205617&r2=205618&view=diff
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan.cc (original)
>> +++ compiler-rt/trunk/lib/msan/msan.cc Fri Apr  4 04:47:41 2014
>> @@ -13,6 +13,7 @@
>>
>> //===----------------------------------------------------------------------===//
>>
>>  #include "msan.h"
>> +#include "msan_thread.h"
>>  #include "sanitizer_common/sanitizer_atomic.h"
>>  #include "sanitizer_common/sanitizer_common.h"
>>  #include "sanitizer_common/sanitizer_flags.h"
>> @@ -59,8 +60,6 @@ THREADLOCAL u64 __msan_va_arg_overflow_s
>>  SANITIZER_INTERFACE_ATTRIBUTE
>>  THREADLOCAL u32 __msan_origin_tls;
>>
>> -THREADLOCAL MsanStackBounds msan_stack_bounds;
>> -
>>  static THREADLOCAL int is_in_symbolizer;
>>  static THREADLOCAL int is_in_loader;
>>
>> @@ -154,14 +153,14 @@ static void InitializeFlags(Flags *f, co
>>
>>  void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
>>                     bool request_fast_unwind) {
>> -  if (!StackTrace::WillUseFastUnwind(request_fast_unwind)) {
>> +  MsanThread *t = GetCurrentThread();
>> +  if (!t || !StackTrace::WillUseFastUnwind(request_fast_unwind)) {
>>      // Block reports from our interceptors during _Unwind_Backtrace.
>>      SymbolizerScope sym_scope;
>>      return stack->Unwind(max_s, pc, bp, 0, 0, 0, request_fast_unwind);
>>    }
>> -  uptr stack_bottom = msan_stack_bounds.stack_addr;
>> -  uptr stack_top = stack_bottom + msan_stack_bounds.stack_size;
>> -  stack->Unwind(max_s, pc, bp, 0, stack_top, stack_bottom,
>> request_fast_unwind);
>> +  stack->Unwind(max_s, pc, bp, 0, t->stack_top(), t->stack_bottom(),
>> +                request_fast_unwind);
>>  }
>>
>>  void PrintWarning(uptr pc, uptr bp) {
>> @@ -315,10 +314,12 @@ void __msan_init() {
>>    Symbolizer::Init(common_flags()->external_symbolizer_path);
>>    Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer);
>>
>> -  GetThreadStackAndTls(/* main */ true, &msan_stack_bounds.stack_addr,
>> -                       &msan_stack_bounds.stack_size,
>> -                       &msan_stack_bounds.tls_addr,
>> -                       &msan_stack_bounds.tls_size);
>> +  MsanTSDInit(MsanTSDDtor);
>> +
>> +  MsanThread *main_thread = MsanThread::Create(0, 0);
>> +  SetCurrentThread(main_thread);
>> +  main_thread->ThreadStart();
>> +
>>    VPrintf(1, "MemorySanitizer init done\n");
>>
>>    msan_init_is_running = 0;
>>
>> Modified: compiler-rt/trunk/lib/msan/msan.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=205618&r1=205617&r2=205618&view=diff
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan.h (original)
>> +++ compiler-rt/trunk/lib/msan/msan.h Fri Apr  4 04:47:41 2014
>> @@ -128,6 +128,11 @@ class ScopedThreadLocalStateBackup {
>>
>>  extern void (*death_callback)(void);
>>
>> +void MsanTSDInit(void (*destructor)(void *tsd));
>> +void *MsanTSDGet();
>> +void MsanTSDSet(void *tsd);
>> +void MsanTSDDtor(void *tsd);
>> +
>>  }  // namespace __msan
>>
>>  #define MSAN_MALLOC_HOOK(ptr, size) \
>> @@ -135,11 +140,4 @@ extern void (*death_callback)(void);
>>  #define MSAN_FREE_HOOK(ptr) \
>>    if (&__msan_free_hook) __msan_free_hook(ptr)
>>
>> -struct MsanStackBounds {
>> -  uptr stack_addr, stack_size;
>> -  uptr tls_addr, tls_size;
>> -};
>> -
>> -extern THREADLOCAL MsanStackBounds msan_stack_bounds;
>> -
>>  #endif  // MSAN_H
>>
>> Modified: compiler-rt/trunk/lib/msan/msan_allocator.cc
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.cc?rev=205618&r1=205617&r2=205618&view=diff
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan_allocator.cc (original)
>> +++ compiler-rt/trunk/lib/msan/msan_allocator.cc Fri Apr  4 04:47:41 2014
>> @@ -15,6 +15,8 @@
>>  #include "sanitizer_common/sanitizer_allocator.h"
>>  #include "sanitizer_common/sanitizer_stackdepot.h"
>>  #include "msan.h"
>> +#include "msan_allocator.h"
>> +#include "msan_thread.h"
>>
>>  namespace __msan {
>>
>> @@ -48,8 +50,9 @@ typedef LargeMmapAllocator<MsanMapUnmapC
>>  typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
>>                            SecondaryAllocator> Allocator;
>>
>> -static THREADLOCAL AllocatorCache cache;
>>  static Allocator allocator;
>> +static AllocatorCache fallback_allocator_cache;
>> +static SpinMutex fallback_mutex;
>>
>>  static int inited = 0;
>>
>> @@ -60,35 +63,51 @@ static inline void Init() {
>>    allocator.Init();
>>  }
>>
>> -void MsanAllocatorThreadFinish() {
>> -  allocator.SwallowCache(&cache);
>> +AllocatorCache *GetAllocatorCache(MsanThreadLocalMallocStorage *ms) {
>> +  CHECK(ms);
>> +  CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache));
>> +  return reinterpret_cast<AllocatorCache *>(ms->allocator_cache);
>>  }
>>
>> -static void *MsanAllocate(StackTrace *stack, uptr size,
>> -                          uptr alignment, bool zeroise) {
>> +void MsanThreadLocalMallocStorage::CommitBack() {
>> +  allocator.SwallowCache(GetAllocatorCache(this));
>> +}
>> +
>> +static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
>> +                          bool zeroise) {
>>    Init();
>>    if (size > kMaxAllowedMallocSize) {
>>      Report("WARNING: MemorySanitizer failed to allocate %p bytes\n",
>>             (void *)size);
>>      return AllocatorReturnNull();
>>    }
>> -  void *res = allocator.Allocate(&cache, size, alignment, false);
>> -  Metadata *meta =
>> reinterpret_cast<Metadata*>(allocator.GetMetaData(res));
>> +  MsanThread *t = GetCurrentThread();
>> +  void *allocated;
>> +  if (t) {
>> +    AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
>> +    allocated = allocator.Allocate(cache, size, alignment, false);
>> +  } else {
>> +    SpinMutexLock l(&fallback_mutex);
>> +    AllocatorCache *cache = &fallback_allocator_cache;
>> +    allocated = allocator.Allocate(cache, size, alignment, false);
>> +  }
>> +  Metadata *meta =
>> +      reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
>>    meta->requested_size = size;
>>    if (zeroise) {
>> -    __msan_clear_and_unpoison(res, size);
>> +    __msan_clear_and_unpoison(allocated, size);
>>    } else if (flags()->poison_in_malloc) {
>> -    __msan_poison(res, size);
>> +    __msan_poison(allocated, size);
>>      if (__msan_get_track_origins()) {
>>        u32 stack_id = StackDepotPut(stack->trace, stack->size);
>>        CHECK(stack_id);
>>        CHECK_EQ((stack_id >> 31),
>>                 0);  // Higher bit is occupied by stack origins.
>> -      __msan_set_origin(res, size, stack_id);
>> +      __msan_set_origin(allocated, size, stack_id);
>>      }
>>    }
>> -  MSAN_MALLOC_HOOK(res, size);
>> -  return res;
>> +  MSAN_MALLOC_HOOK(allocated, size);
>> +  return allocated;
>>  }
>>
>>  void MsanDeallocate(StackTrace *stack, void *p) {
>> @@ -110,7 +129,15 @@ void MsanDeallocate(StackTrace *stack, v
>>        __msan_set_origin(p, size, stack_id);
>>      }
>>    }
>> -  allocator.Deallocate(&cache, p);
>> +  MsanThread *t = GetCurrentThread();
>> +  if (t) {
>> +    AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
>> +    allocator.Deallocate(cache, p);
>> +  } else {
>> +    SpinMutexLock l(&fallback_mutex);
>> +    AllocatorCache *cache = &fallback_allocator_cache;
>> +    allocator.Deallocate(cache, p);
>> +  }
>>  }
>>
>>  void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size,
>>
>> Added: compiler-rt/trunk/lib/msan/msan_allocator.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.h?rev=205618&view=auto
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan_allocator.h (added)
>> +++ compiler-rt/trunk/lib/msan/msan_allocator.h Fri Apr  4 04:47:41 2014
>> @@ -0,0 +1,33 @@
>> +//===-- msan_allocator.h ----------------------------------------*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file is a part of MemorySanitizer.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef MSAN_ALLOCATOR_H
>> +#define MSAN_ALLOCATOR_H
>> +
>> +#include "sanitizer_common/sanitizer_common.h"
>> +
>> +namespace __msan {
>> +
>> +struct MsanThreadLocalMallocStorage {
>> +  uptr quarantine_cache[16];
>> +  // Allocator cache contains atomic_uint64_t which must be 8-byte
>> aligned.
>> +  ALIGNED(8) uptr allocator_cache[96 * (512 * 8 + 16)];  // Opaque.
>> +  void CommitBack();
>> +
>> + private:
>> +  // These objects are allocated via mmap() and are zero-initialized.
>> +  MsanThreadLocalMallocStorage() {}
>> +};
>> +
>> +} // namespace __msan
>> +#endif // MSAN_ALLOCATOR_H
>>
>> Propchange: compiler-rt/trunk/lib/msan/msan_allocator.h
>>
>> ------------------------------------------------------------------------------
>>     svn:eol-style = LF
>>
>> Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=205618&r1=205617&r2=205618&view=diff
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
>> +++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Fri Apr  4 04:47:41
>> 2014
>> @@ -16,6 +16,7 @@
>>
>> //===----------------------------------------------------------------------===//
>>
>>  #include "msan.h"
>> +#include "msan_thread.h"
>>  #include "sanitizer_common/sanitizer_platform_limits_posix.h"
>>  #include "sanitizer_common/sanitizer_allocator.h"
>>  #include "sanitizer_common/sanitizer_allocator_internal.h"
>> @@ -37,8 +38,6 @@ using __sanitizer::atomic_load;
>>  using __sanitizer::atomic_store;
>>  using __sanitizer::atomic_uintptr_t;
>>
>> -static unsigned g_thread_finalize_key;
>> -
>>  // True if this is a nested interceptor.
>>  static THREADLOCAL int in_interceptor_scope;
>>
>> @@ -1038,48 +1037,11 @@ INTERCEPTOR(int, signal, int signo, uptr
>>
>>  extern "C" int pthread_attr_init(void *attr);
>>  extern "C" int pthread_attr_destroy(void *attr);
>> -extern "C" int pthread_setspecific(unsigned key, const void *v);
>> -extern "C" int pthread_yield();
>> -
>> -static void thread_finalize(void *v) {
>> -  uptr iter = (uptr)v;
>> -  if (iter > 1) {
>> -    if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
>> -      Printf("MemorySanitizer: failed to set thread key\n");
>> -      Die();
>> -    }
>> -    return;
>> -  }
>> -  MsanAllocatorThreadFinish();
>> -  __msan_unpoison((void *)msan_stack_bounds.stack_addr,
>> -                  msan_stack_bounds.stack_size);
>> -  if (msan_stack_bounds.tls_size)
>> -    __msan_unpoison((void *)msan_stack_bounds.tls_addr,
>> -                    msan_stack_bounds.tls_size);
>> -}
>> -
>> -struct ThreadParam {
>> -  void* (*callback)(void *arg);
>> -  void *param;
>> -  atomic_uintptr_t done;
>> -};
>>
>>  static void *MsanThreadStartFunc(void *arg) {
>> -  ThreadParam *p = (ThreadParam *)arg;
>> -  void* (*callback)(void *arg) = p->callback;
>> -  void *param = p->param;
>> -  if (pthread_setspecific(g_thread_finalize_key,
>> -          (void *)kPthreadDestructorIterations)) {
>> -    Printf("MemorySanitizer: failed to set thread key\n");
>> -    Die();
>> -  }
>> -  atomic_store(&p->done, 1, memory_order_release);
>> -
>> -  GetThreadStackAndTls(/* main */ false, &msan_stack_bounds.stack_addr,
>> -                       &msan_stack_bounds.stack_size,
>> -                       &msan_stack_bounds.tls_addr,
>> -                       &msan_stack_bounds.tls_size);
>> -  return IndirectExternCall(callback)(param);
>> +  MsanThread *t = (MsanThread *)arg;
>> +  SetCurrentThread(t);
>> +  return t->ThreadStart();
>>  }
>>
>>  INTERCEPTOR(int, pthread_create, void *th, void *attr, void
>> *(*callback)(void*),
>> @@ -1093,16 +1055,9 @@ INTERCEPTOR(int, pthread_create, void *t
>>
>>    AdjustStackSize(attr);
>>
>> -  ThreadParam p;
>> -  p.callback = callback;
>> -  p.param = param;
>> -  atomic_store(&p.done, 0, memory_order_relaxed);
>> +  MsanThread *t = MsanThread::Create(callback, param);
>>
>> -  int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, (void
>> *)&p);
>> -  if (res == 0) {
>> -    while (atomic_load(&p.done, memory_order_acquire) != 1)
>> -      pthread_yield();
>> -  }
>> +  int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
>>
>>    if (attr == &myattr)
>>      pthread_attr_destroy(&myattr);
>> @@ -1114,6 +1069,7 @@ INTERCEPTOR(int, pthread_create, void *t
>>
>>  INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
>>              void (*dtor)(void *value)) {
>> +  if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
>>    ENSURE_MSAN_INITED();
>>    int res = REAL(pthread_key_create)(key, dtor);
>>    if (!res && key)
>> @@ -1368,6 +1324,8 @@ void __msan_clear_and_unpoison(void *a,
>>  }
>>
>>  void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
>> +  if (!msan_inited) return internal_memcpy(dest, src, n);
>> +  if (msan_init_is_running) return REAL(memcpy)(dest, src, n);
>>    ENSURE_MSAN_INITED();
>>    GET_STORE_STACK_TRACE;
>>    void *res = fast_memcpy(dest, src, n);
>> @@ -1376,6 +1334,8 @@ void *__msan_memcpy(void *dest, const vo
>>  }
>>
>>  void *__msan_memset(void *s, int c, SIZE_T n) {
>> +  if (!msan_inited) return internal_memset(s, c, n);
>> +  if (msan_init_is_running) return REAL(memset)(s, c, n);
>>    ENSURE_MSAN_INITED();
>>    void *res = fast_memset(s, c, n);
>>    __msan_unpoison(s, n);
>> @@ -1383,6 +1343,8 @@ void *__msan_memset(void *s, int c, SIZE
>>  }
>>
>>  void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
>> +  if (!msan_inited) return internal_memmove(dest, src, n);
>> +  if (msan_init_is_running) return REAL(memmove)(dest, src, n);
>>    ENSURE_MSAN_INITED();
>>    GET_STORE_STACK_TRACE;
>>    void *res = REAL(memmove)(dest, src, n);
>> @@ -1603,11 +1565,6 @@ void InitializeInterceptors() {
>>    INTERCEPT_FUNCTION(__cxa_atexit);
>>    INTERCEPT_FUNCTION(shmat);
>>
>> -  if (REAL(pthread_key_create)(&g_thread_finalize_key, &thread_finalize))
>> {
>> -    Printf("MemorySanitizer: failed to create thread key\n");
>> -    Die();
>> -  }
>> -
>>    inited = 1;
>>  }
>>  }  // namespace __msan
>>
>> Modified: compiler-rt/trunk/lib/msan/msan_linux.cc
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_linux.cc?rev=205618&r1=205617&r2=205618&view=diff
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan_linux.cc (original)
>> +++ compiler-rt/trunk/lib/msan/msan_linux.cc Fri Apr  4 04:47:41 2014
>> @@ -16,9 +16,11 @@
>>  #if SANITIZER_LINUX
>>
>>  #include "msan.h"
>> +#include "msan_thread.h"
>>
>>  #include <elf.h>
>>  #include <link.h>
>> +#include <pthread.h>
>>  #include <stdio.h>
>>  #include <stdlib.h>
>>  #include <signal.h>
>> @@ -97,6 +99,36 @@ void InstallAtExitHandler() {
>>    atexit(MsanAtExit);
>>  }
>>
>> +// ---------------------- TSD ---------------- {{{1
>> +
>> +static pthread_key_t tsd_key;
>> +static bool tsd_key_inited = false;
>> +void MsanTSDInit(void (*destructor)(void *tsd)) {
>> +  CHECK(!tsd_key_inited);
>> +  tsd_key_inited = true;
>> +  CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
>> +}
>> +
>> +void *MsanTSDGet() {
>> +  CHECK(tsd_key_inited);
>> +  return pthread_getspecific(tsd_key);
>> +}
>> +
>> +void MsanTSDSet(void *tsd) {
>> +  CHECK(tsd_key_inited);
>> +  pthread_setspecific(tsd_key, tsd);
>> +}
>> +
>> +void MsanTSDDtor(void *tsd) {
>> +  MsanThread *t = (MsanThread*)tsd;
>> +  if (t->destructor_iterations_ > 1) {
>> +    t->destructor_iterations_--;
>> +    CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
>> +    return;
>> +  }
>> +  MsanThread::TSDDtor(tsd);
>> +}
>> +
>>  }  // namespace __msan
>>
>>  #endif  // __linux__
>>
>> Added: compiler-rt/trunk/lib/msan/msan_thread.cc
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_thread.cc?rev=205618&view=auto
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan_thread.cc (added)
>> +++ compiler-rt/trunk/lib/msan/msan_thread.cc Fri Apr  4 04:47:41 2014
>> @@ -0,0 +1,86 @@
>> +
>> +#include "msan.h"
>> +#include "msan_thread.h"
>> +#include "msan_interface_internal.h"
>> +
>> +namespace __msan {
>> +
>> +MsanThread *MsanThread::Create(thread_callback_t start_routine,
>> +                               void *arg) {
>> +  uptr PageSize = GetPageSizeCached();
>> +  uptr size = RoundUpTo(sizeof(MsanThread), PageSize);
>> +  MsanThread *thread = (MsanThread*)MmapOrDie(size, __func__);
>> +  thread->start_routine_ = start_routine;
>> +  thread->arg_ = arg;
>> +  thread->destructor_iterations_ = kPthreadDestructorIterations;
>> +
>> +  return thread;
>> +}
>> +
>> +void MsanThread::SetThreadStackAndTls() {
>> +  uptr tls_size = 0;
>> +  uptr stack_size = 0;
>> +  GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size,
>> +                       &tls_begin_, &tls_size);
>> +  stack_top_ = stack_bottom_ + stack_size;
>> +  tls_end_ = tls_begin_ + tls_size;
>> +
>> +  int local;
>> +  CHECK(AddrIsInStack((uptr)&local));
>> +}
>> +
>> +void MsanThread::ClearShadowForThreadStackAndTLS() {
>> +  __msan_unpoison((void *)stack_bottom_, stack_top_ - stack_bottom_);
>> +  if (tls_begin_ != tls_end_)
>> +    __msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_);
>> +}
>> +
>> +void MsanThread::Init() {
>> +  SetThreadStackAndTls();
>> +  CHECK(MEM_IS_APP(stack_bottom_));
>> +  CHECK(MEM_IS_APP(stack_top_ - 1));
>> +  ClearShadowForThreadStackAndTLS();
>> +}
>> +
>> +void MsanThread::TSDDtor(void *tsd) {
>> +  MsanThread *t = (MsanThread*)tsd;
>> +  t->Destroy();
>> +}
>> +
>> +void MsanThread::Destroy() {
>> +  malloc_storage().CommitBack();
>> +  // We also clear the shadow on thread destruction because
>> +  // some code may still be executing in later TSD destructors
>> +  // and we don't want it to have any poisoned stack.
>> +  ClearShadowForThreadStackAndTLS();
>> +  uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
>> +  UnmapOrDie(this, size);
>> +}
>> +
>> +thread_return_t MsanThread::ThreadStart() {
>> +  Init();
>> +
>> +  if (!start_routine_) {
>> +    // start_routine_ == 0 if we're on the main thread or on one of the
>> +    // OS X libdispatch worker threads. But nobody is supposed to call
>> +    // ThreadStart() for the worker threads.
>> +    return 0;
>> +  }
>> +
>> +  thread_return_t res = IndirectExternCall(start_routine_)(arg_);
>> +
>> +  return res;
>> +}
>> +
>> +MsanThread *GetCurrentThread() {
>> +  return reinterpret_cast<MsanThread *>(MsanTSDGet());
>> +}
>> +
>> +void SetCurrentThread(MsanThread *t) {
>> +  // Make sure we do not reset the current MsanThread.
>> +  CHECK_EQ(0, MsanTSDGet());
>> +  MsanTSDSet(t);
>> +  CHECK_EQ(t, MsanTSDGet());
>> +}
>> +
>> +} // namespace __msan
>>
>> Propchange: compiler-rt/trunk/lib/msan/msan_thread.cc
>>
>> ------------------------------------------------------------------------------
>>     svn:eol-style = LF
>>
>> Added: compiler-rt/trunk/lib/msan/msan_thread.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_thread.h?rev=205618&view=auto
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/msan_thread.h (added)
>> +++ compiler-rt/trunk/lib/msan/msan_thread.h Fri Apr  4 04:47:41 2014
>> @@ -0,0 +1,65 @@
>> +//===-- msan_thread.h -------------------------------------------*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file is a part of MemorySanitizer.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef MSAN_THREAD_H
>> +#define MSAN_THREAD_H
>> +
>> +#include "msan_allocator.h"
>> +#include "sanitizer_common/sanitizer_common.h"
>> +
>> +namespace __msan {
>> +
>> +class MsanThread {
>> + public:
>> +  static MsanThread *Create(thread_callback_t start_routine, void *arg);
>> +  static void TSDDtor(void *tsd);
>> +  void Destroy();
>> +
>> +  void Init();  // Should be called from the thread itself.
>> +  thread_return_t ThreadStart();
>> +
>> +  uptr stack_top() { return stack_top_; }
>> +  uptr stack_bottom() { return stack_bottom_; }
>> +  uptr tls_begin() { return tls_begin_; }
>> +  uptr tls_end() { return tls_end_; }
>> +  bool IsMainThread() { return start_routine_ == 0; }
>> +
>> +  bool AddrIsInStack(uptr addr) {
>> +    return addr >= stack_bottom_ && addr < stack_top_;
>> +  }
>> +
>> +  MsanThreadLocalMallocStorage &malloc_storage() { return
>> malloc_storage_; }
>> +
>> +  int destructor_iterations_;
>> +
>> + private:
>> +  // NOTE: There is no MsanThread constructor. It is allocated
>> +  // via mmap() and *must* be valid in zero-initialized state.
>> +  void SetThreadStackAndTls();
>> +  void ClearShadowForThreadStackAndTLS();
>> +  thread_callback_t start_routine_;
>> +  void *arg_;
>> +  uptr stack_top_;
>> +  uptr stack_bottom_;
>> +  uptr tls_begin_;
>> +  uptr tls_end_;
>> +
>> +  MsanThreadLocalMallocStorage malloc_storage_;
>> +};
>> +
>> +MsanThread *GetCurrentThread();
>> +void SetCurrentThread(MsanThread *t);
>> +
>> +} // namespace __msan
>> +
>> +#endif // MSAN_THREAD_H
>>
>> Propchange: compiler-rt/trunk/lib/msan/msan_thread.h
>>
>> ------------------------------------------------------------------------------
>>     svn:eol-style = LF
>>
>> Modified: compiler-rt/trunk/lib/msan/tests/msan_test.cc
>> URL:
>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/tests/msan_test.cc?rev=205618&r1=205617&r2=205618&view=diff
>>
>> ==============================================================================
>> --- compiler-rt/trunk/lib/msan/tests/msan_test.cc (original)
>> +++ compiler-rt/trunk/lib/msan/tests/msan_test.cc Fri Apr  4 04:47:41 2014
>> @@ -2818,22 +2818,22 @@ TEST(MemorySanitizer, SmallStackThread)
>>    ASSERT_EQ(0, res);
>>  }
>>
>> -TEST(MemorySanitizer, PreAllocatedStackThread) {
>> +TEST(MemorySanitizer, SmallPreAllocatedStackThread) {
>>    pthread_attr_t attr;
>>    pthread_t t;
>>    int res;
>>    res = pthread_attr_init(&attr);
>>    ASSERT_EQ(0, res);
>>    void *stack;
>> -  const size_t kStackSize = 64 * 1024;
>> +  const size_t kStackSize = 16 * 1024;
>>    res = posix_memalign(&stack, 4096, kStackSize);
>>    ASSERT_EQ(0, res);
>>    res = pthread_attr_setstack(&attr, stack, kStackSize);
>>    ASSERT_EQ(0, res);
>> -  // A small self-allocated stack can not be extended by the tool.
>> -  // In this case pthread_create is expected to fail.
>>    res = pthread_create(&t, &attr, SmallStackThread_threadfn, NULL);
>> -  EXPECT_NE(0, res);
>> +  EXPECT_EQ(0, res);
>> +  res = pthread_join(t, NULL);
>> +  ASSERT_EQ(0, res);
>>    res = pthread_attr_destroy(&attr);
>>    ASSERT_EQ(0, res);
>>  }
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>



More information about the llvm-commits mailing list