.\" $NetBSD: lock.9,v 1.4 2000/11/07 05:44:51 lukem 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 .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 capabilities in the kernel by preventing multiple threads from simultaneously executing critical section of code which access shared data. A number of different locks are available: .Pp .Bl -tag -width compact .It struct simplelock Provides a simple spinning mutex. The simplelock operations are implemented with machine-dependent locking primitives. .It struct lock A general lock structure for multiple shared locks, upgrading from shared to exclusive, and sleeping/spinning until the lock can be gained. .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 priority at which to sleep. .It Fa wmesg This is the sleep message for sleep locks or a simple name for spin locks. .It Fa timo The maximum sleep time. Used by .Xr tsleep 9 . .It Fa flags Flags to specify the lock type. Valid lock request types are: .Bl -tag -width compact .It LK_SHARED Get one of many possible shared locks. If a thread holding an exclusive lock requests a shared lock, the exclusive lock(s) will be downgraded to shared locks. .It LK_EXCLUSIVE Stop further shared locks, when they are cleared, grant a pending upgrade if it exists, then grant an exclusive lock. Only one exclusive lock may exist at a time, except that a thread holding an exclusive lock may get additional exclusive locks if it explicitly sets the LK_CANRECURSE flag in the lock request, or if the LK_CANRECUSE flag was set when the lock was initialized. .It LK_UPGRADE The thread must hold a shared lock that it wants to have upgraded to an exclusive lock. Other threads may get exclusive access to the 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 lock that it wants to have upgraded to an exclusive lock. If the request succeeds, no other threads will have gotten exclusive access to the 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 (see error returns below). .It LK_DOWNGRADE The thread must hold an exclusive lock that it wants to have downgraded to a shared lock. If the thread holds multiple (recursive) exclusive locks, they will all be downgraded to shared 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. .El .Pp Additional flags which may be used: .Bl -tag -width compact .It LK_NOWAIT Do not sleep to await lock. .It LK_SLEEPFAIL Sleep, then return failure. .It LK_CANRECURSE This may be recursive lock attempt. .It LK_REENABLE Lock is to be reenabled after drain. The LK_REENABLE flag may be set only at the release of a lock obtained by drain. .It LK_SETRECURSE Other locks while we have it OK. .It LK_RECURSEFAIL Attempt at recursive lock fails. .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 flags Flags to specify the lock type. Lock request types 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 .It Fn lockstatus "lock" Determine the status of lock .Fa lock . Returns LK_EXCLUSIVE or LK_SHARED for exclusive and shared 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 type. Lock request types 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 type. Lock request types 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 obtained locks return 0. Locks will always succeed unless one of the following is true: .Bl -tag -width compact .It LK_FORCEUPGRADE is requested and some other process has already requested a lock upgrade (returns EBUSY). .It LK_WAIT is set and a sleep would be required (returns EBUSY). .It LK_SLEEPFAIL is set and a sleep was done (returns ENOLCK). .It PCATCH is set in lock priority and a signal arrives (returns either EINTR or ERESTART if system calls is to be restarted). .It Non-null lock timeout and timeout expires (returns EWOULDBLOCK). .It 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). .El