diff options
author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-09-13 02:28:34 +0000 |
---|---|---|
committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-09-13 02:28:34 +0000 |
commit | 07a485defae1ef578c5b3ce0d4373201948a7345 (patch) | |
tree | 2184f0f32083bd47ef3b82ad016d8d710f8f221f /libpthread/linuxthreads/cancel.c | |
parent | 224ca9f63688cdecd80ed01c25f5f62871fe4cfc (diff) | |
download | uClibc-alpine-07a485defae1ef578c5b3ce0d4373201948a7345.tar.bz2 uClibc-alpine-07a485defae1ef578c5b3ce0d4373201948a7345.tar.xz |
Merge with trunk. "So do that funky merge whiiite boy..."
Diffstat (limited to 'libpthread/linuxthreads/cancel.c')
-rw-r--r-- | libpthread/linuxthreads/cancel.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/libpthread/linuxthreads/cancel.c b/libpthread/linuxthreads/cancel.c index 1356348a7..dbba7eef4 100644 --- a/libpthread/linuxthreads/cancel.c +++ b/libpthread/linuxthreads/cancel.c @@ -26,6 +26,14 @@ extern void __rpc_thread_destroy(void); #endif +#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) { @@ -62,28 +70,31 @@ 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)) { + if (nonexisting_handle(handle, thread)) { __pthread_unlock(&handle->h_lock); return ESRCH; } 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 invoke the interface. If it returns 1, then we succeeded in dequeuing the thread from whatever waiting object it was enqueued - with. In that case, it is our responsibility to wake it up. + with. In that case, it is our responsibility to wake it up. And also to set the p_woken_by_cancel flag so the woken thread can tell that it was woken by cancellation. */ @@ -125,6 +136,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 +157,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); } |