xref: /illumos-gate/usr/src/lib/libc/port/threads/tls.c (revision 66e150d7d3c0cb2de3c45c74612784ffd3e73de6)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "lint.h"
30 #include "thr_uberdata.h"
31 
32 #define	MIN_MOD_SLOTS	16
33 
34 /*
35  * Used to inform libc_init() that we are on the primary link map,
36  * and to cause certain functions (like malloc() and sbrk()) to fail
37  * (with ENOTSUP) when they are called on an alternate link map.
38  */
39 int primary_link_map = 0;
40 
41 #if defined(_LP64)
42 #define	ALIGN	16
43 #else
44 #define	ALIGN	8
45 #endif
46 
47 /*
48  * Grow the TLS module information array as necessary to include the
49  * specified module-id.  tls_modinfo->tls_size must be a power of two.
50  * Return a pointer to the (possibly reallocated) module information array.
51  */
52 static TLS_modinfo *
53 tls_modinfo_alloc(tls_metadata_t *tlsm, ulong_t moduleid)
54 {
55 	tls_t *tls_modinfo = &tlsm->tls_modinfo;
56 	TLS_modinfo *modinfo;
57 	size_t mod_slots;
58 
59 	if ((modinfo = tls_modinfo->tls_data) == NULL ||
60 	    tls_modinfo->tls_size <= moduleid) {
61 		if ((mod_slots = tls_modinfo->tls_size) == 0)
62 			mod_slots = MIN_MOD_SLOTS;
63 		while (mod_slots <= moduleid)
64 			mod_slots *= 2;
65 		modinfo = lmalloc(mod_slots * sizeof (TLS_modinfo));
66 		if (tls_modinfo->tls_data != NULL) {
67 			(void) memcpy(modinfo, tls_modinfo->tls_data,
68 			    tls_modinfo->tls_size * sizeof (TLS_modinfo));
69 			lfree(tls_modinfo->tls_data,
70 			    tls_modinfo->tls_size * sizeof (TLS_modinfo));
71 		}
72 		tls_modinfo->tls_data = modinfo;
73 		tls_modinfo->tls_size = mod_slots;
74 	}
75 	return (modinfo);
76 }
77 
78 /*
79  * This is called from the dynamic linker, before libc_init() is called,
80  * to setup all of the TLS blocks that are available at process startup
81  * and hence must be included as part of the static TLS block.
82  * No locks are needed because we are single-threaded at this point.
83  * We must be careful not to call any function that could possibly
84  * invoke the dynamic linker.  That is, we must only call functions
85  * that are wholly private to libc.
86  */
87 void
88 __tls_static_mods(TLS_modinfo **tlslist, unsigned long statictlssize)
89 {
90 	ulwp_t *oldself = __curthread();
91 	tls_metadata_t *tlsm;
92 	TLS_modinfo **tlspp;
93 	TLS_modinfo *tlsp;
94 	TLS_modinfo *modinfo;
95 	caddr_t data;
96 	caddr_t data_end;
97 	int max_modid;
98 
99 	primary_link_map = 1;		/* inform libc_init */
100 	if (statictlssize == 0)
101 		return;
102 
103 	/*
104 	 * Retrieve whatever dynamic TLS metadata was generated by code
105 	 * running on alternate link maps prior to now (we must be running
106 	 * on the primary link map now since __tls_static_mods() is only
107 	 * called on the primary link map).
108 	 */
109 	tlsm = &__uberdata.tls_metadata;
110 	if (oldself != NULL) {
111 		(void) memcpy(tlsm,
112 		    &oldself->ul_uberdata->tls_metadata, sizeof (*tlsm));
113 		ASSERT(tlsm->static_tls.tls_data == NULL);
114 	}
115 
116 	/*
117 	 * We call lmalloc() to allocate the template even though libc_init()
118 	 * has not yet been called.  lmalloc() must and does deal with this.
119 	 */
120 	ASSERT((statictlssize & (ALIGN - 1)) == 0);
121 	tlsm->static_tls.tls_data = data = lmalloc(statictlssize);
122 	data_end = data + statictlssize;
123 	tlsm->static_tls.tls_size = statictlssize;
124 	/*
125 	 * Initialize the static TLS template.
126 	 * We make no assumptions about the order in memory of the TLS
127 	 * modules we are processing, only that they fit within the
128 	 * total size we are given and that they are self-consistent.
129 	 * We do not assume any order for the moduleid's; we only assume
130 	 * that they are reasonably small integers.
131 	 */
132 	for (max_modid = 0, tlspp = tlslist; (tlsp = *tlspp) != NULL; tlspp++) {
133 		ASSERT(tlsp->tm_flags & TM_FLG_STATICTLS);
134 		ASSERT(tlsp->tm_stattlsoffset > 0);
135 		ASSERT(tlsp->tm_stattlsoffset <= statictlssize);
136 		ASSERT((tlsp->tm_stattlsoffset & (ALIGN - 1)) == 0);
137 		ASSERT(tlsp->tm_filesz <= tlsp->tm_memsz);
138 		ASSERT(tlsp->tm_memsz <= tlsp->tm_stattlsoffset);
139 		if (tlsp->tm_filesz)
140 			(void) memcpy(data_end-tlsp->tm_stattlsoffset,
141 			    tlsp->tm_tlsblock, tlsp->tm_filesz);
142 		if (max_modid < tlsp->tm_modid)
143 			max_modid = tlsp->tm_modid;
144 	}
145 	/*
146 	 * Record the static TLS_modinfo information.
147 	 */
148 	modinfo = tls_modinfo_alloc(tlsm, max_modid);
149 	for (tlspp = tlslist; (tlsp = *tlspp) != NULL; tlspp++)
150 		(void) memcpy(&modinfo[tlsp->tm_modid],
151 		    tlsp, sizeof (*tlsp));
152 
153 	/*
154 	 * Copy the new tls_metadata back to the old, if any,
155 	 * since it will be copied up again in libc_init().
156 	 */
157 	if (oldself != NULL)
158 		(void) memcpy(&oldself->ul_uberdata->tls_metadata,
159 		    tlsm, sizeof (*tlsm));
160 }
161 
162 /*
163  * This is called from the dynamic linker for each module not included
164  * in the static TLS mod list, after the module has been loaded but
165  * before any of the module's init code has been executed.
166  */
167 void
168 __tls_mod_add(TLS_modinfo *tlsp)
169 {
170 	tls_metadata_t *tlsm = &curthread->ul_uberdata->tls_metadata;
171 	ulong_t moduleid = tlsp->tm_modid;
172 	TLS_modinfo *modinfo;
173 
174 	lmutex_lock(&tlsm->tls_lock);
175 	ASSERT(!(tlsp->tm_flags & TM_FLG_STATICTLS));
176 	ASSERT(tlsp->tm_filesz <= tlsp->tm_memsz);
177 	modinfo = tls_modinfo_alloc(tlsm, moduleid);
178 	(void) memcpy(&modinfo[moduleid], tlsp, sizeof (*tlsp));
179 	lmutex_unlock(&tlsm->tls_lock);
180 }
181 
182 /*
183  * Called for each module as it is unloaded from memory by dlclose().
184  */
185 void
186 __tls_mod_remove(TLS_modinfo *tlsp)
187 {
188 	tls_metadata_t *tlsm = &curthread->ul_uberdata->tls_metadata;
189 	ulong_t moduleid = tlsp->tm_modid;
190 	TLS_modinfo *modinfo;
191 
192 	lmutex_lock(&tlsm->tls_lock);
193 	ASSERT(tlsm->tls_modinfo.tls_data != NULL &&
194 	    moduleid < tlsm->tls_modinfo.tls_size);
195 	modinfo = tlsm->tls_modinfo.tls_data;
196 	(void) memset(&modinfo[moduleid], 0, sizeof (TLS_modinfo));
197 	lmutex_unlock(&tlsm->tls_lock);
198 }
199 
200 extern	int	_preexec_exit_handlers();
201 extern	void	libc_init();
202 
203 const Lc_interface tls_rtldinfo[] = {
204 	{CI_VERSION,	(int(*)())CI_V_CURRENT},
205 	{CI_ATEXIT,	(int(*)())_preexec_exit_handlers},
206 	{CI_TLS_MODADD,	(int(*)())__tls_mod_add},
207 	{CI_TLS_MODREM,	(int(*)())__tls_mod_remove},
208 	{CI_TLS_STATMOD, (int(*)())__tls_static_mods},
209 	{CI_THRINIT,	(int(*)())libc_init},
210 	{CI_NULL,	(int(*)())NULL}
211 };
212 
213 /*
214  * Return the address of a TLS variable for the current thread.
215  * Run the constructors for newly-allocated dynamic TLS.
216  */
217 void *
218 slow_tls_get_addr(TLS_index *tls_index)
219 {
220 	ulwp_t *self = curthread;
221 	tls_metadata_t *tlsm = &self->ul_uberdata->tls_metadata;
222 	TLS_modinfo *tlsp;
223 	ulong_t moduleid;
224 	tls_t *tlsent;
225 	caddr_t	base;
226 	void (**initarray)(void);
227 	ulong_t arraycnt = 0;
228 
229 	/*
230 	 * Defer signals until we have finished calling
231 	 * all of the constructors.
232 	 */
233 	sigoff(self);
234 	lmutex_lock(&tlsm->tls_lock);
235 	if ((moduleid = tls_index->ti_moduleid) < self->ul_ntlsent)
236 		tlsent = self->ul_tlsent;
237 	else {
238 		ASSERT(moduleid < tlsm->tls_modinfo.tls_size);
239 		tlsent = lmalloc(tlsm->tls_modinfo.tls_size * sizeof (tls_t));
240 		if (self->ul_tlsent != NULL) {
241 			(void) memcpy(tlsent, self->ul_tlsent,
242 			    self->ul_ntlsent * sizeof (tls_t));
243 			lfree(self->ul_tlsent,
244 			    self->ul_ntlsent * sizeof (tls_t));
245 		}
246 		self->ul_tlsent = tlsent;
247 		self->ul_ntlsent = tlsm->tls_modinfo.tls_size;
248 	}
249 	tlsent += moduleid;
250 	if ((base = tlsent->tls_data) == NULL) {
251 		tlsp = (TLS_modinfo *)tlsm->tls_modinfo.tls_data + moduleid;
252 		if (tlsp->tm_memsz == 0) {	/* dlclose()d module? */
253 			base = NULL;
254 		} else if (tlsp->tm_flags & TM_FLG_STATICTLS) {
255 			/* static TLS is already allocated/initialized */
256 			base = (caddr_t)self - tlsp->tm_stattlsoffset;
257 			tlsent->tls_data = base;
258 			tlsent->tls_size = 0;	/* don't lfree() this space */
259 		} else {
260 			/* allocate/initialize the dynamic TLS */
261 			base = lmalloc(tlsp->tm_memsz);
262 			if (tlsp->tm_filesz != 0)
263 				(void) memcpy(base, tlsp->tm_tlsblock,
264 				    tlsp->tm_filesz);
265 			tlsent->tls_data = base;
266 			tlsent->tls_size = tlsp->tm_memsz;
267 			/* remember the constructors */
268 			arraycnt = tlsp->tm_tlsinitarraycnt;
269 			initarray = tlsp->tm_tlsinitarray;
270 		}
271 	}
272 	lmutex_unlock(&tlsm->tls_lock);
273 
274 	/*
275 	 * Call constructors, if any, in ascending order.
276 	 * We have to do this after dropping tls_lock because
277 	 * we have no idea what the constructors will do.
278 	 * At least we have signals deferred until they are done.
279 	 */
280 	if (arraycnt) {
281 		do {
282 			(**initarray++)();
283 		} while (--arraycnt != 0);
284 	}
285 
286 	if (base == NULL)	/* kludge to get x86/x64 to boot */
287 		base = (caddr_t)self - 512;
288 
289 	sigon(self);
290 	return (base + tls_index->ti_tlsoffset);
291 }
292 
293 #ifdef	TLS_GET_ADDR_IS_WRITTEN_IN_ASSEMBLER
294 /*
295  * For speed, we do not make reference to any static data in this function.
296  * If necessary to do so, we do a tail call to slow_tls_get_addr().
297  */
298 void *
299 __tls_get_addr(TLS_index *tls_index)
300 {
301 	ulwp_t *self = curthread;
302 	tls_t *tlsent = self->ul_tlsent;
303 	ulong_t moduleid;
304 	caddr_t	base;
305 
306 	if ((moduleid = tls_index->ti_moduleid) < self->ul_ntlsent &&
307 	    (base = tlsent[moduleid].tls_data) != NULL)
308 		return (base + tls_index->ti_tlsoffset);
309 
310 	return (slow_tls_get_addr(tls_index));
311 }
312 #endif	/* TLS_GET_ADDR_IS_WRITTEN_IN_ASSEMBLER */
313 
314 /*
315  * This is called by _thrp_setup() to initialize the thread's static TLS.
316  * Constructors for initially allocated static TLS are called here.
317  */
318 void
319 tls_setup()
320 {
321 	ulwp_t *self = curthread;
322 	tls_metadata_t *tlsm = &self->ul_uberdata->tls_metadata;
323 	TLS_modinfo *tlsp;
324 	long moduleid;
325 	ulong_t nmods;
326 
327 	if (tlsm->static_tls.tls_size == 0)	/* no static TLS */
328 		return;
329 
330 	/* static TLS initialization */
331 	(void) memcpy((caddr_t)self - tlsm->static_tls.tls_size,
332 	    tlsm->static_tls.tls_data, tlsm->static_tls.tls_size);
333 
334 	/* call TLS constructors for the static TLS just initialized */
335 	lmutex_lock(&tlsm->tls_lock);
336 	nmods = tlsm->tls_modinfo.tls_size;
337 	for (moduleid = 0; moduleid < nmods; moduleid++) {
338 		/*
339 		 * Resume where we left off in the module array.
340 		 * tls_modinfo.tls_data may have changed since we
341 		 * dropped and reacquired tls_lock, but TLS modules
342 		 * retain their positions in the new array.
343 		 */
344 		tlsp = (TLS_modinfo *)tlsm->tls_modinfo.tls_data + moduleid;
345 		/*
346 		 * Call constructors for this module if there are any
347 		 * to be called and if it is part of the static TLS.
348 		 */
349 		if (tlsp->tm_tlsinitarraycnt != 0 &&
350 		    (tlsp->tm_flags & TM_FLG_STATICTLS)) {
351 			ulong_t arraycnt = tlsp->tm_tlsinitarraycnt;
352 			void (**initarray)(void) = tlsp->tm_tlsinitarray;
353 
354 			/*
355 			 * Call the constructors in ascending order.
356 			 * We must drop tls_lock while doing this because
357 			 * we have no idea what the constructors will do.
358 			 */
359 			lmutex_unlock(&tlsm->tls_lock);
360 			do {
361 				(**initarray++)();
362 			} while (--arraycnt != 0);
363 			lmutex_lock(&tlsm->tls_lock);
364 		}
365 	}
366 	lmutex_unlock(&tlsm->tls_lock);
367 }
368 
369 /*
370  * This is called by _thrp_exit() to deallocate the thread's TLS.
371  * Destructors for all allocated TLS are called here.
372  */
373 void
374 tls_exit()
375 {
376 	ulwp_t *self = curthread;
377 	tls_metadata_t *tlsm = &self->ul_uberdata->tls_metadata;
378 	tls_t *tlsent;
379 	TLS_modinfo *tlsp;
380 	long moduleid;
381 	ulong_t nmods;
382 
383 	if (tlsm->static_tls.tls_size == 0 && self->ul_ntlsent == 0)
384 		return;		/* no TLS */
385 
386 	/*
387 	 * Call TLS destructors for all TLS allocated for this thread.
388 	 */
389 	lmutex_lock(&tlsm->tls_lock);
390 	nmods = tlsm->tls_modinfo.tls_size;
391 	for (moduleid = nmods - 1; moduleid >= 0; --moduleid) {
392 		/*
393 		 * Resume where we left off in the module array.
394 		 * tls_modinfo.tls_data may have changed since we
395 		 * dropped and reacquired tls_lock, but TLS modules
396 		 * retain their positions in the new array.
397 		 */
398 		tlsp = (TLS_modinfo *)tlsm->tls_modinfo.tls_data + moduleid;
399 		/*
400 		 * Call destructors for this module if there are any
401 		 * to be called and if it is part of the static TLS or
402 		 * if the dynamic TLS for the module has been allocated.
403 		 */
404 		if (tlsp->tm_tlsfiniarraycnt != 0 &&
405 		    ((tlsp->tm_flags & TM_FLG_STATICTLS) ||
406 		    (moduleid < self->ul_ntlsent &&
407 		    (tlsent = self->ul_tlsent) != NULL &&
408 		    tlsent[moduleid].tls_data != NULL))) {
409 			ulong_t arraycnt = tlsp->tm_tlsfiniarraycnt;
410 			void (**finiarray)(void) = tlsp->tm_tlsfiniarray;
411 
412 			/*
413 			 * Call the destructors in descending order.
414 			 * We must drop tls_lock while doing this because
415 			 * we have no idea what the destructors will do.
416 			 */
417 			lmutex_unlock(&tlsm->tls_lock);
418 			finiarray += arraycnt;
419 			do {
420 				(**--finiarray)();
421 			} while (--arraycnt != 0);
422 			lmutex_lock(&tlsm->tls_lock);
423 		}
424 	}
425 	lmutex_unlock(&tlsm->tls_lock);
426 
427 	tls_free(self);
428 }
429 
430 /*
431  * We only free the dynamically allocated TLS; the statically
432  * allocated TLS is reused when the ulwp_t is reallocated.
433  */
434 void
435 tls_free(ulwp_t *ulwp)
436 {
437 	ulong_t moduleid;
438 	tls_t *tlsent;
439 	size_t ntlsent;
440 	void *base;
441 	size_t size;
442 
443 	if ((tlsent = ulwp->ul_tlsent) == NULL ||
444 	    (ntlsent = ulwp->ul_ntlsent) == 0)
445 		return;
446 
447 	for (moduleid = 0; moduleid < ntlsent; moduleid++, tlsent++) {
448 		if ((base = tlsent->tls_data) != NULL &&
449 		    (size = tlsent->tls_size) != 0)
450 			lfree(base, size);
451 		tlsent->tls_data = NULL;	/* paranoia */
452 		tlsent->tls_size = 0;
453 	}
454 	lfree(ulwp->ul_tlsent, ntlsent * sizeof (tls_t));
455 	ulwp->ul_tlsent = NULL;
456 	ulwp->ul_ntlsent = 0;
457 }
458