Skip to content

Commit 5209c03

Browse files
committed
sched_ext: Rename scx_bpf_consume() to scx_bpf_dsq_move_to_local()
In sched_ext API, a repeatedly reported pain point is the overuse of the verb "dispatch" and confusion around "consume": - ops.dispatch() - scx_bpf_dispatch[_vtime]() - scx_bpf_consume() - scx_bpf_dispatch[_vtime]_from_dsq*() This overloading of the term is historical. Originally, there were only built-in DSQs and moving a task into a DSQ always dispatched it for execution. Using the verb "dispatch" for the kfuncs to move tasks into these DSQs made sense. Later, user DSQs were added and scx_bpf_dispatch[_vtime]() updated to be able to insert tasks into any DSQ. The only allowed DSQ to DSQ transfer was from a non-local DSQ to a local DSQ and this operation was named "consume". This was already confusing as a task could be dispatched to a user DSQ from ops.enqueue() and then the DSQ would have to be consumed in ops.dispatch(). Later addition of scx_bpf_dispatch_from_dsq*() made the confusion even worse as "dispatch" in this context meant moving a task to an arbitrary DSQ from a user DSQ. Clean up the API with the following renames: 1. scx_bpf_dispatch[_vtime]() -> scx_bpf_dsq_insert[_vtime]() 2. scx_bpf_consume() -> scx_bpf_dsq_move_to_local() 3. scx_bpf_dispatch[_vtime]_from_dsq*() -> scx_bpf_dsq_move[_vtime]*() This patch performs the second rename. Compatibility is maintained by: - The previous kfunc names are still provided by the kernel so that old binaries can run. Kernel generates a warning when the old names are used. - compat.bpf.h provides wrappers for the new names which automatically fall back to the old names when running on older kernels. They also trigger build error if old names are used for new builds. The compat features will be dropped after v6.15. v2: Comment and documentation updates. Signed-off-by: Tejun Heo <[email protected]> Acked-by: Andrea Righi <[email protected]> Acked-by: Changwoo Min <[email protected]> Acked-by: Johannes Bechberger <[email protected]> Acked-by: Giovanni Gherdovich <[email protected]> Cc: Dan Schatzberg <[email protected]> Cc: Ming Yang <[email protected]>
1 parent cc26abb commit 5209c03

File tree

8 files changed

+58
-37
lines changed

8 files changed

+58
-37
lines changed

Documentation/scheduler/sched-ext.rst

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,12 @@ an arbitrary number of dsq's using ``scx_bpf_create_dsq()`` and
203203
``scx_bpf_destroy_dsq()``.
204204

205205
A CPU always executes a task from its local DSQ. A task is "inserted" into a
206-
DSQ. A non-local DSQ is "consumed" to transfer a task to the consuming CPU's
207-
local DSQ.
206+
DSQ. A task in a non-local DSQ is "move"d into the target CPU's local DSQ.
208207

209208
When a CPU is looking for the next task to run, if the local DSQ is not
210-
empty, the first task is picked. Otherwise, the CPU tries to consume the
211-
global DSQ. If that doesn't yield a runnable task either, ``ops.dispatch()``
212-
is invoked.
209+
empty, the first task is picked. Otherwise, the CPU tries to move a task
210+
from the global DSQ. If that doesn't yield a runnable task either,
211+
``ops.dispatch()`` is invoked.
213212

214213
Scheduling Cycle
215214
----------------
@@ -265,15 +264,15 @@ The following briefly shows how a waking task is scheduled and executed.
265264
rather than performing them immediately. There can be up to
266265
``ops.dispatch_max_batch`` pending tasks.
267266

268-
* ``scx_bpf_consume()`` tranfers a task from the specified non-local DSQ
269-
to the dispatching DSQ. This function cannot be called with any BPF
270-
locks held. ``scx_bpf_consume()`` flushes the pending dispatched tasks
271-
before trying to consume the specified DSQ.
267+
* ``scx_bpf_move_to_local()`` moves a task from the specified non-local
268+
DSQ to the dispatching DSQ. This function cannot be called with any BPF
269+
locks held. ``scx_bpf_move_to_local()`` flushes the pending insertions
270+
tasks before trying to move from the specified DSQ.
272271

273272
4. After ``ops.dispatch()`` returns, if there are tasks in the local DSQ,
274273
the CPU runs the first one. If empty, the following steps are taken:
275274

276-
* Try to consume the global DSQ. If successful, run the task.
275+
* Try to move from the global DSQ. If successful, run the task.
277276

278277
* If ``ops.dispatch()`` has dispatched any tasks, retry #3.
279278

