xref: /freebsd/share/man/man9/rmlock.9 (revision 755230eb9f87f66fd4bd20862e73bad612e36199)
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*755230ebSMark Johnston.Dd November 11, 2017
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 ,
43cd32bd7aSJohn Baldwin.Nm rm_sleep ,
44cd32bd7aSJohn Baldwin.Nm rm_assert ,
45*755230ebSMark Johnston.Nm RM_SYSINIT ,
46*755230ebSMark Johnston.Nm RM_SYSINIT_FLAGS
478403b193SJohn Baldwin.Nd kernel reader/writer lock optimized for read-mostly access patterns
48f53d15feSStephan Uphoff.Sh SYNOPSIS
49f53d15feSStephan Uphoff.In sys/param.h
50f53d15feSStephan Uphoff.In sys/lock.h
51f53d15feSStephan Uphoff.In sys/rmlock.h
52f53d15feSStephan Uphoff.Ft void
531a109c1cSRobert Watson.Fn rm_init "struct rmlock *rm" "const char *name"
541a109c1cSRobert Watson.Ft void
551a109c1cSRobert Watson.Fn rm_init_flags "struct rmlock *rm" "const char *name" "int opts"
56f53d15feSStephan Uphoff.Ft void
57f53d15feSStephan Uphoff.Fn rm_destroy "struct rmlock *rm"
58f53d15feSStephan Uphoff.Ft void
59f53d15feSStephan Uphoff.Fn rm_rlock "struct rmlock *rm"  "struct rm_priotracker* tracker"
6036058c09SMax Laier.Ft int
6136058c09SMax Laier.Fn rm_try_rlock "struct rmlock *rm"  "struct rm_priotracker* tracker"
62f53d15feSStephan Uphoff.Ft void
63f53d15feSStephan Uphoff.Fn rm_wlock "struct rmlock *rm"
64f53d15feSStephan Uphoff.Ft void
65f53d15feSStephan Uphoff.Fn rm_runlock "struct rmlock *rm" "struct rm_priotracker* tracker"
66f53d15feSStephan Uphoff.Ft void
67f53d15feSStephan Uphoff.Fn rm_wunlock "struct rmlock *rm"
68433ea89aSRobert Watson.Ft int
69d576deedSPawel Jakub Dawidek.Fn rm_wowned "const struct rmlock *rm"
70cd32bd7aSJohn Baldwin.Ft int
71cd32bd7aSJohn Baldwin.Fn rm_sleep "void *wchan" "struct rmlock *rm" "int priority" "const char *wmesg" "int timo"
72cd32bd7aSJohn Baldwin.Pp
73cd32bd7aSJohn Baldwin.Cd "options INVARIANTS"
74cd32bd7aSJohn Baldwin.Cd "options INVARIANT_SUPPORT"
75cd32bd7aSJohn Baldwin.Ft void
76cd32bd7aSJohn Baldwin.Fn rm_assert "struct rmlock *rm" "int what"
77f53d15feSStephan Uphoff.In sys/kernel.h
78*755230ebSMark Johnston.Fn RM_SYSINIT "name" "struct rmlock *rm" "const char *desc"
79*755230ebSMark Johnston.Fn RM_SYSINIT_FLAGS "name" "struct rmlock *rm" "const char *desc" "int flags"
80f53d15feSStephan Uphoff.Sh DESCRIPTION
818403b193SJohn BaldwinRead-mostly locks allow shared access to protected data by multiple threads,
82f53d15feSStephan Uphoffor exclusive access by a single thread.
83f53d15feSStephan UphoffThe threads with shared access are known as
84f53d15feSStephan Uphoff.Em readers
85f53d15feSStephan Uphoffsince they only read the protected data.
86f53d15feSStephan UphoffA thread with exclusive access is known as a
87f53d15feSStephan Uphoff.Em writer
88f53d15feSStephan Uphoffsince it can modify protected data.
89f53d15feSStephan Uphoff.Pp
908403b193SJohn BaldwinRead-mostly locks are designed to be efficient for locks almost exclusively
91989cbe40SHiten Pandyaused as reader locks and as such should be used for protecting data that
92989cbe40SHiten Pandyararely changes.
938403b193SJohn BaldwinAcquiring an exclusive lock after the lock has been locked for shared access
94989cbe40SHiten Pandyais an expensive operation.
95f53d15feSStephan Uphoff.Pp
968403b193SJohn BaldwinNormal read-mostly locks are similar to
978403b193SJohn Baldwin.Xr rwlock 9
988403b193SJohn Baldwinlocks and follow the same lock ordering rules as
998403b193SJohn Baldwin.Xr rwlock 9
1008403b193SJohn Baldwinlocks.
1018403b193SJohn BaldwinRead-mostly locks have full priority propagation like mutexes.
102f53d15feSStephan UphoffUnlike
1038403b193SJohn Baldwin.Xr rwlock 9 ,
1048403b193SJohn Baldwinread-mostly locks propagate priority to both readers and writers.
1058403b193SJohn BaldwinThis is implemented via the
106989cbe40SHiten Pandya.Va rm_priotracker
1078403b193SJohn Baldwinstructure argument supplied to
108989cbe40SHiten Pandya.Fn rm_rlock
109989cbe40SHiten Pandyaand
1108403b193SJohn Baldwin.Fn rm_runlock .
1118403b193SJohn BaldwinReaders can recurse if the lock is initialized with the
1128403b193SJohn Baldwin.Dv RM_RECURSE
1138403b193SJohn Baldwinoption;
1148403b193SJohn Baldwinhowever, writers are never allowed to recurse.
1158403b193SJohn Baldwin.Pp
1168403b193SJohn BaldwinSleepable read-mostly locks are created by passing
1178403b193SJohn Baldwin.Dv RM_SLEEPABLE
1188403b193SJohn Baldwinto
1198403b193SJohn Baldwin.Fn rm_init_flags .
1208403b193SJohn BaldwinUnlike normal read-mostly locks,
1218403b193SJohn Baldwinsleepable read-mostly locks follow the same lock ordering rules as
1228403b193SJohn Baldwin.Xr sx 9
1238403b193SJohn Baldwinlocks.
1248403b193SJohn BaldwinSleepable read-mostly locks do not propagate priority to writers,
1258403b193SJohn Baldwinbut they do propagate priority to readers.
1268403b193SJohn BaldwinWriters are permitted to sleep while holding a read-mostly lock,
1278403b193SJohn Baldwinbut readers are not.
1288403b193SJohn BaldwinUnlike other sleepable locks such as
1298403b193SJohn Baldwin.Xr sx 9
1308403b193SJohn Baldwinlocks,
1318403b193SJohn Baldwinreaders must use try operations on other sleepable locks to avoid sleeping.
132f53d15feSStephan Uphoff.Ss Macros and Functions
133f53d15feSStephan Uphoff.Bl -tag -width indent
1341a109c1cSRobert Watson.It Fn rm_init "struct rmlock *rm" "const char *name"
1358403b193SJohn BaldwinInitialize the read-mostly lock
1368403b193SJohn Baldwin.Fa rm .
1378403b193SJohn BaldwinThe
1388403b193SJohn Baldwin.Fa name
1398403b193SJohn Baldwindescription is used solely for debugging purposes.
140f53d15feSStephan UphoffThis function must be called before any other operations
141f53d15feSStephan Uphoffon the lock.
1421a109c1cSRobert Watson.It Fn rm_init_flags "struct rmlock *rm" "const char *name" "int opts"
1438403b193SJohn BaldwinSimilar to
1448403b193SJohn Baldwin.Fn rm_init ,
1458403b193SJohn Baldwininitialize the read-mostly lock
1468403b193SJohn Baldwin.Fa rm
1478403b193SJohn Baldwinwith a set of optional flags.
1488403b193SJohn BaldwinThe
1491a109c1cSRobert Watson.Fa opts
1508403b193SJohn Baldwinarguments contains one or more of the following flags:
1511a109c1cSRobert Watson.Bl -tag -width ".Dv RM_NOWITNESS"
1521a109c1cSRobert Watson.It Dv RM_NOWITNESS
1531a109c1cSRobert WatsonInstruct
1541a109c1cSRobert Watson.Xr witness 4
1551a109c1cSRobert Watsonto ignore this lock.
1561a109c1cSRobert Watson.It Dv RM_RECURSE
1578403b193SJohn BaldwinAllow threads to recursively acquire shared locks for
1581a109c1cSRobert Watson.Fa rm .
15936058c09SMax Laier.It Dv RM_SLEEPABLE
1608403b193SJohn BaldwinCreate a sleepable read-mostly lock.
161fd07ddcfSDmitry Chagin.It Dv RM_NEW
162fd07ddcfSDmitry ChaginIf the kernel has been compiled with
163fd07ddcfSDmitry Chagin.Cd "option INVARIANTS" ,
164fd07ddcfSDmitry Chagin.Fn rm_init_flags
165fd07ddcfSDmitry Chaginwill assert that the
166fd07ddcfSDmitry Chagin.Fa rm
167fd07ddcfSDmitry Chaginhas not been initialized multiple times without intervening calls to
168fd07ddcfSDmitry Chagin.Fn rm_destroy
169fd07ddcfSDmitry Chaginunless this option is specified.
1701a109c1cSRobert Watson.El
171f53d15feSStephan Uphoff.It Fn rm_rlock "struct rmlock *rm" "struct rm_priotracker* tracker"
172f53d15feSStephan UphoffLock
173f53d15feSStephan Uphoff.Fa rm
1748403b193SJohn Baldwinas a reader using
175f53d15feSStephan Uphoff.Fa tracker
176f53d15feSStephan Uphoffto track read owners of a lock for priority propagation.
177989cbe40SHiten PandyaThis data structure is only used internally by
178989cbe40SHiten Pandya.Nm
179c6d7cf7bSChristian Bruefferand must persist until
180c6d7cf7bSChristian Brueffer.Fn rm_runlock
181c6d7cf7bSChristian Bruefferhas been called.
182989cbe40SHiten PandyaThis data structure can be allocated on the stack since
1838403b193SJohn Baldwinreaders cannot sleep.
184f53d15feSStephan UphoffIf any thread holds this lock exclusively, the current thread blocks,
185f53d15feSStephan Uphoffand its priority is propagated to the exclusive holder.
186989cbe40SHiten PandyaIf the lock was initialized with the
1878403b193SJohn Baldwin.Dv RM_RECURSE
188989cbe40SHiten Pandyaoption the
189f53d15feSStephan Uphoff.Fn rm_rlock
1908403b193SJohn Baldwinfunction can be called when the current thread has already acquired reader
191f53d15feSStephan Uphoffaccess on
192f53d15feSStephan Uphoff.Fa rm .
19336058c09SMax Laier.It Fn rm_try_rlock "struct rmlock *rm" "struct rm_priotracker* tracker"
19436058c09SMax LaierTry to lock
19536058c09SMax Laier.Fa rm
19636058c09SMax Laieras a reader.
19736058c09SMax Laier.Fn rm_try_rlock
19836058c09SMax Laierwill return 0 if the lock cannot be acquired immediately;
1998403b193SJohn Baldwinotherwise,
2008403b193SJohn Baldwinthe lock will be acquired and a non-zero value will be returned.
20136058c09SMax LaierNote that
20236058c09SMax Laier.Fn rm_try_rlock
20336058c09SMax Laiermay fail even while the lock is not currently held by a writer.
2048403b193SJohn BaldwinIf the lock was initialized with the
2058403b193SJohn Baldwin.Dv RM_RECURSE
2068403b193SJohn Baldwinoption,
2078403b193SJohn Baldwin.Fn rm_try_rlock
2088403b193SJohn Baldwinwill succeed if the current thread has already acquired reader access.
209f53d15feSStephan Uphoff.It Fn rm_wlock "struct rmlock *rm"
210f53d15feSStephan UphoffLock
211f53d15feSStephan Uphoff.Fa rm
212f53d15feSStephan Uphoffas a writer.
213f53d15feSStephan UphoffIf there are any shared owners of the lock, the current thread blocks.
214f53d15feSStephan UphoffThe
215f53d15feSStephan Uphoff.Fn rm_wlock
216f53d15feSStephan Uphofffunction cannot be called recursively.
217f53d15feSStephan Uphoff.It Fn rm_runlock "struct rmlock *rm" "struct rm_priotracker* tracker"
218f53d15feSStephan UphoffThis function releases a shared lock previously acquired by
219f53d15feSStephan Uphoff.Fn rm_rlock .
220f53d15feSStephan UphoffThe
221f53d15feSStephan Uphoff.Fa tracker
222f53d15feSStephan Uphoffargument must match the
223f53d15feSStephan Uphoff.Fa tracker
224f53d15feSStephan Uphoffargument used for acquiring the shared lock
225f53d15feSStephan Uphoff.It Fn rm_wunlock "struct rmlock *rm"
226f53d15feSStephan UphoffThis function releases an exclusive lock previously acquired by
227f53d15feSStephan Uphoff.Fn rm_wlock .
228f53d15feSStephan Uphoff.It Fn rm_destroy "struct rmlock *rm"
229f53d15feSStephan UphoffThis functions destroys a lock previously initialized with
230f53d15feSStephan Uphoff.Fn rm_init .
231f53d15feSStephan UphoffThe
232f53d15feSStephan Uphoff.Fa rm
233f53d15feSStephan Uphofflock must be unlocked.
234d576deedSPawel Jakub Dawidek.It Fn rm_wowned "const struct rmlock *rm"
235433ea89aSRobert WatsonThis function returns a non-zero value if the current thread owns an
236433ea89aSRobert Watsonexclusive lock on
237433ea89aSRobert Watson.Fa rm .
238cd32bd7aSJohn Baldwin.It Fn rm_sleep "void *wchan" "struct rmlock *rm" "int priority" "const char *wmesg" "int timo"
239cd32bd7aSJohn BaldwinThis function atomically releases
240cd32bd7aSJohn Baldwin.Fa rm
241cd32bd7aSJohn Baldwinwhile waiting for an event.
242cd32bd7aSJohn BaldwinThe
243cd32bd7aSJohn Baldwin.Fa rm
244cd32bd7aSJohn Baldwinlock must be exclusively locked.
245cd32bd7aSJohn BaldwinFor more details on the parameters to this function,
246cd32bd7aSJohn Baldwinsee
247cd32bd7aSJohn Baldwin.Xr sleep 9 .
248cd32bd7aSJohn Baldwin.It Fn rm_assert "struct rmlock *rm" "int what"
249cd32bd7aSJohn BaldwinThis function asserts that the
250cd32bd7aSJohn Baldwin.Fa rm
251cd32bd7aSJohn Baldwinlock is in the state specified by
252cd32bd7aSJohn Baldwin.Fa what .
253cd32bd7aSJohn BaldwinIf the assertions are not true and the kernel is compiled with
254cd32bd7aSJohn Baldwin.Cd "options INVARIANTS"
255cd32bd7aSJohn Baldwinand
256cd32bd7aSJohn Baldwin.Cd "options INVARIANT_SUPPORT" ,
257cd32bd7aSJohn Baldwinthe kernel will panic.
258cd32bd7aSJohn BaldwinCurrently the following base assertions are supported:
259cd32bd7aSJohn Baldwin.Bl -tag -width ".Dv RA_UNLOCKED"
260cd32bd7aSJohn Baldwin.It Dv RA_LOCKED
261cd32bd7aSJohn BaldwinAssert that current thread holds either a shared or exclusive lock
262cd32bd7aSJohn Baldwinof
263cd32bd7aSJohn Baldwin.Fa rm .
264cd32bd7aSJohn Baldwin.It Dv RA_RLOCKED
265cd32bd7aSJohn BaldwinAssert that current thread holds a shared lock of
266cd32bd7aSJohn Baldwin.Fa rm .
267cd32bd7aSJohn Baldwin.It Dv RA_WLOCKED
268cd32bd7aSJohn BaldwinAssert that current thread holds an exclusive lock of
269cd32bd7aSJohn Baldwin.Fa rm .
270cd32bd7aSJohn Baldwin.It Dv RA_UNLOCKED
271cd32bd7aSJohn BaldwinAssert that current thread holds neither a shared nor exclusive lock of
272cd32bd7aSJohn Baldwin.Fa rm .
273cd32bd7aSJohn Baldwin.El
274cd32bd7aSJohn Baldwin.Pp
275cd32bd7aSJohn BaldwinIn addition, one of the following optional flags may be specified with
276cd32bd7aSJohn Baldwin.Dv RA_LOCKED ,
277cd32bd7aSJohn Baldwin.Dv RA_RLOCKED ,
278cd32bd7aSJohn Baldwinor
279cd32bd7aSJohn Baldwin.Dv RA_WLOCKED :
280cd32bd7aSJohn Baldwin.Bl -tag -width ".Dv RA_NOTRECURSED"
281cd32bd7aSJohn Baldwin.It Dv RA_RECURSED
282cd32bd7aSJohn BaldwinAssert that the current thread holds a recursive lock of
283cd32bd7aSJohn Baldwin.Fa rm .
284cd32bd7aSJohn Baldwin.It Dv RA_NOTRECURSED
285cd32bd7aSJohn BaldwinAssert that the current thread does not hold a recursive lock of
286cd32bd7aSJohn Baldwin.Fa rm .
287cd32bd7aSJohn Baldwin.El
288f53d15feSStephan Uphoff.El
289f53d15feSStephan Uphoff.Sh SEE ALSO
290f53d15feSStephan Uphoff.Xr locking 9 ,
291f53d15feSStephan Uphoff.Xr mutex 9 ,
292f53d15feSStephan Uphoff.Xr panic 9 ,
293f53d15feSStephan Uphoff.Xr rwlock 9 ,
294f53d15feSStephan Uphoff.Xr sema 9 ,
2959972df7dSDmitry Chagin.Xr sleep 9 ,
296f53d15feSStephan Uphoff.Xr sx 9
297f53d15feSStephan Uphoff.Sh HISTORY
298f53d15feSStephan UphoffThese
299f53d15feSStephan Uphofffunctions appeared in
300f53d15feSStephan Uphoff.Fx 7.0 .
301f53d15feSStephan Uphoff.Sh AUTHORS
302f53d15feSStephan Uphoff.An -nosplit
303f53d15feSStephan UphoffThe
304f53d15feSStephan Uphoff.Nm
305f53d15feSStephan Uphofffacility was written by
306f53d15feSStephan Uphoff.An "Stephan Uphoff" .
307f53d15feSStephan UphoffThis manual page was written by
308f53d15feSStephan Uphoff.An "Gleb Smirnoff"
309989cbe40SHiten Pandyafor rwlock and modified to reflect rmlock by
310f53d15feSStephan Uphoff.An "Stephan Uphoff" .
311f53d15feSStephan Uphoff.Sh BUGS
312989cbe40SHiten PandyaThe
313989cbe40SHiten Pandya.Nm
314989cbe40SHiten Pandyaimplementation is currently not optimized for single processor systems.
315989cbe40SHiten Pandya.Pp
31636058c09SMax Laier.Fn rm_try_rlock
31736058c09SMax Laiercan fail transiently even when there is no writer, while another reader
31836058c09SMax Laierupdates the state on the local CPU.
31936058c09SMax Laier.Pp
320989cbe40SHiten PandyaThe
321989cbe40SHiten Pandya.Nm
322c6d7cf7bSChristian Bruefferimplementation uses a single per CPU list shared by all
323989cbe40SHiten Pandyarmlocks in the system.
324c6d7cf7bSChristian BruefferIf rmlocks become popular, hashing to multiple per CPU queues may
325989cbe40SHiten Pandyabe needed to speed up the writer lock process.
326