Annotation of src/lib/libc/tls/tls.c, Revision 1.9
1.9 ! joerg 1: /* $NetBSD: tls.c,v 1.8 2014/12/14 23:49:17 chs Exp $ */
1.1 joerg 2:
3: /*-
4: * Copyright (c) 2011 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Joerg Sonnenberger.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: #include <sys/cdefs.h>
1.9 ! joerg 33: __RCSID("$NetBSD: tls.c,v 1.8 2014/12/14 23:49:17 chs Exp $");
1.1 joerg 34:
35: #include "namespace.h"
36:
1.2 joerg 37: #define _rtld_tls_allocate __libc_rtld_tls_allocate
38: #define _rtld_tls_free __libc_rtld_tls_free
39:
1.1 joerg 40: #include <sys/tls.h>
41:
42: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
43:
44: #include <sys/param.h>
45: #include <sys/mman.h>
46: #include <link_elf.h>
47: #include <lwp.h>
1.9 ! joerg 48: #include <stdbool.h>
1.1 joerg 49: #include <stddef.h>
50: #include <stdlib.h>
51: #include <string.h>
52: #include <unistd.h>
53:
54: __dso_hidden void __libc_static_tls_setup(void);
55:
1.9 ! joerg 56: static bool is_dynamic;
1.1 joerg 57: static const void *tls_initaddr;
58: static size_t tls_initsize;
59: static size_t tls_size;
60: static size_t tls_allocation;
61: static void *initial_thread_tcb;
62:
1.4 skrll 63: void * __libc_tls_get_addr(void);
64:
65: __weak_alias(__tls_get_addr, __libc_tls_get_addr)
1.1 joerg 66: #ifdef __i386__
1.4 skrll 67: __weak_alias(___tls_get_addr, __libc_tls_get_addr)
1.1 joerg 68: #endif
69:
1.4 skrll 70: void *
71: __libc_tls_get_addr(void)
72: {
73:
74: abort();
1.5 he 75: /* NOTREACHED */
1.4 skrll 76: }
77:
1.1 joerg 78: __weak_alias(_rtld_tls_allocate, __libc_rtld_tls_allocate)
79:
80: struct tls_tcb *
81: _rtld_tls_allocate(void)
82: {
83: struct tls_tcb *tcb;
84: uint8_t *p;
85:
86: if (initial_thread_tcb == NULL) {
87: #ifdef __HAVE_TLS_VARIANT_II
88: tls_size = roundup2(tls_size, sizeof(void *));
89: #endif
90: tls_allocation = tls_size + sizeof(*tcb);
91:
92: initial_thread_tcb = p = mmap(NULL, tls_allocation,
93: PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
94: } else {
95: p = calloc(1, tls_allocation);
96: }
97: if (p == NULL) {
98: static const char msg[] = "TLS allocation failed, terminating\n";
99: write(STDERR_FILENO, msg, sizeof(msg));
100: _exit(127);
101: }
102: #ifdef __HAVE_TLS_VARIANT_I
103: /* LINTED */
104: tcb = (struct tls_tcb *)p;
105: p += sizeof(struct tls_tcb);
106: #else
107: /* LINTED tls_size is rounded above */
108: tcb = (struct tls_tcb *)(p + tls_size);
109: tcb->tcb_self = tcb;
110: #endif
111: memcpy(p, tls_initaddr, tls_initsize);
112:
113: return tcb;
114: }
115:
116: __weak_alias(_rtld_tls_free, __libc_rtld_tls_free)
117:
118: void
119: _rtld_tls_free(struct tls_tcb *tcb)
120: {
121: uint8_t *p;
122:
123: #ifdef __HAVE_TLS_VARIANT_I
124: /* LINTED */
125: p = (uint8_t *)tcb;
126: #else
127: /* LINTED */
128: p = (uint8_t *)tcb - tls_size;
129: #endif
130: if (p == initial_thread_tcb)
131: munmap(p, tls_allocation);
132: else
133: free(p);
134: }
135:
1.7 matt 136: static int __section(".text.startup")
1.1 joerg 137: __libc_static_tls_setup_cb(struct dl_phdr_info *data, size_t len, void *cookie)
138: {
139: const Elf_Phdr *phdr = data->dlpi_phdr;
140: const Elf_Phdr *phlimit = data->dlpi_phdr + data->dlpi_phnum;
141:
142: for (; phdr < phlimit; ++phdr) {
1.9 ! joerg 143: if (phdr->p_type == PT_INTERP) {
! 144: is_dynamic = true;
! 145: return -1;
! 146: }
1.1 joerg 147: if (phdr->p_type != PT_TLS)
148: continue;
149: tls_initaddr = (void *)(phdr->p_vaddr + data->dlpi_addr);
150: tls_initsize = phdr->p_filesz;
151: tls_size = phdr->p_memsz;
152: }
153: return 0;
154: }
155:
156: void
157: __libc_static_tls_setup(void)
158: {
159: struct tls_tcb *tcb;
160:
1.9 ! joerg 161: dl_iterate_phdr(__libc_static_tls_setup_cb, NULL);
! 162: if (is_dynamic)
1.1 joerg 163: return;
164:
165: tcb = _rtld_tls_allocate();
1.3 matt 166: #ifdef __HAVE___LWP_SETTCB
167: __lwp_settcb(tcb);
168: #else
1.1 joerg 169: _lwp_setprivate(tcb);
1.3 matt 170: #endif
1.1 joerg 171: }
172:
173: #endif /* __HAVE_TLS_VARIANT_I || __HAVE_TLS_VARIANT_II */
CVSweb <webmaster@jp.NetBSD.org>