1 /* 2 * Copyright (c) 2005 Jeffrey M. Hsu. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Jeffrey M. Hsu. 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 * 3. Neither the name of The DragonFly Project nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific, prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $DragonFly: src/sys/sys/spinlock2.h,v 1.12 2008/06/04 04:34:54 nth Exp $ 33 */ 34 35 #ifndef _SYS_SPINLOCK2_H_ 36 #define _SYS_SPINLOCK2_H_ 37 38 #ifndef _KERNEL 39 40 #error "This file should not be included by userland programs." 41 42 #else 43 44 #ifndef _SYS_SYSTM_H_ 45 #include <sys/systm.h> 46 #endif 47 #ifndef _SYS_THREAD2_H_ 48 #include <sys/thread2.h> 49 #endif 50 #ifndef _SYS_GLOBALDATA_H_ 51 #include <sys/globaldata.h> 52 #endif 53 #ifndef _MACHINE_ATOMIC_H_ 54 #include <machine/atomic.h> 55 #endif 56 #ifndef _MACHINE_CPUFUNC_H_ 57 #include <machine/cpufunc.h> 58 #endif 59 60 #ifdef SMP 61 62 extern int spin_trylock_wr_contested2(globaldata_t gd); 63 extern void spin_lock_wr_contested2(struct spinlock *mtx); 64 65 #endif 66 67 #ifdef SMP 68 69 /* 70 * Attempt to obtain an exclusive spinlock. Returns FALSE on failure, 71 * TRUE on success. 72 */ 73 static __inline boolean_t 74 spin_trylock(struct spinlock *mtx) 75 { 76 globaldata_t gd = mycpu; 77 int value; 78 79 ++gd->gd_curthread->td_critcount; 80 cpu_ccfence(); 81 ++gd->gd_spinlocks_wr; 82 if ((value = atomic_swap_int(&mtx->lock, SPINLOCK_EXCLUSIVE)) != 0) 83 return (spin_trylock_wr_contested2(gd)); 84 return (TRUE); 85 } 86 87 #else 88 89 static __inline boolean_t 90 spin_trylock(struct spinlock *mtx) 91 { 92 globaldata_t gd = mycpu; 93 94 ++gd->gd_curthread->td_critcount; 95 cpu_ccfence(); 96 ++gd->gd_spinlocks_wr; 97 return (TRUE); 98 } 99 100 #endif 101 102 /* 103 * Obtain an exclusive spinlock and return. 104 */ 105 static __inline void 106 spin_lock_quick(globaldata_t gd, struct spinlock *mtx) 107 { 108 #ifdef SMP 109 int value; 110 #endif 111 112 ++gd->gd_curthread->td_critcount; 113 cpu_ccfence(); 114 ++gd->gd_spinlocks_wr; 115 #ifdef SMP 116 if ((value = atomic_swap_int(&mtx->lock, SPINLOCK_EXCLUSIVE)) != 0) 117 spin_lock_wr_contested2(mtx); 118 #endif 119 } 120 121 static __inline void 122 spin_lock(struct spinlock *mtx) 123 { 124 spin_lock_quick(mycpu, mtx); 125 } 126 127 /* 128 * Release an exclusive spinlock. We can just do this passively, only 129 * ensuring that our spinlock count is left intact until the mutex is 130 * cleared. 131 */ 132 static __inline void 133 spin_unlock_quick(globaldata_t gd, struct spinlock *mtx) 134 { 135 #ifdef SMP 136 mtx->lock = 0; 137 #endif 138 KKASSERT(gd->gd_spinlocks_wr > 0); 139 --gd->gd_spinlocks_wr; 140 cpu_ccfence(); 141 --gd->gd_curthread->td_critcount; 142 } 143 144 static __inline void 145 spin_unlock(struct spinlock *mtx) 146 { 147 spin_unlock_quick(mycpu, mtx); 148 } 149 150 static __inline void 151 spin_init(struct spinlock *mtx) 152 { 153 mtx->lock = 0; 154 } 155 156 static __inline void 157 spin_uninit(struct spinlock *mtx) 158 { 159 /* unused */ 160 } 161 162 #endif /* _KERNEL */ 163 #endif /* _SYS_SPINLOCK2_H_ */ 164 165