Initialize TLS before any application code is run.
Since e19d702b8e33, dlsym and friends use recursive mutexes that
require the current thread id, which is not available before the libc
constructor. This prevents us from using dlsym() in .preinit_array.
This change moves TLS initialization from libc constructor to the earliest
possible point - immediately after linker itself is relocated. As a result,
pthread_internal_t for the initial thread is available from the start.
As a bonus, values stored in TLS in .preinit_array are not lost when libc is
initialized.
Change-Id: Iee5a710ee000173bff63e924adeb4a4c600c1e2d
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index fdfe508..5cad167 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -145,7 +145,7 @@
pthread_mutex_unlock(&gThreadListLock);
}
-static void
+__LIBC_ABI_PRIVATE__ void
_pthread_internal_add( pthread_internal_t* thread )
{
pthread_mutex_lock(&gThreadListLock);
@@ -157,7 +157,7 @@
pthread_mutex_unlock(&gThreadListLock);
}
-pthread_internal_t*
+__LIBC_ABI_PRIVATE__ pthread_internal_t*
__get_thread(void)
{
void** tls = (void**)__get_tls();
@@ -217,6 +217,7 @@
pthread_exit( (void*)func(arg) );
}
+__LIBC_ABI_PRIVATE__
void _init_thread(pthread_internal_t * thread, pid_t kernel_id, pthread_attr_t * attr, void * stack_base)
{
if (attr == NULL) {
@@ -238,8 +239,6 @@
thread->join_count = 0;
thread->cleanup_stack = NULL;
-
- _pthread_internal_add(thread);
}
@@ -371,6 +370,8 @@
_init_thread(thread, tid, (pthread_attr_t*)attr, stack);
+ _pthread_internal_add(thread);
+
if (!madestack)
thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK;