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 * |
18 |
|
|
__errno(void) |
19 |
|
|
{ |
20 |
|
951334618 |
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 * |
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 * |
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 * |
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 |
|
|
}; |