1f53d15feSStephan Uphoff.\" Copyright (c) 2007 Stephan Uphoff <ups@FreeBSD.org> 2f53d15feSStephan Uphoff.\" Copyright (c) 2006 Gleb Smirnoff <glebius@FreeBSD.org> 3f53d15feSStephan Uphoff.\" All rights reserved. 4f53d15feSStephan Uphoff.\" 5f53d15feSStephan Uphoff.\" Redistribution and use in source and binary forms, with or without 6f53d15feSStephan Uphoff.\" modification, are permitted provided that the following conditions 7f53d15feSStephan Uphoff.\" are met: 8f53d15feSStephan Uphoff.\" 1. Redistributions of source code must retain the above copyright 9f53d15feSStephan Uphoff.\" notice, this list of conditions and the following disclaimer. 10f53d15feSStephan Uphoff.\" 2. Redistributions in binary form must reproduce the above copyright 11f53d15feSStephan Uphoff.\" notice, this list of conditions and the following disclaimer in the 12f53d15feSStephan Uphoff.\" documentation and/or other materials provided with the distribution. 13f53d15feSStephan Uphoff.\" 14f53d15feSStephan Uphoff.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15f53d15feSStephan Uphoff.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16f53d15feSStephan Uphoff.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17f53d15feSStephan Uphoff.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18f53d15feSStephan Uphoff.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19f53d15feSStephan Uphoff.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20f53d15feSStephan Uphoff.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21f53d15feSStephan Uphoff.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22f53d15feSStephan Uphoff.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23f53d15feSStephan Uphoff.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24f53d15feSStephan Uphoff.\" SUCH DAMAGE. 25f53d15feSStephan Uphoff.\" 26f53d15feSStephan Uphoff.\" $FreeBSD$ 27f53d15feSStephan Uphoff.\" 28f53d15feSStephan Uphoff.\" Based on rwlock.9 man page 29*d576deedSPawel Jakub Dawidek.Dd November 16, 2011 30f53d15feSStephan Uphoff.Dt RMLOCK 9 31f53d15feSStephan Uphoff.Os 32f53d15feSStephan Uphoff.Sh NAME 33f53d15feSStephan Uphoff.Nm rmlock , 34f53d15feSStephan Uphoff.Nm rm_init , 351a109c1cSRobert Watson.Nm rm_init_flags , 36f53d15feSStephan Uphoff.Nm rm_destroy , 37f53d15feSStephan Uphoff.Nm rm_rlock , 3836058c09SMax Laier.Nm rm_try_rlock , 39f53d15feSStephan Uphoff.Nm rm_wlock , 40f53d15feSStephan Uphoff.Nm rm_runlock , 41f53d15feSStephan Uphoff.Nm rm_wunlock , 42433ea89aSRobert Watson.Nm rm_wowned , 43f53d15feSStephan Uphoff.Nm RM_SYSINIT 44c6d7cf7bSChristian Brueffer.Nd kernel reader/writer lock optimized for mostly read access patterns 45f53d15feSStephan Uphoff.Sh SYNOPSIS 46f53d15feSStephan Uphoff.In sys/param.h 47f53d15feSStephan Uphoff.In sys/lock.h 48f53d15feSStephan Uphoff.In sys/rmlock.h 49f53d15feSStephan Uphoff.Ft void 501a109c1cSRobert Watson.Fn rm_init "struct rmlock *rm" "const char *name" 511a109c1cSRobert Watson.Ft void 521a109c1cSRobert Watson.Fn rm_init_flags "struct rmlock *rm" "const char *name" "int opts" 53f53d15feSStephan Uphoff.Ft void 54f53d15feSStephan Uphoff.Fn rm_destroy "struct rmlock *rm" 55f53d15feSStephan Uphoff.Ft void 56f53d15feSStephan Uphoff.Fn rm_rlock "struct rmlock *rm" "struct rm_priotracker* tracker" 5736058c09SMax Laier.Ft int 5836058c09SMax Laier.Fn rm_try_rlock "struct rmlock *rm" "struct rm_priotracker* tracker" 59f53d15feSStephan Uphoff.Ft void 60f53d15feSStephan Uphoff.Fn rm_wlock "struct rmlock *rm" 61f53d15feSStephan Uphoff.Ft void 62f53d15feSStephan Uphoff.Fn rm_runlock "struct rmlock *rm" "struct rm_priotracker* tracker" 63f53d15feSStephan Uphoff.Ft void 64f53d15feSStephan Uphoff.Fn rm_wunlock "struct rmlock *rm" 65433ea89aSRobert Watson.Ft int 66*d576deedSPawel Jakub Dawidek.Fn rm_wowned "const struct rmlock *rm" 67f53d15feSStephan Uphoff.In sys/kernel.h 68f53d15feSStephan Uphoff.Fn RM_SYSINIT "name" "struct rmlock *rm" "const char *desc" "int opts" 69f53d15feSStephan Uphoff.Sh DESCRIPTION 70f53d15feSStephan UphoffMostly reader locks allow shared access to protected data by multiple threads, 71f53d15feSStephan Uphoffor exclusive access by a single thread. 72f53d15feSStephan UphoffThe threads with shared access are known as 73f53d15feSStephan Uphoff.Em readers 74f53d15feSStephan Uphoffsince they only read the protected data. 75f53d15feSStephan UphoffA thread with exclusive access is known as a 76f53d15feSStephan Uphoff.Em writer 77f53d15feSStephan Uphoffsince it can modify protected data. 78f53d15feSStephan Uphoff.Pp 79989cbe40SHiten PandyaRead mostly locks are designed to be efficient for locks almost exclusively 80989cbe40SHiten Pandyaused as reader locks and as such should be used for protecting data that 81989cbe40SHiten Pandyararely changes. 82989cbe40SHiten PandyaAcquiring an exclusive lock after the lock had been locked for shared access 83989cbe40SHiten Pandyais an expensive operation. 84f53d15feSStephan Uphoff.Pp 85f53d15feSStephan UphoffAlthough reader/writer locks look very similar to 86f53d15feSStephan Uphoff.Xr sx 9 87f53d15feSStephan Uphofflocks, their usage pattern is different. 88f53d15feSStephan UphoffReader/writer locks can be treated as mutexes (see 89f53d15feSStephan Uphoff.Xr mutex 9 ) 9036058c09SMax Laierwith shared/exclusive semantics unless initialized with 9136058c09SMax Laier.Dv RM_SLEEPABLE . 92f53d15feSStephan UphoffUnlike 93f53d15feSStephan Uphoff.Xr sx 9 , 94f53d15feSStephan Uphoffan 95f53d15feSStephan Uphoff.Nm 96f53d15feSStephan Uphoffcan be locked while holding a non-spin mutex, and an 97f53d15feSStephan Uphoff.Nm 9836058c09SMax Laiercannot be held while sleeping, again unless initialized with 9936058c09SMax Laier.Dv RM_SLEEPABLE . 100f53d15feSStephan UphoffThe 101f53d15feSStephan Uphoff.Nm 102c6d7cf7bSChristian Bruefferlocks have full priority propagation like mutexes. 103c6d7cf7bSChristian BruefferThe 104989cbe40SHiten Pandya.Va rm_priotracker 105989cbe40SHiten Pandyastructure argument supplied in 106989cbe40SHiten Pandya.Fn rm_rlock 107989cbe40SHiten Pandyaand 108989cbe40SHiten Pandya.Fn rm_runlock 109989cbe40SHiten Pandyais used to keep track of the read owner(s). 110f53d15feSStephan UphoffAnother important property is that shared holders of 111f53d15feSStephan Uphoff.Nm 112989cbe40SHiten Pandyacan recurse if the lock has been initialized with the 113989cbe40SHiten Pandya.Dv LO_RECURSABLE 114989cbe40SHiten Pandyaoption, however exclusive locks are not allowed to recurse. 115f53d15feSStephan Uphoff.Ss Macros and Functions 116f53d15feSStephan Uphoff.Bl -tag -width indent 1171a109c1cSRobert Watson.It Fn rm_init "struct rmlock *rm" "const char *name" 118f53d15feSStephan UphoffInitialize structure located at 119f53d15feSStephan Uphoff.Fa rm 120989cbe40SHiten Pandyaas mostly reader lock, described by 121f53d15feSStephan Uphoff.Fa name . 122f53d15feSStephan UphoffThe name description is used solely for debugging purposes. 123f53d15feSStephan UphoffThis function must be called before any other operations 124f53d15feSStephan Uphoffon the lock. 1251a109c1cSRobert Watson.It Fn rm_init_flags "struct rmlock *rm" "const char *name" "int opts" 1261a109c1cSRobert WatsonInitialize the rm lock just like the 1271a109c1cSRobert Watson.Fn rm_init 1281a109c1cSRobert Watsonfunction, but specifying a set of optional flags to alter the 1291a109c1cSRobert Watsonbehaviour of 1301a109c1cSRobert Watson.Fa rm , 1311a109c1cSRobert Watsonthrough the 1321a109c1cSRobert Watson.Fa opts 1331a109c1cSRobert Watsonargument. 1341a109c1cSRobert WatsonIt contains one or more of the following flags: 1351a109c1cSRobert Watson.Bl -tag -width ".Dv RM_NOWITNESS" 1361a109c1cSRobert Watson.It Dv RM_NOWITNESS 1371a109c1cSRobert WatsonInstruct 1381a109c1cSRobert Watson.Xr witness 4 1391a109c1cSRobert Watsonto ignore this lock. 1401a109c1cSRobert Watson.It Dv RM_RECURSE 1411a109c1cSRobert WatsonAllow threads to recursively acquire exclusive locks for 1421a109c1cSRobert Watson.Fa rm . 14336058c09SMax Laier.It Dv RM_SLEEPABLE 14436058c09SMax LaierAllow writers to sleep while holding the lock. 14536058c09SMax LaierReaders must not sleep while holding the lock and can avoid to sleep on 14636058c09SMax Laiertaking the lock by using 14736058c09SMax Laier.Fn rm_try_rlock 14836058c09SMax Laierinstead of 14936058c09SMax Laier.Fn rm_rlock . 1501a109c1cSRobert Watson.El 151f53d15feSStephan Uphoff.It Fn rm_rlock "struct rmlock *rm" "struct rm_priotracker* tracker" 152f53d15feSStephan UphoffLock 153f53d15feSStephan Uphoff.Fa rm 154c6d7cf7bSChristian Bruefferas a reader. 155c6d7cf7bSChristian BruefferUsing 156f53d15feSStephan Uphoff.Fa tracker 157f53d15feSStephan Uphoffto track read owners of a lock for priority propagation. 158989cbe40SHiten PandyaThis data structure is only used internally by 159989cbe40SHiten Pandya.Nm 160c6d7cf7bSChristian Bruefferand must persist until 161c6d7cf7bSChristian Brueffer.Fn rm_runlock 162c6d7cf7bSChristian Bruefferhas been called. 163989cbe40SHiten PandyaThis data structure can be allocated on the stack since 164f53d15feSStephan Uphoffrmlocks cannot be held while sleeping. 165f53d15feSStephan UphoffIf any thread holds this lock exclusively, the current thread blocks, 166f53d15feSStephan Uphoffand its priority is propagated to the exclusive holder. 167989cbe40SHiten PandyaIf the lock was initialized with the 168989cbe40SHiten Pandya.Dv LO_RECURSABLE 169989cbe40SHiten Pandyaoption the 170f53d15feSStephan Uphoff.Fn rm_rlock 171f53d15feSStephan Uphofffunction can be called when the thread has already acquired reader 172f53d15feSStephan Uphoffaccess on 173f53d15feSStephan Uphoff.Fa rm . 174f53d15feSStephan UphoffThis is called 175f53d15feSStephan Uphoff.Dq "recursing on a lock" . 17636058c09SMax Laier.It Fn rm_try_rlock "struct rmlock *rm" "struct rm_priotracker* tracker" 17736058c09SMax LaierTry to lock 17836058c09SMax Laier.Fa rm 17936058c09SMax Laieras a reader. 18036058c09SMax Laier.Fn rm_try_rlock 18136058c09SMax Laierwill return 0 if the lock cannot be acquired immediately; 18236058c09SMax Laierotherwise the lock will be acquired and a non-zero value will be returned. 18336058c09SMax LaierNote that 18436058c09SMax Laier.Fn rm_try_rlock 18536058c09SMax Laiermay fail even while the lock is not currently held by a writer. 186f53d15feSStephan Uphoff.It Fn rm_wlock "struct rmlock *rm" 187f53d15feSStephan UphoffLock 188f53d15feSStephan Uphoff.Fa rm 189f53d15feSStephan Uphoffas a writer. 190f53d15feSStephan UphoffIf there are any shared owners of the lock, the current thread blocks. 191f53d15feSStephan UphoffThe 192f53d15feSStephan Uphoff.Fn rm_wlock 193f53d15feSStephan Uphofffunction cannot be called recursively. 194f53d15feSStephan Uphoff.It Fn rm_runlock "struct rmlock *rm" "struct rm_priotracker* tracker" 195f53d15feSStephan UphoffThis function releases a shared lock previously acquired by 196f53d15feSStephan Uphoff.Fn rm_rlock . 197f53d15feSStephan UphoffThe 198f53d15feSStephan Uphoff.Fa tracker 199f53d15feSStephan Uphoffargument must match the 200f53d15feSStephan Uphoff.Fa tracker 201f53d15feSStephan Uphoffargument used for acquiring the shared lock 202f53d15feSStephan Uphoff.It Fn rm_wunlock "struct rmlock *rm" 203f53d15feSStephan UphoffThis function releases an exclusive lock previously acquired by 204f53d15feSStephan Uphoff.Fn rm_wlock . 205f53d15feSStephan Uphoff.It Fn rm_destroy "struct rmlock *rm" 206f53d15feSStephan UphoffThis functions destroys a lock previously initialized with 207f53d15feSStephan Uphoff.Fn rm_init . 208f53d15feSStephan UphoffThe 209f53d15feSStephan Uphoff.Fa rm 210f53d15feSStephan Uphofflock must be unlocked. 211*d576deedSPawel Jakub Dawidek.It Fn rm_wowned "const struct rmlock *rm" 212433ea89aSRobert WatsonThis function returns a non-zero value if the current thread owns an 213433ea89aSRobert Watsonexclusive lock on 214433ea89aSRobert Watson.Fa rm . 215f53d15feSStephan Uphoff.El 216f53d15feSStephan Uphoff.Sh SEE ALSO 217f53d15feSStephan Uphoff.Xr locking 9 , 218f53d15feSStephan Uphoff.Xr mutex 9 , 219f53d15feSStephan Uphoff.Xr panic 9 , 220f53d15feSStephan Uphoff.Xr rwlock 9 , 221f53d15feSStephan Uphoff.Xr sema 9 , 222f53d15feSStephan Uphoff.Xr sx 9 223f53d15feSStephan Uphoff.Sh HISTORY 224f53d15feSStephan UphoffThese 225f53d15feSStephan Uphofffunctions appeared in 226f53d15feSStephan Uphoff.Fx 7.0 . 227f53d15feSStephan Uphoff.Sh AUTHORS 228f53d15feSStephan Uphoff.An -nosplit 229f53d15feSStephan UphoffThe 230f53d15feSStephan Uphoff.Nm 231f53d15feSStephan Uphofffacility was written by 232f53d15feSStephan Uphoff.An "Stephan Uphoff" . 233f53d15feSStephan UphoffThis manual page was written by 234f53d15feSStephan Uphoff.An "Gleb Smirnoff" 235989cbe40SHiten Pandyafor rwlock and modified to reflect rmlock by 236f53d15feSStephan Uphoff.An "Stephan Uphoff" . 237f53d15feSStephan Uphoff.Sh BUGS 238989cbe40SHiten PandyaThe 239989cbe40SHiten Pandya.Nm 240989cbe40SHiten Pandyaimplementation is currently not optimized for single processor systems. 241989cbe40SHiten Pandya.Pp 24236058c09SMax Laier.Fn rm_try_rlock 24336058c09SMax Laiercan fail transiently even when there is no writer, while another reader 24436058c09SMax Laierupdates the state on the local CPU. 24536058c09SMax Laier.Pp 246989cbe40SHiten PandyaThe 247989cbe40SHiten Pandya.Nm 248c6d7cf7bSChristian Bruefferimplementation uses a single per CPU list shared by all 249989cbe40SHiten Pandyarmlocks in the system. 250c6d7cf7bSChristian BruefferIf rmlocks become popular, hashing to multiple per CPU queues may 251989cbe40SHiten Pandyabe needed to speed up the writer lock process. 252989cbe40SHiten Pandya.Pp 253989cbe40SHiten PandyaThe 254989cbe40SHiten Pandya.Nm 255989cbe40SHiten Pandyacan currently not be used as a lock argument for condition variable 256989cbe40SHiten Pandyawait functions. 257