1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #pragma once 30 31 #include <locale.h> 32 #include <mntent.h> 33 #include <stdio.h> 34 #include <sys/cdefs.h> 35 #include <sys/param.h> 36 37 #include "bionic_asm_tls.h" 38 #include "bionic_macros.h" 39 #include "__get_tls.h" 40 #include "grp_pwd.h" 41 42 /** WARNING WARNING WARNING 43 ** 44 ** This header file is *NOT* part of the public Bionic ABI/API and should not 45 ** be used/included by user-serviceable parts of the system (e.g. 46 ** applications). 47 **/ 48 49 class pthread_internal_t; 50 51 // This struct is small, so the linker can allocate a temporary copy on its 52 // stack. It can't be combined with pthread_internal_t because: 53 // - native bridge requires pthread_internal_t to have the same layout across 54 // architectures, and 55 // - On x86, this struct would have to be placed at the front of 56 // pthread_internal_t, moving fields like `tid`. 57 // - We'd like to avoid having a temporary pthread_internal_t object that 58 // needs to be transferred once the final size of static TLS is known. 59 struct bionic_tcb { 60 void* raw_slots_storage[BIONIC_TLS_SLOTS]; 61 62 // Return a reference to a slot given its TP-relative TLS_SLOT_xxx index. 63 // The thread pointer (i.e. __get_tls()) points at &tls_slot(0). tls_slotbionic_tcb64 void*& tls_slot(size_t tpindex) { 65 return raw_slots_storage[tpindex - MIN_TLS_SLOT]; 66 } 67 68 // Initialize the main thread's final object using its bootstrap object. copy_from_bootstrapbionic_tcb69 void copy_from_bootstrap(const bionic_tcb* boot) { 70 // Copy everything. Problematic slots will be reinitialized. 71 *this = *boot; 72 } 73 threadbionic_tcb74 pthread_internal_t* thread() { 75 return static_cast<pthread_internal_t*>(tls_slot(TLS_SLOT_THREAD_ID)); 76 } 77 }; 78 79 /* 80 * Bionic uses some pthread keys internally. All pthread keys used internally 81 * should be created in constructors, except for keys that may be used in or 82 * before constructors. 83 * 84 * We need to manually maintain the count of pthread keys used internally, but 85 * pthread_test should fail if we forget. 86 * 87 * These are the pthread keys currently used internally by libc: 88 * _res_key libc (constructor in BSD code) 89 */ 90 91 #define LIBC_PTHREAD_KEY_RESERVED_COUNT 1 92 93 /* Internally, jemalloc uses a single key for per thread data. */ 94 #define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 1 95 #define BIONIC_PTHREAD_KEY_RESERVED_COUNT (LIBC_PTHREAD_KEY_RESERVED_COUNT + JEMALLOC_PTHREAD_KEY_RESERVED_COUNT) 96 97 /* 98 * Maximum number of pthread keys allocated. 99 * This includes pthread keys used internally and externally. 100 */ 101 #define BIONIC_PTHREAD_KEY_COUNT (BIONIC_PTHREAD_KEY_RESERVED_COUNT + PTHREAD_KEYS_MAX) 102 103 class pthread_key_data_t { 104 public: 105 uintptr_t seq; // Use uintptr_t just for alignment, as we use pointer below. 106 void* data; 107 }; 108 109 // ~3 pages. This struct is allocated as static TLS memory (i.e. at a fixed 110 // offset from the thread pointer). 111 struct bionic_tls { 112 pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT]; 113 114 locale_t locale; 115 116 char basename_buf[MAXPATHLEN]; 117 char dirname_buf[MAXPATHLEN]; 118 119 mntent mntent_buf; 120 char mntent_strings[BUFSIZ]; 121 122 char ptsname_buf[32]; 123 char ttyname_buf[64]; 124 125 char strerror_buf[NL_TEXTMAX]; 126 char strsignal_buf[NL_TEXTMAX]; 127 128 group_state_t group; 129 passwd_state_t passwd; 130 131 // Initialize the main thread's final object using its bootstrap object. copy_from_bootstrapbionic_tls132 void copy_from_bootstrap(const bionic_tls* boot __attribute__((unused))) { 133 // Nothing in bionic_tls needs to be preserved in the transition to the 134 // final TLS objects, so don't copy anything. 135 } 136 }; 137 138 class KernelArgumentBlock; 139 extern "C" void __libc_init_main_thread_early(const KernelArgumentBlock& args, bionic_tcb* temp_tcb); 140 extern "C" void __libc_init_main_thread_late(); 141 extern "C" void __libc_init_main_thread_final(); 142