Saturday, 21 July 2018

Linux Kernel Interrupts

An interrupt is produced by electronic signals from hardware devices and directed into input pins on an interrupt controller (a simple chip that multiplexes multiple interrupt lines into a single line to the processor). These are the process that will be done by kernel.
  1. Upon receiving an interrupt, the interrupt controller sends a signal to the processor.
  2. The processor detects this signal and interrupts its current execution to handle the interrupt.
  3. The processor can then notify the operating system that an interrupt has occurred, and the operating system can handle the interrupt appropriately.
Interrupt handling is amongst the most sensitive tasks performed by kernel and it must satisfy following:
  1. Hardware devices generate interrupts asynchronously (with respect to the processor clock). That means interrupts can come anytime.
  2. Because interrupts can come anytime, the kernel might be handling one of them while another one (of a different type) occurs.
  3. Some critical regions exist inside the kernel code where interrupts must be disabled. Such critical regions must be limited as much as possible.

Interrupts and Exceptions

Unlike interrupts, exceptions occur synchronously with respect to the processor clock; they are often called synchronous interrupts.
Exceptions are produced by the processor while executing instructions either in response to a programming error (e.g. divide by zero) or abnormal conditions that must be handled by the kernel (e.g. a page fault). 
Interrupts: asynchronous interrupts generated by hardware.
Exceptions: synchronous interrupts generated by the processor.
System calls (one type of exception) on the x86 architecture are implemented by the issuance of a software interrupt, which traps into the kernel and causes execution of a special system call handler. 

Interrupts

Maskable – All Interrupt Requests (IRQs) issued by I/O devices give rise to maskable interrupts. A maskable interrupt can be in two states: masked or unmasked; a masked interrupt is ignored by the control unit as long as it remains masked.
Nonmaskable – Only a few critical events (such as hardware failures) give rise to nonmaskable interrupts. Nonmaskable interrupts are always recognized by the CPU.

Exceptions

Falts – Like Divide by zero, Page Fault, Segmentation Fault.
Traps – Reported immediately following the execution of the trapping instruction. Like Breakpoints.
Aborts – Aborts are used to report severe errors, such as hardware failures and invalid or inconsistent values in system tables.

Interrupt handler

An interrupt handler or interrupt service routine (ISR) is the function that the kernel runs in response to a specific interrupt:
  1. Each device that generates interrupts has an associated interrupt handler.
  2. The interrupt handler for a device is part of the device’s driver (the kernel code that manages the device).
What differentiates interrupt handlers from other kernel functions is that the kernel invokes them in response to interrupts and that they run in a special context called interrupt context. This special context is occasionally called atomic context because code executing in this context is unable to block.

Process Context and Interrupt Context

Kernel code running in process context is preemptible. An interrupt context, however, always runs to completion and is not preemptible.

Because of this, there are restrictions on what can be done from interrupt context. Code executing from interrupt context cannot do the following:
  1. Go to sleep or relinquish the processor
  2. Acquire a mutex
  3. Perform time-consuming tasks
  4. Access user space virtual memory

Based on our idea, ISR or Interrupt Handler should be execute very quickly and it should not run for more time.
What if, I want to do huge amount of work upon receiving interrupt? So it is a problem right? If we do like that this will happen.
  1. While ISR run, it doesn’t let other interrupts to run (interrupts with higher priority will run).
  2. Interrupts with same type will be missed.
To eliminate that problem, the processing of interrupts is split into two parts, or halves:
  1. Top halves
  2. Bottom halves

    Top half

    The interrupt handler is the top half. The top half will run immediately upon receipt of the interrupt and performs only the work that is time-critical, such as acknowledging receipt of the interrupt or resetting the hardware.

    Bottom half

    A bottom half is used to process data, letting the top half to deal with new incoming interrupts. Interrupts are enabled when a bottom half runs.
    For example using the network card:
    • When network cards receive packets from the network, the network cards immediately issue an interrupt. This optimizes network throughput and latency and avoids timeouts.
    • The kernel responds by executing the network card’s registered interrupt.
    • The interrupt runs, acknowledges the hardware, copies the new networking packets into main memory, and readies the network card for more packets. These jobs are the important, time-critical, and hardware-specific work.
      • The kernel generally needs to quickly copy the networking packet into main memory because the network data buffer on the networking card is fixed and miniscule in size, particularly compared to main memory. Delays in copying the packets can result in a buffer overrun, with incoming packets overwhelming the networking card’s buffer and thus packets being dropped.
      • After the networking data is safely in the main memory, the interrupt’s job is done, and it can return control of the system to whatever code was interrupted when the interrupt was generated.
    • The rest of the processing and handling of the packets occurs later, in the bottom half.





    There are 4 bottom half mechanisms are available in Linux:
    1. Work-queue
    2. Threaded IRQs
    3. Softirqs
    4. Tasklets










No comments:

Post a Comment