Skip to content
/ linux Public

Commit c1b8245

Browse files
htejungregkh
authored andcommitted
sched_ext: Simplify breather mechanism with scx_aborting flag
[ Upstream commit a69040e ] The breather mechanism was introduced in 62dcbab ("sched_ext: Avoid live-locking bypass mode switching") and e32c260 ("sched_ext: Enable the ops breather and eject BPF scheduler on softlockup") to prevent live-locks by injecting delays when CPUs are trapped in dispatch paths. Currently, it uses scx_breather_depth (atomic_t) and scx_in_softlockup (unsigned long) with separate increment/decrement and cleanup operations. The breather is only activated when aborting, so tie it directly to the exit mechanism. Replace both variables with scx_aborting flag set when exit is claimed and cleared after bypass is enabled. Introduce scx_claim_exit() to consolidate exit_kind claiming and breather enablement. This eliminates scx_clear_softlockup() and simplifies scx_softlockup() and scx_bypass(). The breather mechanism will be replaced by a different abort mechanism in a future patch. This simplification prepares for that change. Reviewed-by: Dan Schatzberg <schatzberg.dan@gmail.com> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> Acked-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org> Stable-dep-of: 83236b2 ("sched_ext: Disable preemption between scx_claim_exit() and kicking helper work") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c44198f commit c1b8245

File tree

1 file changed

+25
-29
lines changed

1 file changed

+25
-29
lines changed

kernel/sched/ext.c

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ static DEFINE_MUTEX(scx_enable_mutex);
3333
DEFINE_STATIC_KEY_FALSE(__scx_enabled);
3434
DEFINE_STATIC_PERCPU_RWSEM(scx_fork_rwsem);
3535
static atomic_t scx_enable_state_var = ATOMIC_INIT(SCX_DISABLED);
36-
static unsigned long scx_in_softlockup;
37-
static atomic_t scx_breather_depth = ATOMIC_INIT(0);
3836
static int scx_bypass_depth;
37+
static bool scx_aborting;
3938
static bool scx_init_task_enabled;
4039
static bool scx_switching_all;
4140
DEFINE_STATIC_KEY_FALSE(__scx_switched_all);
@@ -1791,7 +1790,7 @@ static void scx_breather(struct rq *rq)
17911790

17921791
lockdep_assert_rq_held(rq);
17931792

1794-
if (likely(!atomic_read(&scx_breather_depth)))
1793+
if (likely(!READ_ONCE(scx_aborting)))
17951794
return;
17961795

17971796
raw_spin_rq_unlock(rq);
@@ -1800,9 +1799,9 @@ static void scx_breather(struct rq *rq)
18001799

18011800
do {
18021801
int cnt = 1024;
1803-
while (atomic_read(&scx_breather_depth) && --cnt)
1802+
while (READ_ONCE(scx_aborting) && --cnt)
18041803
cpu_relax();
1805-
} while (atomic_read(&scx_breather_depth) &&
1804+
} while (READ_ONCE(scx_aborting) &&
18061805
time_before64(ktime_get_ns(), until));
18071806

18081807
raw_spin_rq_lock(rq);
@@ -3718,30 +3717,14 @@ void scx_softlockup(u32 dur_s)
37183717
goto out_unlock;
37193718
}
37203719

3721-
/* allow only one instance, cleared at the end of scx_bypass() */
3722-
if (test_and_set_bit(0, &scx_in_softlockup))
3723-
goto out_unlock;
3724-
37253720
printk_deferred(KERN_ERR "sched_ext: Soft lockup - CPU%d stuck for %us, disabling \"%s\"\n",
37263721
smp_processor_id(), dur_s, scx_root->ops.name);
37273722

3728-
/*
3729-
* Some CPUs may be trapped in the dispatch paths. Enable breather
3730-
* immediately; otherwise, we might even be able to get to scx_bypass().
3731-
*/
3732-
atomic_inc(&scx_breather_depth);
3733-
37343723
scx_error(sch, "soft lockup - CPU#%d stuck for %us", smp_processor_id(), dur_s);
37353724
out_unlock:
37363725
rcu_read_unlock();
37373726
}
37383727

