A variety of wording and spelling cleanups to the SMP architecture
document. Submitted by: Hiten Pandya <hiten@angelica.unixdaemons.com>
This commit is contained in:
parent
cd71d80afb
commit
70603a0e48
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=15210
2 changed files with 48 additions and 48 deletions
en_US.ISO8859-1
|
@ -61,8 +61,8 @@
|
|||
|
||||
<para>The goal of SMPng is to allow concurrency in the kernel.
|
||||
The kernel is basically one rather large and complex program. To
|
||||
make the kernel multithreaded we use some of the same tools used
|
||||
to make other programs multithreaded. These include mutexes,
|
||||
make the kernel multi-threaded we use some of the same tools used
|
||||
to make other programs multi-threaded. These include mutexes,
|
||||
shared/exclusive locks, semaphores, and condition variables. For
|
||||
definitions of many of the terms, please see
|
||||
<xref linkend="defs">.</para>
|
||||
|
@ -119,7 +119,7 @@
|
|||
|
||||
<para>Finally, atomic instructions only allow one item to be
|
||||
updated or read. If one needs to atomically update several
|
||||
items, then a lock must be used instad. For example, if two
|
||||
items, then a lock must be used instead. For example, if two
|
||||
counters must be read and have values that are consistent
|
||||
relative to each other, then those counters must be protected
|
||||
by a lock rather than by separate atomic instructions.</para>
|
||||
|
@ -145,7 +145,7 @@
|
|||
to write to the data, you need to have a write lock of all of
|
||||
the locks. This can make writing rather expensive but can be
|
||||
useful when data is accessed in various ways. For example,
|
||||
the parent process pointer is proctected by both the
|
||||
the parent process pointer is protected by both the
|
||||
proctree_lock sx lock and the per-process mutex. Sometimes
|
||||
the proc lock is easier as we are just checking to see who a
|
||||
parent of a process is that we already have locked. However,
|
||||
|
@ -177,7 +177,7 @@
|
|||
<sect2>
|
||||
<title>Interrupt Handling</title>
|
||||
|
||||
<para>Following the pattern of several other multithreaded Unix
|
||||
<para>Following the pattern of several other multi-threaded Unix
|
||||
kernels, FreeBSD deals with interrupt handlers by giving them
|
||||
their own thread context. Providing a context for interrupt
|
||||
handlers allows them to block on locks. To help avoid
|
||||
|
@ -231,11 +231,11 @@
|
|||
the interrupted thread.</para>
|
||||
|
||||
<para>The cons of this optimization are that they are very
|
||||
machine specific and complex and thus only worth the effor if
|
||||
machine specific and complex and thus only worth the effort if
|
||||
their is a large performance improvement. At this point it is
|
||||
probably too early to tell, and in fact, will probably hurt
|
||||
performance as almost all interrupt handlers will immediately
|
||||
block on Giant and require a thread fixup when they block.
|
||||
block on Giant and require a thread fix-up when they block.
|
||||
Also, an alternative method of interrupt handling has been
|
||||
proposed by Mike Smith that works like so:</para>
|
||||
|
||||
|
@ -306,7 +306,7 @@
|
|||
for <function>critical_enter</function> to set a per-thread
|
||||
flag that is cleared by its counterpart. If
|
||||
<function>setrunqueue</function> is called with this flag
|
||||
set, it doesn't preempt regarless of the priority of the new
|
||||
set, it doesn't preempt regardless of the priority of the new
|
||||
thread relative to the current thread. However, since
|
||||
critical sections are used in spin mutexes to prevent
|
||||
context switches and multiple spin mutexes can be acquired,
|
||||
|
@ -330,7 +330,7 @@
|
|||
mechanism is piggybacked onto critical section API by means
|
||||
of the <function>cpu_critical_enter</function> and
|
||||
<function>cpu_critical_exit</function> functions. Currently
|
||||
this API disables and reenables interrupts on all of
|
||||
this API disables and re-enables interrupts on all of
|
||||
FreeBSD's current platforms. This approach may not be
|
||||
purely optimal, but it is simple to understand and simple to
|
||||
get right. Theoretically, this second API need only be used
|
||||
|
@ -348,10 +348,10 @@
|
|||
<title>Design Tradeoffs</title>
|
||||
|
||||
<para>As mentioned earlier, a couple of tradeoffs have been
|
||||
made to sacrafice cases where perfect preemption may not
|
||||
made to sacrifice cases where perfect preemption may not
|
||||
always provide the best performance.</para>
|
||||
|
||||
<para>The first tradeoff is that the preemption code does not
|
||||
<para>The first trade-off is that the preemption code does not
|
||||
take other CPUs into account. Suppose we have a two CPU's A
|
||||
and B with the priority of A's thread as 4 and the priority
|
||||
of B's thread as 2. If CPU B makes a thread with priority 1
|
||||
|
@ -378,7 +378,7 @@
|
|||
switch out the executing thread just before it is about to
|
||||
sleep or execute. The cache on the CPU must then adjust to
|
||||
the new thread. When the kernel returns to the interrupted
|
||||
CPU, it must refill all the cache informatino that was lost.
|
||||
CPU, it must refill all the cache information that was lost.
|
||||
In addition, two extra context switches are performed that
|
||||
could be avoided if the kernel deferred the preemption until
|
||||
the first thread blocked or returned to userland. Thus, by
|
||||
|
@ -445,7 +445,7 @@
|
|||
nesting count. Due to the locking requirements specified
|
||||
above, they will only operate on the current thread and thus
|
||||
would not need to handle the case of making a thread
|
||||
migratable that currently resides on a per-CPU run
|
||||
migrateable that currently resides on a per-CPU run
|
||||
queue.</para>
|
||||
|
||||
<para>It is still debatable if this API is needed or if the
|
||||
|
@ -459,7 +459,7 @@
|
|||
<title>Callouts</title>
|
||||
|
||||
<para>The <function>timeout()</function> kernel facility permits
|
||||
kernel services to register funtions for execution as part
|
||||
kernel services to register functions for execution as part
|
||||
of the <function>softclock()</function> software interrupt.
|
||||
Events are scheduled based on a desired number of clock
|
||||
ticks, and callbacks to the consumer-provided function
|
||||
|
@ -569,7 +569,7 @@
|
|||
count. The mutex need not be held for the duration of the
|
||||
MAC entry operation--some operations, such as label operations
|
||||
on file system objects--are long-lived. To modify the policy
|
||||
list, such as during policy registration and deregistration,
|
||||
list, such as during policy registration and de-registration,
|
||||
the mutex must be held and the reference count must be zero,
|
||||
to prevent modification of the list while it is in use.</para>
|
||||
|
||||
|
@ -609,11 +609,11 @@
|
|||
<para>The newbus system will have one sx lock. Readers will
|
||||
lock it &man.sx.slock.9; and writers will lock it
|
||||
&man.sx.xlock.9;. Internal only functions will not do locking
|
||||
at all. The externally visable ones will lock as needed.
|
||||
at all. The externally visible ones will lock as needed.
|
||||
Those items that don't matter if the race is won or lost will
|
||||
not be locked, since they tend to be read all over the place
|
||||
(eg &man.device.get.softc.9;). There will be relatively few
|
||||
changes to the newbus datastructures, so a single lock should
|
||||
(e.g. &man.device.get.softc.9;). There will be relatively few
|
||||
changes to the newbus data structures, so a single lock should
|
||||
be sufficient and not impose a performance penalty.</para>
|
||||
</sect2>
|
||||
|
||||
|
@ -626,7 +626,7 @@
|
|||
<sect2>
|
||||
<title>Processes and Threads</title>
|
||||
|
||||
<para>- process hiearachy</para>
|
||||
<para>- process hierarchy</para>
|
||||
<para>- proc locks, references</para>
|
||||
<para>- thread-specific copies of proc entries to freeze during system
|
||||
calls, including td_ucred</para>
|
||||
|
@ -696,7 +696,7 @@
|
|||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>sysctl</title>
|
||||
<title>Sysctl</title>
|
||||
|
||||
<para>The <function>sysctl()</function> MIB service is invoked
|
||||
from both within the kernel and from userland applications
|
||||
|
@ -723,7 +723,7 @@
|
|||
|
||||
<para>- To allow for the common case, a sysctl could embed a
|
||||
pointer to a mutex in the SYSCTL_FOO macros and in the struct.
|
||||
This would work for most sysctls. For values protected by sx
|
||||
This would work for most sysctl's. For values protected by sx
|
||||
locks, spin mutexes, or other locking strategies besides a
|
||||
single sleep mutex, SYSCTL_PROC nodes could be used to get the
|
||||
locking right.</para>
|
||||
|
@ -776,7 +776,7 @@
|
|||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Witesss</title>
|
||||
<title>Witness</title>
|
||||
|
||||
<para>- What does it do</para>
|
||||
|
||||
|
@ -849,7 +849,7 @@
|
|||
<glossentry id="MD">
|
||||
<glossterm>MD</glossterm>
|
||||
<glossdef>
|
||||
<para>Machine depenedent.</para>
|
||||
<para>Machine dependent.</para>
|
||||
|
||||
<glossseealso>MI</glossseealso>
|
||||
</glossdef>
|
||||
|
@ -866,7 +866,7 @@
|
|||
<glossentry id="MI">
|
||||
<glossterm>MI</glossterm>
|
||||
<glossdef>
|
||||
<para>Machine indepenedent.</para>
|
||||
<para>Machine independent.</para>
|
||||
|
||||
<glossseealso>MD</glossseealso>
|
||||
</glossdef>
|
||||
|
|
|
@ -61,8 +61,8 @@
|
|||
|
||||
<para>The goal of SMPng is to allow concurrency in the kernel.
|
||||
The kernel is basically one rather large and complex program. To
|
||||
make the kernel multithreaded we use some of the same tools used
|
||||
to make other programs multithreaded. These include mutexes,
|
||||
make the kernel multi-threaded we use some of the same tools used
|
||||
to make other programs multi-threaded. These include mutexes,
|
||||
shared/exclusive locks, semaphores, and condition variables. For
|
||||
definitions of many of the terms, please see
|
||||
<xref linkend="defs">.</para>
|
||||
|
@ -119,7 +119,7 @@
|
|||
|
||||
<para>Finally, atomic instructions only allow one item to be
|
||||
updated or read. If one needs to atomically update several
|
||||
items, then a lock must be used instad. For example, if two
|
||||
items, then a lock must be used instead. For example, if two
|
||||
counters must be read and have values that are consistent
|
||||
relative to each other, then those counters must be protected
|
||||
by a lock rather than by separate atomic instructions.</para>
|
||||
|
@ -145,7 +145,7 @@
|
|||
to write to the data, you need to have a write lock of all of
|
||||
the locks. This can make writing rather expensive but can be
|
||||
useful when data is accessed in various ways. For example,
|
||||
the parent process pointer is proctected by both the
|
||||
the parent process pointer is protected by both the
|
||||
proctree_lock sx lock and the per-process mutex. Sometimes
|
||||
the proc lock is easier as we are just checking to see who a
|
||||
parent of a process is that we already have locked. However,
|
||||
|
@ -177,7 +177,7 @@
|
|||
<sect2>
|
||||
<title>Interrupt Handling</title>
|
||||
|
||||
<para>Following the pattern of several other multithreaded Unix
|
||||
<para>Following the pattern of several other multi-threaded Unix
|
||||
kernels, FreeBSD deals with interrupt handlers by giving them
|
||||
their own thread context. Providing a context for interrupt
|
||||
handlers allows them to block on locks. To help avoid
|
||||
|
@ -231,11 +231,11 @@
|
|||
the interrupted thread.</para>
|
||||
|
||||
<para>The cons of this optimization are that they are very
|
||||
machine specific and complex and thus only worth the effor if
|
||||
machine specific and complex and thus only worth the effort if
|
||||
their is a large performance improvement. At this point it is
|
||||
probably too early to tell, and in fact, will probably hurt
|
||||
performance as almost all interrupt handlers will immediately
|
||||
block on Giant and require a thread fixup when they block.
|
||||
block on Giant and require a thread fix-up when they block.
|
||||
Also, an alternative method of interrupt handling has been
|
||||
proposed by Mike Smith that works like so:</para>
|
||||
|
||||
|
@ -306,7 +306,7 @@
|
|||
for <function>critical_enter</function> to set a per-thread
|
||||
flag that is cleared by its counterpart. If
|
||||
<function>setrunqueue</function> is called with this flag
|
||||
set, it doesn't preempt regarless of the priority of the new
|
||||
set, it doesn't preempt regardless of the priority of the new
|
||||
thread relative to the current thread. However, since
|
||||
critical sections are used in spin mutexes to prevent
|
||||
context switches and multiple spin mutexes can be acquired,
|
||||
|
@ -330,7 +330,7 @@
|
|||
mechanism is piggybacked onto critical section API by means
|
||||
of the <function>cpu_critical_enter</function> and
|
||||
<function>cpu_critical_exit</function> functions. Currently
|
||||
this API disables and reenables interrupts on all of
|
||||
this API disables and re-enables interrupts on all of
|
||||
FreeBSD's current platforms. This approach may not be
|
||||
purely optimal, but it is simple to understand and simple to
|
||||
get right. Theoretically, this second API need only be used
|
||||
|
@ -348,10 +348,10 @@
|
|||
<title>Design Tradeoffs</title>
|
||||
|
||||
<para>As mentioned earlier, a couple of tradeoffs have been
|
||||
made to sacrafice cases where perfect preemption may not
|
||||
made to sacrifice cases where perfect preemption may not
|
||||
always provide the best performance.</para>
|
||||
|
||||
<para>The first tradeoff is that the preemption code does not
|
||||
<para>The first trade-off is that the preemption code does not
|
||||
take other CPUs into account. Suppose we have a two CPU's A
|
||||
and B with the priority of A's thread as 4 and the priority
|
||||
of B's thread as 2. If CPU B makes a thread with priority 1
|
||||
|
@ -378,7 +378,7 @@
|
|||
switch out the executing thread just before it is about to
|
||||
sleep or execute. The cache on the CPU must then adjust to
|
||||
the new thread. When the kernel returns to the interrupted
|
||||
CPU, it must refill all the cache informatino that was lost.
|
||||
CPU, it must refill all the cache information that was lost.
|
||||
In addition, two extra context switches are performed that
|
||||
could be avoided if the kernel deferred the preemption until
|
||||
the first thread blocked or returned to userland. Thus, by
|
||||
|
@ -445,7 +445,7 @@
|
|||
nesting count. Due to the locking requirements specified
|
||||
above, they will only operate on the current thread and thus
|
||||
would not need to handle the case of making a thread
|
||||
migratable that currently resides on a per-CPU run
|
||||
migrateable that currently resides on a per-CPU run
|
||||
queue.</para>
|
||||
|
||||
<para>It is still debatable if this API is needed or if the
|
||||
|
@ -459,7 +459,7 @@
|
|||
<title>Callouts</title>
|
||||
|
||||
<para>The <function>timeout()</function> kernel facility permits
|
||||
kernel services to register funtions for execution as part
|
||||
kernel services to register functions for execution as part
|
||||
of the <function>softclock()</function> software interrupt.
|
||||
Events are scheduled based on a desired number of clock
|
||||
ticks, and callbacks to the consumer-provided function
|
||||
|
@ -569,7 +569,7 @@
|
|||
count. The mutex need not be held for the duration of the
|
||||
MAC entry operation--some operations, such as label operations
|
||||
on file system objects--are long-lived. To modify the policy
|
||||
list, such as during policy registration and deregistration,
|
||||
list, such as during policy registration and de-registration,
|
||||
the mutex must be held and the reference count must be zero,
|
||||
to prevent modification of the list while it is in use.</para>
|
||||
|
||||
|
@ -609,11 +609,11 @@
|
|||
<para>The newbus system will have one sx lock. Readers will
|
||||
lock it &man.sx.slock.9; and writers will lock it
|
||||
&man.sx.xlock.9;. Internal only functions will not do locking
|
||||
at all. The externally visable ones will lock as needed.
|
||||
at all. The externally visible ones will lock as needed.
|
||||
Those items that don't matter if the race is won or lost will
|
||||
not be locked, since they tend to be read all over the place
|
||||
(eg &man.device.get.softc.9;). There will be relatively few
|
||||
changes to the newbus datastructures, so a single lock should
|
||||
(e.g. &man.device.get.softc.9;). There will be relatively few
|
||||
changes to the newbus data structures, so a single lock should
|
||||
be sufficient and not impose a performance penalty.</para>
|
||||
</sect2>
|
||||
|
||||
|
@ -626,7 +626,7 @@
|
|||
<sect2>
|
||||
<title>Processes and Threads</title>
|
||||
|
||||
<para>- process hiearachy</para>
|
||||
<para>- process hierarchy</para>
|
||||
<para>- proc locks, references</para>
|
||||
<para>- thread-specific copies of proc entries to freeze during system
|
||||
calls, including td_ucred</para>
|
||||
|
@ -696,7 +696,7 @@
|
|||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>sysctl</title>
|
||||
<title>Sysctl</title>
|
||||
|
||||
<para>The <function>sysctl()</function> MIB service is invoked
|
||||
from both within the kernel and from userland applications
|
||||
|
@ -723,7 +723,7 @@
|
|||
|
||||
<para>- To allow for the common case, a sysctl could embed a
|
||||
pointer to a mutex in the SYSCTL_FOO macros and in the struct.
|
||||
This would work for most sysctls. For values protected by sx
|
||||
This would work for most sysctl's. For values protected by sx
|
||||
locks, spin mutexes, or other locking strategies besides a
|
||||
single sleep mutex, SYSCTL_PROC nodes could be used to get the
|
||||
locking right.</para>
|
||||
|
@ -776,7 +776,7 @@
|
|||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Witesss</title>
|
||||
<title>Witness</title>
|
||||
|
||||
<para>- What does it do</para>
|
||||
|
||||
|
@ -849,7 +849,7 @@
|
|||
<glossentry id="MD">
|
||||
<glossterm>MD</glossterm>
|
||||
<glossdef>
|
||||
<para>Machine depenedent.</para>
|
||||
<para>Machine dependent.</para>
|
||||
|
||||
<glossseealso>MI</glossseealso>
|
||||
</glossdef>
|
||||
|
@ -866,7 +866,7 @@
|
|||
<glossentry id="MI">
|
||||
<glossterm>MI</glossterm>
|
||||
<glossdef>
|
||||
<para>Machine indepenedent.</para>
|
||||
<para>Machine independent.</para>
|
||||
|
||||
<glossseealso>MD</glossseealso>
|
||||
</glossdef>
|
||||
|
|
Loading…
Reference in a new issue