RTEMS  5.1
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
31 extern "C" {
32 #endif /* __cplusplus */
33 
47 extern char _TLS_Data_begin[];
48 
49 extern char _TLS_Data_end[];
50 
51 extern char _TLS_Data_size[];
52 
53 extern char _TLS_BSS_begin[];
54 
55 extern char _TLS_BSS_end[];
56 
57 extern char _TLS_BSS_size[];
58 
59 extern char _TLS_Size[];
60 
71 extern 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];
82 
83 typedef struct TLS_Thread_control_block {
84 #ifdef __i386__
85  struct TLS_Thread_control_block *tcb;
86 #else /* !__i386__ */
88 #if CPU_SIZEOF_POINTER == 4
89  uintptr_t reserved;
90 #endif
91 #endif /* __i386__ */
93 
94 typedef struct {
95  uintptr_t module;
96  uintptr_t offset;
97 } TLS_Index;
98 
104 static 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;
115  return size;
116 }
117 
125 static 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 
140 static 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 
153 uintptr_t _TLS_Get_allocation_size( void );
154 
163 static 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 
192 static inline void *_TLS_Initialize(
193  void *tls_block,
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 
221 static 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_area;
226  uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
228  ((char *) tls_block + aligned_size);
229 
230  return _TLS_Initialize( tls_block, tcb, dtv );
231 }
232 
244 static 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 );
249  ((char *) tls_block - sizeof(*tcb));
250  uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
252  ((char *) tls_block + aligned_size);
253 
254  return _TLS_Initialize( tls_block, tcb, dtv );
255 }
256 
268 static 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;
276  ((char *) tls_area + ((size + heap_mask) & ~heap_mask));
277  void *tls_block = (char *) tcb - ((size + tls_mask) & ~tls_mask);
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 */
uintptr_t _TLS_Get_allocation_size(void)
Return the TLS area allocation size.
Definition: tlsallocsize.c:36
Definition: tls.h:73
Definition: tls.h:83
#define RTEMS_OBFUSCATE_VARIABLE(_var)
Obfuscates the variable so that the compiler cannot perform optimizations based on the variable value...
Definition: basedefs.h:311
char _TLS_Alignment[]
The TLS section alignment.
Definition: tls.h:94
unsigned size
Definition: tte.h:74