diff options
author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-12-16 04:54:52 +0000 |
---|---|---|
committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-12-16 04:54:52 +0000 |
commit | 7dfaf230d2191da71f3078943ea09d014298e7b0 (patch) | |
tree | 11b16e846adf904f804b8ce15937db12d08259d8 /libpthread/linuxthreads.old/cancel.c | |
parent | 1bcf527f5f8c94aac1b2e80b585898a7266293af (diff) | |
download | uClibc-alpine-7dfaf230d2191da71f3078943ea09d014298e7b0.tar.bz2 uClibc-alpine-7dfaf230d2191da71f3078943ea09d014298e7b0.tar.xz |
Merge from trunk.
Diffstat (limited to 'libpthread/linuxthreads.old/cancel.c')
-rw-r--r-- | libpthread/linuxthreads.old/cancel.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/libpthread/linuxthreads.old/cancel.c b/libpthread/linuxthreads.old/cancel.c index 1356348a7..ac66c5855 100644 --- a/libpthread/linuxthreads.old/cancel.c +++ b/libpthread/linuxthreads.old/cancel.c @@ -25,6 +25,17 @@ #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) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif int pthread_setcancelstate(int state, int * oldstate) @@ -37,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; } @@ -51,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; } @@ -62,6 +73,7 @@ int pthread_cancel(pthread_t thread) int dorestart = 0; pthread_descr th; pthread_extricate_if *pextricate; + int already_canceled; __pthread_lock(&handle->h_lock, NULL); if (invalid_handle(handle, thread)) { @@ -71,13 +83,15 @@ int pthread_cancel(pthread_t thread) th = handle->h_descr; - if (th->p_canceled) { + already_canceled = th->p_canceled; + th->p_canceled = 1; + + if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) { __pthread_unlock(&handle->h_lock); return 0; } pextricate = th->p_extricate; - th->p_canceled = 1; pid = th->p_pid; /* If the thread has registered an extrication interface, then @@ -115,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, @@ -125,6 +139,8 @@ void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, buffer->__routine = routine; buffer->__arg = arg; buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; THREAD_SETMEM(self, p_cleanup, buffer); } @@ -144,6 +160,8 @@ void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, buffer->__arg = arg; buffer->__canceltype = THREAD_GETMEM(self, p_canceltype); buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); THREAD_SETMEM(self, p_cleanup, buffer); } @@ -158,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. */ |