« Previous Lecture | Next Lecture »
Every memory allocation call in the Linux kernel — kmalloc(), alloc_pages(), alloc_pages_exact(), and dozens of others — takes a mysterious first or second argument called a GFP mask. Get it wrong and your driver can silently corrupt the system, deadlock, or crash under a “sleeping in atomic context” bug. This lesson breaks down GFP_KERNEL vs GFP_ATOMIC in plain language, so you know exactly which one to reach for and why.
Process context vs interrupt context
Why sleeping matters to the allocator
GFP_KERNEL vs GFP_ATOMIC decision rule
GFP_NOIO and locking edge cases
Debugging atomic-sleep bugs
Prerequisites
This lesson assumes you already know the basics of writing a kernel module and have seen a memory allocation call like kmalloc() before. If you haven’t yet, start with our free Linux kernel development course module on kernel module programming first.
What Does GFP Actually Mean?
GFP stands for “Get Free Pages,” a nod to the low-level page allocator that ultimately backs every kernel memory request. Every allocation function accepts a gfp_t bitmask that tells the memory management subsystem how it is allowed to behave while trying to satisfy your request — most importantly, whether it is allowed to pause and wait for memory to become available.
Process Context vs Interrupt Context
To understand GFP flags, you first need to understand where your code is running when it asks for memory.
Process Context
Your code runs on behalf of a task/thread — a syscall handler, a kernel thread, a workqueue. It is generally safe to pause and wait here.
Interrupt / Atomic Context
Your code runs as an interrupt handler, a softirq, a tasklet, or while holding a spinlock. It must never pause — it has to run to completion.
The kernel exposes helper macros so your code can check where it’s running: in_task() tells you whether you’re in process context, and in_atomic() tells you whether the current context must run to completion without interruption. Note the asymmetry — you can be in process context and still be atomic at the same time, for example while holding a spinlock, but the reverse is never true.
Why “Sleeping” Matters
A “blocking” or “sleeping” call is one where your code voluntarily gives up the CPU and waits for some event — a timer expiring, data arriving, or in this case, the kernel reclaiming enough memory to satisfy your allocation. Under the hood, sleeping happens by invoking the scheduler. That is only safe from a context where the scheduler is allowed to run something else in your place.
Never sleep in interrupt or atomic context. If your allocation might block, it must only be called from process context.
Violating this rule doesn’t always crash immediately — that’s what makes it dangerous. The kernel has a debug option, CONFIG_DEBUG_ATOMIC_SLEEP, that you should always enable on a development kernel; it flags exactly this class of bug at the moment it happens instead of letting it corrupt state silently.
GFP_KERNEL vs GFP_ATOMIC: The Decision Rule
This is the single most important rule in kernel memory allocation:
GFP_KERNELGFP_ATOMIC| Flag | Can Sleep? | Typical Use |
|---|---|---|
GFP_KERNEL |
Yes | Driver probe functions, ioctl handlers, workqueue callbacks, module init |
GFP_ATOMIC |
No | Interrupt handlers, softirqs, tasklets, code holding a spinlock |
Code Example: Correct Flag Usage
#include <linux/interrupt.h>
#include <linux/slab.h>
/* Runs in process context - safe to sleep */
static int drv_probe(struct platform_device *pdev)
{
struct drv_data *data;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
return 0;
}
/* Runs in interrupt context - must never sleep */
static irqreturn_t drv_irq_handler(int irq, void *dev_id)
{
struct event_record *rec;
rec = kmalloc(sizeof(*rec), GFP_ATOMIC);
if (!rec)
return IRQ_NONE;
/* fill and queue rec for later processing */
return IRQ_HANDLED;
}
A Special Case: GFP_NOIO
Beyond the basic pair, the kernel defines several more specialised flags for internal reclaim behaviour, such as __GFP_IO, __GFP_FS, and __GFP_DIRECT_RECLAIM. One practical variant every driver author should recognise is GFP_NOIO.
When you use GFP_KERNEL, the kernel is implicitly allowed to start disk or network I/O to reclaim memory if things get tight. That’s usually fine — but not if you’re already holding a lock that some I/O completion path also needs, because that can deadlock the system. A classic example is allocating memory while holding a USB device lock: several USB core code paths were fixed over the years specifically to use GFP_NOIO instead of GFP_KERNEL in that situation, to prevent the kernel from re-entering I/O while the device lock is already held.
usb_lock_device(udev);
/* Not GFP_KERNEL here - could trigger IO reclaim
* while the device lock is held */
buf = kmalloc(size, GFP_NOIO);
usb_unlock_device(udev);
Real-World Use Cases
| Scenario | Correct Flag |
|---|---|
| Network driver receive interrupt (NAPI poll off-loaded) | GFP_ATOMIC inside the hard IRQ handler; GFP_KERNEL in the softirq/NAPI poll if not atomic |
| Character device open()/ioctl() | GFP_KERNEL |
| Timer callback (legacy non-threaded) | GFP_ATOMIC |
| Block layer or filesystem code under a lock reachable from writeback | GFP_NOIO or GFP_NOFS as appropriate |
Common Mistakes and Troubleshooting
- Using GFP_KERNEL inside an interrupt handler: This is a textbook “sleeping in atomic context” bug. Turn on
CONFIG_DEBUG_ATOMIC_SLEEPin your development kernel config to catch it immediately. - Using GFP_ATOMIC everywhere out of caution: Atomic allocations dip into a smaller emergency memory pool and are more likely to fail under pressure. Use it only where it’s actually required.
- Allocating memory while holding a lock also used by the reclaim/I-O path: Use GFP_NOIO (or GFP_NOFS) instead of GFP_KERNEL in these cases.
- Assuming atomic context only happens in interrupt handlers: Holding a spinlock in process context is also atomic context. Check with
in_atomic()if unsure.
Best Practices
- Default to
GFP_KERNELwhenever you are certain you’re in process context and hold no atomic locks. - Reserve
GFP_ATOMICstrictly for interrupt/softirq/tasklet code or code under a spinlock. - Enable atomic-sleep debugging during development, never rely on catching it in production.
- Always check the return value of every allocation — atomic allocations especially can fail more often.
Performance and Security Considerations
GFP_ATOMIC allocations draw from a smaller reserved memory pool specifically so that critical low-level code doesn’t starve during memory pressure; overusing it in non-critical paths can exhaust that reserve and cause otherwise-avoidable allocation failures elsewhere in the system. From a security and stability standpoint, an unguarded sleep in atomic context isn’t just a performance bug — it can hang interrupt processing system-wide, so this is one of the few kernel bug classes worth treating as a hard blocker in code review.
Summary / Key Takeaways
- GFP flags tell the allocator whether it’s allowed to sleep while satisfying your request.
- Use
GFP_KERNELin process context where sleeping is safe. - Use
GFP_ATOMICin interrupt context or while holding a spinlock. - Use
GFP_NOIOwhen holding a lock that could deadlock against I/O-triggered reclaim. - Enable
CONFIG_DEBUG_ATOMIC_SLEEPduring development to catch violations early.
Conclusion
Choosing the right GFP flag is one of the most fundamental skills in Linux kernel and device driver programming. Get the context right, and the rest follows: GFP_KERNEL when you can sleep, GFP_ATOMIC when you cannot, and the more specialised flags like GFP_NOIO for the trickier locking situations. Understanding this one rule prevents an entire category of hard-to-reproduce kernel bugs.
FAQ
You risk sleeping in atomic context, which is a serious kernel bug that can hang or crash the system. Always use GFP_ATOMIC there instead.
It’s not inherently slower, but it draws from a smaller reserved memory pool and is more likely to fail under heavy memory pressure, so it should only be used where sleeping is genuinely unsafe.
Use the in_atomic() macro to check, and in_task() to check whether you’re in process context at all.
It’s used when you’re in process context but holding a lock that could deadlock if the allocator tried to reclaim memory via disk or network I/O.
Yes. Holding a spinlock while in process context still makes that code atomic, so sleeping is unsafe even though you are technically in a process’s context.
Yes, every kernel allocator that accepts a gfp_t mask follows the same rule, including kmalloc(), vmalloc() variants, and alloc_pages()-family functions.
EmbeddedPathashala’s free Linux kernel development course and free Linux device drivers course cover GFP flags, the page allocator, and the slab allocator in depth with hands-on labs.
This lesson is part of EmbeddedPathashala’s free Linux kernel development course and free Linux device drivers course — covering memory management, synchronization, and driver internals from the ground up.
