1 /* $OpenBSD: tib.h,v 1.10 2023/12/08 19:14:36 miod Exp $ */ 2 /* 3 * Copyright (c) 2011,2014 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 /* 19 * Thread Information Block (TIB) and Thread Local Storage (TLS) handling 20 * (the TCB, Thread Control Block, is part of the TIB) 21 */ 22 23 #ifndef _TIB_H_ 24 #define _TIB_H_ 25 26 #include <sys/types.h> 27 #include <machine/tcb.h> 28 29 #include <stddef.h> 30 31 32 /* 33 * This header defines struct tib and at least eight macros: 34 * TLS_VARIANT 35 * Either 1 or 2 (Actually defined by <machine/tcb.h>) 36 * 37 * TCB_SET(tcb) 38 * Set the TCB pointer for this thread to 'tcb' 39 * 40 * TCB_GET() 41 * Return the TCB pointer for this thread 42 * 43 * TCB_TO_TIB(tcb) 44 * Given a TCB pointer, return the matching TIB pointer 45 * 46 * TIB_TO_TCB(tib) 47 * Given a TIB pointer, return the matching TCB pointer 48 * 49 * TIB_INIT(tib, dtv, thread) 50 * Initializes a TIB for a new thread, using the supplied 51 * values for its dtv and thread pointers 52 * 53 * TIB_GET() 54 * Short-hand for TCB_TO_TIB(TCB_GET()) 55 * 56 * TIB_EXTRA_ALIGN 57 * On TLS variant 2 archs, what alignment is sufficient 58 * for the extra space that will be used for struct pthread? 59 * 60 * The following functions are provided by either ld.so (dynamic) or 61 * libc (static) for allocating and freeing a common memory block that 62 * will hold both the TIB and the pthread structure: 63 * _dl_allocate_tib(sizeof(struct pthread)) 64 * Allocates a combined TIB and pthread memory region. 65 * The argument is the amount of space to reserve 66 * for the pthread structure. Returns a pointer to 67 * the TIB inside the allocated block. 68 * 69 * _dl_free_tib(tib, sizeof(struct pthread)) 70 * Frees a TIB and pthread block previously allocated 71 * with _dl_allocate_tib(). Must be passed the return 72 * value of that previous call. 73 */ 74 75 /* 76 * Regarding <machine/tcb.h>: 77 * - it must define the TLS_VARIANT macro 78 * - it may define TCB_OFFSET if the TCB address in the kernel and/or 79 * register is offset from the actual TCB address. TCB_OFFSET > 0 80 * means the kernel/register points to *after* the real data. 81 * - if there's a faster way to get or set the TCB pointer for the thread 82 * than the __{get,set}_tcb() syscalls, it should define either or both 83 * the TCB_{GET,SET} macros to do so. 84 */ 85 86 87 /* All archs but mips64 have fast TCB_GET() and don't need caching */ 88 #ifndef __mips64__ 89 # define TCB_HAVE_MD_GET 1 90 #endif 91 #ifdef TCB_SET 92 # define TCB_HAVE_MD_SET 1 93 #else 94 # define TCB_SET(tcb) __set_tcb(tcb) 95 #endif 96 #ifndef TCB_OFFSET 97 # define TCB_OFFSET 0 98 #endif 99 100 /* 101 * tib_cantcancel values is non-zero if the thread should skip all 102 * cancellation processing 103 */ 104 #define CANCEL_DISABLED 1 105 #define CANCEL_DYING 2 106 107 /* 108 * tib_cancel_point is non-zero if we're in a cancel point; its modified 109 * by the cancel point code and read by the cancellation signal handler 110 */ 111 #define CANCEL_POINT 1 112 #define CANCEL_POINT_DELAYED 2 113 114 115 #if TLS_VARIANT == 1 116 /* 117 * ABI specifies that the static TLS data starts two words after the 118 * (notional) thread pointer, with the first of those two words being 119 * the TLS dtv pointer. The other (second) word is reserved for the 120 * implementation, so we place the pointer to the thread structure there, 121 * but we place our actual thread bits before the TCB, at negative offsets 122 * from the TCB pointer. Ergo, memory is laid out, low to high, as: 123 * 124 * [pthread structure] 125 * TIB { 126 * ...cancelation and other int-sized info... 127 * int errno 128 * void *locale 129 * TCB (- TCB_OFFSET) { 130 * void *dtv 131 * struct pthread *thread 132 * } 133 * } 134 * static TLS data 135 */ 136 137 struct tib { 138 void *tib_atexit; 139 int tib_thread_flags; /* internal to libpthread */ 140 pid_t tib_tid; 141 int tib_cantcancel; 142 int tib_cancel_point; 143 int tib_canceled; 144 int tib_errno; 145 void *tib_locale; 146 #ifdef __powerpc64__ 147 void *tib_thread; 148 void *tib_dtv; /* internal to the runtime linker */ 149 #else 150 void *tib_dtv; /* internal to the runtime linker */ 151 void *tib_thread; 152 #endif 153 }; 154 155 156 #elif TLS_VARIANT == 2 157 /* 158 * ABI specifies that the static TLS data occupies the memory before 159 * the TCB pointer, at negative offsets, and that on i386 and amd64 160 * the word the TCB points to contains a pointer to itself. So, 161 * we place errno and our thread bits after that. Memory is laid 162 * out, low to high, as: 163 * static TLS data 164 * TIB { 165 * TCB (- TCB_OFFSET) { 166 * self pointer [i386/amd64 only] 167 * void *dtv 168 * } 169 * struct pthread *thread 170 * void *locale 171 * int errno 172 * ...cancelation and other int-sized info... 173 * } 174 * [pthread structure] 175 */ 176 177 struct tib { 178 #if defined(__i386) || defined(__amd64) 179 struct tib *__tib_self; 180 # define __tib_tcb __tib_self 181 #endif 182 void *tib_dtv; /* internal to the runtime linker */ 183 void *tib_thread; 184 void *tib_locale; 185 int tib_errno; 186 int tib_canceled; 187 int tib_cancel_point; 188 int tib_cantcancel; 189 pid_t tib_tid; 190 int tib_thread_flags; /* internal to libpthread */ 191 void *tib_atexit; 192 }; 193 194 #if defined(__i386) || defined(__amd64) 195 # define _TIB_PREP(tib) \ 196 ((void)((tib)->__tib_self = (tib))) 197 #endif 198 199 #define TIB_EXTRA_ALIGN sizeof(void *) 200 201 #else 202 # error "unknown TLS variant" 203 #endif 204 205 /* nothing to do by default */ 206 #ifndef _TIB_PREP 207 # define _TIB_PREP(tib) ((void)0) 208 #endif 209 210 #define TIB_INIT(tib, dtv, thread) do { \ 211 (tib)->tib_thread = (thread); \ 212 (tib)->tib_atexit = NULL; \ 213 (tib)->tib_locale = NULL; \ 214 (tib)->tib_cantcancel = 0; \ 215 (tib)->tib_cancel_point = 0; \ 216 (tib)->tib_canceled = 0; \ 217 (tib)->tib_dtv = (dtv); \ 218 (tib)->tib_errno = 0; \ 219 (tib)->tib_thread_flags = 0; \ 220 _TIB_PREP(tib); \ 221 } while (0) 222 223 #ifndef __tib_tcb 224 # define __tib_tcb tib_dtv 225 #endif 226 #define _TIBO_TCB (offsetof(struct tib, __tib_tcb) + TCB_OFFSET) 227 228 #define TCB_TO_TIB(tcb) ((struct tib *)((char *)(tcb) - _TIBO_TCB)) 229 #define TIB_TO_TCB(tib) ((char *)(tib) + _TIBO_TCB) 230 #define TIB_GET() TCB_TO_TIB(TCB_GET()) 231 232 233 __BEGIN_DECLS 234 struct dl_info; 235 struct dl_phdr_info; 236 struct dl_cb_0 { 237 void *(*dl_allocate_tib)(size_t); 238 void (*dl_free_tib)(void *, size_t); 239 void (*dl_clean_boot)(void); 240 void *(*dlopen)(const char *, int); 241 int (*dlclose)(void *); 242 void *(*dlsym)(void *, const char *); 243 int (*dladdr)(const void *, struct dl_info *); 244 int (*dlctl)(void *, int, void *); 245 char *(*dlerror)(void); 246 int (*dl_iterate_phdr)(int (*)(struct dl_phdr_info *, 247 size_t, void *), void *); 248 }; 249 250 #define DL_CB_CUR 0 251 typedef struct dl_cb_0 dl_cb; 252 253 /* type of function passed to init functions that returns a dl_cb */ 254 typedef const void *dl_cb_cb(int _version); 255 256 void *_dl_allocate_tib(size_t _extra) __dso_public; 257 void _dl_free_tib(void *_tib, size_t _extra) __dso_public; 258 259 /* The actual syscalls */ 260 void *__get_tcb(void); 261 void __set_tcb(void *_tcb); 262 __END_DECLS 263 264 #endif /* _TIB_H_ */ 265