1.\" 2.\" Copyright (c) 2006 The DragonFly Project. All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 8.\" 1. Redistributions of source code must retain the above copyright 9.\" notice, this list of conditions and the following disclaimer. 10.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" notice, this list of conditions and the following disclaimer in 12.\" the documentation and/or other materials provided with the 13.\" distribution. 14.\" 3. Neither the name of The DragonFly Project nor the names of its 15.\" contributors may be used to endorse or promote products derived 16.\" from this software without specific, prior written permission. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" SUCH DAMAGE. 30.\" 31.\" $DragonFly: src/share/man/man9/spinlock.9,v 1.7 2008/02/17 21:47:39 nant Exp $ 32.\" 33.Dd February 17, 2008 34.Os 35.Dt SPINLOCK 9 36.Sh NAME 37.Nm spin_init , 38.Nm spin_lock_rd , 39.Nm spin_lock_rd_quick , 40.Nm spin_lock_wr , 41.Nm spin_lock_wr_quick , 42.Nm spin_trylock_wr , 43.Nm spin_uninit , 44.Nm spin_unlock_rd , 45.Nm spin_unlock_rd_quick , 46.Nm spin_unlock_wr , 47.Nm spin_unlock_wr_quick 48.Nd core spinlocks 49.Sh SYNOPSIS 50.In sys/spinlock.h 51.In sys/spinlock2.h 52.Ft void 53.Fn spin_init "struct spinlock *mtx" 54.Ft void 55.Fn spin_uninit "struct spinlock *mtx" 56.Ft void 57.Fn spin_lock_rd "struct spinlock *mtx" 58.Ft void 59.Fn spin_lock_rd_quick "globaldata_t gd" "struct spinlock *mtx" 60.Ft void 61.Fn spin_unlock_rd "struct spinlock *mtx" 62.Ft void 63.Fn spin_unlock_rd_quick "globaldata_t gd" "struct spinlock *mtx" 64.Ft void 65.Fn spin_lock_wr "struct spinlock *mtx" 66.Ft void 67.Fn spin_lock_wr_quick "globaldata_t gd" "struct spinlock *mtx" 68.Ft boolean_t 69.Fn spin_trylock_wr "struct spinlock *mtx" 70.Ft void 71.Fn spin_unlock_wr "struct spinlock *mtx" 72.Ft void 73.Fn spin_unlock_wr_quick "globaldata_t gd" "struct spinlock *mtx" 74.Sh DESCRIPTION 75The 76.Fa spinlock 77structure and call API are defined in the 78.In sys/spinlock.h 79and 80.In sys/spinlock2.h 81header files, respectively. 82.Pp 83The 84.Fn spin_init 85function initializes a new 86.Fa spinlock 87structure for use. 88The structure is cleaned up with 89.Fn spin_uninit 90when it is no longer needed. 91.Pp 92The 93.Fn spin_lock_rd 94function obtains a shared 95.Em read-only 96spinlock. 97A thread may hold only one shared lock at a time, and may not acquire any 98new exclusive locks while holding a shared lock (but may already be holding 99some). 100A shared spinlock can be held by multiple CPUs concurrently. 101If a thread attempts to obtain an exclusive spinlock while shared 102references from other CPUs exist it will spin until the shared references 103go away. 104No new shared references will be allowed (that is, new shared requests 105will also spin) while the exclusive spinlock is being acquired. 106If you have the current CPU's 107.Fa globaldata 108pointer in hand you can call 109.Fn spin_lock_rd_quick , 110but most code will just call the normal version. 111Shared spinlocks reserve a bit in the spinlock's memory for each CPU 112and do not clear the bit once set. 113This means that once set, a shared spinlock does not need to issue a 114locked read-modify-write bus cycle to the spinlock's memory, which in 115turn greatly reduces conflicts between CPU caches. 116The bit is cleared via a different mechanism only when an exclusive 117spinlock is acquired. 118The result is extremely low overheads even when a shared spinlock is 119being operated upon concurrently by multiple CPUs. 120.Pp 121A previously obtained shared spinlock is released by calling either 122.Fn spin_unlock_rd 123or 124.Fn spin_unlock_rd_quick . 125.Pp 126The 127.Fn spin_lock_wr 128function obtains an exclusive 129.Em read-write 130spinlock. 131A thread may hold any number of exclusive spinlocks but should always 132be mindful of ordering deadlocks. 133Exclusive spinlocks can only be safely 134acquired if no shared spinlocks are held. 135The 136.Fn spin_trylock_wr 137function will return 138.Dv TRUE 139if the spinlock was successfully obtained and 140.Dv FALSE 141if it wasn't. 142If you have the current CPU's 143.Fa globaldata 144pointer in hand you can call 145.Fn spin_lock_wr_quick , 146but most code will just call the normal version. 147A spinlock used only for exclusive access has about the same overhead 148as a mutex based on a locked bus cycle. 149When used in a mixed shared/exclusive environment, however, additional 150overhead may be incurred to obtain the exclusive spinlock. 151Because shared spinlocks are left intact even after released (to 152optimize shared spinlock performance), the exclusive spinlock code 153must run through any shared bits it finds in the spinlock, clear them, 154and check the related CPU's 155.Fa globaldata 156structure to determine whether it needs to spin or not. 157.Pp 158A previously obtained exclusive spinlock is released by calling either 159.Fn spin_unlock_wr 160or 161.Fn spin_unlock_wr_quick . 162.Sh IMPLEMENTATION NOTES 163A thread may not hold any spinlock across a blocking condition or 164thread switch. 165LWKT tokens should be used for situations where you want an exclusive 166run-time lock that will survive a blocking condition or thread switch. 167Tokens will be automatically unlocked when a thread switches away and 168relocked when the thread is switched back in. 169If you want a lock that survives a blocking condition or thread switch 170without being released, use 171.Xr lockmgr 9 172locks or LWKT reader/writer locks. 173.Pp 174.Dx Ap s 175core spinlocks should only be used around small contained sections of 176code. 177For example, to manage a reference count or to implement higher level 178locking mechanisms. 179Both the token code and the 180.Xr lockmgr 9 181code use exclusive spinlocks internally. 182Core spinlocks should not be used around large chunks of code. 183.Pp 184Holding one or more spinlocks will disable thread preemption by 185another thread (e.g. preemption by an interrupt thread), but will not 186disable FAST interrupts or IPIs. 187This means that a FAST interrupt can still operate during a spinlock, 188and any threaded interrupt (which is basically all interrupts except 189the clock interrupt) will still be scheduled for later execution, but 190will not be able to preempt the current thread. 191If you wish to disable FAST interrupts and IPIs you need to enter a 192critical section prior to obtaining the spinlock. 193.Pp 194Currently, FAST interrupts, including IPI messages, are not allowed to 195acquire any spinlocks. 196It is possible to work around this if 197.Va mycpu->gd_spinlocks_wr 198and 199.Va mycpu->gd_spinlocks_rd 200are both 0. 201If one 202or the other is not zero, the FAST interrupt or IPI cannot acquire 203any spinlocks without risking a deadlock, even if the spinlocks in 204question are not related. 205.Pp 206A thread may hold any number of exclusive 207.Em read-write 208spinlocks. 209However, a thread may only hold one shared 210.Em read-only 211spinlock, and may not acquire any new exclusive locks while it is holding 212that one shared lock. 213This requirement is due to the method exclusive 214spinlocks use to determine when they can clear cached shared bits in 215the lock. 216If an exclusive lock is acquired while holding shared locks, 217a deadlock can occur even if the locks are unrelated. 218Always be mindful of potential deadlocks. 219.Pp 220Spinlocks spin. 221A thread will not block, switch away, or lose its critical section 222while obtaining or releasing a spinlock. 223Spinlocks do not use IPIs or other mechanisms. 224They are considered to be a very low level mechanism. 225.Pp 226If a spinlock can not be obtained after one second a warning will be 227printed on the console. 228If a system panic occurs, spinlocks will succeed after one second in 229order to allow the panic operation to proceed. 230.Pp 231If you have a complex structure such as a 232.Xr vnode 9 233which contains a token or 234.Xr lockmgr 9 235lock, it is legal to directly access the internal spinlock embedded 236in those structures for other purposes as long as the spinlock is not 237held when you issue the token or 238.Xr lockmgr 9 239operation. 240.Sh SEE ALSO 241.Xr crit_enter 9 , 242.Xr lockmgr 9 , 243.Xr serializer 9 244.Sh HISTORY 245A 246.Nm spinlock 247implementation first appeared in 248.Dx 1.3 . 249.Sh AUTHORS 250.An -nosplit 251The original 252.Nm spinlock 253implementation was written by 254.An Jeffrey M. Hsu 255and was later extended by 256.An Matthew Dillon . 257This manual page was written by 258.An Matthew Dillon 259and 260.An Sascha Wildner . 261