Refine the implementation of NiceValue
This commit is contained in:
parent
db3a31d42e
commit
f9839299b2
@ -36,8 +36,9 @@ impl ProcINode for ProcStatINode {
|
|||||||
let stime = 0;
|
let stime = 0;
|
||||||
let cutime = 0;
|
let cutime = 0;
|
||||||
let cstime = 0;
|
let cstime = 0;
|
||||||
let priority = main_thread.nice().read().unwrap().to_priority_val();
|
// Convert [19,-20] to [39,0].
|
||||||
let nice = main_thread.nice().read().unwrap().raw_val();
|
let priority = main_thread.nice().read().unwrap().to_raw_val() + 20;
|
||||||
|
let nice = main_thread.nice().read().unwrap().to_raw_val();
|
||||||
let num_threads = self.0.threads().len();
|
let num_threads = self.0.threads().len();
|
||||||
let itrealvalue = 0;
|
let itrealvalue = 0;
|
||||||
let starttime = self.0.start_time();
|
let starttime = self.0.start_time();
|
||||||
|
@ -42,6 +42,9 @@ pub struct Thread {
|
|||||||
fs: FsViewRef,
|
fs: FsViewRef,
|
||||||
files: FileTableRef,
|
files: FileTableRef,
|
||||||
sched: SchedAgentRef,
|
sched: SchedAgentRef,
|
||||||
|
// According to POSIX, the nice value is a per-process setting.
|
||||||
|
// In our implementation, the threads belong to same process
|
||||||
|
// share the same nice value.
|
||||||
nice: NiceValueRef,
|
nice: NiceValueRef,
|
||||||
rlimits: ResourceLimitsRef,
|
rlimits: ResourceLimitsRef,
|
||||||
// Signal
|
// Signal
|
||||||
|
@ -2,18 +2,17 @@ use super::priority::{NiceValue, PrioWhich};
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::table::{get_all_processes, get_pgrp, get_process};
|
use crate::process::table::{get_all_processes, get_pgrp, get_process};
|
||||||
|
|
||||||
pub fn do_set_priority(which: PrioWhich, who: i32, prio: NiceValue) -> Result<()> {
|
pub fn do_set_priority(which: PrioWhich, who: i32, nice: NiceValue) -> Result<()> {
|
||||||
debug!(
|
debug!(
|
||||||
"set_priority: which: {:?}, who: {}, prio: {:?}",
|
"set_priority: which: {:?}, who: {}, nice: {:?}",
|
||||||
which, who, prio
|
which, who, nice
|
||||||
);
|
);
|
||||||
|
|
||||||
let processes = get_processes(which, who)?;
|
let processes = get_processes(which, who)?;
|
||||||
for process in processes.iter() {
|
for process in processes.iter() {
|
||||||
let main_thread = process
|
for thread in process.threads().iter() {
|
||||||
.main_thread()
|
*thread.nice().write().unwrap() = nice;
|
||||||
.ok_or_else(|| errno!(ESRCH, "invalid pid"))?;
|
}
|
||||||
*main_thread.nice().write().unwrap() = prio;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -22,27 +21,25 @@ pub fn do_get_priority(which: PrioWhich, who: i32) -> Result<NiceValue> {
|
|||||||
debug!("get_priority: which: {:?}, who: {}", which, who);
|
debug!("get_priority: which: {:?}, who: {}", which, who);
|
||||||
|
|
||||||
let processes = get_processes(which, who)?;
|
let processes = get_processes(which, who)?;
|
||||||
let prio = {
|
let nice = {
|
||||||
let mut prio = NiceValue::max_value();
|
let mut nice = NiceValue::MAX;
|
||||||
for process in processes.iter() {
|
for process in processes.iter() {
|
||||||
let main_thread = process
|
let main_thread = process
|
||||||
.main_thread()
|
.main_thread()
|
||||||
.ok_or_else(|| errno!(ESRCH, "invalid pid"))?;
|
.ok_or_else(|| errno!(ESRCH, "invalid pid"))?;
|
||||||
let nice_value = main_thread.nice().read().unwrap();
|
let current_nice = main_thread.nice().read().unwrap();
|
||||||
// Returns the highest priority enjoyed by the processes
|
// Returns the highest priority enjoyed by the processes
|
||||||
if *nice_value < prio {
|
if *current_nice < nice {
|
||||||
prio = *nice_value;
|
nice = *current_nice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prio
|
nice
|
||||||
};
|
};
|
||||||
Ok(prio)
|
Ok(nice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// According to POSIX, the nice value is a per-process setting.
|
|
||||||
// In our implementation, the threads belong to same process share the same nice value.
|
|
||||||
fn get_processes(which: PrioWhich, who: i32) -> Result<Vec<crate::process::ProcessRef>> {
|
fn get_processes(which: PrioWhich, who: i32) -> Result<Vec<crate::process::ProcessRef>> {
|
||||||
Ok(match which {
|
let processes = match which {
|
||||||
PrioWhich::PRIO_PROCESS => {
|
PrioWhich::PRIO_PROCESS => {
|
||||||
let process = if who == 0 {
|
let process = if who == 0 {
|
||||||
current!().process().clone()
|
current!().process().clone()
|
||||||
@ -67,5 +64,10 @@ fn get_processes(which: PrioWhich, who: i32) -> Result<Vec<crate::process::Proce
|
|||||||
return_errno!(ESRCH, "no such user");
|
return_errno!(ESRCH, "no such user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
};
|
||||||
|
if processes.is_empty() {
|
||||||
|
return_errno!(ESRCH, "no such process");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(processes)
|
||||||
}
|
}
|
||||||
|
@ -21,55 +21,48 @@ impl TryFrom<i32> for PrioWhich {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process priority value
|
/// Process scheduling nice value.
|
||||||
///
|
///
|
||||||
/// Lower values give a process a higher scheduling priority.
|
/// Lower values give a process a higher scheduling priority.
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
||||||
pub struct NiceValue {
|
pub struct NiceValue {
|
||||||
value: i32,
|
value: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NiceValue {
|
impl NiceValue {
|
||||||
const MAX_PRIO: i32 = 19;
|
pub const MAX: Self = Self { value: 19 };
|
||||||
|
|
||||||
const MIN_PRIO: i32 = -20;
|
pub const MIN: Self = Self { value: -20 };
|
||||||
|
|
||||||
pub fn max_value() -> Self {
|
/// Create a nice value from a raw value.
|
||||||
Self {
|
///
|
||||||
value: Self::MAX_PRIO,
|
/// The raw value given beyond the range are automatically adjusted
|
||||||
|
/// to the nearest boundary value.
|
||||||
|
pub fn new(raw: i8) -> Self {
|
||||||
|
if raw < Self::MIN.value {
|
||||||
|
Self::MIN
|
||||||
|
} else if raw > Self::MAX.value {
|
||||||
|
Self::MAX
|
||||||
|
} else {
|
||||||
|
Self { value: raw }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min_value() -> Self {
|
/// Convert to the raw value with range [19, -20].
|
||||||
Self {
|
pub fn to_raw_val(self) -> i8 {
|
||||||
value: Self::MIN_PRIO,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn raw_val(&self) -> i32 {
|
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert [19,-20] to priority value [39,0].
|
|
||||||
pub fn to_priority_val(&self) -> i32 {
|
|
||||||
self.value - Self::MIN_PRIO
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert [19,-20] to rlimit style value [1,40].
|
|
||||||
pub fn to_rlimit_val(&self) -> i32 {
|
|
||||||
Self::MAX_PRIO - self.value + 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i32> for NiceValue {
|
impl From<i32> for NiceValue {
|
||||||
fn from(raw: i32) -> Self {
|
fn from(raw: i32) -> Self {
|
||||||
let value = if raw < Self::MIN_PRIO {
|
let adj_raw = if raw > i8::MAX as i32 {
|
||||||
Self::MIN_PRIO
|
i8::MAX
|
||||||
} else if raw > Self::MAX_PRIO {
|
} else if raw < i8::MIN as i32 {
|
||||||
Self::MAX_PRIO
|
i8::MIN
|
||||||
} else {
|
} else {
|
||||||
raw
|
raw as i8
|
||||||
};
|
};
|
||||||
Self { value }
|
Self::new(adj_raw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,16 +83,16 @@ pub fn do_getcpu(cpu_ptr: *mut u32, node_ptr: *mut u32) -> Result<isize> {
|
|||||||
|
|
||||||
pub fn do_set_priority(which: i32, who: i32, prio: i32) -> Result<isize> {
|
pub fn do_set_priority(which: i32, who: i32, prio: i32) -> Result<isize> {
|
||||||
let which = PrioWhich::try_from(which)?;
|
let which = PrioWhich::try_from(which)?;
|
||||||
let prio = NiceValue::from(prio);
|
let nice = NiceValue::from(prio);
|
||||||
super::do_priority::do_set_priority(which, who, prio)?;
|
super::do_priority::do_set_priority(which, who, nice)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_get_priority(which: i32, who: i32) -> Result<isize> {
|
pub fn do_get_priority(which: i32, who: i32) -> Result<isize> {
|
||||||
let which = PrioWhich::try_from(which)?;
|
let which = PrioWhich::try_from(which)?;
|
||||||
let prio = super::do_priority::do_get_priority(which, who)?;
|
let nice = super::do_priority::do_get_priority(which, who)?;
|
||||||
// To avoid negative return values, "getpriority()" will
|
// To avoid negative return values, "getpriority()" will
|
||||||
// not return the normal nice-value, but a negated value that
|
// not return the normal nice-value, but a negated value that
|
||||||
// has been offset by 20 (ie it returns 40..1 instead of -20..19)
|
// has been offset by 20 (ie it returns 40..1 instead of -20..19)
|
||||||
Ok(prio.to_rlimit_val() as isize)
|
Ok((20 - nice.to_raw_val()) as _)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user