Copyright (c) 2007 Stephan Uphoff <ups@FreeBSD.org> Copyright (c) 2006 Gleb Smirnoff <glebius@FreeBSD.org> All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of c...
NAMErmlock rm_init rm_init_flags rm_destroy rm_rlock rm_try_rlock rm_wlock rm_runlock rm_wunlock rm_wowned rm_sleep rm_assert RM_SYSINIT - kernel reader/writer lock optimized for read-mostly access patterns
SYNOPSISIn sys/param.h In sys/lock.h In sys/rmlock.h Ft void Fn rm_init struct rmlock *rm const char *name Ft void Fn rm_init_flags struct rmlock *rm const char *name int opts Ft void Fn rm_destroy struct rmlock *rm Ft void Fn rm_rlock struct rmlock *rm struct rm_priotracker* tracker Ft int Fn rm_try_rlock struct rmlock *rm struct rm_priotracker* tracker Ft void Fn rm_wlock struct rmlock *rm Ft void Fn rm_runlock struct rmlock *rm struct rm_priotracker* tracker Ft void Fn rm_wunlock struct rmlock *rm Ft int Fn rm_wowned const struct rmlock *rm Ft int Fn rm_sleep void *wchan struct rmlock *rm int priority const char *wmesg int timo
options INVARIANTS options INVARIANT_SUPPORT Ft void Fn rm_assert struct rmlock *rm int what In sys/kernel.h Fn RM_SYSINIT name struct rmlock *rm const char *desc int opts
DESCRIPTIONRead-mostly locks allow shared access to protected data by multiple threads, or exclusive access by a single thread. The threads with shared access are known as readers since they only read the protected data. A thread with exclusive access is known as a writer since it can modify protected data.
Read-mostly locks are designed to be efficient for locks almost exclusively used as reader locks and as such should be used for protecting data that rarely changes. Acquiring an exclusive lock after the lock has been locked for shared access is an expensive operation.
Normal read-mostly locks are similar to rwlock(9) locks and follow the same lock ordering rules as rwlock(9) locks. Read-mostly locks have full priority propagation like mutexes. Unlike rwlock(9), read-mostly locks propagate priority to both readers and writers. This is implemented via the rm_priotracker structure argument supplied to Fn rm_rlock and Fn rm_runlock . Readers can recurse if the lock is initialized with the RM_RECURSE option; however, writers are never allowed to recurse.
Sleepable read-mostly locks are created by passing RM_SLEEPABLE to Fn rm_init_flags . Unlike normal read-mostly locks, sleepable read-mostly locks follow the same lock ordering rules as sx(9) locks. Sleepable read-mostly locks do not propagate priority to writers, but they do propagate priority to readers. Writers are permitted to sleep while holding a read-mostly lock, but readers are not. Unlike other sleepable locks such as sx(9) locks, readers must use try operations on other sleepable locks to avoid sleeping.
Macros and Functions
- Fn rm_init struct rmlock *rm const char *name
- Initialize the read-mostly lock Fa rm . The Fa name description is used solely for debugging purposes. This function must be called before any other operations on the lock.
- Fn rm_init_flags struct rmlock *rm const char *name int opts
Fn rm_init ,
initialize the read-mostly lock
with a set of optional flags.
arguments contains one or more of the following flags:
- Instruct witness(4) to ignore this lock.
- Allow threads to recursively acquire shared locks for Fa rm .
- Create a sleepable read-mostly lock.
- If the kernel has been compiled with option INVARIANTS Fn rm_init_flags will assert that the Fa rm has not been initialized multiple times without intervening calls to Fn rm_destroy unless this option is specified.
- Fn rm_rlock struct rmlock *rm struct rm_priotracker* tracker
- Lock Fa rm as a reader using Fa tracker to track read owners of a lock for priority propagation. This data structure is only used internally by sysctl Cm net.inet.tcp.syncookies and must persist until Fn rm_runlock has been called. This data structure can be allocated on the stack since readers cannot sleep. If any thread holds this lock exclusively, the current thread blocks, and its priority is propagated to the exclusive holder. If the lock was initialized with the RM_RECURSE option the Fn rm_rlock function can be called when the current thread has already acquired reader access on Fa rm .
- Fn rm_try_rlock struct rmlock *rm struct rm_priotracker* tracker
- Try to lock Fa rm as a reader. Fn rm_try_rlock will return 0 if the lock cannot be acquired immediately; otherwise, the lock will be acquired and a non-zero value will be returned. Note that Fn rm_try_rlock may fail even while the lock is not currently held by a writer. If the lock was initialized with the RM_RECURSE option, Fn rm_try_rlock will succeed if the current thread has already acquired reader access.
- Fn rm_wlock struct rmlock *rm
- Lock Fa rm as a writer. If there are any shared owners of the lock, the current thread blocks. The Fn rm_wlock function cannot be called recursively.
- Fn rm_runlock struct rmlock *rm struct rm_priotracker* tracker
- This function releases a shared lock previously acquired by Fn rm_rlock . The Fa tracker argument must match the Fa tracker argument used for acquiring the shared lock
- Fn rm_wunlock struct rmlock *rm
- This function releases an exclusive lock previously acquired by Fn rm_wlock .
- Fn rm_destroy struct rmlock *rm
- This functions destroys a lock previously initialized with Fn rm_init . The Fa rm lock must be unlocked.
- Fn rm_wowned const struct rmlock *rm
- This function returns a non-zero value if the current thread owns an exclusive lock on Fa rm .
- Fn rm_sleep void *wchan struct rmlock *rm int priority const char *wmesg int timo
- This function atomically releases Fa rm while waiting for an event. The Fa rm lock must be exclusively locked. For more details on the parameters to this function, see sleep(9).
- Fn rm_assert struct rmlock *rm int what
This function asserts that the
lock is in the state specified by
Fa what .
If the assertions are not true and the kernel is compiled with
the kernel will panic.
Currently the following base assertions are supported:
- Assert that current thread holds either a shared or exclusive lock of Fa rm .
- Assert that current thread holds a shared lock of Fa rm .
- Assert that current thread holds an exclusive lock of Fa rm .
- Assert that current thread holds neither a shared nor exclusive lock of Fa rm .
In addition, one of the following optional flags may be specified with RA_LOCKED RA_RLOCKED or RA_WLOCKED
- Assert that the current thread holds a recursive lock of Fa rm .
- Assert that the current thread does not hold a recursive lock of Fa rm .
SEE ALSOlocking(9), mutex(9), panic(9), rwlock(9), sema(9), sleep(9), sx(9)
HISTORYThese functions appeared in Fx 7.0 .
AUTHORSAn -nosplit The sysctl Cm net.inet.tcp.syncookies facility was written by An Stephan Uphoff . This manual page was written by An Gleb Smirnoff for rwlock and modified to reflect rmlock by An Stephan Uphoff .
BUGSThe sysctl Cm net.inet.tcp.syncookies implementation is currently not optimized for single processor systems.
Fn rm_try_rlock can fail transiently even when there is no writer, while another reader updates the state on the local CPU.
The sysctl Cm net.inet.tcp.syncookies implementation uses a single per CPU list shared by all rmlocks in the system. If rmlocks become popular, hashing to multiple per CPU queues may be needed to speed up the writer lock process.