source: rtems/cpukit/score/include/rtems/score/tls.h @ 320faf8e

4.115
Last change on this file since 320faf8e was 320faf8e, checked in by Sebastian Huber <sebastian.huber@…>, on 04/17/14 at 05:57:09

score: Clarify TLS support

  • Property mode set to 100644
File size: 4.4 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreTLS
5 *
6 * @brief Thread-Local Storage (TLS)
7 */
8
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
34/**
35 * @defgroup ScoreTLS Thread-Local Storage (TLS)
36 *
37 * @ingroup Score
38 *
39 * @brief Thread-local storage (TLS) support.
40 *
41 * Variants I and II are according to Ulrich Drepper, "ELF Handling For
42 * Thread-Local Storage".
43 *
44 * @{
45 */
46
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
61extern char _TLS_Alignment[];
62
63typedef 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];
71} TLS_Dynamic_thread_vector;
72
73typedef struct {
74  TLS_Dynamic_thread_vector *dtv;
75  uintptr_t reserved;
76} TLS_Thread_control_block;
77
78typedef struct {
79  uintptr_t module;
80  uintptr_t offset;
81} TLS_Index;
82
83static inline uintptr_t _TLS_Heap_align_up( uintptr_t val )
84{
85  uintptr_t msk = CPU_HEAP_ALIGNMENT - 1;
86
87  return (val + msk) & ~msk;
88}
89
90static inline uintptr_t _TLS_Get_thread_control_block_area_size(
91  uintptr_t alignment
92)
93{
94  return alignment <= sizeof(TLS_Thread_control_block) ?
95    sizeof(TLS_Thread_control_block) : alignment;
96}
97
98static inline uintptr_t _TLS_Get_allocation_size(
99  uintptr_t size,
100  uintptr_t alignment
101)
102{
103  uintptr_t aligned_size = _TLS_Heap_align_up( size );
104
105  return _TLS_Get_thread_control_block_area_size( alignment )
106    + aligned_size + sizeof(TLS_Dynamic_thread_vector);
107}
108
109static inline void *_TLS_Copy_and_clear( void *tls_area )
110{
111  tls_area = memcpy( tls_area, _TLS_Data_begin, (size_t) _TLS_Data_size );
112
113  memset(
114    (char *) tls_area + (size_t) _TLS_BSS_begin - (size_t) _TLS_Data_begin,
115    0,
116    (size_t) _TLS_BSS_size
117  );
118
119  return tls_area;
120}
121
122static inline void *_TLS_Initialize(
123  void *tls_block,
124  TLS_Thread_control_block *tcb,
125  TLS_Dynamic_thread_vector *dtv
126)
127{
128  tcb->dtv = dtv;
129  dtv->generation_number = 1;
130  dtv->tls_blocks[0] = tls_block;
131
132  return _TLS_Copy_and_clear( tls_block );
133}
134
135/* Use Variant I, TLS offsets emitted by linker takes the TCB into account */
136static inline void *_TLS_TCB_at_area_begin_initialize( void *tls_area )
137{
138  void *tls_block = (char *) tls_area
139    + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
140  TLS_Thread_control_block *tcb = tls_area;
141  uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
142  TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
143    ((char *) tls_block + aligned_size);
144
145  return _TLS_Initialize( tls_block, tcb, dtv );
146}
147
148/* Use Variant I, TLS offsets emitted by linker neglects the TCB */
149static inline void *_TLS_TCB_before_TLS_block_initialize( void *tls_area )
150{
151  void *tls_block = (char *) tls_area
152    + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
153  TLS_Thread_control_block *tcb = (TLS_Thread_control_block *)
154    ((char *) tls_block - sizeof(*tcb));
155  uintptr_t aligned_size = _TLS_Heap_align_up( (uintptr_t) _TLS_Size );
156  TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
157    ((char *) tls_block + aligned_size);
158
159  return _TLS_Initialize( tls_block, tcb, dtv );
160}
161
162/* Use Variant II */
163static inline void *_TLS_TCB_after_TLS_block_initialize( void *tls_area )
164{
165  uintptr_t size = (uintptr_t) _TLS_Size;
166  uintptr_t tls_align = (uintptr_t) _TLS_Alignment;
167  uintptr_t tls_mask = tls_align - 1;
168  uintptr_t heap_align = _TLS_Heap_align_up( tls_align );
169  uintptr_t heap_mask = heap_align - 1;
170  TLS_Thread_control_block *tcb = (TLS_Thread_control_block *)
171    ((char *) tls_area + ((size + heap_mask) & ~heap_mask));
172  void *tls_block = (char *) tcb - ((size + tls_mask) & ~tls_mask);
173  TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
174    ((char *) tcb + sizeof(*tcb));
175
176  _TLS_Initialize( tls_block, tcb, dtv );
177
178  return tcb;
179}
180
181/** @} */
182
183#ifdef __cplusplus
184}
185#endif /* __cplusplus */
186
187#endif /* _RTEMS_SCORE_TLS_H */
Note: See TracBrowser for help on using the repository browser.