about summary refs log tree commit diff
path: root/nptl/pthreadP.h
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/pthreadP.h')
-rw-r--r--nptl/pthreadP.h48
1 files changed, 43 insertions, 5 deletions
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 1813a04583..94f169c564 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -74,7 +74,7 @@ extern int __pthread_debug attribute_hidden;
     if (CANCEL_ENABLED_AND_CANCELED (cancelhandling))			      \
       {									      \
 	THREAD_SETMEM (self, result, PTHREAD_CANCELED);			      \
-	__do_cancel (CURRENT_STACK_FRAME);				      \
+	__do_cancel ();							      \
       }									      \
   } while (0)
 
@@ -85,9 +85,41 @@ extern int __pthread_debug attribute_hidden;
 #define CANCEL_RESET(oldtype) \
   __pthread_disable_asynccancel (oldtype)
 
-/* Function performing the cancellation.  */
-extern void __do_cancel (char *currentframe)
-     __attribute ((visibility ("hidden"), noreturn, regparm (1)));
+/* Same as CANCEL_ASYNC, but for use in libc.so.  */
+#define LIBC_CANCEL_ASYNC() \
+  __libc_enable_asynccancel ()
+/* Same as CANCEL_RESET, but for use in libc.so.  */
+#define LIBC_CANCEL_RESET(oldtype) \
+  __libc_disable_asynccancel (oldtype)
+
+
+/* This function is responsible for calling all registered cleanup
+   handlers and then terminate the thread.  This includes dellocating
+   the thread-specific data.  The implementation is complicated by the
+   fact that we have to handle to cancellation handler registration
+   methods: exceptions using try/finally and setjmp.
+
+   The setjmp method is always available.  The user might compile some
+   code which uses this method because no modern compiler is
+   available.  So we have to handle these first since we cannot call
+   the cleanup handlers if the stack frames are gone.  At the same
+   time this opens a hole for the register exception handler blocks
+   since now they might be in danger of using an overwritten stack
+   frame.  The advise is to only use new or only old style cancellation
+   handling.  */
+static inline void
+__do_cancel (void)
+{
+  struct pthread *self = THREAD_SELF;
+
+  /* Throw an exception.  */
+  // XXX TBI
+
+  /* If throwing an exception didn't work try the longjmp.  */
+  __libc_longjmp (self->cancelbuf, 1);
+
+  /* NOTREACHED */
+}
 
 
 /* Test whether stackframe is still active.  */
@@ -186,7 +218,13 @@ extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void),
 extern int __pthread_kill (pthread_t threadid, int signo);
 extern int __pthread_setcanceltype (int type, int *oldtype);
 extern int __pthread_enable_asynccancel (void) attribute_hidden;
-extern void __pthread_disable_asynccancel (int oldtype) attribute_hidden;
+extern void __pthread_disable_asynccancel (int oldtype)
+     internal_function attribute_hidden;
+
+/* The two functions are in libc.so and not exported.  */
+extern int __libc_enable_asynccancel (void) attribute_hidden;
+extern void __libc_disable_asynccancel (int oldtype)
+     internal_function attribute_hidden;
 
 #ifdef IS_IN_libpthread
 /* Special versions which use non-exported functions.  */