summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2010-04-22 11:06:41 +0000
committerAustin Foxley <austinf@cetoncorp.com>2010-04-22 08:54:10 -0700
commit279c728ee62e53eb055227695bc6fafb31a3a5f1 (patch)
treed7ceb8ed28bec1266dfcfac8af1501948b8f9bda
parentb93b98daf0dd45ac52f99fc4d906e5926cdd5239 (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.in1
-rw-r--r--libc/misc/pthread/weaks.c40
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_mutex.h17
-rw-r--r--libpthread/nptl/forward.c20
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), {