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