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