Whenever a system call is about to return to userspace, or a
hardware interrupt handler exits, any 'software interrupts'
which are marked pending (usually by hardware interrupts) are
run (kernel/softirq.c
).
Much of the real interrupt handling work is done here. Early in the transition to SMP, there were only 'bottom halves' (BHs), which didn't take advantage of multiple CPUs. Shortly after we switched from wind-up computers made of match-sticks and snot, we abandoned this limitation and switched to 'softirqs'.
include/linux/interrupt.h
lists the
different softirqs. A very important softirq is the
timer softirq (include/linux/timer.h
): you can
register to have it call functions for you in a given length of
time.
Softirqs are often a pain to deal with, since the same softirq
will run simultaneously on more than one CPU. For this reason,
tasklets (include/linux/interrupt.h
) are more
often used: they are dynamically-registrable (meaning you can have
as many as you want), and they also guarantee that any tasklet
will only run on one CPU at any time, although different tasklets
can run simultaneously.
The name 'tasklet' is misleading: they have nothing to do with 'tasks', and probably more to do with some bad vodka Alexey Kuznetsov had at the time.
You can tell you are in a softirq (or tasklet)
using the in_softirq()
macro
(include/linux/interrupt.h
).
Beware that this will return a false positive if a bh lock (see below) is held.