Interrupt context bottom half (Softirq or tasklets) - linux

Softirqs /tasklets are said to be executed in interrupt context I have below question with respect to interrupt context bottoms half.
Q1) What happen if we try to put sleep in tasklet (interrupt context Bottom half) ( consider that tasklet is scheduled by interrupt handler).
[My understanding]
As I know while coming out of interrupt handler when tasklet_schedule is called it will get get tasklet_vec structure pointer and if currently no other interrupt / high priority softirq in progress it will schedule ksoftirqd which will run handler (tasklet handler) and if a tall that tasklet handler uses sleep in that case ksoftirqd will move to wait_queue and unless and until another tasklet_schdule is called my interrupted tasklet hander will be continue on that point onwards.
We say "Interrupt context code must not sleep" ( What are consequence if I use sleep in interrupt handler, considering I have not used spint lock OR I have not disabled timer interrupt )
(Please correct me if my understanding is wrong)

Sleep works only in process context not in interrupt context. In interrupt context, "current" is not a valid task so we can put it in sleep and wake it up later. Use threads if u wanna sleep

If you try to sleep in tasklet, there would be a kernel bug indicating context switching in atomic context.
In bottom half, it is interrupt context, and is process context in ksoftirqd.
Regardless of processing tasklet in bottom half or ksoftirqd, thread_info->preempt_count is not zero, which meaning atomic context.

Related

Difference between interrupt context and process context?

What is interrupt context ? What is process context ?
What are the advantages of interrupt context ?
Why bottom half required ? Why not all the processing in top half ?
Process context is the current state of process, process context can be go into the sleep, preemptable, It perform time consumable task, acquiring and releasing mutex.
Interrupt context is when the interrupt occurs state/priority goes to interrupt handler, and current process stops/saves until we complete interrupt, Interrupt context is not time consumable, non preemptable, It cannot go into the sleep.
Bottom Half mechanism, SoftIRQ, Tasklet works in a interrupt context, workqueue can go into the sleep, so it is not run in interrupt context.
Process Context
One of the most important parts of a process are the executing program code. This code was read in from a executable file and executed within the program's address space. Normal program execution occurs in User-space. When a program executes a system call or triggers an exception, it enters Kernel-space. At this point, the kernel are said to being "executing on behalf of the process" and are in process context. When in process context, the current macro is valid. Upon exiting the kernel, the process resumes execution in User-space, unless a higher-priority process have become runnable In the interim (transition period), in which case the scheduler is invoked to select the higher priority process.
Interrupt Context
When executing a interrupt handler or bottom half, the kernel is in interrupt context.Recall That process context is the mode of operation the kernel are in while it's executing on behalf of a process-- For example, executing a system call or running a kernel thread. In process context, the current macro points to the associated task. Furthermore, because a process is coupled to the kernel in process context (because the process is connected to the kernel in the same way as the process above), process context can SleeP or otherwise invoke the scheduler.
Interrupt context, on the other hand, was not associated with a process. The current macro isn't relevant (although it points to the interrupted process). Without a backing process (because there is no process background), interrupt context cannot sleep-how would it ever reschedule? (or how to reschedule it again?) Therefore, cannot call certain functions from interrupt context. If A function sleeps, you cannot use it from your interrupt handler--this limits the functions so one can call from an Interrupt handler. (This is the limit on what functions can be used in an interrupt handler)
Link for more details.

Exactly when tasklet runs after it is schedule by ISR?

I written my ISR and my tasklet ran immediately. BUT, I have seen people saying that tasklet runs only when it gets CPU attention. This is a very generic term CPU attention so i recite for those responders. I mean exactly which moment cpu attention goes to tasklet execution and what happen to the state of CPU ?
Secondly, if suppose that i am keep on getting hard interrupt then when will tasklet get chance to run? Is it possible that tasklet may not get chance to run? How does kernel take care these things ?
TL;DR: Tasklets are run by ksoftirq threads who are handled by Scheduler.
Tasklet is just a form of softirq (it is handled by them with TASKLET_SOFTIRQ priority), so rules on when running tasklets applies to them. Here they are according to Robert Love's book "Linux Kernel
Development":
In the return from hardware interrupt code path
In the ksoftirq kernel thread
In any code that explicitly checks for and executes pending softirqs, such as the networking subsystem
It seems that case (1) will not work if threadirqs=true (kernel boot parameter) which is default value.
UPD: Some notes on ksoftirq relation with Scheduler.
That is what seem to happen:
In hardirq handler you wake up ksoftirq (due to tasklet_schedule())
Thus wake_up_process() checks if ksoftirq may preempt current thread
If (2) is true TIF_NEED_RESCHED flag is set
On the return from hardirq (ret_from_intr - in x86) TIF_NEED_RESCHED flag is checked
If (4) is true, schedule() is called trying to pick next thread to be executed.
There is high chance that ksoftirq will be considered as preempt candidate in (2-3) and it will be picked in (5), but if there are competitors, ksoftirq have to wait till next schedule() cycle - current thread surrenders (i.e. sleeping), clock tick happens, syscall or new interrupt.

