RTEMS  5.0.0
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 
61 extern char _TLS_Alignment[];
62 
63 typedef struct {
64  /*
65  * FIXME: Not sure if the generation number type is correct for all
66  * architectures.
67  */
68  uint32_t generation_number;
69 
70  void *tls_blocks[1];
72 
73 typedef struct TLS_Thread_control_block {
74 #ifdef __i386__
75  struct TLS_Thread_control_block *tcb;
76 #else
78  uintptr_t reserved;
79 #endif
81 
82 typedef struct {
83  uintptr_t module;
84  uintptr_t offset;
85 } TLS_Index;
86 
87 static inline uintptr_t _TLS_Get_size( void )
88 {
89  /*
90  * Do not use _TLS_Size here since this will lead GCC to assume that this
91  * symbol is not 0 and the tests for 0 will be optimized away.
92  */
93  return (uintptr_t) _TLS_BSS_end - (uintptr_t) _TLS_Data_begin;
94 }
95 
96 static inline uintptr_t _TLS_Heap_align_up( uintptr_t val )
97 {
98  uintptr_t msk = CPU_HEAP_ALIGNMENT - 1;
99 
100  return (val + msk) & ~msk;
101 }
102 
103 static inline uintptr_t _TLS_Get_thread_control_block_area_size(
104  uintptr_t alignment
105 )
106 {
107  return alignment <= sizeof(TLS_Thread_control_block) ?
108  sizeof(TLS_Thread_control_block) : alignment;
109 }
110 
111 static inline uintptr_t _TLS_Get_allocation_size(
112  uintptr_t size,
113  uintptr_t alignment
114 )
115 {
116  uintptr_t allocation_size = 0;
117 
118  allocation_size += _TLS_Heap_align_up( size );
119  allocation_size += _TLS_Get_thread_control_block_area_size( alignment );
120 
121 #ifndef __i386__
122  allocation_size += sizeof(TLS_Dynamic_thread_vector);
123 #endif
124 
125  return allocation_size;
126 }
127 
128 static inline void *_TLS_Copy_and_clear( void *tls_area )
129 {
130  tls_area = memcpy(
131  tls_area,
132  _TLS_Data_begin,
133  (size_t) ((uintptr_t)_TLS_Data_size)
134  );
135 
136 
137  memset(
138  (char *) tls_area + (size_t)((intptr_t) _TLS_BSS_begin) -
139  (size_t)((intptr_t) _TLS_Data_begin),
140  0,
141  ((size_t) (intptr_t)_TLS_BSS_size)
142  );
143 
144  return tls_area;
145 }
146 
147 static inline void *_TLS_Initialize(
148  void *tls_block,
151 )
152 {
153 #ifdef __i386__
154  (void) dtv;
155  tcb->tcb = tcb;
156 #else
157  tcb->dtv = dtv;
158  dtv->generation_number = 1;
159  dtv->tls_blocks[0] = tls_block;
160 #endif
161 
162  return _TLS_Copy_and_clear( tls_block );
163 }
164 
165 /* Use Variant I, TLS offsets emitted by linker takes the TCB into account */
166 static inline void *_TLS_TCB_at_area_begin_initialize( void *tls_area )
167 {
168  void *tls_block = (char *) tls_area
169  + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
170  TLS_Thread_control_block *tcb = tls_area;
171  uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
173  ((char *) tls_block + aligned_size);
174 
175  return _TLS_Initialize( tls_block, tcb, dtv );
176 }
177 
178 /* Use Variant I, TLS offsets emitted by linker neglects the TCB */
179 static inline void *_TLS_TCB_before_TLS_block_initialize( void *tls_area )
180 {
181  void *tls_block = (char *) tls_area
182  + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
184  ((char *) tls_block - sizeof(*tcb));
185  uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
187  ((char *) tls_block + aligned_size);
188 
189  return _TLS_Initialize( tls_block, tcb, dtv );
190 }
191 
192 /* Use Variant II */
193 static inline void *_TLS_TCB_after_TLS_block_initialize( void *tls_area )
194 {
195  uintptr_t size = (uintptr_t) _TLS_Size;
196  uintptr_t tls_align = (uintptr_t) _TLS_Alignment;
197  uintptr_t tls_mask = tls_align - 1;
198  uintptr_t heap_align = _TLS_Heap_align_up( tls_align );
199  uintptr_t heap_mask = heap_align - 1;
201  ((char *) tls_area + ((size + heap_mask) & ~heap_mask));
202  void *tls_block = (char *) tcb - ((size + tls_mask) & ~tls_mask);
204  ((char *) tcb + sizeof(*tcb));
205 
206  _TLS_Initialize( tls_block, tcb, dtv );
207 
208  return tcb;
209 }
210 
213 #ifdef __cplusplus
214 }
215 #endif /* __cplusplus */
216 
217 #endif /* _RTEMS_SCORE_TLS_H */
Definition: tls.h:63
Definition: tls.h:73
Definition: tls.h:82
unsigned size
Definition: tte.h:74