@@ -854,6 +854,68 @@ static bool check_builtin_idle_enabled(void)
854854 return false;
855855}
856856
857+ s32 select_cpu_from_kfunc (struct task_struct * p , s32 prev_cpu , u64 wake_flags ,
858+ const struct cpumask * allowed , u64 flags )
859+ {
860+ struct rq * rq ;
861+ struct rq_flags rf ;
862+ s32 cpu ;
863+
864+ if (!kf_cpu_valid (prev_cpu , NULL ))
865+ return - EINVAL ;
866+
867+ if (!check_builtin_idle_enabled ())
868+ return - EBUSY ;
869+
870+ /*
871+ * If called from an unlocked context, acquire the task's rq lock,
872+ * so that we can safely access p->cpus_ptr and p->nr_cpus_allowed.
873+ *
874+ * Otherwise, allow to use this kfunc only from ops.select_cpu()
875+ * and ops.select_enqueue().
876+ */
877+ if (scx_kf_allowed_if_unlocked ()) {
878+ rq = task_rq_lock (p , & rf );
879+ } else {
880+ if (!scx_kf_allowed (SCX_KF_SELECT_CPU | SCX_KF_ENQUEUE ))
881+ return - EPERM ;
882+ rq = scx_locked_rq ();
883+ }
884+
885+ /*
886+ * Validate locking correctness to access p->cpus_ptr and
887+ * p->nr_cpus_allowed: if we're holding an rq lock, we're safe;
888+ * otherwise, assert that p->pi_lock is held.
889+ */
890+ if (!rq )
891+ lockdep_assert_held (& p -> pi_lock );
892+
893+ #ifdef CONFIG_SMP
894+ /*
895+ * This may also be called from ops.enqueue(), so we need to handle
896+ * per-CPU tasks as well. For these tasks, we can skip all idle CPU
897+ * selection optimizations and simply check whether the previously
898+ * used CPU is idle and within the allowed cpumask.
899+ */
900+ if (p -> nr_cpus_allowed == 1 ) {
901+ if (cpumask_test_cpu (prev_cpu , allowed ?: p -> cpus_ptr ) &&
902+ scx_idle_test_and_clear_cpu (prev_cpu ))
903+ cpu = prev_cpu ;
904+ else
905+ cpu = - EBUSY ;
906+ } else {
907+ cpu = scx_select_cpu_dfl (p , prev_cpu , wake_flags ,
908+ allowed ?: p -> cpus_ptr , flags );
909+ }
910+ #else
911+ cpu = - EBUSY ;
912+ #endif
913+ if (scx_kf_allowed_if_unlocked ())
914+ task_rq_unlock (rq , p , & rf );
915+
916+ return cpu ;
917+ }
918+
857919/**
858920 * scx_bpf_cpu_node - Return the NUMA node the given @cpu belongs to, or
859921 * trigger an error if @cpu is invalid
@@ -878,38 +940,26 @@ __bpf_kfunc int scx_bpf_cpu_node(s32 cpu)
878940 * @wake_flags: %SCX_WAKE_* flags
879941 * @is_idle: out parameter indicating whether the returned CPU is idle
880942 *
881- * Can only be called from ops.select_cpu() if the built-in CPU selection is
882- * enabled - ops.update_idle() is missing or %SCX_OPS_KEEP_BUILTIN_IDLE is set.
883- * @p, @prev_cpu and @wake_flags match ops.select_cpu().
943+ * Can be called from ops.select_cpu(), ops.enqueue(), or from an unlocked
944+ * context such as a BPF test_run() call, as long as built-in CPU selection
945+ * is enabled: ops.update_idle() is missing or %SCX_OPS_KEEP_BUILTIN_IDLE
946+ * is set.
884947 *
885948 * Returns the picked CPU with *@is_idle indicating whether the picked CPU is
886949 * currently idle and thus a good candidate for direct dispatching.
887950 */
888951__bpf_kfunc s32 scx_bpf_select_cpu_dfl (struct task_struct * p , s32 prev_cpu ,
889952 u64 wake_flags , bool * is_idle )
890953{
891- #ifdef CONFIG_SMP
892954 s32 cpu ;
893- #endif
894- if (!kf_cpu_valid (prev_cpu , NULL ))
895- goto prev_cpu ;
896-
897- if (!check_builtin_idle_enabled ())
898- goto prev_cpu ;
899-
900- if (!scx_kf_allowed (SCX_KF_SELECT_CPU ))
901- goto prev_cpu ;
902955
903- #ifdef CONFIG_SMP
904- cpu = scx_select_cpu_dfl (p , prev_cpu , wake_flags , NULL , 0 );
956+ cpu = select_cpu_from_kfunc (p , prev_cpu , wake_flags , NULL , 0 );
905957 if (cpu >= 0 ) {
906958 * is_idle = true;
907959 return cpu ;
908960 }
909- #endif
910-
911- prev_cpu :
912961 * is_idle = false;
962+
913963 return prev_cpu ;
914964}
915965
@@ -936,62 +986,7 @@ __bpf_kfunc s32 scx_bpf_select_cpu_dfl(struct task_struct *p, s32 prev_cpu,
936986__bpf_kfunc s32 scx_bpf_select_cpu_and (struct task_struct * p , s32 prev_cpu , u64 wake_flags ,
937987 const struct cpumask * cpus_allowed , u64 flags )
938988{
939- struct rq * rq ;
940- struct rq_flags rf ;
941- s32 cpu ;
942-
943- if (!kf_cpu_valid (prev_cpu , NULL ))
944- return - EINVAL ;
945-
946- if (!check_builtin_idle_enabled ())
947- return - EBUSY ;
948-
949- /*
950- * If called from an unlocked context, acquire the task's rq lock,
951- * so that we can safely access p->cpus_ptr and p->nr_cpus_allowed.
952- *
953- * Otherwise, allow to use this kfunc only from ops.select_cpu()
954- * and ops.select_enqueue().
955- */
956- if (scx_kf_allowed_if_unlocked ()) {
957- rq = task_rq_lock (p , & rf );
958- } else {
959- if (!scx_kf_allowed (SCX_KF_SELECT_CPU | SCX_KF_ENQUEUE ))
960- return - EPERM ;
961- rq = scx_locked_rq ();
962- }
963-
964- /*
965- * Validate locking correctness to access p->cpus_ptr and
966- * p->nr_cpus_allowed: if we're holding an rq lock, we're safe;
967- * otherwise, assert that p->pi_lock is held.
968- */
969- if (!rq )
970- lockdep_assert_held (& p -> pi_lock );
971-
972- #ifdef CONFIG_SMP
973- /*
974- * This may also be called from ops.enqueue(), so we need to handle
975- * per-CPU tasks as well. For these tasks, we can skip all idle CPU
976- * selection optimizations and simply check whether the previously
977- * used CPU is idle and within the allowed cpumask.
978- */
979- if (p -> nr_cpus_allowed == 1 ) {
980- if (cpumask_test_cpu (prev_cpu , cpus_allowed ) &&
981- scx_idle_test_and_clear_cpu (prev_cpu ))
982- cpu = prev_cpu ;
983- else
984- cpu = - EBUSY ;
985- } else {
986- cpu = scx_select_cpu_dfl (p , prev_cpu , wake_flags , cpus_allowed , flags );
987- }
988- #else
989- cpu = - EBUSY ;
990- #endif
991- if (scx_kf_allowed_if_unlocked ())
992- task_rq_unlock (rq , p , & rf );
993-
994- return cpu ;
989+ return select_cpu_from_kfunc (p , prev_cpu , wake_flags , cpus_allowed , flags );
995990}
996991
997992/**
@@ -1294,28 +1289,19 @@ BTF_ID_FLAGS(func, scx_bpf_pick_idle_cpu, KF_RCU)
12941289BTF_ID_FLAGS (func , scx_bpf_pick_any_cpu_node , KF_RCU )
12951290BTF_ID_FLAGS (func , scx_bpf_pick_any_cpu , KF_RCU )
12961291BTF_ID_FLAGS (func , scx_bpf_select_cpu_and , KF_RCU )
1292+ BTF_ID_FLAGS (func , scx_bpf_select_cpu_dfl , KF_RCU )
12971293BTF_KFUNCS_END (scx_kfunc_ids_idle )
12981294
12991295static const struct btf_kfunc_id_set scx_kfunc_set_idle = {
13001296 .owner = THIS_MODULE ,
13011297 .set = & scx_kfunc_ids_idle ,
13021298};
13031299
1304- BTF_KFUNCS_START (scx_kfunc_ids_select_cpu )
1305- BTF_ID_FLAGS (func , scx_bpf_select_cpu_dfl , KF_RCU )
1306- BTF_KFUNCS_END (scx_kfunc_ids_select_cpu )
1307-
1308- static const struct btf_kfunc_id_set scx_kfunc_set_select_cpu = {
1309- .owner = THIS_MODULE ,
1310- .set = & scx_kfunc_ids_select_cpu ,
1311- };
1312-
13131300int scx_idle_init (void )
13141301{
13151302 int ret ;
13161303
1317- ret = register_btf_kfunc_id_set (BPF_PROG_TYPE_STRUCT_OPS , & scx_kfunc_set_select_cpu ) ||
1318- register_btf_kfunc_id_set (BPF_PROG_TYPE_STRUCT_OPS , & scx_kfunc_set_idle ) ||
1304+ ret = register_btf_kfunc_id_set (BPF_PROG_TYPE_STRUCT_OPS , & scx_kfunc_set_idle ) ||
13191305 register_btf_kfunc_id_set (BPF_PROG_TYPE_TRACING , & scx_kfunc_set_idle ) ||
13201306 register_btf_kfunc_id_set (BPF_PROG_TYPE_SYSCALL , & scx_kfunc_set_idle );
13211307
0 commit comments