1 /* 2 * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org. 3 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #ifndef _NO_INLINE_ASM 9 # define _NO_INLINE_ASM 1 10 #endif 11 12 #include <atomic> 13 14 #include <runtime_loader/runtime_loader.h> 15 16 #include <support/TLS.h> 17 #include <tls.h> 18 19 #include <assert.h> 20 21 22 struct tls_index { 23 unsigned long int module; 24 unsigned long int offset; 25 }; 26 27 28 static std::atomic<int> gNextSlot(TLS_FIRST_FREE_SLOT); 29 30 31 static inline void** 32 get_tls() 33 { 34 void** tls; 35 __asm__ __volatile__ ("movq %%fs:0, %0" : "=r" (tls)); 36 return tls; 37 } 38 39 40 int32 41 tls_allocate() 42 { 43 if (gNextSlot < TLS_MAX_KEYS) { 44 auto next = gNextSlot++; 45 if (next < TLS_MAX_KEYS) 46 return next; 47 } 48 49 return B_NO_MEMORY; 50 } 51 52 53 void* 54 tls_get(int32 index) 55 { 56 return get_tls()[index]; 57 } 58 59 60 void** 61 tls_address(int32 index) 62 { 63 return get_tls() + index; 64 } 65 66 67 void 68 tls_set(int32 index, void* value) 69 { 70 get_tls()[index] = value; 71 } 72 73 74 extern "C" void* 75 __tls_get_addr(tls_index* ti) 76 { 77 return __gRuntimeLoader->get_tls_address(ti->module, ti->offset); 78 } 79 80