NAME
rw,
rw_init,
rw_destroy,
rw_enter,
rw_exit,
rw_tryenter,
rw_tryupgrade,
rw_downgrade,
rw_read_held,
rw_write_held,
rw_lock_held —
reader / writer lock primitives
SYNOPSIS
#include <sys/rwlock.h>
void
rw_init(
krwlock_t
*rw);
void
rw_destroy(
krwlock_t
*rw);
void
rw_enter(
krwlock_t
*rw,
const krw_t op);
void
rw_exit(
krwlock_t
*rw);
int
rw_tryenter(
krwlock_t
*rw,
const krw_t op);
int
rw_tryupgrade(
krwlock_t
*rw);
void
rw_downgrade(
krwlock_t
*rw);
int
rw_read_held(
krwlock_t
*rw);
int
rw_write_held(
krwlock_t
*rw);
int
rw_lock_held(
krwlock_t
*rw);
options DIAGNOSTIC
options LOCKDEBUG
DESCRIPTION
Reader / writer locks (RW locks) are used in the kernel to synchronize access to
an object among LWPs (lightweight processes) and soft interrupt handlers.
In addition to the capabilities provided by mutexes, RW locks distinguish
between read (shared) and write (exclusive) access.
RW locks are in one of three distinct states at any given time:
-
-
Unlocked
- The lock is not held.
-
-
Read
locked
- The lock holders intend to read the protected object.
Multiple callers may hold a RW lock with “read intent”
simultaneously.
-
-
Write
locked
- The lock holder intends to update the protected object.
Only one caller may hold a RW lock with “write intent”.
The
krwlock_t type provides storage for the RW lock
object. This should be treated as an opaque object and not examined directly
by consumers.
Note that these interfaces must not be used from a hardware interrupt handler.
OPTIONS AND MACROS
-
-
- options
DIAGNOSTIC
-
Kernels compiled with the
DIAGNOSTIC
option perform
basic sanity checks on RW lock operations.
-
-
- options
LOCKDEBUG
-
Kernels compiled with the
LOCKDEBUG
option perform
potentially CPU intensive sanity checks on RW lock operations.
FUNCTIONS
-
-
- rw_init(rw)
-
Initialize a lock for use. No other operations can be performed on the lock
until it has been initialized.
-
-
- rw_destroy(rw)
-
Release resources used by a lock. The lock may not be used after it has been
destroyed.
-
-
- rw_enter(rw,
op)
-
If
RW_READER
is specified as the argument to
op, acquire a read lock. If the lock is write held,
the caller will block and not return until the hold is acquired. Callers
must not recursively acquire read locks.
If RW_WRITER
is specified, acquire a write lock. If
the lock is already held, the caller will block and not return until the
hold is acquired.
RW locks and other types of locks must always be acquired in a consistent
order with respect to each other. Otherwise, the potential for system
deadlock exists.
-
-
- rw_exit(rw)
-
Release a lock. The lock must have been previously acquired by the
caller.
-
-
- rw_tryenter(rw,
op)
-
Try to acquire a lock, but do not block if the lock is already held. If the
lock is acquired successfully, return non-zero. Otherwise, return zero.
Valid arguments to op are
RW_READER
or
RW_WRITER
.
-
-
- rw_tryupgrade(rw)
-
Try to upgrade a lock from one read hold to a write hold. If the lock is
upgraded successfully, returns non-zero. Otherwise, returns zero.
-
-
- rw_downgrade(rw)
-
Downgrade a lock from a write hold to a read hold.
-
-
- rw_write_held(rw)
-
- rw_read_held(rw)
-
- rw_lock_held(rw)
-
Test the lock's condition and return non-zero if the lock is held
(potentially by the current LWP) and matches the specified condition.
Otherwise, return zero.
These functions must never be used to make locking decisions at run time:
they are provided only for diagnostic purposes.
RW locks are subject to high cache contention on multiprocessor systems, and
scale poorly when the write:read ratio is not strongly in favour of readers.
Ideally, RW locks should only be used in settings when the following three
conditions are met:
- The data object(s) protected by the RW lock are read
much more frequently than written.
- The read-side hold time for the RW lock is long (in the
order of thousands of processor clock cycles).
- Strong synchronization semantics are required: there is
no scope for lockless, lazy or optimistic synchronization.
Generally speaking, it is better to organise code paths and/or data flows such
that fewer and weaker synchronization points are required to ensure correct
operation.
CODE REFERENCES
The core of the RW lock implementation is in
sys/kern/kern_rwlock.c.
The header file
sys/sys/rwlock.h describes the public
interface, and interfaces that machine-dependent code must provide to support
RW locks.
SEE ALSO
lockstat(8),
condvar(9),
mb(9),
mutex(9)
Jim Mauro and
Richard McDougall, Solaris
Internals: Core Kernel Architecture, Prentice Hall,
2001, ISBN
0-13-022496-0.
HISTORY
The RW lock primitives first appeared in
NetBSD
5.0.