summary refs log tree commit diff
path: root/nptl/cancellation.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-12-08 08:25:05 +0000
committerUlrich Drepper <drepper@redhat.com>2002-12-08 08:25:05 +0000
commitbdb04f922004ff8433591f138e40c09722836c45 (patch)
tree965b2db38d2cd7f9fb5114a10d53e3ddcc2bfad4 /nptl/cancellation.c
parent3335502bec2220c7d1e89929d489c1a91a1d862b (diff)
downloadglibc-bdb04f922004ff8433591f138e40c09722836c45.tar.gz
glibc-bdb04f922004ff8433591f138e40c09722836c45.tar.xz
glibc-bdb04f922004ff8433591f138e40c09722836c45.zip
Update.
	* scripts/output-format.sed: Fix bug in one of the s expressions
	which used / for one too many things.
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;
+    }
+}