Commit daa9f66f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'sched_ext-for-6.12-rc5-fixes' of...

Merge tag 'sched_ext-for-6.12-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext

Pull sched_ext fixes from Tejun Heo:

 - Instances of scx_ops_bypass() could race each other leading to
   misbehavior. Fix by protecting the operation with a spinlock.

 - selftest and userspace header fixes

* tag 'sched_ext-for-6.12-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext:
  sched_ext: Fix enq_last_no_enq_fails selftest
  sched_ext: Make cast_mask() inline
  scx: Fix raciness in scx_ops_bypass()
  scx: Fix exit selftest to use custom DSQ
  sched_ext: Fix function pointer type mismatches in BPF selftests
  selftests/sched_ext: add order-only dependency of runner.o on BPFOBJ
parents 7fbaacaf c31f2ee5
Loading
Loading
Loading
Loading
+17 −12
Original line number Diff line number Diff line
@@ -862,7 +862,8 @@ static DEFINE_MUTEX(scx_ops_enable_mutex);
DEFINE_STATIC_KEY_FALSE(__scx_ops_enabled);
DEFINE_STATIC_PERCPU_RWSEM(scx_fork_rwsem);
static atomic_t scx_ops_enable_state_var = ATOMIC_INIT(SCX_OPS_DISABLED);
static atomic_t scx_ops_bypass_depth = ATOMIC_INIT(0);
static int scx_ops_bypass_depth;
static DEFINE_RAW_SPINLOCK(__scx_ops_bypass_lock);
static bool scx_ops_init_task_enabled;
static bool scx_switching_all;
DEFINE_STATIC_KEY_FALSE(__scx_switched_all);
@@ -4298,18 +4299,20 @@ bool task_should_scx(struct task_struct *p)
 */
static void scx_ops_bypass(bool bypass)
{
	int depth, cpu;
	int cpu;
	unsigned long flags;

	raw_spin_lock_irqsave(&__scx_ops_bypass_lock, flags);
	if (bypass) {
		depth = atomic_inc_return(&scx_ops_bypass_depth);
		WARN_ON_ONCE(depth <= 0);
		if (depth != 1)
			return;
		scx_ops_bypass_depth++;
		WARN_ON_ONCE(scx_ops_bypass_depth <= 0);
		if (scx_ops_bypass_depth != 1)
			goto unlock;
	} else {
		depth = atomic_dec_return(&scx_ops_bypass_depth);
		WARN_ON_ONCE(depth < 0);
		if (depth != 0)
			return;
		scx_ops_bypass_depth--;
		WARN_ON_ONCE(scx_ops_bypass_depth < 0);
		if (scx_ops_bypass_depth != 0)
			goto unlock;
	}

	/*
@@ -4326,7 +4329,7 @@ static void scx_ops_bypass(bool bypass)
		struct rq_flags rf;
		struct task_struct *p, *n;

		rq_lock_irqsave(rq, &rf);
		rq_lock(rq, &rf);

		if (bypass) {
			WARN_ON_ONCE(rq->scx.flags & SCX_RQ_BYPASSING);
@@ -4362,11 +4365,13 @@ static void scx_ops_bypass(bool bypass)
			sched_enq_and_set_task(&ctx);
		}

		rq_unlock_irqrestore(rq, &rf);
		rq_unlock(rq, &rf);

		/* resched to restore ticks and idle state */
		resched_cpu(cpu);
	}
unlock:
	raw_spin_unlock_irqrestore(&__scx_ops_bypass_lock, flags);
}

static void free_exit_info(struct scx_exit_info *ei)
+1 −1
Original line number Diff line number Diff line
@@ -320,7 +320,7 @@ u32 bpf_cpumask_weight(const struct cpumask *cpumask) __ksym;
/*
 * Access a cpumask in read-only mode (typically to check bits).
 */
const struct cpumask *cast_mask(struct bpf_cpumask *mask)
static __always_inline const struct cpumask *cast_mask(struct bpf_cpumask *mask)
{
	return (const struct cpumask *)mask;
}
+1 −1
Original line number Diff line number Diff line
@@ -184,7 +184,7 @@ auto-test-targets := \

testcase-targets := $(addsuffix .o,$(addprefix $(SCXOBJ_DIR)/,$(auto-test-targets)))

$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR)
$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR) $(BPFOBJ)
	$(CC) $(CFLAGS) -c $< -o $@

# Create all of the test targets object files, whose testcase objects will be
+3 −3
Original line number Diff line number Diff line
@@ -51,8 +51,8 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(create_dsq_init)

SEC(".struct_ops.link")
struct sched_ext_ops create_dsq_ops = {
	.init_task		= create_dsq_init_task,
	.exit_task		= create_dsq_exit_task,
	.init			= create_dsq_init,
	.init_task		= (void *) create_dsq_init_task,
	.exit_task		= (void *) create_dsq_exit_task,
	.init			= (void *) create_dsq_init,
	.name			= "create_dsq",
};
+2 −2
Original line number Diff line number Diff line
@@ -35,8 +35,8 @@ void BPF_STRUCT_OPS(ddsp_bogus_dsq_fail_exit, struct scx_exit_info *ei)

SEC(".struct_ops.link")
struct sched_ext_ops ddsp_bogus_dsq_fail_ops = {
	.select_cpu		= ddsp_bogus_dsq_fail_select_cpu,
	.exit			= ddsp_bogus_dsq_fail_exit,
	.select_cpu		= (void *) ddsp_bogus_dsq_fail_select_cpu,
	.exit			= (void *) ddsp_bogus_dsq_fail_exit,
	.name			= "ddsp_bogus_dsq_fail",
	.timeout_ms		= 1000U,
};
Loading