smp: README.txt wordsmithing. Squash into 9969ff0.
authorMatt Birkholz <puck@birchwood-abbey.net>
Sat, 21 Feb 2015 18:33:00 +0000 (11:33 -0700)
committerMatt Birkholz <puck@birchwood-abbey.net>
Sat, 21 Feb 2015 18:33:00 +0000 (11:33 -0700)
README.txt

index cb39dab51ee347afc75005fccc35e2d7c86a8037..066b8513723b892459e245e55bb1398fb4692c5b 100644 (file)
@@ -63,34 +63,38 @@ and continue).
 
 The first primitive executed by the main pthread is typically (outside
 of the initial bootstrap) Prim_band_load, which begins with
-smp_gc_start.  Without a fixed objects vector, new processors cannot
-handle the usual global-gc signal, so they start out in the GC-WAIT
-state via the SMP-PAUSE primitive.
-
-To avoid signaling the new processors, the main pthread waits for them
-all to reach the GC-WAIT state and signal "ready".  When ready, the
-main pthread runs the interpreter to bootstrap or load a band.  The
-waiting processors are blocked until the finished condition is
-signaled by the primitive GC daemon.  By that point, a bootstrap or
+smp_gc_start.  At this point there is no fixed objects vector, so the
+GC cannot start by signaling any new processors.  Instead the new
+processors START in the gc-wait state via Scheme's smp-pause
+primitive.
+
+The main pthread avoids signaling new processors by waiting (on the
+"ready" signal) for all processors to reach the gc-wait state.  When
+ready, the main pthread runs the interpreter to bootstrap or load a
+band.  The waiting processors are blocked until the finished condition
+is signaled by the primitive GC daemon.  By that point, a bootstrap or
 band restore will have initialized the interrupt handlers in the fixed
-objects vector.  The non-main processors continue from smp-pause by
-"restarting" smp-idle where they wait for a timer interrupt
-(e.g. when the main thread creates the first non-main thread).
+objects vector.
+
+A processor continues from smp-pause by "restarting" a different
+primitive -- smp-idle.  In smp-idle, they wait for a timer interrupt.
+The first such interrupt comes when the main thread creates the first
+non-main thread.
 
 ** Synchronizing for GC
 
 A processor aborting for GC locks the state_mutex and test-and-sets
 the gc_processor variable.  If successful, it proceeds to interrupt
 the other processors, whose interrupt handlers cause them to execute
-smp-gc-wait, a primitive that shifts them into GC-WAIT state where
+smp-gc-wait, a primitive that shifts them into gc-wait state where
 they block on the finished condition.  gc_processor waits for the
-others to reach the GC-WAIT state by blocking on the ready condition.
+others to reach the gc-wait state by blocking on the ready condition.
 When ready is signaled, the GC processor performs the garbage
 collection and broadcasts the finished condition.
 
 A processor aborting for GC may lock the state_mutex only to find
 another processor has already set the gc_processor variable.  If it
-does, it goes straight to the GC-WAIT state and blocks on the finished
+does, it goes straight to the gc-wait state and blocks on the finished
 condition, then proceeds with an empty local heap as though it had
 accomplished the garbage collection itself.  If the primitive being
 executed needs exclusive access to reformat the heap (a purification
@@ -101,8 +105,8 @@ until it succeeds and can re-arrange the heap.
 
 The runtime system keeps track of the threads running on each
 processor by putting them in a "current-threads" vector.  Newly
-runnable threads are put on a runnable queue (and an idle processor is
-woken, if any).  The timer interrupt handler should pick up a runnable
+runnable threads are put on a runnable queue and an idle processor is
+woken, if any.  The timer interrupt handler should pick up a runnable
 thread and process its continuation.  When a thread is no longer
 runnable and there are no runnable threads in the queue, the processor
 executes either test-select-registry (when it is the io-waiter) or
@@ -112,23 +116,22 @@ All of the operations that manipulate Scheme threads, including
 current-threads, the runnable queue, timers and i/o channel waits,
 must be serialized.  They must grab the thread_mutex and hold it for
 the duration of the operation.  This mutex is distinct from the
-state_mutex so that it can serialize the thread operations, without
+state_mutex so that it can serialize the thread operations without
 locking out GCs.
 
 An important Scheme thread operation is the timer interrupt handler.
 It must grab the thread_mutex because other threads may be spawning or
 signaling threads and thus frobbing the runnable queue and whatnot
 too.  An interrupt handler that grabs a mutex, interrupting code that
-may hold that mutex, is courting deadlock, so care must be taken to
+may hold that mutex, is courting deadlock, so care is taken to
 mask the interrupt as long as (longer than!) the mutex is held.
 
-The OS process receives a timer interrupt (SIGALRM) regularly while
-there are threads in the runnable queue, and whenever a thread would
-wake from sleep.  The signal handler might run in any pthread, but
-is forwarded to the next processor in a ring of all processors.
-Thus 2 processors are interrupted half as often with the same thread
-timer interval.  Four processors run uninterrupted for 4 times the
-interval.
+The OS process receives a timer signal (SIGALRM) regularly while there
+are threads in the runnable queue (or when a thread wakes).  The
+signal handler might run in any pthread, but is forwarded to the next
+processor in the ring of all processors.  Thus 2 processors are
+interrupted half as often with the same thread timer interval.  Four
+processors run uninterrupted for 4 times the interval.
 \f
 
 * Analyses