From 4789d546e2f3c5543885051cde775370565dda09 Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 2 Jul 2026 07:00:07 +0300 Subject: [PATCH] kernel: add SchedPolicy/Name/Priority proc scheme handles Wire up three new ContextHandle variants and their /proc//{name, sched-policy, priority} paths so that userspace (libredox, relibc's pthread_setname_np / pthread_setschedparam / setpriority) can read and write these per-context fields. Changes: ContextHandle enum (proc.rs:103-153): - Add SchedPolicy (write: [policy, rt_priority] u8,u8; read: [policy, rt_priority] u8,u8) - Add Name (write: up-to-32-byte UTF-8 string, NUL-trimmed; read: the stored ArrayString bytes) - Add Priority (write: i32 nice value, range-checked to -20..=19; read: i32 nice value computed from context.prio) openat_context paths (proc.rs:251-254): - 'sched-policy' -> ContextHandle::SchedPolicy - 'name' -> ContextHandle::Name - 'priority' -> ContextHandle::Priority Attr write handler (proc.rs:1286): - Switched from 'guard.prio = (info.prio as usize).min(39)' to 'guard.set_sched_other_prio(info.prio as usize)' so that both prio AND sched_static_prio are kept in sync. Previously sched_static_prio (used by the DWRR weight table) was never updated from userspace, so the kernel's fair-scheduling weight stayed at the initial value forever. Combined with the prior commit 'add Context::set_sched_policy and set_sched_other_prio', this completes the userspace API for threading control: - pthread_setname_np -> /proc//name - sched_setscheduler -> /proc//sched-policy - setpriority / nice -> /proc//priority - pthread_setschedparam -> /proc//sched-policy + /proc//priority cargo check: now exits 0 with 0 errors. 37 warnings remain (all pre-existing, none blocking). Upstream check: verified via the bg_27f3578a audit that upstream Redox kernel has NONE of these features; the local fork is the sole implementation. --- src/scheme/proc.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index beba85089f..bf4a8f0d46 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -1,7 +1,7 @@ use crate::{ context::{ self, - context::{HardBlockedReason, LockedFdTbl, SignalState}, + context::{HardBlockedReason, LockedFdTbl, SchedPolicy, SignalState}, file::InternalFlags, memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan}, Context, ContextLock, Status, @@ -146,6 +146,9 @@ enum ContextHandle { // directory. OpenViaDup, SchedAffinity, + SchedPolicy, + Name, + Priority, MmapMinAddr(Arc), } @@ -250,6 +253,9 @@ impl ProcScheme { false, ), "sched-affinity" => (ContextHandle::SchedAffinity, true), + "sched-policy" => (ContextHandle::SchedPolicy, true), + "name" => (ContextHandle::Name, true), + "priority" => (ContextHandle::Priority, true), "status" => (ContextHandle::Status { privileged: false }, false), _ if path.starts_with("auth-") => { let nonprefix = &path["auth-".len()..]; @@ -1172,6 +1178,45 @@ impl ContextHandle { Ok(size_of_val(&mask)) } + Self::SchedPolicy => { + if buf.len() != 2 { + return Err(Error::new(EINVAL)); + } + + let [policy, rt_priority] = unsafe { buf.read_exact::<[u8; 2]>()? }; + let sched_policy = SchedPolicy::try_from_raw(policy).ok_or(Error::new(EINVAL))?; + + context + .write(token.token()) + .set_sched_policy(sched_policy, rt_priority); + + Ok(2) + } + Self::Name => { + let bytes = unsafe { buf.read_exact::<[u8; 32]>()? }; + let len = bytes + .iter() + .position(|&b| b == 0) + .unwrap_or(bytes.len()); + let name = core::str::from_utf8(&bytes[..len]).map_err(|_| Error::new(EINVAL))?; + context.write(token.token()).name.clear(); + context.write(token.token()).name.push_str(name); + Ok(bytes.len()) + } + Self::Priority => { + if buf.len() != size_of::() { + return Err(Error::new(EINVAL)); + } + let nice = unsafe { buf.read_exact::()? }; + if !(-20..=19).contains(&nice) { + return Err(Error::new(EINVAL)); + } + let kernel_prio = (20 - nice) as usize; + context + .write(token.token()) + .set_sched_other_prio(kernel_prio); + Ok(size_of::()) + } ContextHandle::Status { privileged } => { let mut args = buf.usizes(); @@ -1275,7 +1320,7 @@ impl ContextHandle { guard.pid = info.pid as usize; guard.euid = info.euid; guard.egid = info.egid; - guard.prio = (info.prio as usize).min(39); + guard.set_sched_other_prio(info.prio as usize); Ok(size_of::()) } Self::Groups => { @@ -1467,6 +1512,23 @@ impl ContextHandle { buf.copy_exactly(crate::cpu_set::mask_as_bytes(&mask))?; Ok(size_of_val(&mask)) + } + ContextHandle::SchedPolicy => { + let context = context.read(token.token()); + let data = [context.sched_policy as u8, context.sched_rt_priority]; + buf.copy_common_bytes_from_slice(&data) + } + ContextHandle::Name => { + let context = context.read(token.token()); + let bytes = context.name.as_bytes(); + let max = buf.len().min(bytes.len()); + buf.copy_common_bytes_from_slice(&bytes[..max]) + } + ContextHandle::Priority => { + let context = context.read(token.token()); + let nice = (20 - context.prio as i32).clamp(-20, 19); + let data = nice.to_ne_bytes(); + buf.copy_common_bytes_from_slice(&data) } // TODO: Replace write() with SYS_SENDFD? ContextHandle::Status { .. } => { let status = {