scx_bpf_dsq_insert___v2(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… scx_bpf_dsq_insert___v2 πŸ’…

okay bestie, welcome to the Kernel API Manual β€” this page is scx_bpf_dsq_insert___v2(9) and it's literally the "put a task in the queue" function. let's go πŸŽ€


✨ NAME ✨

scx_bpf_dsq_insert___v2 β€” insert a task into the FIFO queue of a DSQ πŸ¦‹


🌸 SYNOPSIS 🌸

__bpf_kfunc bool scx_bpf_dsq_insert___v2 (struct task_struct *p , u64
dsq_id , u64 slice , u64 enq_flags , const struct bpf_prog_aux *aux );

πŸ’– ARGUMENTS πŸ’–

  • p β€” the task_struct you're inserting, bestie. the main character.
  • dsq_id β€” which DSQ you're inserting into.
  • slice β€” how long p is allowed to run for, in nsecs. pass 0 to just keep whatever the current value is.
  • enq_flags β€” the SCX_ENQ_* flags.
  • aux β€” implicit BPF argument so the function can reach bpf_prog_aux. it's hidden from BPF progs, so don't come looking for it πŸ‘€

πŸ‘‘ DESCRIPTION πŸ‘‘

so what it does: it inserts p into the FIFO queue of the DSQ identified by dsq_id. and get this β€” it is safe to call this function spuriously. iconic behavior honestly. you can call it from ops.enqueue, ops.select_cpu, and ops.dispatch. πŸ’…


🧚 calling it from ops.select_cpu or ops.enqueue 🧚

when you call it from ops.select_cpu or ops.enqueue, that's direct dispatch β€” and p must match the task being enqueued. no substitutions, periodt. πŸ’€

when it's from ops.select_cpu, enq_flags and dsq_id get stored, and p will be directly inserted into the corresponding dispatch queue after ops.select_cpu returns. and if p is inserted into SCX_DSQ_LOCAL, it'll get inserted into the local DSQ of the CPU that ops.select_cpu returned. the enq_flags get OR'd with the enqueue flags on the enqueue path before the task is inserted. slay. πŸ”₯


🌈 calling it from ops.dispatch 🌈

when it's from ops.dispatch, there are no restrictions on p or dsq_id β€” go off πŸ‘‘ β€” and you can call this function upto ops.dispatch_max_batch times to insert multiple tasks. scx_bpf_dispatch_nr_slots returns the number of the remaining slots. scx_bpf_dsq_move_to_local flushes the batch and resets the counter. the way that just works 🫢


πŸ”’ locking, or rather the lack of it πŸ”’

this function doesn't have any locking restrictions and may be called under BPF locks β€” and yes, that's in the future when BPF introduces more flexible locking. iykyk. ✨


⏳ slice behavior ⏳

p is allowed to run for slice. the scheduling path is triggered on slice exhaustion. details, bestie:

  • if slice is zero, the current residual slice is maintained.
  • if it's SCX_SLICE_INF, p never expires and the BPF scheduler must kick the CPU with scx_bpf_kick_cpu to trigger scheduling. don't forget, or nothing happens 😭

πŸ’€ return value πŸ’€

returns true on successful insertion, false on failure.

okay important part: on the root scheduler, a false return triggers scheduler abort β€” and the caller doesn't need to check the return value. so like, you literally can't fail there. cute.

πŸ“ SEE ALSO πŸ“

kernel file ./kernel/sched/ext/ext.c, 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), finish_dispatch(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_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 page!! 🫢 mwah πŸ’‹

sign-off time bestie: this one lives in ./kernel/sched/ext, dated October 2026, and it's scx_bpf_dsq_insert___v2(9) β€” go forth and insert some tasks βœ¨πŸŽ€πŸ’œ

πŸ“¦ where this page comes from