blob: ef95a1c260c16368603f71f6321200b1d8c680d0 [file] [log] [blame]
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +00001/* ===---------- emutls.c - Implements __emutls_get_address ---------------===
2 *
3 * The LLVM Compiler Infrastructure
4 *
5 * This file is dual licensed under the MIT and the University of Illinois Open
6 * Source Licenses. See LICENSE.TXT for details.
7 *
8 * ===----------------------------------------------------------------------===
9 */
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +000010#include <stdint.h>
11#include <stdlib.h>
12#include <string.h>
13
Saleem Abdulrasoold2eb26c2015-10-06 04:33:08 +000014#include "int_lib.h"
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +000015#include "int_util.h"
16
Ryan Prichard1e216a52018-06-12 01:32:26 +000017#ifdef __BIONIC__
18/* There are 4 pthread key cleanup rounds on Bionic. Delay emutls deallocation
19 to round 2. We need to delay deallocation because:
20 - Android versions older than M lack __cxa_thread_atexit_impl, so apps
21 use a pthread key destructor to call C++ destructors.
22 - Apps might use __thread/thread_local variables in pthread destructors.
23 We can't wait until the final two rounds, because jemalloc needs two rounds
24 after the final malloc/free call to free its thread-specific data (see
25 https://reviews.llvm.org/D46978#1107507). */
26#define EMUTLS_SKIP_DESTRUCTOR_ROUNDS 1
27#else
28#define EMUTLS_SKIP_DESTRUCTOR_ROUNDS 0
29#endif
30
Frederich Munch922b6022017-04-25 19:04:19 +000031typedef struct emutls_address_array {
Ryan Prichard1e216a52018-06-12 01:32:26 +000032 uintptr_t skip_destructor_rounds;
Frederich Munch922b6022017-04-25 19:04:19 +000033 uintptr_t size; /* number of elements in the 'data' array */
34 void* data[];
35} emutls_address_array;
36
37static void emutls_shutdown(emutls_address_array *array);
38
39#ifndef _WIN32
40
41#include <pthread.h>
42
43static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER;
44static pthread_key_t emutls_pthread_key;
Yi Kong0c4cf642018-09-20 01:02:13 +000045static bool emutls_key_created = false;
Frederich Munch922b6022017-04-25 19:04:19 +000046
47typedef unsigned int gcc_word __attribute__((mode(word)));
48typedef unsigned int gcc_pointer __attribute__((mode(pointer)));
49
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +000050/* Default is not to use posix_memalign, so systems like Android
51 * can use thread local data without heavier POSIX memory allocators.
52 */
53#ifndef EMUTLS_USE_POSIX_MEMALIGN
54#define EMUTLS_USE_POSIX_MEMALIGN 0
55#endif
56
Saleem Abdulrasool911cfc12015-10-10 21:21:28 +000057static __inline void *emutls_memalign_alloc(size_t align, size_t size) {
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +000058 void *base;
59#if EMUTLS_USE_POSIX_MEMALIGN
60 if (posix_memalign(&base, align, size) != 0)
61 abort();
62#else
63 #define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void*))
64 char* object;
Frederich Munch922b6022017-04-25 19:04:19 +000065 if ((object = (char*)malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL)
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +000066 abort();
67 base = (void*)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES))
68 & ~(uintptr_t)(align - 1));
69
70 ((void**)base)[-1] = object;
71#endif
72 return base;
73}
74
Saleem Abdulrasool911cfc12015-10-10 21:21:28 +000075static __inline void emutls_memalign_free(void *base) {
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +000076#if EMUTLS_USE_POSIX_MEMALIGN
77 free(base);
78#else
79 /* The mallocated address is in ((void**)base)[-1] */
80 free(((void**)base)[-1]);
81#endif
82}
83
Ryan Prichard1e216a52018-06-12 01:32:26 +000084static __inline void emutls_setspecific(emutls_address_array *value) {
85 pthread_setspecific(emutls_pthread_key, (void*) value);
86}
87
88static __inline emutls_address_array* emutls_getspecific() {
89 return (emutls_address_array*) pthread_getspecific(emutls_pthread_key);
90}
91
Frederich Munch922b6022017-04-25 19:04:19 +000092static void emutls_key_destructor(void* ptr) {
Ryan Prichard1e216a52018-06-12 01:32:26 +000093 emutls_address_array *array = (emutls_address_array*)ptr;
94 if (array->skip_destructor_rounds > 0) {
95 /* emutls is deallocated using a pthread key destructor. These
96 * destructors are called in several rounds to accommodate destructor
97 * functions that (re)initialize key values with pthread_setspecific.
98 * Delay the emutls deallocation to accommodate other end-of-thread
99 * cleanup tasks like calling thread_local destructors (e.g. the
100 * __cxa_thread_atexit fallback in libc++abi).
101 */
102 array->skip_destructor_rounds--;
103 emutls_setspecific(array);
104 } else {
105 emutls_shutdown(array);
106 free(ptr);
107 }
Frederich Munch922b6022017-04-25 19:04:19 +0000108}
109
110static __inline void emutls_init(void) {
111 if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0)
112 abort();
Yi Kong0c4cf642018-09-20 01:02:13 +0000113 emutls_key_created = true;
Frederich Munch922b6022017-04-25 19:04:19 +0000114}
115
116static __inline void emutls_init_once(void) {
117 static pthread_once_t once = PTHREAD_ONCE_INIT;
118 pthread_once(&once, emutls_init);
119}
120
121static __inline void emutls_lock() {
122 pthread_mutex_lock(&emutls_mutex);
123}
124
125static __inline void emutls_unlock() {
126 pthread_mutex_unlock(&emutls_mutex);
127}
128
Ryan Prichard31e4a552018-06-12 01:32:25 +0000129#else /* _WIN32 */
Frederich Munch922b6022017-04-25 19:04:19 +0000130
Martell Malonec348a8c2017-05-06 15:13:17 +0000131#include <windows.h>
Frederich Munch922b6022017-04-25 19:04:19 +0000132#include <malloc.h>
133#include <stdio.h>
134#include <assert.h>
Frederich Munch922b6022017-04-25 19:04:19 +0000135
136static LPCRITICAL_SECTION emutls_mutex;
137static DWORD emutls_tls_index = TLS_OUT_OF_INDEXES;
138
139typedef uintptr_t gcc_word;
140typedef void * gcc_pointer;
141
142static void win_error(DWORD last_err, const char *hint) {
143 char *buffer = NULL;
144 if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
145 FORMAT_MESSAGE_FROM_SYSTEM |
146 FORMAT_MESSAGE_MAX_WIDTH_MASK,
147 NULL, last_err, 0, (LPSTR)&buffer, 1, NULL)) {
148 fprintf(stderr, "Windows error: %s\n", buffer);
149 } else {
150 fprintf(stderr, "Unkown Windows error: %s\n", hint);
151 }
152 LocalFree(buffer);
153}
154
155static __inline void win_abort(DWORD last_err, const char *hint) {
156 win_error(last_err, hint);
157 abort();
158}
159
160static __inline void *emutls_memalign_alloc(size_t align, size_t size) {
161 void *base = _aligned_malloc(size, align);
162 if (!base)
163 win_abort(GetLastError(), "_aligned_malloc");
164 return base;
165}
166
167static __inline void emutls_memalign_free(void *base) {
168 _aligned_free(base);
169}
170
171static void emutls_exit(void) {
172 if (emutls_mutex) {
173 DeleteCriticalSection(emutls_mutex);
174 _aligned_free(emutls_mutex);
175 emutls_mutex = NULL;
176 }
177 if (emutls_tls_index != TLS_OUT_OF_INDEXES) {
178 emutls_shutdown((emutls_address_array*)TlsGetValue(emutls_tls_index));
179 TlsFree(emutls_tls_index);
180 emutls_tls_index = TLS_OUT_OF_INDEXES;
181 }
182}
183
184#pragma warning (push)
185#pragma warning (disable : 4100)
186static BOOL CALLBACK emutls_init(PINIT_ONCE p0, PVOID p1, PVOID *p2) {
187 emutls_mutex = (LPCRITICAL_SECTION)_aligned_malloc(sizeof(CRITICAL_SECTION), 16);
188 if (!emutls_mutex) {
189 win_error(GetLastError(), "_aligned_malloc");
190 return FALSE;
191 }
192 InitializeCriticalSection(emutls_mutex);
193
194 emutls_tls_index = TlsAlloc();
195 if (emutls_tls_index == TLS_OUT_OF_INDEXES) {
196 emutls_exit();
197 win_error(GetLastError(), "TlsAlloc");
198 return FALSE;
199 }
200 atexit(&emutls_exit);
201 return TRUE;
202}
203
204static __inline void emutls_init_once(void) {
205 static INIT_ONCE once;
206 InitOnceExecuteOnce(&once, emutls_init, NULL, NULL);
207}
208
209static __inline void emutls_lock() {
210 EnterCriticalSection(emutls_mutex);
211}
212
213static __inline void emutls_unlock() {
214 LeaveCriticalSection(emutls_mutex);
215}
216
217static __inline void emutls_setspecific(emutls_address_array *value) {
218 if (TlsSetValue(emutls_tls_index, (LPVOID) value) == 0)
219 win_abort(GetLastError(), "TlsSetValue");
220}
221
222static __inline emutls_address_array* emutls_getspecific() {
223 LPVOID value = TlsGetValue(emutls_tls_index);
224 if (value == NULL) {
225 const DWORD err = GetLastError();
226 if (err != ERROR_SUCCESS)
227 win_abort(err, "TlsGetValue");
228 }
229 return (emutls_address_array*) value;
230}
231
232/* Provide atomic load/store functions for emutls_get_index if built with MSVC.
233 */
234#if !defined(__ATOMIC_RELEASE)
Martin Storsjobecd2ef2017-08-03 19:04:28 +0000235#include <intrin.h>
Frederich Munch922b6022017-04-25 19:04:19 +0000236
237enum { __ATOMIC_ACQUIRE = 2, __ATOMIC_RELEASE = 3 };
238
239static __inline uintptr_t __atomic_load_n(void *ptr, unsigned type) {
240 assert(type == __ATOMIC_ACQUIRE);
Martin Storsjobecd2ef2017-08-03 19:04:28 +0000241 // These return the previous value - but since we do an OR with 0,
242 // it's equivalent to a plain load.
Frederich Munch922b6022017-04-25 19:04:19 +0000243#ifdef _WIN64
Martin Storsjobecd2ef2017-08-03 19:04:28 +0000244 return InterlockedOr64(ptr, 0);
Frederich Munch922b6022017-04-25 19:04:19 +0000245#else
Martin Storsjobecd2ef2017-08-03 19:04:28 +0000246 return InterlockedOr(ptr, 0);
Frederich Munch922b6022017-04-25 19:04:19 +0000247#endif
248}
249
250static __inline void __atomic_store_n(void *ptr, uintptr_t val, unsigned type) {
251 assert(type == __ATOMIC_RELEASE);
Martin Storsjobecd2ef2017-08-03 19:04:28 +0000252 InterlockedExchangePointer((void *volatile *)ptr, (void *)val);
Frederich Munch922b6022017-04-25 19:04:19 +0000253}
254
Ryan Prichard31e4a552018-06-12 01:32:25 +0000255#endif /* __ATOMIC_RELEASE */
Frederich Munch922b6022017-04-25 19:04:19 +0000256
257#pragma warning (pop)
258
Ryan Prichard31e4a552018-06-12 01:32:25 +0000259#endif /* _WIN32 */
Frederich Munch922b6022017-04-25 19:04:19 +0000260
261static size_t emutls_num_object = 0; /* number of allocated TLS objects */
262
263/* Free the allocated TLS data
264 */
265static void emutls_shutdown(emutls_address_array *array) {
266 if (array) {
267 uintptr_t i;
268 for (i = 0; i < array->size; ++i) {
269 if (array->data[i])
270 emutls_memalign_free(array->data[i]);
271 }
272 }
273}
274
275/* For every TLS variable xyz,
276 * there is one __emutls_control variable named __emutls_v.xyz.
277 * If xyz has non-zero initial value, __emutls_v.xyz's "value"
278 * will point to __emutls_t.xyz, which has the initial value.
279 */
280typedef struct __emutls_control {
281 /* Must use gcc_word here, instead of size_t, to match GCC. When
282 gcc_word is larger than size_t, the upper extra bits are all
283 zeros. We can use variables of size_t to operate on size and
284 align. */
285 gcc_word size; /* size of the object in bytes */
286 gcc_word align; /* alignment of the object in bytes */
287 union {
288 uintptr_t index; /* data[index-1] is the object address */
289 void* address; /* object address, when in single thread env */
290 } object;
291 void* value; /* null or non-zero initial value for the object */
292} __emutls_control;
293
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000294/* Emulated TLS objects are always allocated at run-time. */
Saleem Abdulrasool911cfc12015-10-10 21:21:28 +0000295static __inline void *emutls_allocate_object(__emutls_control *control) {
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000296 /* Use standard C types, check with gcc's emutls.o. */
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000297 COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer));
298 COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void*));
299
300 size_t size = control->size;
301 size_t align = control->align;
Chih-Hung Hsiehc2fab482016-02-04 20:26:00 +0000302 void* base;
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000303 if (align < sizeof(void*))
304 align = sizeof(void*);
305 /* Make sure that align is power of 2. */
306 if ((align & (align - 1)) != 0)
307 abort();
308
Chih-Hung Hsiehc2fab482016-02-04 20:26:00 +0000309 base = emutls_memalign_alloc(align, size);
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000310 if (control->value)
311 memcpy(base, control->value, size);
312 else
313 memset(base, 0, size);
314 return base;
315}
316
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000317
318/* Returns control->object.index; set index if not allocated yet. */
Saleem Abdulrasool911cfc12015-10-10 21:21:28 +0000319static __inline uintptr_t emutls_get_index(__emutls_control *control) {
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000320 uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE);
321 if (!index) {
Frederich Munch922b6022017-04-25 19:04:19 +0000322 emutls_init_once();
323 emutls_lock();
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000324 index = control->object.index;
325 if (!index) {
326 index = ++emutls_num_object;
327 __atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE);
328 }
Frederich Munch922b6022017-04-25 19:04:19 +0000329 emutls_unlock();
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000330 }
331 return index;
332}
333
334/* Updates newly allocated thread local emutls_address_array. */
Saleem Abdulrasool911cfc12015-10-10 21:21:28 +0000335static __inline void emutls_check_array_set_size(emutls_address_array *array,
336 uintptr_t size) {
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000337 if (array == NULL)
338 abort();
339 array->size = size;
Frederich Munch922b6022017-04-25 19:04:19 +0000340 emutls_setspecific(array);
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000341}
342
343/* Returns the new 'data' array size, number of elements,
344 * which must be no smaller than the given index.
345 */
Saleem Abdulrasool911cfc12015-10-10 21:21:28 +0000346static __inline uintptr_t emutls_new_data_array_size(uintptr_t index) {
Ryan Prichard31e4a552018-06-12 01:32:25 +0000347 /* Need to allocate emutls_address_array with extra slots
348 * to store the header.
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000349 * Round up the emutls_address_array size to multiple of 16.
350 */
Ryan Prichard31e4a552018-06-12 01:32:25 +0000351 uintptr_t header_words = sizeof(emutls_address_array) / sizeof(void *);
352 return ((index + header_words + 15) & ~((uintptr_t)15)) - header_words;
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000353}
354
Frederich Munch922b6022017-04-25 19:04:19 +0000355/* Returns the size in bytes required for an emutls_address_array with
356 * N number of elements for data field.
357 */
358static __inline uintptr_t emutls_asize(uintptr_t N) {
359 return N * sizeof(void *) + sizeof(emutls_address_array);
360}
361
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000362/* Returns the thread local emutls_address_array.
363 * Extends its size if necessary to hold address at index.
364 */
Saleem Abdulrasool911cfc12015-10-10 21:21:28 +0000365static __inline emutls_address_array *
366emutls_get_address_array(uintptr_t index) {
Frederich Munch922b6022017-04-25 19:04:19 +0000367 emutls_address_array* array = emutls_getspecific();
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000368 if (array == NULL) {
369 uintptr_t new_size = emutls_new_data_array_size(index);
Frederich Munch922b6022017-04-25 19:04:19 +0000370 array = (emutls_address_array*) malloc(emutls_asize(new_size));
Ryan Prichard1e216a52018-06-12 01:32:26 +0000371 if (array) {
George Burgess IV908dacf2016-04-14 23:58:26 +0000372 memset(array->data, 0, new_size * sizeof(void*));
Ryan Prichard1e216a52018-06-12 01:32:26 +0000373 array->skip_destructor_rounds = EMUTLS_SKIP_DESTRUCTOR_ROUNDS;
374 }
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000375 emutls_check_array_set_size(array, new_size);
376 } else if (index > array->size) {
377 uintptr_t orig_size = array->size;
378 uintptr_t new_size = emutls_new_data_array_size(index);
Frederich Munch922b6022017-04-25 19:04:19 +0000379 array = (emutls_address_array*) realloc(array, emutls_asize(new_size));
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000380 if (array)
381 memset(array->data + orig_size, 0,
382 (new_size - orig_size) * sizeof(void*));
383 emutls_check_array_set_size(array, new_size);
384 }
385 return array;
386}
387
388void* __emutls_get_address(__emutls_control* control) {
389 uintptr_t index = emutls_get_index(control);
Frederich Munch922b6022017-04-25 19:04:19 +0000390 emutls_address_array* array = emutls_get_address_array(index--);
391 if (array->data[index] == NULL)
392 array->data[index] = emutls_allocate_object(control);
393 return array->data[index];
Chih-Hung Hsieh4814b9c2015-08-31 17:14:07 +0000394}
Yi Kong0c4cf642018-09-20 01:02:13 +0000395
396#ifdef __BIONIC__
397/* Called by Bionic on dlclose to delete the emutls pthread key. */
398__attribute__((visibility("hidden")))
399void __emutls_unregister_key(void) {
400 if (emutls_key_created) {
401 pthread_key_delete(emutls_pthread_key);
402 emutls_key_created = false;
403 }
404}
405#endif