1 module rt.tls.arm_eabi; 2 3 pragma(LDC_no_moduleinfo); 4 5 import rtoslink; 6 7 version(LWDR_TLS): 8 9 private { 10 extern(C) { 11 __gshared void* _tdata; /// TLS data (declared in linker script) 12 __gshared void* _tdata_size; /// Size of TLS data 13 __gshared void* _tbss; /// TLS BSS (declared in linker script) 14 __gshared void* _tbss_size; /// Size of TLS BSS 15 } 16 17 /// Wrapper around TLS data defined by linker script 18 pragma(LDC_no_typeinfo) 19 { 20 struct TlsLinkerParams 21 { 22 void* data; 23 size_t dataSize; 24 void* bss; 25 size_t bssSize; 26 size_t fullSize; 27 } 28 } 29 30 /// Get TLS data defined in linker script 31 TlsLinkerParams getTlsLinkerParams() nothrow @nogc 32 { 33 TlsLinkerParams param; 34 param.data = cast(void*)&_tdata; 35 param.dataSize = cast(size_t)&_tdata_size; 36 param.bss = cast(void*)&_tbss; 37 param.bssSize = cast(size_t)&_tbss_size; 38 param.fullSize = param.dataSize + param.bssSize; 39 return param; 40 } 41 42 /// TCB (Thread Control Block) size as defined by ARM EABI. 43 enum ARM_EABI_TCB_SIZE = 8; 44 } 45 46 /// TLS support stores its pointer at index 1 in the TCB (Thread Control Block) 47 enum tlsPointerIndex = 0; 48 49 /// Initialise TLS memory for current thread, return pointer for GC 50 void[] initTLSRanges() nothrow @nogc 51 { 52 TlsLinkerParams tls = getTlsLinkerParams; 53 size_t trueSize = tls.fullSize; 54 void* memory = rtosbackend_heapalloc(trueSize); 55 56 import core.stdc..string : memcpy, memset; 57 58 memset(memory, 0, trueSize); 59 memcpy(memory, tls.data, tls.dataSize); 60 memset(memory + tls.dataSize, 0, tls.bssSize); 61 62 rtosbackend_setTLSPointerCurrThread(memory, tlsPointerIndex); 63 64 return memory[0 .. tls.fullSize]; 65 } 66 67 /// Free TLS memory for current thread 68 void freeTLSRanges() nothrow @nogc 69 { 70 auto memory = rtosbackend_getTLSPointerCurrThread(tlsPointerIndex); 71 rtosbackend_heapfreealloc(memory); 72 } 73 74 /// Get pointer to TLS memory for current thread. Called internally by compiler whenever a TLS variable is accessed. 75 extern(C) void* __aeabi_read_tp() nothrow @nogc 76 { 77 auto ret = rtosbackend_getTLSPointerCurrThread(tlsPointerIndex); 78 return ret; 79 }