Saturday, August 20, 2016

Linux: Sleeping while atomic during kmalloc solved

So you ran into a crash where the kernel complains that you were sleeping while atomic.
You were either able to run objdump or gdb and track down that the crash is caused due
to a kmalloc? How is that possible?
Did you make recent changes which included putting in a kmalloc?

Typical format:
The function is declared in <linux/slab.h>:
void * kmalloc(size_t size, int flags)

This function is often used in a similar fashion:
struct packet_st *ptr;
ptr = kmalloc(sizeof(struct packet_st), GFP_KERNEL);
if (!ptr)
        /* handle error ... */

The problem is that the GFP_KERNEL has to be used in proper context. i.e. you cannot use GFP_KERNEL from IRQ context. This is because GFP_KERNEL tells the kernel that if it was not able to immediately allocate the required page, it is free to sleep. However, as we know, we are not allowed to sleep in "atomic" context. 

Hence, we need to make sure that appropriate context flag is used while requesting memory. If you are in the IRQ context, it is useful to use the GFP_ATOMIC flag instead of GFP_KERNEL. This will solve the problem of the crash.