summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/errno.c
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2016-05-07 19:05:21 +0000
committerguenther <guenther@openbsd.org>2016-05-07 19:05:21 +0000
commitfe38b55cb0aae270de3f844146814682e8cd345c (patch)
tree9825cc8aa96314e8e79ea1802ccbc9349772680b /lib/libc/gen/errno.c
parentImplement ACPI 5.0 GeneralPurposeIo OpRegion support. This basically allows (diff)
downloadwireguard-openbsd-fe38b55cb0aae270de3f844146814682e8cd345c.tar.xz
wireguard-openbsd-fe38b55cb0aae270de3f844146814682e8cd345c.zip
Use a Thread Information Block in both single and multi-threaded programs.
This stores errno, the cancelation flags, and related bits for each thread and is allocated by ld.so or libc.a. This is an ABI break from 5.9-stable! Make libpthread dlopen'able by moving the cancelation wrappers into libc and doing locking and fork/errno handling via callbacks that libpthread registers when it first initializes. 'errno' *must* be declared via <errno.h> now! Clean up libpthread's symbol exports like libc. On powerpc, offset the TIB/TCB/TLS data from the register per the ELF spec. Testing by various, particularly sthen@ and patrick@ ok kettenis@
Diffstat (limited to 'lib/libc/gen/errno.c')
-rw-r--r--lib/libc/gen/errno.c67
1 files changed, 59 insertions, 8 deletions
diff --git a/lib/libc/gen/errno.c b/lib/libc/gen/errno.c
index 62c0978c6aa..d706b0807a7 100644
--- a/lib/libc/gen/errno.c
+++ b/lib/libc/gen/errno.c
@@ -1,21 +1,72 @@
-/* $OpenBSD: errno.c,v 1.5 2005/08/08 08:05:34 espie Exp $ */
+/* $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>
-#undef errno
+#include <unistd.h>
+#include "thread_private.h"
+
+#ifdef TCB_HAVE_MD_GET
/*
- * global errno for unthreaded programs.
+ * 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;
+int *
+__errno(void)
+{
+ return (&TIB_GET()->tib_errno);
+}
+DEF_STRONG(__errno);
+#else /* ! TCB_HAVE_MD_GET */
/*
- * weak version of function used by unthreaded programs.
+ * 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)
+__errno(void)
{
- return &errno;
+ return (_thread_cb.tc_errnoptr());
}
+DEF_STRONG(__errno);
+
+#endif /* !TCB_HAVE_MD_GET */
-__weak_alias(__errno, ___errno);
+
+struct thread_callbacks _thread_cb =
+{
+#ifndef TCB_HAVE_MD_GET
+ .tc_errnoptr = &single_threaded_errnoptr,
+ .tc_tcb = &single_threaded_tcb,
+#endif
+};