1 /* $NetBSD: locks.c,v 1.18 2008/07/29 13:17:47 pooka Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Copyright (c) 2007 Antti Kantee. All Rights Reserved. 31 * 32 * Development of this software was supported by the 33 * Finnish Cultural Foundation. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 45 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 46 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 47 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 50 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 57 #include <sys/param.h> 58 #include <sys/mutex.h> 59 #include <sys/rwlock.h> 60 #include <sys/atomic.h> 61 62 #include <rump/rumpuser.h> 63 64 #include "rump_private.h" 65 66 void 67 mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl) 68 { 69 70 rumpuser_mutex_init(&mtx->kmtx_mtx); 71 } 72 73 void 74 mutex_destroy(kmutex_t *mtx) 75 { 76 77 rumpuser_mutex_destroy(mtx->kmtx_mtx); 78 } 79 80 void 81 mutex_enter(kmutex_t *mtx) 82 { 83 84 rumpuser_mutex_enter(mtx->kmtx_mtx); 85 } 86 87 void 88 mutex_spin_enter(kmutex_t *mtx) 89 { 90 91 mutex_enter(mtx); 92 } 93 94 int 95 mutex_tryenter(kmutex_t *mtx) 96 { 97 98 return rumpuser_mutex_tryenter(mtx->kmtx_mtx); 99 } 100 101 void 102 mutex_exit(kmutex_t *mtx) 103 { 104 105 rumpuser_mutex_exit(mtx->kmtx_mtx); 106 } 107 108 void 109 mutex_spin_exit(kmutex_t *mtx) 110 { 111 112 mutex_exit(mtx); 113 } 114 115 int 116 mutex_owned(kmutex_t *mtx) 117 { 118 119 return rumpuser_mutex_held(mtx->kmtx_mtx); 120 } 121 122 /* reader/writer locks */ 123 124 void 125 rw_init(krwlock_t *rw) 126 { 127 128 rumpuser_rw_init(&rw->krw_pthlock); 129 } 130 131 void 132 rw_destroy(krwlock_t *rw) 133 { 134 135 rumpuser_rw_destroy(rw->krw_pthlock); 136 } 137 138 void 139 rw_enter(krwlock_t *rw, const krw_t op) 140 { 141 142 rumpuser_rw_enter(rw->krw_pthlock, op == RW_WRITER); 143 } 144 145 int 146 rw_tryenter(krwlock_t *rw, const krw_t op) 147 { 148 149 return rumpuser_rw_tryenter(rw->krw_pthlock, op == RW_WRITER); 150 } 151 152 void 153 rw_exit(krwlock_t *rw) 154 { 155 156 rumpuser_rw_exit(rw->krw_pthlock); 157 } 158 159 /* always fails */ 160 int 161 rw_tryupgrade(krwlock_t *rw) 162 { 163 164 return 0; 165 } 166 167 int 168 rw_write_held(krwlock_t *rw) 169 { 170 171 return rumpuser_rw_wrheld(rw->krw_pthlock); 172 } 173 174 int 175 rw_read_held(krwlock_t *rw) 176 { 177 178 return rumpuser_rw_rdheld(rw->krw_pthlock); 179 } 180 181 int 182 rw_lock_held(krwlock_t *rw) 183 { 184 185 return rumpuser_rw_held(rw->krw_pthlock); 186 } 187 188 /* curriculum vitaes */ 189 190 /* forgive me for I have sinned */ 191 #define RUMPCV(a) ((struct rumpuser_cv *)(__UNCONST((a)->cv_wmesg))) 192 193 void 194 cv_init(kcondvar_t *cv, const char *msg) 195 { 196 197 rumpuser_cv_init((struct rumpuser_cv **)__UNCONST(&cv->cv_wmesg)); 198 } 199 200 void 201 cv_destroy(kcondvar_t *cv) 202 { 203 204 rumpuser_cv_destroy(RUMPCV(cv)); 205 } 206 207 void 208 cv_wait(kcondvar_t *cv, kmutex_t *mtx) 209 { 210 211 rumpuser_cv_wait(RUMPCV(cv), mtx->kmtx_mtx); 212 } 213 214 int 215 cv_wait_sig(kcondvar_t *cv, kmutex_t *mtx) 216 { 217 218 rumpuser_cv_wait(RUMPCV(cv), mtx->kmtx_mtx); 219 return 0; 220 } 221 222 int 223 cv_timedwait(kcondvar_t *cv, kmutex_t *mtx, int ticks) 224 { 225 #ifdef DIAGNOSTIC 226 extern int hz; 227 #endif 228 229 if (ticks == 0) { 230 cv_wait(cv, mtx); 231 return 0; 232 } else { 233 KASSERT(hz == 100); 234 return rumpuser_cv_timedwait(RUMPCV(cv), mtx->kmtx_mtx, ticks); 235 } 236 } 237 238 int 239 cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mtx, int ticks) 240 { 241 242 return cv_timedwait(cv, mtx, ticks); 243 } 244 245 void 246 cv_signal(kcondvar_t *cv) 247 { 248 249 rumpuser_cv_signal(RUMPCV(cv)); 250 } 251 252 void 253 cv_broadcast(kcondvar_t *cv) 254 { 255 256 rumpuser_cv_broadcast(RUMPCV(cv)); 257 } 258 259 bool 260 cv_has_waiters(kcondvar_t *cv) 261 { 262 263 return rumpuser_cv_has_waiters(RUMPCV(cv)); 264 } 265 266 /* kernel biglock, only for vnode_if */ 267 268 void 269 _kernel_lock(int nlocks) 270 { 271 272 KASSERT(nlocks == 1); 273 mutex_enter(&rump_giantlock); 274 } 275 276 void 277 _kernel_unlock(int nlocks, int *countp) 278 { 279 280 KASSERT(nlocks == 1); 281 mutex_exit(&rump_giantlock); 282 if (countp) 283 *countp = 1; 284 } 285 286 struct kmutexobj { 287 kmutex_t mo_lock; 288 u_int mo_refcnt; 289 }; 290 291 kmutex_t * 292 mutex_obj_alloc(kmutex_type_t type, int ipl) 293 { 294 struct kmutexobj *mo; 295 296 mo = kmem_alloc(sizeof(*mo), KM_SLEEP); 297 mutex_init(&mo->mo_lock, type, ipl); 298 mo->mo_refcnt = 1; 299 300 return (kmutex_t *)mo; 301 } 302 303 void 304 mutex_obj_hold(kmutex_t *lock) 305 { 306 struct kmutexobj *mo = (struct kmutexobj *)lock; 307 308 atomic_inc_uint(&mo->mo_refcnt); 309 } 310 311 bool 312 mutex_obj_free(kmutex_t *lock) 313 { 314 struct kmutexobj *mo = (struct kmutexobj *)lock; 315 316 if (atomic_dec_uint_nv(&mo->mo_refcnt) > 0) { 317 return false; 318 } 319 mutex_destroy(&mo->mo_lock); 320 kmem_free(mo, sizeof(*mo)); 321 return true; 322 } 323