about summary refs log tree commit diff
path: root/nptl/cancellation.c
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/cancellation.c')
-rw-r--r--nptl/cancellation.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/nptl/cancellation.c b/nptl/cancellation.c
index 890b26ec4e..3cdc574880 100644
--- a/nptl/cancellation.c
+++ b/nptl/cancellation.c
@@ -20,6 +20,7 @@
 #include <setjmp.h>
 #include <stdlib.h>
 #include "pthreadP.h"
+#include "atomic.h"
 
 
 /* This function is responsible for calling all registered cleanup
@@ -90,3 +91,64 @@ __cleanup_thread (struct pthread *self, char *currentframe)
 	}
     }
 }
+
+
+/* The next two functions are similar to pthread_setcanceltype() but
+   more specialized for the use in the cancelable functions like write().
+   They do not need to check parameters etc.  */
+int
+attribute_hidden
+__pthread_enable_asynccancel (void)
+{
+  struct pthread *self = THREAD_SELF;
+  int oldval;
+
+  while (1)
+    {
+      oldval = THREAD_GETMEM (self, cancelhandling);
+      int newval = oldval | CANCELTYPE_BITMASK;
+
+      if (newval == oldval)
+	break;
+
+      if (atomic_compare_and_exchange_acq (&self->cancelhandling, newval,
+					   oldval) == 0)
+	{
+	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
+	    {
+	      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+	      __do_cancel (CURRENT_STACK_FRAME);
+	    }
+
+	  break;
+	}
+    }
+
+  return oldval;
+}
+
+
+void
+attribute_hidden
+__pthread_disable_asynccancel (int oldtype)
+{
+  /* If asynchronous cancellation was enabled before we do not have
+     anything to do.  */
+  if (oldtype & CANCELTYPE_BITMASK)
+    return;
+
+  struct pthread *self = THREAD_SELF;
+
+  while (1)
+    {
+      int oldval = THREAD_GETMEM (self, cancelhandling);
+      int newval = oldval & ~CANCELTYPE_BITMASK;
+
+      if (newval == oldval)
+	break;
+
+      if (atomic_compare_and_exchange_acq (&self->cancelhandling, newval,
+					   oldval) == 0)
+	break;
+    }
+}