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 #include <atomic> 9 10 #include <runtime_loader/runtime_loader.h> 11 12 #include <support/TLS.h> 13 #include <tls.h> 14 15 #include <assert.h> 16 17 18 struct tls_index { 19 unsigned long int module; 20 unsigned long int offset; 21 }; 22 23 24 static std::atomic<int> gNextSlot(TLS_FIRST_FREE_SLOT); 25 26 27 static inline void** 28 get_tls() 29 { 30 void** tls; 31 __asm__ __volatile__ ("movq %%fs:0, %0" : "=r" (tls)); 32 return tls; 33 } 34 35 36 int32 37 tls_allocate() 38 { 39 if (gNextSlot < TLS_MAX_KEYS) { 40 auto next = gNextSlot++; 41 if (next < TLS_MAX_KEYS) 42 return next; 43 } 44 45 return B_NO_MEMORY; 46 } 47 48 49 void* 50 tls_get(int32 index) 51 { 52 return get_tls()[index]; 53 } 54 55 56 void** 57 tls_address(int32 index) 58 { 59 return get_tls() + index; 60 } 61 62 63 void 64 tls_set(int32 index, void* value) 65 { 66 get_tls()[index] = value; 67 } 68 69 70 extern "C" void* 71 __tls_get_addr(tls_index* ti) 72 { 73 return __gRuntimeLoader->get_tls_address(ti->module, ti->offset); 74 } 75 76