1.\" $OpenBSD: rwlock.9,v 1.27 2025/01/29 15:10:35 mpi Exp $ 2.\" 3.\" Copyright (c) 2006 Pedro Martelletto <pedro@ambientworks.net> 4.\" All rights reserved. 5.\" 6.\" Permission to use, copy, modify, and distribute this software for any 7.\" purpose with or without fee is hereby granted, provided that the above 8.\" copyright notice and this permission notice appear in all copies. 9.\" 10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17.\" 18.Dd $Mdocdate: January 29 2025 $ 19.Dt RWLOCK 9 20.Os 21.Sh NAME 22.Nm rwlock , 23.Nm rw_init , 24.Nm rw_init_flags , 25.Nm rw_enter , 26.Nm rw_exit , 27.Nm rw_enter_read , 28.Nm rw_enter_write , 29.Nm rw_exit_read , 30.Nm rw_exit_write , 31.Nm rw_assert_wrlock , 32.Nm rw_assert_rdlock , 33.Nm rw_assert_anylock , 34.Nm rw_assert_unlocked , 35.Nm rw_status , 36.Nm RWLOCK_INITIALIZER , 37.Nm rrw_init , 38.Nm rrw_init_flags , 39.Nm rrw_enter , 40.Nm rrw_exit , 41.Nm rrw_status 42.Nd interface to read/write locks 43.Sh SYNOPSIS 44.In sys/rwlock.h 45.Ft void 46.Fn rw_init "struct rwlock *rwl" "const char *name" 47.Ft void 48.Fn rw_init_flags "struct rwlock *rwl" "const char *name" "int flags" 49.Ft int 50.Fn rw_enter "struct rwlock *rwl" "int flags" 51.Ft void 52.Fn rw_exit "struct rwlock *rwl" 53.Ft void 54.Fn rw_enter_read "struct rwlock *rwl" 55.Ft void 56.Fn rw_enter_write "struct rwlock *rwl" 57.Ft void 58.Fn rw_exit_read "struct rwlock *rwl" 59.Ft void 60.Fn rw_exit_write "struct rwlock *rwl" 61.Ft void 62.Fn rw_assert_wrlock "struct rwlock *rwl" 63.Ft void 64.Fn rw_assert_rdlock "struct rwlock *rwl" 65.Ft void 66.Fn rw_assert_anylock "struct rwlock *rwl" 67.Ft void 68.Fn rw_assert_unlocked "struct rwlock *rwl" 69.Ft int 70.Fn rw_status "struct rwlock *rwl" 71.Fn RWLOCK_INITIALIZER "const char *name" 72.Ft void 73.Fn rrw_init "struct rrwlock *rrwl" "const char *name" 74.Ft void 75.Fn rrw_init_flags "struct rrwlock *rrwl" "const char *name" "int flags" 76.Ft int 77.Fn rrw_enter "struct rrwlock *rrwl" "int flags" 78.Ft void 79.Fn rrw_exit "struct rrwlock *rrwl" 80.Ft int 81.Fn rrw_status "struct rrwlock *rrwl" 82.Sh DESCRIPTION 83The 84.Nm 85set of functions provides a multiple-reader, single-writer locking mechanism to 86ensure mutual exclusion between different threads. 87.Pp 88Read locks can be acquired while the write lock is not held, and may coexist in 89distinct threads at any time. 90A write lock, however, can only be acquired when there are no read locks held, 91granting exclusive access to a single thread. 92.Pp 93The 94.Fn rw_init 95function is used to initiate the lock pointed to by 96.Fa rwl . 97The 98.Fa name 99argument specifies the name of the lock, which is used as the wait message 100if the thread needs to sleep. 101.Pp 102The 103.Fn rw_init_flags 104macro is similar to 105.Fn rw_init , 106but it additionally accepts a bitwise OR of the following flags: 107.Bl -tag -width RWL_NOWITNESS -offset indent 108.It Dv RWL_DUPOK 109Prevents 110.Xr witness 4 111from logging when a thread acquires more than one lock of this lock type. 112.It Dv RWL_IS_VNODE 113Make 114.Xr witness 4 115ignore lock order issues between this lock type and any other lock type 116tagged with the 117.Dv RWL_IS_VNODE 118flag. 119.It Dv RWL_NOWITNESS 120Instructs 121.Xr witness 4 122to ignore this lock. 123.El 124.Pp 125The 126.Fn rw_enter 127function acquires a lock. 128The 129.Fa flags 130argument specifies what kind of lock should be obtained and also 131modifies the operation. 132The possible flags are: 133.Pp 134.Bl -tag -offset indent -width RW_DOWNGRADEXXX -compact 135.It Dv RW_READ 136Acquire a shared lock. 137.It Dv RW_WRITE 138Acquire an exclusive lock. 139.It Dv RW_DOWNGRADE 140Safely release an exclusive lock and acquire a shared lock without 141letting other exclusive locks in between. 142.It Dv RW_UPGRADE 143Upgrade a shared lock into an exclusive one. 144Must be combined with 145.Dv RW_NOSLEEP . 146.It Dv RW_INTR 147When waiting for a lock, allow signals to interrupt the sleep. 148.It Dv RW_NOSLEEP 149Do not wait for busy locks, fail with 150.Dv EBUSY 151instead. 152.It Dv RW_SLEEPFAIL 153Wait for busy locks, but do not obtain them, fail with 154.Dv EAGAIN 155instead. 156.It Dv RW_DUPOK 157Prevents 158.Xr witness 4 , 159for just this 160.Fn rw_enter , 161from logging when this thread already has a lock of this lock type. 162.El 163.Pp 164The 165.Fn rw_exit 166function is used to release a held lock. 167.Pp 168The 169.Fn rw_enter_read 170function acquires a read lock, sleeping if necessary. 171.Pp 172The 173.Fn rw_enter_write 174function acquires a write lock, sleeping if necessary. 175.Pp 176The 177.Fn rw_exit_read 178function releases a read lock. 179.Pp 180The 181.Fn rw_exit_write 182function releases a write lock. 183.Pp 184The 185.Fn rw_assert_wrlock , 186.Fn rw_assert_rdlock , 187.Fn rw_assert_anylock , 188and 189.Fn rw_assert_unlocked 190functions check the status 191.Fa rwl , 192panicking if it is not write-, read-, any-, or unlocked, respectively. 193.Pp 194.Nm rw_status 195returns the current state of the lock. 196.Pp 197A lock declaration may be initialised with the 198.Fn RWLOCK_INITIALIZER 199macro. 200The 201.Fa name 202argument specifies the name of the lock, which is used as the wait message 203if the thread needs to sleep. 204.Pp 205The 206.Nm rrwlock 207functions support recursive write locking by the same process. 208They otherwise behave the same as their rwlock counterparts. 209.Sh CONTEXT 210.Fn rw_init , 211.Fn rw_init_flags , 212.Fn rrw_init 213and 214.Fn rrw_init_flags 215can be called during autoconf, from process context, or from interrupt context. 216.Pp 217All other functions can be called during autoconf or from process context. 218.Sh RETURN VALUES 219.Nm rw_enter 220and 221.Nm rrw_enter 222return 0 on success, or an 223.Xr errno 2 224style value on failure. 225.Pp 226.Nm rw_status 227and 228.Nm rrw_status 229return the state of the lock: 230.Pp 231.Bl -tag -width "RW_WRITE_OTHER" -offset indent -compact 232.It Dv RW_WRITE 233Lock is write locked by the calling thread. 234.It Dv RW_WRITE_OTHER 235Lock is write locked by a different thread. 236.It Dv RW_READ 237Lock is read locked. 238The current thread may be one of the threads that has it locked. 239.It 0 240Lock is not locked. 241.El 242.Sh SEE ALSO 243.Xr witness 4 , 244.Xr mutex 9 , 245.Xr rwsleep 9 , 246.Xr spl 9 247.Sh HISTORY 248The 249.Nm 250functions first appeared in 251.Ox 3.5 . 252.Sh AUTHORS 253The 254.Nm 255functions were written by 256.An Artur Grabowski Aq Mt art@openbsd.org . 257