tib.h revision 1.2
1/* $OpenBSD: tib.h,v 1.2 2016/03/20 02:30:28 guenther 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) 50 * Initializes a TIB for a new thread, using the supplied 51 * value for the dtv pointer 52 * 53 * TIB_TO_THREAD(tib) 54 * Given a TIB pointer, return a pointer to the struct pthread 55 * 56 * TIB_GET() 57 * Short-hand for TCB_TO_TIB(TCB_GET()) 58 * 59 * TIB_THREAD() 60 * Returns a pointer to this thread's struct pthread 61 * 62 * TIB_EXTRA_ALIGN 63 * On TLS varaint 2 archs, what alignment is sufficient 64 * for the extra space that will be used for struct pthread? 65 * 66 * The following functions are provided by either ld.so (dynamic) or 67 * libc (static) for allocating and freeing a common memory block that 68 * will hold both the TIB and the pthread structure: 69 * _dl_allocate_tib(sizeof(struct pthread), flags) 70 * Allocates a combined TIB and pthread memory region. 71 * The first argument is the amount of space to reserve 72 * for the pthread structure; the second argument is 73 * either zero or DAT_UPDATE_CURRENT, the latter meaning 74 * this call is to update/replace the current thread's 75 * TIB. Returns a pointer to the TIB inside the 76 * allocated block. 77 * 78 * _dl_free_tib(tib, sizeof(struct pthread)) 79 * Frees a TIB and pthread block previously allocated 80 * with _dl_allocate_tls(). Must be passed the return 81 * value of that previous call. 82 */ 83 84/* 85 * Regarding <machine/tcb.h>: 86 * - it must define the TLS_VARIANT macro 87 * - if there's a faster way to get or set the TCB pointer for the thread 88 * than the __{get,set}_tcb() syscalls, it should define either or both 89 * the TCB_{GET,SET} macros to do so. 90 */ 91 92 93/* If <machine/tcb.h> doesn't provide a better way, then use the default */ 94#ifdef TCB_GET 95# define TCB_HAVE_MD_GET 1 96#else 97# define TCB_GET() __get_tcb() 98#endif 99#ifdef TCB_SET 100# define TCB_HAVE_MD_SET 1 101#else 102# define TCB_SET(tcb) __set_tcb(tcb) 103#endif 104 105 106#if TLS_VARIANT == 1 107/* 108 * ABI specifies that the static TLS data starts two words after the 109 * (notional) thread pointer, with the first of those two words being 110 * the TLS dtv pointer. The other (second) word is reserved for the 111 * implementation, so we place the thread's locale there, but we place 112 * our thread bits before the TCB, at negative offsets from the 113 * TCB pointer. Ergo, memory is laid out, low to high, as: 114 * 115 * [pthread structure] 116 * TIB { 117 * int cancel_flags 118 * int cancel_requested 119 * int errno 120 * void *locale 121 * TCB { 122 * void *dtv 123 * struct pthread *thread 124 * } 125 * } 126 * static TLS data 127 */ 128 129struct tib { 130#ifdef __LP64__ 131 int __tib_padding; /* padding for 8byte alignment */ 132#endif 133 int tib_cancel_flags; 134 int tib_cancel; 135 int tib_errno; 136 void *tib_locale; 137 void *tib_dtv; /* internal to the runtime linker */ 138 void *tib_thread; 139}; 140#ifdef __LP64__ 141# define _TIB_PREP(tib) ((void)((tib)->__tib_padding = 0)) 142#endif 143 144#define _TIBO_PTHREAD (- _ALIGN(sizeof(struct pthread))) 145 146#elif TLS_VARIANT == 2 147/* 148 * ABI specifies that the static TLS data occupies the memory before 149 * the TCB pointer, at negative offsets, and that on i386 and amd64 150 * the word the TCB points to contains a pointer to itself. So, 151 * we place errno and our thread bits after that. Memory is laid 152 * out, low to high, as: 153 * static TLS data 154 * TIB { 155 * TCB { 156 * self pointer [i386/amd64 only] 157 * void *dtv 158 * } 159 * struct pthread *thread 160 * void *locale 161 * int errno 162 * int cancel_count_flags 163 * int cancel_requested 164 * } 165 * [pthread structure] 166 */ 167 168struct tib { 169#if defined(__i386) || defined(__amd64) 170 struct tib *__tib_self; 171# define __tib_tcb __tib_self 172#endif 173 void *tib_dtv; /* internal to the runtime linker */ 174 void *tib_thread; 175 void *tib_locale; 176 int tib_errno; 177 int tib_cancel; /* set to request cancelation */ 178 int tib_cancel_flags; 179#if defined(__LP64__) || defined(__i386) 180 int __tib_padding; /* padding for 8byte alignment */ 181#endif 182}; 183 184#define _TIBO_PTHREAD _ALIGN(sizeof(struct tib)) 185 186#if defined(__i386) || defined(__amd64) 187# define _TIB_PREP(tib) \ 188 ((void)((tib)->__tib_self = (tib), (tib)->__tib_padding = 0)) 189#elif defined(__LP64__) 190# define _TIB_PREP(tib) ((void)((tib)->__tib_padding = 0)) 191#endif 192 193#define TIB_EXTRA_ALIGN sizeof(void *) 194 195#else 196# error "unknown TLS variant" 197#endif 198 199/* nothing to do by default */ 200#ifndef _TIB_PREP 201# define _TIB_PREP(tib) ((void)0) 202#endif 203 204#define TIB_INIT(tib, dtv, thread) do { \ 205 (tib)->tib_thread = (thread); \ 206 (tib)->tib_locale = NULL; \ 207 (tib)->tib_cancel_flags = 0; \ 208 (tib)->tib_cancel = 0; \ 209 (tib)->tib_dtv = (dtv); \ 210 (tib)->tib_errno = 0; \ 211 _TIB_PREP(tib); \ 212 } while (0) 213 214#ifndef __tib_tcb 215# define __tib_tcb tib_dtv 216#endif 217#define _TIBO_TCB offsetof(struct tib, __tib_tcb) 218 219#define TCB_TO_TIB(tcb) ((struct tib *)((char *)(tcb) - _TIBO_TCB)) 220#define TIB_TO_TCB(tib) ((char *)(tib) + _TIBO_TCB) 221#define TIB_TO_THREAD(tib) ((struct pthread *)(tib)->tib_thread) 222#define TIB_GET() TCB_TO_TIB(TCB_GET()) 223#define TCB_THREAD() TIB_TO_THREAD(TIB_GET()) 224 225 226__BEGIN_DECLS 227void *_dl_allocate_tib(size_t _extra) __dso_public; 228void _dl_free_tib(void *_tib, size_t _extra) __dso_public; 229 230/* The actual syscalls */ 231void *__get_tcb(void); 232void __set_tcb(void *_tcb); 233__END_DECLS 234 235#endif /* _TIB_H_ */ 236