241 lines
7.0 KiB
Groff
241 lines
7.0 KiB
Groff
.\" $NetBSD: rwlock.9,v 1.19 2018/12/10 20:12:36 jdolecek Exp $
|
|
.\"
|
|
.\" Copyright (c) 2006, 2007, 2009 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Andrew Doran.
|
|
.\"
|
|
.\" 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 conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
.\"
|
|
.Dd December 10, 2018
|
|
.Dt RWLOCK 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm rw ,
|
|
.Nm rw_init ,
|
|
.Nm rw_destroy ,
|
|
.Nm rw_enter ,
|
|
.Nm rw_exit ,
|
|
.Nm rw_tryenter ,
|
|
.Nm rw_tryupgrade ,
|
|
.Nm rw_downgrade ,
|
|
.Nm rw_read_held ,
|
|
.Nm rw_write_held ,
|
|
.Nm rw_lock_held
|
|
.Nd reader / writer lock primitives
|
|
.Sh SYNOPSIS
|
|
.In sys/rwlock.h
|
|
.Ft void
|
|
.Fn rw_init "krwlock_t *rw"
|
|
.Ft void
|
|
.Fn rw_destroy "krwlock_t *rw"
|
|
.Ft void
|
|
.Fn rw_enter "krwlock_t *rw" "const krw_t op"
|
|
.Ft void
|
|
.Fn rw_exit "krwlock_t *rw"
|
|
.Ft int
|
|
.Fn rw_tryenter "krwlock_t *rw" "const krw_t op"
|
|
.Ft int
|
|
.Fn rw_tryupgrade "krwlock_t *rw"
|
|
.Ft void
|
|
.Fn rw_downgrade "krwlock_t *rw"
|
|
.Ft int
|
|
.Fn rw_read_held "krwlock_t *rw"
|
|
.Ft int
|
|
.Fn rw_write_held "krwlock_t *rw"
|
|
.Ft int
|
|
.Fn rw_lock_held "krwlock_t *rw"
|
|
.Pp
|
|
.Cd "options DIAGNOSTIC"
|
|
.Cd "options LOCKDEBUG"
|
|
.Sh 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.
|
|
.Pp
|
|
In addition to the capabilities provided by mutexes, RW locks distinguish
|
|
between read (shared) and write (exclusive) access.
|
|
.Pp
|
|
RW locks are in one of three distinct states at any given time:
|
|
.Bl -tag -width cdosrunrundo
|
|
.It Dv Unlocked
|
|
The lock is not held.
|
|
.It Dv Read locked
|
|
The lock holders intend to read the protected object.
|
|
Multiple callers may hold a RW lock with
|
|
.Dq read intent
|
|
simultaneously.
|
|
.It Dv Write locked
|
|
The lock holder intends to update the protected object.
|
|
Only one caller may hold a RW lock with
|
|
.Dq write intent .
|
|
.El
|
|
.Pp
|
|
The
|
|
.Vt krwlock_t
|
|
type provides storage for the RW lock object.
|
|
This should be treated as an opaque object and not examined directly by
|
|
consumers.
|
|
.Pp
|
|
Note that these interfaces must not be used from a hardware
|
|
interrupt handler.
|
|
.Sh OPTIONS AND MACROS
|
|
.Bl -tag -width abcd
|
|
.It Cd "options DIAGNOSTIC"
|
|
.Pp
|
|
Kernels compiled with the
|
|
.Dv DIAGNOSTIC
|
|
option perform basic sanity checks on RW lock operations.
|
|
.It Cd "options LOCKDEBUG"
|
|
.Pp
|
|
Kernels compiled with the
|
|
.Dv LOCKDEBUG
|
|
option perform potentially CPU intensive sanity checks
|
|
on RW lock operations.
|
|
.El
|
|
.Sh FUNCTIONS
|
|
.Bl -tag -width abcd
|
|
.It Fn rw_init "rw"
|
|
.Pp
|
|
Initialize a lock for use.
|
|
No other operations can be performed on the lock until it has been
|
|
initialized.
|
|
.It Fn rw_destroy "rw"
|
|
.Pp
|
|
Release resources used by a lock.
|
|
The lock may not be used after it has been destroyed.
|
|
.It Fn rw_enter "rw" "op"
|
|
.Pp
|
|
If
|
|
.Dv RW_READER
|
|
is specified as the argument to
|
|
.Fa 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.
|
|
.Pp
|
|
If
|
|
.Dv 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.
|
|
.Pp
|
|
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.
|
|
.It Fn rw_exit "rw"
|
|
.Pp
|
|
Release a lock.
|
|
The lock must have been previously acquired by the caller.
|
|
.It Fn rw_tryenter "rw" "op"
|
|
.Pp
|
|
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.
|
|
.Pp
|
|
Valid arguments to
|
|
.Fa op
|
|
are
|
|
.Dv RW_READER
|
|
or
|
|
.Dv RW_WRITER .
|
|
.It Fn rw_tryupgrade "rw"
|
|
.Pp
|
|
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.
|
|
.It Fn rw_downgrade "rw"
|
|
.Pp
|
|
Downgrade a lock from a write hold to a read hold.
|
|
.It Fn rw_write_held "rw"
|
|
.Pp
|
|
Return non-zero if write lock is held by current lwp.
|
|
Otherwise, return zero.
|
|
.It Fn rw_read_held "rw"
|
|
Returns non-zero if read lock is held by any lwp.
|
|
Otherwise, return zero.
|
|
.It Fn rw_lock_held "rw"
|
|
.Pp
|
|
Returns non-zero if either read or write lock is held by any lwp.
|
|
Otherwise, return zero.
|
|
.Pp
|
|
Functions
|
|
.Fn rw_write_held ,
|
|
.Fn rw_read_held ,
|
|
and
|
|
.Fn rw_lock_held
|
|
must never be used to make locking decisions at run time:
|
|
they are provided only for diagnostic purposes.
|
|
They are also not atomic, hence they should only be used to assert
|
|
that lock is held.
|
|
The only exception is
|
|
.Fn rw_write_held ,
|
|
which can be also used safely to assert that write lock is NOT currently
|
|
held by current lwp.
|
|
.El
|
|
.Sh PERFORMANCE CONSIDERATIONS
|
|
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:
|
|
.Bl -bullet
|
|
.It
|
|
The data object(s) protected by the RW lock are read much more frequently
|
|
than written.
|
|
.It
|
|
The read-side hold time for the RW lock is long (in the order of thousands
|
|
of processor clock cycles).
|
|
.It
|
|
Strong synchronization semantics are required: there is no scope for
|
|
lockless, lazy or optimistic synchronization.
|
|
.El
|
|
.Pp
|
|
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.
|
|
.Sh CODE REFERENCES
|
|
The core of the RW lock implementation is in
|
|
.Pa sys/kern/kern_rwlock.c .
|
|
.Pp
|
|
The header file
|
|
.Pa sys/sys/rwlock.h
|
|
describes the public interface, and interfaces that machine-dependent
|
|
code must provide to support RW locks.
|
|
.Sh SEE ALSO
|
|
.Xr membar_ops 3 ,
|
|
.Xr lockstat 8 ,
|
|
.Xr condvar 9 ,
|
|
.Xr mutex 9
|
|
.Rs
|
|
.%A Jim Mauro
|
|
.%A Richard McDougall
|
|
.%T Solaris Internals: Core Kernel Architecture
|
|
.%I Prentice Hall
|
|
.%D 2001
|
|
.%O ISBN 0-13-022496-0
|
|
.Re
|
|
.Sh HISTORY
|
|
The RW lock primitives first appeared in
|
|
.Nx 5.0 .
|