Merge changes I221b1342,I1d1276da,I89b128df,Icb348a11,Ifb3b2d8d

* changes:
  Add a __bionic_get_tls_segment function
  Factor out ScopedRWLock into its own header
  Build the linker with -D_USING_LIBCXX
  Provide a stub aeabi.read_tp on other archs
  Remove TLS_SLOT_TSAN(8)
diff --git a/libc/bionic/bionic_elf_tls.cpp b/libc/bionic/bionic_elf_tls.cpp
index 55c2c31..2d2cbe3 100644
--- a/libc/bionic/bionic_elf_tls.cpp
+++ b/libc/bionic/bionic_elf_tls.cpp
@@ -28,11 +28,43 @@
 
 #include "private/bionic_elf_tls.h"
 
+#include <async_safe/log.h>
 #include <sys/param.h>
+#include <unistd.h>
 
 #include "private/bionic_macros.h"
 #include "private/bionic_tls.h"
 
+// Search for a TLS segment in the given phdr table. Returns true if it has a
+// TLS segment and false otherwise.
+bool __bionic_get_tls_segment(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+                              ElfW(Addr) load_bias, const char* mod_name,
+                              TlsSegment* out) {
+  for (size_t i = 0; i < phdr_count; ++i) {
+    const ElfW(Phdr)& phdr = phdr_table[i];
+    if (phdr.p_type == PT_TLS) {
+      // N.B. The size does not need to be a multiple of the alignment. With
+      // ld.bfd (or after using binutils' strip), the TLS segment's size isn't
+      // rounded up.
+      size_t alignment = phdr.p_align;
+      if (alignment == 0 || !powerof2(alignment)) {
+        async_safe_fatal("error: \"%s\": TLS segment alignment is not a power of 2: %zu",
+                         mod_name, alignment);
+      }
+      // Bionic only respects TLS alignment up to one page.
+      alignment = MIN(alignment, PAGE_SIZE);
+      *out = TlsSegment {
+        phdr.p_memsz,
+        alignment,
+        reinterpret_cast<void*>(load_bias + phdr.p_vaddr),
+        phdr.p_filesz,
+      };
+      return true;
+    }
+  }
+  return false;
+}
+
 void StaticTlsLayout::reserve_tcb() {
   offset_bionic_tcb_ = reserve_type<bionic_tcb>();
 }
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 870a526..46fa630 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -35,30 +35,13 @@
 
 #include <async_safe/log.h>
 
+#include "private/ScopedRWLock.h"
 #include "private/bionic_futex.h"
 #include "private/bionic_tls.h"
 
 static pthread_internal_t* g_thread_list = nullptr;
 static pthread_rwlock_t g_thread_list_lock = PTHREAD_RWLOCK_INITIALIZER;
 
-template <bool write> class ScopedRWLock {
- public:
-  explicit ScopedRWLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) {
-    (write ? pthread_rwlock_wrlock : pthread_rwlock_rdlock)(rwlock_);
-  }
-
-  ~ScopedRWLock() {
-    pthread_rwlock_unlock(rwlock_);
-  }
-
- private:
-  pthread_rwlock_t* rwlock_;
-  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedRWLock);
-};
-
-typedef ScopedRWLock<true> ScopedWriteLock;
-typedef ScopedRWLock<false> ScopedReadLock;
-
 pthread_t __pthread_internal_add(pthread_internal_t* thread) {
   ScopedWriteLock locker(&g_thread_list_lock);
 
diff --git a/libc/private/ScopedRWLock.h b/libc/private/ScopedRWLock.h
new file mode 100644
index 0000000..f034505
--- /dev/null
+++ b/libc/private/ScopedRWLock.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <pthread.h>
+
+#include "private/bionic_macros.h"
+
+template <bool write> class ScopedRWLock {
+ public:
+  explicit ScopedRWLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) {
+    (write ? pthread_rwlock_wrlock : pthread_rwlock_rdlock)(rwlock_);
+  }
+
+  ~ScopedRWLock() {
+    pthread_rwlock_unlock(rwlock_);
+  }
+
+ private:
+  pthread_rwlock_t* rwlock_;
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedRWLock);
+};
+
+typedef ScopedRWLock<true> ScopedWriteLock;
+typedef ScopedRWLock<false> ScopedReadLock;
diff --git a/libc/private/bionic_asm_tls.h b/libc/private/bionic_asm_tls.h
index 06e3dce..0f0873f 100644
--- a/libc/private/bionic_asm_tls.h
+++ b/libc/private/bionic_asm_tls.h
@@ -87,11 +87,9 @@
 #define TLS_SLOT_STACK_GUARD      5
 #define TLS_SLOT_SANITIZER        6 // was historically used for dlerror
 #define TLS_SLOT_ART_THREAD_SELF  7
