Annotation of src/include/tib.h, Revision 1.2
1.2 ! guenther 1: /* $OpenBSD: tib.h,v 1.1 2015/09/14 08:16:14 guenther Exp $ */
1.1 guenther 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 */
1.2 ! guenther 94: #ifdef TCB_GET
! 95: # define TCB_HAVE_MD_GET 1
! 96: #else
! 97: # define TCB_GET() __get_tcb()
1.1 guenther 98: #endif
1.2 ! guenther 99: #ifdef TCB_SET
! 100: # define TCB_HAVE_MD_SET 1
! 101: #else
! 102: # define TCB_SET(tcb) __set_tcb(tcb)
1.1 guenther 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: *
1.2 ! guenther 115: * [pthread structure]
1.1 guenther 116: * TIB {
117: * int cancel_flags
118: * int cancel_requested
119: * int errno
1.2 ! guenther 120: * void *locale
1.1 guenther 121: * TCB {
122: * void *dtv
1.2 ! guenther 123: * struct pthread *thread
1.1 guenther 124: * }
125: * }
126: * static TLS data
127: */
128:
129: struct tib {
1.2 ! guenther 130: #ifdef __LP64__
! 131: int __tib_padding; /* padding for 8byte alignment */
! 132: #endif
1.1 guenther 133: int tib_cancel_flags;
134: int tib_cancel;
135: int tib_errno;
1.2 ! guenther 136: void *tib_locale;
1.1 guenther 137: void *tib_dtv; /* internal to the runtime linker */
1.2 ! guenther 138: void *tib_thread;
1.1 guenther 139: };
1.2 ! guenther 140: #ifdef __LP64__
! 141: # define _TIB_PREP(tib) ((void)((tib)->__tib_padding = 0))
! 142: #endif
1.1 guenther 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: * }
1.2 ! guenther 159: * struct pthread *thread
1.1 guenther 160: * void *locale
161: * int errno
162: * int cancel_count_flags
163: * int cancel_requested
164: * }
1.2 ! guenther 165: * [pthread structure]
1.1 guenther 166: */
167:
168: struct tib {
169: #if defined(__i386) || defined(__amd64)
170: struct tib *__tib_self;
1.2 ! guenther 171: # define __tib_tcb __tib_self
1.1 guenther 172: #endif
173: void *tib_dtv; /* internal to the runtime linker */
1.2 ! guenther 174: void *tib_thread;
1.1 guenther 175: void *tib_locale;
176: int tib_errno;
177: int tib_cancel; /* set to request cancelation */
178: int tib_cancel_flags;
1.2 ! guenther 179: #if defined(__LP64__) || defined(__i386)
1.1 guenther 180: int __tib_padding; /* padding for 8byte alignment */
181: #endif
182: };
183:
184: #define _TIBO_PTHREAD _ALIGN(sizeof(struct tib))
185:
1.2 ! guenther 186: #if defined(__i386) || defined(__amd64)
! 187: # define _TIB_PREP(tib) \
1.1 guenther 188: ((void)((tib)->__tib_self = (tib), (tib)->__tib_padding = 0))
1.2 ! guenther 189: #elif defined(__LP64__)
! 190: # define _TIB_PREP(tib) ((void)((tib)->__tib_padding = 0))
1.1 guenther 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
1.2 ! guenther 201: # define _TIB_PREP(tib) ((void)0)
1.1 guenther 202: #endif
203:
1.2 ! guenther 204: #define TIB_INIT(tib, dtv, thread) do { \
! 205: (tib)->tib_thread = (thread); \
1.1 guenther 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
1.2 ! guenther 215: # define __tib_tcb tib_dtv
1.1 guenther 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)
1.2 ! guenther 221: #define TIB_TO_THREAD(tib) ((struct pthread *)(tib)->tib_thread)
1.1 guenther 222: #define TIB_GET() TCB_TO_TIB(TCB_GET())
1.2 ! guenther 223: #define TCB_THREAD() TIB_TO_THREAD(TIB_GET())
1.1 guenther 224:
225:
226: __BEGIN_DECLS
1.2 ! guenther 227: void *_dl_allocate_tib(size_t _extra) __dso_public;
1.1 guenther 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: __END_DECLS
234:
235: #endif /* _TIB_H_ */