Module irq

Source
Expand description

Handling of Interrupt ReQuests (IRQs).

§Top vs bottom half

OSTD divides the handling of an IRQ into two parts: top half and bottom half.

A driver can assign to a target device an IRQ line, IrqLine, to which a callback function may be registered. When an IRQ arrives at an IRQ line, OSTD will invoke all the callbacks registered on the line, with all local IRQs on the CPU disabled. Thus, the IrqLine callbacks should be written as short as possible, performing the most critical tasks. This is the so-called top half of IRQ handling.

When the top half finishes, OSTD continues on the handling of the IRQ with the bottom half. The logic of the bottom half is specified by a callback function registered via register_bottom_half_handler_l1 (or register_bottom_half_handler_l2, as we will see later). The implementer of this callback function may re-enable local IRQs, thus allowing the less critical tasks performed in the bottom half to be preempted by the more critical ones done in the top half.

OSTD’s split of IRQ handling in top and bottom halves closely resembles that of Linux, but with a key difference: OSTD itself does not hardcode any concrete mechanisms for the bottom-half, e.g., Linux’s softirqs or tasklets. OSTD’s APIs are flexible and powerful enough to enable an OSTD-based kernel to implement such mechanisms itself. This design helps contain the size and complexity of OSTD.

§Nested interrupts

OSTD allows interrupts to be nested. The top-half for handling nested interrupts are still done by IrqLine callbacks, yet the bottom-half logic is done by a new callback registered via register_bottom_half_handler_l2, rather than register_bottom_half_handler_l1.

We introduce the concept of interrupt level to mark the nesting depth of interrupts. InterruptLevel::current keeps track of the current nesting depth on the CPU where the code is executing. There are three interrupt levels:

  • Level 0 (Task Context): Normal execution for a kernel or user task. Code at this level can be preempted by a hardware interrupt.

  • Level 1 (Interrupt Context): Entered when an interrupt preempts task context code. Interrupt handling callbacks that may be invoked at this level are:

  • Level 2 (Nested Interrupt Context): The maximum nesting level, entered when a level 1 bottom-half callback (registered via register_bottom_half_handler_l1) is interrupted. IrqLine callbacks always have IRQ disabled; thus, they can never be preempted.

    Interrupt handling callbacks that may be invoked at this level are:

    At this level, all local IRQs are disabled to prevent further nesting.

Structs§

DisabledLocalIrqGuard
A guard for disabled local IRQs.
IrqLine
An Interrupt ReQuest (IRQ) line.

Enums§

InterruptLevel
The current interrupt level on a CPU.

Functions§

disable_local
Disables all IRQs on the current CPU (i.e., locally).
register_bottom_half_handler_l1
Registers a bottom half callback to be executed at interrupt level 1.
register_bottom_half_handler_l2
Registers a bottom half callback to be executed at interrupt level 2.

Type Aliases§

IrqCallbackFunction
A type alias for the IRQ callback function.