You cannot sleep in an interrupt handler because interrupts do not have a backing process context, and thus there is nothing to reschedule back into. In other words, interrupt handlers are not associated with a task, so there is nothing to "put to sleep" and (more importantly) "nothing to wake up". They must run atomically.
This is not unlike other operating systems. In most operating systems,
interrupts are not threaded. Bottom halves often are, however.
The reason the page fault handler can sleep is that it is invoked only
by code that is running in process context. Because the kernel's own
memory is not pagable, only user-space memory accesses can result in a
page fault. Thus, only a few certain places (such as calls to
copy_{to,from}_user()) can cause a page fault within the kernel. Those
places must all be made by code that can sleep (i.e., process context,
no locks, et cetera).
In a system, there is a thread context and an interrupt context. Interrupts are invoked by the hardware, while threads are scheduler by the RTOS scheduler. Now when an interrupt occurs, any thread will be immediately pre-empted; the interrupt must run to completion and can only be preempted by a higher priority interrupt (where nested interrupts are supported). All pending interrupts will run to completion before the scheduler can run.
Mutex Story
Blocking on a mutex (or indeed any blocking kernel object) is a scheduling event. If you were to make any blocking call in an interrupt, the scheduler will never run. In practice an RTOS would either ignore the blocking call, raise an exception, or enter a terminal error handler.
Now lets imagine this from an interrupt handler's point of view.
If an interrupt handler attempts to get a mutex that is not available, what should it do? The interrupt handler cannot block like the thread (the kernel is not equipped to push the context of an interrupt handler or switch to a thread from an interrupt handler).
If the interrupt handler obtains the mutex, what higher priority code is there that could interrupt the interrupt handler and attempt to use the mutex? Is the interrupt handler going to release the mutex before completing?
How does the kernel assign ownership of the mutex to an interrupt handler? An interrupt handler is not a thread. If the interrupt handler does not release the mutex then how will the kernel validate that the mutex is being released by the owner?
Some Functions Which Sleep
The most common ones are listed below, but you usually have to read the code to find out if other calls are safe. If everyone else who calls it can sleep, you probably need to be able to sleep, too. In particular, registration and deregistration functions usually expect to be called from user context, and can sleep.
Accesses to userspace:
copy_from_user()
copy_to_user()
get_user()
put_user()
mutex_lock_interruptible()
andmutex_lock()
There is a
mutex_trylock()
which does not sleep. Still, it must not be used inside interrupt context since its implementation is not safe for that.mutex_unlock()
will also never sleep. It cannot be used in interrupt context either since a mutex must be released by the same task that acquired it.
Issue Signature :
May 25 21:49:22 <hostname> kernel: amdgpu 0000:08:00.0: RAS: optional ras ta ucode is not available May 25 21:49:22 <hostname> kernel: BUG: sleeping function called from invalid context at mm/slab.h:567 May 25 21:49:22 <hostname> kernel: Call Trace: May 25 21:49:22 <hostname> kernel: dump_stack+0x8b/0xc8 May 25 21:49:22 <hostname> kernel: ___might_sleep.cold+0xb6/0xc6 May 25 21:49:22 <hostname> kernel: kmem_cache_alloc_trace+0x1ea/0x230
Some Functions Which Don’t Sleep
Some functions are safe to call from any context, or holding almost any lock.
Sleep in kmalloc(GFP_KERNEL) should not be allowed in IRQ or atomic context
Using GFP_ATOMIC
prevents sleeping by telling the memory allocation code that it's not allowed to sleep to satisfy the allocation - that's all. If the memory allocation code needs to sleep, and GFP_ATOMIC
has been passed, then it will return an error to the caller instead.Important References :-
https://www.spinics.net/lists/newbies/msg07287.html [ classic reply by robert love ]
https://stackoverflow.com/questions/35011322/why-not-to-use-mutex-inside-an-interrupt [ for similar reason , we cannot use a mutex in an IRQ handler ]