2023/1/17

Note of Linux bottom-half handling - Softirq, tasklet, workqueue, and threaded interrupt

最近因為手上的問題,花了些時間了解 Linux 上的 bottom-half 機制,記錄下看了甚麼。

重點整理

Softirq

  • Software Interrupt context
    • Enable handling of hardware interrupt
    • The timing of executing softirq handlers
      • (1) exit of HW ISR
      • (2) running at ksoftirqd
      • (3) explicitly call do_softirq
    • Not allowed bottom-half context switch
      • no sleep, no scheduling, and no user memory access
  • Normal priority kernel thread per CPU basis, i.e. ksoftirqd
    • ksoftirqd/n, n is the CPU number
  • Each softirq thread has the same softirq handler.
    • Softirq of the same type can run on multiple CPUs
      • Each CPU has a set of softirq pending status bits
      • The registered softirq handlers are shared by CPUs
    • When one softirq handler is running, another softirq handler can run on another CPU.
      • Disable local CPU bottom-half
      • Enable local CPU interrupt
  • Statically allocated. Only 10 softirqs by default. 
    • Has problem on loadable kernel module. Solved by using tasklet.
  • Postpone the user-space execution
    • softirq has time limit to prevent it's too long
  • Basis of tasklet

Tasklet

  • Implemented upon softirqs (tasklet_sofirq and hi_softirq)
  • Software Interrupt context
  • A tasklet only run on one CPU
  • Different tasklets can run concurrently on multiple CPUs
    • Per-cpu taskelet list
    • Tasket_softirq and hi_softirq
  • Run atomically in a run-to-complete fashion

Work queue

  • Implemented upon kernel thread
  • Process context
  • Permit handlers to sleep

Above methods (softirq, tasklet, work queue) need us to explicitly arrange them in top-half handlers.

Threaded interrupts

  • Recommended way to implement bottom-half
  • Handle the complex of hardirq -> tasklet/softirq interaction and locking problems
  • Prioritizing the handlers share an interrupt line

參考資料


第一篇我能看的懂的,白話講解 bottom-half 的機制
講解 threaded interrupt 的由來
jserv 的上課筆記
有比較 threaded interrupt 與其他方式的實驗
Trace Linux source 裡對 softirqs, tasklet, workqueue 的實作。可以深度的瞭解這三個的實作,只是長度有點長,需要時間理解。

很仔細的講解 softirq, tasklet, 和 workqueue 的行為。用條列的方式解釋,可以搭配上面那篇的程式碼一起對照著看。有重點講解了 ksoftirq 的設計想法。

短短的,直接把 softirq 應該記住的重點直接點出來
linux kernel interrupt document。用 lecture 的方式閱讀也蠻清楚的。
裡面有講到 exception, trap, 和 interrupt 這三個在這篇文章中的定義,拿來參考用。

Trap: user requested to transfer control to a special subroutine
Exception: automatically generated trap of exceptional condition
Interrupt: external hardware event
"

講解 preempt_count 的實作,中文有附圖,很清楚。另外也有 softirq 的文章,一樣也是有圖也清楚。
解釋為什麼 softirq 跑在 kernel thread 中,卻還是屬於 interrupt context。

ksoftirqd is implemented as a set of threads, each of which is constrained to only run on a specific CPU. They are scheduled (at a very high priority) by the normal task scheduler. This implementation has the advantage that the time spent executing the bottom halves is accounted to a system task. It is thus possible for the user to see that the machine is overloaded with interrupt processing, and maybe take remedial action.
Although the work is now being done in process context rather than bottom half context, ksoftirqd sets up an environment identical to that found in bottom half context. Specifically, it executes the softirq handlers with local interrupts enabled and bottom halves disabled locally. Code which runs as a bottom half does not need to change for ksoftirqd to run it. 
"
這篇有簡述 Softirq 的行為,還有提到 softirq 在 kernel 2.6.23 之後會跑在 normal user-level priority,舊一點的資料都是說 softirq 會跑在 highest priority。

在自己手上的 kernel 5.10 上驗證這點。

localhost ~ # ps -e -o uid,pid,ppid,pri,ni,cmd | grep ksoft

    0    13     2  19   0 [ksoftirqd/0]
    0    22     2  19   0 [ksoftirqd/1]
    0    28     2  19   0 [ksoftirqd/2]
    0    34     2  19   0 [ksoftirqd/3]
    0    40     2  19   0 [ksoftirqd/4]
    0    47     2  19   0 [ksoftirqd/5]
    0    53     2  19   0 [ksoftirqd/6]
    0    59     2  19   0 [ksoftirqd/7]

19 is normal user-level priority on kernel 5.10.