Generally, interrupt types can be grouped into two categories:
□ Synchronous Interrupts and Exceptions — Are produced by the CPU itself and are directed at the program currently executing. Exceptions may be triggered for a variety of reasons: because of a programming error that occurred at run time (a classical example is division by zero), or because — as the name suggests — an exceptional situation or an anomalous condition has arisen and the processor needs "external" help to deal with it.
In the first case, the kernel must inform the application that an exception has arisen. It can use, for example, the signaling mechanism described in Chapter 5. This gives the application an opportunity to correct the error, issue an appropriate error message, or simply terminate.
An anomalous condition may not necessarily be caused directly by the process but must be repaired with the help of the kernel. A possible example of this is a page fault that always occurs when a process attempts to access a page of virtual address space that is not held in RAM. As discussed in Chapter 4, the kernel must then interact with the CPU to ensure that the desired data are fetched into RAM. The process can then resume at the point at which the exception occurred. It does not even notice that there has been a page error because the kernel recovered the situation automatically.
□ Asynchronous interrupts — Are the classical interrupt type generated by peripheral devices and occur at arbitrary times. Unlike synchronous interrupts, asynchronous interrupts are not associated with a particular process. They can happen at any time, regardless of the activities the system is currently performing.1
Network cards report the arrival of new packages by issuing an associated interrupt. Because the data reach the system at an arbitrary moment in time, it is highly likely that some process or other that has nothing to do with the data is currently executing. So as not to disadvantage this process, the kernel must ensure that the interrupt is processed as quickly as possible by "buffering" data so that CPU time can be returned to the process. This is why the kernel needs mechanisms to defer activities; these are also discussed in this chapter.
What are the common features of the two types of interrupt? If the CPU is not already in kernel mode, it initiates a switch from user to kernel mode. There it executes a special routine called an interrupt service
1 Because, as you will learn shortly, interrupts can be disabled, this statement is not totally correct. The system can at least influence when interrupts do not occur.
routine (ISR for short) or an interrupt handler. The purpose of this routine is to handle exception conditions or anomalous situations — after all, the specific goal of an interrupt is to draw the attention of the kernel to such changes.
A simple distinction between synchronous and asynchronous interrupts is not sufficient to fully describe the features of these two types of interrupt. A further aspect needs to be considered. Many interrupts can be disabled, but a few cannot. The latter category includes, for example, interrupts issued as a result of hardware faults or other system-critical events.
Wherever possible, the kernel tries to avoid disabling interrupts because they are obviously detrimental to system performance. However, there are occasions when it is essential to disable them to prevent the kernel itself from getting into serious trouble. As you will see when we take a closer look at interrupt handlers, major problems may arise in the kernel if a second interrupt occurs while a first interrupt is being handled. If the kernel is interrupted while processing what is already critical code, the synchronization problems discussed in Chapter 5 may arise. In the worst case scenario, this can provoke a kernel deadlock that renders the entire system unusable.
If the kernel allows itself too much time to process an ISR when interrupts are disabled, it can (and will) happen that interrupts are lost although they are essential for correct system operation. The kernel resolves this problem by enabling interrupt handlers to be divided into two parts — a performance-critical top half that executes with disabled interrupts, and a less important bottom half used later to perform all less important actions. Earlier kernel versions included a mechanism of the same name for deferring activities to a later time. However, this has been replaced by more efficient mechanisms, discussed below.
Each interrupt has a number. If interrupt number n is assigned to a network card and m = n is assigned to the SCSI controller, the kernel is able to differentiate between the two devices and call the corresponding ISR to perform a device-specific action. Of course, the same principle also applies for exceptions where different numbers designate different exceptions. Unfortunately, owing to specific (and usually historical) design ''features''(the IA-32 architecture is a particular case in point), the situation is not always as simple as just described. Because only very few numbers are available for hardware interrupts, they must be shared by several devices. On IA-32 processors, the maximum number is usually 15, not a particularly generous figure — especially considering that some interrupts are already permanently assigned to standard system components (keyboard, timers, etc.), thus restricting still further the number available for other peripheral devices.
This procedure is known as interrupt sharing.2 However, both hardware support and kernel support are needed to use this technique because it is necessary to identify the device from which an interrupt originates. This is covered in greater detail in this chapter.
Continue reading here: Hardware IRQs
Was this article helpful?