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
RevLine 
[fa23560]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
[6adb775f]36 */
[fa23560]37
[4f205248]38#include <assert.h>
[582a0b8]39#include <stddef.h>
[118a872]40#include <align.h>
[fa23560]41#include <tls.h>
[38d150e]42#include <stdlib.h>
[19f857a]43#include <str.h>
[4f205248]44#include <macros.h>
[2c4e1cc]45#include <elf/elf.h>
[fa23560]46
[2eadda9]47#include "private/libc.h"
48
[6adb775f]49#ifdef CONFIG_RTLD
50#include <rtld/rtld.h>
51#endif
52
[4f205248]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)
[6adb775f]59{
[91e4567]60#ifdef CONFIG_RTLD
[4f205248]61 assert(runtime_env == NULL);
[91e4567]62#endif
[2c4e1cc]63
64 const elf_segment_header_t *tls =
[2eadda9]65 elf_get_phdr(__progsymbols.elfstart, PT_TLS);
[6adb775f]66
[4f205248]67 if (tls == NULL)
68 return NULL;
69
[e2f26002]70#ifdef CONFIG_TLS_VARIANT_1
[4f205248]71 return (uint8_t *)__tcb_get() + ALIGN_UP(sizeof(tcb_t), tls->p_align);
[e2f26002]72#else /* CONFIG_TLS_VARIANT_2 */
[4f205248]73 return (uint8_t *)__tcb_get() - ALIGN_UP(tls->p_memsz, tls->p_align);
[e2f26002]74#endif
75}
76
[fa23560]77/** Create TLS (Thread Local Storage) data structures.
78 *
79 * @return Pointer to TCB.
80 */
[31399f3]81tcb_t *tls_make(void)
[fa23560]82{
83 void *data;
84 tcb_t *tcb;
[a35b458]85
[6adb775f]86#ifdef CONFIG_RTLD
87 if (runtime_env != NULL)
88 return rtld_tls_make(runtime_env);
89#endif
[a35b458]90
[2c4e1cc]91 const elf_segment_header_t *tls =
[2eadda9]92 elf_get_phdr(__progsymbols.elfstart, PT_TLS);
[2c4e1cc]93 if (tls == NULL)
[0d57c3e]94 return NULL;
[a35b458]95
[2eadda9]96 uintptr_t bias = elf_get_bias(__progsymbols.elfstart);
[4f205248]97 size_t align = max(tls->p_align, _Alignof(tcb_t));
[2c4e1cc]98
[4f205248]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
[2c4e1cc]108
[fa23560]109 /*
110 * Copy thread local data from the initialization image.
111 */
[2c4e1cc]112 memcpy(data, (void *)(tls->p_vaddr + bias), tls->p_filesz);
[fa23560]113 /*
114 * Zero out the thread local uninitialized data.
115 */
[2c4e1cc]116 memset(data + tls->p_filesz, 0, tls->p_memsz - tls->p_filesz);
[fa23560]117
118 return tcb;
119}
120
[31399f3]121void tls_free(tcb_t *tcb)
[fa23560]122{
[3a9414e]123#ifdef CONFIG_RTLD
[d2bb25e7]124 free(tcb->dtv);
[4f205248]125
126 if (runtime_env != NULL) {
127 tls_free_arch(tcb, runtime_env->tls_size, runtime_env->tls_align);
128 return;
129 }
[3a9414e]130#endif
[4f205248]131 const elf_segment_header_t *tls =
[2eadda9]132 elf_get_phdr(__progsymbols.elfstart, PT_TLS);
[4f205248]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)));
[fa23560]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 */
[4f205248]147tcb_t *tls_alloc_variant_1(size_t size, size_t align)
[fa23560]148{
[4f205248]149 tcb_t *tcb = memalign(align, size);
[d2bb25e7]150 if (!tcb)
[0d57c3e]151 return NULL;
[4f205248]152 memset(tcb, 0, sizeof(tcb_t));
[d2bb25e7]153 return tcb;
[fa23560]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 */
[4f205248]161void tls_free_variant_1(tcb_t *tcb, size_t size, size_t align)
[fa23560]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.
[4f205248]173 * @param align Alignment of thread local data.
[fa23560]174 * @return Pointer to TCB structure.
175 */
[4f205248]176tcb_t *tls_alloc_variant_2(size_t size, size_t align)
[fa23560]177{
[4f205248]178 void *data = memalign(align, size);
179 if (data == NULL)
[0d57c3e]180 return NULL;
[fa23560]181
[4f205248]182 tcb_t *tcb = (tcb_t *) (data + size - sizeof(tcb_t));
183 memset(tcb, 0, sizeof(tcb_t));
184 tcb->self = tcb;
[fa23560]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.
[4f205248]192 * @param align Alignment of thread local data.
[fa23560]193 */
[4f205248]194void tls_free_variant_2(tcb_t *tcb, size_t size, size_t align)
[fa23560]195{
[4f205248]196 if (tcb != NULL) {
197 void *start = ((void *) tcb) + sizeof(tcb_t) - size;
198 free(start);
199 }
[fa23560]200}
201#endif
202
203/** @}
204 */
Note: See TracBrowser for help on using the repository browser.