lock, simple_lock_init, simple_lock, simple_lock_try,
simple_unlock,
lockinit, lockmgr, lockstatus, lockmgr_printinfo, - kernel
lock functions
#include <sys/lock.h>
void
simple_lock_init(struct simplelock *slock);
void
simple_lock(struct simplelock *slock);
int
simple_lock_try(struct simplelock *slock);
void
simple_unlock(struct simplelock *slock);
void
lockinit(struct lock *lock, int prio, const char *wmesg, int
timo,
int flags);
int
lockmgr(struct lock *lock, u_int flags, struct simplelock
*slock,
struct proc *p);
int
lockstatus(struct lock *lock);
void
lockmgr_printinfo(struct lock *lock);
The lock functions provide synchronisation in the kernel by
preventing
multiple processes from simultaneously executing critical
sections of
code accessing shared data. A number of different locks are
available:
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.
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 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 processes executing on the
same processor.
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
exclusiveaccess
locks within a single process. It also allows upgrading
a shared-access lock to an exclusive-access lock,
as well as
downgrading an exclusive-access lock to a sharedaccess lock.
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.
The functions which operate on simplelocks are:
simple_lock_init(slock)
The simplelock 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,
struct simplelock slock = SIMPLELOCK_INITIALIZER;
simple_lock(slock)
The simplelock slock is locked. If the simplelock
is held then
execution will spin until the simplelock is acquired. Care must
be taken that the calling process 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.
simple_lock_try(slock)
Try to acquire the simplelock slock without spinning. If the
simplelock is held by another process then the return value is
0. If the simplelock was acquired successfully
then the return
value is 1.
simple_unlock(slock)
The simplelock slock is unlocked. The simplelock
must be locked
and the calling process must be the one that last
acquired the
simplelock. If the calling process does not hold
the simplelock,
the simplelock will be released but the kernel behaviour
is undefined.
The functions which operate on locks are:
lockinit(lock, prio, wmesg, timo, flags)
The lock lock is initialised according to the parameters provided.
Arguments are as follows:
lock The lock.
prio The process priority when it is woken up
after sleeping
on the lock.
wmesg A sleep message used when a process goes
to sleep waiting
for the lock, so that the exact reason
it is sleeping
can easily be identified.
timo The maximum sleep time. Used by
tsleep(9).
flags Flags to specify the lock behaviour permanently over
the lifetime of the lock. Valid lock
flags are:
LK_NOWAIT
Processes should not sleep when
attempting to
acquire the lock.
LK_SLEEPFAIL
Processes should sleep, then return failure
when acquiring the lock.
LK_CANRECURSE
Processes can acquire the lock
recursively.
lockmgr(lock, flags, slock, p)
Set, change or release a lock according to the parameters provided.
Arguments are as follows:
lock The lock.
flags Flags to specify the lock request type.
In addition to
the flags specified above, the following
flags are
valid:
LK_SHARED
Get one of many possible sharedaccess locks.
If a process holding an exclusive-access lock
requests a shared-access lock,
the exclusiveaccess
lock is downgraded to a
shared-access
lock.
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 process holding an exclusive-access
lock may get additional exclusiveaccess
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.
LK_UPGRADE
The process must hold a sharedaccess lock
that it wants to have upgraded to
an exclusive-access
lock. Other processes may get exclusive
access to the protected
resource between
the time that the upgrade
is requested
and the time that it is granted.
LK_EXCLUPGRADE
The process must hold a sharedaccess lock
that it wants to have upgraded to
an exclusive-access
lock. If the request
succeeds, no
other processes 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
process has already requested an
upgrade, the
request will fail.
LK_DOWNGRADE
The process must hold an exclusive-access lock
that it wants to have downgraded
to a sharedaccess
lock. If the process
holds multiple
(recursive) exclusive-access
locks, they will
all be downgraded to shared-access locks.
LK_RELEASE
Release one instance of a lock.
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.
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.
LK_SETRECURSE
Other locks while we have it OK.
LK_RECURSEFAIL
Attempt at recursive lock fails.
LK_SPIN Lock spins instead of sleeping.
LK_INTERLOCK
Unlock the simplelock slock when
the lock is
acquired.
slock Simplelock interlock. If the flag LK_INTERLOCK is set
in flags, slock is a simplelock held by
the caller.
When the lock lock is acquired, the simplelock is released.
If the flag LK_INTERLOCK is not
set, slock is
ignored.
p Should always point to the current process
curproc.
lockstatus(lock)
Determine the status of lock lock. Returns LK_EXCLUSIVE or
LK_SHARED for exclusive-access and shared-access
locks respectively.
lockmgr_printinfo(lock)
Print out information about state of lock lock.
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:
[EBUSY] LK_FORCEUPGRADE is requested and some other
process has already
requested a lock upgrade or LK_NOWAIT is
set and a
sleep would be required.
[ENOLCK] LK_SLEEPFAIL is set and a sleep was done.
[EINTR] PCATCH is set in lock priority and a signal
arrives to interrupt
a system call.
[ERESTART] PCATCH is set in lock priority and a signal
arrives so that
the system call is restarted.
[EWOULDBLOCK]
Non-null lock timeout and timeout expires.
This section describes places within the OpenBSD source tree
where actual
code implementing or utilising the locking framework can be
found. All
pathnames are relative to /usr/src.
The locking framework itself is implemented within the file
sys/kern/kern_lock.c. Data structures and function prototypes for the
framework are located in sys/sys/lock.h.
pmap(9), spl(9), tsleep(9), uvm(9)
The kernel locking API first appeared in 4.4BSD-lite2.
OpenBSD 3.6 June 23, 2000
[ Back ] |