From afad5a0b8fddf8213c4de94648b2d8a832f43f53 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Mon, 28 May 2018 15:39:20 +0530 Subject: [PATCH 1/4] sched/cpupri: Exclude isolated CPUs from the lowest_mask The cpupri_find() returns the candidate CPUs which are running lower priority than the waking RT task in the lowest_mask. This contains isolated CPUs as well. Since the energy aware CPU selection skips isolated CPUs, no target CPU may be found if all unisolated CPUs are running higher priority RT tasks. In which case, we fallback to the default CPU selection algorithm and returns an isolated CPU. This decision is reversed by select_task_rq() and returns an unisolated CPU that is busy with other RT tasks. This RT task packing is desired behavior. However, RT push mechanism pushes the packed RT task to an isolated CPU. This can be avoided by excluding isolated CPUs from the lowest_mask returned by cpupri_find(). Change-Id: I75486b3935caf496a638d0333565beffc47fe249 Signed-off-by: Pavankumar Kondeti [satyap@codeaurora.org: trivial merge conflict resolution] Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/sched/cpupri.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c index 47ba4a9dcd11..6305f73994ff 100644 --- a/kernel/sched/cpupri.c +++ b/kernel/sched/cpupri.c @@ -122,6 +122,8 @@ retry: if (lowest_mask) { cpumask_and(lowest_mask, p->cpus_ptr, vec->mask); + cpumask_andnot(lowest_mask, lowest_mask, + cpu_isolated_mask); if (drop_nopreempts) drop_nopreempt_cpus(lowest_mask); /* From fe605a9890ed48f3d17d7ad844f4278b0002263f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Davidsson?= Date: Thu, 25 Jan 2018 12:06:21 +0100 Subject: [PATCH 2/4] softirq: Don't defer all softirq during RT task MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 [clingutla@codeaurora.org: Renamed local variables and refactored deferred logic to macro for avoiding potential deadlock.] Signed-off-by: Lingutla Chandrasekhar Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/softirq.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/kernel/softirq.c b/kernel/softirq.c index ef2a7b2bf0a4..24cb1e699951 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -253,8 +253,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; @@ -262,6 +270,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; @@ -273,14 +282,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(); @@ -317,15 +326,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); @@ -375,7 +385,7 @@ static inline void invoke_softirq(void) if (ksoftirqd_running(local_softirq_pending())) return; - 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 From 1c71817e0fdf0a5f45aab2b7dafd15fff2c911d5 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Mon, 3 Dec 2018 15:05:26 +0530 Subject: [PATCH 3/4] genirq: Honour IRQ's affinity hint during migration An IRQ affinity is broken during hotplug/isolation when there are no online and un-isolated CPUs in the current affinity mask. An online and un-isolated CPU from the irq_default_affinity mask (i.e /proc/irq/default_smp_affinity) is used as the current affinity. However Individual IRQs can have their affinity hint set via irq_set_affinity_hint() API. When such hint is available, use it instead of the irq_default_affinity which is a system level setting. Change-Id: I53a537582ec4e1aed0c59b49f4fd5b6ca7c0c332 Signed-off-by: Pavankumar Kondeti Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/irq/cpuhotplug.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c index ef18c39f78c1..d995601d04e8 100644 --- a/kernel/irq/cpuhotplug.c +++ b/kernel/irq/cpuhotplug.c @@ -116,6 +116,8 @@ static bool migrate_one_irq(struct irq_desc *desc) affinity = &available_cpus; if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { + const struct cpumask *default_affinity; + /* * If the interrupt is managed, then shut it down and leave * the affinity untouched. @@ -125,6 +127,8 @@ static bool migrate_one_irq(struct irq_desc *desc) irq_shutdown_and_deactivate(desc); return false; } + + default_affinity = desc->affinity_hint ? : irq_default_affinity; /* * The order of preference for selecting a fallback CPU is * @@ -134,9 +138,9 @@ static bool migrate_one_irq(struct irq_desc *desc) */ cpumask_andnot(&available_cpus, cpu_online_mask, cpu_isolated_mask); - if (cpumask_intersects(&available_cpus, irq_default_affinity)) + if (cpumask_intersects(&available_cpus, default_affinity)) cpumask_and(&available_cpus, &available_cpus, - irq_default_affinity); + default_affinity); else if (cpumask_empty(&available_cpus)) affinity = cpu_online_mask; From 0fbe4b198022f5a3df28b9e4d75c23d4403f1d4b Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Tue, 8 Jan 2019 15:38:32 -0800 Subject: [PATCH 4/4] Revert "Mark HI and TASKLET softirq synchronous" This reverts commit 3c53776e29f81719efcf8f7a6e30cdf753bee94d. Reverting the change to match what we have on previous Kernels. Change-Id: I4af64cd7e2c4291dda5f503bf2d74ede459a76c6 [satyap@codeaurora.org: Port to 5.x and fix trivial merge conflict] Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/softirq.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/kernel/softirq.c b/kernel/softirq.c index 24cb1e699951..53ca9850d9ef 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -85,16 +85,12 @@ static void wakeup_softirqd(void) /* * If ksoftirqd is scheduled, we do not want to process pending softirqs - * right now. Let ksoftirqd handle this at its own rate, to get fairness, - * unless we're doing some of the synchronous softirqs. + * right now. Let ksoftirqd handle this at its own rate, to get fairness. */ -#define SOFTIRQ_NOW_MASK ((1 << HI_SOFTIRQ) | (1 << TASKLET_SOFTIRQ)) -static bool ksoftirqd_running(unsigned long pending) +static bool ksoftirqd_running(void) { struct task_struct *tsk = __this_cpu_read(ksoftirqd); - if (pending & SOFTIRQ_NOW_MASK) - return false; return tsk && (tsk->state == TASK_RUNNING) && !__kthread_should_park(tsk); } @@ -355,7 +351,7 @@ asmlinkage __visible void do_softirq(void) pending = local_softirq_pending(); - if (pending && !ksoftirqd_running(pending)) + if (pending && !ksoftirqd_running()) do_softirq_own_stack(); local_irq_restore(flags); @@ -382,7 +378,7 @@ void irq_enter(void) static inline void invoke_softirq(void) { - if (ksoftirqd_running(local_softirq_pending())) + if (ksoftirqd_running()) return; if (!force_irqthreads) {