About Interrupt Nesting:
In the Linux kernel, if the driver does not specifically specify when the application is interrupted, the DO_IRQ is interrupted when the interrupt response is made, and if the interruption of the same device or the interruption of different devices occurs during the execution of the drive interrupt handler, the new interrupt is immediately processed. Or be pending, wait until the current interrupt processing completes, then do processing.
In the 2.4 and 2.6 cores, there is no difference between this piece.
When a general application is interrupted, a break is allowed, that is, the SA_INTERRUPT flag is not used. If sharing is allowed, add Sa_shirq, and add the SA_SAMPLE_RANDOM flag if you can provide entropy for the kernel entropy pool (for example, if you write a driver that is a driver like the IDE). This is an ordinary interrupt request process. For this general scenario, the kernel can be preempted whenever an interrupt occurs, even if the kernel is performing other interrupt functions. Here are two notes: First, because Linux does not support interrupt prioritization, any interrupts can preempt other interrupts, but the same type of interrupts (that is, the definition of interrupts using the same interrupt line) will not preempt preemption, and they will be invoked in turn when performing this type of interruption. The second is the so-called "as long as the interruption, you can preempt the kernel" there is a certain limit, because when the interruption occurs when the system by the interrupt door into the automatic shutdown interrupt (for the x86 platform is the EFlags register if position is 0), only if the interrupt function is executed (handle_irq_event ) in the process of opening a break before preemption. For the same type of interrupts, because they use the same IDT table entry, their status flags (Irq_pending and irq_inprogress) prevent the execution of the same type of interrupt functions (note: To prevent handle_irq_event from being reentrant, rather than to prevent do_ IRQ functions are reentrant, and can be nested freely for different interrupts. Thus, the so-called interrupt nesting is free to nest for different interrupts, and for the same type of interrupts, it cannot be nested.
Here's a quick explanation of how to use the status flag to prevent reentrant interrupts of the same type:
When a type of interrupt occurs for the first time, it is given the irq_pending flag on the state bit of the IDT table entry, indicating that it is pending. The interrupt handler function is then set to NULL, and then because its state does not have a irq_inprogress flag (first), it is placed on the irq_inprogress and places the irq_pending flag, At the same time, the action is given a corresponding interrupt handler function pointer (here is a focus, Linux is a clever use, then explained). In this way, the following can be successfully executed handle_irq_event for interrupt processing, when the interruption in the handle_irq_event, if there is the same type of interruption occurs, then re-enter the DO_IRQ function, and then its state position with the irq_pending flag, However, because the irq_inprogress that was added in the previous interrupt processing is not cleared, the irq_pending flag cannot be cleared here, so the action is null so that the Handle_irq_event function cannot be executed again. To exit this interrupt processing, return to the last interrupt handler function, that is, continue to execute the Handle_irq_event function. When the handle_irq_event returns, check the irq_pending flag and find this flag, indicating that the handle_irq_event was interrupted during execution, and that there was an unhandled kind of interruption, so the handle_irq_event function was cycled again. Until no irq_pending flag exists.
The difference between 2.4 and 2.6, as far as I can see, is mainly in the 2.6 of one into the DO_IRQ, a bit more to shut down the kernel preemption of the action, while in the processing of a irq_per_cpu type of interruption of the processing, the other not much change. Such irq_per_cpu interrupts are primarily used in SMP environments to bind interrupts to a given CPU. For example, when initializing a IPI interrupt in a openpic_init in ARCH/PPC/SYSLIB/OPEN_PIC.C.
In a nutshell, interrupts can be nested, but the same type of interrupts cannot be nested because interrupts occur on an IRQ, which is shielded during the interruption of the response, which means that the interrupt of this IRQ is not found.
At the same time, the interrupt is forbidden in the critical area of the kernel.
About DO_IRQ may lose interrupt Request:
The DO_IRQ function is to determine whether or not there is an interrupt request for the same channel that has not been processed after the Handle_irq_event function has been executed to determine whether the status is set to the Irq_pending flag. However, this method can only determine whether there is, and not know how many unhandled unified channel interrupt requests. That is, if two or more interrupt requests for the same channel come in the first interrupt request to perform the Handle_irq_event function, and those interrupts do not come back, then simply determine whether the status is set by Irq_ The pending flag does not know how many unhandled interrupts are in the end, Handle_irq_event will only be executed again.
Is that a bug? Do not count, as long as you know there is no deal with the interruption OK, know 1 and know N, is essentially the same. As an external device, you should be able to handle situations where your own interrupts have not been addressed.
It is not possible to lose, in each of the structure of the break descriptor, there is a linked list, the list of services to store the program
Several important concepts and relationships used in interrupts:
I. Basic CONCEPTS
1.
|
The resulting position |
Time to happen |
Timing |
Interrupt |
External CPU |
Random |
Asynchronous |
Abnormal |
The program that the CPU is executing |
After an instruction terminates execution |
Synchronous |
2. Code executed by interrupt or exception is not a process, but a kernel control path that represents the execution of the process that is running when the interrupt occurs
The interrupt handler has nothing to do with the running program
The process that causes the exception handler is exactly the current process of the exception handler at run time
Second, characteristics
1. (1) as fast as possible
(2) can be executed in a nested manner, but the same type of interrupts cannot be nested
(3) Limit the critical section as much as possible, because in the critical section, the interruption is prohibited
2. Most of the anomalies occur in the user state, the exception is the only occurrence of the kernel state can trigger the exception
The fault page exception means that the process is switched, so the interrupt handler never executes the action that can cause the page fault
3. Interrupt handler running in kernel state
When the interrupt occurs in the user state, the process's user space stack is switched to the process's system space stack, and the kernel stack is empty as soon as it is switched
When interrupts occur in the kernel state, there is no need to switch the stack space
Third, classification
1. Interrupt classification: Can be shielded from interruption, not shielded interrupt
2. Classification of anomalies:
Classification |
Ways to resolve exceptions |
Example |
Fault |
That instruction will be executed again. |
Page Faults exception handler |
Trap |
Will proceed from the next instruction |
Debug Programs |
Abnormal abort |
Forcing the affected process to terminate |
There's been a serious mistake. |
Four, IRQ
1. The hardware Device controller interrupts the CPU through the IRQ line, and can be shielded from interruption by disabling an IRQ line.
2. Prohibited interrupts will not be lost, after activating IRQ, interrupts will also be sent to the CPU
3. Activate/disable IRQ line!= Global Shield/non-masking for masking interrupts
You can selectively prohibit each IRQ line. Therefore, you can program pic to disallow IRQ, that is, you can tell pic to stop breaking or activate a given IRQ line release. Blocked interrupts are not lost, and once they are activated, pic sends them to the CPU. This feature is used by most interrupt handlers because it allows the interrupt handler to process the same type of IRQ successively
Suppose the CPU has an active IRQ line. A hardware device appears on this IRQ thread, and the multiple APIC system chooses to interrupt our CPU processing. The IRQ line is blocked by another CPU before the CPU response is interrupted; As a result, the IRQ_DISABLED flag is set. Our CPU then begins to handle the pending interrupts; therefore, the DO_IRQ () function answers the interrupt and then returns, but does not perform the interrupt service routine because it finds that the irq_disabled flag is set, so the interrupts that occur before the IRQ line is disabled are lost.
To cope with this situation, the ENABLE_IRQ () function that the kernel uses to activate the IRQ line first checks to see if the interrupt is lost, and if so, the function forces the hardware to cause the lost interrupt to occur again
Their biggest difference is that the upper part is not interrupted and the lower half is interrupted