4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include "thr_uberdata.h"
30 #define MIN_MOD_SLOTS 8
33 * Used to inform libc_init() that we are on the primary link map,
34 * and to cause certain functions (like malloc() and sbrk()) to fail
35 * (with ENOTSUP) when they are called on an alternate link map.
37 int primary_link_map
= 0;
46 * Grow the TLS module information array as necessary to include the
47 * specified module-id. tls_modinfo->tls_size must be a power of two.
48 * Return a pointer to the (possibly reallocated) module information array.
51 tls_modinfo_alloc(tls_metadata_t
*tlsm
, ulong_t moduleid
)
53 tls_t
*tls_modinfo
= &tlsm
->tls_modinfo
;
57 if ((modinfo
= tls_modinfo
->tls_data
) == NULL
||
58 tls_modinfo
->tls_size
<= moduleid
) {
59 if ((mod_slots
= tls_modinfo
->tls_size
) == 0)
60 mod_slots
= MIN_MOD_SLOTS
;
61 while (mod_slots
<= moduleid
)
63 modinfo
= lmalloc(mod_slots
* sizeof (TLS_modinfo
));
64 if (tls_modinfo
->tls_data
!= NULL
) {
65 (void) memcpy(modinfo
, tls_modinfo
->tls_data
,
66 tls_modinfo
->tls_size
* sizeof (TLS_modinfo
));
67 lfree(tls_modinfo
->tls_data
,
68 tls_modinfo
->tls_size
* sizeof (TLS_modinfo
));
70 tls_modinfo
->tls_data
= modinfo
;
71 tls_modinfo
->tls_size
= mod_slots
;
77 * This is called from the dynamic linker, before libc_init() is called,
78 * to setup all of the TLS blocks that are available at process startup
79 * and hence must be included as part of the static TLS block.
80 * No locks are needed because we are single-threaded at this point.
81 * We must be careful not to call any function that could possibly
82 * invoke the dynamic linker. That is, we must only call functions
83 * that are wholly private to libc.
86 __tls_static_mods(TLS_modinfo
**tlslist
, unsigned long statictlssize
)
88 ulwp_t
*oldself
= __curthread();
97 primary_link_map
= 1; /* inform libc_init */
98 if (statictlssize
== 0)
102 * Retrieve whatever dynamic TLS metadata was generated by code
103 * running on alternate link maps prior to now (we must be running
104 * on the primary link map now since __tls_static_mods() is only
105 * called on the primary link map).
107 tlsm
= &__uberdata
.tls_metadata
;
108 if (oldself
!= NULL
) {
110 &oldself
->ul_uberdata
->tls_metadata
, sizeof (*tlsm
));
111 ASSERT(tlsm
->static_tls
.tls_data
== NULL
);
115 * We call lmalloc() to allocate the template even though libc_init()
116 * has not yet been called. lmalloc() must and does deal with this.
118 ASSERT((statictlssize
& (ALIGN
- 1)) == 0);
119 tlsm
->static_tls
.tls_data
= data
= lmalloc(statictlssize
);
120 data_end
= data
+ statictlssize
;
121 tlsm
->static_tls
.tls_size
= statictlssize
;
123 * Initialize the static TLS template.
124 * We make no assumptions about the order in memory of the TLS
125 * modules we are processing, only that they fit within the
126 * total size we are given and that they are self-consistent.
127 * We do not assume any order for the moduleid's; we only assume
128 * that they are reasonably small integers.
130 for (max_modid
= 0, tlspp
= tlslist
; (tlsp
= *tlspp
) != NULL
; tlspp
++) {
131 ASSERT(tlsp
->tm_flags
& TM_FLG_STATICTLS
);
132 ASSERT(tlsp
->tm_stattlsoffset
> 0);
133 ASSERT(tlsp
->tm_stattlsoffset
<= statictlssize
);
134 ASSERT((tlsp
->tm_stattlsoffset
& (ALIGN
- 1)) == 0);
135 ASSERT(tlsp
->tm_filesz
<= tlsp
->tm_memsz
);
136 ASSERT(tlsp
->tm_memsz
<= tlsp
->tm_stattlsoffset
);
138 (void) memcpy(data_end
-tlsp
->tm_stattlsoffset
,
139 tlsp
->tm_tlsblock
, tlsp
->tm_filesz
);
140 if (max_modid
< tlsp
->tm_modid
)
141 max_modid
= tlsp
->tm_modid
;
144 * Record the static TLS_modinfo information.
146 modinfo
= tls_modinfo_alloc(tlsm
, max_modid
);
147 for (tlspp
= tlslist
; (tlsp
= *tlspp
) != NULL
; tlspp
++)
148 (void) memcpy(&modinfo
[tlsp
->tm_modid
],
149 tlsp
, sizeof (*tlsp
));
152 * Copy the new tls_metadata back to the old, if any,
153 * since it will be copied up again in libc_init().
156 (void) memcpy(&oldself
->ul_uberdata
->tls_metadata
,
157 tlsm
, sizeof (*tlsm
));
161 * This is called from the dynamic linker for each module not included
162 * in the static TLS mod list, after the module has been loaded but
163 * before any of the module's init code has been executed.
166 __tls_mod_add(TLS_modinfo
*tlsp
)
168 tls_metadata_t
*tlsm
= &curthread
->ul_uberdata
->tls_metadata
;
169 ulong_t moduleid
= tlsp
->tm_modid
;
170 TLS_modinfo
*modinfo
;
172 lmutex_lock(&tlsm
->tls_lock
);
173 ASSERT(!(tlsp
->tm_flags
& TM_FLG_STATICTLS
));
174 ASSERT(tlsp
->tm_filesz
<= tlsp
->tm_memsz
);
175 modinfo
= tls_modinfo_alloc(tlsm
, moduleid
);
176 (void) memcpy(&modinfo
[moduleid
], tlsp
, sizeof (*tlsp
));
177 lmutex_unlock(&tlsm
->tls_lock
);
181 * Called for each module as it is unloaded from memory by dlclose().
184 __tls_mod_remove(TLS_modinfo
*tlsp
)
186 tls_metadata_t
*tlsm
= &curthread
->ul_uberdata
->tls_metadata
;
187 ulong_t moduleid
= tlsp
->tm_modid
;
188 TLS_modinfo
*modinfo
;
190 lmutex_lock(&tlsm
->tls_lock
);
191 ASSERT(tlsm
->tls_modinfo
.tls_data
!= NULL
&&
192 moduleid
< tlsm
->tls_modinfo
.tls_size
);
193 modinfo
= tlsm
->tls_modinfo
.tls_data
;
194 (void) memset(&modinfo
[moduleid
], 0, sizeof (TLS_modinfo
));
195 lmutex_unlock(&tlsm
->tls_lock
);
198 extern int _preexec_exit_handlers();
199 extern void libc_init();
201 const Lc_interface tls_rtldinfo
[] = {
202 {CI_VERSION
, (int(*)())CI_V_CURRENT
},
203 {CI_ATEXIT
, (int(*)())_preexec_exit_handlers
},
204 {CI_TLS_MODADD
, (int(*)())__tls_mod_add
},
205 {CI_TLS_MODREM
, (int(*)())__tls_mod_remove
},
206 {CI_TLS_STATMOD
, (int(*)())__tls_static_mods
},
207 {CI_THRINIT
, (int(*)())libc_init
},
208 {CI_NULL
, (int(*)())NULL
}
212 * Return the address of a TLS variable for the current thread.
213 * Run the constructors for newly-allocated dynamic TLS.
216 slow_tls_get_addr(TLS_index
*tls_index
)
218 ulwp_t
*self
= curthread
;
219 tls_metadata_t
*tlsm
= &self
->ul_uberdata
->tls_metadata
;
224 void (**initarray
)(void);
225 ulong_t arraycnt
= 0;
228 * Defer signals until we have finished calling
229 * all of the constructors.
232 lmutex_lock(&tlsm
->tls_lock
);
233 if ((moduleid
= tls_index
->ti_moduleid
) < self
->ul_ntlsent
)
234 tlsent
= self
->ul_tlsent
;
236 ASSERT(moduleid
< tlsm
->tls_modinfo
.tls_size
);
237 tlsent
= lmalloc(tlsm
->tls_modinfo
.tls_size
* sizeof (tls_t
));
238 if (self
->ul_tlsent
!= NULL
) {
239 (void) memcpy(tlsent
, self
->ul_tlsent
,
240 self
->ul_ntlsent
* sizeof (tls_t
));
241 lfree(self
->ul_tlsent
,
242 self
->ul_ntlsent
* sizeof (tls_t
));
244 self
->ul_tlsent
= tlsent
;
245 self
->ul_ntlsent
= tlsm
->tls_modinfo
.tls_size
;
248 if ((base
= tlsent
->tls_data
) == NULL
) {
249 tlsp
= (TLS_modinfo
*)tlsm
->tls_modinfo
.tls_data
+ moduleid
;
250 if (tlsp
->tm_memsz
== 0) { /* dlclose()d module? */
252 } else if (tlsp
->tm_flags
& TM_FLG_STATICTLS
) {
253 /* static TLS is already allocated/initialized */
254 base
= (caddr_t
)self
- tlsp
->tm_stattlsoffset
;
255 tlsent
->tls_data
= base
;
256 tlsent
->tls_size
= 0; /* don't lfree() this space */
258 /* allocate/initialize the dynamic TLS */
259 base
= lmalloc(tlsp
->tm_memsz
);
260 if (tlsp
->tm_filesz
!= 0)
261 (void) memcpy(base
, tlsp
->tm_tlsblock
,
263 tlsent
->tls_data
= base
;
264 tlsent
->tls_size
= tlsp
->tm_memsz
;
265 /* remember the constructors */
266 arraycnt
= tlsp
->tm_tlsinitarraycnt
;
267 initarray
= tlsp
->tm_tlsinitarray
;
270 lmutex_unlock(&tlsm
->tls_lock
);
273 * Call constructors, if any, in ascending order.
274 * We have to do this after dropping tls_lock because
275 * we have no idea what the constructors will do.
276 * At least we have signals deferred until they are done.
281 } while (--arraycnt
!= 0);
284 if (base
== NULL
) /* kludge to get x86/x64 to boot */
285 base
= (caddr_t
)self
- 512;
288 return (base
+ tls_index
->ti_tlsoffset
);
291 #ifdef TLS_GET_ADDR_IS_WRITTEN_IN_ASSEMBLER
293 * For speed, we do not make reference to any static data in this function.
294 * If necessary to do so, we do a tail call to slow_tls_get_addr().
297 __tls_get_addr(TLS_index
*tls_index
)
299 ulwp_t
*self
= curthread
;
300 tls_t
*tlsent
= self
->ul_tlsent
;
304 if ((moduleid
= tls_index
->ti_moduleid
) < self
->ul_ntlsent
&&
305 (base
= tlsent
[moduleid
].tls_data
) != NULL
)
306 return (base
+ tls_index
->ti_tlsoffset
);
308 return (slow_tls_get_addr(tls_index
));
310 #endif /* TLS_GET_ADDR_IS_WRITTEN_IN_ASSEMBLER */
313 * This is called by _thrp_setup() to initialize the thread's static TLS.
314 * Constructors for initially allocated static TLS are called here.
319 ulwp_t
*self
= curthread
;
320 tls_metadata_t
*tlsm
= &self
->ul_uberdata
->tls_metadata
;
325 if (tlsm
->static_tls
.tls_size
== 0) /* no static TLS */
328 /* static TLS initialization */
329 (void) memcpy((caddr_t
)self
- tlsm
->static_tls
.tls_size
,
330 tlsm
->static_tls
.tls_data
, tlsm
->static_tls
.tls_size
);
332 /* call TLS constructors for the static TLS just initialized */
333 lmutex_lock(&tlsm
->tls_lock
);
334 nmods
= tlsm
->tls_modinfo
.tls_size
;
335 for (moduleid
= 0; moduleid
< nmods
; moduleid
++) {
337 * Resume where we left off in the module array.
338 * tls_modinfo.tls_data may have changed since we
339 * dropped and reacquired tls_lock, but TLS modules
340 * retain their positions in the new array.
342 tlsp
= (TLS_modinfo
*)tlsm
->tls_modinfo
.tls_data
+ moduleid
;
344 * Call constructors for this module if there are any
345 * to be called and if it is part of the static TLS.
347 if (tlsp
->tm_tlsinitarraycnt
!= 0 &&
348 (tlsp
->tm_flags
& TM_FLG_STATICTLS
)) {
349 ulong_t arraycnt
= tlsp
->tm_tlsinitarraycnt
;
350 void (**initarray
)(void) = tlsp
->tm_tlsinitarray
;
353 * Call the constructors in ascending order.
354 * We must drop tls_lock while doing this because
355 * we have no idea what the constructors will do.
357 lmutex_unlock(&tlsm
->tls_lock
);
360 } while (--arraycnt
!= 0);
361 lmutex_lock(&tlsm
->tls_lock
);
364 lmutex_unlock(&tlsm
->tls_lock
);
368 * This is called by _thrp_exit() to deallocate the thread's TLS.
369 * Destructors for all allocated TLS are called here.
374 ulwp_t
*self
= curthread
;
375 tls_metadata_t
*tlsm
= &self
->ul_uberdata
->tls_metadata
;
381 if (tlsm
->static_tls
.tls_size
== 0 && self
->ul_ntlsent
== 0)
385 * Call TLS destructors for all TLS allocated for this thread.
387 lmutex_lock(&tlsm
->tls_lock
);
388 nmods
= tlsm
->tls_modinfo
.tls_size
;
389 for (moduleid
= nmods
- 1; moduleid
>= 0; --moduleid
) {
391 * Resume where we left off in the module array.
392 * tls_modinfo.tls_data may have changed since we
393 * dropped and reacquired tls_lock, but TLS modules
394 * retain their positions in the new array.
396 tlsp
= (TLS_modinfo
*)tlsm
->tls_modinfo
.tls_data
+ moduleid
;
398 * Call destructors for this module if there are any
399 * to be called and if it is part of the static TLS or
400 * if the dynamic TLS for the module has been allocated.
402 if (tlsp
->tm_tlsfiniarraycnt
!= 0 &&
403 ((tlsp
->tm_flags
& TM_FLG_STATICTLS
) ||
404 (moduleid
< self
->ul_ntlsent
&&
405 (tlsent
= self
->ul_tlsent
) != NULL
&&
406 tlsent
[moduleid
].tls_data
!= NULL
))) {
407 ulong_t arraycnt
= tlsp
->tm_tlsfiniarraycnt
;
408 void (**finiarray
)(void) = tlsp
->tm_tlsfiniarray
;
411 * Call the destructors in descending order.
412 * We must drop tls_lock while doing this because
413 * we have no idea what the destructors will do.
415 lmutex_unlock(&tlsm
->tls_lock
);
416 finiarray
+= arraycnt
;
419 } while (--arraycnt
!= 0);
420 lmutex_lock(&tlsm
->tls_lock
);
423 lmutex_unlock(&tlsm
->tls_lock
);
429 * We only free the dynamically allocated TLS; the statically
430 * allocated TLS is reused when the ulwp_t is reallocated.
433 tls_free(ulwp_t
*ulwp
)
441 if ((tlsent
= ulwp
->ul_tlsent
) == NULL
||
442 (ntlsent
= ulwp
->ul_ntlsent
) == 0)
445 for (moduleid
= 0; moduleid
< ntlsent
; moduleid
++, tlsent
++) {
446 if ((base
= tlsent
->tls_data
) != NULL
&&
447 (size
= tlsent
->tls_size
) != 0)
449 tlsent
->tls_data
= NULL
; /* paranoia */
450 tlsent
->tls_size
= 0;
452 lfree(ulwp
->ul_tlsent
, ntlsent
* sizeof (tls_t
));
453 ulwp
->ul_tlsent
= NULL
;
454 ulwp
->ul_ntlsent
= 0;