-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include "pthreadP.h"
int type;
int *oldtype;
{
- volatile struct pthread *self;
-
if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
return EINVAL;
- self = THREAD_SELF;
+#ifndef SIGCANCEL
+ if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
+ return ENOTSUP;
+#endif
+
+ volatile struct pthread *self = THREAD_SELF;
+ int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
{
- int oldval = THREAD_GETMEM (self, cancelhandling);
int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
? oldval | CANCELTYPE_BITMASK
: oldval & ~CANCELTYPE_BITMASK);
/* Update the cancel handling word. This has to be done
atomically since other bits could be modified as well. */
- if (atomic_compare_and_exchange_acq (&self->cancelhandling, newval,
- oldval) == 0)
+ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+ oldval);
+ if (__glibc_likely (curval == oldval))
{
if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
{
break;
}
+
+ /* Prepare for the next round. */
+ oldval = curval;
}
return 0;