]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/pthread_setcancelstate.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nptl / pthread_setcancelstate.c
CommitLineData
f7a9f785 1/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
76a50749
UD
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
76a50749
UD
18
19#include <errno.h>
20#include "pthreadP.h"
21#include <atomic.h>
22
23
24int
9d46370c 25__pthread_setcancelstate (int state, int *oldstate)
76a50749
UD
26{
27 volatile struct pthread *self;
28
29 if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE)
30 return EINVAL;
31
32 self = THREAD_SELF;
33
b22d701b 34 int oldval = THREAD_GETMEM (self, cancelhandling);
76a50749
UD
35 while (1)
36 {
76a50749
UD
37 int newval = (state == PTHREAD_CANCEL_DISABLE
38 ? oldval | CANCELSTATE_BITMASK
39 : oldval & ~CANCELSTATE_BITMASK);
40
41 /* Store the old value. */
42 if (oldstate != NULL)
43 *oldstate = ((oldval & CANCELSTATE_BITMASK)
44 ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE);
45
46 /* Avoid doing unnecessary work. The atomic operation can
3335502b 47 potentially be expensive if the memory has to be locked and
76a50749
UD
48 remote cache lines have to be invalidated. */
49 if (oldval == newval)
50 break;
51
52 /* Update the cancel handling word. This has to be done
53 atomically since other bits could be modified as well. */
b22d701b
UD
54 int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
55 oldval);
a1ffb40e 56 if (__glibc_likely (curval == oldval))
76a50749
UD
57 {
58 if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
9ae0909b 59 __do_cancel ();
76a50749
UD
60
61 break;
62 }
b22d701b
UD
63
64 /* Prepare for the next round. */
65 oldval = curval;
76a50749
UD
66 }
67
68 return 0;
69}
83614008 70strong_alias (__pthread_setcancelstate, pthread_setcancelstate)
e5d19c08 71hidden_def (__pthread_setcancelstate)