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