Interrupts and DMA: Asynchronous Magic

[!NOTE] The Problem of Speed The CPU runs at 3 GHz (3 billion cycles/sec). A hard disk seek takes 5 ms (15 million cycles). If the CPU waits for the disk, it wastes 15 million cycles doing nothing.

This chapter explains how the OS avoids waiting.


1. The Evolution of Waiting

A. Polling (Busy Waiting)

The CPU constantly checks the device status register. while (device.status ≠ READY);

  • Analogy: “Are we there yet? Are we there yet?”
  • Pros: Zero latency reaction (good for ultra-fast devices).
  • Cons: Wastes 100% CPU.

B. Interrupts (Event Driven)

The CPU sends a command and goes to sleep (or runs another process). When the device is done, it sends an electrical signal (IRQ).

  • Analogy: Setting a timer on the oven and watching TV.
  • Mechanism:
    1. Device pulls IRQ line high.
    2. CPU pauses execution.
    3. CPU looks up the Interrupt Vector Table (IVT) or IDT.
    4. CPU jumps to the Interrupt Service Routine (ISR).

C. DMA (Direct Memory Access)

For large transfers, even interrupts are too slow (one interrupt per byte?). DMA allows the device to write directly to RAM.

  • Analogy: Hiring a moving company (DMA) to move your furniture while you work, instead of carrying every box yourself.

2. Interactive: CPU Timeline Visualizer

See how much “Green” (Useful Work) the CPU gets done in each mode.

User App Waiting/Stalled ISR/Overhead
Select a mode to run simulation...

3. Advanced Concepts

The Cost of Interrupts

Interrupts are not free. They cause a Context Switch:

  1. Flush CPU Pipeline.
  2. Save registers to stack.
  3. Pollute L1/L2 Caches.

Top Half vs Bottom Half: To minimize this cost, Linux splits ISRs:

  • Top Half: Acknowledge hardware, copy small data, schedule work. (Fast, Interrupts Disabled).
  • Bottom Half: Process data, traverse protocols. (Slower, Interrupts Enabled).

Scatter-Gather DMA

Instead of copying one contiguous block, the DMA controller can read a “Scatter List” of pointers and fill non-contiguous memory pages in one go. This is crucial for Zero Copy networking.


4. Code Example: Java NIO (DMA Abstraction)

In high-level languages, we don’t program the DMA controller directly. However, APIs like Java NIO ByteBuffer allow us to use Direct Memory, which the OS can use for DMA without copying to the JVM Heap.

```java import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class DMAExample { public static void main(String[] args) throws Exception { RandomAccessFile file = new RandomAccessFile("data.bin", "rw"); FileChannel channel = file.getChannel(); // allocateDirect asks the OS for off-heap memory. // This memory allows "Zero Copy" DMA transfers. // If we used allocate(), the JVM would have to copy // data from the heap to a temp buffer before I/O. ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024); // 1MB System.out.println("Starting DMA Read..."); // This read operation maps to a scatter-gather DMA op // at the kernel level (if supported). // The CPU is free to run other threads while this happens. int bytesRead = channel.read(buffer); System.out.println("DMA Complete. Bytes: " + bytesRead); buffer.flip(); channel.close(); file.close(); } } ```