Unreliable Guide To Hacking The Linux Kernel states that
You can tell you are in a hardware interrupt, because in_irq() returns true.
Caution. Beware that this will return a false positive if interrupts are disabled (see below).
Is it really the case that in_irq()
may return non-zero not in hardirq context in the Linux kernels 2.6.32 or newer on x86?
In my experiments with the kernel 2.6.32 (Debian 6) and 3.4 (OpenSUSE 12.1), in_irq()
always returned 0 when called from a process context even if it was called between local_irq_disable()
and local_irq_enable()
. The results were the same when I used spinlock functions that disable interrupts instead of local_irq*
.
From the source code of the kernel, I currently cannot see how in_irq()
can return a false positive. Could anyone clarify this?
EDIT: I have also tried both *_irqsave()
and *_irq()
spinlock API as well as local_irq_save()
/ local_irq_restore()
, the results were the same, that is, in_irq()
returned 0 when the interrupts were disabled. Disabling the interrupts explicitly via cli
machine instruction on x86 also did not force in_irq() to return non-zero.
in_irq()
is a wrapper that looks at some bits in preempt_count
, which is an int in the thread_info
struct and a value of 0 means it's not pre-empted so it's not in an irq.
local_irq_disable()
by itself does not affect that count, but spin_lock_irqsave()
does, so that could lead to the false positive. You say you used the spinlock functions, did you use this one? If so, look to see if the value of preempt_count is changing.
EDIT: Just to cover all the bases, check to make sure kernel pre-emption is enabled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With