1a091d823SDavid Xu /* 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 * 26a091d823SDavid Xu * $FreeBSD$ 27a091d823SDavid Xu * 28a091d823SDavid Xu */ 29a091d823SDavid Xu 30a091d823SDavid Xu #include "thr_private.h" 31a091d823SDavid Xu #include "thr_umtx.h" 32a091d823SDavid Xu 338042f26dSDavid Xu void 348042f26dSDavid Xu _thr_umutex_init(struct umutex *mtx) 358042f26dSDavid Xu { 368042f26dSDavid Xu static struct umutex default_mtx = DEFAULT_UMUTEX; 378042f26dSDavid Xu 388042f26dSDavid Xu *mtx = default_mtx; 398042f26dSDavid Xu } 408042f26dSDavid Xu 41a091d823SDavid Xu int 428042f26dSDavid Xu __thr_umutex_lock(struct umutex *mtx) 43cf13ecdaSDavid Xu { 44cf13ecdaSDavid Xu if (_umtx_op(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 0) == 0) 45cf13ecdaSDavid Xu return 0; 46cf13ecdaSDavid Xu return (errno); 47cf13ecdaSDavid Xu } 48cf13ecdaSDavid Xu 49cf13ecdaSDavid Xu int 508042f26dSDavid Xu __thr_umutex_timedlock(struct umutex *mtx, 51cf13ecdaSDavid Xu const struct timespec *timeout) 52cf13ecdaSDavid Xu { 53cf13ecdaSDavid Xu if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 && 54cf13ecdaSDavid Xu timeout->tv_nsec <= 0))) 55cf13ecdaSDavid Xu return (ETIMEDOUT); 56cf13ecdaSDavid Xu if (_umtx_op(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 57cf13ecdaSDavid Xu __DECONST(void *, timeout)) == 0) 58cf13ecdaSDavid Xu return (0); 59cf13ecdaSDavid Xu return (errno); 60cf13ecdaSDavid Xu } 61cf13ecdaSDavid Xu 62cf13ecdaSDavid Xu int 638042f26dSDavid Xu __thr_umutex_unlock(struct umutex *mtx) 64cf13ecdaSDavid Xu { 65cf13ecdaSDavid Xu if (_umtx_op(mtx, UMTX_OP_MUTEX_UNLOCK, 0, 0, 0) == 0) 66cf13ecdaSDavid Xu return (0); 67cf13ecdaSDavid Xu return (errno); 68cf13ecdaSDavid Xu } 69cf13ecdaSDavid Xu 70cf13ecdaSDavid Xu int 718042f26dSDavid Xu __thr_umutex_trylock(struct umutex *mtx) 72cf13ecdaSDavid Xu { 73cf13ecdaSDavid Xu if (_umtx_op(mtx, UMTX_OP_MUTEX_TRYLOCK, 0, 0, 0) == 0) 74cf13ecdaSDavid Xu return (0); 75cf13ecdaSDavid Xu return (errno); 76cf13ecdaSDavid Xu } 77cf13ecdaSDavid Xu 78cf13ecdaSDavid Xu int 79cf13ecdaSDavid Xu __thr_umutex_set_ceiling(struct umutex *mtx, uint32_t ceiling, 80cf13ecdaSDavid Xu uint32_t *oldceiling) 81cf13ecdaSDavid Xu { 82cf13ecdaSDavid Xu if (_umtx_op(mtx, UMTX_OP_SET_CEILING, ceiling, oldceiling, 0) == 0) 83cf13ecdaSDavid Xu return (0); 84cf13ecdaSDavid Xu return (errno); 85cf13ecdaSDavid Xu } 86cf13ecdaSDavid Xu 87cf13ecdaSDavid Xu int 88a091d823SDavid Xu _thr_umtx_wait(volatile umtx_t *mtx, long id, const struct timespec *timeout) 89a091d823SDavid Xu { 90a091d823SDavid Xu if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 && 91a091d823SDavid Xu timeout->tv_nsec <= 0))) 92a091d823SDavid Xu return (ETIMEDOUT); 938042f26dSDavid Xu if (_umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAIT, id, 0, 9437a6356bSDavid Xu __DECONST(void*, timeout)) == 0) 95a091d823SDavid Xu return (0); 96a091d823SDavid Xu return (errno); 97a091d823SDavid Xu } 98a091d823SDavid Xu 99a091d823SDavid Xu int 100a091d823SDavid Xu _thr_umtx_wake(volatile umtx_t *mtx, int nr_wakeup) 101a091d823SDavid Xu { 1028042f26dSDavid Xu if (_umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAKE, 10337a6356bSDavid Xu nr_wakeup, 0, 0) == 0) 104a091d823SDavid Xu return (0); 105a091d823SDavid Xu return (errno); 106a091d823SDavid Xu } 1072bd2c907SDavid Xu 108670b44d6SDavid Xu void 109670b44d6SDavid Xu _thr_ucond_init(struct ucond *cv) 110670b44d6SDavid Xu { 111670b44d6SDavid Xu bzero(cv, sizeof(struct ucond)); 112670b44d6SDavid Xu } 113670b44d6SDavid Xu 1142bd2c907SDavid Xu int 1152bd2c907SDavid Xu _thr_ucond_wait(struct ucond *cv, struct umutex *m, 1162bd2c907SDavid Xu const struct timespec *timeout, int check_unparking) 1172bd2c907SDavid Xu { 1182bd2c907SDavid Xu if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 && 1192bd2c907SDavid Xu timeout->tv_nsec <= 0))) { 1202bd2c907SDavid Xu __thr_umutex_unlock(m); 1212bd2c907SDavid Xu return (ETIMEDOUT); 1222bd2c907SDavid Xu } 1232bd2c907SDavid Xu if (_umtx_op(cv, UMTX_OP_CV_WAIT, 1243c61d00aSDavid Xu check_unparking ? UMTX_CHECK_UNPARKING : 0, 1252bd2c907SDavid Xu m, __DECONST(void*, timeout)) == 0) { 1262bd2c907SDavid Xu return (0); 1272bd2c907SDavid Xu } 1282bd2c907SDavid Xu return (errno); 1292bd2c907SDavid Xu } 1302bd2c907SDavid Xu 1312bd2c907SDavid Xu int 1322bd2c907SDavid Xu _thr_ucond_signal(struct ucond *cv) 1332bd2c907SDavid Xu { 134347126a2SDavid Xu if (!cv->c_has_waiters) 135347126a2SDavid Xu return (0); 1362bd2c907SDavid Xu if (_umtx_op(cv, UMTX_OP_CV_SIGNAL, 0, NULL, NULL) == 0) 1372bd2c907SDavid Xu return (0); 1382bd2c907SDavid Xu return (errno); 1392bd2c907SDavid Xu } 1402bd2c907SDavid Xu 1412bd2c907SDavid Xu int 1422bd2c907SDavid Xu _thr_ucond_broadcast(struct ucond *cv) 1432bd2c907SDavid Xu { 144347126a2SDavid Xu if (!cv->c_has_waiters) 145347126a2SDavid Xu return (0); 1462bd2c907SDavid Xu if (_umtx_op(cv, UMTX_OP_CV_BROADCAST, 0, NULL, NULL) == 0) 1472bd2c907SDavid Xu return (0); 1482bd2c907SDavid Xu return (errno); 1492bd2c907SDavid Xu } 150