1 /* $OpenBSD: tib.c,v 1.1 2016/05/07 19:05:22 guenther Exp $ */ 2 /* 3 * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <tib.h> 19 20 #ifndef PIC 21 # include <stdlib.h> /* malloc and free */ 22 #endif 23 24 #define ELF_ROUND(x,malign) (((x) + (malign)-1) & ~((malign)-1)) 25 26 27 /* 28 * The functions here are weak so that the ld.so versions are used 29 * in dynamic links, whether or not libc is static 30 */ 31 void *_dl_allocate_tib(size_t _extra) __attribute__((weak)); 32 void _dl_free_tib(void *_tib, size_t _extra) __attribute__((weak)); 33 34 /* 35 * Allocate a TIB for passing to __tfork for a new thread. 'extra' 36 * is the amount of space to allocate on the side of the TIB opposite 37 * of the TLS data: before the TIB for variant 1 and after the TIB 38 * for variant 2. If non-zero, tib_thread is set to point to that area. 39 */ 40 void * 41 _dl_allocate_tib(size_t extra) 42 { 43 #ifdef PIC 44 return NULL; /* overriden by ld.so */ 45 #else 46 char *base; 47 char *thread; 48 struct tib *tib; 49 50 # if TLS_VARIANT == 1 51 /* round up the extra size to align the tib after it */ 52 extra = ELF_ROUND(extra, sizeof(void *)); 53 base = malloc(extra + sizeof(struct tib) + _static_tls_size); 54 tib = (struct tib *)(base + extra); 55 thread = base; 56 57 # elif TLS_VARIANT == 2 58 /* round up the tib size to align the extra area after it */ 59 base = malloc(ELF_ROUND(sizeof(struct tib), TIB_EXTRA_ALIGN) + 60 extra + _static_tls_size); 61 tib = (struct tib *)(base + _static_tls_size); 62 thread = (char *)tib + ELF_ROUND(sizeof(struct tib), TIB_EXTRA_ALIGN); 63 # endif 64 65 _static_tls_init(base); 66 TIB_INIT(tib, NULL, thread); 67 68 return (tib); 69 #endif /* !PIC */ 70 } 71 72 void 73 _dl_free_tib(void *tib, size_t extra) 74 { 75 #ifndef PIC 76 size_t tib_offset; 77 78 # if TLS_VARIANT == 1 79 tib_offset = ELF_ROUND(extra, sizeof(void *)); 80 # elif TLS_VARIANT == 2 81 tib_offset = _static_tls_size; 82 # endif 83 84 free((char *)tib - tib_offset); 85 #endif /* !PIC */ 86 } 87