source: mainline/uspace/lib/c/generic/tls.c@ d73d992

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d73d992 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
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
[6adb775f]47#ifdef CONFIG_RTLD
48#include <rtld/rtld.h>
49#endif
50
[4f205248]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)
[6adb775f]57{
[91e4567]58#ifdef CONFIG_RTLD
[4f205248]59 assert(runtime_env == NULL);
[91e4567]60#endif
[2c4e1cc]61
62 const elf_segment_header_t *tls =
63 elf_get_phdr(__executable_start, PT_TLS);
[6adb775f]64
[4f205248]65 if (tls == NULL)
66 return NULL;
67
[e2f26002]68#ifdef CONFIG_TLS_VARIANT_1
[4f205248]69 return (uint8_t *)__tcb_get() + ALIGN_UP(sizeof(tcb_t), tls->p_align);
[e2f26002]70#else /* CONFIG_TLS_VARIANT_2 */
[4f205248]71 return (uint8_t *)__tcb_get() - ALIGN_UP(tls->p_memsz, tls->p_align);
[e2f26002]72#endif
73}
74
[fa23560]75/** Create TLS (Thread Local Storage) data structures.
76 *
77 * @return Pointer to TCB.
78 */
[31399f3]79tcb_t *tls_make(void)
[fa23560]80{
81 void *data;
82 tcb_t *tcb;
[a35b458]83
[6adb775f]84#ifdef CONFIG_RTLD
85 if (runtime_env != NULL)
86 return rtld_tls_make(runtime_env);
87#endif
[a35b458]88
[2c4e1cc]89 const elf_segment_header_t *tls =
90 elf_get_phdr(__executable_start, PT_TLS);
91 if (tls == NULL)
[0d57c3e]92 return NULL;
[a35b458]93
[2c4e1cc]94 uintptr_t bias = elf_get_bias(__executable_start);
[4f205248]95 size_t align = max(tls->p_align, _Alignof(tcb_t));
[2c4e1cc]96
[4f205248]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
[2c4e1cc]106
[fa23560]107 /*
108 * Copy thread local data from the initialization image.
109 */
[2c4e1cc]110 memcpy(data, (void *)(tls->p_vaddr + bias), tls->p_filesz);
[fa23560]111 /*
112 * Zero out the thread local uninitialized data.
113 */
[2c4e1cc]114 memset(data + tls->p_filesz, 0, tls->p_memsz - tls->p_filesz);
[fa23560]115
116 return tcb;
117}
118
[31399f3]119void tls_free(tcb_t *tcb)
[fa23560]120{
[3a9414e]121#ifdef CONFIG_RTLD
[d2bb25e7]122 free(tcb->dtv);
[4f205248]123
124 if (runtime_env != NULL) {
125 tls_free_arch(tcb, runtime_env->tls_size, runtime_env->tls_align);
126 return;
127 }
[3a9414e]128#endif
[4f205248]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)));
[fa23560]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 */
[4f205248]145tcb_t *tls_alloc_variant_1(size_t size, size_t align)
[fa23560]146{
[4f205248]147 tcb_t *tcb = memalign(align, size);
[d2bb25e7]148 if (!tcb)
[0d57c3e]149 return NULL;
[4f205248]150 memset(tcb, 0, sizeof(tcb_t));
[d2bb25e7]151 return tcb;
[fa23560]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 */
[4f205248]159void tls_free_variant_1(tcb_t *tcb, size_t size, size_t align)
[fa23560]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.
[4f205248]171 * @param align Alignment of thread local data.
[fa23560]172 * @return Pointer to TCB structure.
173 */
[4f205248]174tcb_t *tls_alloc_variant_2(size_t size, size_t align)
[fa23560]175{
[4f205248]176 void *data = memalign(align, size);
177 if (data == NULL)
[0d57c3e]178 return NULL;
[fa23560]179
[4f205248]180 tcb_t *tcb = (tcb_t *) (data + size - sizeof(tcb_t));
181 memset(tcb, 0, sizeof(tcb_t));
182 tcb->self = tcb;
[fa23560]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.
[4f205248]190 * @param align Alignment of thread local data.
[fa23560]191 */
[4f205248]192void tls_free_variant_2(tcb_t *tcb, size_t size, size_t align)
[fa23560]193{
[4f205248]194 if (tcb != NULL) {
195 void *start = ((void *) tcb) + sizeof(tcb_t) - size;
196 free(start);
197 }
[fa23560]198}
199#endif
200
201/** @}
202 */
Note: See TracBrowser for help on using the repository browser.