summaryrefslogtreecommitdiff
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)
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;
+ }
+}