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