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 March 16, 2008 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_unlock , 40.Nm rw_try_upgrade , 41.Nm rw_downgrade , 42.Nm rw_sleep , 43.Nm rw_initialized , 44.Nm rw_wowned , 45.Nm rw_assert , 46.Nm RW_SYSINIT 47.Nd kernel reader/writer lock 48.Sh SYNOPSIS 49.In sys/param.h 50.In sys/lock.h 51.In sys/rwlock.h 52.Ft void 53.Fn rw_init "struct rwlock *rw" "const char *name" 54.Ft void 55.Fn rw_init_flags "struct rwlock *rw" "const char *name" "int opts" 56.Ft void 57.Fn rw_destroy "struct rwlock *rw" 58.Ft void 59.Fn rw_rlock "struct rwlock *rw" 60.Ft void 61.Fn rw_wlock "struct rwlock *rw" 62.Ft void 63.Fn rw_runlock "struct rwlock *rw" 64.Ft void 65.Fn rw_wunlock "struct rwlock *rw" 66.Ft void 67.Fn rw_unlock "struct rwlock *rw" 68.Ft int 69.Fn rw_try_upgrade "struct rwlock *rw" 70.Ft void 71.Fn rw_downgrade "struct rwlock *rw" 72.Ft int 73.Fn rw_sleep "void *chan" "struct rwlock *rw" "int priority" "const char *wmesg" "int timo" 74.Ft int 75.Fn rw_initialized "struct rwlock *rw" 76.Ft int 77.Fn rw_wowned "struct rwlock *rw" 78.Pp 79.Cd "options INVARIANTS" 80.Cd "options INVARIANT_SUPPORT" 81.Ft void 82.Fn rw_assert "struct rwlock *rw" "int what" 83.In sys/kernel.h 84.Fn RW_SYSINIT "name" "struct rwlock *rw" "const char *desc" 85.Sh DESCRIPTION 86Reader/writer locks allow shared access to protected data by multiple threads, 87or exclusive access by a single thread. 88The threads with shared access are known as 89.Em readers 90since they only read the protected data. 91A thread with exclusive access is known as a 92.Em writer 93since it can modify protected data. 94.Pp 95Although reader/writer locks look very similar to 96.Xr sx 9 97locks, their usage pattern is different. 98Reader/writer locks can be treated as mutexes (see 99.Xr mutex 9 ) 100with shared/exclusive semantics. 101Unlike 102.Xr sx 9 , 103an 104.Nm 105can be locked while holding a non-spin mutex, and an 106.Nm 107cannot be held while sleeping. 108The 109.Nm 110locks have priority propagation like mutexes, but priority 111can be propagated only to an exclusive holder. 112This limitation comes from the fact that shared owners 113are anonymous. 114Another important property is that shared holders of 115.Nm 116can recurse, 117and exclusive locks can be made recursive selectively. 118.Ss Macros and Functions 119.Bl -tag -width indent 120.It Fn rw_init "struct rwlock *rw" "const char *name" 121Initialize structure located at 122.Fa rw 123as reader/writer lock, described by name 124.Fa name . 125The description is used solely for debugging purposes. 126This function must be called before any other operations 127on the lock. 128.It Fn rw_init_flags "struct rwlock *rw" "const char *name" "int opts" 129Initialize the rw lock just like the 130.Fn rw_init 131function, but specifying a set of optional flags to alter the 132behaviour of 133.Fa rw , 134through the 135.Fa opts 136argument. 137It contains one or more of the following flags: 138.Bl -tag -width ".Dv RW_NOPROFILE" 139.It Dv RW_DUPOK 140Witness should not log messages about duplicate locks being acquired. 141.It Dv RW_NOPROFILE 142Do not profile this lock. 143.It Dv RW_NOWITNESS 144Instruct 145.Xr witness 4 146to ignore this lock. 147.It Dv RW_QUIET 148Do not log any operations for this lock via 149.Xr ktr 4 . 150.It Dv RW_RECURSE 151Allow threads to recursively acquire exclusive locks for 152.Fa rw . 153.El 154.It Fn rw_rlock "struct rwlock *rw" 155Lock 156.Fa rw 157as a reader. 158If any thread holds this lock exclusively, the current thread blocks, 159and its priority is propagated to the exclusive holder. 160The 161.Fn rw_rlock 162function can be called when the thread has already acquired reader 163access on 164.Fa rw . 165This is called 166.Dq "recursing on a lock" . 167.It Fn rw_wlock "struct rwlock *rw" 168Lock 169.Fa rw 170as a writer. 171If there are any shared owners of the lock, the current thread blocks. 172The 173.Fn rw_wlock 174function can be called recursively only if 175.Fa rw 176has been initialized with the 177.Dv RW_RECURSE 178option enabled. 179.It Fn rw_runlock "struct rwlock *rw" 180This function releases a shared lock previously acquired by 181.Fn rw_rlock . 182.It Fn rw_wunlock "struct rwlock *rw" 183This function releases an exclusive lock previously acquired by 184.Fn rw_wlock . 185.It Fn rw_unlock "struct rwlock *rw" 186This function releases a shared lock previously acquired by 187.Fn rw_rlock 188or an exclusive lock previously acquired by 189.Fn rw_wlock . 190.It Fn rw_try_upgrade "struct rwlock *rw" 191Attempt to upgrade a single shared lock to an exclusive lock. 192The current thread must hold a shared lock of 193.Fa rw . 194This will only succeed if the current thread holds the only shared lock on 195.Fa rw , 196and it only holds a single shared lock. 197If the attempt succeeds 198.Fn rw_try_upgrade 199will return a non-zero value, 200and the current thread will hold an exclusive lock. 201If the attempt fails 202.Fn rw_try_upgrade 203will return zero, 204and the current thread will still hold a shared lock. 205.It Fn rw_downgrade "struct rwlock *rw" 206Convert an exclusive lock into a single shared lock. 207The current thread must hold an exclusive lock of 208.Fa rw . 209.It Fn rw_sleep "void *chan" "struct rwlock *rw" "int priority" "const char *wmesg" "int timo" 210Atomically release 211.Fa rw 212while waiting for an event. 213For more details on the parameters to this function, 214see 215.Xr sleep 9 . 216.It Fn rw_initialized "struct rwlock *rw" 217This function returns non-zero if 218.Fa rw 219has been initialized, and zero otherwise. 220.It Fn rw_destroy "struct rwlock *rw" 221This functions destroys a lock previously initialized with 222.Fn rw_init . 223The 224.Fa rw 225lock must be unlocked. 226.It Fn rw_wowned "struct rwlock *rw" 227This function returns a non-zero value if the current thread owns an 228exclusive lock on 229.Fa rw . 230.It Fn rw_assert "struct rwlock *rw" "int what" 231This function allows assertions specified in 232.Fa what 233to be made about 234.Fa rw . 235If the assertions are not true and the kernel is compiled 236with 237.Cd "options INVARIANTS" 238and 239.Cd "options INVARIANT_SUPPORT" , 240the kernel will panic. 241Currently the following assertions are supported: 242.Bl -tag -width ".Dv RA_UNLOCKED" 243.It Dv RA_LOCKED 244Assert that current thread holds either a shared or exclusive lock 245of 246.Fa rw . 247.It Dv RA_RLOCKED 248Assert that current thread holds a shared lock of 249.Fa rw . 250.It Dv RA_WLOCKED 251Assert that current thread holds an exclusive lock of 252.Fa rw . 253.It Dv RA_UNLOCKED 254Assert that current thread holds neither a shared nor exclusive lock of 255.Fa rw . 256.El 257.El 258.Sh SEE ALSO 259.Xr locking 9 , 260.Xr mutex 9 , 261.Xr panic 9 , 262.Xr sema 9 , 263.Xr sx 9 264.Sh HISTORY 265These 266functions appeared in 267.Fx 7.0 . 268.Sh AUTHORS 269.An -nosplit 270The 271.Nm 272facility was written by 273.An "John Baldwin" . 274This manual page was written by 275.An "Gleb Smirnoff" . 276.Sh BUGS 277If 278.Dv WITNESS 279is not included in the kernel, 280then it is impossible to assert that the current thread does or does not 281hold a read lock. 282In the 283.Pf non- Dv WITNESS 284case, the 285.Dv RA_LOCKED 286and 287.Dv RA_RLOCKED 288assertions merely check that some thread holds a read lock. 289.Pp 290Reader/writer is a bit of an awkward name. 291An 292.Nm 293can also be called a 294.Dq Robert Watson 295lock if desired. 296