xref: /openbsd/include/tib.h (revision 9b42e9bf)
1 /*	$OpenBSD: tib.h,v 1.10 2023/12/08 19:14:36 miod 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, thread)
50  *		Initializes a TIB for a new thread, using the supplied
51  *		values for its dtv and thread pointers
52  *
53  *	TIB_GET()
54  *		Short-hand for TCB_TO_TIB(TCB_GET())
55  *
56  *	TIB_EXTRA_ALIGN
57  *		On TLS variant 2 archs, what alignment is sufficient
58  *		for the extra space that will be used for struct pthread?
59  *
60  * The following functions are provided by either ld.so (dynamic) or
61  * libc (static) for allocating and freeing a common memory block that
62  * will hold both the TIB and the pthread structure:
63  *	_dl_allocate_tib(sizeof(struct pthread))
64  *		Allocates a combined TIB and pthread memory region.
65  *		The argument is the amount of space to reserve
66  *		for the pthread structure.  Returns a pointer to
67  *		the TIB inside the allocated block.
68  *
69  * 	_dl_free_tib(tib, sizeof(struct pthread))
70  *		Frees a TIB and pthread block previously allocated
71  *		with _dl_allocate_tib().  Must be passed the return
72  *		value of that previous call.
73  */
74 
75 /*
76  * Regarding <machine/tcb.h>:
77  *  - it must define the TLS_VARIANT macro
78  *  - it may define TCB_OFFSET if the TCB address in the kernel and/or
79  *    register is offset from the actual TCB address.  TCB_OFFSET > 0
80  *    means the kernel/register points to *after* the real data.
81  *  - if there's a faster way to get or set the TCB pointer for the thread
82  *    than the __{get,set}_tcb() syscalls, it should define either or both
83  *    the TCB_{GET,SET} macros to do so.
84  */
85 
86 
87 /* All archs but mips64 have fast TCB_GET() and don't need caching */
88 #ifndef	__mips64__
89 # define TCB_HAVE_MD_GET	1
90 #endif
91 #ifdef	TCB_SET
92 # define TCB_HAVE_MD_SET	1
93 #else
94 # define TCB_SET(tcb)		__set_tcb(tcb)
95 #endif
96 #ifndef TCB_OFFSET
97 # define TCB_OFFSET	0
98 #endif
99 
100 /*
101  * tib_cantcancel values is non-zero if the thread should skip all
102  * cancellation processing
103  */
104 #define CANCEL_DISABLED	1
105 #define CANCEL_DYING	2
106 
107 /*
108  * tib_cancel_point is non-zero if we're in a cancel point; its modified
109  * by the cancel point code and read by the cancellation signal handler
110  */
111 #define CANCEL_POINT		1
112 #define CANCEL_POINT_DELAYED	2
113 
114 
115 #if TLS_VARIANT == 1
116 /*
117  * ABI specifies that the static TLS data starts two words after the
118  * (notional) thread pointer, with the first of those two words being
119  * the TLS dtv pointer.  The other (second) word is reserved for the
120  * implementation, so we place the pointer to the thread structure there,
121  * but we place our actual thread bits before the TCB, at negative offsets
122  * from the TCB pointer.  Ergo, memory is laid out, low to high, as:
123  *
124  *	[pthread structure]
125  *	TIB {
126  *		...cancelation and other int-sized info...
127  *		int errno
128  *		void *locale
129  *		TCB (- TCB_OFFSET) {
130  *			void *dtv
131  *			struct pthread *thread
132  *		}
133  *	}
134  *	static TLS data
135  */
136 
137 struct tib {
138 	void	*tib_atexit;
139 	int	tib_thread_flags;	/* internal to libpthread */
140 	pid_t	tib_tid;
141 	int	tib_cantcancel;
142 	int	tib_cancel_point;
143 	int	tib_canceled;
144 	int	tib_errno;
145 	void	*tib_locale;
146 #ifdef __powerpc64__
147 	void	*tib_thread;
148 	void	*tib_dtv;		/* internal to the runtime linker */
149 #else
150 	void	*tib_dtv;		/* internal to the runtime linker */
151 	void	*tib_thread;
152 #endif
153 };
154 
155 
156 #elif TLS_VARIANT == 2
157 /*
158  * ABI specifies that the static TLS data occupies the memory before
159  * the TCB pointer, at negative offsets, and that on i386 and amd64
160  * the word the TCB points to contains a pointer to itself.  So,
161  * we place errno and our thread bits after that.  Memory is laid
162  * out, low to high, as:
163  *	static TLS data
164  *	TIB {
165  *		TCB (- TCB_OFFSET) {
166  *			self pointer [i386/amd64 only]
167  *			void *dtv
168  *		}
169  *		struct pthread *thread
170  *		void *locale
171  *		int errno
172  *		...cancelation and other int-sized info...
173  *	}
174  *	[pthread structure]
175  */
176 
177 struct tib {
178 #if defined(__i386) || defined(__amd64)
179 	struct	tib *__tib_self;
180 # define __tib_tcb __tib_self
181 #endif
182 	void	*tib_dtv;		/* internal to the runtime linker */
183 	void	*tib_thread;
184 	void	*tib_locale;
185 	int	tib_errno;
186 	int	tib_canceled;
187 	int	tib_cancel_point;
188 	int	tib_cantcancel;
189 	pid_t	tib_tid;
190 	int	tib_thread_flags;	/* internal to libpthread */
191 	void	*tib_atexit;
192 };
193 
194 #if defined(__i386) || defined(__amd64)
195 # define _TIB_PREP(tib)	\
196 	((void)((tib)->__tib_self = (tib)))
197 #endif
198 
199 #define	TIB_EXTRA_ALIGN		sizeof(void *)
200 
201 #else
202 # error "unknown TLS variant"
203 #endif
204 
205 /* nothing to do by default */
206 #ifndef	_TIB_PREP
207 # define _TIB_PREP(tib)	((void)0)
208 #endif
209 
210 #define	TIB_INIT(tib, dtv, thread)	do {		\
211 		(tib)->tib_thread	= (thread);	\
212 		(tib)->tib_atexit	= NULL;		\
213 		(tib)->tib_locale	= NULL;		\
214 		(tib)->tib_cantcancel	= 0;		\
215 		(tib)->tib_cancel_point	= 0;		\
216 		(tib)->tib_canceled	= 0;		\
217 		(tib)->tib_dtv		= (dtv);	\
218 		(tib)->tib_errno	= 0;		\
219 		(tib)->tib_thread_flags = 0;		\
220 		_TIB_PREP(tib);				\
221 	} while (0)
222 
223 #ifndef	__tib_tcb
224 # define __tib_tcb		tib_dtv
225 #endif
226 #define	_TIBO_TCB		(offsetof(struct tib, __tib_tcb) + TCB_OFFSET)
227 
228 #define	TCB_TO_TIB(tcb)		((struct tib *)((char *)(tcb) - _TIBO_TCB))
229 #define	TIB_TO_TCB(tib)		((char *)(tib) + _TIBO_TCB)
230 #define	TIB_GET()		TCB_TO_TIB(TCB_GET())
231 
232 
233 __BEGIN_DECLS
234 struct dl_info;
235 struct dl_phdr_info;
236 struct dl_cb_0 {
237 	void	*(*dl_allocate_tib)(size_t);
238 	void	 (*dl_free_tib)(void *, size_t);
239 	void	 (*dl_clean_boot)(void);
240 	void	*(*dlopen)(const char *, int);
241 	int	 (*dlclose)(void *);
242 	void	*(*dlsym)(void *, const char *);
243 	int	 (*dladdr)(const void *, struct dl_info *);
244 	int	 (*dlctl)(void *, int, void *);
245 	char	*(*dlerror)(void);
246 	int	 (*dl_iterate_phdr)(int (*)(struct dl_phdr_info *,
247 		    size_t, void *), void *);
248 };
249 
250 #define	DL_CB_CUR	0
251 typedef	struct dl_cb_0	dl_cb;
252 
253 /* type of function passed to init functions that returns a dl_cb */
254 typedef	const void *dl_cb_cb(int _version);
255 
256 void	*_dl_allocate_tib(size_t _extra) __dso_public;
257 void	_dl_free_tib(void *_tib, size_t _extra) __dso_public;
258 
259 /* The actual syscalls */
260 void	*__get_tcb(void);
261 void	__set_tcb(void *_tcb);
262 __END_DECLS
263 
264 #endif /* _TIB_H_ */
265