summaryrefslogtreecommitdiffstats
path: root/lib/librthread/rthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/librthread/rthread.c')
-rw-r--r--lib/librthread/rthread.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c
index 710a3a97448..fa2a28d7ac7 100644
--- a/lib/librthread/rthread.c
+++ b/lib/librthread/rthread.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread.c,v 1.75 2013/11/29 16:27:40 guenther Exp $ */
+/* $OpenBSD: rthread.c,v 1.76 2013/12/12 08:12:08 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -104,13 +104,34 @@ _spinunlock(volatile struct _spinlock *lock)
* this is handled by __tfork_thread()
*/
void _rthread_initlib(void) __attribute__((constructor));
-void _rthread_initlib(void)
+void
+_rthread_initlib(void)
{
- struct thread_control_block *tcb = &_initial_thread_tcb;
+ static int tcb_set;
+ struct thread_control_block *tcb;
+
+ if (__predict_false(tcb_set == 0) && __get_tcb() == NULL) {
+ tcb_set = 1;
- /* use libc's errno for the main thread */
- TCB_INIT(tcb, &_initial_thread, ___errno());
- TCB_SET(tcb);
+ /* use libc's errno for the main thread */
+ tcb = &_initial_thread_tcb;
+ TCB_INIT(tcb, &_initial_thread, ___errno());
+ TCB_SET(tcb);
+ }
+}
+
+/*
+ * This is invoked by ___start() in crt0. Eventually, when ld.so handles
+ * TCB setup for dynamic executables, this will only be called to handle
+ * the TCB setup for static executables and may migrate to libc. The
+ * envp argument is so that it can (someday) use that to find the Auxinfo
+ * array and thus the ELF phdr and the PT_TLS info.
+ */
+void __init_tcb(char **_envp);
+void
+__init_tcb(__unused char **envp)
+{
+ _rthread_initlib();
}
int *
@@ -181,6 +202,8 @@ _rthread_init(void)
_thread_pagesize = (size_t)sysconf(_SC_PAGESIZE);
_rthread_attr_default.guard_size = _thread_pagesize;
+ _rthread_initlib();
+
_threads_ready = 1;
_rthread_debug(1, "rthread init\n");