diff options
author | Timo Teräs <timo.teras@iki.fi> | 2010-04-22 11:06:41 +0000 |
---|---|---|
committer | Austin Foxley <austinf@cetoncorp.com> | 2010-04-22 08:54:10 -0700 |
commit | 279c728ee62e53eb055227695bc6fafb31a3a5f1 (patch) | |
tree | d7ceb8ed28bec1266dfcfac8af1501948b8f9bda | |
parent | b93b98daf0dd45ac52f99fc4d906e5926cdd5239 (diff) |
nptl: fix libc internal, dynamically enabled locking
Final iteration to fix libc internal locking if libpthread is pulled
in by dlopen call (directly or indirectly).
We cannot really use the weak symbol trick for shared build, since
the symbols won't get refreshed if libpthread is pulled in dynamically.
In glibc, they have #ifdef SHARED magic to either use pthread_functions
table, or weaks. But as we shared object files with both builds, this
does not sounds good either.
The reintroduces the libc weaks.c, but uses them now only with static
build. For dynamic build, we still use the symbols with same name, but
provide weaks in forward.c so they end up dereferencing the
pthread_functions table indirectly if we are not linked to libpthread.
Mutex initialization is hard coded as inline, as it needs to happen even
if libpthread is not initially loaded.
Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
-rw-r--r-- | libc/misc/pthread/Makefile.in | 1 | ||||
-rw-r--r-- | libc/misc/pthread/weaks.c | 40 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/bits/uClibc_mutex.h | 17 | ||||
-rw-r--r-- | libpthread/nptl/forward.c | 20 |
4 files changed, 62 insertions, 16 deletions
diff --git a/libc/misc/pthread/Makefile.in b/libc/misc/pthread/Makefile.in index 2f436ac1c..69cdf104a 100644 --- a/libc/misc/pthread/Makefile.in +++ b/libc/misc/pthread/Makefile.in @@ -11,6 +11,7 @@ MISC_PTHREAD_DIR := $(top_srcdir)libc/misc/pthread MISC_PTHREAD_OUT := $(top_builddir)libc/misc/pthread libc-shared-$(UCLIBC_HAS_TLS) += $(MISC_PTHREAD_OUT)/tsd.os +libc-static-$(UCLIBC_HAS_THREADS) += $(MISC_PTHREAD_OUT)/weaks.o objclean-y += CLEAN_libc/misc/pthread diff --git a/libc/misc/pthread/weaks.c b/libc/misc/pthread/weaks.c new file mode 100644 index 000000000..fb1d85fd7 --- /dev/null +++ b/libc/misc/pthread/weaks.c @@ -0,0 +1,40 @@ +/* The weak pthread functions for Linux. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <libc-internal.h> + +/* Weaks for internal library use only. + * + * We need to define weaks here to cover all the pthread functions that + * libc itself will use so that we aren't forced to link libc against + * libpthread. This file is only used in libc.a and since we have + * weaks here, they will be automatically overridden by libpthread.a + * if it gets linked in. + */ + +static int __pthread_return_0 (void) { return 0; } +static void __pthread_return_void (void) { return; } + +weak_alias (__pthread_return_0, __pthread_mutex_init) +weak_alias (__pthread_return_0, __pthread_mutex_lock) +weak_alias (__pthread_return_0, __pthread_mutex_trylock) +weak_alias (__pthread_return_0, __pthread_mutex_unlock) +weak_alias (__pthread_return_void, _pthread_cleanup_push_defer) +weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore) + diff --git a/libc/sysdeps/linux/common/bits/uClibc_mutex.h b/libc/sysdeps/linux/common/bits/uClibc_mutex.h index 6d004bb74..3e3d0066a 100644 --- a/libc/sysdeps/linux/common/bits/uClibc_mutex.h +++ b/libc/sysdeps/linux/common/bits/uClibc_mutex.h @@ -15,13 +15,6 @@ #include <pthread.h> #include <bits/uClibc_pthread.h> -#define __uclibc_maybe_call(FUNC, ARGS) \ - (__extension__ ({ \ - __typeof (FUNC) *_fn = (FUNC); \ - if (_fn != NULL) { (*_fn) ARGS; } \ - })) - - #define __UCLIBC_MUTEX_TYPE pthread_mutex_t #define __UCLIBC_MUTEX(M) pthread_mutex_t M @@ -30,21 +23,21 @@ #define __UCLIBC_MUTEX_EXTERN(M) extern pthread_mutex_t M #define __UCLIBC_MUTEX_INIT_VAR(M) \ - __uclibc_maybe_call(__pthread_mutex_init,(&(M),NULL)) + ((M) = (pthread_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) #define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) \ - __uclibc_maybe_call(__pthread_mutex_lock,(&(M))) + __pthread_mutex_lock(&(M)) #define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) \ - __uclibc_maybe_call(__pthread_mutex_unlock,(&(M))) + __pthread_mutex_unlock(&(M)) #define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \ - __uclibc_maybe_call(__pthread_mutex_trylock,(&(M))) + __pthread_mutex_trylock,(&(M)) #define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) \ do { \ struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer; \ - int __infunc_need_locking = ((C) && (__pthread_mutex_lock != NULL)); \ + int __infunc_need_locking = (C); \ if (__infunc_need_locking) { \ _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer, \ (void (*) (void *))__pthread_mutex_unlock, \ diff --git a/libpthread/nptl/forward.c b/libpthread/nptl/forward.c index 8f528d0a8..7878334ac 100644 --- a/libpthread/nptl/forward.c +++ b/libpthread/nptl/forward.c @@ -35,10 +35,11 @@ int __libc_pthread_functions_init attribute_hidden; rettype \ name decl \ { \ - if (!__libc_pthread_functions_init) \ + if (!__libc_pthread_functions_init) { \ defaction; \ - \ - return PTHFCT_CALL (ptr_##name, params); \ + } else { \ + return PTHFCT_CALL (ptr_##name, params); \ + } \ } #define FORWARD(name, decl, params, defretval) \ @@ -130,9 +131,10 @@ FORWARD (pthread_mutex_init, (mutex, mutexattr), 0) FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) +weak_alias (pthread_mutex_lock, __pthread_mutex_lock) FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) - +weak_alias (pthread_mutex_unlock, __pthread_mutex_unlock) FORWARD2 (pthread_self, pthread_t, (void), (), return 0) @@ -143,6 +145,16 @@ FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) #define return /* value is void */ +FORWARD2(_pthread_cleanup_push_defer, + void, (struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg), + (buffer, routine, arg), + { buffer->__routine = routine; buffer->__arg = arg; }); + +FORWARD2(_pthread_cleanup_pop_restore, + void, (struct _pthread_cleanup_buffer *buffer, int execute), + (buffer, execute), + if (execute) { buffer->__routine(buffer->__arg); }); + FORWARD2(__pthread_unwind, void attribute_hidden __attribute ((noreturn)) __cleanup_fct_attribute, (__pthread_unwind_buf_t *buf), (buf), { |