Annotation of src/lib/libc/tls/tls.c, Revision 1.8
1.8 ! chs 1: /* $NetBSD: tls.c,v 1.7 2013/08/19 22:14:37 matt 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.8 ! chs 33: __RCSID("$NetBSD: tls.c,v 1.7 2013/08/19 22:14:37 matt 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>
48: #include <stddef.h>
49: #include <stdlib.h>
50: #include <string.h>
51: #include <unistd.h>
52:
53: __dso_hidden void __libc_static_tls_setup(void);
54:
55: static const void *tls_initaddr;
56: static size_t tls_initsize;
57: static size_t tls_size;
58: static size_t tls_allocation;
59: static void *initial_thread_tcb;
60:
1.4 skrll 61: void * __libc_tls_get_addr(void);
62:
63: __weak_alias(__tls_get_addr, __libc_tls_get_addr)
1.1 joerg 64: #ifdef __i386__
1.4 skrll 65: __weak_alias(___tls_get_addr, __libc_tls_get_addr)
1.1 joerg 66: #endif
67:
1.4 skrll 68: void *
69: __libc_tls_get_addr(void)
70: {
71:
72: abort();
1.5 he 73: /* NOTREACHED */
1.4 skrll 74: }
75:
1.1 joerg 76: __weak_alias(_rtld_tls_allocate, __libc_rtld_tls_allocate)
77:
78: struct tls_tcb *
79: _rtld_tls_allocate(void)
80: {
81: struct tls_tcb *tcb;
82: uint8_t *p;
83:
84: if (initial_thread_tcb == NULL) {
85: #ifdef __HAVE_TLS_VARIANT_II
86: tls_size = roundup2(tls_size, sizeof(void *));
87: #endif
88: tls_allocation = tls_size + sizeof(*tcb);
89:
90: initial_thread_tcb = p = mmap(NULL, tls_allocation,
91: PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
92: } else {
93: p = calloc(1, tls_allocation);
94: }
95: if (p == NULL) {
96: static const char msg[] = "TLS allocation failed, terminating\n";
97: write(STDERR_FILENO, msg, sizeof(msg));
98: _exit(127);
99: }
100: #ifdef __HAVE_TLS_VARIANT_I
101: /* LINTED */
102: tcb = (struct tls_tcb *)p;
103: p += sizeof(struct tls_tcb);
104: #else
105: /* LINTED tls_size is rounded above */
106: tcb = (struct tls_tcb *)(p + tls_size);
107: tcb->tcb_self = tcb;
108: #endif
109: memcpy(p, tls_initaddr, tls_initsize);
110:
111: return tcb;
112: }
113:
114: __weak_alias(_rtld_tls_free, __libc_rtld_tls_free)
115:
116: void
117: _rtld_tls_free(struct tls_tcb *tcb)
118: {
119: uint8_t *p;
120:
121: #ifdef __HAVE_TLS_VARIANT_I
122: /* LINTED */
123: p = (uint8_t *)tcb;
124: #else
125: /* LINTED */
126: p = (uint8_t *)tcb - tls_size;
127: #endif
128: if (p == initial_thread_tcb)
129: munmap(p, tls_allocation);
130: else
131: free(p);
132: }
133:
134: __weakref_visible int rtld_DYNAMIC __weak_reference(_DYNAMIC);
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) {
143: if (phdr->p_type != PT_TLS)
144: continue;
145: tls_initaddr = (void *)(phdr->p_vaddr + data->dlpi_addr);
146: tls_initsize = phdr->p_filesz;
147: tls_size = phdr->p_memsz;
148: }
149: return 0;
150: }
151:
152: void
153: __libc_static_tls_setup(void)
154: {
155: struct tls_tcb *tcb;
156:
1.6 matt 157: if (&rtld_DYNAMIC != NULL) {
1.1 joerg 158: return;
1.6 matt 159: }
1.1 joerg 160:
161: dl_iterate_phdr(__libc_static_tls_setup_cb, NULL);
162:
163: tcb = _rtld_tls_allocate();
1.3 matt 164: #ifdef __HAVE___LWP_SETTCB
165: __lwp_settcb(tcb);
166: #else
1.1 joerg 167: _lwp_setprivate(tcb);
1.3 matt 168: #endif
1.1 joerg 169: }
170:
171: #endif /* __HAVE_TLS_VARIANT_I || __HAVE_TLS_VARIANT_II */
CVSweb <webmaster@jp.NetBSD.org>