Chapter 13 Interrupt Handlers
Chapter 13 Interrupt Handlers
Interrupts are signals that cause the computer's central processing unit to suspend what it is doing and transfer
to a program called an interrupt handler. Special hardware mechanisms that are designed for maximum speed
force the transfer. The interrupt handler determines the cause of the interrupt, takes the appropriate action, and
then returns control to the original process that was suspended.
Interrupts are typically caused by events external to the central processor that require immediate attention, such
as the following:
þ Completion of an I/O operation
þ Detection of a hardware failure
þ "Catastrophes" (power failures, for example)
In order to service interrupts more efficiently, most modern processors support multiple interrupt types, or
levels. Each type usually has a reserved location in memory, called an interrupt vector that specifies where the
interrupt-handler program for that interrupt type is located.
This design speeds processing of an interrupt because the computer can transfer control directly to the
appropriate routine; it does not need a central routine that wastes precious machine cycles determining the
cause of the interrupt. The concept of interrupt types also allows interrupts to be prioritized, so that if several
interrupts occur simultaneously, the most important one can be processed first.
CPUs that support interrupts must also have the capability to block interrupts while they are executing critical
sections of code. Sometimes the CPU can block interrupt levels selectively, but more frequently the effect is
global. While an interrupt is being serviced, the CPU masks all other interrupts of the same or lower priority
until the active handler has completed its execution; similarly, it can preempt the execution of a handler if a
different interrupt with higher priority requires service.
Some CPUs can even draw a distinction between selectively masking interrupts (they are recognized, but their
processing is deferred) and simply disabling them (the interrupt is thrown away).
The creation of interrupt handlers has traditionally been considered one of the most arcane of programming
tasks, suitable only for the elite cadre of system hackers. In reality, writing an interrupt handler is, in itself,
straightforward. Although the exact procedure must, of course, be customized for the characteristics of the
particular CPU and operating system, the guidelines on the following page are applicable to almost any
Computer system.
A program preparing to handle interrupts must do the following:
1. Disable interrupts, if they were previously enabled, to prevent them from occurring while interrupt vectors
are being modified.
2. Initialize the vector for the interrupt of interest to point to the program's interrupt handler.
3. Ensure that, if interrupts were previously disabled, all other vectors point to some valid handler routine.
4. Enable interrupts again.
The interrupt handler itself must follow a simple but rigid sequence of steps:
1. Save the system context (registers, flags, and anything else that the handler will modify and that wasn't
saved automatically by the CPU).
2. Block any interrupts that might cause interference if they were allowed to occur during this handler's
processing. (This is often done automatically by the computer hardware.)
3. Enable any interrupts that should still be allowed to occur during this handler's processing.
4. Determine the cause of the interrupt.
5. Take the appropriate action for the interrupt: receive and store data from the serial port, set a flag to indicate
the completion of a disk-sector transfer, and so forth.
6. Restore the system context.
7. Reenable any interrupt levels that were blocked during this handler's execution.
8. Resume execution of the interrupted process.
As in writing any other program, the key to success in writing an interrupt handler is to program defensively
and cover all the bases. The main reason interrupt handlers have acquired such a mystical reputation is that
they are so difficult to debug when they contain obscure errors.
Because interrupts can occur asynchronously that is, because they can be caused by external events without
regard to the state of the currently executing process bugs in interrupt handlers can cause the system as a whole
to behave quite unpredictably.
Interrupts and the Intel 80x86 Family The Intel 80x86 family of microprocessors supports 256 levels of
prioritized interrupts, which can be triggered by three types of events:
þ Internal hardware interrupts
þ External hardware interrupts
þ Software interrupts
Software Interrupts
Any program can trigger software interrupts synchronously simply by executing an INT instruction. MS-DOS
uses Interrupts 20H through 3FH to communicate with its modules and with application programs. (For
instance,the MS-DOS function dispatcher is reached by executing an Int 21H.) The IBM PC ROM BIOS and
application software use other interrupts, with either higher or lower numbers, for various purposes (Figure 13-
2). These assignments are simply conventions and are not wired into the hardware in any way.
Interrupt Usage Machine
Figure 13-2. Interrupts with special significance on the IBM PC, PC/AT,and PS/2 and compatible computers.
Note that the IBM ROM BIOS uses several interrupts in the range 00HÄ1FH, even though they were reserved
by Intel for CPU faults. IRQ numbers refer to Intel 8259A PIC priority levels.
Servicing an Interrupt
When the CPU senses an interrupt, it pushes the program status word (which
defines the various CPU flags), the code segment (CS) register, and the
instruction pointer (IP) onto the machine stack and disables the interrupt
system. It then uses the 8-bit number that was jammed onto the system bus
by the interrupting device to fetch the address of the handler from the
vector table and resumes execution at that address.
Usually the handler immediately reenables the interrupt system (to allow
higher-priority interrupts to occur), saves any registers it is going to
use, and then processes the interrupt as quickly as possible. Some
external devices also require a special acknowledgment signal so that they
will know the interrupt has been recognized.
If the interrupt was funneled through an 8259A PIC, the handler must send
a special code called end of interrupt (EOI) to the PIC through its
control port to tell it when interrupt processing is completed. (The EOI
has no effect on the CPU itself.) Finally, the handler executes the
special IRET (INTERRUPT RETURN) instruction that restores the original
state of the CPU flags, the CS register, and the instruction pointer.
Whether an interrupt was triggered by an external device or forced by
software execution of an INT instruction, there is no discernible
difference in the system state at the time the interrupt handler receives
control. This fact is convenient when you are writing and testing external
interrupt handlers because you can debug them to a large extent simply by
invoking them with software drivers.
In real life, the interrupt handler would need to save
and restore only the registers that it actually modified. Also, if the
handler made extensive use of the machine stack, it would need to save and
restore the SS and SP registers of the interrupted process and use its own
local stack.