mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
Add support for setpriority and getpriority
This commit is contained in:
parent
26dff7d054
commit
437ab804f3
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -199,8 +199,11 @@ dependencies = [
|
||||
"aster-time",
|
||||
"aster-util",
|
||||
"aster-virtio",
|
||||
"atomic",
|
||||
"bitflags 1.3.2",
|
||||
"bitvec",
|
||||
"bytemuck",
|
||||
"bytemuck_derive",
|
||||
"controlled",
|
||||
"core2",
|
||||
"cpio-decoder",
|
||||
@ -308,6 +311,15 @@ dependencies = [
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
version = "0.1.11"
|
||||
@ -364,9 +376,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.14.0"
|
||||
version = "1.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
|
||||
checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
@ -65,6 +65,9 @@ bitvec = { version = "1.0", default-features = false, features = ["alloc"] }
|
||||
static_assertions = "1.1.0"
|
||||
inherit-methods-macro = { git = "https://github.com/asterinas/inherit-methods-macro", rev = "98f7e3e" }
|
||||
getset = "0.1.2"
|
||||
atomic = "0.6"
|
||||
bytemuck = "1.14.3"
|
||||
bytemuck_derive = "1.5.0"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.0"
|
||||
|
@ -112,8 +112,7 @@ impl DirOps for RootDirOps {
|
||||
let mut cached_children = this.cached_children().write();
|
||||
cached_children.put_entry_if_not_found("self", || SelfSymOps::new_inode(this_ptr.clone()));
|
||||
|
||||
let processes = process_table::get_all_processes();
|
||||
for process in processes {
|
||||
for process in process_table::process_table().iter() {
|
||||
let pid = process.pid().to_string();
|
||||
cached_children.put_entry_if_not_found(&pid, || {
|
||||
PidDirOps::new_inode(process.clone(), this_ptr.clone())
|
||||
|
@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use aster_frame::{cpu::UserContext, user::UserSpace, vm::VmIo};
|
||||
use aster_rights::Full;
|
||||
|
||||
@ -260,6 +262,9 @@ fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Re
|
||||
*sigmask
|
||||
};
|
||||
|
||||
// inherit parent's nice value
|
||||
let child_nice = current.nice().load(Ordering::Relaxed);
|
||||
|
||||
let child_tid = allocate_tid();
|
||||
|
||||
let child = {
|
||||
@ -286,7 +291,8 @@ fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Re
|
||||
.file_table(child_file_table)
|
||||
.fs(child_fs)
|
||||
.umask(child_umask)
|
||||
.sig_dispositions(child_sig_dispositions);
|
||||
.sig_dispositions(child_sig_dispositions)
|
||||
.nice(child_nice);
|
||||
|
||||
process_builder.build()?
|
||||
};
|
||||
|
@ -89,13 +89,12 @@ pub fn tgkill(tid: Tid, tgid: Pid, signal: Option<UserSignal>) -> Result<()> {
|
||||
/// if it is authorized to send the signal to the target group.
|
||||
pub fn kill_all(signal: Option<UserSignal>) -> Result<()> {
|
||||
let current = current!();
|
||||
let processes = process_table::get_all_processes();
|
||||
for process in processes {
|
||||
if Arc::ptr_eq(¤t, &process) || process.is_init_process() {
|
||||
for process in process_table::process_table().iter() {
|
||||
if Arc::ptr_eq(¤t, process) || process.is_init_process() {
|
||||
continue;
|
||||
}
|
||||
|
||||
kill_process(&process, signal)?;
|
||||
kill_process(process, signal)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -246,7 +246,7 @@ impl PosixThread {
|
||||
}
|
||||
|
||||
/// Gets the read-only credentials of the thread.
|
||||
pub(in crate::process) fn credentials(&self) -> Credentials<ReadOp> {
|
||||
pub fn credentials(&self) -> Credentials<ReadOp> {
|
||||
self.credentials.dup().restrict()
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ use crate::{
|
||||
signal::sig_disposition::SigDispositions,
|
||||
Credentials,
|
||||
},
|
||||
sched::nice::Nice,
|
||||
thread::Thread,
|
||||
};
|
||||
|
||||
@ -31,6 +32,7 @@ pub struct ProcessBuilder<'a> {
|
||||
resource_limits: Option<ResourceLimits>,
|
||||
sig_dispositions: Option<Arc<Mutex<SigDispositions>>>,
|
||||
credentials: Option<Credentials>,
|
||||
nice: Option<Nice>,
|
||||
}
|
||||
|
||||
impl<'a> ProcessBuilder<'a> {
|
||||
@ -49,6 +51,7 @@ impl<'a> ProcessBuilder<'a> {
|
||||
resource_limits: None,
|
||||
sig_dispositions: None,
|
||||
credentials: None,
|
||||
nice: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,6 +105,11 @@ impl<'a> ProcessBuilder<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn nice(&mut self, nice: Nice) -> &mut Self {
|
||||
self.nice = Some(nice);
|
||||
self
|
||||
}
|
||||
|
||||
fn check_build(&self) -> Result<()> {
|
||||
if self.main_thread_builder.is_some() {
|
||||
debug_assert!(self.parent.upgrade().is_some());
|
||||
@ -136,6 +144,7 @@ impl<'a> ProcessBuilder<'a> {
|
||||
resource_limits,
|
||||
sig_dispositions,
|
||||
credentials,
|
||||
nice,
|
||||
} = self;
|
||||
|
||||
let process_vm = process_vm.or_else(|| Some(ProcessVm::alloc())).unwrap();
|
||||
@ -160,6 +169,8 @@ impl<'a> ProcessBuilder<'a> {
|
||||
.or_else(|| Some(Arc::new(Mutex::new(SigDispositions::new()))))
|
||||
.unwrap();
|
||||
|
||||
let nice = nice.or_else(|| Some(Nice::default())).unwrap();
|
||||
|
||||
let process = {
|
||||
let threads = Vec::new();
|
||||
Arc::new(Process::new(
|
||||
@ -173,6 +184,7 @@ impl<'a> ProcessBuilder<'a> {
|
||||
umask,
|
||||
sig_dispositions,
|
||||
resource_limits,
|
||||
nice,
|
||||
))
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,7 @@ use crate::{
|
||||
device::tty::open_ntty_as_controlling_terminal,
|
||||
fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask},
|
||||
prelude::*,
|
||||
sched::nice::Nice,
|
||||
thread::{allocate_tid, Thread},
|
||||
vm::vmar::Vmar,
|
||||
};
|
||||
@ -27,6 +28,7 @@ mod session;
|
||||
mod terminal;
|
||||
|
||||
use aster_rights::Full;
|
||||
use atomic::Atomic;
|
||||
pub use builder::ProcessBuilder;
|
||||
pub use job_control::JobControl;
|
||||
pub use process_group::ProcessGroup;
|
||||
@ -72,6 +74,10 @@ pub struct Process {
|
||||
umask: Arc<RwLock<FileCreationMask>>,
|
||||
/// resource limits
|
||||
resource_limits: Mutex<ResourceLimits>,
|
||||
/// Scheduling priority nice value
|
||||
/// According to POSIX.1, the nice value is a per-process attribute,
|
||||
/// the threads in a process should share a nice value.
|
||||
nice: Atomic<Nice>,
|
||||
|
||||
// Signal
|
||||
/// Sig dispositions
|
||||
@ -91,6 +97,7 @@ impl Process {
|
||||
umask: Arc<RwLock<FileCreationMask>>,
|
||||
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
||||
resource_limits: ResourceLimits,
|
||||
nice: Nice,
|
||||
) -> Self {
|
||||
let children_pauser = {
|
||||
// SIGCHID does not interrupt pauser. Child process will
|
||||
@ -114,6 +121,7 @@ impl Process {
|
||||
umask,
|
||||
sig_dispositions,
|
||||
resource_limits: Mutex::new(resource_limits),
|
||||
nice: Atomic::new(nice),
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +214,11 @@ impl Process {
|
||||
&self.resource_limits
|
||||
}
|
||||
|
||||
fn main_thread(&self) -> Option<Arc<Thread>> {
|
||||
pub fn nice(&self) -> &Atomic<Nice> {
|
||||
&self.nice
|
||||
}
|
||||
|
||||
pub fn main_thread(&self) -> Option<Arc<Thread>> {
|
||||
self.threads
|
||||
.lock()
|
||||
.iter()
|
||||
@ -602,6 +614,7 @@ mod test {
|
||||
Arc::new(RwLock::new(FileCreationMask::default())),
|
||||
Arc::new(Mutex::new(SigDispositions::default())),
|
||||
ResourceLimits::default(),
|
||||
Nice::default(),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::collections::btree_map::Values;
|
||||
|
||||
use super::{Pgid, Pid, Process, Session};
|
||||
use crate::{prelude::*, process::signal::signals::Signal};
|
||||
|
||||
@ -68,6 +70,13 @@ impl ProcessGroup {
|
||||
self.pgid
|
||||
}
|
||||
|
||||
/// Acquires a lock on the process group.
|
||||
pub fn lock(&self) -> ProcessGroupGuard {
|
||||
ProcessGroupGuard {
|
||||
inner: self.inner.lock(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Broadcasts signal to all processes in the group.
|
||||
///
|
||||
/// This method should only be used to broadcast fault signal and kernel signal.
|
||||
@ -89,3 +98,32 @@ impl ProcessGroup {
|
||||
self.inner.lock().session.upgrade()
|
||||
}
|
||||
}
|
||||
|
||||
/// A scoped lock for a process group.
|
||||
///
|
||||
/// It provides some public methods to prevent the exposure of the inner type.
|
||||
pub struct ProcessGroupGuard<'a> {
|
||||
inner: MutexGuard<'a, Inner>,
|
||||
}
|
||||
|
||||
impl<'a> ProcessGroupGuard<'a> {
|
||||
/// Returns an iterator over the processes in the group.
|
||||
pub fn iter(&self) -> ProcessGroupIter {
|
||||
ProcessGroupIter {
|
||||
inner: self.inner.processes.values(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the processes of the process group.
|
||||
pub struct ProcessGroupIter<'a> {
|
||||
inner: Values<'a, Pid, Arc<Process>>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ProcessGroupIter<'a> {
|
||||
type Item = &'a Arc<Process>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
//! This table can be used to get process with pid.
|
||||
//! TODO: progress group, thread all need similar mapping
|
||||
|
||||
use alloc::collections::btree_map::Values;
|
||||
|
||||
use super::{Pgid, Pid, Process, ProcessGroup, Session, Sid};
|
||||
use crate::{
|
||||
events::{Events, Observer, Subject},
|
||||
@ -26,13 +28,40 @@ pub(super) fn process_table_mut() -> MutexGuard<'static, BTreeMap<Pid, Arc<Proce
|
||||
PROCESS_TABLE.lock()
|
||||
}
|
||||
|
||||
/// Gets all processes
|
||||
pub fn get_all_processes() -> Vec<Arc<Process>> {
|
||||
PROCESS_TABLE
|
||||
.lock()
|
||||
.iter()
|
||||
.map(|(_, process)| process.clone())
|
||||
.collect()
|
||||
/// Acquires a lock on the process table and returns a `ProcessTable`.
|
||||
pub fn process_table() -> ProcessTable<'static> {
|
||||
ProcessTable {
|
||||
inner: PROCESS_TABLE.lock(),
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper for the mutex-protected process table.
|
||||
///
|
||||
/// It provides the `iter` method to iterator over the processes in the table.
|
||||
pub struct ProcessTable<'a> {
|
||||
inner: MutexGuard<'a, BTreeMap<Pid, Arc<Process>>>,
|
||||
}
|
||||
|
||||
impl<'a> ProcessTable<'a> {
|
||||
/// Returns an iterator over the processes in the table.
|
||||
pub fn iter(&self) -> ProcessTableIter {
|
||||
ProcessTableIter {
|
||||
inner: self.inner.values(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the processes of the process table.
|
||||
pub struct ProcessTableIter<'a> {
|
||||
inner: Values<'a, Pid, Arc<Process>>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ProcessTableIter<'a> {
|
||||
type Item = &'a Arc<Process>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
// ************ Process Group *************
|
||||
|
@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
pub mod nice;
|
||||
mod priority_scheduler;
|
||||
|
||||
// There may be multiple scheduling policies in the system,
|
||||
|
111
kernel/aster-nix/src/sched/nice.rs
Normal file
111
kernel/aster-nix/src/sched/nice.rs
Normal file
@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use bytemuck_derive::NoUninit;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
/// The process scheduling nice value.
|
||||
///
|
||||
/// The nice value is an attribute that can be used to influence the
|
||||
/// CPU scheduler to favor or disfavor a process in scheduling decisions.
|
||||
///
|
||||
/// It is a value in the range -20 to 19, with -20 being the highest priority
|
||||
/// and 19 being the lowest priority. The smaller values give a process a higher
|
||||
/// scheduling priority.
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, NoUninit)]
|
||||
pub struct Nice {
|
||||
value: i8,
|
||||
}
|
||||
|
||||
impl Nice {
|
||||
/// The minimum nice, whose value is -20.
|
||||
pub const MIN: Self = Self { value: -20 };
|
||||
|
||||
/// The maximum nice, whose value is 19.
|
||||
pub const MAX: Self = Self { value: 19 };
|
||||
|
||||
/// Creates a new `Nice` from the raw value.
|
||||
///
|
||||
/// Values given beyond the permissible range are automatically adjusted
|
||||
/// to the nearest boundary value.
|
||||
pub fn new(raw: i8) -> Self {
|
||||
if raw > Self::MAX.to_raw() {
|
||||
Self::MAX
|
||||
} else if raw < Self::MIN.to_raw() {
|
||||
Self::MIN
|
||||
} else {
|
||||
Self { value: raw }
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts to the raw value.
|
||||
pub fn to_raw(self) -> i8 {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for Nice {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
// The default nice value is 0
|
||||
value: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Priority> for Nice {
|
||||
fn from(priority: Priority) -> Self {
|
||||
Self {
|
||||
value: 20 - priority.to_raw() as i8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The process scheduling priority value.
|
||||
///
|
||||
/// It is a value in the range 1 (corresponding to a nice value of 19)
|
||||
/// to 40 (corresponding to a nice value of -20), with 1 being the lowest priority
|
||||
/// and 40 being the highest priority. The greater values give a process a higher
|
||||
/// scheduling priority.
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, NoUninit)]
|
||||
pub struct Priority {
|
||||
value: u8,
|
||||
}
|
||||
|
||||
impl Priority {
|
||||
/// The minimum priority, whose value is 1.
|
||||
pub const MIN: Self = Self { value: 1 };
|
||||
|
||||
/// The maximum priority, whose value is 40.
|
||||
pub const MAX: Self = Self { value: 40 };
|
||||
|
||||
/// Creates a new `Priority` from the raw value.
|
||||
///
|
||||
/// Values given beyond the permissible range are automatically adjusted
|
||||
/// to the nearest boundary value.
|
||||
pub fn new(raw: u8) -> Self {
|
||||
if raw > Self::MAX.to_raw() {
|
||||
Self::MAX
|
||||
} else if raw < Self::MIN.to_raw() {
|
||||
Self::MIN
|
||||
} else {
|
||||
Self { value: raw }
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts to the raw value.
|
||||
pub fn to_raw(self) -> u8 {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Nice> for Priority {
|
||||
fn from(nice: Nice) -> Self {
|
||||
Self {
|
||||
value: (20 - nice.to_raw()) as u8,
|
||||
}
|
||||
}
|
||||
}
|
@ -72,6 +72,7 @@ use crate::{
|
||||
rt_sigreturn::sys_rt_sigreturn,
|
||||
sched_yield::sys_sched_yield,
|
||||
select::sys_select,
|
||||
set_get_priority::{sys_get_priority, sys_set_priority},
|
||||
set_robust_list::sys_set_robust_list,
|
||||
set_tid_address::sys_set_tid_address,
|
||||
setpgid::sys_setpgid,
|
||||
@ -163,6 +164,7 @@ mod rt_sigreturn;
|
||||
mod sched_yield;
|
||||
mod select;
|
||||
mod sendto;
|
||||
mod set_get_priority;
|
||||
mod set_robust_list;
|
||||
mod set_tid_address;
|
||||
mod setfsgid;
|
||||
@ -321,6 +323,8 @@ define_syscall_nums!(
|
||||
SYS_SIGALTSTACK = 131,
|
||||
SYS_STATFS = 137,
|
||||
SYS_FSTATFS = 138,
|
||||
SYS_GET_PRIORITY = 140,
|
||||
SYS_SET_PRIORITY = 141,
|
||||
SYS_PRCTL = 157,
|
||||
SYS_ARCH_PRCTL = 158,
|
||||
SYS_SYNC = 162,
|
||||
@ -505,6 +509,8 @@ pub fn syscall_dispatch(
|
||||
SYS_SIGALTSTACK => syscall_handler!(2, sys_sigaltstack, args),
|
||||
SYS_STATFS => syscall_handler!(2, sys_statfs, args),
|
||||
SYS_FSTATFS => syscall_handler!(2, sys_fstatfs, args),
|
||||
SYS_GET_PRIORITY => syscall_handler!(2, sys_get_priority, args),
|
||||
SYS_SET_PRIORITY => syscall_handler!(3, sys_set_priority, args),
|
||||
SYS_PRCTL => syscall_handler!(5, sys_prctl, args),
|
||||
SYS_ARCH_PRCTL => syscall_handler!(2, sys_arch_prctl, args, context),
|
||||
SYS_SYNC => syscall_handler!(0, sys_sync),
|
||||
|
149
kernel/aster-nix/src/syscall/set_get_priority.rs
Normal file
149
kernel/aster-nix/src/syscall/set_get_priority.rs
Normal file
@ -0,0 +1,149 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use super::{SyscallReturn, SYS_GET_PRIORITY, SYS_SET_PRIORITY};
|
||||
use crate::{
|
||||
log_syscall_entry,
|
||||
prelude::*,
|
||||
process::{credentials, posix_thread::PosixThreadExt, process_table, Pgid, Pid, Process, Uid},
|
||||
sched::nice::Nice,
|
||||
};
|
||||
|
||||
pub fn sys_set_priority(which: i32, who: u32, prio: i32) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SET_PRIORITY);
|
||||
let prio_target = PriorityTarget::new(which, who)?;
|
||||
let new_nice = {
|
||||
let norm_prio = if prio > i8::MAX as i32 {
|
||||
i8::MAX
|
||||
} else if prio < i8::MIN as i32 {
|
||||
i8::MIN
|
||||
} else {
|
||||
prio as i8
|
||||
};
|
||||
Nice::new(norm_prio)
|
||||
};
|
||||
|
||||
debug!(
|
||||
"set_priority prio_target: {:?}, new_nice: {:?}",
|
||||
prio_target, new_nice
|
||||
);
|
||||
|
||||
let processes = get_processes(prio_target)?;
|
||||
for process in processes.iter() {
|
||||
process.nice().store(new_nice, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_get_priority(which: i32, who: u32) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_GET_PRIORITY);
|
||||
let prio_target = PriorityTarget::new(which, who)?;
|
||||
debug!("get_priority prio_target: {:?}", prio_target);
|
||||
|
||||
let processes = get_processes(prio_target)?;
|
||||
let highest_prio = {
|
||||
let mut nice = Nice::MAX;
|
||||
for process in processes.iter() {
|
||||
let proc_nice = process.nice().load(Ordering::Relaxed);
|
||||
// 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.to_raw()
|
||||
};
|
||||
|
||||
Ok(SyscallReturn::Return(highest_prio as _))
|
||||
}
|
||||
|
||||
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()
|
||||
.iter()
|
||||
.filter(|process| {
|
||||
let Some(main_thread) = process.main_thread() else {
|
||||
return false;
|
||||
};
|
||||
let Some(posix_thread) = main_thread.as_posix_thread() else {
|
||||
return false;
|
||||
};
|
||||
uid == posix_thread.credentials().ruid()
|
||||
})
|
||||
.cloned()
|
||||
.collect();
|
||||
if processes.is_empty() {
|
||||
return_errno!(Errno::ESRCH);
|
||||
}
|
||||
processes
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum PriorityTarget {
|
||||
Process(Pid),
|
||||
ProcessGroup(Pgid),
|
||||
User(Uid),
|
||||
}
|
||||
|
||||
impl PriorityTarget {
|
||||
fn new(which: i32, who: u32) -> 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 {
|
||||
current!().pid()
|
||||
} else {
|
||||
who as Pid
|
||||
};
|
||||
Self::Process(pid)
|
||||
}
|
||||
Which::PRIO_PGRP => {
|
||||
let pgid = if who == 0 {
|
||||
current!().pgid()
|
||||
} else {
|
||||
who as Pgid
|
||||
};
|
||||
Self::ProcessGroup(pgid)
|
||||
}
|
||||
Which::PRIO_USER => {
|
||||
let uid = if who == 0 {
|
||||
credentials().ruid()
|
||||
} else {
|
||||
Uid::new(who)
|
||||
};
|
||||
Self::User(uid)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Debug, TryFromInt)]
|
||||
#[repr(i32)]
|
||||
enum Which {
|
||||
PRIO_PROCESS = 0,
|
||||
PRIO_PGRP = 1,
|
||||
PRIO_USER = 2,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user