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*8403b193SJohn Baldwin.Dd June 8, 2012 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 44*8403b193SJohn Baldwin.Nd kernel reader/writer lock optimized for read-mostly 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 66d576deedSPawel 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 70*8403b193SJohn BaldwinRead-mostly 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 79*8403b193SJohn BaldwinRead-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. 82*8403b193SJohn BaldwinAcquiring an exclusive lock after the lock has been locked for shared access 83989cbe40SHiten Pandyais an expensive operation. 84f53d15feSStephan Uphoff.Pp 85*8403b193SJohn BaldwinNormal read-mostly locks are similar to 86*8403b193SJohn Baldwin.Xr rwlock 9 87*8403b193SJohn Baldwinlocks and follow the same lock ordering rules as 88*8403b193SJohn Baldwin.Xr rwlock 9 89*8403b193SJohn Baldwinlocks. 90*8403b193SJohn BaldwinRead-mostly locks have full priority propagation like mutexes. 91f53d15feSStephan UphoffUnlike 92*8403b193SJohn Baldwin.Xr rwlock 9 , 93*8403b193SJohn Baldwinread-mostly locks propagate priority to both readers and writers. 94*8403b193SJohn BaldwinThis is implemented via the 95989cbe40SHiten Pandya.Va rm_priotracker 96*8403b193SJohn Baldwinstructure argument supplied to 97989cbe40SHiten Pandya.Fn rm_rlock 98989cbe40SHiten Pandyaand 99*8403b193SJohn Baldwin.Fn rm_runlock . 100*8403b193SJohn BaldwinReaders can recurse if the lock is initialized with the 101*8403b193SJohn Baldwin.Dv RM_RECURSE 102*8403b193SJohn Baldwinoption; 103*8403b193SJohn Baldwinhowever, writers are never allowed to recurse. 104*8403b193SJohn Baldwin.Pp 105*8403b193SJohn BaldwinSleepable read-mostly locks are created by passing 106*8403b193SJohn Baldwin.Dv RM_SLEEPABLE 107*8403b193SJohn Baldwinto 108*8403b193SJohn Baldwin.Fn rm_init_flags . 109*8403b193SJohn BaldwinUnlike normal read-mostly locks, 110*8403b193SJohn Baldwinsleepable read-mostly locks follow the same lock ordering rules as 111*8403b193SJohn Baldwin.Xr sx 9 112*8403b193SJohn Baldwinlocks. 113*8403b193SJohn BaldwinSleepable read-mostly locks do not propagate priority to writers, 114*8403b193SJohn Baldwinbut they do propagate priority to readers. 115*8403b193SJohn BaldwinWriters are permitted to sleep while holding a read-mostly lock, 116*8403b193SJohn Baldwinbut readers are not. 117*8403b193SJohn BaldwinUnlike other sleepable locks such as 118*8403b193SJohn Baldwin.Xr sx 9 119*8403b193SJohn Baldwinlocks, 120*8403b193SJohn Baldwinreaders must use try operations on other sleepable locks to avoid sleeping. 121f53d15feSStephan Uphoff.Ss Macros and Functions 122f53d15feSStephan Uphoff.Bl -tag -width indent 1231a109c1cSRobert Watson.It Fn rm_init "struct rmlock *rm" "const char *name" 124*8403b193SJohn BaldwinInitialize the read-mostly lock 125*8403b193SJohn Baldwin.Fa rm . 126*8403b193SJohn BaldwinThe 127*8403b193SJohn Baldwin.Fa name 128*8403b193SJohn Baldwindescription is used solely for debugging purposes. 129f53d15feSStephan UphoffThis function must be called before any other operations 130f53d15feSStephan Uphoffon the lock. 1311a109c1cSRobert Watson.It Fn rm_init_flags "struct rmlock *rm" "const char *name" "int opts" 132*8403b193SJohn BaldwinSimilar to 133*8403b193SJohn Baldwin.Fn rm_init , 134*8403b193SJohn Baldwininitialize the read-mostly lock 135*8403b193SJohn Baldwin.Fa rm 136*8403b193SJohn Baldwinwith a set of optional flags. 137*8403b193SJohn BaldwinThe 1381a109c1cSRobert Watson.Fa opts 139*8403b193SJohn Baldwinarguments contains one or more of the following flags: 1401a109c1cSRobert Watson.Bl -tag -width ".Dv RM_NOWITNESS" 1411a109c1cSRobert Watson.It Dv RM_NOWITNESS 1421a109c1cSRobert WatsonInstruct 1431a109c1cSRobert Watson.Xr witness 4 1441a109c1cSRobert Watsonto ignore this lock. 1451a109c1cSRobert Watson.It Dv RM_RECURSE 146*8403b193SJohn BaldwinAllow threads to recursively acquire shared locks for 1471a109c1cSRobert Watson.Fa rm . 14836058c09SMax Laier.It Dv RM_SLEEPABLE 149*8403b193SJohn BaldwinCreate a sleepable read-mostly lock. 1501a109c1cSRobert Watson.El 151f53d15feSStephan Uphoff.It Fn rm_rlock "struct rmlock *rm" "struct rm_priotracker* tracker" 152f53d15feSStephan UphoffLock 153f53d15feSStephan Uphoff.Fa rm 154*8403b193SJohn Baldwinas a reader using 155f53d15feSStephan Uphoff.Fa tracker 156f53d15feSStephan Uphoffto track read owners of a lock for priority propagation. 157989cbe40SHiten PandyaThis data structure is only used internally by 158989cbe40SHiten Pandya.Nm 159c6d7cf7bSChristian Bruefferand must persist until 160c6d7cf7bSChristian Brueffer.Fn rm_runlock 161c6d7cf7bSChristian Bruefferhas been called. 162989cbe40SHiten PandyaThis data structure can be allocated on the stack since 163*8403b193SJohn Baldwinreaders cannot sleep. 164f53d15feSStephan UphoffIf any thread holds this lock exclusively, the current thread blocks, 165f53d15feSStephan Uphoffand its priority is propagated to the exclusive holder. 166989cbe40SHiten PandyaIf the lock was initialized with the 167*8403b193SJohn Baldwin.Dv RM_RECURSE 168989cbe40SHiten Pandyaoption the 169f53d15feSStephan Uphoff.Fn rm_rlock 170*8403b193SJohn Baldwinfunction can be called when the current thread has already acquired reader 171f53d15feSStephan Uphoffaccess on 172f53d15feSStephan Uphoff.Fa rm . 17336058c09SMax Laier.It Fn rm_try_rlock "struct rmlock *rm" "struct rm_priotracker* tracker" 17436058c09SMax LaierTry to lock 17536058c09SMax Laier.Fa rm 17636058c09SMax Laieras a reader. 17736058c09SMax Laier.Fn rm_try_rlock 17836058c09SMax Laierwill return 0 if the lock cannot be acquired immediately; 179*8403b193SJohn Baldwinotherwise, 180*8403b193SJohn Baldwinthe lock will be acquired and a non-zero value will be returned. 18136058c09SMax LaierNote that 18236058c09SMax Laier.Fn rm_try_rlock 18336058c09SMax Laiermay fail even while the lock is not currently held by a writer. 184*8403b193SJohn BaldwinIf the lock was initialized with the 185*8403b193SJohn Baldwin.Dv RM_RECURSE 186*8403b193SJohn Baldwinoption, 187*8403b193SJohn Baldwin.Fn rm_try_rlock 188*8403b193SJohn Baldwinwill succeed if the current thread has already acquired reader access. 189f53d15feSStephan Uphoff.It Fn rm_wlock "struct rmlock *rm" 190f53d15feSStephan UphoffLock 191f53d15feSStephan Uphoff.Fa rm 192f53d15feSStephan Uphoffas a writer. 193f53d15feSStephan UphoffIf there are any shared owners of the lock, the current thread blocks. 194f53d15feSStephan UphoffThe 195f53d15feSStephan Uphoff.Fn rm_wlock 196f53d15feSStephan Uphofffunction cannot be called recursively. 197f53d15feSStephan Uphoff.It Fn rm_runlock "struct rmlock *rm" "struct rm_priotracker* tracker" 198f53d15feSStephan UphoffThis function releases a shared lock previously acquired by 199f53d15feSStephan Uphoff.Fn rm_rlock . 200f53d15feSStephan UphoffThe 201f53d15feSStephan Uphoff.Fa tracker 202f53d15feSStephan Uphoffargument must match the 203f53d15feSStephan Uphoff.Fa tracker 204f53d15feSStephan Uphoffargument used for acquiring the shared lock 205f53d15feSStephan Uphoff.It Fn rm_wunlock "struct rmlock *rm" 206f53d15feSStephan UphoffThis function releases an exclusive lock previously acquired by 207f53d15feSStephan Uphoff.Fn rm_wlock . 208f53d15feSStephan Uphoff.It Fn rm_destroy "struct rmlock *rm" 209f53d15feSStephan UphoffThis functions destroys a lock previously initialized with 210f53d15feSStephan Uphoff.Fn rm_init . 211f53d15feSStephan UphoffThe 212f53d15feSStephan Uphoff.Fa rm 213f53d15feSStephan Uphofflock must be unlocked. 214d576deedSPawel Jakub Dawidek.It Fn rm_wowned "const struct rmlock *rm" 215433ea89aSRobert WatsonThis function returns a non-zero value if the current thread owns an 216433ea89aSRobert Watsonexclusive lock on 217433ea89aSRobert Watson.Fa rm . 218f53d15feSStephan Uphoff.El 219f53d15feSStephan Uphoff.Sh SEE ALSO 220f53d15feSStephan Uphoff.Xr locking 9 , 221f53d15feSStephan Uphoff.Xr mutex 9 , 222f53d15feSStephan Uphoff.Xr panic 9 , 223f53d15feSStephan Uphoff.Xr rwlock 9 , 224f53d15feSStephan Uphoff.Xr sema 9 , 225f53d15feSStephan Uphoff.Xr sx 9 226f53d15feSStephan Uphoff.Sh HISTORY 227f53d15feSStephan UphoffThese 228f53d15feSStephan Uphofffunctions appeared in 229f53d15feSStephan Uphoff.Fx 7.0 . 230f53d15feSStephan Uphoff.Sh AUTHORS 231f53d15feSStephan Uphoff.An -nosplit 232f53d15feSStephan UphoffThe 233f53d15feSStephan Uphoff.Nm 234f53d15feSStephan Uphofffacility was written by 235f53d15feSStephan Uphoff.An "Stephan Uphoff" . 236f53d15feSStephan UphoffThis manual page was written by 237f53d15feSStephan Uphoff.An "Gleb Smirnoff" 238989cbe40SHiten Pandyafor rwlock and modified to reflect rmlock by 239f53d15feSStephan Uphoff.An "Stephan Uphoff" . 240f53d15feSStephan Uphoff.Sh BUGS 241989cbe40SHiten PandyaThe 242989cbe40SHiten Pandya.Nm 243989cbe40SHiten Pandyaimplementation is currently not optimized for single processor systems. 244989cbe40SHiten Pandya.Pp 24536058c09SMax Laier.Fn rm_try_rlock 24636058c09SMax Laiercan fail transiently even when there is no writer, while another reader 24736058c09SMax Laierupdates the state on the local CPU. 24836058c09SMax Laier.Pp 249989cbe40SHiten PandyaThe 250989cbe40SHiten Pandya.Nm 251c6d7cf7bSChristian Bruefferimplementation uses a single per CPU list shared by all 252989cbe40SHiten Pandyarmlocks in the system. 253c6d7cf7bSChristian BruefferIf rmlocks become popular, hashing to multiple per CPU queues may 254989cbe40SHiten Pandyabe needed to speed up the writer lock process. 255989cbe40SHiten Pandya.Pp 256989cbe40SHiten PandyaThe 257989cbe40SHiten Pandya.Nm 258989cbe40SHiten Pandyacan currently not be used as a lock argument for condition variable 259989cbe40SHiten Pandyawait functions. 260