1.\" $NetBSD: rwlock.9,v 1.20 2020/02/22 21:24:45 ad Exp $ 2.\" 3.\" Copyright (c) 2006, 2007, 2009, 2020 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This code is derived from software contributed to The NetBSD Foundation 7.\" by Andrew Doran. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" POSSIBILITY OF SUCH DAMAGE. 29.\" 30.Dd February 22, 2020 31.Dt RWLOCK 9 32.Os 33.Sh NAME 34.Nm rw , 35.Nm rw_init , 36.Nm rw_destroy , 37.Nm rw_enter , 38.Nm rw_exit , 39.Nm rw_tryenter , 40.Nm rw_tryupgrade , 41.Nm rw_downgrade , 42.Nm rw_read_held , 43.Nm rw_write_held , 44.Nm rw_lock_held , 45.Nm rw_lock_op 46.Nd reader / writer lock primitives 47.Sh SYNOPSIS 48.In sys/rwlock.h 49.Ft void 50.Fn rw_init "krwlock_t *rw" 51.Ft void 52.Fn rw_destroy "krwlock_t *rw" 53.Ft void 54.Fn rw_enter "krwlock_t *rw" "const krw_t op" 55.Ft void 56.Fn rw_exit "krwlock_t *rw" 57.Ft int 58.Fn rw_tryenter "krwlock_t *rw" "const krw_t op" 59.Ft int 60.Fn rw_tryupgrade "krwlock_t *rw" 61.Ft void 62.Fn rw_downgrade "krwlock_t *rw" 63.Ft int 64.Fn rw_read_held "krwlock_t *rw" 65.Ft int 66.Fn rw_write_held "krwlock_t *rw" 67.Ft int 68.Fn rw_lock_held "krwlock_t *rw" 69.Ft krw_t 70.Fn rw_lock_op "krwlock_t *rw" 71.Pp 72.Cd "options DIAGNOSTIC" 73.Cd "options LOCKDEBUG" 74.Sh DESCRIPTION 75Reader / writer locks (RW locks) are used in the kernel to synchronize access 76to an object among LWPs (lightweight processes) and soft interrupt handlers. 77.Pp 78In addition to the capabilities provided by mutexes, RW locks distinguish 79between read (shared) and write (exclusive) access. 80.Pp 81RW locks are in one of three distinct states at any given time: 82.Bl -tag -width cdosrunrundo 83.It Dv Unlocked 84The lock is not held. 85.It Dv Read locked 86The lock holders intend to read the protected object. 87Multiple callers may hold a RW lock with 88.Dq read intent 89simultaneously. 90.It Dv Write locked 91The lock holder intends to update the protected object. 92Only one caller may hold a RW lock with 93.Dq write intent . 94.El 95.Pp 96The 97.Vt krwlock_t 98type provides storage for the RW lock object. 99This should be treated as an opaque object and not examined directly by 100consumers. 101.Pp 102Note that these interfaces must not be used from a hardware 103interrupt handler. 104.Sh OPTIONS AND MACROS 105.Bl -tag -width abcd 106.It Cd "options DIAGNOSTIC" 107.Pp 108Kernels compiled with the 109.Dv DIAGNOSTIC 110option perform basic sanity checks on RW lock operations. 111.It Cd "options LOCKDEBUG" 112.Pp 113Kernels compiled with the 114.Dv LOCKDEBUG 115option perform potentially CPU intensive sanity checks 116on RW lock operations. 117.El 118.Sh FUNCTIONS 119.Bl -tag -width abcd 120.It Fn rw_init "rw" 121.Pp 122Initialize a lock for use. 123No other operations can be performed on the lock until it has been 124initialized. 125.It Fn rw_destroy "rw" 126.Pp 127Release resources used by a lock. 128The lock may not be used after it has been destroyed. 129.It Fn rw_enter "rw" "op" 130.Pp 131If 132.Dv RW_READER 133is specified as the argument to 134.Fa op , 135acquire a read lock. 136The caller may block and will not return until the hold is acquired. 137Callers must not recursively acquire read locks. 138.Pp 139If 140.Dv RW_WRITER 141is specified, acquire a write lock. 142If the lock is already held, the caller will block and not return until the 143hold is acquired. 144.Pp 145RW locks and other types of locks must always be acquired in a 146consistent order with respect to each other. 147Otherwise, the potential for system deadlock exists. 148.It Fn rw_exit "rw" 149.Pp 150Release a lock. 151The lock must have been previously acquired by the caller. 152.It Fn rw_tryenter "rw" "op" 153.Pp 154Try to acquire a lock, but do not block if the lock is already held. 155If the lock is acquired successfully, return non-zero. 156Otherwise, return zero. 157.Pp 158Valid arguments to 159.Fa op 160are 161.Dv RW_READER 162or 163.Dv RW_WRITER . 164.It Fn rw_tryupgrade "rw" 165.Pp 166Try to upgrade a lock from one read hold to a write hold. 167If the lock is upgraded successfully, returns non-zero. 168Otherwise, returns zero. 169.It Fn rw_downgrade "rw" 170.Pp 171Downgrade a lock from a write hold to a read hold. 172.It Fn rw_write_held "rw" 173.Pp 174Return non-zero if write lock is held by current lwp. 175Otherwise, return zero. 176.It Fn rw_read_held "rw" 177.Pp 178Returns non-zero if read lock is held by any lwp. 179Otherwise, return zero. 180.It Fn rw_lock_held "rw" 181.Pp 182Returns non-zero if either read or write lock is held by any lwp. 183Otherwise, return zero. 184.Pp 185.Fn rw_write_held , 186.Fn rw_read_held , 187and 188.Fn rw_lock_held 189should not generally be used to make locking decisions at run time: 190they are provided for diagnostic purposes, for example making 191assertions. 192.Pp 193Negative assertions (lock not held) should not be made due to atomicity 194issues, excepting 195.Fn rw_write_held , 196which can safely be used to assert that a write lock is NOT held by 197the current LWP. 198.It Fn rw_lock_op "rw" 199.Pp 200For a lock that is known to be held by the calling LWP, return either 201.Dv RW_READER 202or 203.Dv RW_WRITER 204to denote the type of hold. 205This is useful when dropping and later re-acquiring a lock, if the type 206of hold is not already known. 207.El 208.Sh PERFORMANCE CONSIDERATIONS 209RW locks are subject to high cache contention on multiprocessor systems, 210and scale poorly when the write:read ratio is not strongly in favour of 211readers. 212Ideally, RW locks should only be used in settings when the following three 213conditions are met: 214.Bl -bullet 215.It 216The data object(s) protected by the RW lock are read much more frequently 217than written. 218.It 219The read-side hold time for the RW lock is long (in the order of thousands 220of processor clock cycles). 221.It 222Strong synchronization semantics are required: there is no scope for 223lockless, lazy or optimistic synchronization. 224.El 225.Pp 226Generally speaking, it is better to organise code paths and/or 227data flows such that fewer and weaker synchronization points are required 228to ensure correct operation. 229.Sh CODE REFERENCES 230The core of the RW lock implementation is in 231.Pa sys/kern/kern_rwlock.c . 232.Pp 233The header file 234.Pa sys/sys/rwlock.h 235describes the public interface, and interfaces that machine-dependent 236code must provide to support RW locks. 237.Sh SEE ALSO 238.Xr membar_ops 3 , 239.Xr lockstat 8 , 240.Xr condvar 9 , 241.Xr mutex 9 242.Rs 243.%A Jim Mauro 244.%A Richard McDougall 245.%T Solaris Internals: Core Kernel Architecture 246.%I Prentice Hall 247.%D 2001 248.%O ISBN 0-13-022496-0 249.Re 250.Sh HISTORY 251The RW lock primitives first appeared in 252.Nx 5.0 . 253