scxModule
Linux Extensible Scheduler (sched_ext) integration.
This library allows Lua scripts to interact with the kernel’s sched_ext subsystem. It enables sched_ext/eBPF programs to call Lua functions for task scheduling, providing a flexible way to implement custom scheduling logic in Lua. The primary mechanism involves an sched_ext program calling the bpf_luascx_run
kfunc, which in turn invokes a Lua callback function previously registered
using scx.attach().
The callback runs inside the sched_ext operation that calls the kfunc, and ops.enqueue
runs with the runqueue lock of its CPU held, so a callback must not call print, a
completion’s complete or a mailbox’s send: each can wake a task, and the wakeup takes
that lock again on a CPU that already holds it. An allocation the callback’s Lua makes
under memory pressure, which can wake kswapd, and the log of an error the callback raises
can wake a task the same way.
Needs 6.12 and later, with CONFIG_SCHED_CLASS_EXT; without it the module loads
and offers attach, which raises EOPNOTSUPP, and detach, which does nothing.
The kfunc needs the module’s BTF: run sudo make btf_install before make, or the kernel logs
missing module BTF, cannot register kfuncs and an eBPF program that calls
bpf_luascx_run does not load. The eBPF side is a sched_ext struct_ops
scheduler; tests/scx/scx_pass.bpf.c with tests/scx/pass.lua is a worked
pair.
Class scx_ctx
| scx_ctx:task () | Returns the object for the current task. |
scx
| attach (callback) | Registers a Lua callback function to be invoked by a sched_ext eBPF program. |
| detach () | Unregisters the Lua callback function associated with the current Lunatik runtime. |
Class scx_ctx in detail
- scx_ctx:task ()
-
Returns the object for the current task.
The same task object is reused for every callback: it is valid only during the
callback that returned it, and later it raises or reads the task of the callback
then running.
Returns
scx in detail
- attach (callback)
-
Registers a Lua callback function to be invoked by a sched_ext eBPF program.
When a sched_ext program calls the
bpf_luascx_runkfunc, Lunatik will execute the registered Luacallbackassociated with the current Lunatik runtime. The runtime must be a hardirq one (lunatik run -c hardirq <script>). Calling it again replaces the previous callback.The eBPF program declares the kfunc as:
extern int bpf_luascx_run(char *key, size_t key__sz, struct task_struct *task, struct luascx_task_class *cls) __ksym;key: the name of the Lunatik runtime, the script as given tolunatik runwithout.lua(e.g. “sched/policy”; a path keeps its directory). It is looked up in Lunatik’s table of active runtimes.key__sz:sizeofthe key array, the NUL terminator included.- the task pointer: the task being scheduled.
cls: where the decision is written, a struct of twou64, the dispatch queue and then the slice.
It returns 0 once the callback decided and
clsis filled, and -1, leavingclsas it was, whenclsis NULL or no callback decided.Parameters
- callback
function
Lua function to call. It receives one argument:
ctx: An scx_ctx context object used to inspect the task.It returns the decision, the dispatch queue and then the slice in nanoseconds, which
bpf_luascx_runwrites tocls; a nil one takesSCX_DSQ_GLOBALorSCX_SLICE_DFL. When it returns neither, or raises,bpf_luascx_runreturns -1 and the decision is left to the eBPF program; a value that is not a number is logged asinvalid task classand answered the same way.
Returns
-
nil
Raises
EOPNOTSUPPon a kernel without sched_ext;runtime context mismatchunless the runtime is hardirq;not allowed while the runtime closesfrom a finalizer that runs at its close; or on allocation failure.See also
Usage
-- sched/policy.lua, run with
lunatik run -c hardirq sched/policylocal scx = require("scx") local ext = require("linux.scx") local function my_scheduler(ctx) local task = ctx:task() if task:comm() == "bash" then return ext.dsq.LOCAL, ext.slice.DFL end end scx.attach(my_scheduler) -- In eBPF C code, to call the above Lua function: -- char rt_key[] = "sched/policy"; // the script, without .lua -- int ret = bpf_luascx_run(rt_key, sizeof(rt_key), p, cls); - detach ()
-
Unregisters the Lua callback function associated with the current Lunatik runtime.
After calling this,
bpf_luascx_runcalls targeting this runtime invoke no Lua function: they logno callback attached, return -1 and leave the decision to the eBPF program.Returns
-
nil
Usage
scx.detach()