1 1.1 joerg /* ===---------- emutls.c - Implements __emutls_get_address ---------------=== 2 1.1 joerg * 3 1.1 joerg * The LLVM Compiler Infrastructure 4 1.1 joerg * 5 1.1 joerg * This file is dual licensed under the MIT and the University of Illinois Open 6 1.1 joerg * Source Licenses. See LICENSE.TXT for details. 7 1.1 joerg * 8 1.1 joerg * ===----------------------------------------------------------------------=== 9 1.1 joerg */ 10 1.1 joerg #include <pthread.h> 11 1.1 joerg #include <stdint.h> 12 1.1 joerg #include <stdlib.h> 13 1.1 joerg #include <string.h> 14 1.1 joerg 15 1.1 joerg #include "int_lib.h" 16 1.1 joerg #include "int_util.h" 17 1.1 joerg 18 1.1 joerg /* Default is not to use posix_memalign, so systems like Android 19 1.1 joerg * can use thread local data without heavier POSIX memory allocators. 20 1.1 joerg */ 21 1.1 joerg #ifndef EMUTLS_USE_POSIX_MEMALIGN 22 1.1 joerg #define EMUTLS_USE_POSIX_MEMALIGN 0 23 1.1 joerg #endif 24 1.1 joerg 25 1.1 joerg /* For every TLS variable xyz, 26 1.1 joerg * there is one __emutls_control variable named __emutls_v.xyz. 27 1.1 joerg * If xyz has non-zero initial value, __emutls_v.xyz's "value" 28 1.1 joerg * will point to __emutls_t.xyz, which has the initial value. 29 1.1 joerg */ 30 1.1 joerg typedef struct __emutls_control { 31 1.1 joerg size_t size; /* size of the object in bytes */ 32 1.1 joerg size_t align; /* alignment of the object in bytes */ 33 1.1 joerg union { 34 1.1 joerg uintptr_t index; /* data[index-1] is the object address */ 35 1.1 joerg void* address; /* object address, when in single thread env */ 36 1.1 joerg } object; 37 1.1 joerg void* value; /* null or non-zero initial value for the object */ 38 1.1 joerg } __emutls_control; 39 1.1 joerg 40 1.1 joerg static __inline void *emutls_memalign_alloc(size_t align, size_t size) { 41 1.1 joerg void *base; 42 1.1 joerg #if EMUTLS_USE_POSIX_MEMALIGN 43 1.1 joerg if (posix_memalign(&base, align, size) != 0) 44 1.1 joerg abort(); 45 1.1 joerg #else 46 1.1 joerg #define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void*)) 47 1.1 joerg char* object; 48 1.1 joerg if ((object = malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL) 49 1.1 joerg abort(); 50 1.1 joerg base = (void*)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES)) 51 1.1 joerg & ~(uintptr_t)(align - 1)); 52 1.1 joerg 53 1.1 joerg ((void**)base)[-1] = object; 54 1.1 joerg #endif 55 1.1 joerg return base; 56 1.1 joerg } 57 1.1 joerg 58 1.1 joerg static __inline void emutls_memalign_free(void *base) { 59 1.1 joerg #if EMUTLS_USE_POSIX_MEMALIGN 60 1.1 joerg free(base); 61 1.1 joerg #else 62 1.1 joerg /* The mallocated address is in ((void**)base)[-1] */ 63 1.1 joerg free(((void**)base)[-1]); 64 1.1 joerg #endif 65 1.1 joerg } 66 1.1 joerg 67 1.1 joerg /* Emulated TLS objects are always allocated at run-time. */ 68 1.1 joerg static __inline void *emutls_allocate_object(__emutls_control *control) { 69 1.1 joerg /* Use standard C types, check with gcc's emutls.o. */ 70 1.1 joerg typedef unsigned int gcc_word __attribute__((mode(word))); 71 1.1 joerg typedef unsigned int gcc_pointer __attribute__((mode(pointer))); 72 1.1 joerg COMPILE_TIME_ASSERT(sizeof(size_t) == sizeof(gcc_word)); 73 1.1 joerg COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer)); 74 1.1 joerg COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void*)); 75 1.1 joerg 76 1.1 joerg size_t size = control->size; 77 1.1 joerg size_t align = control->align; 78 1.1 joerg if (align < sizeof(void*)) 79 1.1 joerg align = sizeof(void*); 80 1.1 joerg /* Make sure that align is power of 2. */ 81 1.1 joerg if ((align & (align - 1)) != 0) 82 1.1 joerg abort(); 83 1.1 joerg 84 1.1 joerg void* base = emutls_memalign_alloc(align, size); 85 1.1 joerg if (control->value) 86 1.1 joerg memcpy(base, control->value, size); 87 1.1 joerg else 88 1.1 joerg memset(base, 0, size); 89 1.1 joerg return base; 90 1.1 joerg } 91 1.1 joerg 92 1.1 joerg static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER; 93 1.1 joerg 94 1.1 joerg static size_t emutls_num_object = 0; /* number of allocated TLS objects */ 95 1.1 joerg 96 1.1 joerg typedef struct emutls_address_array { 97 1.1 joerg uintptr_t size; /* number of elements in the 'data' array */ 98 1.1 joerg void* data[]; 99 1.1 joerg } emutls_address_array; 100 1.1 joerg 101 1.1 joerg static pthread_key_t emutls_pthread_key; 102 1.1 joerg 103 1.1 joerg static void emutls_key_destructor(void* ptr) { 104 1.1 joerg emutls_address_array* array = (emutls_address_array*)ptr; 105 1.1 joerg uintptr_t i; 106 1.1 joerg for (i = 0; i < array->size; ++i) { 107 1.1 joerg if (array->data[i]) 108 1.1 joerg emutls_memalign_free(array->data[i]); 109 1.1 joerg } 110 1.1 joerg free(ptr); 111 1.1 joerg } 112 1.1 joerg 113 1.1 joerg static void emutls_init(void) { 114 1.1 joerg if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0) 115 1.1 joerg abort(); 116 1.1 joerg } 117 1.1 joerg 118 1.1 joerg /* Returns control->object.index; set index if not allocated yet. */ 119 1.1 joerg static __inline uintptr_t emutls_get_index(__emutls_control *control) { 120 1.1 joerg uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE); 121 1.1 joerg if (!index) { 122 1.1 joerg static pthread_once_t once = PTHREAD_ONCE_INIT; 123 1.1 joerg pthread_once(&once, emutls_init); 124 1.1 joerg pthread_mutex_lock(&emutls_mutex); 125 1.1 joerg index = control->object.index; 126 1.1 joerg if (!index) { 127 1.1 joerg index = ++emutls_num_object; 128 1.1 joerg __atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE); 129 1.1 joerg } 130 1.1 joerg pthread_mutex_unlock(&emutls_mutex); 131 1.1 joerg } 132 1.1 joerg return index; 133 1.1 joerg } 134 1.1 joerg 135 1.1 joerg /* Updates newly allocated thread local emutls_address_array. */ 136 1.1 joerg static __inline void emutls_check_array_set_size(emutls_address_array *array, 137 1.1 joerg uintptr_t size) { 138 1.1 joerg if (array == NULL) 139 1.1 joerg abort(); 140 1.1 joerg array->size = size; 141 1.1 joerg pthread_setspecific(emutls_pthread_key, (void*)array); 142 1.1 joerg } 143 1.1 joerg 144 1.1 joerg /* Returns the new 'data' array size, number of elements, 145 1.1 joerg * which must be no smaller than the given index. 146 1.1 joerg */ 147 1.1 joerg static __inline uintptr_t emutls_new_data_array_size(uintptr_t index) { 148 1.1 joerg /* Need to allocate emutls_address_array with one extra slot 149 1.1 joerg * to store the data array size. 150 1.1 joerg * Round up the emutls_address_array size to multiple of 16. 151 1.1 joerg */ 152 1.1 joerg return ((index + 1 + 15) & ~((uintptr_t)15)) - 1; 153 1.1 joerg } 154 1.1 joerg 155 1.1 joerg /* Returns the thread local emutls_address_array. 156 1.1 joerg * Extends its size if necessary to hold address at index. 157 1.1 joerg */ 158 1.1 joerg static __inline emutls_address_array * 159 1.1 joerg emutls_get_address_array(uintptr_t index) { 160 1.1 joerg emutls_address_array* array = pthread_getspecific(emutls_pthread_key); 161 1.1 joerg if (array == NULL) { 162 1.1 joerg uintptr_t new_size = emutls_new_data_array_size(index); 163 1.1 joerg array = calloc(new_size + 1, sizeof(void*)); 164 1.1 joerg emutls_check_array_set_size(array, new_size); 165 1.1 joerg } else if (index > array->size) { 166 1.1 joerg uintptr_t orig_size = array->size; 167 1.1 joerg uintptr_t new_size = emutls_new_data_array_size(index); 168 1.1 joerg array = realloc(array, (new_size + 1) * sizeof(void*)); 169 1.1 joerg if (array) 170 1.1 joerg memset(array->data + orig_size, 0, 171 1.1 joerg (new_size - orig_size) * sizeof(void*)); 172 1.1 joerg emutls_check_array_set_size(array, new_size); 173 1.1 joerg } 174 1.1 joerg return array; 175 1.1 joerg } 176 1.1 joerg 177 1.1 joerg void* __emutls_get_address(__emutls_control* control) { 178 1.1 joerg uintptr_t index = emutls_get_index(control); 179 1.1 joerg emutls_address_array* array = emutls_get_address_array(index); 180 1.1 joerg if (array->data[index - 1] == NULL) 181 1.1 joerg array->data[index - 1] = emutls_allocate_object(control); 182 1.1 joerg return array->data[index - 1]; 183 1.1 joerg } 184