Skip to content

Commit c414c21

Browse files
arighihtejun
authored andcommitted
sched_ext: idle: Honor idle flags in the built-in idle selection policy
Enable passing idle flags (%SCX_PICK_IDLE_*) to scx_select_cpu_dfl(), to enforce strict selection criteria, such as selecting an idle CPU strictly within @prev_cpu's node or choosing only a fully idle SMT core. This functionality will be exposed through a dedicated kfunc in a separate patch. Signed-off-by: Andrea Righi <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent 97e13ec commit c414c21

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

kernel/sched/ext.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3396,7 +3396,7 @@ static int select_task_rq_scx(struct task_struct *p, int prev_cpu, int wake_flag
33963396
bool found;
33973397
s32 cpu;
33983398

3399-
cpu = scx_select_cpu_dfl(p, prev_cpu, wake_flags, &found);
3399+
cpu = scx_select_cpu_dfl(p, prev_cpu, wake_flags, 0, &found);
34003400
p->scx.selected_cpu = cpu;
34013401
if (found) {
34023402
p->scx.slice = SCX_SLICE_DFL;

kernel/sched/ext_idle.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ void scx_idle_update_selcpu_topology(struct sched_ext_ops *ops)
418418
* NOTE: tasks that can only run on 1 CPU are excluded by this logic, because
419419
* we never call ops.select_cpu() for them, see select_task_rq().
420420
*/
421-
s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, bool *found)
421+
s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, u64 flags, bool *found)
422422
{
423423
const struct cpumask *llc_cpus = NULL;
424424
const struct cpumask *numa_cpus = NULL;
@@ -455,12 +455,13 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, bool
455455
* If WAKE_SYNC, try to migrate the wakee to the waker's CPU.
456456
*/
457457
if (wake_flags & SCX_WAKE_SYNC) {
458-
cpu = smp_processor_id();
458+
int waker_node;
459459

460460
/*
461461
* If the waker's CPU is cache affine and prev_cpu is idle,
462462
* then avoid a migration.
463463
*/
464+
cpu = smp_processor_id();
464465
if (cpus_share_cache(cpu, prev_cpu) &&
465466
scx_idle_test_and_clear_cpu(prev_cpu)) {
466467
cpu = prev_cpu;
@@ -480,9 +481,11 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, bool
480481
* piled up on it even if there is an idle core elsewhere on
481482
* the system.
482483
*/
484+
waker_node = cpu_to_node(cpu);
483485
if (!(current->flags & PF_EXITING) &&
484486
cpu_rq(cpu)->scx.local_dsq.nr == 0 &&
485-
!cpumask_empty(idle_cpumask(cpu_to_node(cpu))->cpu)) {
487+
(!(flags & SCX_PICK_IDLE_IN_NODE) || (waker_node == node)) &&
488+
!cpumask_empty(idle_cpumask(waker_node)->cpu)) {
486489
if (cpumask_test_cpu(cpu, p->cpus_ptr))
487490
goto cpu_found;
488491
}
@@ -521,15 +524,25 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, bool
521524
}
522525

523526
/*
524-
* Search for any full idle core usable by the task.
527+
* Search for any full-idle core usable by the task.
525528
*
526-
* If NUMA aware idle selection is enabled, the search will
529+
* If the node-aware idle CPU selection policy is enabled
530+
* (%SCX_OPS_BUILTIN_IDLE_PER_NODE), the search will always
527531
* begin in prev_cpu's node and proceed to other nodes in
528532
* order of increasing distance.
529533
*/
530-
cpu = scx_pick_idle_cpu(p->cpus_ptr, node, SCX_PICK_IDLE_CORE);
534+
cpu = scx_pick_idle_cpu(p->cpus_ptr, node, flags | SCX_PICK_IDLE_CORE);
531535
if (cpu >= 0)
532536
goto cpu_found;
537+
538+
/*
539+
* Give up if we're strictly looking for a full-idle SMT
540+
* core.
541+
*/
542+
if (flags & SCX_PICK_IDLE_CORE) {
543+
cpu = prev_cpu;
544+
goto out_unlock;
545+
}
533546
}
534547

535548
/*
@@ -560,18 +573,24 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, bool
560573

561574
/*
562575
* Search for any idle CPU usable by the task.
576+
*
577+
* If the node-aware idle CPU selection policy is enabled
578+
* (%SCX_OPS_BUILTIN_IDLE_PER_NODE), the search will always begin
579+
* in prev_cpu's node and proceed to other nodes in order of
580+
* increasing distance.
563581
*/
564-
cpu = scx_pick_idle_cpu(p->cpus_ptr, node, 0);
582+
cpu = scx_pick_idle_cpu(p->cpus_ptr, node, flags);
565583
if (cpu >= 0)
566584
goto cpu_found;
567585

568-
rcu_read_unlock();
569-
return prev_cpu;
586+
cpu = prev_cpu;
587+
goto out_unlock;
570588

571589
cpu_found:
590+
*found = true;
591+
out_unlock:
572592
rcu_read_unlock();
573593

574-
*found = true;
575594
return cpu;
576595
}
577596

@@ -810,7 +829,7 @@ __bpf_kfunc s32 scx_bpf_select_cpu_dfl(struct task_struct *p, s32 prev_cpu,
810829
goto prev_cpu;
811830

812831
#ifdef CONFIG_SMP
813-
return scx_select_cpu_dfl(p, prev_cpu, wake_flags, is_idle);
832+
return scx_select_cpu_dfl(p, prev_cpu, wake_flags, 0, is_idle);
814833
#endif
815834

816835
prev_cpu:

kernel/sched/ext_idle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static inline s32 scx_pick_idle_cpu(const struct cpumask *cpus_allowed, int node
2727
}
2828
#endif /* CONFIG_SMP */
2929

30-
s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, bool *found);
30+
s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, u64 flags, bool *found);
3131
void scx_idle_enable(struct sched_ext_ops *ops);
3232
void scx_idle_disable(void);
3333
int scx_idle_init(void);

0 commit comments

Comments
 (0)