diff --git a/src/libos/src/fs/procfs/pid/stat.rs b/src/libos/src/fs/procfs/pid/stat.rs index 6a35d668..d1cf9508 100644 --- a/src/libos/src/fs/procfs/pid/stat.rs +++ b/src/libos/src/fs/procfs/pid/stat.rs @@ -36,8 +36,9 @@ impl ProcINode for ProcStatINode { let stime = 0; let cutime = 0; let cstime = 0; - let priority = main_thread.nice().read().unwrap().to_priority_val(); - let nice = main_thread.nice().read().unwrap().raw_val(); + // Convert [19,-20] to [39,0]. + 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 itrealvalue = 0; let starttime = self.0.start_time(); diff --git a/src/libos/src/process/thread/mod.rs b/src/libos/src/process/thread/mod.rs index 1be452fd..f33e1fd0 100644 --- a/src/libos/src/process/thread/mod.rs +++ b/src/libos/src/process/thread/mod.rs @@ -42,6 +42,9 @@ pub struct Thread { fs: FsViewRef, files: FileTableRef, 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, rlimits: ResourceLimitsRef, // Signal diff --git a/src/libos/src/sched/do_priority.rs b/src/libos/src/sched/do_priority.rs index 099cd198..af6b1f42 100644 --- a/src/libos/src/sched/do_priority.rs +++ b/src/libos/src/sched/do_priority.rs @@ -2,18 +2,17 @@ use super::priority::{NiceValue, PrioWhich}; use crate::prelude::*; 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!( - "set_priority: which: {:?}, who: {}, prio: {:?}", - which, who, prio + "set_priority: which: {:?}, who: {}, nice: {:?}", + which, who, nice ); let processes = get_processes(which, who)?; for process in processes.iter() { - let main_thread = process - .main_thread() - .ok_or_else(|| errno!(ESRCH, "invalid pid"))?; - *main_thread.nice().write().unwrap() = prio; + for thread in process.threads().iter() { + *thread.nice().write().unwrap() = nice; + } } Ok(()) } @@ -22,27 +21,25 @@ pub fn do_get_priority(which: PrioWhich, who: i32) -> Result { debug!("get_priority: which: {:?}, who: {}", which, who); let processes = get_processes(which, who)?; - let prio = { - let mut prio = NiceValue::max_value(); + let nice = { + let mut nice = NiceValue::MAX; for process in processes.iter() { let main_thread = process .main_thread() .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 - if *nice_value < prio { - prio = *nice_value; + if *current_nice < nice { + 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> { - Ok(match which { + let processes = match which { PrioWhich::PRIO_PROCESS => { let process = if who == 0 { current!().process().clone() @@ -67,5 +64,10 @@ fn get_processes(which: PrioWhich, who: i32) -> Result for PrioWhich { } } -/// Process priority value +/// Process scheduling nice value. /// /// Lower values give a process a higher scheduling priority. #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)] pub struct NiceValue { - value: i32, + value: i8, } 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 { - Self { - value: Self::MAX_PRIO, + /// Create a nice value from a raw value. + /// + /// 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 { - Self { - value: Self::MIN_PRIO, - } - } - - pub fn raw_val(&self) -> i32 { + /// Convert to the raw value with range [19, -20]. + pub fn to_raw_val(self) -> i8 { 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 for NiceValue { fn from(raw: i32) -> Self { - let value = if raw < Self::MIN_PRIO { - Self::MIN_PRIO - } else if raw > Self::MAX_PRIO { - Self::MAX_PRIO + let adj_raw = if raw > i8::MAX as i32 { + i8::MAX + } else if raw < i8::MIN as i32 { + i8::MIN } else { - raw + raw as i8 }; - Self { value } + Self::new(adj_raw) } } diff --git a/src/libos/src/sched/syscalls.rs b/src/libos/src/sched/syscalls.rs index 8a4ff7cc..c0b32a91 100644 --- a/src/libos/src/sched/syscalls.rs +++ b/src/libos/src/sched/syscalls.rs @@ -83,16 +83,16 @@ pub fn do_getcpu(cpu_ptr: *mut u32, node_ptr: *mut u32) -> Result { pub fn do_set_priority(which: i32, who: i32, prio: i32) -> Result { let which = PrioWhich::try_from(which)?; - let prio = NiceValue::from(prio); - super::do_priority::do_set_priority(which, who, prio)?; + let nice = NiceValue::from(prio); + super::do_priority::do_set_priority(which, who, nice)?; Ok(0) } pub fn do_get_priority(which: i32, who: i32) -> Result { 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 // 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) - Ok(prio.to_rlimit_val() as isize) + Ok((20 - nice.to_raw_val()) as _) }