RTEMS: cpukit/include/rtems/score/tls.h Source File

| RTEMS 5.4-rc2

Loading...
Searching...
No Matches
tls.h
Go to the documentation of this file.
1
9/*
10 * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
11 *
12 * embedded brains GmbH
13 * Dornierstr. 4
14 * 82178 Puchheim
15 * Germany
16 * <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#ifndef _RTEMS_SCORE_TLS_H
24#define _RTEMS_SCORE_TLS_H
25
26#include <rtems/score/cpu.h>
27
28#include <string.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif /* __cplusplus */
33
47extern char _TLS_Data_begin[];
48
49extern char _TLS_Data_end[];
50
51extern char _TLS_Data_size[];
52
53extern char _TLS_BSS_begin[];
54
55extern char _TLS_BSS_end[];
56
57extern char _TLS_BSS_size[];
58
59extern char _TLS_Size[];
60
71extern char _TLS_Alignment[];
72
73 typedef struct {
74 /*
75 * FIXME: Not sure if the generation number type is correct for all
76 * architectures.
77 */
78 uint32_t generation_number;
79
80 void *tls_blocks[1];
81} TLS_Dynamic_thread_vector;
82
83 typedef struct TLS_Thread_control_block {
84#ifdef __i386__
85 struct TLS_Thread_control_block *tcb;
86#else /* !__i386__ */
87 TLS_Dynamic_thread_vector *dtv;
88#if CPU_SIZEOF_POINTER == 4
89 uintptr_t reserved;
90#endif
91#endif /* __i386__ */
92} TLS_Thread_control_block;
93
94 typedef struct {
95 uintptr_t module;
96 uintptr_t offset;
97} TLS_Index;
98
104static inline uintptr_t _TLS_Get_size( void )
105{
106 uintptr_t size;
107
108 /*
109 * We must be careful with using _TLS_Size here since this could lead GCC to
110 * assume that this symbol is not 0 and the tests for 0 will be optimized
111 * away.
112 */
113 size = (uintptr_t) _TLS_Size;
114 RTEMS_OBFUSCATE_VARIABLE( size );
115 return size;
116}
117
125static inline uintptr_t _TLS_Heap_align_up( uintptr_t val )
126{
127 uintptr_t msk = CPU_HEAP_ALIGNMENT - 1;
128
129 return (val + msk) & ~msk;
130}
131
140static inline uintptr_t _TLS_Get_thread_control_block_area_size(
141 uintptr_t alignment
142)
143{
144 return alignment <= sizeof(TLS_Thread_control_block) ?
145 sizeof(TLS_Thread_control_block) : alignment;
146}
147
153uintptr_t _TLS_Get_allocation_size( void );
154
163static inline void *_TLS_Copy_and_clear( void *tls_area )
164{
165 tls_area = memcpy(
166 tls_area,
167 _TLS_Data_begin,
168 (size_t) ((uintptr_t)_TLS_Data_size)
169 );
170
171
172 memset(
173 (char *) tls_area + (size_t)((intptr_t) _TLS_BSS_begin) -
174 (size_t)((intptr_t) _TLS_Data_begin),
175 0,
176 ((size_t) (intptr_t)_TLS_BSS_size)
177 );
178
179 return tls_area;
180}
181
192static inline void *_TLS_Initialize(
193 void *tls_block,
194 TLS_Thread_control_block *tcb,
195 TLS_Dynamic_thread_vector *dtv
196)
197{
198#ifdef __i386__
199 (void) dtv;
200 tcb->tcb = tcb;
201#else
202 tcb->dtv = dtv;
203 dtv->generation_number = 1;
204 dtv->tls_blocks[0] = tls_block;
205#endif
206
207 return _TLS_Copy_and_clear( tls_block );
208}
209
221static inline void *_TLS_TCB_at_area_begin_initialize( void *tls_area )
222{
223 void *tls_block = (char *) tls_area
224 + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
225 TLS_Thread_control_block *tcb = (TLS_Thread_control_block*) tls_area;
226 uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
227 TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
228 ((char *) tls_block + aligned_size);
229
230 return _TLS_Initialize( tls_block, tcb, dtv );
231}
232
244static inline void *_TLS_TCB_before_TLS_block_initialize( void *tls_area )
245{
246 void *tls_block = (char *) tls_area
247 + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
248 TLS_Thread_control_block *tcb = (TLS_Thread_control_block *)
249 ((char *) tls_block - sizeof(*tcb));
250 uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
251 TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
252 ((char *) tls_block + aligned_size);
253
254 return _TLS_Initialize( tls_block, tcb, dtv );
255}
256
268static inline void *_TLS_TCB_after_TLS_block_initialize( void *tls_area )
269{
270 uintptr_t size = (uintptr_t) _TLS_Size;
271 uintptr_t tls_align = (uintptr_t) _TLS_Alignment;
272 uintptr_t tls_mask = tls_align - 1;
273 uintptr_t heap_align = _TLS_Heap_align_up( tls_align );
274 uintptr_t heap_mask = heap_align - 1;
275 TLS_Thread_control_block *tcb = (TLS_Thread_control_block *)
276 ((char *) tls_area + ((size + heap_mask) & ~heap_mask));
277 void *tls_block = (char *) tcb - ((size + tls_mask) & ~tls_mask);
278 TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
279 ((char *) tcb + sizeof(*tcb));
280
281 _TLS_Initialize( tls_block, tcb, dtv );
282
283 return tcb;
284}
285
288#ifdef __cplusplus
289}
290#endif /* __cplusplus */
291
292#endif /* _RTEMS_SCORE_TLS_H */
RTEMS_OBFUSCATE_VARIABLE
#define RTEMS_OBFUSCATE_VARIABLE(_var)
Obfuscates the variable so that the compiler cannot perform optimizations based on the variable value...
Definition: basedefs.h:311
_TLS_Alignment
char _TLS_Alignment[]
The TLS section alignment.
_TLS_Get_allocation_size
uintptr_t _TLS_Get_allocation_size(void)
Return the TLS area allocation size.
Definition: tlsallocsize.c:36
TLS_Dynamic_thread_vector
Definition: tls.h:73
TLS_Index
Definition: tls.h:94
TLS_Thread_control_block
Definition: tls.h:83