1 /*	$OpenBSD: errno.c,v 1.6 2016/05/07 19:05:22 guenther Exp $ */
2 /* PUBLIC DOMAIN: No Rights Reserved.   Marco S Hyman <marc@snafu.org> */
3 
4 #include <tib.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include "thread_private.h"
8 
9 
10 #ifdef TCB_HAVE_MD_GET
11 /*
12  * If there's an MD TCB_GET() macro, then getting the TCB address is
13  * cheap enough that we can do it even in single-threaded programs,
14  * so the tc_errnoptr and tc_tcb callbacks will be unused, and __errno()
15  * can just use TIB_GET().
16  */
17 int *
__errno(void)18 __errno(void)
19 {
20 	return (&TIB_GET()->tib_errno);
21 }
22 DEF_STRONG(__errno);
23 
24 #else /* ! TCB_HAVE_MD_GET */
25 /*
26  * Otherwise, getting the TCB address requires the __get_tcb()
27  * syscall.  Rather than pay that cost for single-threaded programs,
28  * the syscall stubs will invoke the tc_errnoptr callback to set errno
29  * and other code will invoke the tc_tcb callback to get the TCB
30  * for cancelation checks, etc.  The default callbacks will just
31  * work from the cached location of the initial thread's TCB;
32  * libpthread can override them to the necessary more expensive
33  * versions that use __get_tcb().
34  */
35 
36 /* cached pointer to the TCB of the only thread in single-threaded programs */
37 void	*_libc_single_tcb = NULL;
38 
39 static inline void *
single_threaded_tcb(void)40 single_threaded_tcb(void)
41 {
42 	if (__predict_false(_libc_single_tcb == NULL))
43 		_libc_single_tcb = TCB_GET();
44 	return (_libc_single_tcb);
45 }
46 
47 static int *
single_threaded_errnoptr(void)48 single_threaded_errnoptr(void)
49 {
50 	return &TCB_TO_TIB(single_threaded_tcb())->tib_errno;
51 }
52 
53 /*
54  * __errno(): just use the callback to get the applicable current method
55  */
56 int *
__errno(void)57 __errno(void)
58 {
59 	return (_thread_cb.tc_errnoptr());
60 }
61 DEF_STRONG(__errno);
62 
63 #endif /* !TCB_HAVE_MD_GET */
64 
65 
66 struct thread_callbacks _thread_cb =
67 {
68 #ifndef	TCB_HAVE_MD_GET
69 	.tc_errnoptr	= &single_threaded_errnoptr,
70 	.tc_tcb		= &single_threaded_tcb,
71 #endif
72 };
73