From e297eb600dd52acd73fb64ca45905b68f4e9b99b Mon Sep 17 00:00:00 2001
From: Kostya Serebryany <kcc@google.com>
Date: Fri, 23 Nov 2012 14:46:25 +0000
Subject: [PATCH] [libsanitizer] merge from upstream r168514

From-SVN: r193756
---
 gcc/testsuite/ChangeLog                       |   4 +
 gcc/testsuite/c-c++-common/asan/memcmp-1.c    |   2 +-
 libsanitizer/ChangeLog                        |   9 +-
 libsanitizer/MERGE                            |   4 +
 libsanitizer/asan/asan_allocator.cc           |   4 +-
 .../asan/asan_intercepted_functions.h         |   6 +
 libsanitizer/asan/asan_interceptors.cc        |  49 +++++-
 libsanitizer/asan/asan_internal.h             |   1 +
 libsanitizer/asan/asan_linux.cc               |  28 +++-
 libsanitizer/asan/asan_mac.cc                 |  20 ++-
 libsanitizer/asan/asan_mac.h                  |   5 +-
 libsanitizer/asan/asan_malloc_mac.cc          |  30 ++--
 libsanitizer/asan/asan_mapping.h              |  18 +-
 libsanitizer/asan/asan_new_delete.cc          |  38 +++--
 libsanitizer/asan/asan_report.cc              |  22 +--
 libsanitizer/asan/asan_rtl.cc                 |   2 +-
 libsanitizer/asan/asan_stats.cc               |   3 +-
 libsanitizer/asan/asan_thread.cc              |  13 +-
 libsanitizer/asan/asan_thread_registry.cc     |  23 ++-
 libsanitizer/asan/asan_thread_registry.h      |   4 +-
 libsanitizer/asan/asan_win.cc                 |   4 +
 .../include/sanitizer/common_interface_defs.h |   5 +
 libsanitizer/merge.sh                         |   6 +-
 .../sanitizer_common/sanitizer_allocator64.h  |   9 +-
 .../sanitizer_common/sanitizer_common.cc      |  50 ++++--
 .../sanitizer_common/sanitizer_common.h       |  22 ++-
 .../sanitizer_internal_defs.h                 |  47 +++---
 .../sanitizer_common/sanitizer_libc.cc        |  17 ++
 .../sanitizer_common/sanitizer_libc.h         |   5 +
 .../sanitizer_common/sanitizer_linux.cc       |  18 +-
 .../sanitizer_common/sanitizer_mac.cc         |   8 +
 .../sanitizer_placement_new.h                 |   2 +-
 .../sanitizer_common/sanitizer_posix.cc       |  17 +-
 .../sanitizer_common/sanitizer_printf.cc      |  57 +++++--
 .../sanitizer_common/sanitizer_procmaps.h     |   1 -
 .../sanitizer_common/sanitizer_stacktrace.cc  |  24 ++-
 .../sanitizer_common/sanitizer_stacktrace.h   |   2 +
 .../sanitizer_common/sanitizer_symbolizer.cc  |   3 +-
 .../sanitizer_common/sanitizer_symbolizer.h   |   2 +-
 .../sanitizer_symbolizer_linux.cc             |  20 ++-
 .../sanitizer_symbolizer_mac.cc               |   2 -
 .../sanitizer_symbolizer_win.cc               |   2 -
 .../sanitizer_common/sanitizer_win.cc         |  37 +++--
 libsanitizer/tsan/Makefile.am                 |   1 -
 libsanitizer/tsan/Makefile.in                 |   4 +-
 libsanitizer/tsan/tsan_clock.cc               |   7 -
 libsanitizer/tsan/tsan_clock.h                |   2 -
 libsanitizer/tsan/tsan_defs.h                 |  17 +-
 libsanitizer/tsan/tsan_flags.cc               |  10 +-
 libsanitizer/tsan/tsan_flags.h                |   2 +
 libsanitizer/tsan/tsan_interceptors.cc        |  78 ++++++---
 libsanitizer/tsan/tsan_interface.h            |  29 ++--
 libsanitizer/tsan/tsan_interface_ann.cc       |  45 +----
 libsanitizer/tsan/tsan_interface_atomic.cc    |  62 ++++++-
 libsanitizer/tsan/tsan_interface_atomic.h     | 155 +++++++-----------
 libsanitizer/tsan/tsan_mutex.cc               |  24 +--
 libsanitizer/tsan/tsan_platform.h             |   8 +-
 libsanitizer/tsan/tsan_platform_linux.cc      |  22 +--
 libsanitizer/tsan/tsan_platform_mac.cc        |  10 +-
 libsanitizer/tsan/tsan_platform_windows.cc    |  56 +++++++
 libsanitizer/tsan/tsan_printf.cc              |  38 -----
 libsanitizer/tsan/tsan_report.cc              |  80 ++++-----
 libsanitizer/tsan/tsan_rtl.cc                 |  50 ++++--
 libsanitizer/tsan/tsan_rtl.h                  |  26 ++-
 libsanitizer/tsan/tsan_rtl_mutex.cc           |  26 ++-
 libsanitizer/tsan/tsan_rtl_report.cc          |   8 +-
 libsanitizer/tsan/tsan_rtl_thread.cc          |  41 +++--
 libsanitizer/tsan/tsan_stat.cc                |   9 +-
 libsanitizer/tsan/tsan_stat.h                 |   2 +
 libsanitizer/tsan/tsan_suppressions.cc        |   8 +-
 .../tsan/tsan_symbolize_addr2line_linux.cc    |  12 +-
 .../tsan/tsan_update_shadow_word_inl.h        |   4 +-
 72 files changed, 932 insertions(+), 549 deletions(-)
 create mode 100644 libsanitizer/MERGE
 create mode 100644 libsanitizer/tsan/tsan_platform_windows.cc
 delete mode 100644 libsanitizer/tsan/tsan_printf.cc

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8021aef4e878..74a120d1c0d1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2012-11-23  Kostya Serebryany  <kcc@google.com>
+
+	* c-c++-common/asan/memcmp-1.c: Update to match the new libsanitizer.
+
 2012-11-23  Eric Botcazou  <ebotcazou@adacore.com>
 
 	* gnat.dg/discr40.ad[sb]: New test.
diff --git a/gcc/testsuite/c-c++-common/asan/memcmp-1.c b/gcc/testsuite/c-c++-common/asan/memcmp-1.c
index 8f45a3f2fcb6..a23ff236c0d1 100644
--- a/gcc/testsuite/c-c++-common/asan/memcmp-1.c
+++ b/gcc/testsuite/c-c++-common/asan/memcmp-1.c
@@ -13,6 +13,6 @@ main (int argc, char **argv)
   return res;
 }
 
-/* { dg-output "ERROR: AddressSanitizer stack-buffer-overflow.*(\n|\r\n|\r)" } */
+/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow.*(\n|\r\n|\r)" } */
 /* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)memcmp |\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 7e206f9b96ce..0c7e4b753f4c 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,6 +1,13 @@
 2012-11-23  Kostya Serebryany  <kcc@google.com>
         
-	* merge.sh: a script that will help merges from upstream.
+	* merge.sh: Support tsan, support added/removed files.
+	* tsan/Makefile.am: Remove tsan_printf.cc.
+	* tsan/Makefile.in: Regenerated.
+	* other files: Merge from upstream r168514.
+
+2012-11-23  Kostya Serebryany  <kcc@google.com>
+        
+	* merge.sh: New file.
 
 2012-11-23  Jakub Jelinek  <jakub@redhat.com>
 
diff --git a/libsanitizer/MERGE b/libsanitizer/MERGE
new file mode 100644
index 000000000000..05b4cf0d9b58
--- /dev/null
+++ b/libsanitizer/MERGE
@@ -0,0 +1,4 @@
+168514
+
+The first line of this file holds the svn revision number of the
+last merge done from the master library sources.
diff --git a/libsanitizer/asan/asan_allocator.cc b/libsanitizer/asan/asan_allocator.cc
index 3a92802e9722..63ff607f8589 100644
--- a/libsanitizer/asan/asan_allocator.cc
+++ b/libsanitizer/asan/asan_allocator.cc
@@ -56,7 +56,7 @@ static const uptr kMallocSizeClassStepLog = 26;
 static const uptr kMallocSizeClassStep = 1UL << kMallocSizeClassStepLog;
 
 static const uptr kMaxAllowedMallocSize =
-    (__WORDSIZE == 32) ? 3UL << 30 : 8UL << 30;
+    (SANITIZER_WORDSIZE == 32) ? 3UL << 30 : 8UL << 30;
 
 static inline bool IsAligned(uptr a, uptr alignment) {
   return (a & (alignment - 1)) == 0;
@@ -83,7 +83,7 @@ static inline uptr RoundUpToPowerOfTwo(uptr size) {
 
   unsigned long up;  // NOLINT
 #if !defined(_WIN32) || defined(__clang__)
-  up = __WORDSIZE - 1 - __builtin_clzl(size);
+  up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(size);
 #elif defined(_WIN64)
   _BitScanReverse64(&up, size);
 #else
diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h
index ceb596cd48ec..62d1994130fc 100644
--- a/libsanitizer/asan/asan_intercepted_functions.h
+++ b/libsanitizer/asan/asan_intercepted_functions.h
@@ -49,6 +49,12 @@ using __sanitizer::uptr;
 # define ASAN_INTERCEPT_STRNLEN 0
 #endif
 
+#if defined(__linux__) && !defined(ANDROID)
+# define ASAN_INTERCEPT_SWAPCONTEXT 1
+#else
+# define ASAN_INTERCEPT_SWAPCONTEXT 0
+#endif
+
 #if !defined(ANDROID) && !defined(_WIN32)
 # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
 #else
diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc
index 8e15d341b8c5..5b544c87fcb8 100644
--- a/libsanitizer/asan/asan_interceptors.cc
+++ b/libsanitizer/asan/asan_interceptors.cc
@@ -134,6 +134,28 @@ DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
     struct sigaction *oldact);
 #endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
 
+#if ASAN_INTERCEPT_SWAPCONTEXT
+INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
+            struct ucontext_t *ucp) {
+  static bool reported_warning = false;
+  if (!reported_warning) {
+    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
+           "functions and may produce false positives in some cases!\n");
+    reported_warning = true;
+  }
+  // Clear shadow memory for new context (it may share stack
+  // with current context).
+  ClearShadowMemoryForContext(ucp);
+  int res = REAL(swapcontext)(oucp, ucp);
+  // swapcontext technically does not return, but program may swap context to
+  // "oucp" later, that would look as if swapcontext() returned 0.
+  // We need to clear shadow for ucp once again, as it may be in arbitrary
+  // state.
+  ClearShadowMemoryForContext(ucp);
+  return res;
+}
+#endif
+
 INTERCEPTOR(void, longjmp, void *env, int val) {
   __asan_handle_no_return();
   REAL(longjmp)(env, val);
@@ -237,13 +259,17 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
     ASAN_WRITE_RANGE(from, size);
     ASAN_READ_RANGE(to, size);
   }
+#if MAC_INTERPOSE_FUNCTIONS
+  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
+  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
+  return internal_memcpy(to, from, size);
+#else
   return REAL(memcpy)(to, from, size);
+#endif
 }
 
 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
-#if MAC_INTERPOSE_FUNCTIONS
-  if (!asan_inited) return REAL(memmove)(to, from, size);
-#endif
+  if (!asan_inited) return internal_memmove(to, from, size);
   if (asan_init_is_running) {
     return REAL(memmove)(to, from, size);
   }
@@ -252,7 +278,13 @@ INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
     ASAN_WRITE_RANGE(from, size);
     ASAN_READ_RANGE(to, size);
   }
+#if MAC_INTERPOSE_FUNCTIONS
+  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
+  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
+  return internal_memmove(to, from, size);
+#else
   return REAL(memmove)(to, from, size);
+#endif
 }
 
 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
@@ -370,6 +402,14 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
 
 #if ASAN_INTERCEPT_STRDUP
 INTERCEPTOR(char*, strdup, const char *s) {
+#if MAC_INTERPOSE_FUNCTIONS
+  // FIXME: because internal_strdup() uses InternalAlloc(), which currently
+  // just calls malloc() on Mac, we can't use internal_strdup() with the
+  // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
+  // starts using mmap() instead.
+  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
+  if (!asan_inited) return REAL(strdup)(s);
+#endif
   if (!asan_inited) return internal_strdup(s);
   ENSURE_ASAN_INITED();
   if (flags()->replace_str) {
@@ -669,6 +709,9 @@ void InitializeAsanInterceptors() {
   ASAN_INTERCEPT_FUNC(sigaction);
   ASAN_INTERCEPT_FUNC(signal);
 #endif
+#if ASAN_INTERCEPT_SWAPCONTEXT
+  ASAN_INTERCEPT_FUNC(swapcontext);
+#endif
 #if ASAN_INTERCEPT__LONGJMP
   ASAN_INTERCEPT_FUNC(_longjmp);
 #endif
diff --git a/libsanitizer/asan/asan_internal.h b/libsanitizer/asan/asan_internal.h
index 21368eef7c98..3a70ca44fd51 100644
--- a/libsanitizer/asan/asan_internal.h
+++ b/libsanitizer/asan/asan_internal.h
@@ -114,6 +114,7 @@ bool AsanInterceptsSignal(int signum);
 void SetAlternateSignalStack();
 void UnsetAlternateSignalStack();
 void InstallSignalHandlers();
+void ClearShadowMemoryForContext(void *context);
 void AsanPlatformThreadInit();
 
 // Wrapper for TLS/TSD.
diff --git a/libsanitizer/asan/asan_linux.cc b/libsanitizer/asan/asan_linux.cc
index ea7ee9e7bc86..7295216b85d1 100644
--- a/libsanitizer/asan/asan_linux.cc
+++ b/libsanitizer/asan/asan_linux.cc
@@ -66,6 +66,13 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   *pc = ucontext->uc_mcontext.gregs[REG_EIP];
   *bp = ucontext->uc_mcontext.gregs[REG_EBP];
   *sp = ucontext->uc_mcontext.gregs[REG_ESP];
+# elif defined(__powerpc__) || defined(__powerpc64__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.regs->nip;
+  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
+  // The powerpc{,64}-linux ABIs do not specify r31 as the frame
+  // pointer, but GCC always uses r31 when we need a frame pointer.
+  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
 # elif defined(__sparc__)
   ucontext_t *ucontext = (ucontext_t*)context;
   uptr *stk_ptr;
@@ -149,8 +156,10 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
   stack->trace[0] = pc;
   if ((max_s) > 1) {
     stack->max_size = max_s;
-#ifdef __arm__
+#if defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__)
     _Unwind_Backtrace(Unwind_Trace, stack);
+    // Pop off the two ASAN functions from the backtrace.
+    stack->PopStackFrames(2);
 #else
     if (!asan_inited) return;
     if (AsanThread *t = asanThreadRegistry().GetCurrent())
@@ -159,6 +168,23 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
   }
 }
 
+#if !ASAN_ANDROID
+void ClearShadowMemoryForContext(void *context) {
+  ucontext_t *ucp = (ucontext_t*)context;
+  uptr sp = (uptr)ucp->uc_stack.ss_sp;
+  uptr size = ucp->uc_stack.ss_size;
+  // Align to page size.
+  uptr bottom = sp & ~(kPageSize - 1);
+  size += sp - bottom;
+  size = RoundUpTo(size, kPageSize);
+  PoisonShadow(bottom, size, 0);
+}
+#else
+void ClearShadowMemoryForContext(void *context) {
+  UNIMPLEMENTED();
+}
+#endif
+
 }  // namespace __asan
 
 #endif  // __linux__
diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc
index 81e25e8ef599..ae5edd971658 100644
--- a/libsanitizer/asan/asan_mac.cc
+++ b/libsanitizer/asan/asan_mac.cc
@@ -40,7 +40,7 @@ namespace __asan {
 
 void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   ucontext_t *ucontext = (ucontext_t*)context;
-# if __WORDSIZE == 64
+# if SANITIZER_WORDSIZE == 64
   *pc = ucontext->uc_mcontext->__ss.__rip;
   *bp = ucontext->uc_mcontext->__ss.__rbp;
   *sp = ucontext->uc_mcontext->__ss.__rsp;
@@ -48,7 +48,7 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   *pc = ucontext->uc_mcontext->__ss.__eip;
   *bp = ucontext->uc_mcontext->__ss.__ebp;
   *sp = ucontext->uc_mcontext->__ss.__esp;
-# endif  // __WORDSIZE
+# endif  // SANITIZER_WORDSIZE
 }
 
 int GetMacosVersion() {
@@ -66,6 +66,7 @@ int GetMacosVersion() {
       switch (version[1]) {
         case '0': return MACOS_VERSION_SNOW_LEOPARD;
         case '1': return MACOS_VERSION_LION;
+        case '2': return MACOS_VERSION_MOUNTAIN_LION;
         default: return MACOS_VERSION_UNKNOWN;
       }
     }
@@ -128,7 +129,14 @@ bool AsanInterceptsSignal(int signum) {
 }
 
 void AsanPlatformThreadInit() {
-  ReplaceCFAllocator();
+  // For the first program thread, we can't replace the allocator before
+  // __CFInitialize() has been called. If it hasn't, we'll call
+  // MaybeReplaceCFAllocator() later on this thread.
+  // For other threads __CFInitialize() has been called before their creation.
+  // See also asan_malloc_mac.cc.
+  if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) {
+    MaybeReplaceCFAllocator();
+  }
 }
 
 AsanLock::AsanLock(LinkerInitialized) {
@@ -161,6 +169,10 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
   }
 }
 
+void ClearShadowMemoryForContext(void *context) {
+  UNIMPLEMENTED();
+}
+
 // The range of pages to be used for escape islands.
 // TODO(glider): instead of mapping a fixed range we must find a range of
 // unmapped pages in vmmap and take them.
@@ -169,7 +181,7 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
 // kHighMemBeg or kHighMemEnd.
 static void *island_allocator_pos = 0;
 
-#if __WORDSIZE == 32
+#if SANITIZER_WORDSIZE == 32
 # define kIslandEnd (0xffdf0000 - kPageSize)
 # define kIslandBeg (kIslandEnd - 256 * kPageSize)
 #else
diff --git a/libsanitizer/asan/asan_mac.h b/libsanitizer/asan/asan_mac.h
index 18aca0dd84e1..2c162fb0c397 100644
--- a/libsanitizer/asan/asan_mac.h
+++ b/libsanitizer/asan/asan_mac.h
@@ -38,7 +38,8 @@ enum {
   MACOS_VERSION_UNKNOWN = 0,
   MACOS_VERSION_LEOPARD,
   MACOS_VERSION_SNOW_LEOPARD,
-  MACOS_VERSION_LION
+  MACOS_VERSION_LION,
+  MACOS_VERSION_MOUNTAIN_LION
 };
 
 // Used by asan_malloc_mac.cc and asan_mac.cc
@@ -47,7 +48,7 @@ extern "C" void __CFInitialize();
 namespace __asan {
 
 int GetMacosVersion();
-void ReplaceCFAllocator();
+void MaybeReplaceCFAllocator();
 
 }  // namespace __asan
 
diff --git a/libsanitizer/asan/asan_malloc_mac.cc b/libsanitizer/asan/asan_malloc_mac.cc
index 2df34845f124..3f281c9cc3bf 100644
--- a/libsanitizer/asan/asan_malloc_mac.cc
+++ b/libsanitizer/asan/asan_malloc_mac.cc
@@ -95,10 +95,6 @@ INTERCEPTOR(void, free, void *ptr) {
   }
 }
 
-namespace __asan {
-  void ReplaceCFAllocator();
-}
-
 // We can't always replace the default CFAllocator with cf_asan right in
 // ReplaceSystemMalloc(), because it is sometimes called before
 // __CFInitialize(), when the default allocator is invalid and replacing it may
@@ -116,7 +112,7 @@ INTERCEPTOR(void, __CFInitialize, void) {
   CHECK(asan_inited);
 #endif
   REAL(__CFInitialize)();
-  if (!cf_asan && asan_inited) ReplaceCFAllocator();
+  if (!cf_asan && asan_inited) MaybeReplaceCFAllocator();
 }
 
 namespace {
@@ -291,12 +287,10 @@ size_t mi_good_size(malloc_zone_t *zone, size_t size) {
 
 boolean_t mi_check(malloc_zone_t *zone) {
   UNIMPLEMENTED();
-  return true;
 }
 
 void mi_print(malloc_zone_t *zone, boolean_t verbose) {
   UNIMPLEMENTED();
-  return;
 }
 
 void mi_log(malloc_zone_t *zone, void *address) {
@@ -331,7 +325,7 @@ boolean_t mi_zone_locked(malloc_zone_t *zone) {
 extern int __CFRuntimeClassTableSize;
 
 namespace __asan {
-void ReplaceCFAllocator() {
+void MaybeReplaceCFAllocator() {
   static CFAllocatorContext asan_context = {
         /*version*/ 0, /*info*/ &asan_zone,
         /*retain*/ 0, /*release*/ 0,
