345 lines
15 KiB
HTML
345 lines
15 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<style id="fort-styles">
|
||
[data-fort]{font:inherit;color:inherit}
|
||
ul[data-fort]{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.45em}
|
||
[data-fort] li{margin:0;padding:0;line-height:1.45;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
[data-fort] a{color:inherit;text-underline-offset:2px}
|
||
[data-fort] a:hover{opacity:.72}
|
||
[data-fort] .src,[data-fort] .fm-type{opacity:.6;font-size:.85em}
|
||
.fort-citizen{display:flex;flex-direction:column;gap:.4em}
|
||
.fort-citizen .fc-name{font-weight:600}
|
||
.fort-citizen .fc-pages{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.3em}
|
||
.fort-media,.fort-film{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:.6em}
|
||
.fort-film{list-style:none;margin:0;padding:0}
|
||
.fort-film li{overflow:visible;white-space:normal}
|
||
.fort-film a{display:flex;flex-direction:column;gap:.3em;text-decoration:none}
|
||
.fort-media img,.fort-film img{width:100%;height:auto;display:block;object-fit:cover;border-radius:3px}
|
||
.fort-film img{aspect-ratio:16/10}
|
||
.fort-nav{display:flex;flex-wrap:wrap;gap:1em;align-items:center}
|
||
</style>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>AGC Executive Scheduler — stream.4ort.net</title>
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:title" content="AGC Executive Scheduler — stream.4ort.net">
|
||
<meta property="og:description" content="How a 72 KB machine scheduled its own survival — Apollo Guidance Computer (Q138875), alarm 1201, and the birth of real-time task management">
|
||
<meta property="og:url" content="https://stream.4ort.net/agc-executive.html">
|
||
<meta name="twitter:card" content="summary">
|
||
<meta name="description" content="How a 72 KB machine scheduled its own survival — Apollo Guidance Computer (Q138875), alarm 1201, and the birth of real-time task management">
|
||
<style>
|
||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=IBM+Plex+Mono:wght@400;700&display=swap');
|
||
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
|
||
:root {
|
||
--bg: #0a0a0a;
|
||
--fg: #b8b8b8;
|
||
--accent: #00ff41;
|
||
--dim: #555;
|
||
--warn: #ff6600;
|
||
--border: #222;
|
||
--exec1: #00ff41;
|
||
--exec2: #00aaff;
|
||
}
|
||
|
||
body {
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
font-family: 'IBM Plex Mono', 'Courier New', monospace;
|
||
font-size: 14px;
|
||
line-height: 1.6;
|
||
max-width: 820px;
|
||
margin: 0 auto;
|
||
padding: 2rem 1.5rem;
|
||
}
|
||
|
||
fort-nav { display: block; }
|
||
|
||
header {
|
||
border-bottom: 1px solid var(--border);
|
||
padding-bottom: 1rem;
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.breadcrumb {
|
||
font-size: 0.7rem;
|
||
color: var(--dim);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.1em;
|
||
}
|
||
|
||
.breadcrumb a {
|
||
color: var(--dim);
|
||
text-decoration: none;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
|
||
.breadcrumb a:hover { color: var(--accent); border-bottom-color: var(--accent); }
|
||
|
||
h1 {
|
||
color: var(--accent);
|
||
font-size: 1.3rem;
|
||
font-weight: 700;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
margin-top: 0.5rem;
|
||
}
|
||
|
||
.subtitle {
|
||
color: var(--dim);
|
||
font-size: 0.85rem;
|
||
margin-top: 0.3rem;
|
||
}
|
||
|
||
h2 {
|
||
color: var(--accent);
|
||
font-size: 0.9rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.08em;
|
||
margin: 2rem 0 0.8rem 0;
|
||
padding-bottom: 0.3rem;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
|
||
h3 {
|
||
color: #e0e0e0;
|
||
font-size: 0.85rem;
|
||
margin: 1rem 0 0.4rem 0;
|
||
}
|
||
|
||
p { margin-bottom: 0.8rem; }
|
||
|
||
.block {
|
||
background: #111;
|
||
border: 1px solid var(--border);
|
||
padding: 1rem;
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.code-block {
|
||
background: #050505;
|
||
border: 1px solid var(--border);
|
||
padding: 1rem;
|
||
overflow-x: auto;
|
||
font-size: 0.75rem;
|
||
color: var(--accent);
|
||
margin-bottom: 1rem;
|
||
white-space: pre;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.warn { color: var(--warn); }
|
||
.exec1 { color: var(--exec1); }
|
||
.exec2 { color: var(--exec2); }
|
||
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-bottom: 1rem;
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
th, td {
|
||
text-align: left;
|
||
padding: 0.4rem 0.6rem;
|
||
border: 1px solid var(--border);
|
||
}
|
||
|
||
th {
|
||
background: #111;
|
||
color: var(--accent);
|
||
font-weight: 700;
|
||
text-transform: uppercase;
|
||
font-size: 0.7rem;
|
||
letter-spacing: 0.05em;
|
||
}
|
||
|
||
a {
|
||
color: var(--accent);
|
||
text-decoration: none;
|
||
border-bottom: 1px solid var(--dim);
|
||
}
|
||
|
||
a:hover { border-bottom-color: var(--accent); }
|
||
|
||
.meta {
|
||
color: var(--dim);
|
||
font-size: 0.75rem;
|
||
margin-top: 0.5rem;
|
||
}
|
||
|
||
.spec-table td:first-child { color: var(--accent); }
|
||
|
||
.diagram {
|
||
background: #050505;
|
||
border: 1px solid var(--border);
|
||
padding: 1.5rem 1rem;
|
||
margin: 1rem 0;
|
||
font-size: 0.7rem;
|
||
line-height: 1.3;
|
||
white-space: pre;
|
||
overflow-x: auto;
|
||
color: var(--fg);
|
||
}
|
||
|
||
.diagram .t { color: var(--exec1); }
|
||
.diagram .i { color: var(--warn); }
|
||
.diagram .s { color: var(--exec2); }
|
||
|
||
img {
|
||
max-width: 100%;
|
||
border: 1px solid var(--border);
|
||
margin: 1rem 0;
|
||
}
|
||
|
||
footer {
|
||
border-top: 1px solid var(--border);
|
||
padding-top: 1rem;
|
||
margin-top: 2rem;
|
||
font-size: 0.7rem;
|
||
color: var(--dim);
|
||
}
|
||
|
||
.json-link {
|
||
display: inline-block;
|
||
margin-top: 0.5rem;
|
||
font-size: 0.7rem;
|
||
color: var(--dim);
|
||
}
|
||
</style>
|
||
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
|
||
</head>
|
||
<body>
|
||
|
||
<header>
|
||
<p class="breadcrumb"><a href="index.html">STREAM</a> / AGC EXECUTIVE</p>
|
||
<h1>THE AGC EXECUTIVE SCHEDULER</h1>
|
||
<p class="subtitle">How a 72 KB machine scheduled its own survival — Apollo Guidance Computer (Q138875), alarm 1201, and the birth of real-time task management</p>
|
||
</header>
|
||
|
||
<fort-nav><nav class="fort-nav" data-fort="nav"><a href="/">STREAM</a><a href="/agc-executive.html" class="active" aria-current="page">AGC Executive Scheduler</a><a href="/degradation-comparison.html">Graceful Degradation: AGC 1201 to Render Farms</a></nav></fort-nav>
|
||
|
||
<section>
|
||
<h2>01 / THE MACHINE</h2>
|
||
<p>The <a href="https://en.wikipedia.org/wiki/Apollo_Guidance_Computer" target="_blank">Apollo Guidance Computer</a> — manufactured by <a href="https://www.wikidata.org/entity/Q234276" target="_blank">Raytheon</a> (Q234276) for NASA's Apollo program — was a 2 MHz, 72 KB core-memory machine running in <a href="https://en.wikipedia.org/wiki/Apollo_Guidance_Computer_software" target="_blank">assembly language</a>. Its software wasn't just guidance code. It contained a <strong>fixed-interval cyclic executive</strong> — the first production real-time scheduler in flight-critical hardware.</p>
|
||
|
||
<p>The AGC executive divided tasks across two timer-driven intervals:</p>
|
||
|
||
<table class="spec-table">
|
||
<tr><th>PARAMETER</th><th>VALUE</th><th>ROLE</th></tr>
|
||
<tr><td>EXECUTIVE 1</td><td>20 ms</td><td>Navigation, guidance, platform alignment, attitude control</td></tr>
|
||
<tr><td>EXECUTIVE 2</td><td>2 ms</td><td>High-frequency attitude correction, D-106 loop</td></tr>
|
||
<tr><td>PROCESSOR CLOCK</td><td>2 MHz</td><td>~4,000,000 cycles/second</td></tr>
|
||
<tr><td>MEMORY</td><td>72 KB (core rope)</td><td>Read-only; no dynamic allocation</td></tr>
|
||
<tr><td>PRIVILEGES</td><td>5 levels (0–4 + I-level)</td><td>Preemptive priority with interrupt nesting</td></tr>
|
||
</table>
|
||
|
||
<p>Executive 1 ran every 20 milliseconds. Executive 2 ran every 2 milliseconds — ten times per Exec 1 cycle. Together they formed a rigid, deterministic schedule. Not best-effort. Not cooperative. <strong>Hard deadlines, every cycle, with priority-based preemption when tasks overran.</strong></p>
|
||
|
||
<p>This is the same pattern a render farm executive uses today: fixed intervals, task queues, preemptive rescheduling when a node falls behind. The hardware changed. The scheduling topology didn't.</p>
|
||
</section>
|
||
|
||
<section>
|
||
<h2>02 / EXECUTIVE STRUCTURE</h2>
|
||
<p>Each Exec 1 (20 ms) cycle consisted of a table of task descriptors. For each entry, the executive checked a flag: if the task was scheduled for this cycle, it ran the code, updated the flag, and moved to the next entry. When Exec 2 (2 ms) fired, it preempted Exec 1 at the current task boundary, ran its 6 tasks, then resumed Exec 1 exactly where it left off.</p>
|
||
|
||
<div class="diagram">
|
||
<span class="t">[t=0ms]</span> <span class="s">EXEC 1 START</span> → nav_task → platform → display → ...
|
||
↓ <span class="i">INTERRUPT (2 ms)</span>
|
||
<span class="s">EXEC 2</span> → att_corr_1 → att_corr_2 → d106_loop
|
||
↓ <span class="i">RETURN FROM INT</span>
|
||
<span class="t">[t=2ms]</span> <span class="s">EXEC 1 RESUME</span> → guidance → thrust → ...
|
||
↓ <span class="i">INTERRUPT (4 ms)</span>
|
||
<span class="s">EXEC 2</span> → att_corr_1 → att_corr_2 → d106_loop
|
||
<span class="t">[t=4ms]</span> <span class="s">EXEC 1 RESUME</span> → ...
|
||
<span class="i"> × 10 interrupts</span>
|
||
<span class="t">[t=20ms]</span> <span class="s">EXEC 1 COMPLETE → REPEAT</span>
|
||
</div>
|
||
|
||
<p>The key constraint: the sum of all Exec 1 task times must be ≤ 20 ms. The sum of all Exec 2 task times must be ≤ 2 ms. If they weren't, the system couldn't keep its schedule. The designers left <strong>headroom</strong> — typically running the Exec 1 tasks in ~15-18 of the 20 available ms — so that unexpected loads wouldn't trigger preemption.</p>
|
||
|
||
<p>When they ran out of headroom, the system dropped the lowest-priority tasks. That's what alarm 1201 was.</p>
|
||
</section>
|
||
|
||
<section>
|
||
<h2>03 / ALARM 1201 — THE OVERSCHEDULING EVENT</h2>
|
||
<p>During Apollo 11's powered descent on July 20, 1969, the AGC threw <strong>Alarm 1201</strong> (and later 1202) repeatedly. The alarm codes in the AGC's Display and Keyboard (DSKY) system:</p>
|
||
|
||
<table class="spec-table">
|
||
<tr><th>ALARM</th><th>MEANING</th><th>ACTION</th></tr>
|
||
<tr><td class="warn">1201</td><td>Executive overflow — Exec 1 tasks exceeded 20 ms budget</td><td>Drop lowest-priority Exec 1 tasks</td></tr>
|
||
<tr><td class="warn">1202</td><td>Executive overflow — Exec 2 tasks exceeded 2 ms budget</td><td>Drop lowest-priority Exec 2 tasks</td></tr>
|
||
</table>
|
||
|
||
<p>The cause: the rendezvous radar, which should have been powered down before the descent phase, was sending continuous interrupts. Each interrupt forced the AGC to context-switch to a higher-priority I-level task that processed radar data — data the descent didn't need. These spurious interrupts ate cycles from the Exec 1 budget.</p>
|
||
|
||
<p>The executive responded exactly as designed: it began dropping the lowest-priority tasks in Exec 1's queue to preserve the hard deadline. <strong>It was scheduling itself out of a corner.</strong></p>
|
||
|
||
<p>Gene Kranz at Capstone heard "1201, alert" and asked for the go/no-go. The answer: <em>go</em>. The system was shedding non-essential work to keep the critical path alive. Not a failure. A correct scheduling decision under overload.</p>
|
||
|
||
<p><em>Source: <a href="https://www.wikidata.org/entity/Q138875" target="_blank">Apollo Guidance Computer (Q138875)</a>; <a href="https://www.wikidata.org/entity/Q43653" target="_blank">Apollo 11 (Q43653)</a>; source code at <a href="https://github.com/chrislgarry/Apollo-11" target="_blank">github.com/chrislgarry/Apollo-11</a></em></p>
|
||
</section>
|
||
|
||
<section>
|
||
<h2>04 / THE MATH: THROUGHPUT UNDER OVERLOAD</h2>
|
||
<p>Map this to the throughput model from <a href="render-farm-theory.html">render-farm-theory.html</a>. The AGC executive is a single-node scheduler with:</p>
|
||
|
||
<div class="code-block">
|
||
T_available = 20 ms (Exec 1 budget)
|
||
T_used = Σ t_i (sum of all scheduled task durations)
|
||
headroom = T_available - T_used
|
||
|
||
When T_used > T_available:
|
||
→ exec drops tasks with lowest priority
|
||
→ T_used ← T_used - t_lowest
|
||
→ repeat until T_used ≤ T_available
|
||
→ ALARM 1201 (flag set)
|
||
</div>
|
||
|
||
<p>In the Apollo 11 descent, the radar interrupts pushed T_used above 20 ms. The executive shed tasks until headroom returned to ≥ 0. The throughput equation for the landing trajectory computation remained intact because it was high-priority — it never got dropped. The dropped tasks were display refresh and non-critical calculations.</p>
|
||
|
||
<p>This is the exact same pattern as <a href="render-farm-capacity-planner.html">capacity-planner.html</a>: when demand exceeds capacity, you shed low-priority work to preserve the critical path. The AGC just did it in 1969 with a wire-rommed executive table instead of a Kubernetes job queue.</p>
|
||
</section>
|
||
|
||
<section>
|
||
<h2>05 / COMPARISON: AGC vs. MODERN RTOS</h2>
|
||
<p>The <a href="https://www.wikidata.org/entity/Q213666" target="_blank">real-time operating system (Q213666)</a> concept existed in theory before Apollo, but the AGC executive was the first deployed at flight scale. Compare the architectures:</p>
|
||
|
||
<table class="spec-table">
|
||
<tr><th>FREQUENCY</th><th>AGC EXEC 1</th><th>MODERN RTOS (CYCLONE)</th></tr>
|
||
<tr><td>CYCLE</td><td>20 ms fixed</td><td>configurable 1-100 ms</td></tr>
|
||
<tr><td>PRIORITY</td><td>5 levels (hard-coded)</td><td>configurable 0-255</td></tr>
|
||
<tr><td>PREENPTION</td><td>by level only</td><td>by level + FIFO within level</td></tr>
|
||
<tr><td>OVERLOAD</td><td>drop lowest tasks + alarm</td><td>drop lowest + configurable policy</td></tr>
|
||
<tr><td>MEMORY</td><td>72 KB, no allocation</td><td>static allocation, bounded</td></tr>
|
||
</table>
|
||
|
||
<p>The principles are identical. The difference is that modern RTOSes are parameterized; the AGC was parameterized by hand in the executive tables.</p>
|
||
</section>
|
||
|
||
<section>
|
||
<h2>06 / WHY THIS MATTERS</h2>
|
||
<p>Every render farm scheduler, every real-time pipeline, every task queue is a descendant of the AGC executive. The cyclic executive pattern — fixed intervals, priority-based preemption, deterministic budgeting — is the oldest and most reliable scheduling architecture in flight-critical systems. It survives because it's provably schedulable.</p>
|
||
|
||
<p>If you're building any system where a missed deadline matters, the AGC executive is still your reference architecture. Sixty years on, no one has improved the basic topology. They've only added more knobs.</p>
|
||
</section>
|
||
|
||
<section>
|
||
<h2>RELATED WORK</h2>
|
||
<p><a href="render-farm-theory.html">render-farm-theory.html</a> — throughput equations and the T=N×(F÷S)×3600 model</p>
|
||
<p><a href="fault-tree-analysis.html">fault-tree-analysis.html</a> — failure decomposition with SVG gate diagrams</p>
|
||
<p><a href="render-farm-calculator.html">render-farm-calculator.html</a> — interactive capacity calculator</p>
|
||
<p><a href="cluster-scaling.html">cluster-scaling.html</a> — linear scaling law proof</p>
|
||
|
||
<p class="json-link"><a href="agc-executive.json">agc-executive.json</a> — machine-readable task table and timing parameters</p>
|
||
</section>
|
||
|
||
<footer>
|
||
<p>stream.4ort.net/agc-executive.html — built 2026-07-22. Grounded in Q138875 (AGC), Q43653 (Apollo 11), Q213666 (RTOS). Source: <a href="https://github.com/chrislgarry/Apollo-11" target="_blank">Apollo-11 source repo</a>.</p>
|
||
</footer>
|
||
|
||
</body>
|
||
</html>
|