source: mainline/uspace/lib/c/generic/tls.c@ 8dab988

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8dab988 was 4f205248, checked in by Jiří Zárevúcky <jiri.zarevucky@…>, 7 years ago

Honor TLS alignment.

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
33 *
34 * Support for thread-local storage, as described in:
35 * Drepper U.: ELF Handling For Thread-Local Storage, 2005
36 */
37
38#include <assert.h>
39#include <stddef.h>
40#include <align.h>
41#include <tls.h>
42#include <stdlib.h>
43#include <str.h>
44#include <macros.h>
45#include <elf/elf.h>
46
47#ifdef CONFIG_RTLD
48#include <rtld/rtld.h>
49#endif
50
51#if !defined(CONFIG_TLS_VARIANT_1) && !defined(CONFIG_TLS_VARIANT_2)
52#error Unknown TLS variant.
53#endif
54
55/** Get address of static TLS block */
56void *tls_get(void)
57{
58#ifdef CONFIG_RTLD
59 assert(runtime_env == NULL);
60#endif
61
62 const elf_segment_header_t *tls =
63 elf_get_phdr(__executable_start, PT_TLS);
64
65 if (tls == NULL)
66 return NULL;
67
68#ifdef CONFIG_TLS_VARIANT_1
69 return (uint8_t *)__tcb_get() + ALIGN_UP(sizeof(tcb_t), tls->p_align);
70#else /* CONFIG_TLS_VARIANT_2 */
71 return (uint8_t *)__tcb_get() - ALIGN_UP(tls->p_memsz, tls->p_align);
72#endif
73}
74
75/** Create TLS (Thread Local Storage) data structures.
76 *
77 * @return Pointer to TCB.
78 */
79tcb_t *tls_make(void)
80{
81 void *data;
82 tcb_t *tcb;
83
84#ifdef CONFIG_RTLD
85 if (runtime_env != NULL)
86 return rtld_tls_make(runtime_env);
87#endif
88
89 const elf_segment_header_t *tls =
90 elf_get_phdr(__executable_start, PT_TLS);
91 if (tls == NULL)
92 return NULL;
93
94 uintptr_t bias = elf_get_bias(__executable_start);
95 size_t align = max(tls->p_align, _Alignof(tcb_t));
96
97#ifdef CONFIG_TLS_VARIANT_1
98 tcb = tls_alloc_arch(
99 ALIGN_UP(sizeof(tcb_t), align) + tls->p_memsz, align);
100 data = (void *) tcb + ALIGN_UP(sizeof(tcb_t), align);
101#else
102 tcb = tls_alloc_arch(
103 ALIGN_UP(tls->p_memsz, align) + sizeof(tcb_t), align);
104 data = (void *) tcb - ALIGN_UP(tls->p_memsz, tls->p_align);
105#endif
106
107 /*
108 * Copy thread local data from the initialization image.
109 */
110 memcpy(data, (void *)(tls->p_vaddr + bias), tls->p_filesz);
111 /*
112 * Zero out the thread local uninitialized data.
113 */
114 memset(data + tls->p_filesz, 0, tls->p_memsz - tls->p_filesz);
115
116 return tcb;
117}
118
119void tls_free(tcb_t *tcb)
120{
121#ifdef CONFIG_RTLD
122 free(tcb->dtv);
123
124 if (runtime_env != NULL) {
125 tls_free_arch(tcb, runtime_env->tls_size, runtime_env->tls_align);
126 return;
127 }
128#endif
129 const elf_segment_header_t *tls =
130 elf_get_phdr(__executable_start, PT_TLS);
131
132 assert(tls != NULL);
133 tls_free_arch(tcb,
134 ALIGN_UP(tls->p_memsz, tls->p_align) + sizeof(tcb_t),
135 max(tls->p_align, _Alignof(tcb_t)));
136}
137
138#ifdef CONFIG_TLS_VARIANT_1
139/** Allocate TLS variant 1 data structures.
140 *
141 * @param data Start of TLS section. This is an output argument.
142 * @param size Size of tdata + tbss section.
143 * @return Pointer to tcb_t structure.
144 */
145tcb_t *tls_alloc_variant_1(size_t size, size_t align)
146{
147 tcb_t *tcb = memalign(align, size);
148 if (!tcb)
149 return NULL;
150 memset(tcb, 0, sizeof(tcb_t));
151 return tcb;
152}
153
154/** Free TLS variant I data structures.
155 *
156 * @param tcb Pointer to TCB structure.
157 * @param size This argument is ignored.
158 */
159void tls_free_variant_1(tcb_t *tcb, size_t size, size_t align)
160{
161 free(tcb);
162}
163#endif
164
165#ifdef CONFIG_TLS_VARIANT_2
166/** Allocate TLS variant II data structures.
167 *
168 * @param data Pointer to pointer to thread local data. This is
169 * actually an output argument.
170 * @param size Size of thread local data.
171 * @param align Alignment of thread local data.
172 * @return Pointer to TCB structure.
173 */
174tcb_t *tls_alloc_variant_2(size_t size, size_t align)
175{
176 void *data = memalign(align, size);
177 if (data == NULL)
178 return NULL;
179
180 tcb_t *tcb = (tcb_t *) (data + size - sizeof(tcb_t));
181 memset(tcb, 0, sizeof(tcb_t));
182 tcb->self = tcb;
183 return tcb;
184}
185
186/** Free TLS variant II data structures.
187 *
188 * @param tcb Pointer to TCB structure.
189 * @param size Size of thread local data.
190 * @param align Alignment of thread local data.
191 */
192void tls_free_variant_2(tcb_t *tcb, size_t size, size_t align)
193{
194 if (tcb != NULL) {
195 void *start = ((void *) tcb) + sizeof(tcb_t) - size;
196 free(start);
197 }
198}
199#endif
200
201/** @}
202 */
Note: See TracBrowser for help on using the repository browser.