aboutsummaryrefslogtreecommitdiff
path: root/share/man/man9/locking.9
diff options
context:
space:
mode:
Diffstat (limited to 'share/man/man9/locking.9')
-rw-r--r--share/man/man9/locking.9372
1 files changed, 372 insertions, 0 deletions
diff --git a/share/man/man9/locking.9 b/share/man/man9/locking.9
new file mode 100644
index 000000000000..825eb7f097a0
--- /dev/null
+++ b/share/man/man9/locking.9
@@ -0,0 +1,372 @@
+.\" Copyright (c) 2007 Julian Elischer (julian - freebsd org )
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 14, 2007
+.Dt LOCKING 9
+.Os
+.Sh NAME
+.Nm locking
+.Nd kernel synchronization primitives
+.Sh SYNOPSIS
+All sorts of stuff to go here.
+.Pp
+.Sh DESCRIPTION
+The
+.Em FreeBSD
+kernel is written to run across multiple CPUs and as such requires
+several different synchronization primitives to allow the developers
+to safely access and manipulate the many data types required.
+.Pp
+These include:
+.Bl -enum
+.It
+Spin Mutexes
+.It
+Sleep Mutexes
+.It
+pool Mutexes
+.It
+Shared-Exclusive locks
+.It
+Reader-Writer locks
+.It
+Read-Mostly locks
+.It
+Turnstiles
+.It
+Semaphores
+.It
+Condition variables
+.It
+Sleep/wakeup
+.It
+Giant
+.It
+Lockmanager locks
+.El
+.Pp
+The primitives interact and have a number of rules regarding how
+they can and can not be combined.
+There are too many for the average
+human mind and they keep changing.
+(if you disagree, please write replacement text) :-)
+.Pp
+Some of these primitives may be used at the low (interrupt) level and
+some may not.
+.Pp
+There are strict ordering requirements and for some of the types this
+is checked using the
+.Xr witness 4
+code.
+.Pp
+.Ss SPIN Mutexes
+Mutexes are the basic primitive.
+You either hold it or you don't.
+If you don't own it then you just spin, waiting for the holder (on
+another CPU) to release it.
+Hopefully they are doing something fast.
+You
+.Em must not
+do anything that deschedules the thread while you
+are holding a SPIN mutex.
+.Ss Mutexes
+Basically (regular) mutexes will deschedule the thread if the
+mutex can not be acquired.
+A non-spin mutex can be considered to be equivalent
+to getting a write lock on an
+.Em rw_lock
+(see below), and in fact non-spin mutexes and rw_locks may soon become the same thing.
+As in spin mutexes, you either get it or you don't.
+You may only call the
+.Xr sleep 9
+call via
+.Fn msleep
+or the new
+.Fn mtx_sleep
+variant.
+These will atomically drop the mutex and reacquire it
+as part of waking up.
+This is often however a
+.Em BAD
+idea because it generally relies on you having
+such a good knowledge of all the call graph above you
+and what assumptions it is making that there are a lot
+of ways to make hard-to-find mistakes.
+For example you MUST re-test all the assumptions you made before,
+all the way up the call graph to where you got the lock.
+You can not just assume that mtx_sleep can be inserted anywhere.
+If any caller above you has any mutex or
+rwlock, your sleep, will cause a panic.
+If the sleep only happens rarely it may be years before the
+bad code path is found.
+.Ss Pool Mutexes
+A variant of regular mutexes where the allocation of the mutex is handled
+more by the system.
+.Ss Rw_locks
+Reader/writer locks allow shared access to protected data by multiple threads,
+or exclusive access by a single thread.
+The threads with shared access are known as
+.Em readers
+since they should only read the protected data.
+A thread with exclusive access is known as a
+.Em writer
+since it may modify protected data.
+.Pp
+Although reader/writer locks look very similar to
+.Xr sx 9
+(see below) locks, their usage pattern is different.
+Reader/writer locks can be treated as mutexes (see above and
+.Xr mutex 9 )
+with shared/exclusive semantics.
+More specifically, regular mutexes can be
+considered to be equivalent to a write-lock on an
+.Em rw_lock.
+In the future this may in fact
+become literally the fact.
+An
+.Em rw_lock
+can be locked while holding a regular mutex, but
+can
+.Em not
+be held while sleeping.
+The
+.Em rw_lock
+locks have priority propagation like mutexes, but priority
+can be propagated only to an exclusive holder.
+This limitation comes from the fact that shared owners
+are anonymous.
+Another important property is that shared holders of
+.Em rw_lock
+can recurse, but exclusive locks are not allowed to recurse.
+This ability should not be used lightly and
+.Em may go away.
+Users of recursion in any locks should be prepared to
+defend their decision against vigorous criticism.
+.Ss Rm_locks
+Mostly reader locks are similar to
+.Em Reader/write
+locks but optimized for very infrequent
+.Em writer
+locking.
+.Em rm_lock
+locks implement full priority propagation by tracking shared owners
+using a lock user supplied
+.Em tracker
+data structure.
+.Ss Sx_locks
+Shared/exclusive locks are used to protect data that are read far more often
+than they are written.
+Mutexes are inherently more efficient than shared/exclusive locks, so
+shared/exclusive locks should be used prudently.
+The main reason for using an
+.Em sx_lock
+is that a thread may hold a shared or exclusive lock on an
+.Em sx_lock
+lock while sleeping.
+As a consequence of this however, an
+.Em sx_lock
+lock may not be acquired while holding a mutex.
+The reason for this is that, if one thread slept while holding an
+.Em sx_lock
+lock while another thread blocked on the same
+.Em sx_lock
+lock after acquiring a mutex, then the second thread would effectively
+end up sleeping while holding a mutex, which is not allowed.
+The
+.Em sx_lock
+should be considered to be closely related to
+.Xr sleep 9 .
+In fact it could in some cases be
+considered a conditional sleep.
+.Ss Turnstiles
+Turnstiles are used to hold a queue of threads blocked on
+non-sleepable locks.
+Sleepable locks use condition variables to implement their queues.
+Turnstiles differ from a sleep queue in that turnstile queue's
+are assigned to a lock held by an owning thread.
+Thus, when one thread is enqueued onto a turnstile, it can lend its
+priority to the owning thread.
+If this sounds confusing, we need to describe it better.
+.Ss Semaphores
+.Ss Condition variables
+Condition variables are used in conjunction with mutexes to wait for
+conditions to occur.
+A thread must hold the mutex before calling the
+.Fn cv_wait* ,
+functions.
+When a thread waits on a condition, the mutex
+is atomically released before the thread is blocked, then reacquired
+before the function call returns.
+.Ss Giant
+Giant is a special instance of a sleep lock.
+It has several special characteristics.
+.Bl -enum
+.It
+It is recursive.
+.It
+Drivers can request that Giant be locked around them, but this is
+going away.
+.It
+You can sleep while it has recursed, but other recursive locks cannot.
+.It
+Giant must be locked first before other locks.
+.It
+There are places in the kernel that drop Giant and pick it back up
+again.
+Sleep locks will do this before sleeping.
+Parts of the Network or VM code may do this as well, depending on the
+setting of a sysctl.
+This means that you cannot count on Giant keeping other code from
+running if your code sleeps, even if you want it to.
+.El
+.Ss Sleep/wakeup
+The functions
+.Fn tsleep ,
+.Fn msleep ,
+.Fn msleep_spin ,
+.Fn pause ,
+.Fn wakeup ,
+and
+.Fn wakeup_one
+handle event-based thread blocking.
+If a thread must wait for an external event, it is put to sleep by
+.Fn tsleep ,
+.Fn msleep ,
+.Fn msleep_spin ,
+or
+.Fn pause .
+Threads may also wait using one of the locking primitive sleep routines
+.Xr mtx_sleep 9 ,
+.Xr rw_sleep 9 ,
+or
+.Xr sx_sleep 9 .
+.Pp
+The parameter
+.Fa chan
+is an arbitrary address that uniquely identifies the event on which
+the thread is being put to sleep.
+All threads sleeping on a single
+.Fa chan
+are woken up later by
+.Fn wakeup ,
+often called from inside an interrupt routine, to indicate that the
+resource the thread was blocking on is available now.
+.Pp
+Several of the sleep functions including
+.Fn msleep ,
+.Fn msleep_spin ,
+and the locking primitive sleep routines specify an additional lock
+parameter.
+The lock will be released before sleeping and reacquired
+before the sleep routine returns.
+If
+.Fa priority
+includes the
+.Dv PDROP
+flag, then the lock will not be reacquired before returning.
+The lock is used to ensure that a condition can be checked atomically,
+and that the current thread can be suspended without missing a
+change to the condition, or an associated wakeup.
+In addition, all of the sleep routines will fully drop the
+.Va Giant
+mutex
+(even if recursed)
+while the thread is suspended and will reacquire the
+.Va Giant
+mutex before the function returns.
+.Pp
+.Ss lockmanager locks
+Largely deprecated.
+See the
+.Xr lock 9
+page for more information.
+I don't know what the downsides are but I'm sure someone will fill in this part.
+.Sh Usage tables.
+.Ss Interaction table.
+The following table shows what you can and can not do if you hold
+one of the synchronization primitives discussed here:
+(someone who knows what they are talking about should write this table)
+.Bl -column ".Ic xxxxxxxxxxxxxxxxxxxx" ".Xr XXXXXXXXX" ".Xr XXXXXXX" ".Xr XXXXXXX" ".Xr XXXXXXX" ".Xr XXXXX" -offset indent
+.It Xo
+.Em "You have: You want:" Ta Spin_mtx Ta Slp_mtx Ta sx_lock Ta rw_lock Ta rm_lock Ta sleep
+.Xc
+.It Ic SPIN mutex Ta \&ok-1 Ta \&no Ta \&no Ta \&no Ta \&no Ta \&no-3
+.It Ic Sleep mutex Ta \&ok Ta \&ok-1 Ta \&no Ta \&ok Ta \&ok Ta \&no-3
+.It Ic sx_lock Ta \&ok Ta \&ok Ta \&ok-2 Ta \&ok Ta \&ok Ta \&ok-4
+.It Ic rw_lock Ta \&ok Ta \&ok Ta \&no Ta \&ok-2 Ta \&ok Ta \&no-3
+.It Ic rm_lock Ta \&ok Ta \&ok Ta \&no Ta \&ok Ta \&ok-2 Ta \&no
+.El
+.Pp
+.Em *1
+Recursion is defined per lock.
+Lock order is important.
+.Pp
+.Em *2
+readers can recurse though writers can not.
+Lock order is important.
+.Pp
+.Em *3
+There are calls atomically release this primitive when going to sleep
+and reacquire it on wakeup (e.g.
+.Fn mtx_sleep ,
+.Fn rw_sleep
+and
+.Fn msleep_spin
+).
+.Pp
+.Em *4
+Though one can sleep holding an sx lock, one can also use
+.Fn sx_sleep
+which atomically release this primitive when going to sleep and
+reacquire it on wakeup.
+.Ss Context mode table.
+The next table shows what can be used in different contexts.
+At this time this is a rather easy to remember table.
+.Bl -column ".Ic Xxxxxxxxxxxxxxxxxxxx" ".Xr XXXXXXXXX" ".Xr XXXXXXX" ".Xr XXXXXXX" ".Xr XXXXXXX" ".Xr XXXXX" -offset indent
+.It Xo
+.Em "Context:" Ta Spin_mtx Ta Slp_mtx Ta sx_lock Ta rw_lock Ta rm_lock Ta sleep
+.Xc
+.It interrupt: Ta \&ok Ta \&no Ta \&no Ta \&no Ta \&no Ta \&no
+.It idle: Ta \&ok Ta \&no Ta \&no Ta \&no Ta \&no Ta \&no
+.El
+.Sh SEE ALSO
+.Xr condvar 9 ,
+.Xr lock 9 ,
+.Xr mtx_pool 9 ,
+.Xr mutex 9 ,
+.Xr rmlock 9 ,
+.Xr rwlock 9 ,
+.Xr sema 9 ,
+.Xr sleep 9 ,
+.Xr sx 9 ,
+.Xr LOCK_PROFILING 9 ,
+.Xr WITNESS 9
+.Sh HISTORY
+These
+functions appeared in
+.Bsx 4.1
+through
+.Fx 7.0