2 * SPDX-License-Identifier: BSD-2-Clause
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(_thr_cancel, pthread_cancel);
39 __weak_reference(_thr_cancel, _pthread_cancel);
40 __weak_reference(_thr_setcancelstate, pthread_setcancelstate);
41 __weak_reference(_thr_setcancelstate, _pthread_setcancelstate);
42 __weak_reference(_thr_setcanceltype, pthread_setcanceltype);
43 __weak_reference(_thr_setcanceltype, _pthread_setcanceltype);
44 __weak_reference(_Tthr_testcancel, pthread_testcancel);
45 __weak_reference(_Tthr_testcancel, _pthread_testcancel);
46 __weak_reference(_Tthr_cancel_enter, _pthread_cancel_enter);
47 __weak_reference(_Tthr_cancel_leave, _pthread_cancel_leave);
50 testcancel(struct pthread *curthread)
52 if (__predict_false(SHOULD_CANCEL(curthread) &&
53 !THR_IN_CRITICAL(curthread)))
54 _pthread_exit(PTHREAD_CANCELED);
58 _thr_testcancel(struct pthread *curthread)
60 testcancel(curthread);
64 _thr_cancel(pthread_t pthread)
66 struct pthread *curthread = _get_curthread();
70 * POSIX says _pthread_cancel should be async cancellation safe.
71 * _thr_find_thread and THR_THREAD_UNLOCK will enter and leave critical
72 * region automatically.
74 if ((ret = _thr_find_thread(curthread, pthread, 1)) == 0) {
75 if (!pthread->cancel_pending) {
76 pthread->cancel_pending = 1;
77 if (pthread->state != PS_DEAD)
78 _thr_send_sig(pthread, SIGCANCEL);
80 THR_THREAD_UNLOCK(curthread, pthread);
86 _thr_setcancelstate(int state, int *oldstate)
88 struct pthread *curthread = _get_curthread();
91 oldval = curthread->cancel_enable;
93 case PTHREAD_CANCEL_DISABLE:
94 curthread->cancel_enable = 0;
96 case PTHREAD_CANCEL_ENABLE:
97 curthread->cancel_enable = 1;
98 if (curthread->cancel_async)
99 testcancel(curthread);
106 *oldstate = oldval ? PTHREAD_CANCEL_ENABLE :
107 PTHREAD_CANCEL_DISABLE;
113 _thr_setcanceltype(int type, int *oldtype)
115 struct pthread *curthread = _get_curthread();
118 oldval = curthread->cancel_async;
120 case PTHREAD_CANCEL_ASYNCHRONOUS:
121 curthread->cancel_async = 1;
122 testcancel(curthread);
124 case PTHREAD_CANCEL_DEFERRED:
125 curthread->cancel_async = 0;
132 *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS :
133 PTHREAD_CANCEL_DEFERRED;
139 _Tthr_testcancel(void)
141 struct pthread *curthread;
144 curthread = _get_curthread();
145 testcancel(curthread);
149 _thr_cancel_enter(struct pthread *curthread)
151 curthread->cancel_point = 1;
152 testcancel(curthread);
156 _thr_cancel_enter2(struct pthread *curthread, int maycancel)
158 curthread->cancel_point = 1;
159 if (__predict_false(SHOULD_CANCEL(curthread) &&
160 !THR_IN_CRITICAL(curthread))) {
162 thr_wake(curthread->tid);
164 _pthread_exit(PTHREAD_CANCELED);
169 _thr_cancel_leave(struct pthread *curthread, int maycancel)
171 curthread->cancel_point = 0;
172 if (__predict_false(SHOULD_CANCEL(curthread) &&
173 !THR_IN_CRITICAL(curthread) && maycancel))
174 _pthread_exit(PTHREAD_CANCELED);
178 _Tthr_cancel_enter(int maycancel)
180 _thr_cancel_enter2(_get_curthread(), maycancel);
184 _Tthr_cancel_leave(int maycancel)
186 _thr_cancel_leave(_get_curthread(), maycancel);