xref: /openbsd/include/tib.h (revision 9b42e9bf)
1*9b42e9bfSmiod /*	$OpenBSD: tib.h,v 1.10 2023/12/08 19:14:36 miod Exp $	*/
2f09ad35cSguenther /*
3f09ad35cSguenther  * Copyright (c) 2011,2014 Philip Guenther <guenther@openbsd.org>
4f09ad35cSguenther  *
5f09ad35cSguenther  * Permission to use, copy, modify, and distribute this software for any
6f09ad35cSguenther  * purpose with or without fee is hereby granted, provided that the above
7f09ad35cSguenther  * copyright notice and this permission notice appear in all copies.
8f09ad35cSguenther  *
9f09ad35cSguenther  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10f09ad35cSguenther  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11f09ad35cSguenther  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12f09ad35cSguenther  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13f09ad35cSguenther  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14f09ad35cSguenther  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15f09ad35cSguenther  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16f09ad35cSguenther  */
17f09ad35cSguenther 
18f09ad35cSguenther /*
19f09ad35cSguenther  * Thread Information Block (TIB) and Thread Local Storage (TLS) handling
20f09ad35cSguenther  * (the TCB, Thread Control Block, is part of the TIB)
21f09ad35cSguenther  */
22f09ad35cSguenther 
23f09ad35cSguenther #ifndef	_TIB_H_
24f09ad35cSguenther #define	_TIB_H_
25f09ad35cSguenther 
26f09ad35cSguenther #include <sys/types.h>
27f09ad35cSguenther #include <machine/tcb.h>
28f09ad35cSguenther 
29f09ad35cSguenther #include <stddef.h>
30f09ad35cSguenther 
31f09ad35cSguenther 
32f09ad35cSguenther /*
33f09ad35cSguenther  * This header defines struct tib and at least eight macros:
34f09ad35cSguenther  *	TLS_VARIANT
35f09ad35cSguenther  *		Either 1 or 2  (Actually defined by <machine/tcb.h>)
36f09ad35cSguenther  *
37f09ad35cSguenther  *	TCB_SET(tcb)
38f09ad35cSguenther  *		Set the TCB pointer for this thread to 'tcb'
39f09ad35cSguenther  *
40f09ad35cSguenther  *	TCB_GET()
41f09ad35cSguenther  *		Return the TCB pointer for this thread
42f09ad35cSguenther  *
43f09ad35cSguenther  *	TCB_TO_TIB(tcb)
44f09ad35cSguenther  *		Given a TCB pointer, return the matching TIB pointer
45f09ad35cSguenther  *
46f09ad35cSguenther  *	TIB_TO_TCB(tib)
47f09ad35cSguenther  *		Given a TIB pointer, return the matching TCB pointer
48f09ad35cSguenther  *
49fe38b55cSguenther  *	TIB_INIT(tib, dtv, thread)
50f09ad35cSguenther  *		Initializes a TIB for a new thread, using the supplied
51fe38b55cSguenther  *		values for its dtv and thread pointers
52f09ad35cSguenther  *
53f09ad35cSguenther  *	TIB_GET()
54f09ad35cSguenther  *		Short-hand for TCB_TO_TIB(TCB_GET())
55f09ad35cSguenther  *
56f09ad35cSguenther  *	TIB_EXTRA_ALIGN
572811b70eSjmc  *		On TLS variant 2 archs, what alignment is sufficient
58f09ad35cSguenther  *		for the extra space that will be used for struct pthread?
59f09ad35cSguenther  *
60f09ad35cSguenther  * The following functions are provided by either ld.so (dynamic) or
61f09ad35cSguenther  * libc (static) for allocating and freeing a common memory block that
62f09ad35cSguenther  * will hold both the TIB and the pthread structure:
63fe38b55cSguenther  *	_dl_allocate_tib(sizeof(struct pthread))
64f09ad35cSguenther  *		Allocates a combined TIB and pthread memory region.
65fe38b55cSguenther  *		The argument is the amount of space to reserve
66fe38b55cSguenther  *		for the pthread structure.  Returns a pointer to
67fe38b55cSguenther  *		the TIB inside the allocated block.
68f09ad35cSguenther  *
69f09ad35cSguenther  * 	_dl_free_tib(tib, sizeof(struct pthread))
70f09ad35cSguenther  *		Frees a TIB and pthread block previously allocated
71fe38b55cSguenther  *		with _dl_allocate_tib().  Must be passed the return
72f09ad35cSguenther  *		value of that previous call.
73f09ad35cSguenther  */
74f09ad35cSguenther 
75f09ad35cSguenther /*
76f09ad35cSguenther  * Regarding <machine/tcb.h>:
77f09ad35cSguenther  *  - it must define the TLS_VARIANT macro
78fe38b55cSguenther  *  - it may define TCB_OFFSET if the TCB address in the kernel and/or
79fe38b55cSguenther  *    register is offset from the actual TCB address.  TCB_OFFSET > 0
80fe38b55cSguenther  *    means the kernel/register points to *after* the real data.
81f09ad35cSguenther  *  - if there's a faster way to get or set the TCB pointer for the thread
82f09ad35cSguenther  *    than the __{get,set}_tcb() syscalls, it should define either or both
83f09ad35cSguenther  *    the TCB_{GET,SET} macros to do so.
84f09ad35cSguenther  */
85f09ad35cSguenther 
86f09ad35cSguenther 
8729879bdcSvisa /* All archs but mips64 have fast TCB_GET() and don't need caching */
8829879bdcSvisa #ifndef	__mips64__
89157c34b3Sguenther # define TCB_HAVE_MD_GET	1
90f09ad35cSguenther #endif
91157c34b3Sguenther #ifdef	TCB_SET
92157c34b3Sguenther # define TCB_HAVE_MD_SET	1
93157c34b3Sguenther #else
94f09ad35cSguenther # define TCB_SET(tcb)		__set_tcb(tcb)
95f09ad35cSguenther #endif
96fe38b55cSguenther #ifndef TCB_OFFSET
97fe38b55cSguenther # define TCB_OFFSET	0
98fe38b55cSguenther #endif
99fe38b55cSguenther 
100fe38b55cSguenther /*
10118cf7fd7Sguenther  * tib_cantcancel values is non-zero if the thread should skip all
102fe38b55cSguenther  * cancellation processing
103fe38b55cSguenther  */
104fe38b55cSguenther #define CANCEL_DISABLED	1
105fe38b55cSguenther #define CANCEL_DYING	2
106fe38b55cSguenther 
107fe38b55cSguenther /*
108fe38b55cSguenther  * tib_cancel_point is non-zero if we're in a cancel point; its modified
109fe38b55cSguenther  * by the cancel point code and read by the cancellation signal handler
110fe38b55cSguenther  */
111fe38b55cSguenther #define CANCEL_POINT		1
112fe38b55cSguenther #define CANCEL_POINT_DELAYED	2
113f09ad35cSguenther 
114f09ad35cSguenther 
115f09ad35cSguenther #if TLS_VARIANT == 1
116f09ad35cSguenther /*
117f09ad35cSguenther  * ABI specifies that the static TLS data starts two words after the
118f09ad35cSguenther  * (notional) thread pointer, with the first of those two words being
119f09ad35cSguenther  * the TLS dtv pointer.  The other (second) word is reserved for the
120fe38b55cSguenther  * implementation, so we place the pointer to the thread structure there,
121fe38b55cSguenther  * but we place our actual thread bits before the TCB, at negative offsets
122fe38b55cSguenther  * from the TCB pointer.  Ergo, memory is laid out, low to high, as:
123f09ad35cSguenther  *
124157c34b3Sguenther  *	[pthread structure]
125f09ad35cSguenther  *	TIB {
126fe38b55cSguenther  *		...cancelation and other int-sized info...
127f09ad35cSguenther  *		int errno
128157c34b3Sguenther  *		void *locale
129fe38b55cSguenther  *		TCB (- TCB_OFFSET) {
130f09ad35cSguenther  *			void *dtv
131157c34b3Sguenther  *			struct pthread *thread
132f09ad35cSguenther  *		}
133f09ad35cSguenther  *	}
134f09ad35cSguenther  *	static TLS data
135f09ad35cSguenther  */
136f09ad35cSguenther 
137f09ad35cSguenther struct tib {
13853213268Skettenis 	void	*tib_atexit;
139fe38b55cSguenther 	int	tib_thread_flags;	/* internal to libpthread */
140fe38b55cSguenther 	pid_t	tib_tid;
141fe38b55cSguenther 	int	tib_cantcancel;
142fe38b55cSguenther 	int	tib_cancel_point;
143fe38b55cSguenther 	int	tib_canceled;
144f09ad35cSguenther 	int	tib_errno;
145f09ad35cSguenther 	void	*tib_locale;
146874055c7Skettenis #ifdef __powerpc64__
147874055c7Skettenis 	void	*tib_thread;
148874055c7Skettenis 	void	*tib_dtv;		/* internal to the runtime linker */
149874055c7Skettenis #else
150157c34b3Sguenther 	void	*tib_dtv;		/* internal to the runtime linker */
151157c34b3Sguenther 	void	*tib_thread;
152874055c7Skettenis #endif
153f09ad35cSguenther };
154f09ad35cSguenther 
155f09ad35cSguenther 
156f09ad35cSguenther #elif TLS_VARIANT == 2
157f09ad35cSguenther /*
158f09ad35cSguenther  * ABI specifies that the static TLS data occupies the memory before
159f09ad35cSguenther  * the TCB pointer, at negative offsets, and that on i386 and amd64
160f09ad35cSguenther  * the word the TCB points to contains a pointer to itself.  So,
161f09ad35cSguenther  * we place errno and our thread bits after that.  Memory is laid
162f09ad35cSguenther  * out, low to high, as:
163f09ad35cSguenther  *	static TLS data
164f09ad35cSguenther  *	TIB {
165fe38b55cSguenther  *		TCB (- TCB_OFFSET) {
166f09ad35cSguenther  *			self pointer [i386/amd64 only]
167f09ad35cSguenther  *			void *dtv
168f09ad35cSguenther  *		}
169157c34b3Sguenther  *		struct pthread *thread
170f09ad35cSguenther  *		void *locale
171f09ad35cSguenther  *		int errno
172fe38b55cSguenther  *		...cancelation and other int-sized info...
173f09ad35cSguenther  *	}
174157c34b3Sguenther  *	[pthread structure]
175f09ad35cSguenther  */
176f09ad35cSguenther 
177f09ad35cSguenther struct tib {
178f09ad35cSguenther #if defined(__i386) || defined(__amd64)
179f09ad35cSguenther 	struct	tib *__tib_self;
180f09ad35cSguenther # define __tib_tcb __tib_self
181f09ad35cSguenther #endif
182f09ad35cSguenther 	void	*tib_dtv;		/* internal to the runtime linker */
183157c34b3Sguenther 	void	*tib_thread;
184f09ad35cSguenther 	void	*tib_locale;
185f09ad35cSguenther 	int	tib_errno;
186fe38b55cSguenther 	int	tib_canceled;
187fe38b55cSguenther 	int	tib_cancel_point;
188fe38b55cSguenther 	int	tib_cantcancel;
189fe38b55cSguenther 	pid_t	tib_tid;
190fe38b55cSguenther 	int	tib_thread_flags;	/* internal to libpthread */
19153213268Skettenis 	void	*tib_atexit;
192f09ad35cSguenther };
193f09ad35cSguenther 
194157c34b3Sguenther #if defined(__i386) || defined(__amd64)
195f09ad35cSguenther # define _TIB_PREP(tib)	\
196fe38b55cSguenther 	((void)((tib)->__tib_self = (tib)))
197f09ad35cSguenther #endif
198f09ad35cSguenther 
199f09ad35cSguenther #define	TIB_EXTRA_ALIGN		sizeof(void *)
200f09ad35cSguenther 
201f09ad35cSguenther #else
202f09ad35cSguenther # error "unknown TLS variant"
203f09ad35cSguenther #endif
204f09ad35cSguenther 
205f09ad35cSguenther /* nothing to do by default */
206f09ad35cSguenther #ifndef	_TIB_PREP
207f09ad35cSguenther # define _TIB_PREP(tib)	((void)0)
208f09ad35cSguenther #endif
209f09ad35cSguenther 
210157c34b3Sguenther #define	TIB_INIT(tib, dtv, thread)	do {		\
211157c34b3Sguenther 		(tib)->tib_thread	= (thread);	\
21253213268Skettenis 		(tib)->tib_atexit	= NULL;		\
213f09ad35cSguenther 		(tib)->tib_locale	= NULL;		\
214fe38b55cSguenther 		(tib)->tib_cantcancel	= 0;		\
215fe38b55cSguenther 		(tib)->tib_cancel_point	= 0;		\
216fe38b55cSguenther 		(tib)->tib_canceled	= 0;		\
217f09ad35cSguenther 		(tib)->tib_dtv		= (dtv);	\
218f09ad35cSguenther 		(tib)->tib_errno	= 0;		\
219*9b42e9bfSmiod 		(tib)->tib_thread_flags = 0;		\
220f09ad35cSguenther 		_TIB_PREP(tib);				\
221f09ad35cSguenther 	} while (0)
222f09ad35cSguenther 
223f09ad35cSguenther #ifndef	__tib_tcb
224f09ad35cSguenther # define __tib_tcb		tib_dtv
225f09ad35cSguenther #endif
226fe38b55cSguenther #define	_TIBO_TCB		(offsetof(struct tib, __tib_tcb) + TCB_OFFSET)
227f09ad35cSguenther 
228f09ad35cSguenther #define	TCB_TO_TIB(tcb)		((struct tib *)((char *)(tcb) - _TIBO_TCB))
229f09ad35cSguenther #define	TIB_TO_TCB(tib)		((char *)(tib) + _TIBO_TCB)
230f09ad35cSguenther #define	TIB_GET()		TCB_TO_TIB(TCB_GET())
231f09ad35cSguenther 
232f09ad35cSguenther 
233f09ad35cSguenther __BEGIN_DECLS
234c0197e40Sguenther struct dl_info;
235c0197e40Sguenther struct dl_phdr_info;
236c0197e40Sguenther struct dl_cb_0 {
237c0197e40Sguenther 	void	*(*dl_allocate_tib)(size_t);
238c0197e40Sguenther 	void	 (*dl_free_tib)(void *, size_t);
239c0197e40Sguenther 	void	 (*dl_clean_boot)(void);
240c0197e40Sguenther 	void	*(*dlopen)(const char *, int);
241c0197e40Sguenther 	int	 (*dlclose)(void *);
242c0197e40Sguenther 	void	*(*dlsym)(void *, const char *);
243c0197e40Sguenther 	int	 (*dladdr)(const void *, struct dl_info *);
244c0197e40Sguenther 	int	 (*dlctl)(void *, int, void *);
245c0197e40Sguenther 	char	*(*dlerror)(void);
246c0197e40Sguenther 	int	 (*dl_iterate_phdr)(int (*)(struct dl_phdr_info *,
247c0197e40Sguenther 		    size_t, void *), void *);
248c0197e40Sguenther };
249c0197e40Sguenther 
250c0197e40Sguenther #define	DL_CB_CUR	0
251c0197e40Sguenther typedef	struct dl_cb_0	dl_cb;
252c0197e40Sguenther 
253c0197e40Sguenther /* type of function passed to init functions that returns a dl_cb */
254c0197e40Sguenther typedef	const void *dl_cb_cb(int _version);
255c0197e40Sguenther 
256157c34b3Sguenther void	*_dl_allocate_tib(size_t _extra) __dso_public;
257f09ad35cSguenther void	_dl_free_tib(void *_tib, size_t _extra) __dso_public;
258f09ad35cSguenther 
259f09ad35cSguenther /* The actual syscalls */
260f09ad35cSguenther void	*__get_tcb(void);
261f09ad35cSguenther void	__set_tcb(void *_tcb);
262f09ad35cSguenther __END_DECLS
263f09ad35cSguenther 
264f09ad35cSguenther #endif /* _TIB_H_ */
265