1*9b42e9bfSmiod /* $OpenBSD: tib.h,v 1.10 2023/12/08 19:14:36 miod Exp $ */ 2f09ad35cSguenther /* 3f09ad35cSguenther * Copyright (c) 2011,2014 Philip Guenther <guenther@openbsd.org> 4f09ad35cSguenther * 5f09ad35cSguenther * Permission to use, copy, modify, and distribute this software for any 6f09ad35cSguenther * purpose with or without fee is hereby granted, provided that the above 7f09ad35cSguenther * copyright notice and this permission notice appear in all copies. 8f09ad35cSguenther * 9f09ad35cSguenther * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10f09ad35cSguenther * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11f09ad35cSguenther * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12f09ad35cSguenther * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13f09ad35cSguenther * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14f09ad35cSguenther * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15f09ad35cSguenther * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16f09ad35cSguenther */ 17f09ad35cSguenther 18f09ad35cSguenther /* 19f09ad35cSguenther * Thread Information Block (TIB) and Thread Local Storage (TLS) handling 20f09ad35cSguenther * (the TCB, Thread Control Block, is part of the TIB) 21f09ad35cSguenther */ 22f09ad35cSguenther 23f09ad35cSguenther #ifndef _TIB_H_ 24f09ad35cSguenther #define _TIB_H_ 25f09ad35cSguenther 26f09ad35cSguenther #include <sys/types.h> 27f09ad35cSguenther #include <machine/tcb.h> 28f09ad35cSguenther 29f09ad35cSguenther #include <stddef.h> 30f09ad35cSguenther 31f09ad35cSguenther 32f09ad35cSguenther /* 33f09ad35cSguenther * This header defines struct tib and at least eight macros: 34f09ad35cSguenther * TLS_VARIANT 35f09ad35cSguenther * Either 1 or 2 (Actually defined by <machine/tcb.h>) 36f09ad35cSguenther * 37f09ad35cSguenther * TCB_SET(tcb) 38f09ad35cSguenther * Set the TCB pointer for this thread to 'tcb' 39f09ad35cSguenther * 40f09ad35cSguenther * TCB_GET() 41f09ad35cSguenther * Return the TCB pointer for this thread 42f09ad35cSguenther * 43f09ad35cSguenther * TCB_TO_TIB(tcb) 44f09ad35cSguenther * Given a TCB pointer, return the matching TIB pointer 45f09ad35cSguenther * 46f09ad35cSguenther * TIB_TO_TCB(tib) 47f09ad35cSguenther * Given a TIB pointer, return the matching TCB pointer 48f09ad35cSguenther * 49fe38b55cSguenther * TIB_INIT(tib, dtv, thread) 50f09ad35cSguenther * Initializes a TIB for a new thread, using the supplied 51fe38b55cSguenther * values for its dtv and thread pointers 52f09ad35cSguenther * 53f09ad35cSguenther * TIB_GET() 54f09ad35cSguenther * Short-hand for TCB_TO_TIB(TCB_GET()) 55f09ad35cSguenther * 56f09ad35cSguenther * TIB_EXTRA_ALIGN 572811b70eSjmc * On TLS variant 2 archs, what alignment is sufficient 58f09ad35cSguenther * for the extra space that will be used for struct pthread? 59f09ad35cSguenther * 60f09ad35cSguenther * The following functions are provided by either ld.so (dynamic) or 61f09ad35cSguenther * libc (static) for allocating and freeing a common memory block that 62f09ad35cSguenther * will hold both the TIB and the pthread structure: 63fe38b55cSguenther * _dl_allocate_tib(sizeof(struct pthread)) 64f09ad35cSguenther * Allocates a combined TIB and pthread memory region. 65fe38b55cSguenther * The argument is the amount of space to reserve 66fe38b55cSguenther * for the pthread structure. Returns a pointer to 67fe38b55cSguenther * the TIB inside the allocated block. 68f09ad35cSguenther * 69f09ad35cSguenther * _dl_free_tib(tib, sizeof(struct pthread)) 70f09ad35cSguenther * Frees a TIB and pthread block previously allocated 71fe38b55cSguenther * with _dl_allocate_tib(). Must be passed the return 72f09ad35cSguenther * value of that previous call. 73f09ad35cSguenther */ 74f09ad35cSguenther 75f09ad35cSguenther /* 76f09ad35cSguenther * Regarding <machine/tcb.h>: 77f09ad35cSguenther * - it must define the TLS_VARIANT macro 78fe38b55cSguenther * - it may define TCB_OFFSET if the TCB address in the kernel and/or 79fe38b55cSguenther * register is offset from the actual TCB address. TCB_OFFSET > 0 80fe38b55cSguenther * means the kernel/register points to *after* the real data. 81f09ad35cSguenther * - if there's a faster way to get or set the TCB pointer for the thread 82f09ad35cSguenther * than the __{get,set}_tcb() syscalls, it should define either or both 83f09ad35cSguenther * the TCB_{GET,SET} macros to do so. 84f09ad35cSguenther */ 85f09ad35cSguenther 86f09ad35cSguenther 8729879bdcSvisa /* All archs but mips64 have fast TCB_GET() and don't need caching */ 8829879bdcSvisa #ifndef __mips64__ 89157c34b3Sguenther # define TCB_HAVE_MD_GET 1 90f09ad35cSguenther #endif 91157c34b3Sguenther #ifdef TCB_SET 92157c34b3Sguenther # define TCB_HAVE_MD_SET 1 93157c34b3Sguenther #else 94f09ad35cSguenther # define TCB_SET(tcb) __set_tcb(tcb) 95f09ad35cSguenther #endif 96fe38b55cSguenther #ifndef TCB_OFFSET 97fe38b55cSguenther # define TCB_OFFSET 0 98fe38b55cSguenther #endif 99fe38b55cSguenther 100fe38b55cSguenther /* 10118cf7fd7Sguenther * tib_cantcancel values is non-zero if the thread should skip all 102fe38b55cSguenther * cancellation processing 103fe38b55cSguenther */ 104fe38b55cSguenther #define CANCEL_DISABLED 1 105fe38b55cSguenther #define CANCEL_DYING 2 106fe38b55cSguenther 107fe38b55cSguenther /* 108fe38b55cSguenther * tib_cancel_point is non-zero if we're in a cancel point; its modified 109fe38b55cSguenther * by the cancel point code and read by the cancellation signal handler 110fe38b55cSguenther */ 111fe38b55cSguenther #define CANCEL_POINT 1 112fe38b55cSguenther #define CANCEL_POINT_DELAYED 2 113f09ad35cSguenther 114f09ad35cSguenther 115f09ad35cSguenther #if TLS_VARIANT == 1 116f09ad35cSguenther /* 117f09ad35cSguenther * ABI specifies that the static TLS data starts two words after the 118f09ad35cSguenther * (notional) thread pointer, with the first of those two words being 119f09ad35cSguenther * the TLS dtv pointer. The other (second) word is reserved for the 120fe38b55cSguenther * implementation, so we place the pointer to the thread structure there, 121fe38b55cSguenther * but we place our actual thread bits before the TCB, at negative offsets 122fe38b55cSguenther * from the TCB pointer. Ergo, memory is laid out, low to high, as: 123f09ad35cSguenther * 124157c34b3Sguenther * [pthread structure] 125f09ad35cSguenther * TIB { 126fe38b55cSguenther * ...cancelation and other int-sized info... 127f09ad35cSguenther * int errno 128157c34b3Sguenther * void *locale 129fe38b55cSguenther * TCB (- TCB_OFFSET) { 130f09ad35cSguenther * void *dtv 131157c34b3Sguenther * struct pthread *thread 132f09ad35cSguenther * } 133f09ad35cSguenther * } 134f09ad35cSguenther * static TLS data 135f09ad35cSguenther */ 136f09ad35cSguenther 137f09ad35cSguenther struct tib { 13853213268Skettenis void *tib_atexit; 139fe38b55cSguenther int tib_thread_flags; /* internal to libpthread */ 140fe38b55cSguenther pid_t tib_tid; 141fe38b55cSguenther int tib_cantcancel; 142fe38b55cSguenther int tib_cancel_point; 143fe38b55cSguenther int tib_canceled; 144f09ad35cSguenther int tib_errno; 145f09ad35cSguenther void *tib_locale; 146874055c7Skettenis #ifdef __powerpc64__ 147874055c7Skettenis void *tib_thread; 148874055c7Skettenis void *tib_dtv; /* internal to the runtime linker */ 149874055c7Skettenis #else 150157c34b3Sguenther void *tib_dtv; /* internal to the runtime linker */ 151157c34b3Sguenther void *tib_thread; 152874055c7Skettenis #endif 153f09ad35cSguenther }; 154f09ad35cSguenther 155f09ad35cSguenther 156f09ad35cSguenther #elif TLS_VARIANT == 2 157f09ad35cSguenther /* 158f09ad35cSguenther * ABI specifies that the static TLS data occupies the memory before 159f09ad35cSguenther * the TCB pointer, at negative offsets, and that on i386 and amd64 160f09ad35cSguenther * the word the TCB points to contains a pointer to itself. So, 161f09ad35cSguenther * we place errno and our thread bits after that. Memory is laid 162f09ad35cSguenther * out, low to high, as: 163f09ad35cSguenther * static TLS data 164f09ad35cSguenther * TIB { 165fe38b55cSguenther * TCB (- TCB_OFFSET) { 166f09ad35cSguenther * self pointer [i386/amd64 only] 167f09ad35cSguenther * void *dtv 168f09ad35cSguenther * } 169157c34b3Sguenther * struct pthread *thread 170f09ad35cSguenther * void *locale 171f09ad35cSguenther * int errno 172fe38b55cSguenther * ...cancelation and other int-sized info... 173f09ad35cSguenther * } 174157c34b3Sguenther * [pthread structure] 175f09ad35cSguenther */ 176f09ad35cSguenther 177f09ad35cSguenther struct tib { 178f09ad35cSguenther #if defined(__i386) || defined(__amd64) 179f09ad35cSguenther struct tib *__tib_self; 180f09ad35cSguenther # define __tib_tcb __tib_self 181f09ad35cSguenther #endif 182f09ad35cSguenther void *tib_dtv; /* internal to the runtime linker */ 183157c34b3Sguenther void *tib_thread; 184f09ad35cSguenther void *tib_locale; 185f09ad35cSguenther int tib_errno; 186fe38b55cSguenther int tib_canceled; 187fe38b55cSguenther int tib_cancel_point; 188fe38b55cSguenther int tib_cantcancel; 189fe38b55cSguenther pid_t tib_tid; 190fe38b55cSguenther int tib_thread_flags; /* internal to libpthread */ 19153213268Skettenis void *tib_atexit; 192f09ad35cSguenther }; 193f09ad35cSguenther 194157c34b3Sguenther #if defined(__i386) || defined(__amd64) 195f09ad35cSguenther # define _TIB_PREP(tib) \ 196fe38b55cSguenther ((void)((tib)->__tib_self = (tib))) 197f09ad35cSguenther #endif 198f09ad35cSguenther 199f09ad35cSguenther #define TIB_EXTRA_ALIGN sizeof(void *) 200f09ad35cSguenther 201f09ad35cSguenther #else 202f09ad35cSguenther # error "unknown TLS variant" 203f09ad35cSguenther #endif 204f09ad35cSguenther 205f09ad35cSguenther /* nothing to do by default */ 206f09ad35cSguenther #ifndef _TIB_PREP 207f09ad35cSguenther # define _TIB_PREP(tib) ((void)0) 208f09ad35cSguenther #endif 209f09ad35cSguenther 210157c34b3Sguenther #define TIB_INIT(tib, dtv, thread) do { \ 211157c34b3Sguenther (tib)->tib_thread = (thread); \ 21253213268Skettenis (tib)->tib_atexit = NULL; \ 213f09ad35cSguenther (tib)->tib_locale = NULL; \ 214fe38b55cSguenther (tib)->tib_cantcancel = 0; \ 215fe38b55cSguenther (tib)->tib_cancel_point = 0; \ 216fe38b55cSguenther (tib)->tib_canceled = 0; \ 217f09ad35cSguenther (tib)->tib_dtv = (dtv); \ 218f09ad35cSguenther (tib)->tib_errno = 0; \ 219*9b42e9bfSmiod (tib)->tib_thread_flags = 0; \ 220f09ad35cSguenther _TIB_PREP(tib); \ 221f09ad35cSguenther } while (0) 222f09ad35cSguenther 223f09ad35cSguenther #ifndef __tib_tcb 224f09ad35cSguenther # define __tib_tcb tib_dtv 225f09ad35cSguenther #endif 226fe38b55cSguenther #define _TIBO_TCB (offsetof(struct tib, __tib_tcb) + TCB_OFFSET) 227f09ad35cSguenther 228f09ad35cSguenther #define TCB_TO_TIB(tcb) ((struct tib *)((char *)(tcb) - _TIBO_TCB)) 229f09ad35cSguenther #define TIB_TO_TCB(tib) ((char *)(tib) + _TIBO_TCB) 230f09ad35cSguenther #define TIB_GET() TCB_TO_TIB(TCB_GET()) 231f09ad35cSguenther 232f09ad35cSguenther 233f09ad35cSguenther __BEGIN_DECLS 234c0197e40Sguenther struct dl_info; 235c0197e40Sguenther struct dl_phdr_info; 236c0197e40Sguenther struct dl_cb_0 { 237c0197e40Sguenther void *(*dl_allocate_tib)(size_t); 238c0197e40Sguenther void (*dl_free_tib)(void *, size_t); 239c0197e40Sguenther void (*dl_clean_boot)(void); 240c0197e40Sguenther void *(*dlopen)(const char *, int); 241c0197e40Sguenther int (*dlclose)(void *); 242c0197e40Sguenther void *(*dlsym)(void *, const char *); 243c0197e40Sguenther int (*dladdr)(const void *, struct dl_info *); 244c0197e40Sguenther int (*dlctl)(void *, int, void *); 245c0197e40Sguenther char *(*dlerror)(void); 246c0197e40Sguenther int (*dl_iterate_phdr)(int (*)(struct dl_phdr_info *, 247c0197e40Sguenther size_t, void *), void *); 248c0197e40Sguenther }; 249c0197e40Sguenther 250c0197e40Sguenther #define DL_CB_CUR 0 251c0197e40Sguenther typedef struct dl_cb_0 dl_cb; 252c0197e40Sguenther 253c0197e40Sguenther /* type of function passed to init functions that returns a dl_cb */ 254c0197e40Sguenther typedef const void *dl_cb_cb(int _version); 255c0197e40Sguenther 256157c34b3Sguenther void *_dl_allocate_tib(size_t _extra) __dso_public; 257f09ad35cSguenther void _dl_free_tib(void *_tib, size_t _extra) __dso_public; 258f09ad35cSguenther 259f09ad35cSguenther /* The actual syscalls */ 260f09ad35cSguenther void *__get_tcb(void); 261f09ad35cSguenther void __set_tcb(void *_tcb); 262f09ad35cSguenther __END_DECLS 263f09ad35cSguenther 264f09ad35cSguenther #endif /* _TIB_H_ */ 265