1bb535300SJeff Roberson /* 2a091d823SDavid Xu * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 3a091d823SDavid Xu * All rights reserved. 4a091d823SDavid Xu * 5a091d823SDavid Xu * Redistribution and use in source and binary forms, with or without 6a091d823SDavid Xu * modification, are permitted provided that the following conditions 7a091d823SDavid Xu * are met: 8a091d823SDavid Xu * 1. Redistributions of source code must retain the above copyright 9a091d823SDavid Xu * notice unmodified, this list of conditions, and the following 10a091d823SDavid Xu * disclaimer. 11a091d823SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright 12a091d823SDavid Xu * notice, this list of conditions and the following disclaimer in the 13a091d823SDavid Xu * documentation and/or other materials provided with the distribution. 14a091d823SDavid Xu * 15a091d823SDavid Xu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16a091d823SDavid Xu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17a091d823SDavid Xu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18a091d823SDavid Xu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19a091d823SDavid Xu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20a091d823SDavid Xu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21a091d823SDavid Xu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22a091d823SDavid Xu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23a091d823SDavid Xu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24a091d823SDavid Xu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25a091d823SDavid Xu * 26bb535300SJeff Roberson * $FreeBSD$ 27a091d823SDavid Xu * 28bb535300SJeff Roberson */ 29bb535300SJeff Roberson 3037a6356bSDavid Xu #include "namespace.h" 31a091d823SDavid Xu #include <pthread.h> 3237a6356bSDavid Xu #include "un-namespace.h" 33a091d823SDavid Xu 34a091d823SDavid Xu #include "thr_private.h" 356da7f493SMike Makonnen 36bb535300SJeff Roberson __weak_reference(_pthread_cancel, pthread_cancel); 37bb535300SJeff Roberson __weak_reference(_pthread_setcancelstate, pthread_setcancelstate); 38bb535300SJeff Roberson __weak_reference(_pthread_setcanceltype, pthread_setcanceltype); 39bb535300SJeff Roberson __weak_reference(_pthread_testcancel, pthread_testcancel); 40bb535300SJeff Roberson 41f08e1bf6SDavid Xu static inline void 42f08e1bf6SDavid Xu testcancel(struct pthread *curthread) 43f08e1bf6SDavid Xu { 44f08e1bf6SDavid Xu if (__predict_false(SHOULD_CANCEL(curthread) && 45f08e1bf6SDavid Xu !THR_IN_CRITICAL(curthread))) 46f08e1bf6SDavid Xu _pthread_exit(PTHREAD_CANCELED); 47f08e1bf6SDavid Xu } 48f08e1bf6SDavid Xu 49f08e1bf6SDavid Xu void 50f08e1bf6SDavid Xu _thr_testcancel(struct pthread *curthread) 51f08e1bf6SDavid Xu { 52f08e1bf6SDavid Xu testcancel(curthread); 53f08e1bf6SDavid Xu } 54f08e1bf6SDavid Xu 55bb535300SJeff Roberson int 56bb535300SJeff Roberson _pthread_cancel(pthread_t pthread) 57bb535300SJeff Roberson { 58a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 59a091d823SDavid Xu int ret; 60bb535300SJeff Roberson 61d39d6512SMike Makonnen /* 62f08e1bf6SDavid Xu * POSIX says _pthread_cancel should be async cancellation safe. 63f08e1bf6SDavid Xu * _thr_ref_add and _thr_ref_delete will enter and leave critical 64f08e1bf6SDavid Xu * region automatically. 65d39d6512SMike Makonnen */ 66f08e1bf6SDavid Xu if ((ret = _thr_ref_add(curthread, pthread, 0)) == 0) { 67f08e1bf6SDavid Xu THR_THREAD_LOCK(curthread, pthread); 68f08e1bf6SDavid Xu if (!pthread->cancel_pending) { 69f08e1bf6SDavid Xu pthread->cancel_pending = 1; 70f08e1bf6SDavid Xu if (pthread->cancel_enable) 71a091d823SDavid Xu _thr_send_sig(pthread, SIGCANCEL); 726da7f493SMike Makonnen } 73f08e1bf6SDavid Xu THR_THREAD_UNLOCK(curthread, pthread); 74f08e1bf6SDavid Xu _thr_ref_delete(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 THR_LOCK(curthread); 89f08e1bf6SDavid Xu curthread->cancel_enable = 0; 90f08e1bf6SDavid Xu THR_UNLOCK(curthread); 91a091d823SDavid Xu break; 92a091d823SDavid Xu case PTHREAD_CANCEL_ENABLE: 93f08e1bf6SDavid Xu THR_LOCK(curthread); 94f08e1bf6SDavid Xu curthread->cancel_enable = 1; 95f08e1bf6SDavid Xu THR_UNLOCK(curthread); 96bb535300SJeff Roberson break; 97bb535300SJeff Roberson default: 98f08e1bf6SDavid Xu return (EINVAL); 994cd18a22SMike Makonnen } 100bb535300SJeff Roberson 101f08e1bf6SDavid Xu if (oldstate) { 102f08e1bf6SDavid Xu *oldstate = oldval ? PTHREAD_CANCEL_ENABLE : 103f08e1bf6SDavid Xu PTHREAD_CANCEL_DISABLE; 104f08e1bf6SDavid Xu } 105f08e1bf6SDavid Xu return (0); 106a091d823SDavid Xu } 107a091d823SDavid Xu 1084cd18a22SMike Makonnen int 1094cd18a22SMike Makonnen _pthread_setcanceltype(int type, int *oldtype) 1104cd18a22SMike Makonnen { 111a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 112f08e1bf6SDavid Xu int oldval; 1134cd18a22SMike Makonnen 114f08e1bf6SDavid Xu oldval = curthread->cancel_async; 1154cd18a22SMike Makonnen switch (type) { 1164cd18a22SMike Makonnen case PTHREAD_CANCEL_ASYNCHRONOUS: 117f08e1bf6SDavid Xu curthread->cancel_async = 1; 118a091d823SDavid Xu testcancel(curthread); 1194cd18a22SMike Makonnen break; 1204cd18a22SMike Makonnen case PTHREAD_CANCEL_DEFERRED: 121f08e1bf6SDavid Xu curthread->cancel_async = 0; 1224cd18a22SMike Makonnen break; 1234cd18a22SMike Makonnen default: 124f08e1bf6SDavid Xu return (EINVAL); 1254cd18a22SMike Makonnen } 126a091d823SDavid Xu 127f08e1bf6SDavid Xu if (oldtype) { 128f08e1bf6SDavid Xu *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS : 129f08e1bf6SDavid Xu PTHREAD_CANCEL_DEFERRED; 130f08e1bf6SDavid Xu } 131f08e1bf6SDavid Xu return (0); 132bb535300SJeff Roberson } 133bb535300SJeff Roberson 134bb535300SJeff Roberson void 135bb535300SJeff Roberson _pthread_testcancel(void) 136bb535300SJeff Roberson { 137f08e1bf6SDavid Xu struct pthread *curthread = _get_curthread(); 1386da7f493SMike Makonnen 139f08e1bf6SDavid Xu _thr_cancel_enter(curthread); 140f08e1bf6SDavid Xu _thr_cancel_leave(curthread); 1414cd18a22SMike Makonnen } 142bb535300SJeff Roberson 143bb535300SJeff Roberson void 144f08e1bf6SDavid Xu _thr_cancel_enter(struct pthread *curthread) 145bb535300SJeff Roberson { 146f08e1bf6SDavid Xu if (curthread->cancel_enable) { 147f08e1bf6SDavid Xu curthread->cancel_point++; 148f08e1bf6SDavid Xu testcancel(curthread); 149f08e1bf6SDavid Xu } 150f08e1bf6SDavid Xu } 151f08e1bf6SDavid Xu 152f08e1bf6SDavid Xu void 153f08e1bf6SDavid Xu _thr_cancel_leave(struct pthread *curthread) 154f08e1bf6SDavid Xu { 155f08e1bf6SDavid Xu if (curthread->cancel_enable) 156f08e1bf6SDavid Xu curthread->cancel_point--; 157bb535300SJeff Roberson } 158