@@ -286,7 +285,7 @@ Note that the BPF scheduler can always choose to dispatch tasks immediately
286285
in ``ops.enqueue()`` as illustrated in the above simple example. If only the
287286
built-in DSQs are used, there is no need to implement ``ops.dispatch()`` as
288287
a task is never queued on the BPF scheduler and both the local and global
289-
DSQs are consumed automatically.
288+
DSQs are executed automatically.
290289

291290
``scx_bpf_dsq_insert()`` inserts the task on the FIFO of the target DSQ. Use
292291
``scx_bpf_dsq_insert_vtime()`` for the priority queue. Internal DSQs such as

kernel/sched/ext.c

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -264,25 +264,25 @@ struct sched_ext_ops {
264264
void (*dequeue)(struct task_struct *p, u64 deq_flags);
265265

266266
/**
267-
* dispatch - Dispatch tasks from the BPF scheduler and/or consume DSQs
267+
* dispatch - Dispatch tasks from the BPF scheduler and/or user DSQs
268268
* @cpu: CPU to dispatch tasks for
269269
* @prev: previous task being switched out
270270
*
271271
* Called when a CPU's local dsq is empty. The operation should dispatch
272272
* one or more tasks from the BPF scheduler into the DSQs using
273-
* scx_bpf_dsq_insert() and/or consume user DSQs into the local DSQ
274-
* using scx_bpf_consume().
273+
* scx_bpf_dsq_insert() and/or move from user DSQs into the local DSQ
274+
* using scx_bpf_dsq_move_to_local().
275275
*
276276
* The maximum number of times scx_bpf_dsq_insert() can be called
277-
* without an intervening scx_bpf_consume() is specified by
277+
* without an intervening scx_bpf_dsq_move_to_local() is specified by
278278
* ops.dispatch_max_batch. See the comments on top of the two functions
279279
* for more details.
280280
*
281281
* When not %NULL, @prev is an SCX task with its slice depleted. If
282282
* @prev is still runnable as indicated by set %SCX_TASK_QUEUED in
283283
* @prev->scx.flags, it is not enqueued yet and will be enqueued after
284284
* ops.dispatch() returns. To keep executing @prev, return without
285-
* dispatching or consuming any tasks. Also see %SCX_OPS_ENQ_LAST.
285+
* dispatching or moving any tasks. Also see %SCX_OPS_ENQ_LAST.
286286
*/
287287
void (*dispatch)(s32 cpu, struct task_struct *prev);
288288

@@ -6372,13 +6372,17 @@ __bpf_kfunc void scx_bpf_dispatch(struct task_struct *p, u64 dsq_id, u64 slice,
63726372
* @enq_flags: SCX_ENQ_*
63736373
*
63746374
* Insert @p into the vtime priority queue of the DSQ identified by @dsq_id.
6375-
* Tasks queued into the priority queue are ordered by @vtime and always
6376-
* consumed after the tasks in the FIFO queue. All other aspects are identical
6377-
* to scx_bpf_dsq_insert().
6375+
* Tasks queued into the priority queue are ordered by @vtime. All other aspects
6376+
* are identical to scx_bpf_dsq_insert().
63786377
*
63796378
* @vtime ordering is according to time_before64() which considers wrapping. A
63806379
* numerically larger vtime may indicate an earlier position in the ordering and
63816380
* vice-versa.
6381+
*
6382+
* A DSQ can only be used as a FIFO or priority queue at any given time and this
6383+
* function must not be called on a DSQ which already has one or more FIFO tasks
6384+
* queued and vice-versa. Also, the built-in DSQs (SCX_DSQ_LOCAL and
6385+
* SCX_DSQ_GLOBAL) cannot be used as priority queues.
63826386
*/
63836387
__bpf_kfunc void scx_bpf_dsq_insert_vtime(struct task_struct *p, u64 dsq_id,
63846388
u64 slice, u64 vtime, u64 enq_flags)
@@ -6539,21 +6543,20 @@ __bpf_kfunc void scx_bpf_dispatch_cancel(void)
65396543
}
65406544

65416545
/**
6542-
* scx_bpf_consume - Transfer a task from a DSQ to the current CPU's local DSQ
6543-
* @dsq_id: DSQ to consume
6546+
* scx_bpf_dsq_move_to_local - move a task from a DSQ to the current CPU's local DSQ
6547+
* @dsq_id: DSQ to move task from
65446548
*
6545-
* Consume a task from the non-local DSQ identified by @dsq_id and transfer it
6546-
* to the current CPU's local DSQ for execution. Can only be called from
6547-
* ops.dispatch().
6549+
* Move a task from the non-local DSQ identified by @dsq_id to the current CPU's
6550+
* local DSQ for execution. Can only be called from ops.dispatch().
65486551
*
65496552
* This function flushes the in-flight dispatches from scx_bpf_dsq_insert()
6550-
* before trying to consume the specified DSQ. It may also grab rq locks and
6553+
* before trying to move from the specified DSQ. It may also grab rq locks and
65516554
* thus can't be called under any BPF locks.
65526555
*
6553-
* Returns %true if a task has been consumed, %false if there isn't any task to
6554-
* consume.
6556+
* Returns %true if a task has been moved, %false if there isn't any task to
6557+
* move.
65556558
*/
6556-
__bpf_kfunc bool scx_bpf_consume(u64 dsq_id)
6559+
__bpf_kfunc bool scx_bpf_dsq_move_to_local(u64 dsq_id)
65576560
{
65586561
struct scx_dsp_ctx *dspc = this_cpu_ptr(scx_dsp_ctx);
65596562
struct scx_dispatch_q *dsq;
@@ -6583,6 +6586,13 @@ __bpf_kfunc bool scx_bpf_consume(u64 dsq_id)
65836586
}
65846587
}
65856588

