17

I know that there are process context and interrupt context but I don't understand when executing softirq or tasklet, which context is it run under.

I have seen some people use the term "bottom-halves context", if there's such term, what's the difference comparing with the others.

Another question to softirq and tasklet is that why sleep are not allowed during execution??

Can anyone help me identify these questions, thanks!!

codingfreak
  • 4,467
  • 11
  • 48
  • 60
kai
  • 1,141
  • 3
  • 15
  • 25

3 Answers3

21

The softirq and tasklet are both kind of bottom-halves mechanism. Sleep is not allowed becuase they run under interrupt context not process context. If sleep is allowed, then the linux cannot schedule them and finally cause a kernel panic with a dequeue_task error. The interrupt context does not even have a data structure describing the register info, so they can never be scheduled by linux. If it is designed to have that structure and can be scheduled, the performance for interrupt handling process will be effected.

  • The Linux kernel's source code (I'm looking at v4.20.1) for `do_softirq` has `if ( in_interrupt() ) return;` as its first line. So, it seems like it's refusing to operate in interrupt context. – Daniel Walker Aug 23 '21 at 15:45
15

@kai: your qs reg which context bottom-halves execute in?

Technically, softirq's do run in an interrupt context - the "softirq" context; it's just that it's not "hard-irq" context (which is the context when a hardware interrupt occurs).

So, in a softirq handler, in terms of the 'lookup' macros Linux provides:

in_interrupt: yes | in_irq: no | in_softirq: yes | in_serving_softirq: yes

But be aware (beware!!! :): "all of the restrictions that apply to interrupt handlers also apply to bottom halves. Thus, bottom halves cannot sleep, cannot access user space, and cannot invoke the scheduler." -- LDD3.

Jermaine answers the rest of your question.

[Update] In addition, I'd like to point out that one can define simple and elegant macros that help print debug info as and when required. Over the years, I've put these macros and convenience routines into a header file; you can check it out and download it here: "A Header of Convenience".

There are macros / functions to:

  • make debug prints along with funcname / line# info (via the usual printk() or trace_printk()) and only if DEBUG mode is On
    • dump the kernel-mode stack
    • print the current context (process or interrupt along with flags in the form that ftrace uses)
    • a simple assert() macro (!)
    • a cpu-intensive DELAY_LOOP (useful for test rigs that must spin on the processor)
    • an equivalent to usermode sleep functionality
    • a function to calculate the time delta given two timestamps (timeval structs)
    • convert decimal to binary, and
    • a few more.

Whew :-)

kaiwan
  • 2,114
  • 1
  • 18
  • 23
  • 1
    We should also realize that, as of around 2.6.30, Thomas Gleixner (and others) have been actively moving the traditional interrupt handling model to that of the PREEMPT_RT's "threaded interrupt" model. So, yeah, within this model the traditional 'hard-irq' now runs via a kernel thread, implying, in process context! Crazy huh. Until one realizes that this is intentional: in order to support prioritized interrupt handlers and to have the ability to have interrupt code-paths preemptible by 'real-time' usermode threads! Ref: http://elinux.org/images/e/ef/InterruptThreads-Slides_Anderson.pdf‎ – kaiwan Jan 11 '14 at 09:48
9

I agree with the accepted answer and Kaiwan's answer, but they did not mention ksoftirqd. If the CPU is under heavy load of softirqs and/or tasklets, it schedules its ksoftirqd thread which process the raised softirqs and tasklets in process context.

So I guess the answer to the OP's question would be: softirqs can run in either interrupt or process contexts.

Update: A quick look on run_ksoftirqd() shows that __do_softirq() is called with local irqs disabled. So, while technically running in process context, same restrictions (like no sleeping) apply.

srd
  • 1,207
  • 12
  • 13
  • Hello srd, this is exactly what has been bothering me! I read in Linux Kernel Development [Robert Love] that softirqs and tasklets run in interrrupt context. The book also mentions ksoftirqd which is a kernel thread (and therefore runs in process context). As you know, this thread is employed for each processor in order to run softirqs/tasklets when many softirqs/tasklets are being raised due to some reason (for example, high traffic load on a network card). But how does a thread (process context) run a softirq/tasklet which is meant to run in interrupt context only?! I still don't understand. – Mohammad Ali Asgar Oct 20 '14 at 05:34
  • Hi @MohammadAliAsgar! I'm reading the same book (3rd edition), and from what I understand: a 'softirq' action will be executed when `do_softirq()` is called; this function can be called either from an interrupt context, on the return path of an interrupt handler ("hardirq"), or from a process context (`ksoftirqd` kernel thread or other code, like the networking subsystem). This is how the code can run in either context. And since it can run in interrupt context, it must not sleep because the scheduler won't be able to reschedule it. Take this with a grain of salt, but hope it helps – Catalin Dec 21 '20 at 18:34
  • @Catalin Hi thanks, what about tasklet? Are they called in the same manner (do_softirq())? – Chan Kim Aug 19 '21 at 05:47
  • 1
    @ChanKim From my reading of the book mentioned above, yes, tasklets are called in the same manner. They are built on top of sotfirqs, idea being that it is unlikely that you need to add a new *softirq* to the system, but you are free to add *tasklets*, which will be executed when processing specific *softirqs* (`HI_SOFTIRQ` and `TASKLET_SOFTIRQ`, afaiu) – Catalin Aug 22 '21 at 15:03
  • @Catalin ah, I now rememer tasklet is one of softirqs! thanks! – Chan Kim Aug 23 '21 at 05:15