1 /* 2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 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. 14 * 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. 25 * 26 * $FreeBSD$ 27 * 28 */ 29 30 #include "thr_private.h" 31 #include "thr_umtx.h" 32 33 void 34 _thr_umutex_init(struct umutex *mtx) 35 { 36 static struct umutex default_mtx = DEFAULT_UMUTEX; 37 38 *mtx = default_mtx; 39 mtx->m_spincount = _thr_adaptive_spin; 40 } 41 42 int 43 __thr_umutex_lock(struct umutex *mtx) 44 { 45 if (_umtx_op(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 0) != -1) 46 return 0; 47 return (errno); 48 } 49 50 int 51 __thr_umutex_timedlock(struct umutex *mtx, 52 const struct timespec *timeout) 53 { 54 if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 && 55 timeout->tv_nsec <= 0))) 56 return (ETIMEDOUT); 57 if (_umtx_op(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 58 __DECONST(void *, timeout)) != -1) 59 return (0); 60 return (errno); 61 } 62 63 int 64 __thr_umutex_unlock(struct umutex *mtx) 65 { 66 if (_umtx_op(mtx, UMTX_OP_MUTEX_UNLOCK, 0, 0, 0) != -1) 67 return (0); 68 return (errno); 69 } 70 71 int 72 __thr_umutex_trylock(struct umutex *mtx) 73 { 74 if (_umtx_op(mtx, UMTX_OP_MUTEX_TRYLOCK, 0, 0, 0) != -1) 75 return (0); 76 return (errno); 77 } 78 79 int 80 __thr_umutex_set_ceiling(struct umutex *mtx, uint32_t ceiling, 81 uint32_t *oldceiling) 82 { 83 if (_umtx_op(mtx, UMTX_OP_SET_CEILING, ceiling, oldceiling, 0) != -1) 84 return (0); 85 return (errno); 86 } 87 88 int 89 _thr_umtx_wait(volatile umtx_t *mtx, long id, const struct timespec *timeout) 90 { 91 if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 && 92 timeout->tv_nsec <= 0))) 93 return (ETIMEDOUT); 94 if (_umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAIT, id, 0, 95 __DECONST(void*, timeout)) != -1) 96 return (0); 97 return (errno); 98 } 99 100 int 101 _thr_umtx_wake(volatile umtx_t *mtx, int nr_wakeup) 102 { 103 if (_umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAKE, 104 nr_wakeup, 0, 0) != -1) 105 return (0); 106 return (errno); 107 } 108 109 void 110 _thr_ucond_init(struct ucond *cv) 111 { 112 bzero(cv, sizeof(struct ucond)); 113 } 114 115 int 116 _thr_ucond_wait(struct ucond *cv, struct umutex *m, 117 const struct timespec *timeout, int check_unparking) 118 { 119 if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 && 120 timeout->tv_nsec <= 0))) { 121 __thr_umutex_unlock(m); 122 return (ETIMEDOUT); 123 } 124 if (_umtx_op(cv, UMTX_OP_CV_WAIT, 125 check_unparking ? UMTX_CHECK_UNPARKING : 0, 126 m, __DECONST(void*, timeout)) != -1) { 127 return (0); 128 } 129 return (errno); 130 } 131 132 int 133 _thr_ucond_signal(struct ucond *cv) 134 { 135 if (!cv->c_has_waiters) 136 return (0); 137 if (_umtx_op(cv, UMTX_OP_CV_SIGNAL, 0, NULL, NULL) != -1) 138 return (0); 139 return (errno); 140 } 141 142 int 143 _thr_ucond_broadcast(struct ucond *cv) 144 { 145 if (!cv->c_has_waiters) 146 return (0); 147 if (_umtx_op(cv, UMTX_OP_CV_BROADCAST, 0, NULL, NULL) != -1) 148 return (0); 149 return (errno); 150 } 151