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
137struct 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
177struct 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
234struct dl_info;
235struct dl_phdr_info;
236struct 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
251typedef	struct dl_cb_0	dl_cb;
252
253/* type of function passed to init functions that returns a dl_cb */
254typedef	const void *dl_cb_cb(int _version);
255
256void	*_dl_allocate_tib(size_t _extra) __dso_public;
257void	_dl_free_tib(void *_tib, size_t _extra) __dso_public;
258
259/* The actual syscalls */
260void	*__get_tcb(void);
261void	__set_tcb(void *_tcb);
262__END_DECLS
263
264#endif /* _TIB_H_ */
265