2 * Copyright (c) 2005, David Xu<davidxu@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $DragonFly: src/lib/libthread_xu/thread/thr_cancel.c,v 1.2 2005/03/29 19:26:20 joerg Exp $
29 #include <machine/tls.h>
32 #include "thr_private.h"
34 __weak_reference(_pthread_cancel, pthread_cancel);
35 __weak_reference(_pthread_setcancelstate, pthread_setcancelstate);
36 __weak_reference(_pthread_setcanceltype, pthread_setcanceltype);
37 __weak_reference(_pthread_testcancel, pthread_testcancel);
39 int _pthread_setcanceltype(int type, int *oldtype);
42 _pthread_cancel(pthread_t pthread)
44 struct pthread *curthread = tls_get_curthread();
45 int oldval, newval = 0;
50 * POSIX says _pthread_cancel should be async cancellation safe,
51 * so we temporarily disable async cancellation.
53 _pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
54 if ((ret = _thr_ref_add(curthread, pthread, 0)) != 0) {
55 _pthread_setcanceltype(oldtype, NULL);
60 oldval = pthread->cancelflags;
61 if (oldval & THR_CANCEL_NEEDED)
63 newval = oldval | THR_CANCEL_NEEDED;
64 } while (!atomic_cmpset_acq_int(&pthread->cancelflags, oldval, newval));
66 if (!(oldval & THR_CANCEL_NEEDED) && SHOULD_ASYNC_CANCEL(newval))
67 _thr_send_sig(pthread, SIGCANCEL);
69 _thr_ref_delete(curthread, pthread);
70 _pthread_setcanceltype(oldtype, NULL);
75 testcancel(struct pthread *curthread)
79 newval = curthread->cancelflags;
80 if (SHOULD_CANCEL(newval))
81 pthread_exit(PTHREAD_CANCELED);
85 _pthread_setcancelstate(int state, int *oldstate)
87 struct pthread *curthread = tls_get_curthread();
90 oldval = curthread->cancelflags;
92 *oldstate = ((oldval & THR_CANCEL_DISABLE) ?
93 PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE);
95 case PTHREAD_CANCEL_DISABLE:
96 atomic_set_int(&curthread->cancelflags, THR_CANCEL_DISABLE);
99 case PTHREAD_CANCEL_ENABLE:
100 atomic_clear_int(&curthread->cancelflags, THR_CANCEL_DISABLE);
101 testcancel(curthread);
112 _pthread_setcanceltype(int type, int *oldtype)
114 struct pthread *curthread = tls_get_curthread();
117 oldval = curthread->cancelflags;
119 *oldtype = ((oldval & THR_CANCEL_AT_POINT) ?
120 PTHREAD_CANCEL_ASYNCHRONOUS :
121 PTHREAD_CANCEL_DEFERRED);
123 case PTHREAD_CANCEL_ASYNCHRONOUS:
124 atomic_set_int(&curthread->cancelflags, THR_CANCEL_AT_POINT);
125 testcancel(curthread);
128 case PTHREAD_CANCEL_DEFERRED:
129 atomic_clear_int(&curthread->cancelflags, THR_CANCEL_AT_POINT);
140 _pthread_testcancel(void)
142 testcancel(tls_get_curthread());
146 _thr_cancel_enter(struct pthread *curthread)
150 oldval = curthread->cancelflags;
151 if (!(oldval & THR_CANCEL_AT_POINT)) {
152 atomic_set_int(&curthread->cancelflags, THR_CANCEL_AT_POINT);
153 testcancel(curthread);
159 _thr_cancel_leave(struct pthread *curthread, int previous)
161 if (!(previous & THR_CANCEL_AT_POINT))
162 atomic_clear_int(&curthread->cancelflags, THR_CANCEL_AT_POINT);