@@ -342,7 +336,7 @@ void ReplaceCFAllocator() {
         /*preferredSize*/ 0 };
   if (!cf_asan)
     cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context);
-  if (CFAllocatorGetDefault() != cf_asan)
+  if (flags()->replace_cfallocator && CFAllocatorGetDefault() != cf_asan)
     CFAllocatorSetDefault(cf_asan);
 }
 
@@ -410,16 +404,14 @@ void ReplaceSystemMalloc() {
   // Make sure the default allocator was replaced.
   CHECK(malloc_default_zone() == &asan_zone);
 
-  if (flags()->replace_cfallocator) {
-    // If __CFInitialize() hasn't been called yet, cf_asan will be created and
-    // installed as the default allocator after __CFInitialize() finishes (see
-    // the interceptor for __CFInitialize() above). Otherwise install cf_asan
-    // right now. On both Snow Leopard and Lion __CFInitialize() calls
-    // __CFAllocatorInitialize(), which initializes the _base._cfisa field of
-    // the default allocators we check here.
-    if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) {
-      ReplaceCFAllocator();
-    }
+  // If __CFInitialize() hasn't been called yet, cf_asan will be created and
+  // installed as the default allocator after __CFInitialize() finishes (see
+  // the interceptor for __CFInitialize() above). Otherwise install cf_asan
+  // right now. On both Snow Leopard and Lion __CFInitialize() calls
+  // __CFAllocatorInitialize(), which initializes the _base._cfisa field of
+  // the default allocators we check here.
+  if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) {
+    MaybeReplaceCFAllocator();
   }
 }
 }  // namespace __asan
diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h
index 40a38db0544f..c93280fdd6c7 100644
--- a/libsanitizer/asan/asan_mapping.h
+++ b/libsanitizer/asan/asan_mapping.h
@@ -28,10 +28,14 @@ extern __attribute__((visibility("default"))) uptr __asan_mapping_offset;
 #  define SHADOW_OFFSET (0)
 # else
 #  define SHADOW_SCALE (3)
-#  if __WORDSIZE == 32
+#  if SANITIZER_WORDSIZE == 32
 #   define SHADOW_OFFSET (1 << 29)
 #  else
-#   define SHADOW_OFFSET (1ULL << 44)
+#   if defined(__powerpc64__)
+#    define SHADOW_OFFSET (1ULL << 41)
+#   else
+#    define SHADOW_OFFSET (1ULL << 44)
+#   endif
 #  endif
 # endif
 #endif  // ASAN_FLEXIBLE_MAPPING_AND_OFFSET
@@ -40,11 +44,15 @@ extern __attribute__((visibility("default"))) uptr __asan_mapping_offset;
 #define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) | (SHADOW_OFFSET))
 #define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE)
 
-#if __WORDSIZE == 64
+#if SANITIZER_WORDSIZE == 64
+# if defined(__powerpc64__)
+  static const uptr kHighMemEnd = 0x00000fffffffffffUL;
+# else
   static const uptr kHighMemEnd = 0x00007fffffffffffUL;
-#else  // __WORDSIZE == 32
+# endif
+#else  // SANITIZER_WORDSIZE == 32
   static const uptr kHighMemEnd = 0xffffffff;
-#endif  // __WORDSIZE
+#endif  // SANITIZER_WORDSIZE
 
 
 #define kLowMemBeg      0
diff --git a/libsanitizer/asan/asan_new_delete.cc b/libsanitizer/asan/asan_new_delete.cc
index a2180ae94442..8132e58b6e2e 100644
--- a/libsanitizer/asan/asan_new_delete.cc
+++ b/libsanitizer/asan/asan_new_delete.cc
@@ -15,7 +15,6 @@
 #include "asan_stack.h"
 
 #include <stddef.h>
-#include <new>
 
 namespace __asan {
 // This function is a no-op. We need it to make sure that object file
@@ -26,29 +25,40 @@ void ReplaceOperatorsNewAndDelete() { }
 
 using namespace __asan;  // NOLINT
 
+// On Android new() goes through malloc interceptors.
+#if !ASAN_ANDROID
+
+// Fake std::nothrow_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+}  // namespace std
+
 #define OPERATOR_NEW_BODY \
   GET_STACK_TRACE_HERE_FOR_MALLOC;\
   return asan_memalign(0, size, &stack);
 
-#if ASAN_ANDROID
+INTERCEPTOR_ATTRIBUTE
 void *operator new(size_t size) { OPERATOR_NEW_BODY; }
+INTERCEPTOR_ATTRIBUTE
 void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
-#else
-void *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
-void *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
-void *operator new(size_t size, std::nothrow_t const&) throw()
-{ OPERATOR_NEW_BODY; }
-void *operator new[](size_t size, std::nothrow_t const&) throw()
-{ OPERATOR_NEW_BODY; }
-#endif
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
 
 #define OPERATOR_DELETE_BODY \
   GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
   asan_free(ptr, &stack);
 
-void operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
-void operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
-void operator delete(void *ptr, std::nothrow_t const&) throw()
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&)
 { OPERATOR_DELETE_BODY; }
-void operator delete[](void *ptr, std::nothrow_t const&) throw()
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&)
 { OPERATOR_DELETE_BODY; }
