[compiler-rt] 84c2c49 - scudo: Introduce a new mechanism to let Scudo access a platform-specific TLS slot

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 19:15:53 PDT 2020


Author: Peter Collingbourne
Date: 2020-09-10T19:14:28-07:00
New Revision: 84c2c4977dfe89112fd564a69c693d271663229c

URL: https://github.com/llvm/llvm-project/commit/84c2c4977dfe89112fd564a69c693d271663229c
DIFF: https://github.com/llvm/llvm-project/commit/84c2c4977dfe89112fd564a69c693d271663229c.diff

LOG: scudo: Introduce a new mechanism to let Scudo access a platform-specific TLS slot

An upcoming change to Scudo will change how we use the TLS slot
in tsd_shared.h, which will be a little easier to deal with if
we can remove the code path that calls pthread_getspecific and
pthread_setspecific. The only known user of this code path is Fuchsia.

We can't eliminate this code path by making Fuchsia use ELF TLS
because although Fuchsia supports ELF TLS, it is not supported within
libc itself. To address this, Roland McGrath on the Fuchsia team has
proposed that Scudo will optionally call a platform-provided function
to access a TLS slot reserved for Scudo. Android also has a reserved
TLS slot, but the code that accesses the TLS slot lives in Scudo.

We can eliminate some complexity and duplicated code by having Android
use the same mechanism that was proposed for Fuchsia, which is what
this change does. A separate change to Android implements it.

Differential Revision: https://reviews.llvm.org/D87420

Added: 
    

Modified: 
    compiler-rt/lib/scudo/standalone/linux.h
    compiler-rt/lib/scudo/standalone/tsd_shared.h

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/scudo/standalone/linux.h b/compiler-rt/lib/scudo/standalone/linux.h
index c8e41484c851..72acb6da83a7 100644
--- a/compiler-rt/lib/scudo/standalone/linux.h
+++ b/compiler-rt/lib/scudo/standalone/linux.h
@@ -18,51 +18,6 @@ namespace scudo {
 // 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
index 25ba191826c3..041b834c7485 100644
--- 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 @@ struct TSDRegistrySharedT {
   }
 
 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 @@ struct TSDRegistrySharedT {
   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_


        


More information about the llvm-commits mailing list