source: mainline/uspace/lib/c/generic/tls.c@ 99d3123

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

Remove undefined references to main program from shared libc.

  • 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#include "private/libc.h"
48
49#ifdef CONFIG_RTLD
50#include <rtld/rtld.h>
51#endif
52
53#if !defined(CONFIG_TLS_VARIANT_1) && !defined(CONFIG_TLS_VARIANT_2)
54#error Unknown TLS variant.
55#endif
56
57/** Get address of static TLS block */
58void *tls_get(void)
59{
60#ifdef CONFIG_RTLD
61 assert(runtime_env == NULL);
62#endif
63
64 const elf_segment_header_t *tls =
65 elf_get_phdr(__progsymbols.elfstart, PT_TLS);
66
67 if (tls == NULL)
68 return NULL;
69
70#ifdef CONFIG_TLS_VARIANT_1
71 return (uint8_t *)__tcb_get() + ALIGN_UP(sizeof(tcb_t), tls->p_align);
72#else /* CONFIG_TLS_VARIANT_2 */
73 return (uint8_t *)__tcb_get() - ALIGN_UP(tls->p_memsz, tls->p_align);
74#endif
75}
76
77/** Create TLS (Thread Local Storage) data structures.
78 *
79 * @return Pointer to TCB.
80 */
81tcb_t *tls_make(void)
82{
83 void *data;
84 tcb_t *tcb;
85
86#ifdef CONFIG_RTLD
87 if (runtime_env != NULL)
88 return rtld_tls_make(runtime_env);
89#endif
90
91 const elf_segment_header_t *tls =
92 elf_get_phdr(__progsymbols.elfstart, PT_TLS);
93 if (tls == NULL)
94 return NULL;
95
96 uintptr_t bias = elf_get_bias(__progsymbols.elfstart);
97 size_t align = max(tls->p_align, _Alignof(tcb_t));
98
99#ifdef CONFIG_TLS_VARIANT_1
100 tcb = tls_alloc_arch(
101 ALIGN_UP(sizeof(tcb_t), align) + tls->p_memsz, align);
102 data = (void *) tcb + ALIGN_UP(sizeof(tcb_t), align);
103#else
104 tcb = tls_alloc_arch(
105 ALIGN_UP(tls->p_memsz, align) + sizeof(tcb_t), align);
106 data = (void *) tcb - ALIGN_UP(tls->p_memsz, tls->p_align);
107#endif
108
109 /*
110 * Copy thread local data from the initialization image.
111 */
112 memcpy(data, (void *)(tls->p_vaddr + bias), tls->p_filesz);
113 /*
114 * Zero out the thread local uninitialized data.
115 */
116 memset(data + tls->p_filesz, 0, tls->p_memsz - tls->p_filesz);
117
118 return tcb;
119}
120
121void tls_free(tcb_t *tcb)
122{
123#ifdef CONFIG_RTLD
124 free(tcb->dtv);
125
126 if (runtime_env != NULL) {
127 tls_free_arch(tcb, runtime_env->tls_size, runtime_env->tls_align);
128 return;
129 }
130#endif
131 const elf_segment_header_t *tls =
132 elf_get_phdr(__progsymbols.elfstart, PT_TLS);
133
134 assert(tls != NULL);
135 tls_free_arch(tcb,
136 ALIGN_UP(tls->p_memsz, tls->p_align) + sizeof(tcb_t),
137 max(tls->p_align, _Alignof(tcb_t)));
138}
139
140#ifdef CONFIG_TLS_VARIANT_1
141/** Allocate TLS variant 1 data structures.
142 *
143 * @param data Start of TLS section. This is an output argument.
144 * @param size Size of tdata + tbss section.
145 * @return Pointer to tcb_t structure.
146 */
147tcb_t *tls_alloc_variant_1(size_t size, size_t align)
148{
149 tcb_t *tcb = memalign(align, size);
150 if (!tcb)
151 return NULL;
152 memset(tcb, 0, sizeof(tcb_t));
153 return tcb;
154}
155
156/** Free TLS variant I data structures.
157 *
158 * @param tcb Pointer to TCB structure.
159 * @param size This argument is ignored.
160 */
161void tls_free_variant_1(tcb_t *tcb, size_t size, size_t align)
162{
163 free(tcb);
164}
165#endif
166
167#ifdef CONFIG_TLS_VARIANT_2
168/** Allocate TLS variant II data structures.
169 *
170 * @param data Pointer to pointer to thread local data. This is
171 * actually an output argument.
172 * @param size Size of thread local data.
173 * @param align Alignment of thread local data.
174 * @return Pointer to TCB structure.
175 */
176tcb_t *tls_alloc_variant_2(size_t size, size_t align)
177{
178 void *data = memalign(align, size);
179 if (data == NULL)
180 return NULL;
181
182 tcb_t *tcb = (tcb_t *) (data + size - sizeof(tcb_t));
183 memset(tcb, 0, sizeof(tcb_t));
184 tcb->self = tcb;
185 return tcb;
186}
187
188/** Free TLS variant II data structures.
189 *
190 * @param tcb Pointer to TCB structure.
191 * @param size Size of thread local data.
192 * @param align Alignment of thread local data.
193 */
194void tls_free_variant_2(tcb_t *tcb, size_t size, size_t align)
195{
196 if (tcb != NULL) {
197 void *start = ((void *) tcb) + sizeof(tcb_t) - size;
198 free(start);
199 }
200}
201#endif
202
203/** @}
204 */
Note: See TracBrowser for help on using the repository browser.