Work around CLONE_SETTLS being weird on x86.

Unlike other architectures, on x86 (but not x86-64), CLONE_SETTLS
takes a pointer to a struct user_desc instead of a pointer to the
TLS itself. Rather than have to deal with this here, let's just use
the old __set_tls mechanism we used to use (and still use for the
main thread on all architectures, so it's not going away any time
soon).

Bug: 11826724
Change-Id: I02a27939a73ae6cea1134a3f4c1dd7eafea479da
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 19d19b0..f20a005 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -41,6 +41,7 @@
 #include "private/ScopedPthreadMutexLocker.h"
 
 extern "C" pid_t __bionic_clone(uint32_t flags, void* child_stack, int* parent_tid, void* tls, int* child_tid, int (*fn)(void*), void* arg);
+extern "C" int __set_tls(void*);
 
 #ifdef __i386__
 #define ATTRIBUTES __attribute__((noinline)) __attribute__((fastcall))
@@ -61,6 +62,10 @@
     thread->tls[i] = NULL;
   }
 
+#if defined(__i386__)
+  __set_tls(thread->tls);
+#endif
+
   // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
   thread->tls[TLS_SLOT_SELF] = thread->tls;
   thread->tls[TLS_SLOT_THREAD_ID] = thread;
@@ -225,6 +230,12 @@
 
   int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
       CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
+#if defined(__i386__)
+  // On x86 (but not x86-64), CLONE_SETTLS takes a pointer to a struct user_desc rather than
+  // a pointer to the TLS itself. Rather than try to deal with that here, we just let x86 set
+  // the TLS manually in __init_tls, like all architectures used to.
+  flags &= ~CLONE_SETTLS;
+#endif
   int rc = __bionic_clone(flags, child_stack, &(thread->tid), thread->tls, &(thread->tid), __pthread_start, thread);
   if (rc == -1) {
     int clone_errno = errno;