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