top half and bottom half
Imagine a paramedic arriving at an emergency. The first job is the urgent few seconds: stop the bleeding, secure the scene — done immediately, no matter what. The thorough treatment — paperwork, follow-up, the long care — comes afterward, in calmer conditions. An interrupt handler is split the same way. The top half is the urgent part that runs the instant the interrupt fires; the bottom half is the slower, less time-critical work, deliberately deferred to run a little later.
Concretely, when a device interrupts, the kernel runs the top half (the interrupt service routine proper) with interrupts often disabled, so it must be lightning-fast: acknowledge the device, grab the freshly arrived data into a buffer, and schedule the rest of the work. Then it returns, re-enabling interrupts quickly. The deferred work — parsing a network packet up the protocol stack, copying data to a waiting process, deciding what to do next — runs as the bottom half once it is safe and convenient. Linux offers several bottom-half mechanisms: softirqs (high-throughput, can run on several CPUs at once), tasklets (a simpler softirq that is serialised per type), and work queues (which run in a normal kernel thread and, unlike the others, are allowed to sleep).
Why it matters: this split is how an OS stays responsive under a storm of interrupts. If all the work were done in the top half, a busy network card could keep interrupts disabled so long that the clock, the keyboard, and everything else would be starved. By doing only the bare minimum immediately and pushing the bulk to a bottom half that runs with interrupts enabled, the system handles high event rates without locking everyone else out. The names vary across systems — deferred procedure calls on Windows, softirqs and tasklets on Linux — but the idea is universal.
A network card receives a packet. The top half just copies the packet into a kernel buffer and flags 'work pending,' then returns in microseconds. Later, a softirq (the bottom half) parses the packet through TCP/IP and delivers it to the right socket.
Do the urgent minimum now; defer the bulk to run later with interrupts enabled.
The top half cannot sleep and runs with interrupts partly off, so it must be tiny; the bottom half is where any real, possibly-slow processing belongs. Putting slow work in the top half is the bug this whole split exists to prevent.