Initialize TLS before any application code is run.

Since e19d702b8e, 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
This commit is contained in:
Evgeniy Stepanov
2012-03-22 18:01:53 +04:00
parent d5099016f7
commit 1a78fbb5c8
6 changed files with 48 additions and 27 deletions

View File

@@ -2054,10 +2054,6 @@ static void parse_preloads(const char *path, char *delim)
}
}
#define ANDROID_TLS_SLOTS BIONIC_TLS_SLOTS
static void * __tls_area[ANDROID_TLS_SLOTS];
/*
* This code is called after the linker has linked itself and
* fixed it's own GOT. It is safe to make references to externs
@@ -2076,18 +2072,6 @@ static unsigned __linker_init_post_relocation(unsigned **elfdata)
const char *ldpath_env = NULL;
const char *ldpreload_env = NULL;
/* Setup a temporary TLS area that is used to get a working
* errno for system calls.
*/
__set_tls(__tls_area);
pid = getpid();
#if TIMING
struct timeval t0, t1;
gettimeofday(&t0, 0);
#endif
/* NOTE: we store the elfdata pointer on a special location
* of the temporary TLS area in order to pass it to
* the C Library's runtime initializer.
@@ -2096,7 +2080,14 @@ static unsigned __linker_init_post_relocation(unsigned **elfdata)
* to point to a different location to ensure that no other
* shared library constructor can access it.
*/
__tls_area[TLS_SLOT_BIONIC_PREINIT] = elfdata;
__libc_init_tls(elfdata);
pid = getpid();
#if TIMING
struct timeval t0, t1;
gettimeofday(&t0, 0);
#endif
/* Initialize environment functions, and get to the ELF aux vectors table */
vecs = linker_env_init(vecs);