6589+
/* for backward compatibility, will be removed in v6.15 */
6590+
__bpf_kfunc bool scx_bpf_consume(u64 dsq_id)
6591+
{
6592+
printk_deferred_once(KERN_WARNING "sched_ext: scx_bpf_consume() renamed to scx_bpf_dsq_move_to_local()");
6593+
return scx_bpf_dsq_move_to_local(dsq_id);
6594+
}
6595+
65866596
/**
65876597
* scx_bpf_dispatch_from_dsq_set_slice - Override slice when dispatching from DSQ
65886598
* @it__iter: DSQ iterator in progress
@@ -6684,6 +6694,7 @@ __bpf_kfunc_end_defs();
66846694
BTF_KFUNCS_START(scx_kfunc_ids_dispatch)
66856695
BTF_ID_FLAGS(func, scx_bpf_dispatch_nr_slots)
66866696
BTF_ID_FLAGS(func, scx_bpf_dispatch_cancel)
6697+
BTF_ID_FLAGS(func, scx_bpf_dsq_move_to_local)
66876698
BTF_ID_FLAGS(func, scx_bpf_consume)
66886699
BTF_ID_FLAGS(func, scx_bpf_dispatch_from_dsq_set_slice)
66896700
BTF_ID_FLAGS(func, scx_bpf_dispatch_from_dsq_set_vtime)

tools/sched_ext/include/scx/common.bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void scx_bpf_dsq_insert(struct task_struct *p, u64 dsq_id, u64 slice, u64 enq_fl
4040
void scx_bpf_dsq_insert_vtime(struct task_struct *p, u64 dsq_id, u64 slice, u64 vtime, u64 enq_flags) __ksym __weak;
4141
u32 scx_bpf_dispatch_nr_slots(void) __ksym;
4242
void scx_bpf_dispatch_cancel(void) __ksym;
43-
bool scx_bpf_consume(u64 dsq_id) __ksym;
43+
bool scx_bpf_dsq_move_to_local(u64 dsq_id) __ksym;
4444
void scx_bpf_dispatch_from_dsq_set_slice(struct bpf_iter_scx_dsq *it__iter, u64 slice) __ksym __weak;
4545
void scx_bpf_dispatch_from_dsq_set_vtime(struct bpf_iter_scx_dsq *it__iter, u64 vtime) __ksym __weak;
4646
bool scx_bpf_dispatch_from_dsq(struct bpf_iter_scx_dsq *it__iter, struct task_struct *p, u64 dsq_id, u64 enq_flags) __ksym __weak;

tools/sched_ext/include/scx/compat.bpf.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
*/
4444
void scx_bpf_dispatch___compat(struct task_struct *p, u64 dsq_id, u64 slice, u64 enq_flags) __ksym __weak;
4545
void scx_bpf_dispatch_vtime___compat(struct task_struct *p, u64 dsq_id, u64 slice, u64 vtime, u64 enq_flags) __ksym __weak;
46+
bool scx_bpf_consume___compat(u64 dsq_id) __ksym __weak;
4647

