From a2db50d5d7fa67b297eddd1c0549f08ea4b6a950 Mon Sep 17 00:00:00 2001
From: Yabin Cui <yabinc@google.com>
Date: Fri, 20 Mar 2015 10:58:04 -0700
Subject: [PATCH] Fix alignment error for pthread_internal_t/pthread stack.

aligned attribute can only control compiler's behavior, but we
are manually allocating pthread_internal_t. So we need to make
sure of alignment manually.

Change-Id: Iea4c46eadf10dfd15dc955c5f41cf6063cfd8536
---
 libc/bionic/pthread_create.cpp | 11 ++++++-----
 libc/bionic/pthread_internal.h |  2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index a4bd054c7..5389f144f 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -162,15 +162,16 @@ static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp,
   }
 
   // Mapped space(or user allocated stack) is used for:
-  //   thread_internal_t
+  //   pthread_internal_t
   //   thread stack (including guard page)
-  stack_top -= sizeof(pthread_internal_t);
+
+  // To safely access the pthread_internal_t and thread stack, we need to find a 16-byte aligned boundary.
+  stack_top = reinterpret_cast<uint8_t*>(
+                (reinterpret_cast<uintptr_t>(stack_top) - sizeof(pthread_internal_t)) & ~0xf);
+
   pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
   attr->stack_size = stack_top - reinterpret_cast<uint8_t*>(attr->stack_base);
 
-  // No need to check stack_top alignment. The size of pthread_internal_t is 16-bytes aligned,
-  // and user allocated stack is guaranteed by pthread_attr_setstack.
-
   thread->mmap_size = mmap_size;
   thread->attr = *attr;
   __init_tls(thread);
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 538e0daaf..13964c2d8 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -103,7 +103,7 @@ struct pthread_internal_t {
    */
 #define __BIONIC_DLERROR_BUFFER_SIZE 512
   char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
-} __attribute__((aligned(16))); // Align it as thread stack top below it should be aligned.
+};
 
 __LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread, bool add_to_thread_list);
 __LIBC_HIDDEN__ void __init_tls(pthread_internal_t* thread);