1*5e53a4f9SPedro F. Giffuni /*- 2*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*5e53a4f9SPedro F. Giffuni * 4a091d823SDavid Xu * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 5a091d823SDavid Xu * All rights reserved. 6a091d823SDavid Xu * 7a091d823SDavid Xu * Redistribution and use in source and binary forms, with or without 8a091d823SDavid Xu * modification, are permitted provided that the following conditions 9a091d823SDavid Xu * are met: 10a091d823SDavid Xu * 1. Redistributions of source code must retain the above copyright 11a091d823SDavid Xu * notice unmodified, this list of conditions, and the following 12a091d823SDavid Xu * disclaimer. 13a091d823SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright 14a091d823SDavid Xu * notice, this list of conditions and the following disclaimer in the 15a091d823SDavid Xu * documentation and/or other materials provided with the distribution. 16a091d823SDavid Xu * 17a091d823SDavid Xu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18a091d823SDavid Xu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19a091d823SDavid Xu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20a091d823SDavid Xu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21a091d823SDavid Xu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22a091d823SDavid Xu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a091d823SDavid Xu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a091d823SDavid Xu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a091d823SDavid Xu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26a091d823SDavid Xu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27bb535300SJeff Roberson */ 28bb535300SJeff Roberson 2932793011SKonstantin Belousov #include <sys/cdefs.h> 3032793011SKonstantin Belousov __FBSDID("$FreeBSD$"); 3132793011SKonstantin Belousov 3237a6356bSDavid Xu #include "namespace.h" 33a091d823SDavid Xu #include <pthread.h> 3437a6356bSDavid Xu #include "un-namespace.h" 35a091d823SDavid Xu 36a091d823SDavid Xu #include "thr_private.h" 376da7f493SMike Makonnen 38bb535300SJeff Roberson __weak_reference(_pthread_cancel, pthread_cancel); 39bb535300SJeff Roberson __weak_reference(_pthread_setcancelstate, pthread_setcancelstate); 40bb535300SJeff Roberson __weak_reference(_pthread_setcanceltype, pthread_setcanceltype); 41bb535300SJeff Roberson __weak_reference(_pthread_testcancel, pthread_testcancel); 42bb535300SJeff Roberson 43f08e1bf6SDavid Xu static inline void 44f08e1bf6SDavid Xu testcancel(struct pthread *curthread) 45f08e1bf6SDavid Xu { 46f08e1bf6SDavid Xu if (__predict_false(SHOULD_CANCEL(curthread) && 47635f917aSDavid Xu !THR_IN_CRITICAL(curthread))) 48f08e1bf6SDavid Xu _pthread_exit(PTHREAD_CANCELED); 49f08e1bf6SDavid Xu } 50f08e1bf6SDavid Xu 51f08e1bf6SDavid Xu void 52f08e1bf6SDavid Xu _thr_testcancel(struct pthread *curthread) 53f08e1bf6SDavid Xu { 54f08e1bf6SDavid Xu testcancel(curthread); 55f08e1bf6SDavid Xu } 56f08e1bf6SDavid Xu 57bb535300SJeff Roberson int 58bb535300SJeff Roberson _pthread_cancel(pthread_t pthread) 59bb535300SJeff Roberson { 60a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 61a091d823SDavid Xu int ret; 62bb535300SJeff Roberson 63d39d6512SMike Makonnen /* 64f08e1bf6SDavid Xu * POSIX says _pthread_cancel should be async cancellation safe. 65a9b764e2SDavid Xu * _thr_find_thread and THR_THREAD_UNLOCK will enter and leave critical 66f08e1bf6SDavid Xu * region automatically. 67d39d6512SMike Makonnen */ 68a9b764e2SDavid Xu if ((ret = _thr_find_thread(curthread, pthread, 0)) == 0) { 69f08e1bf6SDavid Xu if (!pthread->cancel_pending) { 70f08e1bf6SDavid Xu pthread->cancel_pending = 1; 7117dce7e1SDavid Xu if (pthread->state != PS_DEAD) 72a091d823SDavid Xu _thr_send_sig(pthread, SIGCANCEL); 736da7f493SMike Makonnen } 74f08e1bf6SDavid Xu THR_THREAD_UNLOCK(curthread, pthread); 75f08e1bf6SDavid Xu } 76f08e1bf6SDavid Xu return (ret); 77a091d823SDavid Xu } 78a091d823SDavid Xu 79bb535300SJeff Roberson int 80bb535300SJeff Roberson _pthread_setcancelstate(int state, int *oldstate) 81bb535300SJeff Roberson { 82a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 83f08e1bf6SDavid Xu int oldval; 84bb535300SJeff Roberson 85f08e1bf6SDavid Xu oldval = curthread->cancel_enable; 86bb535300SJeff Roberson switch (state) { 87bb535300SJeff Roberson case PTHREAD_CANCEL_DISABLE: 88f08e1bf6SDavid Xu curthread->cancel_enable = 0; 89a091d823SDavid Xu break; 90a091d823SDavid Xu case PTHREAD_CANCEL_ENABLE: 91f08e1bf6SDavid Xu curthread->cancel_enable = 1; 92a0b9cbc8SKonstantin Belousov if (curthread->cancel_async) 9302c3c858SDavid Xu testcancel(curthread); 94bb535300SJeff Roberson break; 95bb535300SJeff Roberson default: 96f08e1bf6SDavid Xu return (EINVAL); 974cd18a22SMike Makonnen } 98bb535300SJeff Roberson 99f08e1bf6SDavid Xu if (oldstate) { 100f08e1bf6SDavid Xu *oldstate = oldval ? PTHREAD_CANCEL_ENABLE : 101f08e1bf6SDavid Xu PTHREAD_CANCEL_DISABLE; 102f08e1bf6SDavid Xu } 103f08e1bf6SDavid Xu return (0); 104a091d823SDavid Xu } 105a091d823SDavid Xu 1064cd18a22SMike Makonnen int 1074cd18a22SMike Makonnen _pthread_setcanceltype(int type, int *oldtype) 1084cd18a22SMike Makonnen { 109a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 110f08e1bf6SDavid Xu int oldval; 1114cd18a22SMike Makonnen 112f08e1bf6SDavid Xu oldval = curthread->cancel_async; 1134cd18a22SMike Makonnen switch (type) { 1144cd18a22SMike Makonnen case PTHREAD_CANCEL_ASYNCHRONOUS: 115f08e1bf6SDavid Xu curthread->cancel_async = 1; 116a091d823SDavid Xu testcancel(curthread); 1174cd18a22SMike Makonnen break; 1184cd18a22SMike Makonnen case PTHREAD_CANCEL_DEFERRED: 119f08e1bf6SDavid Xu curthread->cancel_async = 0; 1204cd18a22SMike Makonnen break; 1214cd18a22SMike Makonnen default: 122f08e1bf6SDavid Xu return (EINVAL); 1234cd18a22SMike Makonnen } 124a091d823SDavid Xu 125f08e1bf6SDavid Xu if (oldtype) { 126f08e1bf6SDavid Xu *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS : 127f08e1bf6SDavid Xu PTHREAD_CANCEL_DEFERRED; 128f08e1bf6SDavid Xu } 129f08e1bf6SDavid Xu return (0); 130bb535300SJeff Roberson } 131bb535300SJeff Roberson 132bb535300SJeff Roberson void 133bb535300SJeff Roberson _pthread_testcancel(void) 134bb535300SJeff Roberson { 135f08e1bf6SDavid Xu struct pthread *curthread = _get_curthread(); 1366da7f493SMike Makonnen 13702c3c858SDavid Xu testcancel(curthread); 1384cd18a22SMike Makonnen } 139bb535300SJeff Roberson 140bb535300SJeff Roberson void 141f08e1bf6SDavid Xu _thr_cancel_enter(struct pthread *curthread) 142bb535300SJeff Roberson { 14302c3c858SDavid Xu curthread->cancel_point = 1; 144f08e1bf6SDavid Xu testcancel(curthread); 145f08e1bf6SDavid Xu } 146635f917aSDavid Xu 147635f917aSDavid Xu void 14802c3c858SDavid Xu _thr_cancel_enter2(struct pthread *curthread, int maycancel) 149635f917aSDavid Xu { 15002c3c858SDavid Xu curthread->cancel_point = 1; 151635f917aSDavid Xu if (__predict_false(SHOULD_CANCEL(curthread) && 152635f917aSDavid Xu !THR_IN_CRITICAL(curthread))) { 153635f917aSDavid Xu if (!maycancel) 154635f917aSDavid Xu thr_wake(curthread->tid); 155635f917aSDavid Xu else 156635f917aSDavid Xu _pthread_exit(PTHREAD_CANCELED); 157635f917aSDavid Xu } 158f08e1bf6SDavid Xu } 159f08e1bf6SDavid Xu 160f08e1bf6SDavid Xu void 16102c3c858SDavid Xu _thr_cancel_leave(struct pthread *curthread, int maycancel) 162f08e1bf6SDavid Xu { 16393ea4a71SDavid Xu curthread->cancel_point = 0; 164e5c66a0dSDavid Xu if (__predict_false(SHOULD_CANCEL(curthread) && 165e5c66a0dSDavid Xu !THR_IN_CRITICAL(curthread) && maycancel)) 166e5c66a0dSDavid Xu _pthread_exit(PTHREAD_CANCELED); 1673ce4e91dSDavid Xu } 168f4213b90SDavid Xu 169f4213b90SDavid Xu void 170f4213b90SDavid Xu _pthread_cancel_enter(int maycancel) 171f4213b90SDavid Xu { 172f4213b90SDavid Xu _thr_cancel_enter2(_get_curthread(), maycancel); 173f4213b90SDavid Xu } 174f4213b90SDavid Xu 175f4213b90SDavid Xu void 176f4213b90SDavid Xu _pthread_cancel_leave(int maycancel) 177f4213b90SDavid Xu { 178f4213b90SDavid Xu _thr_cancel_leave(_get_curthread(), maycancel); 179f4213b90SDavid Xu } 180