diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2013-02-14 03:38:16 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2013-02-14 03:38:16 +0000 |
commit | 7aa7079b8803602cb3f8e866d89b4cddae293c4e (patch) | |
tree | 28214dacf5c955a15f987af2f5916dcbe5230916 /lib | |
parent | 7d94210036c7bdc418abb2f8f20c3bf4950bd30e (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.c | 49 | ||||
-rw-r--r-- | lib/librthread/tcb.h | 17 |
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_ */ |