partially applicable. This does at least remove some mutex flags that were obsoleted a long, long time ago as well as rename the lockmgr section to be more generic.
313 lines
9.4 KiB
Text
313 lines
9.4 KiB
Text
<!--
|
|
The FreeBSD Documentation Project
|
|
The FreeBSD SMP Next Generation Project
|
|
|
|
$FreeBSD$
|
|
-->
|
|
|
|
<chapter id="locking">
|
|
<title>Locking Notes</title>
|
|
|
|
<para><emphasis>This chapter is maintained by the FreeBSD SMP Next
|
|
Generation Project. Please direct any comments or suggestions
|
|
to its &a.smp;.</emphasis></para>
|
|
|
|
|
|
<para>This document outlines the locking used in the FreeBSD kernel
|
|
to permit effective multi-processing within the kernel. Locking
|
|
can be achieved via several means. Data structures can be
|
|
protected by mutexes or &man.lockmgr.9; locks. A few variables
|
|
are protected simply by always using atomic operations to access
|
|
them.</para>
|
|
|
|
<sect1 id="locking-mutexes">
|
|
<title>Mutexes</title>
|
|
|
|
<para>A mutex is simply a lock used to guarantee mutual exclusion.
|
|
Specifically, a mutex may only be owned by one entity at a time.
|
|
If another entity wishes to obtain a mutex that is already
|
|
owned, it must wait until the mutex is released. In the FreeBSD
|
|
kernel, mutexes are owned by processes.</para>
|
|
|
|
<para>Mutexes may be recursively acquired, but they are intended
|
|
to be held for a short period of time. Specifically, one may
|
|
not sleep while holding a mutex. If you need to hold a lock
|
|
across a sleep, use a &man.lockmgr.9; lock.</para>
|
|
|
|
<para>Each mutex has several properties of interest:</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>Variable Name</term>
|
|
<listitem>
|
|
<para>The name of the <type>struct mtx</type> variable in
|
|
the kernel source.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>Logical Name</term>
|
|
<listitem>
|
|
<para>The name of the mutex assigned to it by
|
|
<function>mtx_init</function>. This name is displayed in
|
|
KTR trace messages and witness errors and warnings and is
|
|
used to distinguish mutexes in the witness code.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>Type</term>
|
|
<listitem>
|
|
<para>The type of the mutex in terms of the
|
|
<constant>MTX_*</constant> flags. The meaning for each
|
|
flag is related to its meaning as documented in
|
|
&man.mutex.9;.</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><constant>MTX_DEF</constant></term>
|
|
<listitem>
|
|
<para>A sleep mutex</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><constant>MTX_SPIN</constant></term>
|
|
<listitem>
|
|
<para>A spin mutex</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><constant>MTX_RECURSE</constant></term>
|
|
<listitem>
|
|
<para>This mutex is allowed to recurse.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>Protectees</term>
|
|
<listitem>
|
|
<para>A list of data structures or data structure members
|
|
that this entry protects. For data structure members, the
|
|
name will be in the form of
|
|
<structname/structure name/.<structfield/member name/.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>Dependent Functions</term>
|
|
<listitem>
|
|
<para>Functions that can only be called if this mutex is
|
|
held.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<table frame="all" colsep="1" rowsep="1" pgwide="1">
|
|
<title>Mutex List</title>
|
|
|
|
<tgroup cols="5">
|
|
<thead>
|
|
<row>
|
|
<entry>Variable Name</entry>
|
|
<entry>Logical Name</entry>
|
|
<entry>Type</entry>
|
|
<entry>Protectees</entry>
|
|
<entry>Dependent Functions</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<!-- The scheduler lock -->
|
|
<tbody>
|
|
<row>
|
|
<entry>sched_lock</entry>
|
|
<entry><quote>sched lock</quote></entry>
|
|
<entry>
|
|
<constant>MTX_SPIN</constant> |
|
|
<constant>MTX_RECURSE</constant>
|
|
</entry>
|
|
<entry>
|
|
<varname>_gmonparam</varname>,
|
|
<varname>cnt.v_swtch</varname>,
|
|
<varname>cp_time</varname>,
|
|
<varname>curpriority</varname>,
|
|
<structname/mtx/.<structfield/mtx_blocked/,
|
|
<structname/mtx/.<structfield/mtx_contested/,
|
|
<structname/proc/.<structfield/p_procq/,
|
|
<structname/proc/.<structfield/p_slpq/,
|
|
<structname/proc/.<structfield/p_sflag/
|
|
<structname/proc/.<structfield/p_stat/,
|
|
<structname/proc/.<structfield/p_estcpu/,
|
|
<structname/proc/.<structfield/p_cpticks/
|
|
<structname/proc/.<structfield/p_pctcpu/,
|
|
<structname/proc/.<structfield/p_wchan/,
|
|
<structname/proc/.<structfield/p_wmesg/,
|
|
<structname/proc/.<structfield/p_swtime/,
|
|
<structname/proc/.<structfield/p_slptime/,
|
|
<structname/proc/.<structfield/p_runtime/,
|
|
<structname/proc/.<structfield/p_uu/,
|
|
<structname/proc/.<structfield/p_su/,
|
|
<structname/proc/.<structfield/p_iu/,
|
|
<structname/proc/.<structfield/p_uticks/,
|
|
<structname/proc/.<structfield/p_sticks/,
|
|
<structname/proc/.<structfield/p_iticks/,
|
|
<structname/proc/.<structfield/p_oncpu/,
|
|
<structname/proc/.<structfield/p_lastcpu/,
|
|
<structname/proc/.<structfield/p_rqindex/,
|
|
<structname/proc/.<structfield/p_heldmtx/,
|
|
<structname/proc/.<structfield/p_blocked/,
|
|
<structname/proc/.<structfield/p_mtxname/,
|
|
<structname/proc/.<structfield/p_contested/,
|
|
<structname/proc/.<structfield/p_priority/,
|
|
<structname/proc/.<structfield/p_usrpri/,
|
|
<structname/proc/.<structfield/p_nativepri/,
|
|
<structname/proc/.<structfield/p_nice/,
|
|
<structname/proc/.<structfield/p_rtprio/,
|
|
<varname>pscnt</varname>,
|
|
<varname>slpque</varname>,
|
|
<varname>itqueuebits</varname>,
|
|
<varname>itqueues</varname>,
|
|
<varname>rtqueuebits</varname>,
|
|
<varname>rtqueues</varname>,
|
|
<varname>queuebits</varname>,
|
|
<varname>queues</varname>,
|
|
<varname>idqueuebits</varname>,
|
|
<varname>idqueues</varname>,
|
|
<varname>switchtime</varname>,
|
|
<varname>switchticks</varname>
|
|
</entry>
|
|
<entry>
|
|
<function>setrunqueue</function>,
|
|
<function>remrunqueue</function>,
|
|
<function>mi_switch</function>,
|
|
<function>chooseproc</function>,
|
|
<function>schedclock</function>,
|
|
<function>resetpriority</function>,
|
|
<function>updatepri</function>,
|
|
<function>maybe_resched</function>,
|
|
<function>cpu_switch</function>,
|
|
<function>cpu_throw</function>,
|
|
<function>need_resched</function>,
|
|
<function>resched_wanted</function>,
|
|
<function>clear_resched</function>,
|
|
<function>aston</function>,
|
|
<function>astoff</function>,
|
|
<function>astpending</function>,
|
|
<function>calcru</function>,
|
|
<function>proc_compare</function>
|
|
</entry>
|
|
</row>
|
|
|
|
<!-- The vm86 pcb lock -->
|
|
<row>
|
|
<entry>vm86pcb_lock</entry>
|
|
<entry><quote>vm86pcb lock</quote></entry>
|
|
<entry>
|
|
<constant>MTX_DEF</constant>
|
|
</entry>
|
|
<entry>
|
|
<varname>vm86pcb</varname>
|
|
</entry>
|
|
<entry>
|
|
<function>vm86_bioscall</function>
|
|
</entry>
|
|
</row>
|
|
|
|
<!-- Giant -->
|
|
<row>
|
|
<entry>Giant</entry>
|
|
<entry><quote>Giant</quote></entry>
|
|
<entry>
|
|
<constant>MTX_DEF</constant> |
|
|
<constant>MTX_RECURSE</constant>
|
|
</entry>
|
|
<entry>nearly everything</entry>
|
|
<entry>lots</entry>
|
|
</row>
|
|
|
|
<!-- The callout lock -->
|
|
<row>
|
|
<entry>callout_lock</entry>
|
|
<entry><quote>callout lock</quote></entry>
|
|
<entry>
|
|
<constant>MTX_SPIN</constant> |
|
|
<constant>MTX_RECURSE</constant>
|
|
</entry>
|
|
<entry>
|
|
<varname>callfree</varname>,
|
|
<varname>callwheel</varname>,
|
|
<varname>nextsoftcheck</varname>,
|
|
<structname/proc/.<structfield/p_itcallout/,
|
|
<structname/proc/.<structfield/p_slpcallout/,
|
|
<varname>softticks</varname>,
|
|
<varname>ticks</varname>
|
|
</entry>
|
|
<entry>
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</sect1>
|
|
|
|
<sect1 id="locking-sx">
|
|
<title>Shared Exclusive Locks</title>
|
|
|
|
<para>These locks provide basic reader-writer type functionality
|
|
and may be held by a sleeping process. Currently they are
|
|
backed by &man.lockmgr.9;.</para>
|
|
|
|
<table>
|
|
<title>Shared Exclusive Lock List</title>
|
|
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Variable Name</entry>
|
|
<entry>Protectees</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry><varname>allproc_lock</varname></entry>
|
|
<entry>
|
|
<varname>allproc</varname>
|
|
<varname>zombproc</varname>
|
|
<varname>pidhashtbl</varname>
|
|
<structname/proc/.<structfield/p_list/
|
|
<structname/proc/.<structfield/p_hash/
|
|
<varname>nextpid</varname>
|
|
</entry>
|
|
<entry><varname>proctree_lock</varname></entry>
|
|
<entry>
|
|
<structname/proc/.<structfield/p_children/
|
|
<structname/proc/.<structfield/p_sibling/
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</sect1>
|
|
|
|
<sect1 id="locking-atomic">
|
|
<title>Atomically Protected Variables</title>
|
|
|
|
<para>An atomically protected variable is a special variable that
|
|
is not protected by an explicit lock. Instead, all data
|
|
accesses to the variables use special atomic operations as
|
|
described in &man.atomic.9;. Very few variables are treated
|
|
this way, although other synchronization primitives such as
|
|
mutexes are implemented with atomically protected
|
|
variables.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><structname/mtx/.<structfield/mtx_lock/</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect1>
|
|
</chapter>
|