338 lines
12 KiB
Groff
338 lines
12 KiB
Groff
.\" $NetBSD: lock.9,v 1.8 2001/07/01 03:24:51 gmcgarry Exp $
|
|
.\"
|
|
.\" Copyright (c) 2000 The NetBSD Foundation, Inc.
|
|
.\" 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 conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\" 3. All advertising materials mentioning features or use of this software
|
|
.\" must display the following acknowledgement:
|
|
.\" This product includes software developed by the NetBSD
|
|
.\" Foundation, Inc. and its contributors.
|
|
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
.\" contributors may be used to endorse or promote products derived
|
|
.\" from this software without specific prior written permission.
|
|
.\"
|
|
.\" 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 June 23, 2000
|
|
.Dt LOCK 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm lock ,
|
|
.Nm simple_lock_init ,
|
|
.Nm simple_lock ,
|
|
.Nm simple_lock_try ,
|
|
.Nm simple_unlock ,
|
|
.Nm simple_lock_freecheck ,
|
|
.Nm simple_lock_dump ,
|
|
.Nm lockinit ,
|
|
.Nm lockmgr ,
|
|
.Nm lockstatus ,
|
|
.Nm lockmgr_printinfo ,
|
|
.Nm spinlockinit ,
|
|
.Nm spinlockmgr
|
|
.Nd kernel lock functions
|
|
.Sh SYNOPSIS
|
|
.Fd #include <sys/lock.h>
|
|
.Ft void
|
|
.Fn simple_lock_init "struct simplelock *slock"
|
|
.Ft void
|
|
.Fn simple_lock "struct simplelock *slock"
|
|
.Ft int
|
|
.Fn simple_lock_try "struct simplelock *slock"
|
|
.Ft void
|
|
.Fn simple_lock_unlock "struct simplelock *slock"
|
|
.Ft void
|
|
.Fn simple_lock_freecheck "void *start" "void *end"
|
|
.Ft void
|
|
.Fn simple_lock_dump "void"
|
|
.Ft void
|
|
.Fn lockinit "struct lock *lock" "int prio" "const char *wmesg" \
|
|
"int timo" "int flags"
|
|
.Ft int
|
|
.Fn lockmgr "struct lock *lock" "u_int flags" "struct simplelock *slock"
|
|
.Ft int
|
|
.Fn lockstatus "struct lock *lock"
|
|
.Ft void
|
|
.Fn lockmgr_printinfo "struct lock *lock"
|
|
.Ft void
|
|
.Fn spinlockinit "struct lock *lock" "const char *wmesg" "int flags"
|
|
.Ft int
|
|
.Fn spinlockmgr "struct lock *lock" "u_int flags" "struct simplelock *slock"
|
|
.Sh DESCRIPTION
|
|
.Pp
|
|
The
|
|
.Nm
|
|
functions provide synchronisation in the kernel by preventing multiple
|
|
threads from simultaneously executing critical sections of code
|
|
accessing shared data. A number of different locks are available:
|
|
.Pp
|
|
.Bl -tag -width compact
|
|
.It struct simplelock
|
|
Provides a simple spinning mutex. A processor will busy-wait while
|
|
trying to acquire a simplelock. The simplelock operations are
|
|
implemented with machine-dependent locking primitives.
|
|
.Pp
|
|
Simplelocks are usually used only by the high-level lock manager and
|
|
to protect short, critical sections of code. Simplelocks are the only
|
|
locks that can be be used inside an interrupt handler. For a
|
|
simplelock to be used in an interrupt handler, care must be taken to
|
|
disable the interrupt, acquire the lock, do any processing, release
|
|
the simplelock and re-enable the interrupt. This procedure is
|
|
necessary to avoid deadlock between the interrupt handler and other
|
|
threads executing on the same processor.
|
|
.It struct lock
|
|
Provides a high-level lock supporting sleeping/spinning until the lock
|
|
can be acquired. The lock manager supplies both exclusive-access and
|
|
shared-access locks, with recursive exclusive-access locks within a
|
|
single thread. It also allows upgrading a shared-access lock to an
|
|
exclusive-access lock, as well as downgrading an exclusive-access lock
|
|
to a shared-access lock.
|
|
.El
|
|
.Pp
|
|
If the kernel option LOCKDEBUG is enabled, additional facilities
|
|
are provided to record additional lock information. These facilities are
|
|
provided to assist in determining deadlock occurrences.
|
|
.Sh FUNCTIONS
|
|
The functions which operate on simplelocks are:
|
|
.Pp
|
|
.Bl -tag -width compact
|
|
.It Fn simple_lock_init "slock"
|
|
The simplelock
|
|
.Fa slock
|
|
is initialised to the unlocked state. A statically allocated simplelock
|
|
also can be initialised with the macro SIMPLELOCK_INITIALIZER. The
|
|
effect is the same as the dynamic initialisation by a call to
|
|
simple_lock_init. For example,
|
|
.Pp
|
|
struct simplelock slock = SIMPLELOCK_INITIALIZER;
|
|
.It Fn simple_lock "slock"
|
|
The simplelock
|
|
.Fa slock
|
|
is locked. If the simplelock is held then execution will
|
|
spin until the simplelock is acquired. Care must be taken that the
|
|
calling thread does not already hold the simplelock. In this case, the
|
|
simplelock can never be acquired. If kernel option LOCKDEBUG is enabled,
|
|
a "locking against myself" panic will occur.
|
|
.It Fn simple_lock_try "slock"
|
|
Try to acquire the simplelock
|
|
.Fa slock
|
|
without spinning. If the simplelock is held by another thread
|
|
then the return value is 0. If the simplelock was acquired
|
|
successfully then the return value is 1.
|
|
.It Fn simple_lock_unlock "slock"
|
|
The simplelock
|
|
.Fa slock
|
|
is unlocked. The simplelock must be locked and the calling thread must
|
|
be the one that last acquired the simplelock. If the calling
|
|
thread does not hold the simplelock, the simplelock will be released
|
|
but the kernel behaviour is undefined.
|
|
.It Fn simple_lock_freecheck "start" "end"
|
|
Check that all simplelocks in the address range
|
|
.Fa start
|
|
to
|
|
.Fa end
|
|
are not held. If a simplelock within the range is found, the kernel
|
|
enters the debugger. This function is available only with kernel
|
|
option LOCKDEBUG. It provides a mechanism for basic simplelock
|
|
consistency checks.
|
|
.It Fn simple_lock_dump "void"
|
|
Dump the state of all simplelocks in the kernel. This function is
|
|
available only with kernel option LOCKDEBUG.
|
|
.El
|
|
.Pp
|
|
The functions which operate on locks are:
|
|
.Pp
|
|
.Bl -tag -width compact
|
|
.It Fn lockinit "lock" "prio" "wmesg" "timo" "flags"
|
|
The lock
|
|
.Fa lock
|
|
is initialised according to the parameters provided. Arguments are as
|
|
follows:
|
|
.Bl -tag -width compact
|
|
.It Fa lock
|
|
The lock.
|
|
.It Fa prio
|
|
The thread priority when it is woken up after sleeping on the lock.
|
|
.It Fa wmesg
|
|
A sleep message used when a thread goes to sleep waiting for the lock, so
|
|
that the exact reason it is sleeping can easily be identified.
|
|
.It Fa timo
|
|
The maximum sleep time. Used by
|
|
.Xr tsleep 9 .
|
|
.It Fa flags
|
|
Flags to specify the lock behaviour permanently over the lifetime of
|
|
the lock. Valid lock flags are:
|
|
.Bl -tag -width compact
|
|
.It LK_NOWAIT
|
|
Threads should not sleep when attempting to acquire the lock.
|
|
.It LK_SLEEPFAIL
|
|
Threads should sleep, then return failure when acquiring the lock.
|
|
.It LK_CANRECURSE
|
|
Threads can acquire the lock recursively.
|
|
.El
|
|
.El
|
|
.It Fn lockmgr "lock" "flags" "slock"
|
|
Set, change or release a lock according to the parameters provided.
|
|
Arguments are as follows:
|
|
.Bl -tag -width compact
|
|
.It Fa lock
|
|
The lock.
|
|
.It Fa slock
|
|
Simplelock interlock. The simplelock
|
|
.Fa slock
|
|
is set by the caller. When the lock
|
|
.Fa lock
|
|
is acquired, the simplelock is released.
|
|
.It Fa flags
|
|
Flags to specify the lock request type. In addition to the flags
|
|
specified above, the following flags are valid:
|
|
.Bl -tag -width compact
|
|
.It LK_SHARED
|
|
Get one of many possible shared-access locks. If a thread holding an
|
|
exclusive-access lock requests a shared-access lock, the
|
|
exclusive-access lock is downgraded to a shared-access lock.
|
|
.It LK_EXCLUSIVE
|
|
Stop further shared-access locks, when they are cleared, grant a
|
|
pending upgrade if it exists, then grant an exclusive-access lock.
|
|
Only one exclusive-access lock may exist at a time, except that a
|
|
thread holding an exclusive-access lock may get additional
|
|
exclusive-access locks if it explicitly sets the LK_CANRECURSE flag in
|
|
the lock request, or if the LK_CANRECURSE flag was set when the lock
|
|
was initialised.
|
|
.It LK_UPGRADE
|
|
The thread must hold a shared-access lock that it wants to have
|
|
upgraded to an exclusive-access lock. Other threads may get exclusive
|
|
access to the protected resource between the time that the upgrade is
|
|
requested and the time that it is granted.
|
|
.It LK_EXCLUPGRADE
|
|
The thread must hold a shared-access lock that it wants to have
|
|
upgraded to an exclusive-access lock. If the request succeeds, no
|
|
other threads will have acquired exclusive access to the protected
|
|
resource between the time that the upgrade is requested and the time
|
|
that it is granted. However, if another thread has already requested
|
|
an upgrade, the request will fail.
|
|
.It LK_DOWNGRADE
|
|
The thread must hold an exclusive-access lock that it wants to have
|
|
downgraded to a shared-access lock. If the thread holds multiple
|
|
(recursive) exclusive-access locks, they will all be downgraded to
|
|
shared-access locks.
|
|
.It LK_RELEASE
|
|
Release one instance of a lock.
|
|
.It LK_DRAIN
|
|
Wait for all activity on the lock to end, then mark it decommissioned.
|
|
This feature is used before freeing a lock that is part of a piece of
|
|
memory that is about to be freed.
|
|
.It LK_REENABLE
|
|
Lock is to be re-enabled after drain. The LK_REENABLE flag may be set
|
|
only at the release of a lock obtained by a drain.
|
|
.It LK_SETRECURSE
|
|
Other locks while we have it OK.
|
|
.It LK_RECURSEFAIL
|
|
Attempt at recursive lock fails.
|
|
.It LK_SPIN
|
|
Lock spins instead of sleeping.
|
|
.El
|
|
.El
|
|
.It Fn lockstatus "lock"
|
|
Determine the status of lock
|
|
.Fa lock .
|
|
Returns LK_EXCLUSIVE or LK_SHARED for exclusive-access and
|
|
shared-access locks respectively.
|
|
.It Fn lockmgr_printinfo "lock"
|
|
Print out information about state of lock
|
|
.Fa lock .
|
|
.It Fn spinlockinit "lock" "wmesg" "flags"
|
|
The lock
|
|
.Fa lock
|
|
is initialised as a spinlock according to the parameters provided.
|
|
Arguments are as follows:
|
|
.Bl -tag -width compact
|
|
.It Fa lock
|
|
The lock.
|
|
.It Fa wmesg
|
|
This is a simple name for lock.
|
|
.It Fa flags
|
|
Flags to specify the lock behaviour. Valid lock flags are the same as
|
|
outlined above.
|
|
.El
|
|
.It Fn spinlockmgr "lock" "flags" "slock"
|
|
Set, change or release a lock according to the parameters provided.
|
|
Arguments are as follows:
|
|
.Bl -tag -width compact
|
|
.It Fa lock
|
|
The spin lock.
|
|
.It Fa flags
|
|
Flags to specify the lock request type. Valid lock flags are the same
|
|
as outlined above.
|
|
.It Fa slock
|
|
Simplelock interlock. The simplelock
|
|
.Fa slock
|
|
is set by the caller. When the lock
|
|
.Fa lock
|
|
is acquired, the simplelock is released.
|
|
.El
|
|
.El
|
|
.Sh RETURN VALUES
|
|
Successfully acquired locks return 0. A failed lock attempt always
|
|
returns a non-zero error value. No lock is held after an error
|
|
return (in particular, a failed LK_UPGRADE or LK_FORCEUPGRADE will
|
|
have released its shared-access lock). Locks will always succeed
|
|
unless one of the following is true:
|
|
.Bl -tag -width Er
|
|
.It Bq Er EBUSY
|
|
LK_FORCEUPGRADE is requested and some other thread has already
|
|
requested a lock upgrade or LK_NOWAIT is set and a sleep would
|
|
be required.
|
|
.It Bq Er ENOLCK
|
|
LK_SLEEPFAIL is set and a sleep was done.
|
|
.It Bq Er EINTR
|
|
PCATCH is set in lock priority and a signal arrives to interrupt
|
|
a system call.
|
|
.It Bq Er ERESTART
|
|
PCATCH is set in lock priority and a signal arrives so that
|
|
the system call is restarted.
|
|
.It Bq Er EWOULDBLOCK
|
|
Non-null lock timeout and timeout expires.
|
|
.El
|
|
.Sh CODE REFERENCES
|
|
This section describes places within the
|
|
.Nx
|
|
source tree where actual code implementing or utilising the locking
|
|
framework can be found. All pathnames are relative to
|
|
.Pa /usr/src .
|
|
.Pp
|
|
The locking framework itself is implemented within the file
|
|
.Pa sys/kern/kern_lock.c .
|
|
Data structures and function prototypes for the framework are located
|
|
in
|
|
.Pa sys/sys/lock.h .
|
|
Machine-dependent simplelock primitives are implemented within the
|
|
file
|
|
.Pa sys/arch/<arch>/include/lock.h .
|
|
.Sh SEE ALSO
|
|
.Xr pmap 9 ,
|
|
.Xr spl 9 ,
|
|
.Xr tsleep 9 ,
|
|
.Xr uvm 9 .
|
|
.Sh HISTORY
|
|
The kernel locking API first appeared in
|
|
.Bx 4.4 -lite2.
|