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 }