container: expose priority and SCHED_OTHER policy
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / ShareFS (push) Successful in 40s
Test / Sandbox (push) Successful in 46s
Test / Sandbox (race detector) (push) Successful in 45s
Test / Hakurei (push) Successful in 52s
Test / Hakurei (race detector) (push) Successful in 50s
Test / Flake checks (push) Successful in 1m14s

The more explicit API removes the arbitrary limit preventing use of SCHED_OTHER (referred to as SCHED_NORMAL in the kernel). This change also exposes priority value to set.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-03-12 01:14:03 +09:00
parent 04e6bc3c5c
commit 196b200d0f
7 changed files with 34 additions and 15 deletions

View File

@@ -38,9 +38,13 @@ type (
Container struct {
// Whether the container init should stay alive after its parent terminates.
AllowOrphan bool
// Scheduling policy to set via sched_setscheduler(2). The zero value
// skips this call. Supported policies are [SCHED_BATCH], [SCHED_IDLE].
// Whether to set SchedPolicy and SchedPriority via sched_setscheduler(2).
SetScheduler bool
// Scheduling policy to set via sched_setscheduler(2).
SchedPolicy std.SchedPolicy
// Scheduling priority to set via sched_setscheduler(2). The zero value
// implies the minimum value supported by the current SchedPolicy.
SchedPriority std.Int
// Cgroup fd, nil to disable.
Cgroup *int
// ExtraFiles passed through to initial process in the container, with
@@ -373,7 +377,15 @@ func (p *Container) Start() error {
// sched_setscheduler: thread-directed but acts on all processes
// created from the calling thread
if p.SchedPolicy > 0 && p.SchedPolicy <= std.SCHED_LAST {
if p.SetScheduler {
if p.SchedPolicy < 0 || p.SchedPolicy > std.SCHED_LAST {
return &StartError{
Fatal: false,
Step: "set scheduling policy",
Err: EINVAL,
}
}
var param schedParam
if priority, err := p.SchedPolicy.GetPriorityMin(); err != nil {
return &StartError{
@@ -382,10 +394,13 @@ func (p *Container) Start() error {
Err: err,
}
} else {
param.priority = priority
param.priority = max(priority, p.SchedPriority)
}
p.msg.Verbosef("setting scheduling policy %s", p.SchedPolicy)
p.msg.Verbosef(
"setting scheduling policy %s priority %d",
p.SchedPolicy, param.priority,
)
if err := schedSetscheduler(
0, // calling thread
p.SchedPolicy,
@@ -393,7 +408,7 @@ func (p *Container) Start() error {
); err != nil {
return &StartError{
Fatal: true,
Step: "enforce landlock ruleset",
Step: "set scheduling policy",
Err: err,
}
}

View File

@@ -134,7 +134,7 @@ func (policy SchedPolicy) GetPriorityMax() (Int, error) {
0, 0,
)
schedPriority[policy][0] = Int(priority)
if schedPriority[policy][0] < 0 {
if errno != 0 {
schedPriorityErr[policy][0] = errno
}
})
@@ -151,10 +151,9 @@ func (policy SchedPolicy) GetPriorityMin() (Int, error) {
0, 0,
)
schedPriority[policy][1] = Int(priority)
if schedPriority[policy][1] < 0 {
if errno != 0 {
schedPriorityErr[policy][1] = errno
}
})
return schedPriority[policy][1], schedPriorityErr[policy][1]
}

View File

@@ -63,12 +63,12 @@ type schedParam struct {
//
// [very subtle to use correctly]: https://www.openwall.com/lists/musl/2016/03/01/4
func schedSetscheduler(tid int, policy std.SchedPolicy, param *schedParam) error {
if r, _, errno := Syscall(
if _, _, errno := Syscall(
SYS_SCHED_SETSCHEDULER,
uintptr(tid),
uintptr(policy),
uintptr(unsafe.Pointer(param)),
); r < 0 {
); errno != 0 {
return errno
}
return nil