363 lines
12 KiB
Groff
363 lines
12 KiB
Groff
.\" $NetBSD: lock.9,v 1.15 2002/10/14 13:43:26 wiz 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 \*[Lt]sys/lock.h\*[Gt]
|
|
.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_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
|
|
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_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.
|
|
If the flag LK_INTERLOCK is set in
|
|
.Fa flags ,
|
|
.Fa slock
|
|
is a simplelock held by the caller.
|
|
When the lock
|
|
.Fa lock
|
|
is acquired, the simplelock is released.
|
|
If the flag LK_INTERLOCK is not set,
|
|
.Fa slock
|
|
is ignored.
|
|
.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.
|
|
.It LK_INTERLOCK
|
|
Unlock the simplelock
|
|
.Fa slock
|
|
when the lock is acquired.
|
|
.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/\*[Lt]arch\*[Gt]/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 .
|