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