# WAITLIST System in the Apollo Guidance Computer (AGC): The Native Delayed-Task Scheduler

> Discover the Apollo Guidance Computer's WAITLIST system, the native delayed-task scheduler. Execute programs with precise centisecond delays for deterministic real-time guidance.

- Repository: [Chris Garry/Apollo-11](https://github.com/chrislgarry/Apollo-11)
- Tags: internals
- Published: 2026-03-04

---

**The WAITLIST system is the Apollo Guidance Computer's native delayed-task scheduler that queues programs to execute after precise centisecond delays without busy-waiting, enabling deterministic real-time guidance operations.**

The WAITLIST subsystem in the LM (Luminary) AGC allows guidance software to schedule future tasks with millisecond precision. As implemented in the `chrislgarry/Apollo-11` repository, this mechanism maintains a sorted queue of pending operations, freeing the processor for continuous navigation calculations rather than wasting cycles on busy-waiting loops.

## Architecture of the WAITLIST Scheduler

The WAITLIST system maintains two parallel erase-mode lists in memory to track pending operations. According to the source in `Luminary099/WAITLIST.agc`, these structures handle up to nine simultaneous delayed tasks.

### Task Queue Structure (LST1 and LST2)

The scheduler uses a dual-list architecture to separate timing data from executable addresses:

- **LST1**: Contains the *relative* delay values (in centiseconds) for up to nine pending tasks, stored as sorted offsets from the current time.
- **LST2**: Holds the corresponding **2CADR** (2-word addresses) of those tasks, allowing the dispatcher to locate the executable code when delays expire.

When a new task enters the queue, the system inserts it into the sorted position and adjusts the remaining delays for subsequent entries to maintain accurate relative timing.

### Time Base and Precision

The WAITLIST system operates on a centisecond granularity (1 cs = 0.01 s) using the **TIME3** accumulator. As defined in the source code, TIME3 counts down from 16384 centiseconds (approximately 162.5 seconds). The scheduler calculates delay values using the formula `C(TIME3) = 16384 - (T1 - T)`, where *T* represents the current time and *T1* the target execution time.

## How WAITLIST Schedules Tasks

Software modules invoke the scheduler through a standardized calling convention that places the delay in the accumulator and follows with the task address.

### Standard WAITLIST Calling Sequence

A typical invocation follows this exact sequence documented in `Luminary099/WAITLIST.agc` (lines 64-70):

```assembly
; L = address of the task to start (2-CADR)
; A = delay in centiseconds (Δt)
L-1    CA   DELTAT          ; Δt = time until task start
L      TC   WAITLIST        ; queue the task
L+1    2CADR DESIRED_TASK   ; high word of task address
L+2    (MINOR OF 2CADR)    ; low word (often 0)
L+3    RELINT             ; return here after insertion

```

The `WAITLIST` routine inserts the new entry into the sorted list, adjusting remaining delays for existing entries to maintain the relative timebase.

### The TWIDDLE Optimization for Same-Bank Tasks

When the target task resides in the same memory bank as the caller, the **TWIDDLE** pseudo-instruction provides a space optimization. As implemented in `Luminary099/WAITLIST.agc` (lines 71-78), TWIDDLE encodes the address directly rather than using the split 2CADR format, saving one word of memory:

```assembly
L-1    CA   DELTAT
L      TC   TWIDDLE          ; same-bank optimisation
L+1    ADRES DESIRED_TASK   ; full address (no 2-CADR split)
L+2    RELINT

```

TWIDDLE otherwise behaves identically to the standard WAITLIST call, entering the task into the same LST1/LST2 queues.

## Task Dispatch and Execution

Once queued, tasks await execution through a hardware-triggered interrupt mechanism that guarantees deterministic timing for critical guidance functions.

### T3RUPT Interrupt Handling

The **T3RUPT** interrupt—triggered by the 3-second "RUPT" clock—scans the head of the WAITLIST queue during each period. If the earliest entry's delay has elapsed, the interrupt handler dequeues the task, restores its 2CADR from LST2, and branches to it using `DCS ENDTASK`. This dispatch logic appears in `Luminary099/WAITLIST.agc` (lines 78-94) and `Luminary099/T3RUPT_PROGRAM.agc`.

### Interrupt-Inhibited Execution Model

All tasks scheduled through WAITLIST execute with **interrupts inhibited**, as explicitly documented in the source (lines 58-63 of `Luminary099/WAITLIST.agc`). This design choice guarantees deterministic timing for critical guidance functions by preventing higher-priority interrupts from preempting time-sensitive operations.

### Overflow Protection

The system enforces a hard limit of nine concurrent tasks. If software attempts to queue a tenth task, the scheduler triggers a special abort with code **OCT 1203 — WAITLIST OVERFLOW** (lines 84-87), preventing memory corruption in the fixed-size LST1/LST2 buffers.

## Integration with Delay Routines

Higher-level timing utilities `FIXDELAY` and `VARDELAY` provide convenient wrappers around the core WAITLIST mechanism. These helper routines, defined in `Luminary099/WAITLIST.agc` (lines 51-57), invoke the scheduler under the same control flow but accept either fixed or variable delay parameters for auxiliary functions.

Additional integration points appear in `Luminary099/LONGCALL.agc`, which schedules tasks via WAITLIST or TWIDDLE depending on address space requirements, and `Luminary099/RESTARTS_ROUTINE.agc`, which distinguishes WAITLIST calls from other restart types during system recovery.

## Summary

- **WAITLIST** serves as the AGC's deterministic delayed-task scheduler, managing execution timing without busy-waiting.
- The system maintains two sorted erase-mode lists (**LST1** for delays, **LST2** for 2CADR addresses) supporting up to nine concurrent tasks.
- Tasks are queued via `TC WAITLIST` with delays specified in centiseconds, or via **TWIDDLE** for same-bank optimizations.
- The **T3RUPT** interrupt dispatches ready tasks while the **TIME3** accumulator provides the 16384-centisecond timing base.
- Execution occurs with interrupts inhibited to ensure deterministic guidance calculations, with **OCT 1203** aborts preventing queue overflow.

## Frequently Asked Questions

### How does the WAITLIST system differ from modern operating system timers?

Unlike modern preemptive multitasking systems, the AGC's WAITLIST operates as a cooperative, interrupt-inhibited scheduler with fixed queue slots. It lacks process isolation and priority inheritance, instead offering deterministic, millisecond-precision timing specifically optimized for the LM's guidance calculations. The system maintains hardware-level control through the TIME3 accumulator rather than software clock interrupts.

### What happens when the WAITLIST queue fills up?

When software attempts to schedule a tenth concurrent task, the system generates an **OCT 1203** abort code labeled "WAITLIST OVERFLOW" and halts execution. This hard limit protects the fixed-size LST1 and LST2 erase-mode buffers from corruption. Mission software was designed to avoid this condition through careful scheduling analysis during development.

### Why does the WAITLIST system use centiseconds instead of milliseconds?

The centisecond granularity (0.01 seconds) represents a compromise between timing precision and computational overhead suitable for 1960s hardware. The **TIME3** accumulator's 16384-centisecond range (approximately 162.5 seconds) provides sufficient duration for lunar descent phases while minimizing the interrupt frequency required to update the countdown timer.

### Can WAITLIST tasks themselves schedule additional WAITLIST calls?

Yes, tasks executing under WAITLIST control can recursively invoke the scheduler to chain subsequent operations. Because tasks run with interrupts inhibited, they must complete quickly to avoid delaying the T3RUPT handler. The `TASKOVER.agc` module manages proper cleanup and return to the scheduler, enabling complex sequenced operations during critical flight phases.