xref: /linux/tools/testing/selftests/sched_ext/enq_select_cpu.bpf.c (revision feacb1774bd5eac6382990d0f6d1378dc01dd78f)
1*36adf6feSAndrea Righi // SPDX-License-Identifier: GPL-2.0
2*36adf6feSAndrea Righi /*
3*36adf6feSAndrea Righi  * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4*36adf6feSAndrea Righi  * Copyright (c) 2023 David Vernet <dvernet@meta.com>
5*36adf6feSAndrea Righi  * Copyright (c) 2023 Tejun Heo <tj@kernel.org>
6*36adf6feSAndrea Righi  */
7*36adf6feSAndrea Righi 
8*36adf6feSAndrea Righi #include <scx/common.bpf.h>
9*36adf6feSAndrea Righi 
10*36adf6feSAndrea Righi char _license[] SEC("license") = "GPL";
11*36adf6feSAndrea Righi 
12*36adf6feSAndrea Righi UEI_DEFINE(uei);
13*36adf6feSAndrea Righi 
14*36adf6feSAndrea Righi s32 BPF_STRUCT_OPS(enq_select_cpu_select_cpu, struct task_struct *p,
15*36adf6feSAndrea Righi 		   s32 prev_cpu, u64 wake_flags)
16*36adf6feSAndrea Righi {
17*36adf6feSAndrea Righi 	/* Bounce all tasks to ops.enqueue() */
18*36adf6feSAndrea Righi 	return prev_cpu;
19*36adf6feSAndrea Righi }
20*36adf6feSAndrea Righi 
21*36adf6feSAndrea Righi void BPF_STRUCT_OPS(enq_select_cpu_enqueue, struct task_struct *p,
22*36adf6feSAndrea Righi 		    u64 enq_flags)
23*36adf6feSAndrea Righi {
24*36adf6feSAndrea Righi 	s32 cpu, prev_cpu = scx_bpf_task_cpu(p);
25*36adf6feSAndrea Righi 	bool found = false;
26*36adf6feSAndrea Righi 
27*36adf6feSAndrea Righi 	cpu = scx_bpf_select_cpu_dfl(p, prev_cpu, 0, &found);
28*36adf6feSAndrea Righi 	if (found) {
29*36adf6feSAndrea Righi 		scx_bpf_dsq_insert(p, SCX_DSQ_LOCAL_ON | cpu, SCX_SLICE_DFL, enq_flags);
30*36adf6feSAndrea Righi 		return;
31*36adf6feSAndrea Righi 	}
32*36adf6feSAndrea Righi 
33*36adf6feSAndrea Righi 	scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
34*36adf6feSAndrea Righi }
35*36adf6feSAndrea Righi 
36*36adf6feSAndrea Righi void BPF_STRUCT_OPS(enq_select_cpu_exit, struct scx_exit_info *ei)
37*36adf6feSAndrea Righi {
38*36adf6feSAndrea Righi 	UEI_RECORD(uei, ei);
39*36adf6feSAndrea Righi }
40*36adf6feSAndrea Righi 
41*36adf6feSAndrea Righi struct task_cpu_arg {
42*36adf6feSAndrea Righi 	pid_t pid;
43*36adf6feSAndrea Righi };
44*36adf6feSAndrea Righi 
45*36adf6feSAndrea Righi SEC("syscall")
46*36adf6feSAndrea Righi int select_cpu_from_user(struct task_cpu_arg *input)
47*36adf6feSAndrea Righi {
48*36adf6feSAndrea Righi 	struct task_struct *p;
49*36adf6feSAndrea Righi 	bool found = false;
50*36adf6feSAndrea Righi 	s32 cpu;
51*36adf6feSAndrea Righi 
52*36adf6feSAndrea Righi 	p = bpf_task_from_pid(input->pid);
53*36adf6feSAndrea Righi 	if (!p)
54*36adf6feSAndrea Righi 		return -EINVAL;
55*36adf6feSAndrea Righi 
56*36adf6feSAndrea Righi 	bpf_rcu_read_lock();
57*36adf6feSAndrea Righi 	cpu = scx_bpf_select_cpu_dfl(p, bpf_get_smp_processor_id(), 0, &found);
58*36adf6feSAndrea Righi 	if (!found)
59*36adf6feSAndrea Righi 		cpu = -EBUSY;
60*36adf6feSAndrea Righi 	bpf_rcu_read_unlock();
61*36adf6feSAndrea Righi 
62*36adf6feSAndrea Righi 	bpf_task_release(p);
63*36adf6feSAndrea Righi 
64*36adf6feSAndrea Righi 	return cpu;
65*36adf6feSAndrea Righi }
66*36adf6feSAndrea Righi 
67*36adf6feSAndrea Righi SEC(".struct_ops.link")
68*36adf6feSAndrea Righi struct sched_ext_ops enq_select_cpu_ops = {
69*36adf6feSAndrea Righi 	.select_cpu		= (void *)enq_select_cpu_select_cpu,
70*36adf6feSAndrea Righi 	.enqueue		= (void *)enq_select_cpu_enqueue,
71*36adf6feSAndrea Righi 	.exit			= (void *)enq_select_cpu_exit,
72*36adf6feSAndrea Righi 	.name			= "enq_select_cpu",
73*36adf6feSAndrea Righi 	.timeout_ms		= 1000U,
74*36adf6feSAndrea Righi };
75