aboutsummaryrefslogtreecommitdiff
path: root/include/linux/hardirq.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/hardirq.h')
-rw-r--r--include/linux/hardirq.h17
1 files changed, 13 insertions, 4 deletions
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 49829988bfa..181006cc94a 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -72,17 +72,26 @@
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
-#define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != 0)
-
-#ifdef CONFIG_PREEMPT
+#if defined(CONFIG_PREEMPT)
+# define PREEMPT_INATOMIC_BASE kernel_locked()
# define PREEMPT_CHECK_OFFSET 1
#else
+# define PREEMPT_INATOMIC_BASE 0
# define PREEMPT_CHECK_OFFSET 0
#endif
/*
+ * Are we running in atomic context? WARNING: this macro cannot
+ * always detect atomic context; in particular, it cannot know about
+ * held spinlocks in non-preemptible kernels. Thus it should not be
+ * used in the general case to determine whether sleeping is possible.
+ * Do not use in_atomic() in driver code.
+ */
+#define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_INATOMIC_BASE)
+
+/*
* Check whether we were atomic before we did preempt_disable():
- * (used by the scheduler)
+ * (used by the scheduler, *after* releasing the kernel lock)
*/
#define in_atomic_preempt_off() \
((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)