Commit e4302cc0 authored by Natanael Copa's avatar Natanael Copa

core/uclibc: fix the pthread aliasing + patch from upstream

For details:
http://lists.uclibc.org/pipermail/uclibc/2009-June/042578.html
parent f912479a
From 52c9ef85a65f4dc25a4d1ff79c0fba1ed53ef43a Mon Sep 17 00:00:00 2001
From: Denis Vlasenko <vda.linux@googlemail.com>
Date: Thu, 12 Mar 2009 20:56:59 +0000
Subject: [PATCH 01/39] linuxthreads fixes from Will Newton (will.newton AT gmail.com):
* share Sys V semaphores in order to get appropriate SEM_UNDO semantics.
* correct guardaddr in pthread_free() for TLS case
* move spinlock unlocking before restart()
* When exit was called from a signal handler, the restart
from the manager processing the exit request instead restarted the thread
in pthread_cond_timedwait.
(see http://sources.redhat.com/ml/libc-ports/2006-05/msg00000.html)
---
libpthread/linuxthreads/descr.h | 2 --
libpthread/linuxthreads/manager.c | 15 ++++++++-------
libpthread/linuxthreads/pthread.c | 26 +++++++++++++++-----------
libpthread/linuxthreads/specific.c | 10 ++++++----
libpthread/linuxthreads/spinlock.c | 14 +++++++++++++-
libpthread/linuxthreads/spinlock.h | 6 ++++--
libpthread/linuxthreads/sysdeps/i386/tls.h | 2 --
7 files changed, 46 insertions(+), 29 deletions(-)
diff --git a/libpthread/linuxthreads/descr.h b/libpthread/linuxthreads/descr.h
index 24ec30b..47a9acd 100644
--- a/libpthread/linuxthreads/descr.h
+++ b/libpthread/linuxthreads/descr.h
@@ -123,9 +123,7 @@ struct _pthread_descr_struct
union dtv *dtvp;
pthread_descr self; /* Pointer to this structure */
int multiple_threads;
-# ifdef NEED_DL_SYSINFO
uintptr_t sysinfo;
-# endif
} data;
void *__padding[16];
} p_header;
diff --git a/libpthread/linuxthreads/manager.c b/libpthread/linuxthreads/manager.c
index be1e8d2..b068d6c 100644
--- a/libpthread/linuxthreads/manager.c
+++ b/libpthread/linuxthreads/manager.c
@@ -742,15 +742,15 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
pid = __clone2(pthread_start_thread_event,
(void **)new_thread_bottom,
(char *)stack_addr - new_thread_bottom,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
__pthread_sig_cancel, new_thread);
#elif _STACK_GROWS_UP
pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
__pthread_sig_cancel, new_thread);
#else
pid = __clone(pthread_start_thread_event, stack_addr,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
__pthread_sig_cancel, new_thread);
#endif
saved_errno = errno;
@@ -783,15 +783,15 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
pid = __clone2(pthread_start_thread,
(void **)new_thread_bottom,
(char *)stack_addr - new_thread_bottom,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
__pthread_sig_cancel, new_thread);
#elif _STACK_GROWS_UP
pid = __clone(pthread_start_thread, (void *) new_thread_bottom,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
__pthread_sig_cancel, new_thread);
#else
pid = __clone(pthread_start_thread, stack_addr,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
__pthread_sig_cancel, new_thread);
#endif /* !NEED_SEPARATE_REGISTER_STACK */
saved_errno = errno;
@@ -892,10 +892,11 @@ static void pthread_free(pthread_descr th)
#ifdef _STACK_GROWS_UP
# ifdef USE_TLS
size_t stacksize = guardaddr - th->p_stackaddr;
+ guardaddr = th->p_stackaddr;
# else
size_t stacksize = guardaddr - (char *)th;
-# endif
guardaddr = (char *)th;
+# endif
#else
/* Guardaddr is always set, even if guardsize is 0. This allows
us to compute everything else. */
diff --git a/libpthread/linuxthreads/pthread.c b/libpthread/linuxthreads/pthread.c
index 91333f2..4d1d906 100644
--- a/libpthread/linuxthreads/pthread.c
+++ b/libpthread/linuxthreads/pthread.c
@@ -740,17 +740,17 @@ int __pthread_initialize_manager(void)
pid = __clone2(__pthread_manager_event,
(void **) __pthread_manager_thread_bos,
THREAD_MANAGER_STACK_SIZE,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
mgr);
#elif _STACK_GROWS_UP
pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_bos,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
mgr);
#else
pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_tos,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM,
mgr);
#endif
@@ -780,13 +780,13 @@ int __pthread_initialize_manager(void)
#ifdef NEED_SEPARATE_REGISTER_STACK
pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
THREAD_MANAGER_STACK_SIZE,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
#elif _STACK_GROWS_UP
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
#else
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr);
#endif
}
if (__builtin_expect (pid, 0) == -1) {
@@ -972,6 +972,10 @@ static void pthread_onexit_process(int retcode, void *arg)
struct pthread_request request;
pthread_descr self = thread_self();
+ /* Make sure we come back here after suspend(), in case we entered
+ from a signal handler. */
+ THREAD_SETMEM(self, p_signal_jmp, NULL);
+
request.req_thread = self;
request.req_kind = REQ_PROCESS_EXIT;
request.req_args.exit.code = retcode;
@@ -1201,13 +1205,13 @@ void __pthread_wait_for_restart_signal(pthread_descr self)
void __pthread_restart_old(pthread_descr th)
{
- if (atomic_increment(&th->p_resume_count) == -1)
+ if (pthread_atomic_increment(&th->p_resume_count) == -1)
kill(th->p_pid, __pthread_sig_restart);
}
void __pthread_suspend_old(pthread_descr self)
{
- if (atomic_decrement(&self->p_resume_count) <= 0)
+ if (pthread_atomic_decrement(&self->p_resume_count) <= 0)
__pthread_wait_for_restart_signal(self);
}
@@ -1218,7 +1222,7 @@ __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime)
int was_signalled = 0;
sigjmp_buf jmpbuf;
- if (atomic_decrement(&self->p_resume_count) == 0) {
+ if (pthread_atomic_decrement(&self->p_resume_count) == 0) {
/* Set up a longjmp handler for the restart signal, unblock
the signal and sleep. */
@@ -1275,9 +1279,9 @@ __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime)
being delivered. */
if (!was_signalled) {
- if (atomic_increment(&self->p_resume_count) != -1) {
+ if (pthread_atomic_increment(&self->p_resume_count) != -1) {
__pthread_wait_for_restart_signal(self);
- atomic_decrement(&self->p_resume_count); /* should be zero now! */
+ pthread_atomic_decrement(&self->p_resume_count); /* should be zero now! */
/* woke spontaneously and consumed restart signal */
return 1;
}
diff --git a/libpthread/linuxthreads/specific.c b/libpthread/linuxthreads/specific.c
index 92eec3d..764bf1e 100644
--- a/libpthread/linuxthreads/specific.c
+++ b/libpthread/linuxthreads/specific.c
@@ -104,13 +104,14 @@ int pthread_key_delete(pthread_key_t key)
that if the key is reallocated later by pthread_key_create, its
associated values will be NULL in all threads.
- If no threads have been created yet, clear it just in the
- current thread. */
+ If no threads have been created yet, or if we are exiting, clear
+ it just in the current thread. */
struct pthread_key_delete_helper_args args;
args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
- if (__pthread_manager_request != -1)
+ if (__pthread_manager_request != -1
+ && !(__builtin_expect (__pthread_exit_requested, 0)))
{
struct pthread_request request;
@@ -203,8 +204,9 @@ void __pthread_destroy_specifics()
__pthread_lock(THREAD_GETMEM(self, p_lock), self);
for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) {
if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) {
- free(THREAD_GETMEM_NC(self, p_specific[i]));
+ void *p = THREAD_GETMEM_NC(self, p_specific[i]);
THREAD_SETMEM_NC(self, p_specific[i], NULL);
+ free(p);
}
}
__pthread_unlock(THREAD_GETMEM(self, p_lock));
diff --git a/libpthread/linuxthreads/spinlock.c b/libpthread/linuxthreads/spinlock.c
index f325402..f0cf19c 100644
--- a/libpthread/linuxthreads/spinlock.c
+++ b/libpthread/linuxthreads/spinlock.c
@@ -637,8 +637,20 @@ void __pthread_alt_unlock(struct _pthread_fastlock *lock)
#if defined HAS_COMPARE_AND_SWAP
wait_node_dequeue(pp_head, pp_max_prio, p_max_prio);
#endif
+
+ /* Release the spinlock *before* restarting. */
+#if defined TEST_FOR_COMPARE_AND_SWAP
+ if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+ {
+ __pthread_release(&lock->__spinlock);
+ }
+#endif
+
restart(p_max_prio->thr);
- break;
+
+ return;
}
}
diff --git a/libpthread/linuxthreads/spinlock.h b/libpthread/linuxthreads/spinlock.h
index 210ead4..2a3c227 100644
--- a/libpthread/linuxthreads/spinlock.h
+++ b/libpthread/linuxthreads/spinlock.h
@@ -172,7 +172,8 @@ static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock)
/* Operations on pthread_atomic, which is defined in internals.h */
-static __inline__ long atomic_increment(struct pthread_atomic *pa)
+static __inline__ long
+pthread_atomic_increment (struct pthread_atomic *pa)
{
long oldval;
@@ -184,7 +185,8 @@ static __inline__ long atomic_increment(struct pthread_atomic *pa)
}
-static __inline__ long atomic_decrement(struct pthread_atomic *pa)
+static __inline__ long
+pthread_atomic_decrement (struct pthread_atomic *pa)
{
long oldval;
diff --git a/libpthread/linuxthreads/sysdeps/i386/tls.h b/libpthread/linuxthreads/sysdeps/i386/tls.h
index 2abd3a0..4c9b680 100644
--- a/libpthread/linuxthreads/sysdeps/i386/tls.h
+++ b/libpthread/linuxthreads/sysdeps/i386/tls.h
@@ -46,9 +46,7 @@ typedef struct
dtv_t *dtv;
void *self; /* Pointer to the thread descriptor. */
int multiple_threads;
-#ifdef NEED_DL_SYSINFO
uintptr_t sysinfo;
-#endif
} tcbhead_t;
#else /* __ASSEMBLER__ */
--
1.6.3.2
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=uclibc
pkgver=0.9.30.1
pkgrel=7
pkgrel=8
pkgdesc="C library for developing embedded Linux systems"
url=http://uclibc.org
license="LGPL-2"
......@@ -14,6 +14,8 @@ source="http://uclibc.org/downloads/$_mynamever.tar.bz2
$pkgname-0.9.30.1-resolv.patch
uclibc-0.9.30.1-pthread_getattr_np.patch
0001-ldd-segfault-fix.patch
0001-linuxthreads-fixes-from-Will-Newton-will.newton-AT-g.patch
pthread-new-aliasing-fix.diff
ppoll.patch
uclibcconfig
"
......@@ -22,7 +24,7 @@ _prepare() {
local i gcc_major
cd "$srcdir/$_mynamever/"
# patches goes here
for i in ../*.patch; do
for i in ../*.patch ../*.diff; do
msg "Applying $i..."
patch -p1 < $i || return 1
done
......@@ -49,5 +51,7 @@ md5sums="1a4b84e5536ad8170563ffa88c34679c uClibc-0.9.30.1.tar.bz2
ea91460617601b6e084ead66bc3948f5 uclibc-0.9.30.1-resolv.patch
cf80c0d44a41e02f389be427ee615d61 uclibc-0.9.30.1-pthread_getattr_np.patch
4079b20c763727863bc53408e4988434 0001-ldd-segfault-fix.patch
bcd1c4c9c87f092fb4631559e6ec13ba 0001-linuxthreads-fixes-from-Will-Newton-will.newton-AT-g.patch
969187e1da84d0a0a5957b392a3d5a2b pthread-new-aliasing-fix.diff
60738298e377295d359768a09adac0bb ppoll.patch
0a87f57d3e5001027f43b7c959d96319 uclibcconfig"
diff --git a/libpthread/linuxthreads/cancel.c b/libpthread/linuxthreads/cancel.c
index 3435680..1412b57 100644
--- a/libpthread/linuxthreads/cancel.c
+++ b/libpthread/linuxthreads/cancel.c
@@ -152,8 +152,8 @@ void pthread_testcancel(void)
__pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
-void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
- void (*routine)(void *), void * arg)
+void __pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
+ void (*routine)(void *), void * arg)
{
pthread_descr self = thread_self();
buffer->__routine = routine;
@@ -163,17 +163,19 @@ void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
buffer->__prev = NULL;
THREAD_SETMEM(self, p_cleanup, buffer);
}
+strong_alias(__pthread_cleanup_push, _pthread_cleanup_push);
-void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer,
- int execute)
+void __pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer,
+ int execute)
{
pthread_descr self = thread_self();
if (execute) buffer->__routine(buffer->__arg);
THREAD_SETMEM(self, p_cleanup, buffer->__prev);
}
+strong_alias(__pthread_cleanup_pop, _pthread_cleanup_pop);
-void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
- void (*routine)(void *), void * arg)
+void __pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
+ void (*routine)(void *), void * arg)
{
pthread_descr self = thread_self();
buffer->__routine = routine;
@@ -185,9 +187,10 @@ void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED);
THREAD_SETMEM(self, p_cleanup, buffer);
}
+strong_alias(__pthread_cleanup_push_defer, _pthread_cleanup_push_defer);
-void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
- int execute)
+void __pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
+ int execute)
{
pthread_descr self = thread_self();
if (execute) buffer->__routine(buffer->__arg);
@@ -198,6 +201,7 @@ void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
__pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
+strong_alias(__pthread_cleanup_pop_restore, _pthread_cleanup_pop_restore);
extern void __rpc_thread_destroy(void);
void __pthread_perform_cleanup(char *currentframe)
diff --git a/libpthread/linuxthreads/forward.c b/libpthread/linuxthreads/forward.c
index f9f8ea1..385e79f 100644
--- a/libpthread/linuxthreads/forward.c
+++ b/libpthread/linuxthreads/forward.c
@@ -24,6 +24,10 @@
/* psm: keep this before internals.h */
/* libc_hidden_proto(exit) */
+#define hidden_strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name), \
+ visibility ("hidden")));
+
#include "internals.h"
/* Pointers to the libc functions. */
@@ -104,8 +108,7 @@ FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */
FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS))
-strong_alias (__pthread_exit, pthread_exit)
-
+hidden_strong_alias (__pthread_exit, pthread_exit)
FORWARD (pthread_getschedparam,
(pthread_t target_thread, int *policy, struct sched_param *param),
@@ -120,16 +123,16 @@ FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0)
FORWARD (pthread_mutex_init,
(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr),
(mutex, mutexattr), 0)
-strong_alias(pthread_mutex_init, __pthread_mutex_init)
+hidden_strong_alias(pthread_mutex_init, __pthread_mutex_init)
FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0)
-strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
+hidden_strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0)
-strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
+hidden_strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0)
-strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
+hidden_strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
FORWARD2 (pthread_self, pthread_t, (void), (), return 0)
diff --git a/libpthread/linuxthreads/internals.h b/libpthread/linuxthreads/internals.h
index eb0a519..4ad6a0d 100644
--- a/libpthread/linuxthreads/internals.h
+++ b/libpthread/linuxthreads/internals.h
@@ -380,6 +380,17 @@ extern int __pthread_setschedparam (pthread_t thread, int policy,
extern int __pthread_setcancelstate (int state, int * oldstate);
extern int __pthread_setcanceltype (int type, int * oldtype);
+extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+ void (*__routine) (void *),
+ void *__arg) __THROW;
+extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+ int __execute) __THROW;
+extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
+ void (*__routine) (void *),
+ void *__arg) __THROW;
+extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
+ int __execute) __THROW;
+
extern void __pthread_restart_old(pthread_descr th);
extern void __pthread_suspend_old(pthread_descr self);
extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime);
diff --git a/libpthread/linuxthreads/pthread.c b/libpthread/linuxthreads/pthread.c
index 4d1d906..012b74b 100644
--- a/libpthread/linuxthreads/pthread.c
+++ b/libpthread/linuxthreads/pthread.c
@@ -280,10 +280,10 @@ struct pthread_functions __pthread_functions =
.ptr_pthread_sigaction = __pthread_sigaction,
.ptr_pthread_sigwait = __pthread_sigwait,
.ptr_pthread_raise = __pthread_raise,
- .ptr__pthread_cleanup_push = _pthread_cleanup_push,
- .ptr__pthread_cleanup_push_defer = _pthread_cleanup_push_defer,
- .ptr__pthread_cleanup_pop = _pthread_cleanup_pop,
- .ptr__pthread_cleanup_pop_restore = _pthread_cleanup_pop_restore,
+ .ptr__pthread_cleanup_push = __pthread_cleanup_push,
+ .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer,
+ .ptr__pthread_cleanup_pop = __pthread_cleanup_pop,
+ .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore,
};
#ifdef SHARED
# define ptr_pthread_functions &__pthread_functions
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment