Linux Core - Interrupt

Top Half v.s. Botton Half

APIC - Advanced Programmable Interrupt Controller - is a internal device to handle interrupt for ARM chip.

Top Half

ISR - Interrupt Service Routine address is stored in the Interrupt Vector Table

The top half is the interrupt handler, and it:[1][2]

An interrupt handler needs to be registered during initialization, and deregistered during cleanup.

#include <linux/interrupt.h>

int request_irq(unsigned int irq, irq_handler_t hander,
			   unsigned long flags, const char* name, void *dev);

and to remove an interrupt handler:

#include <linux/interrupt.h>

void free_irq(unsigned int irq, void *dev);

Botton Half

The linux bottom half mechanism are provided below:

space allocation Scheduling Priority Context
SoftIRQ static defined High Interrupt
Tasklet dynamic registered medium Interrupt
Work Queue dynamic registered medium Process

softirq

how-softirq-works-in-kernel.png

The same type of softirq can run on different processors simultanaeously. However, particular softirq (of the same type) cannot run concurrently on two processors, this ensures that there is no race condition.

How many available softirqs?

From kernel 5.10, here's all available pre-defined softirqs

// include/linux/interrupt.h

enum {
    HI_SOFTIRQ=0,          
    TIMER_SOFTIRQ,         // timer
    NET_TX_SOFTIRQ,        // networking
    NET_RX_SOFTIRQ,        // networking
    BLOCK_SOFTIRQ,         // IO
    IRQ_POLL_SOFTIRQ,
    TASKLET_SOFTIRQ,       // tasklet
    SCHED_SOFTIRQ,         // schedule
    HRTIMER_SOFTIRQ,       // timer
    RCU_SOFTIRQ,           // lock
    NR_SOFTIRQS
};

ksoftirqd

In most cases, softirqs are scheduled in hardware interrupts, which may arrive very quickly, faster than they can be serviced. They are then queued (softirq is labeled as defered) by the kernel in order to be processed later. ksoftirqd are responsible for late execution (process context). A ksoftirqd is per-CPU kernel thread raised to handle unserved software interrupts.[3][4][5][6]

example:

static void run_ksoftirqd(unsigned int cpu) {
	local_irq_disable();
	if (local_softirq_pending()) {
		__do_softirq();
		rcp_note_context_switch(cpu);
		local_irq_enable();
		cond_resched();
		return;
	}
	local_irq_enable();
}
cwyark@roscube-test:~$ ps aux | grep ksoft
root          13  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/0]
root          22  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/1]
root          28  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/2]
root          34  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/3]
root          40  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/4]
root          46  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/5]
root          52  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/6]
root          58  0.0  0.0      0     0 ?        S    23:24   0:00 [ksoftirqd/7]

TaskLet

tasklet in linux is a lightweight, bottom-half mechanism for deferring work to be execute later in a context where it is safe to perform tasks that might sleep or take a long time to complete.

tasklets are non-preemptive, once a tasklet starts running, it runs to completion without being interrupted by other tasklets. however, tasklets can be preempted by softirqs, hard IRQs and kernel preemption.

Tasklets are executed on the same CPU where they were scheduled, and they run in interrupt context.

Bottom Half Multiple Processor
softirq 相同性質的softirq可在不同處理器上同時執行、但是無法由多個處理器一起執行一個softirq
tasklet 同性質的tasklet不能同時執行

here's a reference [7]

Pasted image 20240123225610.png

Work Queue

work queue is more flexible than tasklet and can be created dynamically at runtime. It runs in process context, not in interrupt context, which means it can sleep, perform file I/O, and wait on semaphores, operations that is not possible in softirq or tasklet.

worker queues are managed by kworker threads within the kernel.

Scheduler deferred mechanism
kworker work queues
ksoftirqd softirqs

  1. https://www.cs.otago.ac.nz/cosc440/labs/lab08.pdf ↩︎

  2. https://hackmd.io/@RinHizakura/B14d-o24v ↩︎

  3. https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s07.html ↩︎

  4. https://zhuanlan.zhihu.com/p/80680484 ↩︎

  5. https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-9.html ↩︎

  6. https://arthurchiao.art/blog/linux-irq-softirq-zh/#使用场景 ↩︎

  7. https://hackmd.io/@sysprog/linux-interrupt ↩︎