Simplify pthread_create, using more public API.

Change-Id: I08e65ba88ed01436223e4e528631c9e41ec0e7f4
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 881b091..266d6fa 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -73,12 +73,10 @@
   unsigned stack_size = 128 * 1024;
   unsigned stack_bottom = stack_top - stack_size;
 
-  pthread_attr_t thread_attr;
-  pthread_attr_init(&thread_attr);
-  pthread_attr_setstack(&thread_attr, (void*) stack_bottom, stack_size);
-
   static pthread_internal_t thread;
-  _init_thread(&thread, gettid(), &thread_attr, (void*) stack_bottom, false);
+  pthread_attr_init(&thread.attr);
+  pthread_attr_setstack(&thread.attr, (void*) stack_bottom, stack_size);
+  _init_thread(&thread, gettid(), false);
 
   static void* tls_area[BIONIC_TLS_SLOTS];
   __init_tls(tls_area, &thread);
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index bdf2b87..3564c73 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -181,20 +181,11 @@
 #include <private/logd.h>
 
 __LIBC_ABI_PRIVATE__
-int _init_thread(pthread_internal_t* thread, pid_t kernel_id, const pthread_attr_t* attr,
-                 void* stack_base, bool add_to_thread_list)
-{
+int _init_thread(pthread_internal_t* thread, pid_t kernel_id, bool add_to_thread_list) {
     int error = 0;
 
-    thread->attr = *attr;
-    thread->attr.stack_base = stack_base;
     thread->kernel_id = kernel_id;
 
-    // Make a note of whether the user supplied this stack (so we know whether or not to free it).
-    if (attr->stack_base == stack_base) {
-        thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK;
-    }
-
     // Set the scheduling policy/priority of the thread.
     if (thread->attr.sched_policy != SCHED_NORMAL) {
         struct sched_param param;
@@ -285,22 +276,29 @@
     thread->allocated_on_heap = true;
 
     if (attr == NULL) {
-        attr = &gDefaultPthreadAttr;
+      pthread_attr_init(&thread->attr);
+    } else {
+      thread->attr = *attr;
+      attr = NULL; // Prevent misuse below.
     }
 
-    // make sure the stack is PAGE_SIZE aligned
-    size_t stack_size = (attr->stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
-    uint8_t* stack = attr->stack_base;
-    if (stack == NULL) {
-        stack = mkstack(stack_size, attr->guard_size);
-        if (stack == NULL) {
+    // Make sure the stack size is PAGE_SIZE aligned.
+    size_t stack_size = (thread->attr.stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+
+    if (thread->attr.stack_base == NULL) {
+        // The caller didn't provide a stack, so allocate one.
+        thread->attr.stack_base = mkstack(stack_size, thread->attr.guard_size);
+        if (thread->attr.stack_base == NULL) {
             free(thread);
             return EAGAIN;
         }
+    } else {
+        // The caller did provide a stack, so remember we're not supposed to free it.
+        thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK;
     }
 
-    // Make room for TLS
-    void** tls = (void**)(stack + stack_size - BIONIC_TLS_SLOTS*sizeof(void*));
+    // Make room for TLS.
+    void** tls = (void**)((uint8_t*)(thread->attr.stack_base) + stack_size - BIONIC_TLS_SLOTS * sizeof(void*));
 
     // Create a mutex for the thread in TLS_SLOT_SELF to wait on once it starts so we can keep
     // it from doing anything until after we notify the debugger about it
@@ -321,15 +319,15 @@
     if (tid < 0) {
         int clone_errno = errno;
         pthread_mutex_unlock(start_mutex);
-        if (stack != attr->stack_base) {
-            munmap(stack, stack_size);
+        if ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_STACK) == 0) {
+            munmap(thread->attr.stack_base, stack_size);
         }
         free(thread);
         errno = old_errno;
         return clone_errno;
     }
 
-    int init_errno = _init_thread(thread, tid, attr, stack, true);
+    int init_errno = _init_thread(thread, tid, true);
     if (init_errno != 0) {
         // Mark the thread detached and let its __thread_entry run to
         // completion. (It'll just exit immediately, cleaning up its resources.)
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index 831a28e..c47f95e 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -30,19 +30,15 @@
 
 #include "pthread_internal.h"
 
-#define DEFAULT_STACKSIZE (1024 * 1024)
-
-const pthread_attr_t gDefaultPthreadAttr = {
-  .flags = 0,
-  .stack_base = NULL,
-  .stack_size = DEFAULT_STACKSIZE,
-  .guard_size = PAGE_SIZE,
-  .sched_policy = SCHED_NORMAL,
-  .sched_priority = 0
-};
+#define DEFAULT_STACK_SIZE (1024 * 1024)
 
 int pthread_attr_init(pthread_attr_t* attr) {
-  *attr = gDefaultPthreadAttr;
+  attr->flags = 0;
+  attr->stack_base = NULL;
+  attr->stack_size = DEFAULT_STACK_SIZE;
+  attr->guard_size = PAGE_SIZE;
+  attr->sched_policy = SCHED_NORMAL;
+  attr->sched_priority = 0;
   return 0;
 }
 
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 63071d9..a17c37d 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -55,8 +55,7 @@
     char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
 } pthread_internal_t;
 
-int _init_thread(pthread_internal_t* thread, pid_t kernel_id, const pthread_attr_t* attr,
-                 void* stack_base, bool add_to_thread_list);
+int _init_thread(pthread_internal_t* thread, pid_t kernel_id, bool add_to_thread_list);
 void _pthread_internal_add( pthread_internal_t*  thread );
 pthread_internal_t* __get_thread(void);
 
@@ -65,7 +64,6 @@
 #define PTHREAD_ATTR_FLAG_DETACHED      0x00000001
 #define PTHREAD_ATTR_FLAG_USER_STACK    0x00000002
 
-extern __LIBC_HIDDEN__ const pthread_attr_t gDefaultPthreadAttr;
 extern pthread_internal_t* gThreadList;
 extern pthread_mutex_t gThreadListLock;