3739-
static void scx_clear_softlockup(void)
3740-
{
3741-
if (test_and_clear_bit(0, &scx_in_softlockup))
3742-
atomic_dec(&scx_breather_depth);
3743-
}
3744-
37453728
/**
37463729
* scx_bypass - [Un]bypass scx_ops and guarantee forward progress
37473730
* @bypass: true for bypass, false for unbypass
@@ -3802,8 +3785,6 @@ static void scx_bypass(bool bypass)
38023785
ktime_get_ns() - bypass_timestamp);
38033786
}
38043787

3805-
atomic_inc(&scx_breather_depth);
3806-
38073788
/*
38083789
* No task property is changing. We just need to make sure all currently
38093790
* queued tasks are re-queued according to the new scx_rq_bypassing()
@@ -3860,10 +3841,8 @@ static void scx_bypass(bool bypass)
38603841
raw_spin_rq_unlock(rq);
38613842
}
38623843

3863-
atomic_dec(&scx_breather_depth);
38643844
unlock:
38653845
raw_spin_unlock_irqrestore(&bypass_lock, flags);
3866-
scx_clear_softlockup();
38673846
}
38683847

38693848
static void free_exit_info(struct scx_exit_info *ei)
@@ -3958,6 +3937,7 @@ static void scx_disable_workfn(struct kthread_work *work)
39583937

39593938
/* guarantee forward progress by bypassing scx_ops */
39603939
scx_bypass(true);
3940+
WRITE_ONCE(scx_aborting, false);
39613941

39623942
switch (scx_set_enable_state(SCX_DISABLING)) {
39633943
case SCX_DISABLING:
@@ -4086,9 +4066,24 @@ static void scx_disable_workfn(struct kthread_work *work)
40864066
scx_bypass(false);
40874067
}
40884068

4089-
static void scx_disable(enum scx_exit_kind kind)
4069+
static bool scx_claim_exit(struct scx_sched *sch, enum scx_exit_kind kind)
40904070
{
40914071
int none = SCX_EXIT_NONE;
4072+
4073+
if (!atomic_try_cmpxchg(&sch->exit_kind, &none, kind))
4074+
return false;
4075+
4076+
/*
4077+
* Some CPUs may be trapped in the dispatch paths. Enable breather
4078+
* immediately; otherwise, we might not even be able to get to
4079+
* scx_bypass().
4080+
*/
4081+
WRITE_ONCE(scx_aborting, true);
4082+
return true;
4083+
}
4084+
4085+
static void scx_disable(enum scx_exit_kind kind)
4086+
{
40924087
struct scx_sched *sch;
40934088

40944089
if (WARN_ON_ONCE(kind == SCX_EXIT_NONE || kind == SCX_EXIT_DONE))
@@ -4097,7 +4092,7 @@ static void scx_disable(enum scx_exit_kind kind)
40974092
rcu_read_lock();
40984093
sch = rcu_dereference(scx_root);
40994094
if (sch) {
4100-
atomic_try_cmpxchg(&sch->exit_kind, &none, kind);
4095+
scx_claim_exit(sch, kind);
41014096
kthread_queue_work(sch->helper, &sch->disable_work);
41024097
}
41034098
rcu_read_unlock();
@@ -4418,9 +4413,8 @@ static void scx_vexit(struct scx_sched *sch,
44184413
const char *fmt, va_list args)
44194414
{
44204415
struct scx_exit_info *ei = sch->exit_info;
4421-
int none = SCX_EXIT_NONE;
44224416

4423-
if (!atomic_try_cmpxchg(&sch->exit_kind, &none, kind))
4417+
if (!scx_claim_exit(sch, kind))
44244418
return;
44254419

44264420
ei->exit_code = exit_code;
@@ -4645,6 +4639,8 @@ static void scx_enable_workfn(struct kthread_work *work)
46454639
*/
46464640
WARN_ON_ONCE(scx_set_enable_state(SCX_ENABLING) != SCX_DISABLED);
46474641
WARN_ON_ONCE(scx_root);
4642+
if (WARN_ON_ONCE(READ_ONCE(scx_aborting)))
4643+
WRITE_ONCE(scx_aborting, false);
46484644

46494645
atomic_long_set(&scx_nr_rejected, 0);
46504646

0 commit comments

Comments
 (0)