diff options
-rw-r--r-- | libpthread/linuxthreads.old/cancel.c | 27 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/condvar.c | 8 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/internals.h | 4 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/join.c | 11 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/manager.c | 2 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/oldsemaphore.c | 2 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/pthread.c | 2 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/ptlongjmp.c | 21 | ||||
-rw-r--r-- | libpthread/linuxthreads.old/semaphore.c | 8 |
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; |