1.\" Copyright (c) 2006 Gleb Smirnoff <glebius@FreeBSD.org> 2.\" 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.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd November 25, 2007 28.Dt RWLOCK 9 29.Os 30.Sh NAME 31.Nm rwlock , 32.Nm rw_init , 33.Nm rw_init_flags, 34.Nm rw_destroy , 35.Nm rw_rlock , 36.Nm rw_wlock , 37.Nm rw_runlock , 38.Nm rw_wunlock , 39.Nm rw_try_upgrade , 40.Nm rw_downgrade , 41.Nm rw_sleep , 42.Nm rw_initialized , 43.Nm rw_wowned , 44.Nm rw_assert , 45.Nm RW_SYSINIT 46.Nd kernel reader/writer lock 47.Sh SYNOPSIS 48.In sys/param.h 49.In sys/lock.h 50.In sys/rwlock.h 51.Ft void 52.Fn rw_init "struct rwlock *rw" "const char *name" 53.Ft void 54.Fn rw_init_flags "struct rwlock *rw" "const char *name" "int opts" 55.Ft void 56.Fn rw_destroy "struct rwlock *rw" 57.Ft void 58.Fn rw_rlock "struct rwlock *rw" 59.Ft void 60.Fn rw_wlock "struct rwlock *rw" 61.Ft void 62.Fn rw_runlock "struct rwlock *rw" 63.Ft void 64.Fn rw_wunlock "struct rwlock *rw" 65.Ft int 66.Fn rw_try_upgrade "struct rwlock *rw" 67.Ft void 68.Fn rw_downgrade "struct rwlock *rw" 69.Ft int 70.Fn rw_sleep "void *chan" "struct rwlock *rw" "int priority" "const char *wmesg" "int timo" 71.Ft int 72.Fn rw_initialized "struct rwlock *rw" 73.Ft int 74.Fn rw_wowned "struct rwlock *rw" 75.Pp 76.Cd "options INVARIANTS" 77.Cd "options INVARIANT_SUPPORT" 78.Ft void 79.Fn rw_assert "struct rwlock *rw" "int what" 80.In sys/kernel.h 81.Fn RW_SYSINIT "name" "struct rwlock *rw" "const char *desc" 82.Sh DESCRIPTION 83Reader/writer locks allow shared access to protected data by multiple threads, 84or exclusive access by a single thread. 85The threads with shared access are known as 86.Em readers 87since they only read the protected data. 88A thread with exclusive access is known as a 89.Em writer 90since it can modify protected data. 91.Pp 92Although reader/writer locks look very similar to 93.Xr sx 9 94locks, their usage pattern is different. 95Reader/writer locks can be treated as mutexes (see 96.Xr mutex 9 ) 97with shared/exclusive semantics. 98Unlike 99.Xr sx 9 , 100an 101.Nm 102can be locked while holding a non-spin mutex, and an 103.Nm 104cannot be held while sleeping. 105The 106.Nm 107locks have priority propagation like mutexes, but priority 108can be propagated only to an exclusive holder. 109This limitation comes from the fact that shared owners 110are anonymous. 111Another important property is that shared holders of 112.Nm 113can recurse, 114and exclusive locks can be made recursive selectively. 115.Ss Macros and Functions 116.Bl -tag -width indent 117.It Fn rw_init "struct rwlock *rw" "const char *name" 118Initialize structure located at 119.Fa rw 120as reader/writer lock, described by name 121.Fa name . 122The description is used solely for debugging purposes. 123This function must be called before any other operations 124on the lock. 125.It Fn rw_init_flags "struct rwlock *rw" "const char *name" "int opts" 126Initialize the rw lock just like the 127.Fn rw_init 128function, but specifying a set of optional flags to alter the 129behaviour of 130.Fa rw , 131through the 132.Fa opts 133argument. 134It contains one or more of the following flags: 135.Bl -tag -width ".Dv RW_NOPROFILE" 136.It Dv RW_DUPOK 137Witness should not log messages about duplicate locks being acquired. 138.It Dv RW_NOPROFILE 139Do not profile this lock. 140.It Dv RW_NOWITNESS 141Instruct 142.Xr witness 4 143to ignore this lock. 144.It Dv RW_QUIET 145Do not log any operations for this lock via 146.Xr ktr 4 . 147.It Dv RW_RECURSE 148Allow threads to recursively acquire exclusive locks for 149.Fa rw . 150.It Fn rw_rlock "struct rwlock *rw" 151Lock 152.Fa rw 153as a reader. 154If any thread holds this lock exclusively, the current thread blocks, 155and its priority is propagated to the exclusive holder. 156The 157.Fn rw_rlock 158function can be called when the thread has already acquired reader 159access on 160.Fa rw . 161This is called 162.Dq "recursing on a lock" . 163.It Fn rw_wlock "struct rwlock *rw" 164Lock 165.Fa rw 166as a writer. 167If there are any shared owners of the lock, the current thread blocks. 168The 169.Fn rw_wlock 170function can be called recursively only if 171.Fa rw 172has been initialized with the 173.Dv RW_RECURSE 174option enabled. 175.It Fn rw_runlock "struct rwlock *rw" 176This function releases a shared lock previously acquired by 177.Fn rw_rlock . 178.It Fn rw_wunlock "struct rwlock *rw" 179This function releases an exclusive lock previously acquired by 180.Fn rw_wlock . 181.It Fn rw_try_upgrade "struct rwlock *rw" 182Attempt to upgrade a single shared lock to an exclusive lock. 183The current thread must hold a shared lock of 184.Fa rw . 185This will only succeed if the current thread holds the only shared lock on 186.Fa rw , 187and it only holds a single shared lock. 188If the attempt succeeds 189.Fn rw_try_upgrade 190will return a non-zero value, 191and the current thread will hold an exclusive lock. 192If the attempt fails 193.Fn rw_try_upgrade 194will return zero, 195and the current thread will still hold a shared lock. 196.It Fn rw_downgrade "struct rwlock *rw" 197Convert an exclusive lock into a single shared lock. 198The current thread must hold an exclusive lock of 199.Fa rw . 200.It Fn rw_sleep "void *chan" "struct rwlock *rw" "int priority" "const char *wmesg" "int timo" 201Atomically release 202.Fa rw 203while waiting for an event. 204For more details on the parameters to this function, 205see 206.Xr sleep 9 . 207.It Fn rw_initialized "struct rwlock *rw" 208This function returns non-zero if 209.Fa rw 210has been initialized, and zero otherwise. 211.It Fn rw_destroy "struct rwlock *rw" 212This functions destroys a lock previously initialized with 213.Fn rw_init . 214The 215.Fa rw 216lock must be unlocked. 217.It Fn rw_wowned "struct rwlock *rw" 218This function returns a non-zero value if the current thread owns an 219exclusive lock on 220.Fa rw . 221.It Fn rw_assert "struct rwlock *rw" "int what" 222This function allows assertions specified in 223.Fa what 224to be made about 225.Fa rw . 226If the assertions are not true and the kernel is compiled 227with 228.Cd "options INVARIANTS" 229and 230.Cd "options INVARIANT_SUPPORT" , 231the kernel will panic. 232Currently the following assertions are supported: 233.Bl -tag -width ".Dv RA_UNLOCKED" 234.It Dv RA_LOCKED 235Assert that current thread holds either a shared or exclusive lock 236of 237.Fa rw . 238.It Dv RA_RLOCKED 239Assert that current thread holds a shared lock of 240.Fa rw . 241.It Dv RA_WLOCKED 242Assert that current thread holds an exclusive lock of 243.Fa rw . 244.It Dv RA_UNLOCKED 245Assert that current thread holds neither a shared nor exclusive lock of 246.Fa rw . 247.El 248.El 249.Sh SEE ALSO 250.Xr locking 9 , 251.Xr mutex 9 , 252.Xr panic 9 , 253.Xr sema 9 , 254.Xr sx 9 255.Sh HISTORY 256These 257functions appeared in 258.Fx 7.0 . 259.Sh AUTHORS 260.An -nosplit 261The 262.Nm 263facility was written by 264.An "John Baldwin" . 265This manual page was written by 266.An "Gleb Smirnoff" . 267.Sh BUGS 268If 269.Dv WITNESS 270is not included in the kernel, 271then it is impossible to assert that the current thread does or does not 272hold a read lock. 273In the 274.Pf non- Dv WITNESS 275case, the 276.Dv RA_LOCKED 277and 278.Dv RA_RLOCKED 279assertions merely check that some thread holds a read lock. 280.Pp 281Reader/writer is a bit of an awkward name. 282An 283.Nm 284can also be called a 285.Dq Robert Watson 286lock if desired. 287