diff --git a/compiler-rt/lib/scudo/standalone/linux.h b/compiler-rt/lib/scudo/standalone/linux.h
--- a/compiler-rt/lib/scudo/standalone/linux.h
+++ b/compiler-rt/lib/scudo/standalone/linux.h
@@ -18,51 +18,6 @@
 // MapPlatformData is unused on Linux, define it as a minimally sized structure.
 struct MapPlatformData {};
 
-#if SCUDO_ANDROID
-
-#if defined(__aarch64__)
-#define __get_tls()                                                            \
-  ({                                                                           \
-    void **__v;                                                                \
-    __asm__("mrs %0, tpidr_el0" : "=r"(__v));                                  \
-    __v;                                                                       \
-  })
-#elif defined(__arm__)
-#define __get_tls()                                                            \
-  ({                                                                           \
-    void **__v;                                                                \
-    __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v));                         \
-    __v;                                                                       \
-  })
-#elif defined(__i386__)
-#define __get_tls()                                                            \
-  ({                                                                           \
-    void **__v;                                                                \
-    __asm__("movl %%gs:0, %0" : "=r"(__v));                                    \
-    __v;                                                                       \
-  })
-#elif defined(__x86_64__)
-#define __get_tls()                                                            \
-  ({                                                                           \
-    void **__v;                                                                \
-    __asm__("mov %%fs:0, %0" : "=r"(__v));                                     \
-    __v;                                                                       \
-  })
-#else
-#error "Unsupported architecture."
-#endif
-
-// The Android Bionic team has allocated a TLS slot for sanitizers starting
-// with Q, given that Android currently doesn't support ELF TLS. It is used to
-// store sanitizer thread specific data.
-static const int TLS_SLOT_SANITIZER = 6;
-
-ALWAYS_INLINE uptr *getAndroidTlsPtr() {
-  return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]);
-}
-
-#endif // SCUDO_ANDROID
-
 } // namespace scudo
 
 #endif // SCUDO_LINUX
diff --git a/compiler-rt/lib/scudo/standalone/tsd_shared.h b/compiler-rt/lib/scudo/standalone/tsd_shared.h
--- a/compiler-rt/lib/scudo/standalone/tsd_shared.h
+++ b/compiler-rt/lib/scudo/standalone/tsd_shared.h
@@ -9,9 +9,17 @@
 #ifndef SCUDO_TSD_SHARED_H_
 #define SCUDO_TSD_SHARED_H_
 
-#include "linux.h" // for getAndroidTlsPtr()
 #include "tsd.h"
 
+#if SCUDO_HAS_PLATFORM_TLS_SLOT
+// This is a platform-provided header that needs to be on the include path when
+// Scudo is compiled. It must declare a function with the prototype:
+//   uintptr_t *getPlatformAllocatorTlsSlot()
+// that returns the address of a thread-local word of storage reserved for
+// Scudo, that must be zero-initialized in newly created threads.
+#include "scudo_platform_tls_slot.h"
+#endif
+
 namespace scudo {
 
 template <class Allocator, u32 TSDsArraySize, u32 DefaultTSDCount>
@@ -80,26 +88,21 @@
   }
 
 private:
-  ALWAYS_INLINE void setCurrentTSD(TSD<Allocator> *CurrentTSD) {
-#if _BIONIC
-    *getAndroidTlsPtr() = reinterpret_cast<uptr>(CurrentTSD);
-#elif SCUDO_LINUX
-    ThreadTSD = CurrentTSD;
+  ALWAYS_INLINE uptr *getTlsPtr() const {
+#if SCUDO_HAS_PLATFORM_TLS_SLOT
+    return reinterpret_cast<uptr *>(getPlatformAllocatorTlsSlot());
 #else
-    CHECK_EQ(
-        pthread_setspecific(PThreadKey, reinterpret_cast<void *>(CurrentTSD)),
-        0);
+    static thread_local uptr ThreadTSD;
+    return &ThreadTSD;
 #endif
   }
 
+  ALWAYS_INLINE void setCurrentTSD(TSD<Allocator> *CurrentTSD) {
+    *getTlsPtr() = reinterpret_cast<uptr>(CurrentTSD);
+  }
+
   ALWAYS_INLINE TSD<Allocator> *getCurrentTSD() {
-#if _BIONIC
-    return reinterpret_cast<TSD<Allocator> *>(*getAndroidTlsPtr());
-#elif SCUDO_LINUX
-    return ThreadTSD;
-#else
-    return reinterpret_cast<TSD<Allocator> *>(pthread_getspecific(PThreadKey));
-#endif
+    return reinterpret_cast<TSD<Allocator> *>(*getTlsPtr());
   }
 
   bool setNumberOfTSDs(u32 N) {
@@ -195,17 +198,8 @@
   HybridMutex Mutex;
   HybridMutex MutexTSDs;
   TSD<Allocator> TSDs[TSDsArraySize];
-#if SCUDO_LINUX && !_BIONIC
-  static THREADLOCAL TSD<Allocator> *ThreadTSD;
-#endif
 };
 
-#if SCUDO_LINUX && !_BIONIC
-template <class Allocator, u32 TSDsArraySize, u32 DefaultTSDCount>
-THREADLOCAL TSD<Allocator>
-    *TSDRegistrySharedT<Allocator, TSDsArraySize, DefaultTSDCount>::ThreadTSD;
-#endif
-
 } // namespace scudo
 
 #endif // SCUDO_TSD_SHARED_H_