kernel: add SchedPolicy/Name/Priority proc scheme handles
Wire up three new ContextHandle variants and their /proc/<pid>/{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/<tid>/name
- sched_setscheduler -> /proc/<tid>/sched-policy
- setpriority / nice -> /proc/<tid>/priority
- pthread_setschedparam -> /proc/<tid>/sched-policy + /proc/<tid>/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.
This commit is contained in:
+64
-2
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
context::{
|
context::{
|
||||||
self,
|
self,
|
||||||
context::{HardBlockedReason, LockedFdTbl, SignalState},
|
context::{HardBlockedReason, LockedFdTbl, SchedPolicy, SignalState},
|
||||||
file::InternalFlags,
|
file::InternalFlags,
|
||||||
memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan},
|
memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan},
|
||||||
Context, ContextLock, Status,
|
Context, ContextLock, Status,
|
||||||
@@ -146,6 +146,9 @@ enum ContextHandle {
|
|||||||
// directory.
|
// directory.
|
||||||
OpenViaDup,
|
OpenViaDup,
|
||||||
SchedAffinity,
|
SchedAffinity,
|
||||||
|
SchedPolicy,
|
||||||
|
Name,
|
||||||
|
Priority,
|
||||||
|
|
||||||
MmapMinAddr(Arc<AddrSpaceWrapper>),
|
MmapMinAddr(Arc<AddrSpaceWrapper>),
|
||||||
}
|
}
|
||||||
@@ -250,6 +253,9 @@ impl ProcScheme {
|
|||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
"sched-affinity" => (ContextHandle::SchedAffinity, true),
|
"sched-affinity" => (ContextHandle::SchedAffinity, true),
|
||||||
|
"sched-policy" => (ContextHandle::SchedPolicy, true),
|
||||||
|
"name" => (ContextHandle::Name, true),
|
||||||
|
"priority" => (ContextHandle::Priority, true),
|
||||||
"status" => (ContextHandle::Status { privileged: false }, false),
|
"status" => (ContextHandle::Status { privileged: false }, false),
|
||||||
_ if path.starts_with("auth-") => {
|
_ if path.starts_with("auth-") => {
|
||||||
let nonprefix = &path["auth-".len()..];
|
let nonprefix = &path["auth-".len()..];
|
||||||
@@ -1172,6 +1178,45 @@ impl ContextHandle {
|
|||||||
|
|
||||||
Ok(size_of_val(&mask))
|
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::<i32>() {
|
||||||
|
return Err(Error::new(EINVAL));
|
||||||
|
}
|
||||||
|
let nice = unsafe { buf.read_exact::<i32>()? };
|
||||||
|
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::<i32>())
|
||||||
|
}
|
||||||
ContextHandle::Status { privileged } => {
|
ContextHandle::Status { privileged } => {
|
||||||
let mut args = buf.usizes();
|
let mut args = buf.usizes();
|
||||||
|
|
||||||
@@ -1275,7 +1320,7 @@ impl ContextHandle {
|
|||||||
guard.pid = info.pid as usize;
|
guard.pid = info.pid as usize;
|
||||||
guard.euid = info.euid;
|
guard.euid = info.euid;
|
||||||
guard.egid = info.egid;
|
guard.egid = info.egid;
|
||||||
guard.prio = (info.prio as usize).min(39);
|
guard.set_sched_other_prio(info.prio as usize);
|
||||||
Ok(size_of::<ProcSchemeAttrs>())
|
Ok(size_of::<ProcSchemeAttrs>())
|
||||||
}
|
}
|
||||||
Self::Groups => {
|
Self::Groups => {
|
||||||
@@ -1467,6 +1512,23 @@ impl ContextHandle {
|
|||||||
|
|
||||||
buf.copy_exactly(crate::cpu_set::mask_as_bytes(&mask))?;
|
buf.copy_exactly(crate::cpu_set::mask_as_bytes(&mask))?;
|
||||||
Ok(size_of_val(&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?
|
} // TODO: Replace write() with SYS_SENDFD?
|
||||||
ContextHandle::Status { .. } => {
|
ContextHandle::Status { .. } => {
|
||||||
let status = {
|
let status = {
|
||||||
|
|||||||
Reference in New Issue
Block a user