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