Index: lib/tsan/rtl/tsan_external.cc
===================================================================
--- lib/tsan/rtl/tsan_external.cc
+++ lib/tsan/rtl/tsan_external.cc
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "tsan_rtl.h"
+#include "tsan_interceptors.h"
 
 namespace __tsan {
 
@@ -57,9 +58,12 @@
   CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
   ThreadState *thr = cur_thread();
   thr->external_tag = (uptr)tag;
-  FuncEntry(thr, (uptr)caller_pc);
-  MemoryRead(thr, CALLERPC, (uptr)addr, kSizeLog8);
-  FuncExit(thr);
+  if (caller_pc) FuncEntry(thr, (uptr)caller_pc);
+  bool in_ignored_lib;
+  if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) {
+    MemoryRead(thr, CALLERPC, (uptr)addr, kSizeLog8);
+  }
+  if (caller_pc) FuncExit(thr);
   thr->external_tag = 0;
 }
 
@@ -68,9 +72,12 @@
   CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
   ThreadState *thr = cur_thread();
   thr->external_tag = (uptr)tag;
-  FuncEntry(thr, (uptr)caller_pc);
-  MemoryWrite(thr, CALLERPC, (uptr)addr, kSizeLog8);
-  FuncExit(thr);
+  if (caller_pc) FuncEntry(thr, (uptr)caller_pc);
+  bool in_ignored_lib;
+  if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) {
+    MemoryWrite(thr, CALLERPC, (uptr)addr, kSizeLog8);
+  }
+  if (caller_pc) FuncExit(thr);
   thr->external_tag = 0;
 }
 }  // extern "C"
Index: lib/tsan/rtl/tsan_interceptors.h
===================================================================
--- lib/tsan/rtl/tsan_interceptors.h
+++ lib/tsan/rtl/tsan_interceptors.h
@@ -19,6 +19,8 @@
   bool ignoring_;
 };
 
+LibIgnore *libignore();
+
 }  // namespace __tsan
 
 #define SCOPED_INTERCEPTOR_RAW(func, ...) \
Index: lib/tsan/rtl/tsan_interceptors.cc
===================================================================
--- lib/tsan/rtl/tsan_interceptors.cc
+++ lib/tsan/rtl/tsan_interceptors.cc
@@ -219,7 +219,7 @@
 // The object is 64-byte aligned, because we want hot data to be located in
 // a single cache line if possible (it's accessed in every interceptor).
 static ALIGNED(64) char libignore_placeholder[sizeof(LibIgnore)];
