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 }