softirq: Don't defer all softirq during RT task
Since 'commit f332a9d53e33 ("softirq: defer softirq processing to ksoftirqd if CPU is busy with RT")', all softirqs are deferred to ksoftirqd if one of the potentially long softirqs are pending. This can significantly delay processing of tasklets and timers, which are frequently designed to be running at high priority. Defer only the potentially slow softirqs to ksoftirqd. Change-Id: I7a2ef7c59749ccf086066c59962ff326786da6f4 Signed-off-by: Björn Davidsson <bjorn.davidsson@sony.com> [clingutla@codeaurora.org:- Renamed local variables and refactored deferred logic to macro for avoiding potential deadlock.] Signed-off-by: Lingutla Chandrasekhar <clingutla@codeaurora.org>
This commit is contained in:
parent
63d54f82b9
commit
b1b1320534
1 changed files with 18 additions and 8 deletions
|
@ -234,8 +234,16 @@ static inline bool lockdep_softirq_start(void) { return false; }
|
|||
static inline void lockdep_softirq_end(bool in_hardirq) { }
|
||||
#endif
|
||||
|
||||
#define long_softirq_pending() (local_softirq_pending() & LONG_SOFTIRQ_MASK)
|
||||
#define defer_for_rt() (long_softirq_pending() && cpupri_check_rt())
|
||||
#define softirq_deferred_for_rt(pending) \
|
||||
({ \
|
||||
__u32 deferred = 0; \
|
||||
if (cpupri_check_rt()) { \
|
||||
deferred = pending & LONG_SOFTIRQ_MASK; \
|
||||
pending &= ~LONG_SOFTIRQ_MASK; \
|
||||
} \
|
||||
deferred; \
|
||||
})
|
||||
|
||||
asmlinkage __visible void __softirq_entry __do_softirq(void)
|
||||
{
|
||||
unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
|
||||
|
@ -243,6 +251,7 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
|
|||
int max_restart = MAX_SOFTIRQ_RESTART;
|
||||
struct softirq_action *h;
|
||||
bool in_hardirq;
|
||||
__u32 deferred;
|
||||
__u32 pending;
|
||||
int softirq_bit;
|
||||
|
||||
|
@ -254,14 +263,14 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
|
|||
current->flags &= ~PF_MEMALLOC;
|
||||
|
||||
pending = local_softirq_pending();
|
||||
deferred = softirq_deferred_for_rt(pending);
|
||||
account_irq_enter_time(current);
|
||||
|
||||
__local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
|
||||
in_hardirq = lockdep_softirq_start();
|
||||
|
||||
restart:
|
||||
/* Reset the pending bitmask before enabling irqs */
|
||||
set_softirq_pending(0);
|
||||
set_softirq_pending(deferred);
|
||||
__this_cpu_write(active_softirqs, pending);
|
||||
|
||||
local_irq_enable();
|
||||
|
@ -297,15 +306,16 @@ restart:
|
|||
local_irq_disable();
|
||||
|
||||
pending = local_softirq_pending();
|
||||
deferred = softirq_deferred_for_rt(pending);
|
||||
|
||||
if (pending) {
|
||||
if (time_before(jiffies, end) && !need_resched() &&
|
||||
!defer_for_rt() &&
|
||||
--max_restart)
|
||||
goto restart;
|
||||
|
||||
wakeup_softirqd();
|
||||
}
|
||||
|
||||
if (pending | deferred)
|
||||
wakeup_softirqd();
|
||||
lockdep_softirq_end(in_hardirq);
|
||||
account_irq_exit_time(current);
|
||||
__local_bh_enable(SOFTIRQ_OFFSET);
|
||||
|
@ -352,7 +362,7 @@ void irq_enter(void)
|
|||
|
||||
static inline void invoke_softirq(void)
|
||||
{
|
||||
if (!force_irqthreads && !defer_for_rt()) {
|
||||
if (!force_irqthreads) {
|
||||
#ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
|
||||
/*
|
||||
* We can safely execute softirq on the current stack if
|
||||
|
|
Loading…
Add table
Reference in a new issue