+
+#endif
diff --git a/libsanitizer/asan/asan_report.cc b/libsanitizer/asan/asan_report.cc
index 7e6381c2beb0..c35b4ec14f79 100644
--- a/libsanitizer/asan/asan_report.cc
+++ b/libsanitizer/asan/asan_report.cc
@@ -42,7 +42,7 @@ void AppendToErrorMessageBuffer(const char *buffer) {
 
 static void PrintBytes(const char *before, uptr *a) {
   u8 *bytes = (u8*)a;
-  uptr byte_num = (__WORDSIZE) / 8;
+  uptr byte_num = (SANITIZER_WORDSIZE) / 8;
   Printf("%s%p:", before, (void*)a);
   for (uptr i = 0; i < byte_num; i++) {
     Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
@@ -178,7 +178,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
     Printf("    [%zu, %zu) '%s'\n", beg, beg + size, buf);
   }
   Printf("HINT: this may be a false positive if your program uses "
-             "some custom stack unwind mechanism\n"
+             "some custom stack unwind mechanism or swapcontext\n"
              "      (longjmp and C++ exceptions *are* supported)\n");
   DescribeThread(t->summary());
   return true;
@@ -287,7 +287,9 @@ class ScopedInErrorReport {
         // an error report will finish doing it.
         SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
       }
-      Die();
+      // If we're still not dead for some reason, use raw Exit() instead of
+      // Die() to bypass any additional checks.
+      Exit(flags()->exitcode);
     }
     __asan_on_error();
     reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
@@ -320,7 +322,7 @@ class ScopedInErrorReport {
 
 void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
   ScopedInErrorReport in_report;
-  Report("ERROR: AddressSanitizer crashed on unknown address %p"
+  Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
              " (pc %p sp %p bp %p T%d)\n",
              (void*)addr, (void*)pc, (void*)sp, (void*)bp,
              asanThreadRegistry().GetCurrentTidOrInvalid());
@@ -331,14 +333,14 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
 
 void ReportDoubleFree(uptr addr, StackTrace *stack) {
   ScopedInErrorReport in_report;
-  Report("ERROR: AddressSanitizer attempting double-free on %p:\n", addr);
+  Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
   PrintStack(stack);
   DescribeHeapAddress(addr, 1);
 }
 
 void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
   ScopedInErrorReport in_report;
-  Report("ERROR: AddressSanitizer attempting free on address "
+  Report("ERROR: AddressSanitizer: attempting free on address "
              "which was not malloc()-ed: %p\n", addr);
   PrintStack(stack);
   DescribeHeapAddress(addr, 1);
@@ -346,7 +348,7 @@ void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
 
 void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
   ScopedInErrorReport in_report;
-  Report("ERROR: AddressSanitizer attempting to call "
+  Report("ERROR: AddressSanitizer: attempting to call "
              "malloc_usable_size() for pointer which is "
              "not owned: %p\n", addr);
   PrintStack(stack);
@@ -355,7 +357,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
 
 void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
   ScopedInErrorReport in_report;
-  Report("ERROR: AddressSanitizer attempting to call "
+  Report("ERROR: AddressSanitizer: attempting to call "
              "__asan_get_allocated_size() for pointer which is "
              "not owned: %p\n", addr);
   PrintStack(stack);
@@ -366,7 +368,7 @@ void ReportStringFunctionMemoryRangesOverlap(
     const char *function, const char *offset1, uptr length1,
     const char *offset2, uptr length2, StackTrace *stack) {
   ScopedInErrorReport in_report;
-  Report("ERROR: AddressSanitizer %s-param-overlap: "
+  Report("ERROR: AddressSanitizer: %s-param-overlap: "
              "memory ranges [%p,%p) and [%p, %p) overlap\n", \
              function, offset1, offset1 + length1, offset2, offset2 + length2);
   PrintStack(stack);
@@ -459,7 +461,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
     }
   }
 
-  Report("ERROR: AddressSanitizer %s on address "
+  Report("ERROR: AddressSanitizer: %s on address "
              "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
              bug_descr, (void*)addr, pc, bp, sp);
 
diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc
index 442d41c4f23c..7731c17a3511 100644
--- a/libsanitizer/asan/asan_rtl.cc
+++ b/libsanitizer/asan/asan_rtl.cc
@@ -132,7 +132,7 @@ void InitializeFlags(Flags *f, const char *env) {
   f->unmap_shadow_on_exit = false;
   f->abort_on_error = false;
   f->atexit = false;
-  f->disable_core = (__WORDSIZE == 64);
+  f->disable_core = (SANITIZER_WORDSIZE == 64);
   f->strip_path_prefix = "";
   f->allow_reexec = true;
   f->print_full_thread_history = true;
diff --git a/libsanitizer/asan/asan_stats.cc b/libsanitizer/asan/asan_stats.cc
index fa4adcb7f9aa..ecdf5ffad09d 100644
--- a/libsanitizer/asan/asan_stats.cc
+++ b/libsanitizer/asan/asan_stats.cc
@@ -54,7 +54,8 @@ void AsanStats::Print() {
 static AsanLock print_lock(LINKER_INITIALIZED);
 
 static void PrintAccumulatedStats() {
-  AsanStats stats = asanThreadRegistry().GetAccumulatedStats();
+  AsanStats stats;
+  asanThreadRegistry().GetAccumulatedStats(&stats);
   // Use lock to keep reports from mixing up.
   ScopedLock lock(&print_lock);
   stats.Print();
diff --git a/libsanitizer/asan/asan_thread.cc b/libsanitizer/asan/asan_thread.cc
index 9295c1570ecf..4ec98e5ed227 100644
--- a/libsanitizer/asan/asan_thread.cc
+++ b/libsanitizer/asan/asan_thread.cc
@@ -116,25 +116,25 @@ void AsanThread::ClearShadowForThreadStack() {
 
 const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
   uptr bottom = 0;
-  bool is_fake_stack = false;
   if (AddrIsInStack(addr)) {
     bottom = stack_bottom();
   } else {
     bottom = fake_stack().AddrIsInFakeStack(addr);
     CHECK(bottom);
-    is_fake_stack = true;
+    *offset = addr - bottom;
+    return  (const char *)((uptr*)bottom)[1];
   }
-  uptr aligned_addr = addr & ~(__WORDSIZE/8 - 1);  // align addr.
+  uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1);  // align addr.
   u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
   u8 *shadow_bottom = (u8*)MemToShadow(bottom);
 
   while (shadow_ptr >= shadow_bottom &&
-      *shadow_ptr != kAsanStackLeftRedzoneMagic) {
+         *shadow_ptr != kAsanStackLeftRedzoneMagic) {
     shadow_ptr--;
   }
 
   while (shadow_ptr >= shadow_bottom &&
-      *shadow_ptr == kAsanStackLeftRedzoneMagic) {
+         *shadow_ptr == kAsanStackLeftRedzoneMagic) {
     shadow_ptr--;
   }
 
@@ -144,8 +144,7 @@ const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
   }
 
   uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
-  CHECK((ptr[0] == kCurrentStackFrameMagic) ||
-      (is_fake_stack && ptr[0] == kRetiredStackFrameMagic));
+  CHECK(ptr[0] == kCurrentStackFrameMagic);
   *offset = addr - (uptr)ptr;
   return (const char*)ptr[1];
 }
diff --git a/libsanitizer/asan/asan_thread_registry.cc b/libsanitizer/asan/asan_thread_registry.cc
index 840837e00042..9858cce22b07 100644
--- a/libsanitizer/asan/asan_thread_registry.cc
+++ b/libsanitizer/asan/asan_thread_registry.cc
@@ -102,16 +102,20 @@ AsanStats &AsanThreadRegistry::GetCurrentThreadStats() {
   return (t) ? t->stats() : main_thread_.stats();
 }
 
-AsanStats AsanThreadRegistry::GetAccumulatedStats() {
+void AsanThreadRegistry::GetAccumulatedStats(AsanStats *stats) {
   ScopedLock lock(&mu_);
   UpdateAccumulatedStatsUnlocked();
-  return accumulated_stats_;
+  internal_memcpy(stats, &accumulated_stats_, sizeof(accumulated_stats_));
 }
 
 uptr AsanThreadRegistry::GetCurrentAllocatedBytes() {
   ScopedLock lock(&mu_);
   UpdateAccumulatedStatsUnlocked();
-  return accumulated_stats_.malloced - accumulated_stats_.freed;
+  uptr malloced = accumulated_stats_.malloced;
+  uptr freed = accumulated_stats_.freed;
+  // Return sane value if malloced < freed due to racy
+  // way we update accumulated stats.
+  return (malloced > freed) ? malloced - freed : 1;
 }
 
 uptr AsanThreadRegistry::GetHeapSize() {
@@ -123,11 +127,14 @@ uptr AsanThreadRegistry::GetHeapSize() {
 uptr AsanThreadRegistry::GetFreeBytes() {
   ScopedLock lock(&mu_);
   UpdateAccumulatedStatsUnlocked();
-  return accumulated_stats_.mmaped
-         - accumulated_stats_.malloced
-         - accumulated_stats_.malloced_redzones
-         + accumulated_stats_.really_freed
-         + accumulated_stats_.really_freed_redzones;
+  uptr total_free = accumulated_stats_.mmaped
+                  + accumulated_stats_.really_freed
+                  + accumulated_stats_.really_freed_redzones;
+  uptr total_used = accumulated_stats_.malloced
+                  + accumulated_stats_.malloced_redzones;
+  // Return sane value if total_free < total_used due to racy
+  // way we update accumulated stats.
+  return (total_free > total_used) ? total_free - total_used : 1;
 }
 
 // Return several stats counters with a single call to
diff --git a/libsanitizer/asan/asan_thread_registry.h b/libsanitizer/asan/asan_thread_registry.h
index 99d5cb56af08..bb6b2678faab 100644
--- a/libsanitizer/asan/asan_thread_registry.h
+++ b/libsanitizer/asan/asan_thread_registry.h
@@ -45,9 +45,9 @@ class AsanThreadRegistry {
   // Returns stats for GetCurrent(), or stats for
   // T0 if GetCurrent() returns 0.
   AsanStats &GetCurrentThreadStats();
-  // Flushes all thread-local stats to accumulated stats, and returns
+  // Flushes all thread-local stats to accumulated stats, and makes
   // a copy of accumulated stats.
-  AsanStats GetAccumulatedStats();
+  void GetAccumulatedStats(AsanStats *stats);
   uptr GetCurrentAllocatedBytes();
   uptr GetHeapSize();
   uptr GetFreeBytes();
diff --git a/libsanitizer/asan/asan_win.cc b/libsanitizer/asan/asan_win.cc
index a5c0441dafa6..8b7f9ef0e383 100644
--- a/libsanitizer/asan/asan_win.cc
+++ b/libsanitizer/asan/asan_win.cc
@@ -137,6 +137,10 @@ void AsanPlatformThreadInit() {
   // Nothing here for now.
 }
 
+void ClearShadowMemoryForContext(void *context) {
+  UNIMPLEMENTED();
+}
+
 }  // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h b/libsanitizer/include/sanitizer/common_interface_defs.h
index d78d2802a2b8..f6e814df6f5f 100644
--- a/libsanitizer/include/sanitizer/common_interface_defs.h
+++ b/libsanitizer/include/sanitizer/common_interface_defs.h
@@ -68,6 +68,11 @@ extern "C" {
   // Tell the tools to write their reports to "path.<pid>" instead of stderr.
   void __sanitizer_set_report_path(const char *path)
       SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // Tell the tools to write their reports to given file descriptor instead of
+  // stderr.
+  void __sanitizer_set_report_fd(int fd)
+      SANITIZER_INTERFACE_ATTRIBUTE;
 }  // extern "C"
 
 #endif  // SANITIZER_COMMON_INTERFACE_DEFS_H
diff --git a/libsanitizer/merge.sh b/libsanitizer/merge.sh
index 6918ee2475fb..297af56e790d 100755
--- a/libsanitizer/merge.sh
+++ b/libsanitizer/merge.sh
@@ -44,10 +44,11 @@ merge() {
       cp -v $upstream_path/$f $local_path
     elif [ -f $upstream_path/$f ]; then
       echo "FOUND IN UPSTREAM :" $f
-      echo "UNSUPPORTED YET" && exit 1
+      cp -v $upstream_path/$f $local_path
+      svn add $local_path/$f
     elif [ -f $local_path/$f ]; then
       echo "FOUND IN LOCAL    :" $f
-      echo "UNSUPPORTED YET" && exit 1
+      svn remove $local_path/$f
     fi
   done
 
@@ -65,6 +66,7 @@ CUR_REV=$(get_current_rev)
 echo Current upstream revision: $CUR_REV
 merge include/sanitizer include/sanitizer
 merge lib/asan asan
+merge lib/tsan/rtl tsan
 merge lib/sanitizer_common sanitizer_common
 merge lib/interception interception
 
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator64.h b/libsanitizer/sanitizer_common/sanitizer_allocator64.h
index 247719876aa7..7614aba52ac9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator64.h
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator64.h
@@ -16,7 +16,7 @@
 #define SANITIZER_ALLOCATOR_H
 
 #include "sanitizer_internal_defs.h"
-#if __WORDSIZE != 64
+#if SANITIZER_WORDSIZE != 64
 # error "sanitizer_allocator64.h can only be used on 64-bit platforms"
 #endif
 
@@ -275,7 +275,12 @@ class SizeClassAllocator64 {
     } while (idx < end_idx);
     region->allocated_user += idx - beg_idx;
     region->allocated_meta += i * kMetadataSize;
-    CHECK_LT(region->allocated_user + region->allocated_meta, kRegionSize);
+    if (region->allocated_user + region->allocated_meta > kRegionSize) {
+      Printf("Out of memory. Dying.\n");
+      Printf("The process has exhausted %zuMB for size class %zu.\n",
+          kRegionSize / 1024 / 1024, size);
+      Die();
+    }
   }
 
   void *AllocateBySizeClass(uptr class_id) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cc b/libsanitizer/sanitizer_common/sanitizer_common.cc
index 43ef980e846f..fda67a542d50 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_common.cc
@@ -14,7 +14,9 @@
 
 namespace __sanitizer {
 
-static fd_t report_fd = 2;  // By default, dump to stderr.
+// By default, dump to stderr. If report_fd is kInvalidFd, try to obtain file
+// descriptor by opening file in report_path.
+static fd_t report_fd = kStderrFd;
 static char report_path[4096];  // Set via __sanitizer_set_report_path.
 
 static void (*DieCallback)(void);
@@ -44,18 +46,27 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
   Die();
 }
 
+static void MaybeOpenReportFile() {
+  if (report_fd != kInvalidFd)
+    return;
+  fd_t fd = internal_open(report_path, true);
+  if (fd == kInvalidFd) {
+    report_fd = kStderrFd;
+    Report("ERROR: Can't open file: %s\n", report_path);
+    Die();
+  }
+  report_fd = fd;
+}
+
+bool PrintsToTty() {
+  MaybeOpenReportFile();
+  return internal_isatty(report_fd);
+}
+
 void RawWrite(const char *buffer) {
   static const char *kRawWriteError = "RawWrite can't output requested buffer!";
   uptr length = (uptr)internal_strlen(buffer);
-  if (report_fd == kInvalidFd) {
-    fd_t fd = internal_open(report_path, true);
-    if (fd == kInvalidFd) {
-      report_fd = 2;
-      Report("ERROR: Can't open file: %s\n", report_path);
-      Die();
-    }
-    report_fd = fd;
-  }
+  MaybeOpenReportFile();
   if (length != internal_write(report_fd, buffer, length)) {
     internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
     Die();
@@ -136,16 +147,27 @@ void SortArray(uptr *array, uptr size) {
 
 }  // namespace __sanitizer
 
+using namespace __sanitizer;  // NOLINT
+
+extern "C" {
 void __sanitizer_set_report_path(const char *path) {
   if (!path) return;
   uptr len = internal_strlen(path);
-  if (len > sizeof(__sanitizer::report_path) - 100) {
+  if (len > sizeof(report_path) - 100) {
     Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
            path[0], path[1], path[2], path[3],
            path[4], path[5], path[6], path[7]);
     Die();
   }
-  internal_snprintf(__sanitizer::report_path,
-                    sizeof(__sanitizer::report_path), "%s.%d", path, GetPid());
-  __sanitizer::report_fd = kInvalidFd;
+  internal_snprintf(report_path, sizeof(report_path), "%s.%d", path, GetPid());
+  report_fd = kInvalidFd;
+}
+
+void __sanitizer_set_report_fd(int fd) {
+  if (report_fd != kStdoutFd &&
+      report_fd != kStderrFd &&
+      report_fd != kInvalidFd)
+    internal_close(report_fd);
+  report_fd = fd;
 }
+}  // extern "C"
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h
index cddefd7ea090..e565b93af29f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.h
+++ b/libsanitizer/sanitizer_common/sanitizer_common.h
@@ -19,14 +19,24 @@
 namespace __sanitizer {
 
 // Constants.
-const uptr kWordSize = __WORDSIZE / 8;
+const uptr kWordSize = SANITIZER_WORDSIZE / 8;
 const uptr kWordSizeInBits = 8 * kWordSize;
-const uptr kPageSizeBits = 12;
-const uptr kPageSize = 1UL << kPageSizeBits;
+#if defined(__powerpc__) || defined(__powerpc64__)
+// Current PPC64 kernels use 64K pages sizes, but they can be
+// configured with 4K or even other sizes.
+// We may want to use getpagesize() or sysconf(_SC_PAGESIZE) here rather than
+// hardcoding the values, but today these values need to be compile-time
+// constants.
+const uptr kPageSize = 1UL << 16;
+const uptr kCacheLineSize = 128;
+const uptr kMmapGranularity = kPageSize;
+#elif !defined(_WIN32)
+const uptr kPageSize = 1UL << 12;
 const uptr kCacheLineSize = 64;
-#ifndef _WIN32
 const uptr kMmapGranularity = kPageSize;
 #else
+const uptr kPageSize = 1UL << 12;
+const uptr kCacheLineSize = 64;
 const uptr kMmapGranularity = 1UL << 16;
 #endif
 
@@ -96,6 +106,7 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
 
 // IO
 void RawWrite(const char *buffer);
+bool PrintsToTty();
 void Printf(const char *format, ...);
 void Report(const char *format, ...);
 void SetPrintfAndReportCallback(void (*callback)(const char *));
@@ -114,6 +125,7 @@ void *MapFileToMemory(const char *file_name, uptr *buff_size);
 // OS
 void DisableCoreDumper();
 void DumpProcessMap();
+bool FileExists(const char *filename);
 const char *GetEnv(const char *name);
 const char *GetPwd();
 void ReExec();
@@ -170,7 +182,7 @@ INLINE int ToLower(int c) {
   return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
 }
 
-#if __WORDSIZE == 64
+#if SANITIZER_WORDSIZE == 64
 # define FIRST_32_SECOND_64(a, b) (b)
 #else
 # define FIRST_32_SECOND_64(a, b) (a)
diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
index da4d049e2c69..a6795c6720b3 100644
--- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
+++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
@@ -22,8 +22,7 @@ using namespace __sanitizer;  // NOLINT
 #define WEAK SANITIZER_WEAK_ATTRIBUTE
 
 // Platform-specific defs.
-#if defined(_WIN32)
-typedef unsigned long    DWORD;  // NOLINT
+#if defined(_MSC_VER)
 # define ALWAYS_INLINE __declspec(forceinline)
 // FIXME(timurrrr): do we need this on Windows?
 # define ALIAS(x)
@@ -33,7 +32,11 @@ typedef unsigned long    DWORD;  // NOLINT
 # define NORETURN __declspec(noreturn)
 # define THREADLOCAL   __declspec(thread)
 # define NOTHROW
-#else  // _WIN32
+# define LIKELY(x) (x)
+# define UNLIKELY(x) (x)
+# define UNUSED
+# define USED
+#else  // _MSC_VER
 # define ALWAYS_INLINE __attribute__((always_inline))
 # define ALIAS(x) __attribute__((alias(x)))
 # define ALIGNED(x) __attribute__((aligned(x)))
@@ -41,22 +44,15 @@ typedef unsigned long    DWORD;  // NOLINT
 # define NOINLINE __attribute__((noinline))
 # define NORETURN  __attribute__((noreturn))
 # define THREADLOCAL   __thread
-# ifdef __cplusplus
-#   define NOTHROW throw()
-# else
-#   define NOTHROW __attribute__((__nothrow__))
-#endif
-#endif  // _WIN32
-
-// We have no equivalent of these on Windows.
-#ifndef _WIN32
+# define NOTHROW throw()
 # define LIKELY(x)     __builtin_expect(!!(x), 1)
 # define UNLIKELY(x)   __builtin_expect(!!(x), 0)
 # define UNUSED __attribute__((unused))
 # define USED __attribute__((used))
-#endif
+#endif  // _MSC_VER
 
 #if defined(_WIN32)
+typedef unsigned long DWORD;  // NOLINT
 typedef DWORD thread_return_t;
 # define THREAD_CALLING_CONV __stdcall
 #else  // _WIN32
@@ -65,15 +61,11 @@ typedef void* thread_return_t;
 #endif  // _WIN32
 typedef thread_return_t (THREAD_CALLING_CONV *thread_callback_t)(void* arg);
 
-// If __WORDSIZE was undefined by the platform, define it in terms of the
-// compiler built-ins __LP64__ and _WIN64.
-#ifndef __WORDSIZE
-# if __LP64__ || defined(_WIN64)
-#  define __WORDSIZE 64
-# else
-#  define __WORDSIZE 32
-#  endif
-#endif  // __WORDSIZE
+#if __LP64__ || defined(_WIN64)
+#  define SANITIZER_WORDSIZE 64
+#else
+#  define SANITIZER_WORDSIZE 32
+#endif
 
 // NOTE: Functions below must be defined in each run-time.
 namespace __sanitizer {
@@ -128,7 +120,12 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
 #define DCHECK_GE(a, b)
 #endif
 
-#define UNIMPLEMENTED() CHECK("unimplemented" && 0)
+#define UNREACHABLE(msg) do { \
+  CHECK(0 && msg); \
+  Die(); \
+} while (0)
+
+#define UNIMPLEMENTED() UNREACHABLE("unimplemented")
 
 #define COMPILER_CHECK(pred) IMPL_COMPILER_ASSERT(pred, __LINE__)
 
@@ -142,13 +139,13 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
 // have stdint.h (like in Visual Studio 9).
 #undef __INT64_C
 #undef __UINT64_C
-#if __WORDSIZE == 64
+#if SANITIZER_WORDSIZE == 64
 # define __INT64_C(c)  c ## L
 # define __UINT64_C(c) c ## UL
 #else
 # define __INT64_C(c)  c ## LL
 # define __UINT64_C(c) c ## ULL
-#endif  // __WORDSIZE == 64
+#endif  // SANITIZER_WORDSIZE == 64
 #undef INT32_MIN
 #define INT32_MIN              (-2147483647-1)
 #undef INT32_MAX
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.cc b/libsanitizer/sanitizer_common/sanitizer_libc.cc
index 21869bc4846f..4d43cd7d0133 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.cc
@@ -42,6 +42,23 @@ void *internal_memcpy(void *dest, const void *src, uptr n) {
   return dest;
 }
 
+void *internal_memmove(void *dest, const void *src, uptr n) {
+  char *d = (char*)dest;
+  char *s = (char*)src;
+  sptr i, signed_n = (sptr)n;
+  CHECK_GE(signed_n, 0);
+  if (d < s) {
+    for (i = 0; i < signed_n; ++i)
+      d[i] = s[i];
+  } else {
+    if (d > s && signed_n > 0)
+      for (i = signed_n - 1; i >= 0 ; --i) {
+        d[i] = s[i];
+      }
+  }
+  return dest;
+}
+
 void *internal_memset(void* s, int c, uptr n) {
   // The next line prevents Clang from making a call to memset() instead of the
   // loop below.
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h b/libsanitizer/sanitizer_common/sanitizer_libc.h
index 135285111905..4aa4a279d402 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.h
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.h
@@ -27,6 +27,7 @@ s64 internal_atoll(const char *nptr);
 void *internal_memchr(const void *s, int c, uptr n);
 int internal_memcmp(const void* s1, const void* s2, uptr n);
 void *internal_memcpy(void *dest, const void *src, uptr n);
+void *internal_memmove(void *dest, const void *src, uptr n);
 // Should not be used in performance-critical places.
 void *internal_memset(void *s, int c, uptr n);
 char* internal_strchr(const char *s, int c);
@@ -52,7 +53,11 @@ int internal_munmap(void *addr, uptr length);
 // I/O
 typedef int fd_t;
 const fd_t kInvalidFd = -1;
+const fd_t kStdinFd = 0;
+const fd_t kStdoutFd = 1;
+const fd_t kStderrFd = 2;
 int internal_close(fd_t fd);
+int internal_isatty(fd_t fd);
 fd_t internal_open(const char *filename, bool write);
 uptr internal_read(fd_t fd, void *buf, uptr count);
 uptr internal_write(fd_t fd, const void *buf, uptr count);
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc
index f2a0d39ca992..2145aa04113d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc
@@ -30,9 +30,9 @@
 #include <errno.h>
 
 // Are we using 32-bit or 64-bit syscalls?
-// x32 (which defines __x86_64__) has __WORDSIZE == 32
+// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
 // but it still needs to use 64-bit syscalls.
-#if defined(__x86_64__) || __WORDSIZE == 64
+#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
 #else
 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
@@ -101,6 +101,20 @@ int internal_sched_yield() {
 }
 
 // ----------------- sanitizer_common.h
+bool FileExists(const char *filename) {
+#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
+  struct stat st;
+  if (syscall(__NR_stat, filename, &st))
+    return false;
+#else
+  struct stat64 st;
+  if (syscall(__NR_stat64, filename, &st))
+    return false;
+#endif
+  // Sanity check: filename is a regular file.
+  return S_ISREG(st.st_mode);
+}
+
 uptr GetTid() {
   return syscall(__NR_gettid);
 }
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc
index 400cd21842b2..aa313baff925 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc
@@ -78,6 +78,14 @@ int internal_sched_yield() {
 }
 
 // ----------------- sanitizer_common.h
+bool FileExists(const char *filename) {
+  struct stat st;
+  if (stat(filename, &st))
+    return false;
+  // Sanity check: filename is a regular file.
+  return S_ISREG(st.st_mode);
+}
+
 uptr GetTid() {
   return reinterpret_cast<uptr>(pthread_self());
 }
diff --git a/libsanitizer/sanitizer_common/sanitizer_placement_new.h b/libsanitizer/sanitizer_common/sanitizer_placement_new.h
index d149683b43de..e32d65702df0 100644
--- a/libsanitizer/sanitizer_common/sanitizer_placement_new.h
+++ b/libsanitizer/sanitizer_common/sanitizer_placement_new.h
@@ -17,7 +17,7 @@
 #include "sanitizer_internal_defs.h"
 
 namespace __sanitizer {
-#if (__WORDSIZE == 64) || defined(__APPLE__)
+#if (SANITIZER_WORDSIZE == 64) || defined(__APPLE__)
 typedef uptr operator_new_ptr_type;
 #else
 typedef u32 operator_new_ptr_type;
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cc b/libsanitizer/sanitizer_common/sanitizer_posix.cc
index 8f71cfc049dd..bd9270ecaa42 100644
--- a/libsanitizer/sanitizer_common/sanitizer_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_posix.cc
@@ -72,10 +72,15 @@ void UnmapOrDie(void *addr, uptr size) {
 }
 
 void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
-  return internal_mmap((void*)fixed_addr, size,
-                      PROT_READ | PROT_WRITE,
-                      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
-                      -1, 0);
+  void *p = internal_mmap((void*)(fixed_addr & ~(kPageSize - 1)),
+      RoundUpTo(size, kPageSize),
+      PROT_READ | PROT_WRITE,
+      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
+      -1, 0);
+  if (p == (void*)-1)
+    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
+           size, size, fixed_addr, errno);
+  return p;
 }
 
 void *Mprotect(uptr fixed_addr, uptr size) {
@@ -182,6 +187,10 @@ int Atexit(void (*function)(void)) {
 #endif
 }
 
+int internal_isatty(fd_t fd) {
+  return isatty(fd);
+}
+
 }  // namespace __sanitizer
 
 #endif  // __linux__ || __APPLE_
diff --git a/libsanitizer/sanitizer_common/sanitizer_printf.cc b/libsanitizer/sanitizer_common/sanitizer_printf.cc
index da4dc7f53a18..5876fef04f3b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_printf.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_printf.cc
@@ -43,7 +43,12 @@ static int AppendUnsigned(char **buff, const char *buff_end, u64 num,
     num_buffer[pos++] = num % base;
     num /= base;
   } while (num > 0);
-  while (pos < minimal_num_length) num_buffer[pos++] = 0;
+  if (pos < minimal_num_length) {
+    // Make sure compiler doesn't insert call to memset here.
+    internal_memset(&num_buffer[pos], 0,
+                    sizeof(num_buffer[0]) * (minimal_num_length - pos));
+    pos = minimal_num_length;
+  }
   int result = 0;
   while (pos-- > 0) {
     uptr digit = num_buffer[pos];
@@ -53,13 +58,16 @@ static int AppendUnsigned(char **buff, const char *buff_end, u64 num,
   return result;
 }
 
-static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num) {
+static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
+                               u8 minimal_num_length) {
   int result = 0;
   if (num < 0) {
     result += AppendChar(buff, buff_end, '-');
     num = -num;
+    if (minimal_num_length)
+      --minimal_num_length;
   }
-  result += AppendUnsigned(buff, buff_end, (u64)num, 10, 0);
+  result += AppendUnsigned(buff, buff_end, (u64)num, 10, minimal_num_length);
   return result;
 }
 
@@ -77,14 +85,14 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
   int result = 0;
   result += AppendString(buff, buff_end, "0x");
   result += AppendUnsigned(buff, buff_end, ptr_value, 16,
-                           (__WORDSIZE == 64) ? 12 : 8);
+                           (SANITIZER_WORDSIZE == 64) ? 12 : 8);
   return result;
 }
 
 int VSNPrintf(char *buff, int buff_length,
               const char *format, va_list args) {
-  static const char *kPrintfFormatsHelp = "Supported Printf formats: "
-                                          "%%[z]{d,u,x}; %%p; %%s; %%c\n";
+  static const char *kPrintfFormatsHelp =
+    "Supported Printf formats: %%(0[0-9]*)?(z|ll)?{d,u,x}; %%p; %%s; %%c\n";
   RAW_CHECK(format);
   RAW_CHECK(buff_length > 0);
   const char *buff_end = &buff[buff_length - 1];
@@ -96,42 +104,55 @@ int VSNPrintf(char *buff, int buff_length,
       continue;
     }
     cur++;
+    bool have_width = (*cur == '0');
+    int width = 0;
+    if (have_width) {
+      while (*cur >= '0' && *cur <= '9') {
+        have_width = true;
+        width = width * 10 + *cur++ - '0';
+      }
+    }
     bool have_z = (*cur == 'z');
     cur += have_z;
+    bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l');
+    cur += have_ll * 2;
     s64 dval;
     u64 uval;
+    bool have_flags = have_width | have_z | have_ll;
     switch (*cur) {
       case 'd': {
-        dval = have_z ? va_arg(args, sptr)
-                      : va_arg(args, int);
-        result += AppendSignedDecimal(&buff, buff_end, dval);
+        dval = have_ll ? va_arg(args, s64)
+             : have_z ? va_arg(args, sptr)
+             : va_arg(args, int);
+        result += AppendSignedDecimal(&buff, buff_end, dval, width);
         break;
       }
       case 'u':
       case 'x': {
-        uval = have_z ? va_arg(args, uptr)
-                      : va_arg(args, unsigned);
+        uval = have_ll ? va_arg(args, u64)
+             : have_z ? va_arg(args, uptr)
+             : va_arg(args, unsigned);
         result += AppendUnsigned(&buff, buff_end, uval,
-                                 (*cur == 'u') ? 10 : 16, 0);
+                                 (*cur == 'u') ? 10 : 16, width);
         break;
       }
       case 'p': {
-        RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
+        RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
         result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
         break;
       }
       case 's': {
-        RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
+        RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
         result += AppendString(&buff, buff_end, va_arg(args, char*));
         break;
       }
       case 'c': {
-        RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
+        RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
         result += AppendChar(&buff, buff_end, va_arg(args, int));
         break;
       }
       case '%' : {
-        RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
+        RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
         result += AppendChar(&buff, buff_end, '%');
         break;
       }
@@ -151,7 +172,7 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)) {
 }
 
 void Printf(const char *format, ...) {
-  const int kLen = 1024 * 4;
+  const int kLen = 16 * 1024;
   InternalScopedBuffer<char> buffer(kLen);
   va_list args;
   va_start(args, format);
@@ -177,7 +198,7 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
 
 // Like Printf, but prints the current PID before the output string.
 void Report(const char *format, ...) {
-  const int kLen = 1024 * 4;
+  const int kLen = 16 * 1024;
   InternalScopedBuffer<char> buffer(kLen);
   int needed_length = internal_snprintf(buffer.data(),
                                         kLen, "==%d== ", GetPid());
diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps.h b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
index 5e5e5ce89be4..5541cfc0c630 100644
--- a/libsanitizer/sanitizer_common/sanitizer_procmaps.h
+++ b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
@@ -23,7 +23,6 @@ class MemoryMappingLayout {
   bool GetObjectNameAndOffset(uptr addr, uptr *offset,
                               char filename[], uptr filename_size) {
     UNIMPLEMENTED();
-    return false;
   }
 };
 
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
index 915c4b8050a5..037a7c3f9c00 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
@@ -31,7 +31,12 @@ static uptr patch_pc(uptr pc) {
   // Cancel Thumb bit.
   pc = pc & (~1);
 #endif
+#if defined(__powerpc__) || defined(__powerpc64__)
+  // PCs are always 4 byte aligned.
+  return pc - 4;
+#else
   return pc - 1;
+#endif
 }
 
 static void PrintStackFramePrefix(uptr frame_num, uptr pc) {
@@ -75,7 +80,8 @@ void StackTrace::PrintStack(const uptr *addr, uptr size,
         Printf(" %s\n", StripPathPrefix(buff.data(), strip_file_prefix));
         frame_num++;
       }
-    } else if (symbolize) {
+    }
+    if (symbolize && addr_frames_num == 0) {
       // Use our own (online) symbolizer, if necessary.
       addr_frames_num = SymbolizeCode(pc, addr_frames.data(),
                                       addr_frames.size());
@@ -135,12 +141,20 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp,
   }
 }
 
+void StackTrace::PopStackFrames(uptr count) {
+  CHECK(size >= count);
+  size -= count;
+  for (uptr i = 0; i < size; i++) {
+    trace[i] = trace[i + count];
+  }
+}
+
 // On 32-bits we don't compress stack traces.
 // On 64-bits we compress stack traces: if a given pc differes slightly from
 // the previous one, we record a 31-bit offset instead of the full pc.
 SANITIZER_INTERFACE_ATTRIBUTE
 uptr StackTrace::CompressStack(StackTrace *stack, u32 *compressed, uptr size) {
-#if __WORDSIZE == 32
+#if SANITIZER_WORDSIZE == 32
   // Don't compress, just copy.
   uptr res = 0;
   for (uptr i = 0; i < stack->size && i < size; i++) {
@@ -181,7 +195,7 @@ uptr StackTrace::CompressStack(StackTrace *stack, u32 *compressed, uptr size) {
     compressed[c_index] = 0;
   if (c_index + 1 < size)
     compressed[c_index + 1] = 0;
-#endif  // __WORDSIZE
+#endif  // SANITIZER_WORDSIZE
 
   // debug-only code
 #if 0
@@ -204,7 +218,7 @@ uptr StackTrace::CompressStack(StackTrace *stack, u32 *compressed, uptr size) {
 SANITIZER_INTERFACE_ATTRIBUTE
 void StackTrace::UncompressStack(StackTrace *stack,
                                  u32 *compressed, uptr size) {
-#if __WORDSIZE == 32
+#if SANITIZER_WORDSIZE == 32
   // Don't uncompress, just copy.
   stack->size = 0;
   for (uptr i = 0; i < size && i < kStackTraceMax; i++) {
@@ -239,7 +253,7 @@ void StackTrace::UncompressStack(StackTrace *stack,
     stack->trace[stack->size++] = pc;
     prev_pc = pc;
   }
-#endif  // __WORDSIZE
+#endif  // SANITIZER_WORDSIZE
 }
 
 }  // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
index a7934c65e1e0..b36a1a082c5a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
@@ -43,6 +43,8 @@ struct StackTrace {
 
   void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom);
 
+  void PopStackFrames(uptr count);
+
   static uptr GetCurrentPc();
 
   static uptr CompressStack(StackTrace *stack,
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc
index 66ac3c8a2467..efd1e8168320 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc
@@ -291,7 +291,8 @@ class Symbolizer {
     }
   }
 
-  static const uptr kMaxNumberOfModuleContexts = 4096;
+  // 16K loaded modules should be enough for everyone.
+  static const uptr kMaxNumberOfModuleContexts = 1 << 14;
   LoadedModule *modules_;  // Array of module descriptions is leaked.
   uptr n_modules_;
 
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
index 83adf0252826..13ec83f2cbf2 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
@@ -77,7 +77,7 @@ class LoadedModule {
   };
   char *full_name_;
   uptr base_address_;
-  static const uptr kMaxNumberOfAddressRanges = 8;
+  static const uptr kMaxNumberOfAddressRanges = 6;
   AddressRange ranges_[kMaxNumberOfAddressRanges];
   uptr n_ranges_;
 };
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc
index 50e39a75c3a4..bb1c40f96136 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc
@@ -21,6 +21,7 @@
 #include <poll.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #if !defined(__ANDROID__) && !defined(ANDROID)
@@ -29,8 +30,15 @@
 
 namespace __sanitizer {
 
+static const int kSymbolizerStartupTimeMillis = 10;
+
 bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
                                int *input_fd, int *output_fd) {
+  if (!FileExists(path_to_symbolizer)) {
+    Report("WARNING: invalid path to external symbolizer!\n");
+    return false;
+  }
+
   int *infd = NULL;
   int *outfd = NULL;
   // The client program may close its stdin and/or stdout and/or stderr
@@ -97,13 +105,23 @@ bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
   internal_close(infd[1]);
   *input_fd = infd[0];
   *output_fd = outfd[1];
+
+  // Check that symbolizer subprocess started successfully.
+  int pid_status;
+  SleepForMillis(kSymbolizerStartupTimeMillis);
+  int exited_pid = waitpid(pid, &pid_status, WNOHANG);
+  if (exited_pid != 0) {
+    // Either waitpid failed, or child has already exited.
+    Report("WARNING: external symbolizer didn't start up correctly!\n");
+    return false;
+  }
+
   return true;
 }
 
 #if defined(__ANDROID__) || defined(ANDROID)
 uptr GetListOfModules(LoadedModule *modules, uptr max_modules) {
   UNIMPLEMENTED();
-  return 0;
 }
 #else  // ANDROID
 typedef ElfW(Phdr) Elf_Phdr;
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc
index c5ca616d89d3..a1b931b737e2 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc
@@ -18,12 +18,10 @@ namespace __sanitizer {
 bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
                                int *input_fd, int *output_fd) {
   UNIMPLEMENTED();
-  return false;
 }
 
 uptr GetListOfModules(LoadedModule *modules, uptr max_modules) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 }  // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
index 7e6ba53e128a..3b81e794e595 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
@@ -20,12 +20,10 @@ namespace __sanitizer {
 bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
                                int *input_fd, int *output_fd) {
   UNIMPLEMENTED();
-  return false;
 }
 
 uptr GetListOfModules(LoadedModule *modules, uptr max_modules) {
   UNIMPLEMENTED();
-  return 0;
 };
 
 }  // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc
index 314852304d83..03a5c204c667 100644
--- a/libsanitizer/sanitizer_common/sanitizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_win.cc
@@ -10,6 +10,9 @@
 // sanitizer_libc.h.
 //===----------------------------------------------------------------------===//
 #ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#include <stdlib.h>
 #include <windows.h>
 
 #include "sanitizer_common.h"
@@ -18,6 +21,10 @@
 namespace __sanitizer {
 
 // --------------------- sanitizer_common.h
+bool FileExists(const char *filename) {
+  UNIMPLEMENTED();
+}
+
 int GetPid() {
   return GetProcessId(GetCurrentProcess());
 }
@@ -39,7 +46,6 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
   *stack_bottom = (uptr)mbi.AllocationBase;
 }
 
-
 void *MmapOrDie(uptr size, const char *mem_type) {
   void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
   if (rv == 0) {
@@ -59,8 +65,12 @@ void UnmapOrDie(void *addr, uptr size) {
 }
 
 void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
-  return VirtualAlloc((LPVOID)fixed_addr, size,
-                      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+  void *p = VirtualAlloc((LPVOID)fixed_addr, size,
+      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+  if (p == 0)
+    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n",
+           size, size, fixed_addr, GetLastError());
+  return p;
 }
 
 void *Mprotect(uptr fixed_addr, uptr size) {
@@ -75,7 +85,6 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
 
 void *MapFileToMemory(const char *file_name, uptr *buff_size) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 const char *GetEnv(const char *name) {
@@ -96,7 +105,6 @@ const char *GetEnv(const char *name) {
 
 const char *GetPwd() {
   UNIMPLEMENTED();
-  return 0;
 }
 
 void DumpProcessMap() {
@@ -113,7 +121,6 @@ void ReExec() {
 
 bool StackSizeIsUnlimited() {
   UNIMPLEMENTED();
-  return false;
 }
 
 void SetStackSizeLimitInBytes(uptr limit) {
@@ -137,39 +144,40 @@ void Abort() {
   _exit(-1);  // abort is not NORETURN on Windows.
 }
 
+#ifndef SANITIZER_GO
 int Atexit(void (*function)(void)) {
   return atexit(function);
 }
+#endif
 
 // ------------------ sanitizer_libc.h
 void *internal_mmap(void *addr, uptr length, int prot, int flags,
                     int fd, u64 offset) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 int internal_munmap(void *addr, uptr length) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 int internal_close(fd_t fd) {
   UNIMPLEMENTED();
-  return 0;
+}
+
+int internal_isatty(fd_t fd) {
+  UNIMPLEMENTED();
 }
 
 fd_t internal_open(const char *filename, bool write) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 uptr internal_read(fd_t fd, void *buf, uptr count) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 uptr internal_write(fd_t fd, const void *buf, uptr count) {
-  if (fd != 2)
+  if (fd != kStderrFd)
     UNIMPLEMENTED();
   HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
   if (err == 0)
@@ -182,21 +190,18 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) {
 
 uptr internal_filesize(fd_t fd) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 int internal_dup2(int oldfd, int newfd) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
   UNIMPLEMENTED();
-  return 0;
 }
 
 int internal_sched_yield() {
-  UNIMPLEMENTED();
+  Sleep(0);
   return 0;
 }
 
diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am
index a307502c97ae..c4fbad9b74df 100644
--- a/libsanitizer/tsan/Makefile.am
+++ b/libsanitizer/tsan/Makefile.am
@@ -26,7 +26,6 @@ tsan_files = \
         tsan_suppressions.cc \
         tsan_interface_ann.cc \
         tsan_mman.cc \
-        tsan_printf.cc \
         tsan_rtl_report.cc \
         tsan_symbolize_addr2line_linux.cc
 
diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in
index a893bccd5ef5..b919969cf474 100644
--- a/libsanitizer/tsan/Makefile.in
+++ b/libsanitizer/tsan/Makefile.in
@@ -84,7 +84,7 @@ am__objects_1 = tsan_clock.lo tsan_interface_atomic.lo tsan_mutex.lo \
 	tsan_rtl.lo tsan_stat.lo tsan_sync.lo tsan_interceptors.lo \
 	tsan_md5.lo tsan_platform_mac.lo tsan_rtl_mutex.lo \
 	tsan_suppressions.lo tsan_interface_ann.lo tsan_mman.lo \
-	tsan_printf.lo tsan_rtl_report.lo \
+	tsan_rtl_report.lo \
 	tsan_symbolize_addr2line_linux.lo
 am_libtsan_la_OBJECTS = $(am__objects_1)
 libtsan_la_OBJECTS = $(am_libtsan_la_OBJECTS)
@@ -261,7 +261,6 @@ tsan_files = \
         tsan_suppressions.cc \
         tsan_interface_ann.cc \
         tsan_mman.cc \
-        tsan_printf.cc \
         tsan_rtl_report.cc \
         tsan_symbolize_addr2line_linux.cc
 
@@ -395,7 +394,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_mutex.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_linux.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_mac.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_printf.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_report.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_mutex.Plo@am__quote@
diff --git a/libsanitizer/tsan/tsan_clock.cc b/libsanitizer/tsan/tsan_clock.cc
index 937f861477fa..5d45a5d15fb4 100644
--- a/libsanitizer/tsan/tsan_clock.cc
+++ b/libsanitizer/tsan/tsan_clock.cc
@@ -103,13 +103,6 @@ void ThreadClock::acq_rel(SyncClock *dst) {
   release(dst);
 }
 
-void ThreadClock::Disable(unsigned tid) {
-  u64 c0 = clk_[tid];
-  for (uptr i = 0; i < kMaxTidInClock; i++)
-    clk_[i] = (u64)-1;
-  clk_[tid] = c0;
-}
-
 SyncClock::SyncClock()
   : clk_(MBlockClock) {
 }
diff --git a/libsanitizer/tsan/tsan_clock.h b/libsanitizer/tsan/tsan_clock.h
index d5c17305b315..8e4bf99ca896 100644
--- a/libsanitizer/tsan/tsan_clock.h
+++ b/libsanitizer/tsan/tsan_clock.h
@@ -59,8 +59,6 @@ struct ThreadClock {
       nclk_ = tid + 1;
   }
 
-  void Disable(unsigned tid);
-
   uptr size() const {
     return nclk_;
   }
diff --git a/libsanitizer/tsan/tsan_defs.h b/libsanitizer/tsan/tsan_defs.h
index 6a6f6b978327..6f3fd21e246d 100644
--- a/libsanitizer/tsan/tsan_defs.h
+++ b/libsanitizer/tsan/tsan_defs.h
@@ -22,6 +22,12 @@
 
 namespace __tsan {
 
+#ifdef TSAN_GO
+const char *const kTsanOptionsEnv = "GORACE";
+#else
+const char *const kTsanOptionsEnv = "TSAN_OPTIONS";
+#endif
+
 const int kTidBits = 13;
 const unsigned kMaxTid = 1 << kTidBits;
 const unsigned kMaxTidInClock = kMaxTid * 2;  // This includes msb 'freed' bit.
@@ -34,20 +40,23 @@ const int kTraceStackSize = 256;
 #ifdef TSAN_SHADOW_COUNT
 # if TSAN_SHADOW_COUNT == 2 \
   || TSAN_SHADOW_COUNT == 4 || TSAN_SHADOW_COUNT == 8
-const unsigned kShadowCnt = TSAN_SHADOW_COUNT;
+const uptr kShadowCnt = TSAN_SHADOW_COUNT;
 # else
 #   error "TSAN_SHADOW_COUNT must be one of 2,4,8"
 # endif
 #else
 // Count of shadow values in a shadow cell.
-const unsigned kShadowCnt = 8;
+const uptr kShadowCnt = 4;
 #endif
 
 // That many user bytes are mapped onto a single shadow cell.
-const unsigned kShadowCell = 8;
+const uptr kShadowCell = 8;
 
 // Size of a single shadow value (u64).
-const unsigned kShadowSize = 8;
+const uptr kShadowSize = 8;
+
+// Shadow memory is kShadowMultiplier times larger than user memory.
+const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
 
 #if defined(TSAN_COLLECT_STATS) && TSAN_COLLECT_STATS
 const bool kCollectStats = true;
diff --git a/libsanitizer/tsan/tsan_flags.cc b/libsanitizer/tsan/tsan_flags.cc
index e8563f5f8770..a69c6a6b545e 100644
--- a/libsanitizer/tsan/tsan_flags.cc
+++ b/libsanitizer/tsan/tsan_flags.cc
@@ -38,6 +38,7 @@ void InitializeFlags(Flags *f, const char *env) {
   f->enable_annotations = true;
   f->suppress_equal_stacks = true;
   f->suppress_equal_addresses = true;
+  f->report_bugs = true;
   f->report_thread_leaks = true;
   f->report_destroy_locked = true;
   f->report_signal_unsafe = true;
@@ -45,7 +46,7 @@ void InitializeFlags(Flags *f, const char *env) {
   f->strip_path_prefix = "";
   f->suppressions = "";
   f->exitcode = 66;
-  f->log_fileno = 2;
+  f->log_fileno = kStderrFd;
   f->atexit_sleep_ms = 1000;
   f->verbosity = 0;
   f->profile_memory = "";
@@ -61,6 +62,7 @@ void InitializeFlags(Flags *f, const char *env) {
   ParseFlag(env, &f->enable_annotations, "enable_annotations");
   ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
   ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
+  ParseFlag(env, &f->report_bugs, "report_bugs");
   ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks");
   ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked");
   ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe");
@@ -75,6 +77,12 @@ void InitializeFlags(Flags *f, const char *env) {
   ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms");
   ParseFlag(env, &f->stop_on_start, "stop_on_start");
   ParseFlag(env, &f->external_symbolizer_path, "external_symbolizer_path");
+
+  if (!f->report_bugs) {
+    f->report_thread_leaks = false;
+    f->report_destroy_locked = false;
+    f->report_signal_unsafe = false;
+  }
 }
 
 }  // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_flags.h b/libsanitizer/tsan/tsan_flags.h
index a6310e3ce6cd..451d3684729b 100644
--- a/libsanitizer/tsan/tsan_flags.h
+++ b/libsanitizer/tsan/tsan_flags.h
@@ -29,6 +29,8 @@ struct Flags {
   // Supress a race report if we've already output another race report
   // on the same address.
   bool suppress_equal_addresses;
+  // Turns off bug reporting entirely (useful for benchmarking).
+  bool report_bugs;
   // Report thread leaks at exit?
   bool report_thread_leaks;
   // Report destruction of a locked mutex?
diff --git a/libsanitizer/tsan/tsan_interceptors.cc b/libsanitizer/tsan/tsan_interceptors.cc
index 194e236ece7a..191dea7387a1 100644
--- a/libsanitizer/tsan/tsan_interceptors.cc
+++ b/libsanitizer/tsan/tsan_interceptors.cc
@@ -113,6 +113,7 @@ struct SignalDesc {
 };
 
 struct SignalContext {
+  int in_blocking_func;
   int int_signal_send;
   int pending_signal_count;
   SignalDesc pending_signals[kSigCount];
@@ -134,8 +135,6 @@ static SignalContext *SigCtx(ThreadState *thr) {
 
 static unsigned g_thread_finalize_key;
 
-static void process_pending_signals(ThreadState *thr);
-
 ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
                                      uptr pc)
     : thr_(thr)
@@ -154,28 +153,43 @@ ScopedInterceptor::~ScopedInterceptor() {
   thr_->in_rtl--;
   if (thr_->in_rtl == 0) {
     FuncExit(thr_);
-    process_pending_signals(thr_);
+    ProcessPendingSignals(thr_);
   }
   CHECK_EQ(in_rtl_, thr_->in_rtl);
 }
 
+#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
+
+struct BlockingCall {
+  explicit BlockingCall(ThreadState *thr)
+      : ctx(SigCtx(thr)) {
+    ctx->in_blocking_func++;
+  }
+
+  ~BlockingCall() {
+    ctx->in_blocking_func--;
+  }
+
+  SignalContext *ctx;
+};
+
 TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
   SCOPED_TSAN_INTERCEPTOR(sleep, sec);
-  unsigned res = sleep(sec);
+  unsigned res = BLOCK_REAL(sleep)(sec);
   AfterSleep(thr, pc);
   return res;
 }
 
 TSAN_INTERCEPTOR(int, usleep, long_t usec) {
   SCOPED_TSAN_INTERCEPTOR(usleep, usec);
-  int res = usleep(usec);
+  int res = BLOCK_REAL(usleep)(usec);
   AfterSleep(thr, pc);
   return res;
 }
 
 TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
   SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
-  int res = nanosleep(req, rem);
+  int res = BLOCK_REAL(nanosleep)(req, rem);
   AfterSleep(thr, pc);
   return res;
 }
@@ -236,7 +250,6 @@ static void finalize(void *arg) {
   {
     ScopedInRtl in_rtl;
     DestroyAndFree(atexit_ctx);
-    REAL(usleep)(flags()->atexit_sleep_ms * 1000);
   }
   int status = Finalize(cur_thread());
   if (status)
@@ -251,13 +264,13 @@ TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
 
 TSAN_INTERCEPTOR(void, longjmp, void *env, int val) {
   SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
-  TsanPrintf("ThreadSanitizer: longjmp() is not supported\n");
+  Printf("ThreadSanitizer: longjmp() is not supported\n");
   Die();
 }
 
 TSAN_INTERCEPTOR(void, siglongjmp, void *env, int val) {
   SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val);
-  TsanPrintf("ThreadSanitizer: siglongjmp() is not supported\n");
+  Printf("ThreadSanitizer: siglongjmp() is not supported\n");
   Die();
 }
 
@@ -588,7 +601,7 @@ static void thread_finalize(void *v) {
   uptr iter = (uptr)v;
   if (iter > 1) {
     if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
-      TsanPrintf("ThreadSanitizer: failed to set thread key\n");
+      Printf("ThreadSanitizer: failed to set thread key\n");
       Die();
     }
     return;
@@ -621,7 +634,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
     ThreadState *thr = cur_thread();
     ScopedInRtl in_rtl;
     if (pthread_setspecific(g_thread_finalize_key, (void*)4)) {
-      TsanPrintf("ThreadSanitizer: failed to set thread key\n");
+      Printf("ThreadSanitizer: failed to set thread key\n");
       Die();
     }
     while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
@@ -676,7 +689,7 @@ TSAN_INTERCEPTOR(int, pthread_create,
 TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
   SCOPED_TSAN_INTERCEPTOR(pthread_join, th, ret);
   int tid = ThreadTid(thr, pc, (uptr)th);
-  int res = REAL(pthread_join)(th, ret);
+  int res = BLOCK_REAL(pthread_join)(th, ret);
   if (res == 0) {
     ThreadJoin(thr, pc, tid);
   }
@@ -979,7 +992,7 @@ TSAN_INTERCEPTOR(int, sem_destroy, void *s) {
 
 TSAN_INTERCEPTOR(int, sem_wait, void *s) {
   SCOPED_TSAN_INTERCEPTOR(sem_wait, s);
-  int res = REAL(sem_wait)(s);
+  int res = BLOCK_REAL(sem_wait)(s);
   if (res == 0) {
     Acquire(thr, pc, (uptr)s);
   }
@@ -988,7 +1001,7 @@ TSAN_INTERCEPTOR(int, sem_wait, void *s) {
 
 TSAN_INTERCEPTOR(int, sem_trywait, void *s) {
   SCOPED_TSAN_INTERCEPTOR(sem_trywait, s);
-  int res = REAL(sem_trywait)(s);
+  int res = BLOCK_REAL(sem_trywait)(s);
   if (res == 0) {
     Acquire(thr, pc, (uptr)s);
   }
@@ -997,7 +1010,7 @@ TSAN_INTERCEPTOR(int, sem_trywait, void *s) {
 
 TSAN_INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
   SCOPED_TSAN_INTERCEPTOR(sem_timedwait, s, abstime);
-  int res = REAL(sem_timedwait)(s, abstime);
+  int res = BLOCK_REAL(sem_timedwait)(s, abstime);
   if (res == 0) {
     Acquire(thr, pc, (uptr)s);
   }
@@ -1189,13 +1202,19 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
 
 TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
   SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
-  int res = REAL(epoll_wait)(epfd, ev, cnt, timeout);
+  int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
   if (res > 0) {
     Acquire(thr, pc, epollfd2addr(epfd));
   }
   return res;
 }
 
+TSAN_INTERCEPTOR(int, poll, void *fds, long_t nfds, int timeout) {
+  SCOPED_TSAN_INTERCEPTOR(poll, fds, nfds, timeout);
+  int res = BLOCK_REAL(poll)(fds, nfds, timeout);
+  return res;
+}
+
 static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
     my_siginfo_t *info, void *ctx) {
   ThreadState *thr = cur_thread();
@@ -1203,7 +1222,12 @@ static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
   // Don't mess with synchronous signals.
   if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
       sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE ||
-      (sctx && sig == sctx->int_signal_send)) {
+      // If we are sending signal to ourselves, we must process it now.
+      (sctx && sig == sctx->int_signal_send) ||
+      // If we are in blocking function, we can safely process it now
+      // (but check if we are in a recursive interceptor,
+      // i.e. pthread_join()->munmap()).
+      (sctx && sctx->in_blocking_func == 1 && thr->in_rtl == 1)) {
     CHECK(thr->in_rtl == 0 || thr->in_rtl == 1);
     int in_rtl = thr->in_rtl;
     thr->in_rtl = 0;
@@ -1317,7 +1341,15 @@ TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
   return res;
 }
 
-static void process_pending_signals(ThreadState *thr) {
+TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
+  SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
+  // It's intercepted merely to process pending signals.
+  return REAL(gettimeofday)(tv, tz);
+}
+
+namespace __tsan {
+
+void ProcessPendingSignals(ThreadState *thr) {
   CHECK_EQ(thr->in_rtl, 0);
   SignalContext *sctx = SigCtx(thr);
   if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler)
@@ -1342,7 +1374,7 @@ static void process_pending_signals(ThreadState *thr) {
           sigactions[sig].sa_sigaction(sig, &signal->siginfo, &signal->ctx);
         else
           sigactions[sig].sa_handler(sig);
-        if (errno != 0) {
+        if (flags()->report_bugs && errno != 0) {
           ScopedInRtl in_rtl;
           __tsan::StackTrace stack;
           uptr pc = signal->sigaction ?
@@ -1364,8 +1396,6 @@ static void process_pending_signals(ThreadState *thr) {
   thr->in_signal_handler = false;
 }
 
-namespace __tsan {
-
 void InitializeInterceptors() {
   CHECK_GT(cur_thread()->in_rtl, 0);
 
@@ -1482,6 +1512,7 @@ void InitializeInterceptors() {
 
   TSAN_INTERCEPT(epoll_ctl);
   TSAN_INTERCEPT(epoll_wait);
+  TSAN_INTERCEPT(poll);
 
   TSAN_INTERCEPT(sigaction);
   TSAN_INTERCEPT(signal);
@@ -1491,17 +1522,18 @@ void InitializeInterceptors() {
   TSAN_INTERCEPT(sleep);
   TSAN_INTERCEPT(usleep);
   TSAN_INTERCEPT(nanosleep);
+  TSAN_INTERCEPT(gettimeofday);
 
   atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
       AtExitContext();
 
   if (__cxa_atexit(&finalize, 0, 0)) {
-    TsanPrintf("ThreadSanitizer: failed to setup atexit callback\n");
+    Printf("ThreadSanitizer: failed to setup atexit callback\n");
     Die();
   }
 
   if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
-    TsanPrintf("ThreadSanitizer: failed to create thread key\n");
+    Printf("ThreadSanitizer: failed to create thread key\n");
     Die();
   }
 }
diff --git a/libsanitizer/tsan/tsan_interface.h b/libsanitizer/tsan/tsan_interface.h
index 72bb1e91c3da..dede9be5f06d 100644
--- a/libsanitizer/tsan/tsan_interface.h
+++ b/libsanitizer/tsan/tsan_interface.h
@@ -14,7 +14,6 @@
 #ifndef TSAN_INTERFACE_H
 #define TSAN_INTERFACE_H
 
-#include <sanitizer/common_interface_defs.h> 
 // This header should NOT include any other headers.
 // All functions in this header are extern "C" and start with __tsan_.
 
@@ -24,24 +23,24 @@ extern "C" {
 
 // This function should be called at the very beginning of the process,
 // before any instrumented code is executed and before any call to malloc.
-void __tsan_init() SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_init();
 
-void __tsan_read1(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read2(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read4(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read8(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read16(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_read1(void *addr);
+void __tsan_read2(void *addr);
+void __tsan_read4(void *addr);
+void __tsan_read8(void *addr);
+void __tsan_read16(void *addr);
 
-void __tsan_write1(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write2(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write4(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write8(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write16(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_write1(void *addr);
+void __tsan_write2(void *addr);
+void __tsan_write4(void *addr);
+void __tsan_write8(void *addr);
+void __tsan_write16(void *addr);
 
-void __tsan_vptr_update(void **vptr_p, void *new_val) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_vptr_update(void **vptr_p, void *new_val);
 
-void __tsan_func_entry(void *call_pc) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_func_exit() SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_func_entry(void *call_pc);
+void __tsan_func_exit();
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/libsanitizer/tsan/tsan_interface_ann.cc b/libsanitizer/tsan/tsan_interface_ann.cc
index fd5c1cc6cd43..b9e084b7327d 100644
--- a/libsanitizer/tsan/tsan_interface_ann.cc
+++ b/libsanitizer/tsan/tsan_interface_ann.cc
@@ -157,57 +157,47 @@ bool IsExpectedReport(uptr addr, uptr size) {
 using namespace __tsan;  // NOLINT
 
 extern "C" {
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateHappensBefore(char *f, int l, uptr addr) {
   SCOPED_ANNOTATION(AnnotateHappensBefore);
   Release(cur_thread(), CALLERPC, addr);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateHappensAfter(char *f, int l, uptr addr) {
   SCOPED_ANNOTATION(AnnotateHappensAfter);
   Acquire(cur_thread(), CALLERPC, addr);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateCondVarSignal(char *f, int l, uptr cv) {
   SCOPED_ANNOTATION(AnnotateCondVarSignal);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
   SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
   SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateCondVarWait(char *f, int l, uptr cv, uptr lock) {
   SCOPED_ANNOTATION(AnnotateCondVarWait);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateRWLockCreate(char *f, int l, uptr m) {
   SCOPED_ANNOTATION(AnnotateRWLockCreate);
   MutexCreate(thr, pc, m, true, true, false);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
   SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
   MutexCreate(thr, pc, m, true, true, true);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateRWLockDestroy(char *f, int l, uptr m) {
   SCOPED_ANNOTATION(AnnotateRWLockDestroy);
   MutexDestroy(thr, pc, m);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateRWLockAcquired(char *f, int l, uptr m, uptr is_w) {
   SCOPED_ANNOTATION(AnnotateRWLockAcquired);
   if (is_w)
@@ -216,7 +206,6 @@ void AnnotateRWLockAcquired(char *f, int l, uptr m, uptr is_w) {
     MutexReadLock(thr, pc, m);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateRWLockReleased(char *f, int l, uptr m, uptr is_w) {
   SCOPED_ANNOTATION(AnnotateRWLockReleased);
   if (is_w)
@@ -225,35 +214,30 @@ void AnnotateRWLockReleased(char *f, int l, uptr m, uptr is_w) {
     MutexReadUnlock(thr, pc, m);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateTraceMemory(char *f, int l, uptr mem) {
   SCOPED_ANNOTATION(AnnotateTraceMemory);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateFlushState(char *f, int l) {
   SCOPED_ANNOTATION(AnnotateFlushState);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateNewMemory(char *f, int l, uptr mem, uptr size) {
   SCOPED_ANNOTATION(AnnotateNewMemory);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateNoOp(char *f, int l, uptr mem) {
   SCOPED_ANNOTATION(AnnotateNoOp);
 }
 
 static void ReportMissedExpectedRace(ExpectRace *race) {
-  TsanPrintf("==================\n");
-  TsanPrintf("WARNING: ThreadSanitizer: missed expected data race\n");
-  TsanPrintf("  %s addr=%zx %s:%d\n",
+  Printf("==================\n");
+  Printf("WARNING: ThreadSanitizer: missed expected data race\n");
+  Printf("  %s addr=%zx %s:%d\n",
       race->desc, race->addr, race->file, race->line);
-  TsanPrintf("==================\n");
+  Printf("==================\n");
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateFlushExpectedRaces(char *f, int l) {
   SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
   Lock lock(&dyn_ann_ctx->mtx);
@@ -269,38 +253,31 @@ void AnnotateFlushExpectedRaces(char *f, int l) {
   }
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateEnableRaceDetection(char *f, int l, int enable) {
   SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
   // FIXME: Reconsider this functionality later. It may be irrelevant.
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateMutexIsUsedAsCondVar(char *f, int l, uptr mu) {
   SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotatePCQGet(char *f, int l, uptr pcq) {
   SCOPED_ANNOTATION(AnnotatePCQGet);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotatePCQPut(char *f, int l, uptr pcq) {
   SCOPED_ANNOTATION(AnnotatePCQPut);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotatePCQDestroy(char *f, int l, uptr pcq) {
   SCOPED_ANNOTATION(AnnotatePCQDestroy);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotatePCQCreate(char *f, int l, uptr pcq) {
   SCOPED_ANNOTATION(AnnotatePCQCreate);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
   SCOPED_ANNOTATION(AnnotateExpectRace);
   Lock lock(&dyn_ann_ctx->mtx);
@@ -317,73 +294,60 @@ static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
 }
 
 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
-// SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateBenignRaceSized(char *f, int l, uptr mem, uptr size, char *desc) {
   SCOPED_ANNOTATION(AnnotateBenignRaceSized);
   BenignRaceImpl(f, l, mem, size, desc);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateBenignRace(char *f, int l, uptr mem, char *desc) {
   SCOPED_ANNOTATION(AnnotateBenignRace);
   BenignRaceImpl(f, l, mem, 1, desc);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateIgnoreReadsBegin(char *f, int l) {
   SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
   IgnoreCtl(cur_thread(), false, true);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateIgnoreReadsEnd(char *f, int l) {
   SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
   IgnoreCtl(cur_thread(), false, false);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateIgnoreWritesBegin(char *f, int l) {
   SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
   IgnoreCtl(cur_thread(), true, true);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateIgnoreWritesEnd(char *f, int l) {
   SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
   IgnoreCtl(cur_thread(), true, false);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotatePublishMemoryRange(char *f, int l, uptr addr, uptr size) {
   SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateUnpublishMemoryRange(char *f, int l, uptr addr, uptr size) {
   SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void AnnotateThreadName(char *f, int l, char *name) {
   SCOPED_ANNOTATION(AnnotateThreadName);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
   SCOPED_ANNOTATION(AnnotateHappensBefore);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
   SCOPED_ANNOTATION(AnnotateHappensAfter);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void WTFAnnotateBenignRaceSized(char *f, int l, uptr mem, uptr sz, char *desc) {
   SCOPED_ANNOTATION(AnnotateBenignRaceSized);
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 int RunningOnValgrind() {
   return flags()->running_on_valgrind;
 }
@@ -392,7 +356,6 @@ double __attribute__((weak)) ValgrindSlowdown(void) {
   return 10.0;
 }
 
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 const char *ThreadSanitizerQuery(const char *query) {
   if (internal_strcmp(query, "pure_happens_before") == 0)
     return "1";
diff --git a/libsanitizer/tsan/tsan_interface_atomic.cc b/libsanitizer/tsan/tsan_interface_atomic.cc
index 7b459f15d466..037a080da67d 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.cc
+++ b/libsanitizer/tsan/tsan_interface_atomic.cc
@@ -37,12 +37,12 @@ typedef __tsan_atomic8 a8;
 typedef __tsan_atomic16 a16;
 typedef __tsan_atomic32 a32;
 typedef __tsan_atomic64 a64;
-const int mo_relaxed = __tsan_memory_order_relaxed;
-const int mo_consume = __tsan_memory_order_consume;
-const int mo_acquire = __tsan_memory_order_acquire;
-const int mo_release = __tsan_memory_order_release;
-const int mo_acq_rel = __tsan_memory_order_acq_rel;
-const int mo_seq_cst = __tsan_memory_order_seq_cst;
+const morder mo_relaxed = __tsan_memory_order_relaxed;
+const morder mo_consume = __tsan_memory_order_consume;
+const morder mo_acquire = __tsan_memory_order_acquire;
+const morder mo_release = __tsan_memory_order_release;
+const morder mo_acq_rel = __tsan_memory_order_acq_rel;
+const morder mo_seq_cst = __tsan_memory_order_seq_cst;
 
 static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) {
   StatInc(thr, StatAtomic);
@@ -77,10 +77,32 @@ static bool IsAcquireOrder(morder mo) {
       || mo == mo_acq_rel || mo == mo_seq_cst;
 }
 
+static morder ConvertOrder(morder mo) {
+  if (mo > (morder)100500) {
+    mo = morder(mo - 100500);
+    if (mo ==  morder(1 << 0))
+      mo = mo_relaxed;
+    else if (mo == morder(1 << 1))
+      mo = mo_consume;
+    else if (mo == morder(1 << 2))
+      mo = mo_acquire;
+    else if (mo == morder(1 << 3))
+      mo = mo_release;
+    else if (mo == morder(1 << 4))
+      mo = mo_acq_rel;
+    else if (mo == morder(1 << 5))
+      mo = mo_seq_cst;
+  }
+  CHECK_GE(mo, mo_relaxed);
+  CHECK_LE(mo, mo_seq_cst);
+  return mo;
+}
+
 #define SCOPED_ATOMIC(func, ...) \
-    if ((u32)mo > 100500) mo = (morder)((u32)mo - 100500); \
+    mo = ConvertOrder(mo); \
     mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
     ThreadState *const thr = cur_thread(); \
+    ProcessPendingSignals(thr); \
     const uptr pc = (uptr)__builtin_return_address(0); \
     AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
     ScopedAtomic sa(thr, pc, __FUNCTION__); \
@@ -187,6 +209,13 @@ static bool AtomicCAS(ThreadState *thr, uptr pc,
   return false;
 }
 
+template<typename T>
+static T AtomicCAS(ThreadState *thr, uptr pc,
+    volatile T *a, T c, T v, morder mo) {
+  AtomicCAS(thr, pc, a, &c, v, mo);
+  return c;
+}
+
 static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {
   __sync_synchronize();
 }
@@ -359,6 +388,25 @@ int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
   SCOPED_ATOMIC(CAS, a, c, v, mo);
 }
 
+a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
+    morder mo) {
+  SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
+    morder mo) {
+  SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+
+a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
+    morder mo) {
+  SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+
+a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
+    morder mo) {
+  SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+
 void __tsan_atomic_thread_fence(morder mo) {
   char* a;
   SCOPED_ATOMIC(Fence, mo);
diff --git a/libsanitizer/tsan/tsan_interface_atomic.h b/libsanitizer/tsan/tsan_interface_atomic.h
index 37532ce41856..fea97b69debf 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.h
+++ b/libsanitizer/tsan/tsan_interface_atomic.h
@@ -23,148 +23,119 @@ typedef long  __tsan_atomic64;  // NOLINT
 // Part of ABI, do not change.
 // http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/atomic?view=markup
 typedef enum {
-  __tsan_memory_order_relaxed = 1 << 0,
-  __tsan_memory_order_consume = 1 << 1,
-  __tsan_memory_order_acquire = 1 << 2,
-  __tsan_memory_order_release = 1 << 3,
-  __tsan_memory_order_acq_rel = 1 << 4,
-  __tsan_memory_order_seq_cst = 1 << 5
+  __tsan_memory_order_relaxed,
+  __tsan_memory_order_consume,
+  __tsan_memory_order_acquire,
+  __tsan_memory_order_release,
+  __tsan_memory_order_acq_rel,
+  __tsan_memory_order_seq_cst
 } __tsan_memory_order;
 
 __tsan_atomic8 __tsan_atomic8_load(const volatile __tsan_atomic8 *a,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 __tsan_atomic16 __tsan_atomic16_load(const volatile __tsan_atomic16 *a,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 __tsan_atomic32 __tsan_atomic32_load(const volatile __tsan_atomic32 *a,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 __tsan_atomic64 __tsan_atomic64_load(const volatile __tsan_atomic64 *a,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 
 void __tsan_atomic8_store(volatile __tsan_atomic8 *a, __tsan_atomic8 v,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 void __tsan_atomic16_store(volatile __tsan_atomic16 *a, __tsan_atomic16 v,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 void __tsan_atomic32_store(volatile __tsan_atomic32 *a, __tsan_atomic32 v,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 void __tsan_atomic64_store(volatile __tsan_atomic64 *a, __tsan_atomic64 v,
-    __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_memory_order mo);
 
 __tsan_atomic8 __tsan_atomic8_exchange(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 v, __tsan_memory_order mo);
 __tsan_atomic16 __tsan_atomic16_exchange(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 v, __tsan_memory_order mo);
 __tsan_atomic32 __tsan_atomic32_exchange(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a, 
-    __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 v, __tsan_memory_order mo);
 
 __tsan_atomic8 __tsan_atomic8_fetch_add(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 v, __tsan_memory_order mo);
 __tsan_atomic16 __tsan_atomic16_fetch_add(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 v, __tsan_memory_order mo);
 __tsan_atomic32 __tsan_atomic32_fetch_add(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 v, __tsan_memory_order mo);
 __tsan_atomic64 __tsan_atomic64_fetch_add(volatile __tsan_atomic64 *a,
-    __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic64 v, __tsan_memory_order mo);
 
 __tsan_atomic8 __tsan_atomic8_fetch_sub(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 v, __tsan_memory_order mo);
 __tsan_atomic16 __tsan_atomic16_fetch_sub(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 v, __tsan_memory_order mo);
 __tsan_atomic32 __tsan_atomic32_fetch_sub(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 v, __tsan_memory_order mo);
 __tsan_atomic64 __tsan_atomic64_fetch_sub(volatile __tsan_atomic64 *a,
-    __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic64 v, __tsan_memory_order mo);
 
 __tsan_atomic8 __tsan_atomic8_fetch_and(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 v, __tsan_memory_order mo);
 __tsan_atomic16 __tsan_atomic16_fetch_and(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 v, __tsan_memory_order mo);
 __tsan_atomic32 __tsan_atomic32_fetch_and(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 v, __tsan_memory_order mo);
 __tsan_atomic64 __tsan_atomic64_fetch_and(volatile __tsan_atomic64 *a,
-    __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic64 v, __tsan_memory_order mo);
 
 __tsan_atomic8 __tsan_atomic8_fetch_or(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 v, __tsan_memory_order mo);
 __tsan_atomic16 __tsan_atomic16_fetch_or(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 v, __tsan_memory_order mo);
 __tsan_atomic32 __tsan_atomic32_fetch_or(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 v, __tsan_memory_order mo);
 __tsan_atomic64 __tsan_atomic64_fetch_or(volatile __tsan_atomic64 *a,
-    __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic64 v, __tsan_memory_order mo);
 
 __tsan_atomic8 __tsan_atomic8_fetch_xor(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 v, __tsan_memory_order mo);
 __tsan_atomic16 __tsan_atomic16_fetch_xor(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 v, __tsan_memory_order mo);
 __tsan_atomic32 __tsan_atomic32_fetch_xor(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 v, __tsan_memory_order mo);
 __tsan_atomic64 __tsan_atomic64_fetch_xor(volatile __tsan_atomic64 *a,
-    __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic64 v, __tsan_memory_order mo);
 
 int __tsan_atomic8_compare_exchange_weak(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo);
 int __tsan_atomic16_compare_exchange_weak(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo);
 int __tsan_atomic32_compare_exchange_weak(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo);
 int __tsan_atomic64_compare_exchange_weak(volatile __tsan_atomic64 *a,
-    __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo);
 
 int __tsan_atomic8_compare_exchange_strong(volatile __tsan_atomic8 *a,
-    __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo);
 int __tsan_atomic16_compare_exchange_strong(volatile __tsan_atomic16 *a,
-    __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo);
 int __tsan_atomic32_compare_exchange_strong(volatile __tsan_atomic32 *a,
-    __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo);
 int __tsan_atomic64_compare_exchange_strong(volatile __tsan_atomic64 *a,
-    __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-
-void __tsan_atomic_thread_fence(__tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_atomic_signal_fence(__tsan_memory_order mo)
-    SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+    __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_compare_exchange_val(
+    volatile __tsan_atomic8 *a, __tsan_atomic8 c, __tsan_atomic8 v,
+    __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_compare_exchange_val(
+    volatile __tsan_atomic16 *a, __tsan_atomic16 c, __tsan_atomic16 v,
+    __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_compare_exchange_val(
+    volatile __tsan_atomic32 *a, __tsan_atomic32 c, __tsan_atomic32 v,
+    __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_compare_exchange_val(
+    volatile __tsan_atomic64 *a, __tsan_atomic64 c, __tsan_atomic64 v,
+    __tsan_memory_order mo);
+
+void __tsan_atomic_thread_fence(__tsan_memory_order mo);
+void __tsan_atomic_signal_fence(__tsan_memory_order mo);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/libsanitizer/tsan/tsan_mutex.cc b/libsanitizer/tsan/tsan_mutex.cc
index 83af02992b49..6a1e0cec53ad 100644
--- a/libsanitizer/tsan/tsan_mutex.cc
+++ b/libsanitizer/tsan/tsan_mutex.cc
@@ -90,25 +90,25 @@ void InitializeMutex() {
     }
   }
 #if 0
-  TsanPrintf("Can lock graph:\n");
+  Printf("Can lock graph:\n");
   for (int i = 0; i < N; i++) {
     for (int j = 0; j < N; j++) {
-      TsanPrintf("%d ", CanLockAdj[i][j]);
+      Printf("%d ", CanLockAdj[i][j]);
     }
-    TsanPrintf("\n");
+    Printf("\n");
   }
-  TsanPrintf("Can lock graph closure:\n");
+  Printf("Can lock graph closure:\n");
   for (int i = 0; i < N; i++) {
     for (int j = 0; j < N; j++) {
-      TsanPrintf("%d ", CanLockAdj2[i][j]);
+      Printf("%d ", CanLockAdj2[i][j]);
     }
-    TsanPrintf("\n");
+    Printf("\n");
   }
 #endif
   // Verify that the graph is acyclic.
   for (int i = 0; i < N; i++) {
     if (CanLockAdj2[i][i]) {
-      TsanPrintf("Mutex %d participates in a cycle\n", i);
+      Printf("Mutex %d participates in a cycle\n", i);
       Die();
     }
   }
@@ -119,7 +119,7 @@ DeadlockDetector::DeadlockDetector() {
 }
 
 void DeadlockDetector::Lock(MutexType t) {
-  // TsanPrintf("LOCK %d @%zu\n", t, seq_ + 1);
+  // Printf("LOCK %d @%zu\n", t, seq_ + 1);
   u64 max_seq = 0;
   u64 max_idx = MutexTypeInvalid;
   for (int i = 0; i != MutexTypeCount; i++) {
@@ -134,17 +134,17 @@ void DeadlockDetector::Lock(MutexType t) {
   locked_[t] = ++seq_;
   if (max_idx == MutexTypeInvalid)
     return;
-  // TsanPrintf("  last %d @%zu\n", max_idx, max_seq);
+  // Printf("  last %d @%zu\n", max_idx, max_seq);
   if (!CanLockAdj[max_idx][t]) {
-    TsanPrintf("ThreadSanitizer: internal deadlock detected\n");
-    TsanPrintf("ThreadSanitizer: can't lock %d while under %zu\n",
+    Printf("ThreadSanitizer: internal deadlock detected\n");
+    Printf("ThreadSanitizer: can't lock %d while under %zu\n",
                t, (uptr)max_idx);
     CHECK(0);
   }
 }
 
 void DeadlockDetector::Unlock(MutexType t) {
-  // TsanPrintf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
+  // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
   CHECK(locked_[t]);
   locked_[t] = 0;
 }
diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h
index d7a4cf7b0e93..f849182503c9 100644
--- a/libsanitizer/tsan/tsan_platform.h
+++ b/libsanitizer/tsan/tsan_platform.h
@@ -15,13 +15,17 @@
 
 #include "tsan_rtl.h"
 
-#if __LP64__
+#if defined(__LP64__) || defined(_WIN64)
 namespace __tsan {
 
 #if defined(TSAN_GO)
 static const uptr kLinuxAppMemBeg = 0x000000000000ULL;
 static const uptr kLinuxAppMemEnd = 0x00fcffffffffULL;
+# if defined(_WIN32)
+static const uptr kLinuxShadowMsk = 0x010000000000ULL;
+# else
 static const uptr kLinuxShadowMsk = 0x100000000000ULL;
+# endif
 // TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout,
 // when memory addresses are of the 0x2axxxxxxxxxx form.
 // The option is enabled with 'setarch x86_64 -L'.
@@ -93,7 +97,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
 
 }  // namespace __tsan
 
-#else  // __LP64__
+#else  // defined(__LP64__) || defined(_WIN64)
 # error "Only 64-bit is supported"
 #endif
 
diff --git a/libsanitizer/tsan/tsan_platform_linux.cc b/libsanitizer/tsan/tsan_platform_linux.cc
index d7de503c51d2..b26065543fe5 100644
--- a/libsanitizer/tsan/tsan_platform_linux.cc
+++ b/libsanitizer/tsan/tsan_platform_linux.cc
@@ -81,46 +81,42 @@ static void ProtectRange(uptr beg, uptr end) {
   if (beg == end)
     return;
   if (beg != (uptr)Mprotect(beg, end - beg)) {
-    TsanPrintf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
-    TsanPrintf("FATAL: Make sure you are not using unlimited stack\n");
+    Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
+    Printf("FATAL: Make sure you are not using unlimited stack\n");
     Die();
   }
 }
 #endif
 
+#ifndef TSAN_GO
 void InitializeShadowMemory() {
   uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg,
     kLinuxShadowEnd - kLinuxShadowBeg);
   if (shadow != kLinuxShadowBeg) {
-    TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
-    TsanPrintf("FATAL: Make sure to compile with -fPIE and "
+    Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
+    Printf("FATAL: Make sure to compile with -fPIE and "
                "to link with -pie (%p, %p).\n", shadow, kLinuxShadowBeg);
     Die();
   }
-#ifndef TSAN_GO
   const uptr kClosedLowBeg  = 0x200000;
   const uptr kClosedLowEnd  = kLinuxShadowBeg - 1;
   const uptr kClosedMidBeg = kLinuxShadowEnd + 1;
   const uptr kClosedMidEnd = kLinuxAppMemBeg - 1;
   ProtectRange(kClosedLowBeg, kClosedLowEnd);
   ProtectRange(kClosedMidBeg, kClosedMidEnd);
-#endif
-#ifndef TSAN_GO
   DPrintf("kClosedLow   %zx-%zx (%zuGB)\n",
       kClosedLowBeg, kClosedLowEnd, (kClosedLowEnd - kClosedLowBeg) >> 30);
-#endif
   DPrintf("kLinuxShadow %zx-%zx (%zuGB)\n",
       kLinuxShadowBeg, kLinuxShadowEnd,
       (kLinuxShadowEnd - kLinuxShadowBeg) >> 30);
-#ifndef TSAN_GO
   DPrintf("kClosedMid   %zx-%zx (%zuGB)\n",
       kClosedMidBeg, kClosedMidEnd, (kClosedMidEnd - kClosedMidBeg) >> 30);
-#endif
   DPrintf("kLinuxAppMem %zx-%zx (%zuGB)\n",
       kLinuxAppMemBeg, kLinuxAppMemEnd,
       (kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
   DPrintf("stack        %zx\n", (uptr)&shadow);
 }
+#endif
 
 static uptr g_data_start;
 static uptr g_data_end;
@@ -133,10 +129,10 @@ static void CheckPIE() {
   if (proc_maps.Next(&start, &end,
                      /*offset*/0, /*filename*/0, /*filename_size*/0)) {
     if ((u64)start < kLinuxAppMemBeg) {
-      TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory ("
+      Printf("FATAL: ThreadSanitizer can not mmap the shadow memory ("
              "something is mapped at 0x%zx < 0x%zx)\n",
              start, kLinuxAppMemBeg);
-      TsanPrintf("FATAL: Make sure to compile with -fPIE"
+      Printf("FATAL: Make sure to compile with -fPIE"
              " and to link with -pie.\n");
       Die();
     }
@@ -221,7 +217,7 @@ const char *InitializePlatform() {
   g_tls_size = (uptr)InitTlsSize();
   InitDataSeg();
 #endif
-  return getenv("TSAN_OPTIONS");
+  return getenv(kTsanOptionsEnv);
 }
 
 void FinalizePlatform() {
diff --git a/libsanitizer/tsan/tsan_platform_mac.cc b/libsanitizer/tsan/tsan_platform_mac.cc
index e22a500cf15b..808d99c0207f 100644
--- a/libsanitizer/tsan/tsan_platform_mac.cc
+++ b/libsanitizer/tsan/tsan_platform_mac.cc
@@ -50,13 +50,14 @@ uptr GetShadowMemoryConsumption() {
 void FlushShadowMemory() {
 }
 
+#ifndef TSAN_GO
 void InitializeShadowMemory() {
   uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg,
     kLinuxShadowEnd - kLinuxShadowBeg);
   if (shadow != kLinuxShadowBeg) {
-    TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
-    TsanPrintf("FATAL: Make sure to compile with -fPIE and "
-               "to link with -pie.\n");
+    Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
+    Printf("FATAL: Make sure to compile with -fPIE and "
+           "to link with -pie.\n");
     Die();
   }
   DPrintf("kLinuxShadow %zx-%zx (%zuGB)\n",
@@ -66,6 +67,7 @@ void InitializeShadowMemory() {
       kLinuxAppMemBeg, kLinuxAppMemEnd,
       (kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
 }
+#endif
 
 const char *InitializePlatform() {
   void *p = 0;
@@ -78,7 +80,7 @@ const char *InitializePlatform() {
     setrlimit(RLIMIT_CORE, (rlimit*)&lim);
   }
 
-  return getenv("TSAN_OPTIONS");
+  return getenv(kTsanOptionsEnv);
 }
 
 void FinalizePlatform() {
diff --git a/libsanitizer/tsan/tsan_platform_windows.cc b/libsanitizer/tsan/tsan_platform_windows.cc
new file mode 100644
index 000000000000..74b9020d0774
--- /dev/null
+++ b/libsanitizer/tsan/tsan_platform_windows.cc
@@ -0,0 +1,56 @@
+//===-- tsan_platform_windows.cc ------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Windows-specific code.
+//===----------------------------------------------------------------------===//
+
+#ifdef _WIN32
+
+#include "tsan_platform.h"
+
+#include <stdlib.h>
+
+namespace __tsan {
+
+ScopedInRtl::ScopedInRtl() {
+}
+
+ScopedInRtl::~ScopedInRtl() {
+}
+
+uptr GetShadowMemoryConsumption() {
+  return 0;
+}
+
+void FlushShadowMemory() {
+}
+
+const char *InitializePlatform() {
+  return getenv(kTsanOptionsEnv);
+}
+
+void FinalizePlatform() {
+  fflush(0);
+}
+
+uptr GetTlsSize() {
+  return 0;
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+                          uptr *tls_addr, uptr *tls_size) {
+  *stk_addr = 0;
+  *stk_size = 0;
+  *tls_addr = 0;
+  *tls_size = 0;
+}
+
+}  // namespace __tsan
+
+#endif  // #ifdef _WIN32
diff --git a/libsanitizer/tsan/tsan_printf.cc b/libsanitizer/tsan/tsan_printf.cc
deleted file mode 100644
index 982e2925dc3d..000000000000
--- a/libsanitizer/tsan/tsan_printf.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-//===-- tsan_printf.cc ----------------------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_libc.h"
-#include "tsan_defs.h"
-#include "tsan_mman.h"
-#include "tsan_platform.h"
-
-#include <stdarg.h>  // va_list
-
-namespace __sanitizer {
-int VSNPrintf(char *buff, int buff_length, const char *format, va_list args);
-}  // namespace __sanitizer
-
-namespace __tsan {
-
-void TsanPrintf(const char *format, ...) {
-  ScopedInRtl in_rtl;
-  const uptr kMaxLen = 16 * 1024;
-  InternalScopedBuffer<char> buffer(kMaxLen);
-  va_list args;
-  va_start(args, format);
-  uptr len = VSNPrintf(buffer.data(), buffer.size(), format, args);
-  va_end(args);
-  internal_write(CTX() ? flags()->log_fileno : 2,
-      buffer.data(), len < buffer.size() ? len : buffer.size() - 1);
-}
-
-}  // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_report.cc b/libsanitizer/tsan/tsan_report.cc
index 716a20f1213f..62e0b0c33142 100644
--- a/libsanitizer/tsan/tsan_report.cc
+++ b/libsanitizer/tsan/tsan_report.cc
@@ -29,98 +29,102 @@ ReportDesc::~ReportDesc() {
 #ifndef TSAN_GO
 
 static void PrintHeader(ReportType typ) {
-  TsanPrintf("WARNING: ThreadSanitizer: ");
+  Printf("WARNING: ThreadSanitizer: ");
 
   if (typ == ReportTypeRace)
-    TsanPrintf("data race");
+    Printf("data race");
   else if (typ == ReportTypeUseAfterFree)
-    TsanPrintf("heap-use-after-free");
+    Printf("heap-use-after-free");
   else if (typ == ReportTypeThreadLeak)
-    TsanPrintf("thread leak");
+    Printf("thread leak");
   else if (typ == ReportTypeMutexDestroyLocked)
-    TsanPrintf("destroy of a locked mutex");
+    Printf("destroy of a locked mutex");
   else if (typ == ReportTypeSignalUnsafe)
-    TsanPrintf("signal-unsafe call inside of a signal");
+    Printf("signal-unsafe call inside of a signal");
   else if (typ == ReportTypeErrnoInSignal)
-    TsanPrintf("signal handler spoils errno");
+    Printf("signal handler spoils errno");
 
-  TsanPrintf(" (pid=%d)\n", GetPid());
+  Printf(" (pid=%d)\n", GetPid());
 }
 
 void PrintStack(const ReportStack *ent) {
+  if (ent == 0) {
+    Printf("    [failed to restore the stack]\n\n");
+    return;
+  }
   for (int i = 0; ent; ent = ent->next, i++) {
-    TsanPrintf("    #%d %s %s:%d", i, ent->func, ent->file, ent->line);
+    Printf("    #%d %s %s:%d", i, ent->func, ent->file, ent->line);
     if (ent->col)
-      TsanPrintf(":%d", ent->col);
+      Printf(":%d", ent->col);
     if (ent->module && ent->offset)
-      TsanPrintf(" (%s+%p)\n", ent->module, (void*)ent->offset);
+      Printf(" (%s+%p)\n", ent->module, (void*)ent->offset);
     else
-      TsanPrintf(" (%p)\n", (void*)ent->pc);
+      Printf(" (%p)\n", (void*)ent->pc);
   }
-  TsanPrintf("\n");
+  Printf("\n");
 }
 
 static void PrintMop(const ReportMop *mop, bool first) {
-  TsanPrintf("  %s of size %d at %p",
+  Printf("  %s of size %d at %p",
       (first ? (mop->write ? "Write" : "Read")
              : (mop->write ? "Previous write" : "Previous read")),
       mop->size, (void*)mop->addr);
   if (mop->tid == 0)
-    TsanPrintf(" by main thread:\n");
+    Printf(" by main thread:\n");
   else
-    TsanPrintf(" by thread %d:\n", mop->tid);
+    Printf(" by thread %d:\n", mop->tid);
   PrintStack(mop->stack);
 }
 
 static void PrintLocation(const ReportLocation *loc) {
   if (loc->type == ReportLocationGlobal) {
-    TsanPrintf("  Location is global '%s' of size %zu at %zx %s:%d\n",
+    Printf("  Location is global '%s' of size %zu at %zx %s:%d\n",
                loc->name, loc->size, loc->addr, loc->file, loc->line);
   } else if (loc->type == ReportLocationHeap) {
-    TsanPrintf("  Location is heap block of size %zu at %p allocated",
+    Printf("  Location is heap block of size %zu at %p allocated",
         loc->size, loc->addr);
     if (loc->tid == 0)
-      TsanPrintf(" by main thread:\n");
+      Printf(" by main thread:\n");
     else
-      TsanPrintf(" by thread %d:\n", loc->tid);
+      Printf(" by thread %d:\n", loc->tid);
     PrintStack(loc->stack);
   } else if (loc->type == ReportLocationStack) {
-    TsanPrintf("  Location is stack of thread %d:\n", loc->tid);
+    Printf("  Location is stack of thread %d:\n", loc->tid);
   }
 }
 
 static void PrintMutex(const ReportMutex *rm) {
   if (rm->stack == 0)
     return;
-  TsanPrintf("  Mutex %d created at:\n", rm->id);
+  Printf("  Mutex %d created at:\n", rm->id);
   PrintStack(rm->stack);
 }
 
 static void PrintThread(const ReportThread *rt) {
   if (rt->id == 0)  // Little sense in describing the main thread.
     return;
-  TsanPrintf("  Thread %d", rt->id);
+  Printf("  Thread %d", rt->id);
   if (rt->name)
-    TsanPrintf(" '%s'", rt->name);
-  TsanPrintf(" (tid=%zu, %s)", rt->pid, rt->running ? "running" : "finished");
+    Printf(" '%s'", rt->name);
+  Printf(" (tid=%zu, %s)", rt->pid, rt->running ? "running" : "finished");
   if (rt->stack)
-    TsanPrintf(" created at:");
-  TsanPrintf("\n");
+    Printf(" created at:");
+  Printf("\n");
   PrintStack(rt->stack);
 }
 
 static void PrintSleep(const ReportStack *s) {
-  TsanPrintf("  As if synchronized via sleep:\n");
+  Printf("  As if synchronized via sleep:\n");
   PrintStack(s);
 }
 
 void PrintReport(const ReportDesc *rep) {
-  TsanPrintf("==================\n");
+  Printf("==================\n");
   PrintHeader(rep->typ);
 
   for (uptr i = 0; i < rep->stacks.Size(); i++) {
     if (i)
-      TsanPrintf("  and:\n");
+      Printf("  and:\n");
     PrintStack(rep->stacks[i]);
   }
 
@@ -139,21 +143,21 @@ void PrintReport(const ReportDesc *rep) {
   for (uptr i = 0; i < rep->threads.Size(); i++)
     PrintThread(rep->threads[i]);
 
-  TsanPrintf("==================\n");
+  Printf("==================\n");
 }
 
 #else
 
 void PrintStack(const ReportStack *ent) {
   for (int i = 0; ent; ent = ent->next, i++) {
-    TsanPrintf("  %s()\n      %s:%d +0x%zx\n",
+    Printf("  %s()\n      %s:%d +0x%zx\n",
         ent->func, ent->file, ent->line, (void*)ent->offset);
   }
-  TsanPrintf("\n");
+  Printf("\n");
 }
 
 static void PrintMop(const ReportMop *mop, bool first) {
-  TsanPrintf("%s by goroutine %d:\n",
+  Printf("%s by goroutine %d:\n",
       (first ? (mop->write ? "Write" : "Read")
              : (mop->write ? "Previous write" : "Previous read")),
       mop->tid);
@@ -163,19 +167,19 @@ static void PrintMop(const ReportMop *mop, bool first) {
 static void PrintThread(const ReportThread *rt) {
   if (rt->id == 0)  // Little sense in describing the main thread.
     return;
-  TsanPrintf("Goroutine %d (%s) created at:\n",
+  Printf("Goroutine %d (%s) created at:\n",
     rt->id, rt->running ? "running" : "finished");
   PrintStack(rt->stack);
 }
 
 void PrintReport(const ReportDesc *rep) {
-  TsanPrintf("==================\n");
-  TsanPrintf("WARNING: DATA RACE\n");
+  Printf("==================\n");
+  Printf("WARNING: DATA RACE\n");
   for (uptr i = 0; i < rep->mops.Size(); i++)
     PrintMop(rep->mops[i], i == 0);
   for (uptr i = 0; i < rep->threads.Size(); i++)
     PrintThread(rep->threads[i]);
-  TsanPrintf("==================\n");
+  Printf("==================\n");
 }
 
 #endif
diff --git a/libsanitizer/tsan/tsan_rtl.cc b/libsanitizer/tsan/tsan_rtl.cc
index 4ff26973ce3e..a3e82710d901 100644
--- a/libsanitizer/tsan/tsan_rtl.cc
+++ b/libsanitizer/tsan/tsan_rtl.cc
@@ -137,7 +137,7 @@ static void InitializeMemoryProfile() {
       flags()->profile_memory, GetPid());
   fd_t fd = internal_open(filename.data(), true);
   if (fd == kInvalidFd) {
-    TsanPrintf("Failed to open memory profile file '%s'\n", &filename[0]);
+    Printf("Failed to open memory profile file '%s'\n", &filename[0]);
     Die();
   }
   internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);
@@ -159,6 +159,10 @@ static void InitializeMemoryFlush() {
   internal_start_thread(&MemoryFlushThread, 0);
 }
 
+void MapShadow(uptr addr, uptr size) {
+  MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
+}
+
 void Initialize(ThreadState *thr) {
   // Thread safe because done before all threads exist.
   static bool is_initialized = false;
@@ -177,24 +181,32 @@ void Initialize(ThreadState *thr) {
   InitializeMutex();
   InitializeDynamicAnnotations();
   ctx = new(ctx_placeholder) Context;
+#ifndef TSAN_GO
   InitializeShadowMemory();
+#endif
   ctx->dead_list_size = 0;
   ctx->dead_list_head = 0;
   ctx->dead_list_tail = 0;
   InitializeFlags(&ctx->flags, env);
+  // Setup correct file descriptor for error reports.
+  __sanitizer_set_report_fd(flags()->log_fileno);
   InitializeSuppressions();
 #ifndef TSAN_GO
   // Initialize external symbolizer before internal threads are started.
   const char *external_symbolizer = flags()->external_symbolizer_path;
   if (external_symbolizer != 0 && external_symbolizer[0] != '\0') {
-    InitializeExternalSymbolizer(external_symbolizer);
+    if (!InitializeExternalSymbolizer(external_symbolizer)) {
+      Printf("Failed to start external symbolizer: '%s'\n",
+             external_symbolizer);
+      Die();
+    }
   }
 #endif
   InitializeMemoryProfile();
   InitializeMemoryFlush();
 
   if (ctx->flags.verbosity)
-    TsanPrintf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
+    Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
                GetPid());
 
   // Initialize thread 0.
@@ -206,7 +218,7 @@ void Initialize(ThreadState *thr) {
   ctx->initialized = true;
 
   if (flags()->stop_on_start) {
-    TsanPrintf("ThreadSanitizer is suspended at startup (pid %d)."
+    Printf("ThreadSanitizer is suspended at startup (pid %d)."
            " Call __tsan_resume().\n",
            GetPid());
     while (__tsan_resumed == 0);
@@ -218,6 +230,9 @@ int Finalize(ThreadState *thr) {
   Context *ctx = __tsan::ctx;
   bool failed = false;
 
+  if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
+    SleepForMillis(flags()->atexit_sleep_ms);
+
   // Wait for pending reports.
   ctx->report_mtx.Lock();
   ctx->report_mtx.Unlock();
@@ -226,15 +241,20 @@ int Finalize(ThreadState *thr) {
 
   if (ctx->nreported) {
     failed = true;
-    TsanPrintf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
+#ifndef TSAN_GO
+    Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
+#else
+    Printf("Found %d data race(s)\n", ctx->nreported);
+#endif
   }
 
   if (ctx->nmissed_expected) {
     failed = true;
-    TsanPrintf("ThreadSanitizer: missed %d expected races\n",
+    Printf("ThreadSanitizer: missed %d expected races\n",
         ctx->nmissed_expected);
   }
 
+  StatAggregate(ctx->stat, thr->stat);
   StatOutput(ctx->stat);
   return failed ? flags()->exitcode : 0;
 }
@@ -298,18 +318,22 @@ static inline void HandleRace(ThreadState *thr, u64 *shadow_mem,
   thr->racy_state[0] = cur.raw();
   thr->racy_state[1] = old.raw();
   thr->racy_shadow_addr = shadow_mem;
+#ifndef TSAN_GO
+  HACKY_CALL(__tsan_report_race);
+#else
   ReportRace(thr);
+#endif
 }
 
 static inline bool BothReads(Shadow s, int kAccessIsWrite) {
   return !kAccessIsWrite && !s.is_write();
 }
 
-static inline bool OldIsRWStronger(Shadow old, int kAccessIsWrite) {
+static inline bool OldIsRWNotWeaker(Shadow old, int kAccessIsWrite) {
   return old.is_write() || !kAccessIsWrite;
 }
 
-static inline bool OldIsRWWeaker(Shadow old, int kAccessIsWrite) {
+static inline bool OldIsRWWeakerOrEqual(Shadow old, int kAccessIsWrite) {
   return !old.is_write() || kAccessIsWrite;
 }
 
@@ -323,7 +347,7 @@ static inline bool HappensBefore(Shadow old, ThreadState *thr) {
 
 ALWAYS_INLINE
 void MemoryAccessImpl(ThreadState *thr, uptr addr,
-    int kAccessSizeLog, bool kAccessIsWrite, FastState fast_state,
+    int kAccessSizeLog, bool kAccessIsWrite,
     u64 *shadow_mem, Shadow cur) {
   StatInc(thr, StatMop);
   StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
@@ -407,11 +431,11 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
       (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
 #if TSAN_DEBUG
   if (!IsAppMem(addr)) {
-    TsanPrintf("Access to non app mem %zx\n", addr);
+    Printf("Access to non app mem %zx\n", addr);
     DCHECK(IsAppMem(addr));
   }
   if (!IsShadowMem((uptr)shadow_mem)) {
-    TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
+    Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
     DCHECK(IsShadowMem((uptr)shadow_mem));
   }
 #endif
@@ -429,7 +453,7 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
   // That is, this call must be moved somewhere below.
   TraceAddEvent(thr, fast_state.epoch(), EventTypeMop, pc);
 
-  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, fast_state,
+  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite,
       shadow_mem, cur);
 }
 
@@ -491,6 +515,7 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
   MemoryRangeSet(thr, pc, addr, size, s.raw());
 }
 
+ALWAYS_INLINE
 void FuncEntry(ThreadState *thr, uptr pc) {
   DCHECK_EQ(thr->in_rtl, 0);
   StatInc(thr, StatFuncEnter);
@@ -520,6 +545,7 @@ void FuncEntry(ThreadState *thr, uptr pc) {
   thr->shadow_stack_pos++;
 }
 
+ALWAYS_INLINE
 void FuncExit(ThreadState *thr) {
   DCHECK_EQ(thr->in_rtl, 0);
   StatInc(thr, StatFuncExit);
diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h
index 3df229c88441..de357a5d5a0e 100644
--- a/libsanitizer/tsan/tsan_rtl.h
+++ b/libsanitizer/tsan/tsan_rtl.h
@@ -25,11 +25,7 @@
 #define TSAN_RTL_H
 
 #include "sanitizer_common/sanitizer_common.h"
-#if __WORDSIZE == 64
 #include "sanitizer_common/sanitizer_allocator64.h"
-#else
-#include "sanitizer_common/sanitizer_allocator.h"
-#endif
 #include "tsan_clock.h"
 #include "tsan_defs.h"
 #include "tsan_flags.h"
@@ -69,7 +65,6 @@ Allocator *allocator();
 
 void TsanCheckFailed(const char *file, int line, const char *cond,
                      u64 v1, u64 v2);
-void TsanPrintf(const char *format, ...);
 
 // FastState (from most significant bit):
 //   unused          : 1
@@ -234,10 +229,6 @@ class Shadow : public FastState {
   }
 };
 
-// Freed memory.
-// As if 8-byte write by thread 0xff..f at epoch 0xff..f, races with everything.
-const u64 kShadowFreed = 0xfffffffffffffff8ull;
-
 struct SignalContext;
 
 // This struct is stored in TLS.
@@ -442,6 +433,7 @@ void ALWAYS_INLINE INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) {
     thr->stat[typ] += n;
 }
 
+void MapShadow(uptr addr, uptr size);
 void InitializeShadowMemory();
 void InitializeInterceptors();
 void InitializeDynamicAnnotations();
@@ -456,13 +448,13 @@ bool IsFiredSuppression(Context *ctx,
 bool IsExpectedReport(uptr addr, uptr size);
 
 #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
-# define DPrintf TsanPrintf
+# define DPrintf Printf
 #else
 # define DPrintf(...)
 #endif
 
 #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 2
-# define DPrintf2 TsanPrintf
+# define DPrintf2 Printf
 #else
 # define DPrintf2(...)
 #endif
@@ -476,7 +468,7 @@ int Finalize(ThreadState *thr);
 void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
     int kAccessSizeLog, bool kAccessIsWrite);
 void MemoryAccessImpl(ThreadState *thr, uptr addr,
-    int kAccessSizeLog, bool kAccessIsWrite, FastState fast_state,
+    int kAccessSizeLog, bool kAccessIsWrite,
     u64 *shadow_mem, Shadow cur);
 void MemoryRead1Byte(ThreadState *thr, uptr pc, uptr addr);
 void MemoryWrite1Byte(ThreadState *thr, uptr pc, uptr addr);
@@ -499,7 +491,8 @@ int ThreadTid(ThreadState *thr, uptr pc, uptr uid);
 void ThreadJoin(ThreadState *thr, uptr pc, int tid);
 void ThreadDetach(ThreadState *thr, uptr pc, int tid);
 void ThreadFinalize(ThreadState *thr);
-void ThreadFinalizerGoroutine(ThreadState *thr);
+int ThreadCount(ThreadState *thr);
+void ProcessPendingSignals(ThreadState *thr);
 
 void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
                  bool rw, bool recursive, bool linker_init);
@@ -511,6 +504,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
 void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
 
 void Acquire(ThreadState *thr, uptr pc, uptr addr);
+void AcquireGlobal(ThreadState *thr, uptr pc);
 void Release(ThreadState *thr, uptr pc, uptr addr);
 void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
 void AfterSleep(ThreadState *thr, uptr pc);
@@ -521,7 +515,7 @@ void AfterSleep(ThreadState *thr, uptr pc);
 // The trick is that the call preserves all registers and the compiler
 // does not treat it as a call.
 // If it does not work for you, use normal call.
-#if TSAN_DEBUG == 0
+#if 0 && TSAN_DEBUG == 0
 // The caller may not create the stack frame for itself at all,
 // so we create a reserve stack frame for it (1024b must be enough).
 #define HACKY_CALL(f) \
@@ -542,7 +536,11 @@ void ALWAYS_INLINE INLINE TraceAddEvent(ThreadState *thr, u64 epoch,
                                         EventType typ, uptr addr) {
   StatInc(thr, StatEvents);
   if (UNLIKELY((epoch % kTracePartSize) == 0)) {
+#ifndef TSAN_GO
+    HACKY_CALL(__tsan_trace_switch);
+#else
     TraceSwitch(thr);
+#endif
   }
   Event *evp = &thr->trace.events[epoch % kTraceSize];
   Event ev = (u64)addr | ((u64)typ << 61);
diff --git a/libsanitizer/tsan/tsan_rtl_mutex.cc b/libsanitizer/tsan/tsan_rtl_mutex.cc
index 098894f5caa8..9ace430bc586 100644
--- a/libsanitizer/tsan/tsan_rtl_mutex.cc
+++ b/libsanitizer/tsan/tsan_rtl_mutex.cc
@@ -82,7 +82,7 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr) {
   } else if (s->owner_tid == thr->tid) {
     CHECK_GT(s->recursion, 0);
   } else {
-    TsanPrintf("ThreadSanitizer WARNING: double lock\n");
+    Printf("ThreadSanitizer WARNING: double lock\n");
     PrintCurrentStack(thr, pc);
   }
   if (s->recursion == 0) {
@@ -110,13 +110,13 @@ void MutexUnlock(ThreadState *thr, uptr pc, uptr addr) {
   if (s->recursion == 0) {
     if (!s->is_broken) {
       s->is_broken = true;
-      TsanPrintf("ThreadSanitizer WARNING: unlock of unlocked mutex\n");
+      Printf("ThreadSanitizer WARNING: unlock of unlocked mutex\n");
       PrintCurrentStack(thr, pc);
     }
   } else if (s->owner_tid != thr->tid) {
     if (!s->is_broken) {
       s->is_broken = true;
-      TsanPrintf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+      Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
       PrintCurrentStack(thr, pc);
     }
   } else {
@@ -145,7 +145,7 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
   TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeRLock, addr);
   SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, false);
   if (s->owner_tid != SyncVar::kInvalidTid) {
-    TsanPrintf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");
+    Printf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");
     PrintCurrentStack(thr, pc);
   }
   thr->clock.set(thr->tid, thr->fast_state.epoch());
@@ -165,7 +165,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
   TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeRUnlock, addr);
   SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
   if (s->owner_tid != SyncVar::kInvalidTid) {
-    TsanPrintf("ThreadSanitizer WARNING: read unlock of a write "
+    Printf("ThreadSanitizer WARNING: read unlock of a write "
                "locked mutex\n");
     PrintCurrentStack(thr, pc);
   }
@@ -213,7 +213,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
     }
   } else if (!s->is_broken) {
     s->is_broken = true;
-    TsanPrintf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+    Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
     PrintCurrentStack(thr, pc);
   }
   s->mtx.Unlock();
@@ -229,6 +229,20 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) {
   s->mtx.ReadUnlock();
 }
 
+void AcquireGlobal(ThreadState *thr, uptr pc) {
+  Context *ctx = CTX();
+  Lock l(&ctx->thread_mtx);
+  for (unsigned i = 0; i < kMaxTid; i++) {
+    ThreadContext *tctx = ctx->threads[i];
+    if (tctx == 0)
+      continue;
+    if (tctx->status == ThreadStatusRunning)
+      thr->clock.set(i, tctx->thr->fast_state.epoch());
+    else
+      thr->clock.set(i, tctx->epoch1);
+  }
+}
+
 void Release(ThreadState *thr, uptr pc, uptr addr) {
   CHECK_GT(thr->in_rtl, 0);
   DPrintf("#%d: Release %zx\n", thr->tid, addr);
diff --git a/libsanitizer/tsan/tsan_rtl_report.cc b/libsanitizer/tsan/tsan_rtl_report.cc
index 1511913d7428..24e29d25400c 100644
--- a/libsanitizer/tsan/tsan_rtl_report.cc
+++ b/libsanitizer/tsan/tsan_rtl_report.cc
@@ -26,9 +26,9 @@ namespace __tsan {
 void TsanCheckFailed(const char *file, int line, const char *cond,
                      u64 v1, u64 v2) {
   ScopedInRtl in_rtl;
-  TsanPrintf("FATAL: ThreadSanitizer CHECK failed: "
-             "%s:%d \"%s\" (0x%zx, 0x%zx)\n",
-             file, line, cond, (uptr)v1, (uptr)v2);
+  Printf("FATAL: ThreadSanitizer CHECK failed: "
+         "%s:%d \"%s\" (0x%zx, 0x%zx)\n",
+         file, line, cond, (uptr)v1, (uptr)v2);
   Die();
 }
 
@@ -383,6 +383,8 @@ bool IsFiredSuppression(Context *ctx,
 }
 
 void ReportRace(ThreadState *thr) {
+  if (!flags()->report_bugs)
+    return;
   ScopedInRtl in_rtl;
 
   bool freed = false;
diff --git a/libsanitizer/tsan/tsan_rtl_thread.cc b/libsanitizer/tsan/tsan_rtl_thread.cc
index 0ae658c17438..bb7f35c24ed4 100644
--- a/libsanitizer/tsan/tsan_rtl_thread.cc
+++ b/libsanitizer/tsan/tsan_rtl_thread.cc
@@ -50,6 +50,23 @@ void ThreadFinalize(ThreadState *thr) {
   }
 }
 
+int ThreadCount(ThreadState *thr) {
+  CHECK_GT(thr->in_rtl, 0);
+  Context *ctx = CTX();
+  Lock l(&ctx->thread_mtx);
+  int cnt = 0;
+  for (unsigned i = 0; i < kMaxTid; i++) {
+    ThreadContext *tctx = ctx->threads[i];
+    if (tctx == 0)
+      continue;
+    if (tctx->status != ThreadStatusCreated
+        && tctx->status != ThreadStatusRunning)
+      continue;
+    cnt++;
+  }
+  return cnt;
+}
+
 static void ThreadDead(ThreadState *thr, ThreadContext *tctx) {
   Context *ctx = CTX();
   CHECK_GT(thr->in_rtl, 0);
@@ -80,7 +97,7 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
   if (ctx->dead_list_size > kThreadQuarantineSize
       || ctx->thread_seq >= kMaxTid) {
     if (ctx->dead_list_size == 0) {
-      TsanPrintf("ThreadSanitizer: %d thread limit exceeded. Dying.\n",
+      Printf("ThreadSanitizer: %d thread limit exceeded. Dying.\n",
                  kMaxTid);
       Die();
     }
@@ -273,7 +290,7 @@ void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
   Lock l(&ctx->thread_mtx);
   ThreadContext *tctx = ctx->threads[tid];
   if (tctx->status == ThreadStatusInvalid) {
-    TsanPrintf("ThreadSanitizer: join of non-existent thread\n");
+    Printf("ThreadSanitizer: join of non-existent thread\n");
     return;
   }
   CHECK_EQ(tctx->detached, false);
@@ -291,7 +308,7 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
   Lock l(&ctx->thread_mtx);
   ThreadContext *tctx = ctx->threads[tid];
   if (tctx->status == ThreadStatusInvalid) {
-    TsanPrintf("ThreadSanitizer: detach of non-existent thread\n");
+    Printf("ThreadSanitizer: detach of non-existent thread\n");
     return;
   }
   if (tctx->status == ThreadStatusFinished) {
@@ -301,10 +318,6 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
   }
 }
 
-void ThreadFinalizerGoroutine(ThreadState *thr) {
-  thr->clock.Disable(thr->tid);
-}
-
 void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
                        uptr size, bool is_write) {
   if (size == 0)
@@ -317,19 +330,19 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
 
 #if TSAN_DEBUG
   if (!IsAppMem(addr)) {
-    TsanPrintf("Access to non app mem %zx\n", addr);
+    Printf("Access to non app mem %zx\n", addr);
     DCHECK(IsAppMem(addr));
   }
   if (!IsAppMem(addr + size - 1)) {
-    TsanPrintf("Access to non app mem %zx\n", addr + size - 1);
+    Printf("Access to non app mem %zx\n", addr + size - 1);
     DCHECK(IsAppMem(addr + size - 1));
   }
   if (!IsShadowMem((uptr)shadow_mem)) {
-    TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
+    Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
     DCHECK(IsShadowMem((uptr)shadow_mem));
   }
   if (!IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1))) {
-    TsanPrintf("Bad shadow addr %p (%zx)\n",
+    Printf("Bad shadow addr %p (%zx)\n",
                shadow_mem + size * kShadowCnt / 8 - 1, addr + size - 1);
     DCHECK(IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1)));
   }
@@ -353,7 +366,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
     Shadow cur(fast_state);
     cur.SetWrite(is_write);
     cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
-    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, fast_state,
+    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
         shadow_mem, cur);
   }
   if (unaligned)
@@ -364,7 +377,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
     Shadow cur(fast_state);
     cur.SetWrite(is_write);
     cur.SetAddr0AndSizeLog(0, kAccessSizeLog);
-    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, fast_state,
+    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
         shadow_mem, cur);
     shadow_mem += kShadowCnt;
   }
@@ -374,7 +387,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
     Shadow cur(fast_state);
     cur.SetWrite(is_write);
     cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
-    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, fast_state,
+    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
         shadow_mem, cur);
   }
 }
diff --git a/libsanitizer/tsan/tsan_stat.cc b/libsanitizer/tsan/tsan_stat.cc
index fcbc631e086d..68acae81e666 100644
--- a/libsanitizer/tsan/tsan_stat.cc
+++ b/libsanitizer/tsan/tsan_stat.cc
@@ -194,7 +194,12 @@ void StatOutput(u64 *stat) {
   name[StatInt_opendir]                  = "  opendir                         ";
   name[StatInt_epoll_ctl]                = "  epoll_ctl                       ";
   name[StatInt_epoll_wait]               = "  epoll_wait                      ";
+  name[StatInt_poll]                     = "  poll                            ";
   name[StatInt_sigaction]                = "  sigaction                       ";
+  name[StatInt_sleep]                    = "  sleep                           ";
+  name[StatInt_usleep]                   = "  usleep                          ";
+  name[StatInt_nanosleep]                = "  nanosleep                       ";
+  name[StatInt_gettimeofday]             = "  gettimeofday                    ";
 
   name[StatAnnotation]                   = "Dynamic annotations               ";
   name[StatAnnotateHappensBefore]        = "  HappensBefore                   ";
@@ -239,9 +244,9 @@ void StatOutput(u64 *stat) {
   name[StatMtxAtExit]                    = "  Atexit                          ";
   name[StatMtxAnnotations]               = "  Annotations                     ";
 
-  TsanPrintf("Statistics:\n");
+  Printf("Statistics:\n");
   for (int i = 0; i < StatCnt; i++)
-    TsanPrintf("%s: %zu\n", name[i], (uptr)stat[i]);
+    Printf("%s: %zu\n", name[i], (uptr)stat[i]);
 }
 
 }  // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_stat.h b/libsanitizer/tsan/tsan_stat.h
index b194343a08a9..25bff8b7080b 100644
--- a/libsanitizer/tsan/tsan_stat.h
+++ b/libsanitizer/tsan/tsan_stat.h
@@ -193,6 +193,7 @@ enum StatType {
   StatInt_opendir,
   StatInt_epoll_ctl,
   StatInt_epoll_wait,
+  StatInt_poll,
   StatInt_sigaction,
   StatInt_signal,
   StatInt_raise,
@@ -201,6 +202,7 @@ enum StatType {
   StatInt_sleep,
   StatInt_usleep,
   StatInt_nanosleep,
+  StatInt_gettimeofday,
 
   // Dynamic annotations.
   StatAnnotation,
diff --git a/libsanitizer/tsan/tsan_suppressions.cc b/libsanitizer/tsan/tsan_suppressions.cc
index 9b087add3c26..3f825a804a13 100644
--- a/libsanitizer/tsan/tsan_suppressions.cc
+++ b/libsanitizer/tsan/tsan_suppressions.cc
@@ -31,19 +31,19 @@ static char *ReadFile(const char *filename) {
     internal_snprintf(tmp.data(), tmp.size(), "%s/%s", GetPwd(), filename);
   fd_t fd = internal_open(tmp.data(), false);
   if (fd == kInvalidFd) {
-    TsanPrintf("ThreadSanitizer: failed to open suppressions file '%s'\n",
+    Printf("ThreadSanitizer: failed to open suppressions file '%s'\n",
                tmp.data());
     Die();
   }
   const uptr fsize = internal_filesize(fd);
   if (fsize == (uptr)-1) {
-    TsanPrintf("ThreadSanitizer: failed to stat suppressions file '%s'\n",
+    Printf("ThreadSanitizer: failed to stat suppressions file '%s'\n",
                tmp.data());
     Die();
   }
   char *buf = (char*)internal_alloc(MBlockSuppression, fsize + 1);
   if (fsize != internal_read(fd, buf, fsize)) {
-    TsanPrintf("ThreadSanitizer: failed to read suppressions file '%s'\n",
+    Printf("ThreadSanitizer: failed to read suppressions file '%s'\n",
                tmp.data());
     Die();
   }
@@ -108,7 +108,7 @@ Suppression *SuppressionParse(const char* supp) {
         stype = SuppressionSignal;
         line += sizeof("signal:") - 1;
       } else {
-        TsanPrintf("ThreadSanitizer: failed to parse suppressions file\n");
+        Printf("ThreadSanitizer: failed to parse suppressions file\n");
         Die();
       }
       Suppression *s = (Suppression*)internal_alloc(MBlockSuppression,
diff --git a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc b/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
index 9caf091fecf8..23540c07ca93 100644
--- a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
+++ b/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
@@ -48,17 +48,17 @@ struct DlIteratePhdrCtx {
 static void NOINLINE InitModule(ModuleDesc *m) {
   int outfd[2] = {};
   if (pipe(&outfd[0])) {
-    TsanPrintf("ThreadSanitizer: outfd pipe() failed (%d)\n", errno);
+    Printf("ThreadSanitizer: outfd pipe() failed (%d)\n", errno);
     Die();
   }
   int infd[2] = {};
   if (pipe(&infd[0])) {
-    TsanPrintf("ThreadSanitizer: infd pipe() failed (%d)\n", errno);
+    Printf("ThreadSanitizer: infd pipe() failed (%d)\n", errno);
     Die();
   }
   int pid = fork();
   if (pid == 0) {
-    flags()->log_fileno = STDERR_FILENO;
+    __sanitizer_set_report_fd(STDERR_FILENO);
     internal_close(STDOUT_FILENO);
     internal_close(STDIN_FILENO);
     internal_dup2(outfd[0], STDIN_FILENO);
@@ -72,7 +72,7 @@ static void NOINLINE InitModule(ModuleDesc *m) {
     execl("/usr/bin/addr2line", "/usr/bin/addr2line", "-Cfe", m->fullname, 0);
     _exit(0);
   } else if (pid < 0) {
-    TsanPrintf("ThreadSanitizer: failed to fork symbolizer\n");
+    Printf("ThreadSanitizer: failed to fork symbolizer\n");
     Die();
   }
   internal_close(outfd[0]);
@@ -153,14 +153,14 @@ ReportStack *SymbolizeCodeAddr2Line(uptr addr) {
   char addrstr[32];
   internal_snprintf(addrstr, sizeof(addrstr), "%p\n", (void*)offset);
   if (0 >= internal_write(m->out_fd, addrstr, internal_strlen(addrstr))) {
-    TsanPrintf("ThreadSanitizer: can't write from symbolizer (%d, %d)\n",
+    Printf("ThreadSanitizer: can't write from symbolizer (%d, %d)\n",
         m->out_fd, errno);
     Die();
   }
   InternalScopedBuffer<char> func(1024);
   ssize_t len = internal_read(m->inp_fd, func.data(), func.size() - 1);
   if (len <= 0) {
-    TsanPrintf("ThreadSanitizer: can't read from symbolizer (%d, %d)\n",
+    Printf("ThreadSanitizer: can't read from symbolizer (%d, %d)\n",
         m->inp_fd, errno);
     Die();
   }
diff --git a/libsanitizer/tsan/tsan_update_shadow_word_inl.h b/libsanitizer/tsan/tsan_update_shadow_word_inl.h
index ae4a318f9525..e22859c1ddeb 100644
--- a/libsanitizer/tsan/tsan_update_shadow_word_inl.h
+++ b/libsanitizer/tsan/tsan_update_shadow_word_inl.h
@@ -32,7 +32,7 @@ do {
     if (Shadow::TidsAreEqual(old, cur)) {
       StatInc(thr, StatShadowSameThread);
       if (OldIsInSameSynchEpoch(old, thr)) {
-        if (OldIsRWStronger(old, kAccessIsWrite)) {
+        if (OldIsRWNotWeaker(old, kAccessIsWrite)) {
           // found a slot that holds effectively the same info
           // (that is, same tid, same sync epoch and same size)
           StatInc(thr, StatMopSame);
@@ -41,7 +41,7 @@ do {
         StoreIfNotYetStored(sp, &store_word);
         break;
       }
-      if (OldIsRWWeaker(old, kAccessIsWrite))
+      if (OldIsRWWeakerOrEqual(old, kAccessIsWrite))
         StoreIfNotYetStored(sp, &store_word);
       break;
     }
-- 
GitLab