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:
Robert Watson 2002-12-07 14:25:25 +00:00
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
articles/smp
books/arch-handbook/smp

View file

@ -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>

View file

@ -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>