Table of Contents
At any time each of the CPUs in a system can be:
not associated with any process, serving a hardware interrupt;
not associated with any process, serving a softirq or tasklet;
running in kernel space, associated with a process (user context);
running a process in user space.
There is an ordering between these. The bottom two can preempt each other, but above that is a strict hierarchy: each can only be preempted by the ones above it. For example, while a softirq is running on a CPU, no other softirq will preempt it, but a hardware interrupt can. However, any other CPUs in the system execute independently.
We'll see a number of ways that the user context can block interrupts, to become truly non-preemptable.
User context is when you are coming in from a system call or other
trap: like userspace, you can be preempted by more important tasks
and by interrupts. You can sleep, by calling
schedule()
.
You are always in user context on module load and unload, and on operations on the block device layer.
In user context, the current
pointer (indicating
the task we are currently executing) is valid, and
in_interrupt()
(include/linux/interrupt.h
) is false
.
Beware that if you have preemption or softirqs disabled
(see below), in_interrupt()
will return a
false positive.