summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2013-02-14 03:38:16 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2013-02-14 03:38:16 +0000
commit7aa7079b8803602cb3f8e866d89b4cddae293c4e (patch)
tree28214dacf5c955a15f987af2f5916dcbe5230916 /lib
parent7d94210036c7bdc418abb2f8f20c3bf4950bd30e (diff)
Make libpthread compatible with an ld.so that does TCB allocation:
if the initial thread already has a TCB then don't override it, and if the _dl_allocate_tls() and _dl_free_tls() symbols exist then use them instead of malloc/free ok kettenis@
Diffstat (limited to 'lib')
-rw-r--r--lib/librthread/rthread.c49
-rw-r--r--lib/librthread/tcb.h17
2 files changed, 47 insertions, 19 deletions
diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c
index f19fc926d49..bbf68d521b2 100644
--- a/lib/librthread/rthread.c
+++ b/lib/librthread/rthread.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread.c,v 1.66 2012/08/22 23:43:32 matthew Exp $ */
+/* $OpenBSD: rthread.c,v 1.67 2013/02/14 03:38:15 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -47,6 +47,9 @@
#include "rthread.h"
#include "tcb.h"
+#pragma weak _dl_allocate_tls
+#pragma weak _dl_free_tls
+
static int concurrency_level; /* not used */
int _threads_ready;
@@ -100,11 +103,20 @@ _spinunlock(_spinlock_lock_t *lock)
void _rthread_initlib(void) __attribute__((constructor));
void _rthread_initlib(void)
{
- struct thread_control_block *tcb = &_initial_thread_tcb;
+ struct thread_control_block *tcb = __get_tcb();
+
+ /*
+ * A newer ld.so may provide a TCB allocation for us.
+ * If not, use a static allocation
+ */
+ if (tcb == NULL) {
+ tcb = &_initial_thread_tcb;
+ tcb->tcb_dtv = 0;
+ TCB_SET(tcb);
+ }
/* use libc's errno for the main thread */
TCB_INIT(tcb, &_initial_thread, ___errno());
- TCB_SET(tcb);
}
int *
@@ -260,6 +272,30 @@ pthread_self(void)
return (TCB_THREAD());
}
+static inline struct thread_control_block *
+allocate_tcb(void)
+{
+ struct thread_control_block *tcb;
+
+ if (&_dl_allocate_tls != 0)
+ tcb = _dl_allocate_tls(NULL);
+ else {
+ tcb = malloc(sizeof(*tcb));
+ tcb->tcb_dtv = 0;
+ }
+ return (tcb);
+}
+
+static inline void
+free_tcb(struct thread_control_block *tcb)
+{
+ if (&_dl_free_tls != 0)
+ _dl_free_tls(tcb);
+ else
+ free(tcb);
+}
+
+
static void
_rthread_reaper(void)
{
@@ -275,8 +311,7 @@ restart:
_rthread_debug(3, "rthread reaping %p stack %p\n",
(void *)thread, (void *)thread->stack);
_rthread_free_stack(thread->stack);
- _rtld_free_tls(thread->arg,
- sizeof(struct thread_control_block), sizeof(void *));
+ free_tcb(thread->arg);
free(thread);
goto restart;
}
@@ -417,7 +452,7 @@ pthread_create(pthread_t *threadp, const pthread_attr_t *attr,
goto fail1;
}
- tcb = _rtld_allocate_tls(NULL, sizeof(*tcb), sizeof(void *));
+ tcb = allocate_tcb();
if (tcb == NULL) {
rc = errno;
goto fail2;
@@ -446,7 +481,7 @@ pthread_create(pthread_t *threadp, const pthread_attr_t *attr,
_spinlock(&_thread_lock);
LIST_REMOVE(thread, threads);
_spinunlock(&_thread_lock);
- _rtld_free_tls(tcb, sizeof(*tcb), sizeof(void *));
+ free_tcb(tcb);
fail2:
_rthread_free_stack(thread->stack);
fail1:
diff --git a/lib/librthread/tcb.h b/lib/librthread/tcb.h
index 43e2820e1e7..2139d21d6db 100644
--- a/lib/librthread/tcb.h
+++ b/lib/librthread/tcb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcb.h,v 1.4 2012/02/18 21:43:28 fgsch Exp $ */
+/* $OpenBSD: tcb.h,v 1.5 2013/02/14 03:38:15 guenther Exp $ */
/*
* Copyright (c) 2011 Philip Guenther <guenther@openbsd.org>
*
@@ -85,7 +85,6 @@ struct thread_control_block {
__ERRNOPTR(TCB_THREAD())
#define TCB_INIT(tcb, thread, errnoptr) \
do { \
- (tcb)->tcb_dtv = 0; \
(tcb)->tcb_thread = (thread); \
__ERRNOPTR(thread) = (errnoptr); \
} while (0)
@@ -113,7 +112,6 @@ struct thread_control_block {
#define TCB_INIT(tcb, thread, errnoptr) \
do { \
(tcb)->__tcb_self = (tcb); \
- (tcb)->tcb_dtv = 0; \
(tcb)->tcb_thread = (thread); \
(tcb)->__tcb_errno = (errnoptr); \
} while (0)
@@ -129,16 +127,11 @@ struct thread_control_block {
#define TCB_SET(tcb) __set_tcb(tcb)
#endif
-#if 0
-void *_rtld_allocate_tls(void *, size_t, size_t);
-void _rtld_free_tls(void *, size_t, size_t);
-#else
/*
- * XXX Until we have these in ld.so and support __thread, just use
- * malloc/free. The main thread's TCB cannot be allocated or freed with these.
+ * Functions that will eventually be provided by ld.so for allocating
+ * and freeing TCBs
*/
-#define _rtld_allocate_tls(old, size, align) malloc(size)
-#define _rtld_free_tls(old, size, align) free(old)
-#endif
+void *_dl_allocate_tls(void *);
+void _dl_free_tls(void *);
#endif /* _TCB_H_ */