diff options
Diffstat (limited to 'share/man/man9/locking.9')
-rw-r--r-- | share/man/man9/locking.9 | 372 |
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 |