]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/pthread_setcanceltype.c
alloc_buffer: Return unqualified pointer type in alloc_buffer_next
[thirdparty/glibc.git] / nptl / pthread_setcanceltype.c
CommitLineData
04277e02 1/* Copyright (C) 2002-2019 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_setcanceltype (int type, int *oldtype)
76a50749 26{
76a50749
UD
27 if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
28 return EINVAL;
29
2f531bbb
RM
30#ifndef SIGCANCEL
31 if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
32 return ENOTSUP;
33#endif
34
35 volatile struct pthread *self = THREAD_SELF;
76a50749 36
b22d701b 37 int oldval = THREAD_GETMEM (self, cancelhandling);
76a50749
UD
38 while (1)
39 {
76a50749
UD
40 int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
41 ? oldval | CANCELTYPE_BITMASK
42 : oldval & ~CANCELTYPE_BITMASK);
43
44 /* Store the old value. */
45 if (oldtype != NULL)
46 *oldtype = ((oldval & CANCELTYPE_BITMASK)
47 ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED);
48
49 /* Avoid doing unnecessary work. The atomic operation can
3335502b 50 potentially be expensive if the memory has to be locked and
76a50749
UD
51 remote cache lines have to be invalidated. */
52 if (oldval == newval)
53 break;
54
55 /* Update the cancel handling word. This has to be done
56 atomically since other bits could be modified as well. */
b22d701b
UD
57 int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
58 oldval);
a1ffb40e 59 if (__glibc_likely (curval == oldval))
76a50749
UD
60 {
61 if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
62 {
63 THREAD_SETMEM (self, result, PTHREAD_CANCELED);
9ae0909b 64 __do_cancel ();
76a50749
UD
65 }
66
67 break;
68 }
b22d701b
UD
69
70 /* Prepare for the next round. */
71 oldval = curval;
76a50749
UD
72 }
73
74 return 0;
75}
09efc3ba 76strong_alias (__pthread_setcanceltype, pthread_setcanceltype)