*_tsk_need_resched() need to test for the specific need-resched flag. The only users are RCU and the scheduler. For RCU we always want to schedule at the earliest opportunity and that is always RESCHED_eager. For the scheduler, keep everything as RESCHED_eager for now. Originally-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx> --- include/linux/sched.h | 17 ++++++++++++----- kernel/rcu/tree.c | 4 ++-- kernel/rcu/tree_exp.h | 4 ++-- kernel/rcu/tree_plugin.h | 4 ++-- kernel/rcu/tree_stall.h | 2 +- kernel/sched/core.c | 9 +++++---- kernel/sched/deadline.c | 4 ++-- kernel/sched/fair.c | 2 +- kernel/sched/idle.c | 2 +- kernel/sched/rt.c | 4 ++-- 10 files changed, 30 insertions(+), 22 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 12d0626601a0..6dd206b2ef50 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2060,19 +2060,26 @@ static inline bool test_tsk_thread_flag(struct task_struct *tsk, int flag) return test_ti_thread_flag(task_thread_info(tsk), flag); } -static inline void set_tsk_need_resched(struct task_struct *tsk) +static inline void set_tsk_need_resched(struct task_struct *tsk, resched_t lazy) { - set_tsk_thread_flag(tsk,TIF_NEED_RESCHED); + set_tsk_thread_flag(tsk, tif_resched(lazy)); } static inline void clear_tsk_need_resched(struct task_struct *tsk) { - clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED); + clear_tsk_thread_flag(tsk, tif_resched(RESCHED_eager)); + clear_tsk_thread_flag(tsk, tif_resched(RESCHED_lazy)); } -static inline bool test_tsk_need_resched(struct task_struct *tsk) +static inline bool test_tsk_need_resched(struct task_struct *tsk, resched_t lazy) { - return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED)); + return unlikely(test_tsk_thread_flag(tsk, tif_resched(lazy))); +} + +static inline bool test_tsk_need_resched_any(struct task_struct *tsk) +{ + return test_tsk_need_resched(tsk, RESCHED_eager) || + test_tsk_need_resched(tsk, RESCHED_lazy); } /* diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index cb1caefa8bd0..a7776ae78900 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -2231,7 +2231,7 @@ void rcu_sched_clock_irq(int user) if (smp_load_acquire(this_cpu_ptr(&rcu_data.rcu_urgent_qs))) { /* Idle and userspace execution already are quiescent states. */ if (!rcu_is_cpu_rrupt_from_idle() && !user) { - set_tsk_need_resched(current); + set_tsk_need_resched(current, RESCHED_eager); set_preempt_need_resched(); } __this_cpu_write(rcu_data.rcu_urgent_qs, false); @@ -2379,7 +2379,7 @@ static __latent_entropy void rcu_core(void) if (IS_ENABLED(CONFIG_PREEMPT_COUNT) && (!(preempt_count() & PREEMPT_MASK))) { rcu_preempt_deferred_qs(current); } else if (rcu_preempt_need_deferred_qs(current)) { - set_tsk_need_resched(current); + set_tsk_need_resched(current, RESCHED_eager); set_preempt_need_resched(); } diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h index 8239b39d945b..a4a23ac1115b 100644 --- a/kernel/rcu/tree_exp.h +++ b/kernel/rcu/tree_exp.h @@ -755,7 +755,7 @@ static void rcu_exp_handler(void *unused) rcu_report_exp_rdp(rdp); } else { WRITE_ONCE(rdp->cpu_no_qs.b.exp, true); - set_tsk_need_resched(t); + set_tsk_need_resched(t, RESCHED_eager); set_preempt_need_resched(); } return; @@ -856,7 +856,7 @@ static void rcu_exp_need_qs(void) __this_cpu_write(rcu_data.cpu_no_qs.b.exp, true); /* Store .exp before .rcu_urgent_qs. */ smp_store_release(this_cpu_ptr(&rcu_data.rcu_urgent_qs), true); - set_tsk_need_resched(current); + set_tsk_need_resched(current, RESCHED_eager); set_preempt_need_resched(); } diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 41021080ad25..f87191e008ff 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -658,7 +658,7 @@ static void rcu_read_unlock_special(struct task_struct *t) // Also if no expediting and no possible deboosting, // slow is OK. Plus nohz_full CPUs eventually get // tick enabled. - set_tsk_need_resched(current); + set_tsk_need_resched(current, RESCHED_eager); set_preempt_need_resched(); if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled && expboost && !rdp->defer_qs_iw_pending && cpu_online(rdp->cpu)) { @@ -725,7 +725,7 @@ static void rcu_flavor_sched_clock_irq(int user) (preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK))) { /* No QS, force context switch if deferred. */ if (rcu_preempt_need_deferred_qs(t)) { - set_tsk_need_resched(t); + set_tsk_need_resched(t, RESCHED_eager); set_preempt_need_resched(); } } else if (rcu_preempt_need_deferred_qs(t)) { diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h index 6f06dc12904a..b74b7b04cf35 100644 --- a/kernel/rcu/tree_stall.h +++ b/kernel/rcu/tree_stall.h @@ -705,7 +705,7 @@ static void print_cpu_stall(unsigned long gps) * progress and it could be we're stuck in kernel space without context * switches for an entirely unreasonable amount of time. */ - set_tsk_need_resched(current); + set_tsk_need_resched(current, RESCHED_eager); set_preempt_need_resched(); } diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e30007c11722..e2215c417323 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -927,7 +927,7 @@ static bool set_nr_if_polling(struct task_struct *p) #else static inline bool set_nr_and_not_polling(struct task_struct *p) { - set_tsk_need_resched(p); + set_tsk_need_resched(p, RESCHED_eager); return true; } @@ -1039,13 +1039,13 @@ void resched_curr(struct rq *rq) lockdep_assert_rq_held(rq); - if (test_tsk_need_resched(curr)) + if (test_tsk_need_resched(curr, RESCHED_eager)) return; cpu = cpu_of(rq); if (cpu == smp_processor_id()) { - set_tsk_need_resched(curr); + set_tsk_need_resched(curr, RESCHED_eager); set_preempt_need_resched(); return; } @@ -2223,7 +2223,8 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags) * A queue event has occurred, and we're going to schedule. In * this case, we can save a useless back to back clock update. */ - if (task_on_rq_queued(rq->curr) && test_tsk_need_resched(rq->curr)) + if (task_on_rq_queued(rq->curr) && + test_tsk_need_resched(rq->curr, RESCHED_eager)) rq_clock_skip_update(rq); } diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 58b542bf2893..e6815c3bd2f0 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1953,7 +1953,7 @@ static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p, * let us try to decide what's the best thing to do... */ if ((p->dl.deadline == rq->curr->dl.deadline) && - !test_tsk_need_resched(rq->curr)) + !test_tsk_need_resched(rq->curr, RESCHED_eager)) check_preempt_equal_dl(rq, p); #endif /* CONFIG_SMP */ } @@ -2467,7 +2467,7 @@ static void pull_dl_task(struct rq *this_rq) static void task_woken_dl(struct rq *rq, struct task_struct *p) { if (!task_on_cpu(rq, p) && - !test_tsk_need_resched(rq->curr) && + !test_tsk_need_resched(rq->curr, RESCHED_eager) && p->nr_cpus_allowed > 1 && dl_task(rq->curr) && (rq->curr->nr_cpus_allowed < 2 || diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index df348aa55d3c..4d86c618ffa2 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -8087,7 +8087,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ * prevents us from potentially nominating it as a false LAST_BUDDY * below. */ - if (test_tsk_need_resched(curr)) + if (test_tsk_need_resched(curr, RESCHED_eager)) return; /* Idle tasks are by definition preempted by non-idle tasks. */ diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index d4a55448e459..eacd204e2879 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -329,7 +329,7 @@ static enum hrtimer_restart idle_inject_timer_fn(struct hrtimer *timer) struct idle_timer *it = container_of(timer, struct idle_timer, timer); WRITE_ONCE(it->done, 1); - set_tsk_need_resched(current); + set_tsk_need_resched(current, RESCHED_eager); return HRTIMER_NORESTART; } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 0597ba0f85ff..a79ce6746dd0 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1735,7 +1735,7 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag * to move current somewhere else, making room for our non-migratable * task. */ - if (p->prio == rq->curr->prio && !test_tsk_need_resched(rq->curr)) + if (p->prio == rq->curr->prio && !test_tsk_need_resched(rq->curr, RESCHED_eager)) check_preempt_equal_prio(rq, p); #endif } @@ -2466,7 +2466,7 @@ static void pull_rt_task(struct rq *this_rq) static void task_woken_rt(struct rq *rq, struct task_struct *p) { bool need_to_push = !task_on_cpu(rq, p) && - !test_tsk_need_resched(rq->curr) && + !test_tsk_need_resched(rq->curr, RESCHED_eager) && p->nr_cpus_allowed > 1 && (dl_task(rq->curr) || rt_task(rq->curr)) && (rq->curr->nr_cpus_allowed < 2 || -- 2.31.1