finish_dispatch(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… finish_dispatch(9) β€” like, the Kernel API Manual page, bestie ✨

okay so picture this: it's giving "kernel scheduler lore" and honestly? iconic. this is the man page for finish_dispatch, straight out of the Kernel API Manual, and we're gonna get through it together. no cap. 🫢


✨ NAME ✨

finish_dispatch β€” asynchronously finish dispatching a task πŸ’«


🌸 SYNOPSIS 🌸

void finish_dispatch (struct scx_sched *sch , struct rq *rq , struct
task_struct *p , unsigned long qseq_at_dispatch , u64 dsq_id , u64 slice
, u64 vtime , u64 enq_flags );

like yes that's a lot of parameters. we're gonna go through every single one. hydrate first. πŸ“


πŸŽ€ ARGUMENTS πŸŽ€

  • sch β€” the scheduler. the main character, obviously πŸ‘‘
  • rq β€” the current rq, and heads up bestie: it's locked πŸ”’
  • p β€” the task that's finishing up its dispatching moment ✨
  • qseq_at_dispatch β€” the qseq from back when p started getting dispatched. like a timestamp but for queueing, iykyk πŸ•°οΈ
  • dsq_id β€” destination DSQ ID 🎯
  • slice β€” the slice carried by the insert verdict. ngl, 0 keeps the current value πŸ’…
  • vtime β€” the vtime carried by the insert verdict β€” this one gets committed on PRIQ inserts ⭐
  • enq_flags β€” SCX_ENQ_*. that's it, that's the description πŸ¦‹

πŸ’œ DESCRIPTION πŸ’œ

so here's the vibe: dispatching to local DSQs might have to wait for queueing to finish, or it might need rq lock dancing 😭 (yes that's a real thing in here, we don't make the rules). and we're like, absolutely not doing either of those while inside ops.dispatch, because that would be locking order inversion and we simply do not do that here πŸ’€

so! dispatching gets split into two parts, periodt:

  1. scx_bpf_dsq_insert β€” called by ops.dispatch, records the task and its qseq πŸ“
  2. once ops.dispatch returns, this function gets called to finish up ✨
🚨 okay this part is so important, bestie, read it twice: there is no guarantee that p is still valid for dispatching β€” or even that it was valid in the first place 😭. make sure the task is still owned by the BPF scheduler, and claim the ownership before dispatching. fr fr, do not skip this.

πŸ¦‹ SEE ALSO πŸ¦‹

the friend group (aka the Kernel file ./kernel/sched/ext/ext.c, plus everyone in it):

scx_is_descendant(9), rq_is_open(9), scx_fill_cmask_scratch(9), scx_call_op_set_cpumask(9), nldsq_next_task(9), nldsq_cursor_next_task(9), nldsq_cursor_lost_task(9), scx_task_iter_start(9), scx_task_iter_unlock(9), scx_task_iter_relock(9), scx_task_iter_stop(9), scx_task_iter_next(9), scx_task_iter_next_locked(9), scx_dump_event(9), wait_ops_state(9), scx_cpu_valid(9), schedule_deferred(9), schedule_deferred_locked(9), dsq_insert_head(9), set_task_slice_keep_oob(9), scx_task_slice_ended(9), move_remote_task_to_local_dsq(9), unlink_dsq_and_switch_rq_lock(9), move_task_between_dsqs(9), dispatch_to_local_dsq(9), scx_prio_less(9), __scx_init_task(9), task_dead_and_done(9), scx_tg_sched(9), scx_tg_knob_sched(9), handle_lockup(9), scx_rcu_cpu_stall(9), scx_softlockup(9), scx_hardlockup(9), unbypass_renotify_idle(9), scx_bypass(9), scx_propagate_exit_irq_workfn(9), scx_flush_disable_work(9), print_scx_info(9), scx_bpf_dsq_insert___v2(9), __scx_bpf_dsq_insert_vtime(9), scx_bpf_dispatch_nr_slots(9), scx_bpf_dispatch_cancel(9), scx_bpf_dsq_move_to_local___v2(9), scx_bpf_dsq_move_set_slice(9), scx_bpf_dsq_move_set_vtime(9), scx_bpf_dsq_move(9), scx_bpf_dsq_move_vtime(9), scx_bpf_reenqueue_local(9), scx_bpf_create_dsq(9), scx_bpf_task_set_slice(9), scx_bpf_task_set_dsq_vtime(9), scx_bpf_kick_cpu(9), scx_bpf_kick_cid(9), scx_bpf_dsq_nr_queued(9), scx_bpf_destroy_dsq(9), bpf_iter_scx_dsq_new(9), bpf_iter_scx_dsq_next(9), bpf_iter_scx_dsq_destroy(9), scx_bpf_dsq_peek(9), scx_bpf_dsq_reenq(9), scx_bpf_reenqueue_local___v2(9), scx_bpf_exit_bstr(9), scx_bpf_error_bstr(9), scx_bpf_dump_bstr(9), scx_bpf_cpuperf_cap(9), scx_bpf_cidperf_cap(9), scx_bpf_cpuperf_cur(9), scx_bpf_cidperf_cur(9), scx_bpf_cpuperf_set(9), scx_bpf_cidperf_set(9), scx_bpf_nr_node_ids(9), scx_bpf_nr_cpu_ids(9), scx_bpf_nr_cids(9), scx_bpf_nr_online_cids(9), scx_bpf_online_cmask(9), scx_bpf_this_cid(9), scx_bpf_get_possible_cpumask(9), scx_bpf_get_online_cpumask(9), scx_bpf_put_cpumask(9), scx_bpf_task_running(9), scx_bpf_task_cpu(9), scx_bpf_task_cid(9), scx_bpf_locked_rq(9), scx_bpf_cpu_curr(9), scx_bpf_cid_curr(9), scx_bpf_tid_to_task(9), scx_bpf_now(9), scx_bpf_events(9), scx_bpf_task_cgroup(9)


🌈 and that's the whole page, bestie! 🌈 it lives in ./kernel/sched/ext, dated October 2026 β€” save the date, screenshot it, put it on your fridge πŸ’– mwah, go dispatch something responsibly πŸ§šβ€β™€οΈ

πŸ“¦ where this page comes from