| 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 | .Dd August 30, 2010 |
| 32 | .Dt SPINLOCK 9 |
| 33 | .Os |
| 34 | .Sh NAME |
| 35 | .Nm spin_init , |
| 36 | .Nm spin_lock , |
| 37 | .Nm spin_lock_quick , |
| 38 | .Nm spin_trylock , |
| 39 | .Nm spin_uninit , |
| 40 | .Nm spin_unlock , |
| 41 | .Nm spin_unlock_quick , |
| 42 | .Nm spin_pool_lock , |
| 43 | .Nm spin_pool_unlock |
| 44 | .Nd core spinlocks |
| 45 | .Sh SYNOPSIS |
| 46 | .In sys/spinlock.h |
| 47 | .In sys/spinlock2.h |
| 48 | .Ft void |
| 49 | .Fn spin_init "struct spinlock *mtx" |
| 50 | .Ft void |
| 51 | .Fn spin_uninit "struct spinlock *mtx" |
| 52 | .Ft void |
| 53 | .Fn spin_lock "struct spinlock *mtx" |
| 54 | .Ft void |
| 55 | .Fn spin_lock_quick "globaldata_t gd" "struct spinlock *mtx" |
| 56 | .Ft boolean_t |
| 57 | .Fn spin_trylock "struct spinlock *mtx" |
| 58 | .Ft void |
| 59 | .Fn spin_unlock "struct spinlock *mtx" |
| 60 | .Ft void |
| 61 | .Fn spin_unlock_quick "globaldata_t gd" "struct spinlock *mtx" |
| 62 | .Sh DESCRIPTION |
| 63 | The |
| 64 | .Fa spinlock |
| 65 | structure and call API are defined in the |
| 66 | .In sys/spinlock.h |
| 67 | and |
| 68 | .In sys/spinlock2.h |
| 69 | header files, respectively. |
| 70 | .Pp |
| 71 | The |
| 72 | .Fn spin_init |
| 73 | function initializes a new |
| 74 | .Fa spinlock |
| 75 | structure for use. |
| 76 | The structure is cleaned up with |
| 77 | .Fn spin_uninit |
| 78 | when it is no longer needed. |
| 79 | .Pp |
| 80 | The |
| 81 | .Fn spin_lock |
| 82 | function obtains an exclusive |
| 83 | .Em read-write |
| 84 | spinlock. |
| 85 | A thread may hold any number of exclusive spinlocks but should always |
| 86 | be mindful of ordering deadlocks. |
| 87 | The |
| 88 | .Fn spin_trylock |
| 89 | function will return |
| 90 | .Dv TRUE |
| 91 | if the spinlock was successfully obtained and |
| 92 | .Dv FALSE |
| 93 | if it wasn't. |
| 94 | If you have the current CPU's |
| 95 | .Fa globaldata |
| 96 | pointer in hand you can call |
| 97 | .Fn spin_lock_quick , |
| 98 | but most code will just call the normal version. |
| 99 | A spinlock used only for exclusive access has about the same overhead |
| 100 | as a mutex based on a locked bus cycle. |
| 101 | .Pp |
| 102 | A previously obtained exclusive spinlock is released by calling either |
| 103 | .Fn spin_unlock |
| 104 | or |
| 105 | .Fn spin_unlock_quick . |
| 106 | .Pp |
| 107 | The |
| 108 | .Fn spin_pool_lock |
| 109 | function locks a pool spinlock associated with a given address. The spinlock's |
| 110 | lifetime is not tied to any objects at the address. The function returns the |
| 111 | locked spinlock. The |
| 112 | .Fn spin_pool_unlock |
| 113 | function unlocks a pool spinlock associated with an address. Pool spinlocks |
| 114 | need not be initialized. |
| 115 | .Sh IMPLEMENTATION NOTES |
| 116 | A thread may not hold any spinlock across a blocking condition or |
| 117 | thread switch. |
| 118 | LWKT tokens should be used for situations where you want an exclusive |
| 119 | run-time lock that will survive a blocking condition or thread switch. |
| 120 | Tokens will be automatically unlocked when a thread switches away and |
| 121 | relocked when the thread is switched back in. |
| 122 | If you want a lock that survives a blocking condition or thread switch |
| 123 | without being released, use |
| 124 | .Xr lockmgr 9 |
| 125 | locks or LWKT reader/writer locks. |
| 126 | .Pp |
| 127 | .Dx Ap s |
| 128 | core spinlocks should only be used around small contained sections of |
| 129 | code. |
| 130 | For example, to manage a reference count or to implement higher level |
| 131 | locking mechanisms. |
| 132 | Both the token code and the |
| 133 | .Xr lockmgr 9 |
| 134 | code use exclusive spinlocks internally. |
| 135 | Core spinlocks should not be used around large chunks of code. |
| 136 | .Pp |
| 137 | Holding one or more spinlocks will disable thread preemption by |
| 138 | another thread (e.g. preemption by an interrupt thread), but will not |
| 139 | disable FAST interrupts or IPIs. |
| 140 | This means that a FAST interrupt can still operate during a spinlock, |
| 141 | and any threaded interrupt (which is basically all interrupts except |
| 142 | the clock interrupt) will still be scheduled for later execution, but |
| 143 | will not be able to preempt the current thread. |
| 144 | If you wish to disable FAST interrupts and IPIs you need to enter a |
| 145 | critical section prior to obtaining the spinlock. |
| 146 | .Pp |
| 147 | Currently, FAST interrupts, including IPI messages, are not allowed to |
| 148 | acquire any spinlocks. |
| 149 | It is possible to work around this if |
| 150 | .Va mycpu->gd_spinlocks_wr |
| 151 | is 0. |
| 152 | If one |
| 153 | or the other is not zero, the FAST interrupt or IPI cannot acquire |
| 154 | any spinlocks without risking a deadlock, even if the spinlocks in |
| 155 | question are not related. |
| 156 | .Pp |
| 157 | A thread may hold any number of exclusive |
| 158 | .Em read-write |
| 159 | spinlocks. |
| 160 | .Pp |
| 161 | Spinlocks spin. |
| 162 | A thread will not block, switch away, or lose its critical section |
| 163 | while obtaining or releasing a spinlock. |
| 164 | Spinlocks do not use IPIs or other mechanisms. |
| 165 | They are considered to be a very low level mechanism. |
| 166 | .Pp |
| 167 | If a spinlock can not be obtained after one second a warning will be |
| 168 | printed on the console. |
| 169 | If a system panic occurs, spinlocks will succeed after one second in |
| 170 | order to allow the panic operation to proceed. |
| 171 | .Pp |
| 172 | If you have a complex structure such as a |
| 173 | .Xr vnode 9 |
| 174 | which contains a token or |
| 175 | .Xr lockmgr 9 |
| 176 | lock, it is legal to directly access the internal spinlock embedded |
| 177 | in those structures for other purposes as long as the spinlock is not |
| 178 | held when you issue the token or |
| 179 | .Xr lockmgr 9 |
| 180 | operation. |
| 181 | .Sh FILES |
| 182 | The uncontended path of the spinlock implementation is in |
| 183 | .Pa /sys/sys/spinlock2.h . |
| 184 | The core of the spinlock implementation is in |
| 185 | .Pa /sys/kern/kern_spinlock.c . |
| 186 | .Sh SEE ALSO |
| 187 | .Xr crit_enter 9 , |
| 188 | .Xr lockmgr 9 , |
| 189 | .Xr serializer 9 |
| 190 | .Sh HISTORY |
| 191 | A |
| 192 | .Nm spinlock |
| 193 | implementation first appeared in |
| 194 | .Dx 1.3 . |
| 195 | .Sh AUTHORS |
| 196 | .An -nosplit |
| 197 | The original |
| 198 | .Nm spinlock |
| 199 | implementation was written by |
| 200 | .An Jeffrey M. Hsu |
| 201 | and was later extended by |
| 202 | .An Matthew Dillon . |
| 203 | This manual page was written by |
| 204 | .An Matthew Dillon |
| 205 | and |
| 206 | .An Sascha Wildner . |