aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2021-03-09 09:55:53 +0100
committerThomas Gleixner <tglx@linutronix.de>2021-03-17 16:34:08 +0100
commit728b478d2d358480b333b42d0e10e0fecb20114c (patch)
tree2f1a1bd80bd1c0a018bb881bab907c476b2c1e28
parenttasklets: Switch tasklet_disable() to the sleep wait variant (diff)
downloadlinux-dev-728b478d2d358480b333b42d0e10e0fecb20114c.tar.xz
linux-dev-728b478d2d358480b333b42d0e10e0fecb20114c.zip
softirq: Add RT specific softirq accounting
RT requires the softirq processing and local bottomhalf disabled regions to be preemptible. Using the normal preempt count based serialization is therefore not possible because this implicitely disables preemption. RT kernels use a per CPU local lock to serialize bottomhalfs. As local_bh_disable() can nest the lock can only be acquired on the outermost invocation of local_bh_disable() and released when the nest count becomes zero. Tasks which hold the local lock can be preempted so its required to keep track of the nest count per task. Add a RT only counter to task struct and adjust the relevant macros in preempt.h. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Tested-by: Paul E. McKenney <paulmck@kernel.org> Reviewed-by: Frederic Weisbecker <frederic@kernel.org> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20210309085726.983627589@linutronix.de
-rw-r--r--include/linux/hardirq.h1
-rw-r--r--include/linux/preempt.h6
-rw-r--r--include/linux/sched.h3
3 files changed, 9 insertions, 1 deletions
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 7c9d6a2d7e90..69bc86ea382c 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -6,6 +6,7 @@
#include <linux/preempt.h>
#include <linux/lockdep.h>
#include <linux/ftrace_irq.h>
+#include <linux/sched.h>
#include <linux/vtime.h>
#include <asm/hardirq.h>
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index 69cc8b64aa3a..9881eac0698f 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -79,7 +79,11 @@
#define nmi_count() (preempt_count() & NMI_MASK)
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
-#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
+#ifdef CONFIG_PREEMPT_RT
+# define softirq_count() (current->softirq_disable_cnt & SOFTIRQ_MASK)
+#else
+# define softirq_count() (preempt_count() & SOFTIRQ_MASK)
+#endif
#define irq_count() (nmi_count() | hardirq_count() | softirq_count())
/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ef00bb22164c..743a613c9cf3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1044,6 +1044,9 @@ struct task_struct {
int softirq_context;
int irq_config;
#endif
+#ifdef CONFIG_PREEMPT_RT
+ int softirq_disable_cnt;
+#endif
#ifdef CONFIG_LOCKDEP
# define MAX_LOCK_DEPTH 48UL