Add sched_attr system call series

This commit is contained in:
js2xxx
2025-02-11 13:35:24 +00:00
committed by Tate, Hongliang Tian
parent 9e1c939a3f
commit c1dde01fc3
24 changed files with 588 additions and 42 deletions

View File

@ -0,0 +1,116 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::Ordering;
use super::SyscallReturn;
use crate::{
prelude::*,
process::{posix_thread::AsPosixThread, process_table, Pgid, Pid, Process, Uid},
sched::Nice,
};
pub fn sys_get_priority(which: i32, who: u32, ctx: &Context) -> Result<SyscallReturn> {
let prio_target = PriorityTarget::new(which, who, ctx)?;
debug!("get_priority prio_target: {:?}", prio_target);
let processes = get_processes(prio_target)?;
let highest_prio = {
let mut nice = Nice::MAX.value().get();
for process in processes.iter() {
let proc_nice = process.nice().load(Ordering::Relaxed).value().get();
// Returns the highest priority enjoyed by the processes
if proc_nice < nice {
nice = proc_nice;
}
}
// The system call returns nice values translated to the range 40 to 1,
// since a negative return value would be interpreted as an error.
20 - nice
};
Ok(SyscallReturn::Return(highest_prio as _))
}
pub(super) fn get_processes(prio_target: PriorityTarget) -> Result<Vec<Arc<Process>>> {
Ok(match prio_target {
PriorityTarget::Process(pid) => {
let process = process_table::get_process(pid).ok_or(Error::new(Errno::ESRCH))?;
vec![process]
}
PriorityTarget::ProcessGroup(pgid) => {
let process_group =
process_table::get_process_group(&pgid).ok_or(Error::new(Errno::ESRCH))?;
let processes: Vec<Arc<Process>> = process_group.lock().iter().cloned().collect();
if processes.is_empty() {
return_errno!(Errno::ESRCH);
}
processes
}
PriorityTarget::User(uid) => {
// Get the processes that are running under the specified user
let processes: Vec<Arc<Process>> = process_table::process_table_mut()
.iter()
.filter(|process| {
let main_thread = process.main_thread();
let posix_thread = main_thread.as_posix_thread().unwrap();
uid == posix_thread.credentials().ruid()
})
.cloned()
.collect();
if processes.is_empty() {
return_errno!(Errno::ESRCH);
}
processes
}
})
}
#[derive(Debug)]
pub(super) enum PriorityTarget {
Process(Pid),
ProcessGroup(Pgid),
User(Uid),
}
impl PriorityTarget {
pub(super) fn new(which: i32, who: u32, ctx: &Context) -> Result<Self> {
let which = Which::try_from(which)
.map_err(|_| Error::with_message(Errno::EINVAL, "invalid which value"))?;
Ok(match which {
Which::PRIO_PROCESS => {
let pid = if who == 0 {
ctx.process.pid()
} else {
who as Pid
};
Self::Process(pid)
}
Which::PRIO_PGRP => {
let pgid = if who == 0 {
ctx.process.pgid()
} else {
who as Pgid
};
Self::ProcessGroup(pgid)
}
Which::PRIO_USER => {
let uid = if who == 0 {
ctx.posix_thread.credentials().ruid()
} else {
Uid::new(who)
};
Self::User(uid)
}
})
}
}
#[expect(non_camel_case_types)]
#[derive(Clone, Debug, TryFromInt)]
#[repr(i32)]
pub(super) enum Which {
PRIO_PROCESS = 0,
PRIO_PGRP = 1,
PRIO_USER = 2,
}