2 * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
3 * Distributed under the terms of the MIT License.
11 #include <support/TLS.h>
15 #include <util/kernel_cpp.h>
21 inline TLSBlock(void* pointer
);
23 inline status_t
Initialize(unsigned dso
);
27 bool IsInvalid() const { return fPointer
== NULL
; }
29 void* operator+(addr_t offset
) const
30 { return (void*)((addr_t
)fPointer
+ offset
); }
40 unsigned Counter() const { return fCounter
; }
41 unsigned Size() const { return fSize
; }
43 void SetCounter(unsigned counter
) { fCounter
= counter
; }
44 void SetSize(unsigned size
) { fSize
= size
; }
51 class DynamicThreadVector
{
53 inline DynamicThreadVector();
57 inline TLSBlock
& operator[](unsigned dso
);
60 bool _DoesExist() const { return *fVector
!= NULL
; }
61 unsigned _Size() const
63 ? fGeneration
->Size() : 0; }
65 unsigned _Generation() const;
67 status_t
_ResizeVector(unsigned minimumSize
);
70 Generation
* fGeneration
;
75 TLSBlockTemplates
* TLSBlockTemplates::fInstance
;
79 TLSBlockTemplate::SetBaseAddress(addr_t baseAddress
)
81 fAddress
= (void*)((addr_t
)fAddress
+ baseAddress
);
86 TLSBlockTemplate::CreateBlock()
88 void* pointer
= malloc(fMemorySize
);
91 memcpy(pointer
, fAddress
, fFileSize
);
92 if (fMemorySize
> fFileSize
)
93 memset((char*)pointer
+ fFileSize
, 0, fMemorySize
- fFileSize
);
94 return TLSBlock(pointer
);
99 TLSBlockTemplates::Get()
101 if (fInstance
== NULL
)
102 fInstance
= new TLSBlockTemplates
;
108 TLSBlockTemplates::Register(const TLSBlockTemplate
& block
)
112 if (!fFreeDSOs
.empty()) {
113 dso
= fFreeDSOs
.back();
114 fFreeDSOs
.pop_back();
115 fTemplates
[dso
] = block
;
117 dso
= fTemplates
.size();
118 fTemplates
.push_back(block
);
121 fTemplates
[dso
].SetGeneration(fGeneration
);
127 TLSBlockTemplates::Unregister(unsigned dso
)
129 if (dso
== unsigned(-1))
133 fFreeDSOs
.push_back(dso
);
138 TLSBlockTemplates::SetBaseAddress(unsigned dso
, addr_t baseAddress
)
140 if (dso
!= unsigned(-1))
141 fTemplates
[dso
].SetBaseAddress(baseAddress
);
146 TLSBlockTemplates::GetGeneration(unsigned dso
) const
148 if (dso
== unsigned(-1))
150 return fTemplates
[dso
].Generation();
155 TLSBlockTemplates::CreateBlock(unsigned dso
)
157 return fTemplates
[dso
].CreateBlock();
161 TLSBlockTemplates::TLSBlockTemplates()
175 TLSBlock::TLSBlock(void* pointer
)
183 TLSBlock::Initialize(unsigned dso
)
185 fPointer
= TLSBlockTemplates::Get().CreateBlock(dso
).fPointer
;
186 return fPointer
!= NULL
? B_OK
: B_NO_MEMORY
;
198 Generation::Generation()
206 DynamicThreadVector::DynamicThreadVector()
208 fVector((TLSBlock
**)tls_address(TLS_DYNAMIC_THREAD_VECTOR
)),
211 if (*fVector
!= NULL
)
212 fGeneration
= (Generation
*)*(void**)*fVector
;
217 DynamicThreadVector::DestroyAll()
219 for (unsigned i
= 0; i
< _Size(); i
++) {
220 TLSBlock
& block
= (*fVector
)[i
+ 1];
221 if (!block
.IsInvalid())
233 DynamicThreadVector::operator[](unsigned dso
)
235 unsigned generation
= TLSBlockTemplates::Get().GetGeneration(-1);
236 if (_Generation() < generation
) {
237 for (unsigned i
= 0; i
< _Size(); i
++) {
238 TLSBlock
& block
= (*fVector
)[i
+ 1];
239 unsigned dsoGeneration
240 = TLSBlockTemplates::Get().GetGeneration(dso
);
241 if (_Generation() < dsoGeneration
&& dsoGeneration
<= generation
)
245 fGeneration
->SetCounter(generation
);
248 if (_Size() <= dso
) {
249 status_t result
= _ResizeVector(dso
+ 1);
254 TLSBlock
& block
= (*fVector
)[dso
+ 1];
255 if (block
.IsInvalid()) {
256 status_t result
= block
.Initialize(dso
);
266 DynamicThreadVector::_Generation() const
268 if (fGeneration
!= NULL
)
269 return fGeneration
->Counter();
275 DynamicThreadVector::_ResizeVector(unsigned minimumSize
)
277 static const unsigned kInitialSize
= 4;
278 unsigned size
= std::max(minimumSize
, kInitialSize
);
279 unsigned oldSize
= _Size();
283 void* newVector
= realloc(*fVector
, (size
+ 1) * sizeof(TLSBlock
));
284 if (newVector
== NULL
)
287 *fVector
= (TLSBlock
*)newVector
;
288 memset(*fVector
+ oldSize
+ 1, 0, (size
- oldSize
) * sizeof(TLSBlock
));
289 if (fGeneration
== NULL
) {
290 fGeneration
= new Generation
;
291 if (fGeneration
== NULL
)
295 *(Generation
**)*fVector
= fGeneration
;
296 fGeneration
->SetSize(size
);
303 get_tls_address(unsigned dso
, addr_t offset
)
305 DynamicThreadVector dynamicThreadVector
;
306 TLSBlock
& block
= dynamicThreadVector
[dso
];
307 if (block
.IsInvalid())
309 return block
+ offset
;
316 DynamicThreadVector().DestroyAll();