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.4 2006/04/06 13:03:09 davidxu Exp $
29 #include "namespace.h"
30 #include <machine/tls.h>
32 #include "un-namespace.h"
34 #include "thr_private.h"
36 int _pthread_setcanceltype(int type
, int *oldtype
);
39 _pthread_cancel(pthread_t pthread
)
41 struct pthread
*curthread
= tls_get_curthread();
42 int oldval
, newval
= 0;
47 * POSIX says _pthread_cancel should be async cancellation safe,
48 * so we temporarily disable async cancellation.
50 _pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, &oldtype
);
51 if ((ret
= _thr_ref_add(curthread
, pthread
, 0)) != 0) {
52 _pthread_setcanceltype(oldtype
, NULL
);
57 oldval
= pthread
->cancelflags
;
58 if (oldval
& THR_CANCEL_NEEDED
)
60 newval
= oldval
| THR_CANCEL_NEEDED
;
61 } while (!atomic_cmpset_acq_int(&pthread
->cancelflags
, oldval
, newval
));
63 if (!(oldval
& THR_CANCEL_NEEDED
) && SHOULD_ASYNC_CANCEL(newval
))
64 _thr_send_sig(pthread
, SIGCANCEL
);
66 _thr_ref_delete(curthread
, pthread
);
67 _pthread_setcanceltype(oldtype
, NULL
);
72 testcancel(struct pthread
*curthread
)
76 newval
= curthread
->cancelflags
;
77 if (SHOULD_CANCEL(newval
))
78 _pthread_exit(PTHREAD_CANCELED
);
82 _pthread_setcancelstate(int state
, int *oldstate
)
84 struct pthread
*curthread
= tls_get_curthread();
87 oldval
= curthread
->cancelflags
;
89 *oldstate
= ((oldval
& THR_CANCEL_DISABLE
) ?
90 PTHREAD_CANCEL_DISABLE
: PTHREAD_CANCEL_ENABLE
);
92 case PTHREAD_CANCEL_DISABLE
:
93 atomic_set_int(&curthread
->cancelflags
, THR_CANCEL_DISABLE
);
96 case PTHREAD_CANCEL_ENABLE
:
97 atomic_clear_int(&curthread
->cancelflags
, THR_CANCEL_DISABLE
);
98 testcancel(curthread
);
109 _pthread_setcanceltype(int type
, int *oldtype
)
111 struct pthread
*curthread
= tls_get_curthread();
114 oldval
= curthread
->cancelflags
;
116 *oldtype
= ((oldval
& THR_CANCEL_AT_POINT
) ?
117 PTHREAD_CANCEL_ASYNCHRONOUS
:
118 PTHREAD_CANCEL_DEFERRED
);
120 case PTHREAD_CANCEL_ASYNCHRONOUS
:
121 atomic_set_int(&curthread
->cancelflags
, THR_CANCEL_AT_POINT
);
122 testcancel(curthread
);
125 case PTHREAD_CANCEL_DEFERRED
:
126 atomic_clear_int(&curthread
->cancelflags
, THR_CANCEL_AT_POINT
);
137 _pthread_testcancel(void)
139 testcancel(tls_get_curthread());
143 _thr_cancel_enter(struct pthread
*curthread
)
147 oldval
= curthread
->cancelflags
;
148 if (!(oldval
& THR_CANCEL_AT_POINT
)) {
149 atomic_set_int(&curthread
->cancelflags
, THR_CANCEL_AT_POINT
);
150 testcancel(curthread
);
156 _thr_cancel_leave(struct pthread
*curthread
, int previous
)
158 if (!(previous
& THR_CANCEL_AT_POINT
))
159 atomic_clear_int(&curthread
->cancelflags
, THR_CANCEL_AT_POINT
);
162 __strong_reference(_pthread_cancel
, pthread_cancel
);
163 __strong_reference(_pthread_setcancelstate
, pthread_setcancelstate
);
164 __strong_reference(_pthread_setcanceltype
, pthread_setcanceltype
);
165 __strong_reference(_pthread_testcancel
, pthread_testcancel
);