ANDROID: softirq: defer softirq processing to ksoftirqd if CPU is busy with RT

Defer the softirq processing to ksoftirqd if a RT task is
running or queued on the current CPU. This complements the RT
task placement algorithm which tries to find a CPU that is not
currently busy with softirqs.

Currently NET_TX, NET_RX, BLOCK and IRQ_POLL softirqs are only
deferred as they can potentially run for long time.

Additionally, this patch stubs out ksoftirqd_running() logic,
in the CONFIG_RT_SOFTIRQ_AWARE_SCHED case, as deferring
potentially long-running softirqs will cause the logic to not
process shorter-running softirqs immediately. By stubbing it out
the potentially long running softirqs are deferred, but the
shorter running ones can still run immediately.

This patch includes folded-in fixes by:
  Lingutla Chandrasekhar <clingutla@codeaurora.org>
  Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
  J. Avila <elavila@google.com>

Cc: John Dias <joaodias@google.com>
Cc: Connor O'Brien <connoro@google.com>
Cc: Rick Yiu <rickyiu@google.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Qais Yousef <qyousef@google.com>
Cc: Chris Redpath <chris.redpath@arm.com>
Cc: Abhijeet Dharmapurikar <adharmap@quicinc.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Joel Fernandes <joel@joelfernandes.org>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: kernel-team@android.com
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
[satyap@codeaurora.org: trivial merge conflict resolution.]
Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
[elavila: Port to mainline, squash with bugfix]
Signed-off-by: J. Avila <elavila@google.com>
[jstultz: Rebase to linus/HEAD, minor rearranging of code,
 included bug fix Reported-by: Qais Yousef <qais.yousef@arm.com> ]
Signed-off-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/lkml/20221116075929.453876-4-jstultz@google.com/
[jstultz: Had to rework this previous cherry-pick to android15-6.6
 incorrectly re-added the ksoftirqd_running logic which was previously
 removed, and resulted in build issues for the
 !CONFIG_RT_SOFTIRQ_AWARE_SCHED case]
Signed-off-by: John Stultz <jstultz@google.com>
Change-Id: I626250ff25d2915e72b8758e9d00ceac6a182df1
Bug: 168521633
Bug: 332627282
---
v4:
* Fix commit message to accurately note long-running softirqs
  (suggested by Qais)
* Switch to using rt_task(current) (suggested by Qais)
v5:
* Switch to using CONFIG_RT_SOFTIRQ_AWARE_SCHED (suggested by
  Joel Fernandes <joel@joelfernandes.org>)
This commit is contained in:
Pavankumar Kondeti
2017-06-28 12:00:31 +05:30
committed by Treehugger Robot
parent 01603b5411
commit 0312436e3f
+24 -3
View File
@@ -526,6 +526,21 @@ static inline bool lockdep_softirq_start(void) { return false; }
static inline void lockdep_softirq_end(bool in_hardirq) { }
#endif
#ifdef CONFIG_RT_SOFTIRQ_AWARE_SCHED
static __u32 softirq_deferred_for_rt(__u32 *pending)
{
__u32 deferred = 0;
if (rt_task(current)) {
deferred = *pending & LONG_SOFTIRQ_MASK;
*pending &= ~LONG_SOFTIRQ_MASK;
}
return deferred;
}
#else
#define softirq_deferred_for_rt(x) (0)
#endif
static void handle_softirqs(bool ksirqd)
{
unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
@@ -533,6 +548,7 @@ static void handle_softirqs(bool ksirqd)
int max_restart = MAX_SOFTIRQ_RESTART;
struct softirq_action *h;
bool in_hardirq;
__u32 deferred;
__u32 pending;
int softirq_bit;
@@ -544,14 +560,16 @@ static void handle_softirqs(bool ksirqd)
current->flags &= ~PF_MEMALLOC;
pending = local_softirq_pending();
deferred = softirq_deferred_for_rt(&pending);
softirq_handle_begin();
in_hardirq = lockdep_softirq_start();
account_softirq_enter(current);
restart:
/* Reset the pending bitmask before enabling irqs */
set_softirq_pending(0);
set_softirq_pending(deferred);
set_active_softirqs(pending);
local_irq_enable();
@@ -589,14 +607,17 @@ restart:
local_irq_disable();
pending = local_softirq_pending();
deferred = softirq_deferred_for_rt(&pending);
if (pending) {
if (time_before(jiffies, end) && !need_resched() &&
--max_restart)
goto restart;
wakeup_softirqd();
}
if (pending | deferred)
wakeup_softirqd();
account_softirq_exit(current);
lockdep_softirq_end(in_hardirq);
softirq_handle_end();