/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped * in memory. Beware: all writes to libc globals from this function will * apply to linker-private copies and will not be visible from libc later on. * * Note: this function creates a pthread_internal_t for the initial thread and * stores the pointer in TLS, but does not add it to pthread's thread list. This * has to be done later from libc itself (see __libc_init_common). * * This function also stores a pointer to the kernel argument block in a TLS slot to be * picked up by the libc constructor. */ void __libc_init_tls(KernelArgumentBlock& args) { __libc_auxv = args.auxv; static void* tls[BIONIC_TLS_SLOTS]; static pthread_internal_t main_thread; main_thread.tls = tls; // Tell the kernel to clear our tid field when we exit, so we're like any other pthread. // As a side-effect, this tells us our pid (which is the same as the main thread's tid). main_thread.tid = __set_tid_address(&main_thread.tid); main_thread.set_cached_pid(main_thread.tid); // Work out the extent of the main thread's stack. uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE; size_t stack_size = get_main_thread_stack_size(); void* stack_bottom = reinterpret_cast<void*>(stack_top - stack_size); // We don't want to free the main thread's stack even when the main thread exits // because things like environment variables with global scope live on it. pthread_attr_init(&main_thread.attr); pthread_attr_setstack(&main_thread.attr, stack_bottom, stack_size); main_thread.attr.flags = PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK | PTHREAD_ATTR_FLAG_MAIN_THREAD; __init_thread(&main_thread, false); __init_tls(&main_thread); __set_tls(main_thread.tls); tls[TLS_SLOT_BIONIC_PREINIT] = &args; __init_alternate_signal_stack(&main_thread); }
/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped * in memory. Beware: all writes to libc globals from this function will * apply to linker-private copies and will not be visible from libc later on. * * Note: this function creates a pthread_internal_t for the initial thread and * stores the pointer in TLS, but does not add it to pthread's gThreadList. This * has to be done later from libc itself (see __libc_init_common). * * This function also stores a pointer to the kernel argument block in a TLS slot to be * picked up by the libc constructor. */ void __libc_init_tls(KernelArgumentBlock& args) { __libc_auxv = args.auxv; uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE; size_t stack_size = get_main_thread_stack_size(); uintptr_t stack_bottom = stack_top - stack_size; static void* tls[BIONIC_TLS_SLOTS]; static pthread_internal_t thread; thread.tid = gettid(); thread.tls = tls; pthread_attr_init(&thread.attr); pthread_attr_setstack(&thread.attr, (void*) stack_bottom, stack_size); _init_thread(&thread, false); __init_tls(&thread); tls[TLS_SLOT_BIONIC_PREINIT] = &args; }