summaryrefslogtreecommitdiff
path: root/include/linux/hardirq.h
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-02-21 20:17:22 +0100
committerThomas Gleixner <tglx@linutronix.de>2010-02-21 20:17:22 +0100
commit5f854cfc024622e4aae14d7cf422f6ff86278688 (patch)
tree426e77c6f6e4939c80440bf1fabcb020e3ee145b /include/linux/hardirq.h
parentcc24da0742870f152ddf1002aa39dfcd83f7cf9c (diff)
parent4ec62b2b2e6bd7ddef7b6cea6e5db7b5578a6532 (diff)
downloadlwn-5f854cfc024622e4aae14d7cf422f6ff86278688.tar.gz
lwn-5f854cfc024622e4aae14d7cf422f6ff86278688.zip
Forward to 2.6.33-rc8
Merge branch 'linus' into rt/head with a pile of conflicts. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include/linux/hardirq.h')
-rw-r--r--include/linux/hardirq.h56
1 files changed, 51 insertions, 5 deletions
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 16966fbab185..8a2b0889a008 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -64,6 +64,12 @@
#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
#define NMI_OFFSET (1UL << NMI_SHIFT)
+#ifndef PREEMPT_ACTIVE
+#define PREEMPT_ACTIVE_BITS 1
+#define PREEMPT_ACTIVE_SHIFT (NMI_SHIFT + NMI_BITS)
+#define PREEMPT_ACTIVE (__IRQ_MASK(PREEMPT_ACTIVE_BITS) << PREEMPT_ACTIVE_SHIFT)
+#endif
+
#if PREEMPT_ACTIVE < (1 << (NMI_SHIFT + NMI_BITS))
#error PREEMPT_ACTIVE is too low!
#endif
@@ -77,8 +83,8 @@
* Are we doing bottom half or hardware interrupt processing?
* Are we in a softirq context? Interrupt context?
*/
-#define in_irq() (hardirq_count() || (current->flags & PF_HARDIRQ))
-#define in_softirq() (softirq_count() || (current->flags & PF_SOFTIRQ))
+#define in_irq() (hardirq_count() || (current->extra_flags & PFE_HARDIRQ))
+#define in_softirq() (softirq_count() || (current->extra_flags & PFE_SOFTIRQ))
#define in_interrupt() (irq_count())
/*
@@ -86,6 +92,8 @@
*/
#define in_nmi() (preempt_count() & NMI_MASK)
+#define PREEMPT_INATOMIC_BASE 0
+
/*
* Are we running in atomic context? WARNING: this macro cannot
* always detect atomic context; in particular, it cannot know about
@@ -93,7 +101,21 @@
* 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) != 0)
+#define in_atomic() \
+ ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_INATOMIC_BASE)
+
+#ifdef CONFIG_PREEMPT
+# define PREEMPT_CHECK_OFFSET 1
+#else
+# define PREEMPT_CHECK_OFFSET 0
+#endif
+
+/*
+ * Check whether we were atomic before we did preempt_disable():
+ * (used by the scheduler)
+ */
+#define in_atomic_preempt_off() \
+ ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
#ifdef CONFIG_PREEMPT
# define preemptible() (preempt_count() == 0 && !irqs_disabled())
@@ -117,17 +139,41 @@ static inline void account_system_vtime(struct task_struct *tsk)
}
#endif
-#if defined(CONFIG_NO_HZ) && !defined(CONFIG_CLASSIC_RCU)
+#if defined(CONFIG_NO_HZ)
+#if defined(CONFIG_TINY_RCU)
+extern void rcu_enter_nohz(void);
+extern void rcu_exit_nohz(void);
+
+static inline void rcu_irq_enter(void)
+{
+ rcu_exit_nohz();
+}
+
+static inline void rcu_irq_exit(void)
+{
+ rcu_enter_nohz();
+}
+
+static inline void rcu_nmi_enter(void)
+{
+}
+
+static inline void rcu_nmi_exit(void)
+{
+}
+
+#else
extern void rcu_irq_enter(void);
extern void rcu_irq_exit(void);
extern void rcu_nmi_enter(void);
extern void rcu_nmi_exit(void);
+#endif
#else
# define rcu_irq_enter() do { } while (0)
# define rcu_irq_exit() do { } while (0)
# define rcu_nmi_enter() do { } while (0)
# define rcu_nmi_exit() do { } while (0)
-#endif /* #if defined(CONFIG_NO_HZ) && !defined(CONFIG_CLASSIC_RCU) */
+#endif /* #if defined(CONFIG_NO_HZ) */
/*
* It is safe to do non-atomic ops on ->hardirq_context,