2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2005, David Xu <davidxu@freebsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "namespace.h"
34 #include "un-namespace.h"
36 #include "thr_private.h"
38 __weak_reference(_pthread_cancel, pthread_cancel);
39 __weak_reference(_pthread_setcancelstate, pthread_setcancelstate);
40 __weak_reference(_pthread_setcanceltype, pthread_setcanceltype);
41 __weak_reference(_pthread_testcancel, pthread_testcancel);
44 testcancel(struct pthread *curthread)
46 if (__predict_false(SHOULD_CANCEL(curthread) &&
47 !THR_IN_CRITICAL(curthread)))
48 _pthread_exit(PTHREAD_CANCELED);
52 _thr_testcancel(struct pthread *curthread)
54 testcancel(curthread);
58 _pthread_cancel(pthread_t pthread)
60 struct pthread *curthread = _get_curthread();
64 * POSIX says _pthread_cancel should be async cancellation safe.
65 * _thr_find_thread and THR_THREAD_UNLOCK will enter and leave critical
66 * region automatically.
68 if ((ret = _thr_find_thread(curthread, pthread, 0)) == 0) {
69 if (!pthread->cancel_pending) {
70 pthread->cancel_pending = 1;
71 if (pthread->state != PS_DEAD)
72 _thr_send_sig(pthread, SIGCANCEL);
74 THR_THREAD_UNLOCK(curthread, pthread);
80 _pthread_setcancelstate(int state, int *oldstate)
82 struct pthread *curthread = _get_curthread();
85 oldval = curthread->cancel_enable;
87 case PTHREAD_CANCEL_DISABLE:
88 curthread->cancel_enable = 0;
90 case PTHREAD_CANCEL_ENABLE:
91 curthread->cancel_enable = 1;
92 if (curthread->cancel_async)
93 testcancel(curthread);
100 *oldstate = oldval ? PTHREAD_CANCEL_ENABLE :
101 PTHREAD_CANCEL_DISABLE;
107 _pthread_setcanceltype(int type, int *oldtype)
109 struct pthread *curthread = _get_curthread();
112 oldval = curthread->cancel_async;
114 case PTHREAD_CANCEL_ASYNCHRONOUS:
115 curthread->cancel_async = 1;
116 testcancel(curthread);
118 case PTHREAD_CANCEL_DEFERRED:
119 curthread->cancel_async = 0;
126 *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS :
127 PTHREAD_CANCEL_DEFERRED;
133 _pthread_testcancel(void)
135 struct pthread *curthread = _get_curthread();
137 testcancel(curthread);
141 _thr_cancel_enter(struct pthread *curthread)
143 curthread->cancel_point = 1;
144 testcancel(curthread);
148 _thr_cancel_enter2(struct pthread *curthread, int maycancel)
150 curthread->cancel_point = 1;
151 if (__predict_false(SHOULD_CANCEL(curthread) &&
152 !THR_IN_CRITICAL(curthread))) {
154 thr_wake(curthread->tid);
156 _pthread_exit(PTHREAD_CANCELED);
161 _thr_cancel_leave(struct pthread *curthread, int maycancel)
163 curthread->cancel_point = 0;
164 if (__predict_false(SHOULD_CANCEL(curthread) &&
165 !THR_IN_CRITICAL(curthread) && maycancel))
166 _pthread_exit(PTHREAD_CANCELED);
170 _pthread_cancel_enter(int maycancel)
172 _thr_cancel_enter2(_get_curthread(), maycancel);
176 _pthread_cancel_leave(int maycancel)
178 _thr_cancel_leave(_get_curthread(), maycancel);