* Multiple Machines
-The current implementation assumes multiple OS threads (pthreads) run
-multiple Scheme machines in the same address space, accessing a shared
-heap. Each machine has thread-local registers and gets sole use of
-stack and heap segments in the shared address space UNTIL a garbage
-collection is signaled. During GC, one processor becomes "the GC
-processor". It interrupts the others, waits for them to stop in a "GC
-wait" state, then performs the garbage collection, tracing each
-processor's stack as well as the usual roots. It evacuates objects
-from each processor's local heap segment to the shared to_space. When
-complete, each processor's heap segment is empty and the pointers in
-its stack all point to the new shared heap.
+The current implementation assumes multiple OS threads (pthreads) each
+run a Scheme machine and access a shared heap. Each machine has
+thread-local registers and gets sole use of stack and heap segments in
+the shared address space UNTIL a garbage collection is signaled.
+During GC, one processor becomes "the GC processor". It interrupts
+the others, waits for them to stop in a "GC wait" state, then performs
+the garbage collection, tracing each processor's stack as well as the
+usual roots. It evacuates objects from each processor's local heap
+segment to the shared to_space. When complete, each processor's heap
+segment is empty and the pointers in its stack all point to the new
+shared heap.
When not garbage collecting (or waiting for a GC to complete), or
running, a processor is "idle" -- blocked waiting for an interrupt.
runnable (i.e. dead or blocked).
The "I/O waiter" is the "first" processor to become idle. It blocks
-in select instead of pause. If there are no idle processors, I/O is
-polled in the thread timer interrupt handler as usual. Thus, when a
-processor "finishes" a thread (i.e. the thread blocks, suspends or
-dies), it consults the runnable queue. If the queue is empty, the
-processor attempts to become the "I/O waiter". If there already is
-one, it goes to idle.
+in test-select-registry instead of smp-idle. If there are no idle
+processors, I/O is polled (nonblocking) in the thread timer interrupt
+handler as usual. Thus, when a processor "finishes" a thread
+(i.e. the thread blocks, suspends or dies), it consults the runnable
+queue. If the queue is empty, the processor attempts to become the
+"I/O waiter". If there already is one, it goes to idle.
When I/O arrives, the I/O waiter runs with it, but first wakes an idle
processor (with a timer interrupt) if any. The awoken likely will
become the next I/O waiter, though another processor could finish a
thread or get a timer interrupt and become I/O waiter first. Ensuring
-there is one I/O waiter simplifies updates to the system's select-
+there is one I/O waiter simplifies updates to the system's io-
registry.
All of the logic for scheduling threads and managing processors is
the garbage collector to make processor state changes atomic. Two
condition variables, "ready" and "finished", are used with the
state_mutex to cause the GC processor to wait for the others to get
-ready (export thread-local state) and for the others to wait until the
-GC processor is finished (so they can import their thread-local state
-and continue).
+ready (export pthread-local state) and for the others to wait until
+the GC processor is finished (so they can import their pthread-local
+state and continue).
** Creating Processors
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 main pthread avoids signaling uninitialized 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.
A processor continues from smp-pause by "restarting" a different
primitive -- smp-idle. In smp-idle, they wait for a timer interrupt.