-#define TLS_SLOT_TSAN             8 // should be replaced with TLS_SLOT_SANITIZER
 
 // The maximum slot is fixed by the minimum TLS alignment in Bionic executables.
-// It should be changed to 7 once TLS_SLOT_TSAN is removed.
-#define MAX_TLS_SLOT              8
+#define MAX_TLS_SLOT              7
 
 #elif defined(__i386__) || defined(__x86_64__)
 
@@ -109,10 +107,9 @@
 #define TLS_SLOT_STACK_GUARD      5
 #define TLS_SLOT_SANITIZER        6 // was historically used for dlerror
 #define TLS_SLOT_ART_THREAD_SELF  7
-#define TLS_SLOT_TSAN             8 // should be replaced with TLS_SLOT_SANITIZER
-#define TLS_SLOT_DTV              9
-#define TLS_SLOT_BIONIC_TLS       10
-#define MAX_TLS_SLOT              10 // update this value when reserving a slot
+#define TLS_SLOT_DTV              8
+#define TLS_SLOT_BIONIC_TLS       9
+#define MAX_TLS_SLOT              9 // update this value when reserving a slot
 
 #endif
 
diff --git a/libc/private/bionic_elf_tls.h b/libc/private/bionic_elf_tls.h
index e847669..48a4d25 100644
--- a/libc/private/bionic_elf_tls.h
+++ b/libc/private/bionic_elf_tls.h
@@ -28,7 +28,20 @@
 
 #pragma once
 
+#include <link.h>
 #include <stdint.h>
+#include <sys/cdefs.h>
+
+struct TlsSegment {
+  size_t size = 0;
+  size_t alignment = 1;
+  const void* init_ptr = "";    // Field is non-null even when init_size is 0.
+  size_t init_size = 0;
+};
+
+__LIBC_HIDDEN__ bool __bionic_get_tls_segment(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+                                              ElfW(Addr) load_bias, const char* mod_name,
+                                              TlsSegment* out);
 
 struct StaticTlsLayout {
   constexpr StaticTlsLayout() {}
diff --git a/linker/Android.bp b/linker/Android.bp
index 38a53f8..e103ade 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -176,6 +176,11 @@
         "-Wextra",
         "-Wunused",
         "-Werror",
+
+        // Define _USING_LIBCXX so <stdatomic.h> defers to the <atomic> header. When a Soong module
+        // uses the platform libc++, Soong automatically passes this macro, but the dynamic linker
+        // links against libc++ manually.
+        "-D_USING_LIBCXX",
     ],
 
     // TODO: split out the asflags.
diff --git a/tests/__aeabi_read_tp_test.cpp b/tests/__aeabi_read_tp_test.cpp
index ab96af9..6974658 100644
--- a/tests/__aeabi_read_tp_test.cpp
+++ b/tests/__aeabi_read_tp_test.cpp
@@ -32,7 +32,12 @@
 
 #if defined(__arm__)
 extern "C" void* __aeabi_read_tp();
-TEST(aeabi, read_tp) {
-  ASSERT_EQ(__aeabi_read_tp(), static_cast<void*>(__get_tls()));
-}
 #endif
+
+TEST(aeabi, read_tp) {
+#if defined(__arm__)
+  ASSERT_EQ(__aeabi_read_tp(), static_cast<void*>(__get_tls()));
+#else
+  GTEST_LOG_(INFO) << "__aeabi_read_tp is only available on arm32.\n";
+#endif
+}