summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2006-11-09 08:11:33 +0000
committerMike Frysinger <vapier@gentoo.org>2006-11-09 08:11:33 +0000
commit087d97a0a8349e5ddb23c7476b464a0eac85409a (patch)
tree189538f3cd8b173265d83133a02eccebed9bffeb
parentf0d13fdd5d5f11847ce6d5b148e167e7999e075e (diff)
backport from upstream:
2001-04-10 Ulrich Drepper <drepper@redhat.com> * join.c (pthread_exit): Move code to new function __pthread_do_exit which takes an extra parameter with the current frame pointer. Call new function with CURRENT_STACK_FRAME. (__pthread_do_exit): New function. Call __pthread_perform_cleanup with the new parameter. (pthread_join): Call __pthread_do_exit instead of pthread_exit. * cancel.c (__pthread_perform_cleanup): Takes extra parameter. Use this parameter as the initial value the cleanup handler records are compared against. No active cleanup handler record must have an address lower than the previous one and the initial record must be above (below on PA) the frame address passed in. (pthread_setcancelstate): Call __pthread_do_exit instead of pthread_exit. (pthread_setcanceltype): Likewise. (pthread_testcancel): Likewise. (_pthread_cleanup_pop_restore): Likewise. * condvar.c (pthread_cond_wait): Likewise. (pthread_cond_timedwait_relative): Likewise. * manager.c (pthread_start_thread): Likewise. * oldsemaphore.c (__old_sem_wait): Likewise. * pthread.c (pthread_handle_sigcancel): Likewise. * semaphore.c (__new_sem_wait): Likewise. (sem_timedwait): Likewise. * ptlongjmp.c (pthread_cleanup_upto): Also use current stack frame to limit the cleanup handlers which get run. * internals.h: Add prototype for __pthread_do_exit. Adjust prototype for __pthread_perform_cleanup.
-rw-r--r--libpthread/linuxthreads.old/cancel.c27
-rw-r--r--libpthread/linuxthreads.old/condvar.c8
-rw-r--r--libpthread/linuxthreads.old/internals.h4
-rw-r--r--libpthread/linuxthreads.old/join.c11
-rw-r--r--libpthread/linuxthreads.old/manager.c2
-rw-r--r--libpthread/linuxthreads.old/oldsemaphore.c2
-rw-r--r--libpthread/linuxthreads.old/pthread.c2
-rw-r--r--libpthread/linuxthreads.old/ptlongjmp.c21
-rw-r--r--libpthread/linuxthreads.old/semaphore.c8
9 files changed, 63 insertions, 22 deletions
diff --git a/libpthread/linuxthreads.old/cancel.c b/libpthread/linuxthreads.old/cancel.c
index 25b098dd5..ac66c5855 100644
--- a/libpthread/linuxthreads.old/cancel.c
+++ b/libpthread/linuxthreads.old/cancel.c
@@ -25,6 +25,9 @@
#include <rpc/rpc.h>
extern void __rpc_thread_destroy(void);
#endif
+#include <bits/stackinfo.h>
+
+#include <stdio.h>
#ifdef _STACK_GROWS_DOWN
# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other)
@@ -45,7 +48,7 @@ int pthread_setcancelstate(int state, int * oldstate)
if (THREAD_GETMEM(self, p_canceled) &&
THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
return 0;
}
@@ -59,7 +62,7 @@ int pthread_setcanceltype(int type, int * oldtype)
if (THREAD_GETMEM(self, p_canceled) &&
THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
return 0;
}
@@ -126,7 +129,7 @@ void pthread_testcancel(void)
pthread_descr self = thread_self();
if (THREAD_GETMEM(self, p_canceled)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
@@ -173,15 +176,27 @@ void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
if (THREAD_GETMEM(self, p_canceled) &&
THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
-void __pthread_perform_cleanup(void)
+void __pthread_perform_cleanup(char *currentframe)
{
pthread_descr self = thread_self();
struct _pthread_cleanup_buffer * c;
+
for (c = THREAD_GETMEM(self, p_cleanup); c != NULL; c = c->__prev)
- c->__routine(c->__arg);
+ {
+#if _STACK_GROWS_DOWN
+ if ((char *) c <= currentframe)
+ break;
+#elif _STACK_GROWS_UP
+ if ((char *) c >= currentframe)
+ break;
+#else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+#endif
+ c->__routine(c->__arg);
+ }
#ifdef __UCLIBC_HAS_RPC__
/* And the TSD which needs special help. */
diff --git a/libpthread/linuxthreads.old/condvar.c b/libpthread/linuxthreads.old/condvar.c
index 62df907c1..3d77f781a 100644
--- a/libpthread/linuxthreads.old/condvar.c
+++ b/libpthread/linuxthreads.old/condvar.c
@@ -93,7 +93,7 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
if (already_canceled) {
__pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
__pthread_mutex_unlock(mutex);
@@ -122,7 +122,7 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
THREAD_SETMEM(self, p_woken_by_cancel, 0);
__pthread_mutex_lock(mutex);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
/* Put back any resumes we caught that don't belong to us. */
@@ -168,7 +168,7 @@ pthread_cond_timedwait_relative(pthread_cond_t *cond,
if (already_canceled) {
__pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
__pthread_mutex_unlock(mutex);
@@ -216,7 +216,7 @@ pthread_cond_timedwait_relative(pthread_cond_t *cond,
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
THREAD_SETMEM(self, p_woken_by_cancel, 0);
__pthread_mutex_lock(mutex);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
/* Put back any resumes we caught that don't belong to us. */
diff --git a/libpthread/linuxthreads.old/internals.h b/libpthread/linuxthreads.old/internals.h
index bd4d8ae13..ab227d6cc 100644
--- a/libpthread/linuxthreads.old/internals.h
+++ b/libpthread/linuxthreads.old/internals.h
@@ -448,8 +448,10 @@ extern int __librt_multiple_threads;
/* Internal global functions */
+void __pthread_do_exit (void *retval, char *currentframe)
+ __attribute__ ((__noreturn__));
void __pthread_destroy_specifics(void);
-void __pthread_perform_cleanup(void);
+void __pthread_perform_cleanup(char *currentframe);
int __pthread_initialize_manager(void);
void __pthread_message(char * fmt, ...);
int __pthread_manager(void *reqfd);
diff --git a/libpthread/linuxthreads.old/join.c b/libpthread/linuxthreads.old/join.c
index 6a8a9d982..f249a8114 100644
--- a/libpthread/linuxthreads.old/join.c
+++ b/libpthread/linuxthreads.old/join.c
@@ -27,6 +27,11 @@
void pthread_exit(void * retval)
{
+ __pthread_do_exit (retval, CURRENT_STACK_FRAME);
+}
+
+void __pthread_do_exit(void *retval, char *currentframe)
+{
pthread_descr self = thread_self();
pthread_descr joining;
struct pthread_request request;
@@ -36,7 +41,7 @@ void pthread_exit(void * retval)
contain cancellation points */
THREAD_SETMEM(self, p_canceled, 0);
/* Call cleanup functions and destroy the thread-specific data */
- __pthread_perform_cleanup();
+ __pthread_perform_cleanup(currentframe);
__pthread_destroy_specifics();
/* Store return value */
__pthread_lock(THREAD_GETMEM(self, p_lock), self);
@@ -150,7 +155,7 @@ int pthread_join(pthread_t thread_id, void ** thread_return)
if (already_canceled) {
__pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
PDEBUG("before suspend\n");
@@ -163,7 +168,7 @@ int pthread_join(pthread_t thread_id, void ** thread_return)
if (THREAD_GETMEM(self, p_woken_by_cancel)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
__pthread_lock(&handle->h_lock, self);
}
diff --git a/libpthread/linuxthreads.old/manager.c b/libpthread/linuxthreads.old/manager.c
index dbbee3f6f..cad2aacdf 100644
--- a/libpthread/linuxthreads.old/manager.c
+++ b/libpthread/linuxthreads.old/manager.c
@@ -309,7 +309,7 @@ pthread_start_thread(void *arg)
outcome = self->p_start_args.start_routine(THREAD_GETMEM(self,
p_start_args.arg));
/* Exit with the given return value */
- pthread_exit(outcome);
+ __pthread_do_exit(outcome, CURRENT_STACK_FRAME);
}
static int
diff --git a/libpthread/linuxthreads.old/oldsemaphore.c b/libpthread/linuxthreads.old/oldsemaphore.c
index 6e91dc3c7..178affa1b 100644
--- a/libpthread/linuxthreads.old/oldsemaphore.c
+++ b/libpthread/linuxthreads.old/oldsemaphore.c
@@ -136,7 +136,7 @@ int __old_sem_wait(old_sem_t * sem)
}
}
}
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
}
}
diff --git a/libpthread/linuxthreads.old/pthread.c b/libpthread/linuxthreads.old/pthread.c
index d9adfa432..2efb4d2d4 100644
--- a/libpthread/linuxthreads.old/pthread.c
+++ b/libpthread/linuxthreads.old/pthread.c
@@ -819,7 +819,7 @@ static void pthread_handle_sigcancel(int sig)
if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
if (jmpbuf != NULL) {
THREAD_SETMEM(self, p_cancel_jmp, NULL);
diff --git a/libpthread/linuxthreads.old/ptlongjmp.c b/libpthread/linuxthreads.old/ptlongjmp.c
index 055a217d3..b3ff2746f 100644
--- a/libpthread/linuxthreads.old/ptlongjmp.c
+++ b/libpthread/linuxthreads.old/ptlongjmp.c
@@ -18,6 +18,7 @@
#include <setjmp.h>
#include "pthread.h"
#include "internals.h"
+#include <bits/stackinfo.h>
/* These functions are not declared anywhere since they shouldn't be
used at another place but here. */
@@ -28,11 +29,29 @@ static void pthread_cleanup_upto(__jmp_buf target)
{
pthread_descr self = thread_self();
struct _pthread_cleanup_buffer * c;
+ char *currentframe = CURRENT_STACK_FRAME;
for (c = THREAD_GETMEM(self, p_cleanup);
c != NULL && _JMPBUF_UNWINDS(target, c);
c = c->__prev)
- c->__routine(c->__arg);
+ {
+#if _STACK_GROWS_DOWN
+ if ((char *) c <= currentframe)
+ {
+ c = NULL;
+ break;
+ }
+#elif _STACK_GROWS_UP
+ if ((char *) c >= currentframe)
+ {
+ c = NULL;
+ break;
+ }
+#else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+#endif
+ c->__routine(c->__arg);
+ }
THREAD_SETMEM(self, p_cleanup, c);
if (THREAD_GETMEM(self, p_in_sighandler)
&& _JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler)))
diff --git a/libpthread/linuxthreads.old/semaphore.c b/libpthread/linuxthreads.old/semaphore.c
index a44f52411..7502b6e78 100644
--- a/libpthread/linuxthreads.old/semaphore.c
+++ b/libpthread/linuxthreads.old/semaphore.c
@@ -87,7 +87,7 @@ int __new_sem_wait(sem_t * sem)
if (already_canceled) {
__pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
/* Wait for sem_post or cancellation, or fall through if already canceled */
@@ -113,7 +113,7 @@ int __new_sem_wait(sem_t * sem)
if (THREAD_GETMEM(self, p_woken_by_cancel)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
/* We got the semaphore */
return 0;
@@ -252,7 +252,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime)
if (already_canceled) {
__pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
spurious_wakeup_count = 0;
@@ -297,7 +297,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime)
if (THREAD_GETMEM(self, p_woken_by_cancel)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_exit(PTHREAD_CANCELED);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
/* We got the semaphore */
return 0;