4748
#define scx_bpf_dsq_insert(p, dsq_id, slice, enq_flags) \
4849
(bpf_ksym_exists(scx_bpf_dsq_insert) ? \
@@ -54,12 +55,22 @@ void scx_bpf_dispatch_vtime___compat(struct task_struct *p, u64 dsq_id, u64 slic
5455
scx_bpf_dsq_insert_vtime((p), (dsq_id), (slice), (vtime), (enq_flags)) : \
5556
scx_bpf_dispatch_vtime___compat((p), (dsq_id), (slice), (vtime), (enq_flags)))
5657

58+
#define scx_bpf_dsq_move_to_local(dsq_id) \
59+
(bpf_ksym_exists(scx_bpf_dsq_move_to_local) ? \
60+
scx_bpf_dsq_move_to_local((dsq_id)) : \
61+
scx_bpf_consume___compat((dsq_id)))
62+
5763
#define scx_bpf_dispatch(p, dsq_id, slice, enq_flags) \
5864
_Static_assert(false, "scx_bpf_dispatch() renamed to scx_bpf_dsq_insert()")
5965

6066
#define scx_bpf_dispatch_vtime(p, dsq_id, slice, vtime, enq_flags) \
6167
_Static_assert(false, "scx_bpf_dispatch_vtime() renamed to scx_bpf_dsq_insert_vtime()")
6268

69+
#define scx_bpf_consume(dsq_id) ({ \
70+
_Static_assert(false, "scx_bpf_consume() renamed to scx_bpf_dsq_move_to_local()"); \
71+
false; \
72+
})
73+
6374
/*
6475
* Define sched_ext_ops. This may be expanded to define multiple variants for
6576
* backward compatibility. See compat.h::SCX_OPS_LOAD/ATTACH().

tools/sched_ext/scx_central.bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,13 @@ void BPF_STRUCT_OPS(central_dispatch, s32 cpu, struct task_struct *prev)
219219
}
220220

221221
/* look for a task to run on the central CPU */
222-
if (scx_bpf_consume(FALLBACK_DSQ_ID))
222+
if (scx_bpf_dsq_move_to_local(FALLBACK_DSQ_ID))
223223
return;
224224
dispatch_to_cpu(central_cpu);
225225
} else {
226226
bool *gimme;
227227

228-
if (scx_bpf_consume(FALLBACK_DSQ_ID))
228+
if (scx_bpf_dsq_move_to_local(FALLBACK_DSQ_ID))
229229
return;
230230

231231
gimme = ARRAY_ELEM_PTR(cpu_gimme_task, cpu, nr_cpu_ids);

tools/sched_ext/scx_flatcg.bpf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ static bool try_pick_next_cgroup(u64 *cgidp)
665665
goto out_free;
666666
}
667667

668-
if (!scx_bpf_consume(cgid)) {
668+
if (!scx_bpf_dsq_move_to_local(cgid)) {
669669
bpf_cgroup_release(cgrp);
670670
stat_inc(FCG_STAT_PNC_EMPTY);
671671
goto out_stash;
@@ -745,7 +745,7 @@ void BPF_STRUCT_OPS(fcg_dispatch, s32 cpu, struct task_struct *prev)
745745
goto pick_next_cgroup;
746746

747747
if (vtime_before(now, cpuc->cur_at + cgrp_slice_ns)) {
748-
if (scx_bpf_consume(cpuc->cur_cgid)) {
748+
if (scx_bpf_dsq_move_to_local(cpuc->cur_cgid)) {
749749
stat_inc(FCG_STAT_CNS_KEEP);
750750
return;
751751
}
@@ -785,7 +785,7 @@ void BPF_STRUCT_OPS(fcg_dispatch, s32 cpu, struct task_struct *prev)
785785
pick_next_cgroup:
786786
cpuc->cur_at = now;
787787

788-
if (scx_bpf_consume(FALLBACK_DSQ)) {
788+
if (scx_bpf_dsq_move_to_local(FALLBACK_DSQ)) {
789789
cpuc->cur_cgid = 0;
790790
return;
791791
}

tools/sched_ext/scx_qmap.bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ void BPF_STRUCT_OPS(qmap_dispatch, s32 cpu, struct task_struct *prev)
374374
if (dispatch_highpri(false))
375375
return;
376376

377-
if (!nr_highpri_queued && scx_bpf_consume(SHARED_DSQ))
377+
if (!nr_highpri_queued && scx_bpf_dsq_move_to_local(SHARED_DSQ))
378378
return;
379379

380380
if (dsp_inf_loop_after && nr_dispatched > dsp_inf_loop_after) {
@@ -439,7 +439,7 @@ void BPF_STRUCT_OPS(qmap_dispatch, s32 cpu, struct task_struct *prev)
439439
if (!batch || !scx_bpf_dispatch_nr_slots()) {
440440
if (dispatch_highpri(false))
441441
return;
442-
scx_bpf_consume(SHARED_DSQ);
442+
scx_bpf_dsq_move_to_local(SHARED_DSQ);
443443
return;
444444
}
445445
if (!cpuc->dsp_cnt)

tools/sched_ext/scx_simple.bpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ void BPF_STRUCT_OPS(simple_enqueue, struct task_struct *p, u64 enq_flags)
9494

9595
void BPF_STRUCT_OPS(simple_dispatch, s32 cpu, struct task_struct *prev)
9696
{
97-
scx_bpf_consume(SHARED_DSQ);
97+
scx_bpf_dsq_move_to_local(SHARED_DSQ);
9898
}
9999

100100
void BPF_STRUCT_OPS(simple_running, struct task_struct *p)

0 commit comments

Comments
 (0)