-static LibIgnore *libignore() {
+LibIgnore *libignore() {
   return reinterpret_cast<LibIgnore*>(&libignore_placeholder[0]);
 }
 
Index: test/tsan/Darwin/external-ignore-noninstrumented.cc
===================================================================
--- test/tsan/Darwin/external-ignore-noninstrumented.cc
+++ test/tsan/Darwin/external-ignore-noninstrumented.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_tsan -shared %p/external-lib.cc -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \
+// RUN:   -o %t-lib.dylib -install_name @rpath/`basename %t-lib.dylib`
+
+// RUN: %clangxx_tsan -shared %p/external-noninstrumented-module.cc %t-lib.dylib -fno-sanitize=thread \
+// RUN:   -o %t-module.dylib -install_name @rpath/`basename %t-module.dylib`
+
+// RUN: %clangxx_tsan %s %t-module.dylib -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+
+extern "C" void NonInstrumentedModule();
+int main(int argc, char *argv[]) {
+  NonInstrumentedModule();
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
Index: test/tsan/Darwin/external-lib.cc
===================================================================
--- test/tsan/Darwin/external-lib.cc
+++ test/tsan/Darwin/external-lib.cc
@@ -0,0 +1,68 @@
+// This file is used from other tests.
+// RUN: true
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct MyObject;
+typedef MyObject *MyObjectRef;
+extern "C" {
+  void InitializeLibrary();
+  MyObject *ObjectCreate();
+  long ObjectRead(MyObject *);
+  void ObjectWrite(MyObject *, long);
+  void ObjectWriteAnother(MyObject *, long);
+}
+
+struct MyObject {
+  long _val;
+  long _another;
+};
+
+#if defined(USE_TSAN_CALLBACKS)
+static void *tag;
+void *(*callback_register_tag)(const char *object_type);
+void *(*callback_assign_tag)(void *addr, void *tag);
+void (*callback_read)(void *addr, void *caller_pc, void *tag);
+void (*callback_write)(void *addr, void *caller_pc, void *tag);
+#endif
+
+void InitializeLibrary() {
+#if defined(USE_TSAN_CALLBACKS)
+  callback_register_tag = (decltype(callback_register_tag))dlsym(RTLD_DEFAULT, "__tsan_external_register_tag");
+  callback_assign_tag = (decltype(callback_assign_tag))dlsym(RTLD_DEFAULT, "__tsan_external_assign_tag");
+  callback_read = (decltype(callback_read))dlsym(RTLD_DEFAULT, "__tsan_external_read");
+  callback_write = (decltype(callback_write))dlsym(RTLD_DEFAULT, "__tsan_external_write");
+  tag = callback_register_tag("MyLibrary::MyObject");
+#endif
+}
+
+MyObject *ObjectCreate() {
+  MyObject *ref = (MyObject *)malloc(sizeof(MyObject));
+#if defined(USE_TSAN_CALLBACKS)
+  callback_assign_tag(ref, tag);
+#endif
+  return ref;
+}
+
+long ObjectRead(MyObject *ref) {
+#if defined(USE_TSAN_CALLBACKS)
+  callback_read(ref, __builtin_return_address(0), tag);
+#endif
+  return ref->_val;
+}
+
+void ObjectWrite(MyObject *ref, long val) {
+#if defined(USE_TSAN_CALLBACKS)
+  callback_write(ref, __builtin_return_address(0), tag);
+#endif
+  ref->_val = val;
+}
+
+void ObjectWriteAnother(MyObject *ref, long val) {
+#if defined(USE_TSAN_CALLBACKS)
+  callback_write(ref, __builtin_return_address(0), tag);
+#endif
+  ref->_another = val;
+}
Index: test/tsan/Darwin/external-noninstrumented-module.cc
===================================================================
--- test/tsan/Darwin/external-noninstrumented-module.cc
+++ test/tsan/Darwin/external-noninstrumented-module.cc
@@ -0,0 +1,27 @@
+// This file is used from other tests.
+// RUN: true
+
+#include <thread>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+struct MyObject;
+typedef MyObject *MyObjectRef;
+extern "C" {
+  void InitializeLibrary();
+  MyObject *ObjectCreate();
+  long ObjectRead(MyObject *);
+  void ObjectWrite(MyObject *, long);
+  void ObjectWriteAnother(MyObject *, long);
+}
+
+extern "C" void NonInstrumentedModule() {
+  InitializeLibrary();
+  
+  MyObjectRef ref = ObjectCreate();
+  std::thread t1([ref]{ ObjectWrite(ref, 42); });
+  std::thread t2([ref]{ ObjectWrite(ref, 43); });
+  t1.join();
+  t2.join();
+}
Index: test/tsan/Darwin/external.cc
===================================================================
--- test/tsan/Darwin/external.cc
+++ test/tsan/Darwin/external.cc
@@ -1,12 +1,12 @@
-// RUN: %clangxx_tsan %s -shared -DSHARED_LIB \
+// RUN: %clangxx_tsan %p/external-lib.cc -shared \
 // RUN:                               -o %t-lib-instrumented.dylib \
 // RUN:   -install_name @rpath/`basename %t-lib-instrumented.dylib`
 
-// RUN: %clangxx_tsan %s -shared -DSHARED_LIB -fno-sanitize=thread \
+// RUN: %clangxx_tsan %p/external-lib.cc -shared -fno-sanitize=thread \
 // RUN:                               -o %t-lib-noninstrumented.dylib \
 // RUN:   -install_name @rpath/`basename %t-lib-noninstrumented.dylib`
 
-// RUN: %clangxx_tsan %s -shared -DSHARED_LIB -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \
+// RUN: %clangxx_tsan %p/external-lib.cc -shared -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \
 // RUN:                               -o %t-lib-noninstrumented-callbacks.dylib \
 // RUN:   -install_name @rpath/`basename %t-lib-noninstrumented-callbacks.dylib`
 
@@ -23,8 +23,6 @@
 
 #include <thread>
 
-#include <dlfcn.h>
-#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -38,62 +36,6 @@
   void ObjectWriteAnother(MyObject *, long);
 }
 
-#if defined(SHARED_LIB)
-
-struct MyObject {
-  long _val;
-  long _another;
-};
-
-#if defined(USE_TSAN_CALLBACKS)
-static void *tag;
-void *(*callback_register_tag)(const char *object_type);
-void *(*callback_assign_tag)(void *addr, void *tag);
-void (*callback_read)(void *addr, void *caller_pc, void *tag);
-void (*callback_write)(void *addr, void *caller_pc, void *tag);
-#endif
-
-void InitializeLibrary() {
-#if defined(USE_TSAN_CALLBACKS)
-  callback_register_tag = (decltype(callback_register_tag))dlsym(RTLD_DEFAULT, "__tsan_external_register_tag");
-  callback_assign_tag = (decltype(callback_assign_tag))dlsym(RTLD_DEFAULT, "__tsan_external_assign_tag");
-  callback_read = (decltype(callback_read))dlsym(RTLD_DEFAULT, "__tsan_external_read");
-  callback_write = (decltype(callback_write))dlsym(RTLD_DEFAULT, "__tsan_external_write");
-  tag = callback_register_tag("MyLibrary::MyObject");
-#endif
-}
-
-MyObject *ObjectCreate() {
-  MyObject *ref = (MyObject *)malloc(sizeof(MyObject));
-#if defined(USE_TSAN_CALLBACKS)
-  callback_assign_tag(ref, tag);
-#endif
-  return ref;
-}
-
-long ObjectRead(MyObject *ref) {
-#if defined(USE_TSAN_CALLBACKS)
-  callback_read(ref, __builtin_return_address(0), tag);
-#endif
-  return ref->_val;
-}
-
-void ObjectWrite(MyObject *ref, long val) {
-#if defined(USE_TSAN_CALLBACKS)
-  callback_write(ref, __builtin_return_address(0), tag);
-#endif
-  ref->_val = val;
-}
-
-void ObjectWriteAnother(MyObject *ref, long val) {
-#if defined(USE_TSAN_CALLBACKS)
-  callback_write(ref, __builtin_return_address(0), tag);
-#endif
-  ref->_another = val;
-}
-
-#else  // defined(SHARED_LIB)
-
 int main(int argc, char *argv[]) {
   InitializeLibrary();
   
@@ -159,5 +101,3 @@
   fprintf(stderr, "WW test done\n");
   // CHECK: WW test done
 }
-
-#endif  // defined(SHARED_LIB)