what will happen to tasklet execution if interrupt occurs in between

The things I know about tasklet:
Tasklet runs with all interrupt enabled.
The tasklet runs in interrupt context.
It can't be sleep.
It runs in atomic way.
it has the assurance to be scheduled never late than next tick.
My questions:
Since in bottom half all interrupts are enabled, what happened If a tasklet is running and in between any interrupt comes. (If interrupts are disabled during tasklet execution then what is the benefit of tasklet)?
Why is the surety that tasklet will always be scheduled upto next tick?
Is it correct to say that tasklets are softirq with priority level 0(Hi priority tasklet) and priority level 6(Normal taslet)?
*Since in bottom half all interrupts are enabled, what happened If a tasklet is running and in between any interrupt comes. (If interrupts are disabled during tasklet execution then what is the benefit of tasklet)?*
From what i understand Tasklet (which is built on soft IRQ) runs in soft IRQ context which essentially means it runs in context of whatever process was running when the process was interrupted by Hard IRQ (so it is borrowing stack) , so an interrupt again would return back to tasklet execution.
*Is it correct to say that tasklets are softirq with priority level 0(Hi priority tasklet) and priority level 6(Normal taslet)?*
Yes tasklets are essentially wrappers built on Soft IRQ.

How is interrupt context "restored" when a interrupt handler is interrupted by another interrupt?

I read some related posts:
(1) From Robert Love: http://permalink.gmane.org/gmane.linux.kernel.kernelnewbies/1791
You cannot sleep in an interrupt handler because interrupts do not have a backing
process context, and thus there is nothing to reschedule back into. In other
words, interrupt handlers are not associated with a task, so there is nothing to
"put to sleep" and (more importantly) "nothing to wake up". They must run
atomically.
(2) From Which context are softirq and tasklet in?
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.
So in my understanding, interrupt handlers run in interrupt context, and can not sleep, that is to say, can not perform the context switch as normal processes do with backing mechanism.
But a interrupt handler can be interrupted by another interrupt. And when the second interrupt handler finishes its work, control flow would jump back to the first interrupt handler.
How is this "restoring" implemented without normal context switch? Is it like normal function calls with all the registers and other related stuff stored in a certain stack?
The short answer is that an interrupt handler, if it can be interrupted by an interrupt, is interrupted precisely the same way anything else is interrupted by an interrupt.
Say process X is running. If process X is interrupted, then the interrupt handler runs. To the extent there is a context, it's still process X, though it's now running interrupt code in the kernel (think of the state as X->interrupt if you like). If another interrupt occurs, then the interrupt is interrupted, but there is still no special process context. The state is now X->first_interrupt->second_interrupt. When the second interrupt finishes, the first interrupt will resume just as X will resume when the first interrupt finishes. Still, the only process context is process X.
You can describe these as context switches, but they aren't like process context switches. They're more analogous to entering and exiting the kernel -- the process context stays the same but the execution level and unit of code can change.
The interrupt routine will store some CPU state and registers before enter real interrupt handler, and will restore these information before returning to interrupted task. Normally, this kind of storing and restoring is not called context-switch, as the context of interrupted process is not changed.
As of 2020, interrupts (hard IRQ here) in Linux do not nest on a local CPU in general. This is at least mentioned twice by group/maintainer actively contributing to Linux kernel:
From NAPI updates written by Jakub Kicinski in 2020:
…Because normal interrupts don't nest in Linux, the system can't service any new interrupt while it's already processing one.
And from Bootlin in 2022:
…Interrupt handlers are run with all interrupts disabled on the local CPU…
So this question is probably less relevant nowadays, at least for Linux kernel.

Interrupt handlers executed in a different thread?

I wanted to know when the processor get's interrupted and an ISR (interrupt service routine) is executed, is that executed in the context of the thread that was interrupted to handle this interrupt or is it executed in its own thread and then goes back to where it left of in the original thread?
So a context switch actually occurs when an interrupt occurs?
A thread isn't created to handle the interrupt (part of why system calls can sometimes fail), though you can have a special thread to handle interrupts (read about "second level interrupt handlers" in the Wikipedia article on interrupt handling; I'm not certain if Windows uses SLIHs). There is a potential context switch since the ISR runs in kernel mode. Even if the current thread is in kernel mode, some context will be saved before calling the interrupt handler.
Still looking for documentation.

Resources