3.8 Modes of Transfer
Data transfers between the CPU, memory, and I/O devices are managed under distinct operational modes. Depending on whether the CPU is kept in a busy-wait state or interrupted asynchronously, the system balances timing overheads. This chapter explores Programmed I/O, Interrupt-Driven I/O, and Direct Memory Access.
Learning Objectives
- Define the three main modes of I/O transfer: Programmed I/O, Interrupt-Driven I/O, and Direct Memory Access (DMA).
- Explain the execution bottleneck of Programmed I/O (CPU is kept in a busy-wait polling loop).
- Compute the CPU time spent in polling loops given device data rates and CPU instruction execution speeds.
- Contrast Programmed I/O and Interrupt-Driven I/O in terms of CPU overhead and response latency.
- Evaluate the effectiveness of interrupt-driven transfers for low-speed devices (keyboard) vs. high-speed devices (disk).
Before studying this chapter, you should review Chapter 3.7: Asynchronous Transfer to understand handshake request/acknowledge lines.
1. Overview of I/O Transfer Modes
To coordinate data movements, the system employs three distinct software/hardware paradigms: - **Programmed I/O**: The CPU executes program loops to query device flags. - **Interrupt-Driven I/O**: Peripherals interrupt the CPU asynchronously, eliminating polling loops. - **Direct Memory Access (DMA)**: A dedicated hardware controller manages transfers directly with RAM, bypassing the CPU.
2. Programmed I/O & Busy-Wait Polling
In **Programmed I/O**, the CPU initiates I/O and then enters a **Polling Loop**, repeatedly reading the status register of the **IO Module** until the "Ready" flag is set:
POLL_LOOP: IN AL, STATUS_PORT ; Read Status Register
TEST AL, READY_FLAG ; Check Ready Bit
JZ POLL_LOOP ; Loop if not ready
IN AL, DATA_PORT ; Read Data Buffer
This busy-wait loop consumes $100\%$ of CPU execution cycles during the waiting period, creating a major performance bottleneck.
3. Interrupt-Driven I/O
**Interrupt-Driven I/O** frees the CPU. Instead of polling, the CPU continues normal instruction execution. When the peripheral is ready, the interface asserts the system Interrupt request line.
Upon detecting the interrupt, the CPU executes a **Context Switch**: 1. Completes the current instruction. 2. Pushes the Program Counter ($PC$) and Status Register ($PSW$) onto the Stack. 3. Loads the starting address of the **Interrupt Service Routine (ISR)**. 4. Executes the data transfer. 5. Restores context using a Return-from-Interrupt (`IRET`) opcode.
4. Worked Examples & Traces
Worked Example 3.8.1: CPU Polling Overhead Calculation
**Problem**: A keyboard transmits data at $20\text{ characters/second}$. The CPU operates at a clock speed of $20\text{ MHz}$ ($20,000,000\text{ cycles/second}$). To read each character, the CPU runs a programmed I/O loop: - The polling loop takes 50 clock cycles and runs continuously. - If the CPU spends $99.9\%$ of its time waiting for the character, trace the waste.
**Step-by-Step Calculation**:
- **Determine Time between Characters**: $$\text{Time} = \frac{1}{20\text{ characters/sec}} = 0.05\text{ seconds} = 50\text{ ms}$$
- **Calculate CPU Cycles in 50 ms**: $$\text{Cycles} = 0.05\text{ seconds} \times 20,000,000\text{ cycles/sec} = 1,000,000\text{ cycles}$$
- **Determine Polling Iterations**: $$\text{Iterations} = \frac{1,000,000\text{ cycles}}{50\text{ cycles/iteration}} = 20,000\text{ loop runs}$$
- **Verify Waste**: The CPU reads the status register $20,000$ times per character, executing $1,000,000$ cycles of redundant instruction fetches to retrieve a single byte, illustrating the programmed I/O bottleneck.
Worked Example 3.8.2: Interrupt Overhead vs. Polling
**Problem**: If the keyboard above is updated to use Interrupt-Driven I/O, where the context switch and ISR execution take a combined total of $400$ clock cycles, calculate CPU time overhead.
**Solution**: 1. Over a $1$-second period, $20$ interrupts occur. 2. Total CPU cycles consumed $= 20 \times 400 = 8,000\text{ cycles}$. 3. Percentage of CPU capacity spent on I/O: $$\text{Overhead} = \frac{8,000}{20,000,000} \times 100\% = 0.04\%$$ 4. **Conclusion**: Interrupt-Driven I/O frees $99.96\%$ of the CPU capacity to run user programs.
Common Mistakes to Avoid
- **Misestimating Interrupt Suitability**: Assuming interrupt-driven I/O is suitable for high-speed disk drives. If a disk transfers at $1\text{ MB/sec}$, context switching ($400$ cycles per byte) would require $400\text{ million CPU cycles/sec}$, saturating the CPU. High-speed transfers require DMA.
- **Forgetting context save**: Omitting the save of the flag register ($PSW$) during interrupt branching.
Revision Summary & Takeaways
- Programmed I/O keeps the CPU in a busy-wait polling loop.
- Interrupt I/O suspends the CPU asynchronously, saving context to branch to an ISR.
- Low-speed devices use interrupts, while high-speed devices require DMA.
We have seen how the CPU branches to an ISR when a single device asserts an interrupt. In Chapter 3.9: Priority Interrupts, we explore the hardware arbiter designs (Daisy Chaining and Parallel Priority Encoders) used to resolve conflicts when multiple devices assert interrupts simultaneously.
Check Your Understanding
References
- **ref-notes-syed-arsalaan**: Handwritten Lecture Notes, Page 99 (ISR Entry Context saving). [Local Verified]
- **ref-notes-class**: Class COA Lecture Notes, Page 50 (Programmed I/O Flowcharts). [Local Verified]
- **ref-book-stallings**: William Stallings, *Computer Organization and Architecture*, Chapter 7. [Pending Verification]
- **ref-lecture-sengupta-32**: Prof. Indranil Sengupta, NPTEL COA, Lecture 32 (Modes of Transfer). [Pending Verification]