diff --git a/src/process/caps.rs b/src/process/caps.rs index 0329ed2..d7c51ba 100644 --- a/src/process/caps.rs +++ b/src/process/caps.rs @@ -60,7 +60,7 @@ pub async fn sys_capget(hdrp: TUA, datap: TUA) -> Re .iter() .find(|task| task.0.tgid.value() == header.pid as u32) .and_then(|task| task.1.upgrade()) - .map(|x| x.t_shared.clone()) + .map(|x| (*x).clone()) .ok_or(KernelError::NoProcess)? }; match header.version { @@ -96,7 +96,7 @@ pub async fn sys_capset(hdrp: TUA, datap: TUA) -> Re .iter() .find(|task| task.0.tgid.value() == header.pid as u32) .and_then(|task| task.1.upgrade()) - .map(|x| x.t_shared.clone()) + .map(|x| (*x).clone()) .ok_or(KernelError::NoProcess)? }; diff --git a/src/sched/mod.rs b/src/sched/mod.rs index 331841b..7fb39bb 100644 --- a/src/sched/mod.rs +++ b/src/sched/mod.rs @@ -218,11 +218,11 @@ impl SchedState { { let current = self.run_q.current_mut(); - current.task.update_accounting(Some(now_inst)); + current.work.task.update_accounting(Some(now_inst)); // Reset accounting baseline after updating stats to avoid double-counting // the same time interval on the next scheduler tick. - current.task.reset_last_account(now_inst); + current.work.reset_last_account(now_inst); } self.run_q.schedule(now_inst) @@ -270,7 +270,7 @@ pub fn sys_sched_yield() -> Result { } pub fn current_work() -> Arc { - SCHED_STATE.borrow().run_q.current().task.clone() + SCHED_STATE.borrow().run_q.current().work.clone() } pub fn current_work_waker() -> Waker { diff --git a/src/sched/runqueue/mod.rs b/src/sched/runqueue/mod.rs index f66f78f..e4cef03 100644 --- a/src/sched/runqueue/mod.rs +++ b/src/sched/runqueue/mod.rs @@ -101,8 +101,8 @@ impl RunQueue { let mut deferred_drops: Vec = Vec::new(); if let Some(mut cur_task) = self.running_task.take() { - prev_task = Arc::as_ptr(&cur_task.task); - let state = cur_task.task.state.load(Ordering::Acquire); + prev_task = Arc::as_ptr(&cur_task.work); + let state = cur_task.work.state.load(Ordering::Acquire); match state { TaskState::Running | TaskState::Woken => { if cur_task.tick(now) { @@ -116,7 +116,7 @@ impl RunQueue { TaskState::PendingSleep | TaskState::PendingStop => { // Task wants to deactivate. Drop the RunnableTask now to // restore sched_data. - let work = cur_task.task.clone(); + let work = cur_task.work.clone(); cur_task.sched_data.last_cpu = ArchImpl::id(); self.total_weight = self.total_weight.saturating_sub(cur_task.weight() as u64); drop(cur_task); @@ -138,17 +138,17 @@ impl RunQueue { { next_task.about_to_execute(now); - if Arc::as_ptr(&next_task.task) != prev_task { + if Arc::as_ptr(&next_task.work) != prev_task { // If we scheduled a different task than before, context switch. NUM_CONTEXT_SWITCHES.fetch_add(1, Ordering::Relaxed); next_task.switch_context(); - next_task.task.reset_last_account(now); + next_task.work.reset_last_account(now); CUR_TASK_PTR .borrow_mut() - .set_current(Box::as_ptr(&next_task.task.task) as *mut _); + .set_current(Box::as_ptr(&next_task.work.task) as *mut _); } self.running_task = Some(next_task); @@ -158,7 +158,7 @@ impl RunQueue { CUR_TASK_PTR .borrow_mut() - .set_current(Box::as_ptr(&self.idle.task.task) as *mut _); + .set_current(Box::as_ptr(&self.idle.work.task) as *mut _); } deferred_drops @@ -192,7 +192,7 @@ impl RunQueue { } while let Some(ByDeadline(best)) = self.eligible.pop() { - if best.task.state.load(Ordering::Acquire).is_finished() { + if best.work.state.load(Ordering::Acquire).is_finished() { self.total_weight = self.total_weight.saturating_sub(best.weight() as u64); deferred_drops.push(best); continue; @@ -211,8 +211,9 @@ impl RunQueue { None } - fn enqueue(&mut self, task: RunnableTask) { - task.task.state.mark_runnable(); + fn enqueue(&mut self, mut task: RunnableTask) { + task.refresh_priority(); + task.work.state.mark_runnable(); if self.v_clock.is_task_eligible(&task) { self.eligible.push(ByDeadline(task)); diff --git a/src/sched/sched_task/mod.rs b/src/sched/sched_task/mod.rs index 15124c5..6a57844 100644 --- a/src/sched/sched_task/mod.rs +++ b/src/sched/sched_task/mod.rs @@ -7,7 +7,7 @@ use super::{DEFAULT_TIME_SLICE, SCHED_WEIGHT_BASE, VT_FIXED_SHIFT}; use crate::{ arch::{Arch, ArchImpl}, drivers::timer::{Instant, schedule_preempt}, - process::owned::OwnedTask, + process::{Task, owned::OwnedTask}, sync::SpinLock, }; @@ -16,12 +16,6 @@ use state::TaskStateMachine; pub mod state; -pub struct Work { - pub task: Box, - pub state: TaskStateMachine, - pub sched_data: SpinLock>, -} - pub const NR_CPUS: usize = 256; pub const CPU_MASK_SIZE: usize = NR_CPUS / 64; @@ -37,10 +31,11 @@ pub struct SchedulerData { pub last_run: Option, pub last_cpu: usize, pub cpu_mask: [u64; CPU_MASK_SIZE], + pub priority: i8, } impl SchedulerData { - fn new() -> Self { + fn new(task: &Box) -> Self { Self { v_runtime: 0, v_eligible: 0, @@ -50,58 +45,72 @@ impl SchedulerData { last_run: None, last_cpu: usize::MAX, cpu_mask: [u64::MAX; CPU_MASK_SIZE], + priority: task.priority(), + } + } +} + +pub struct Work { + pub task: Box, + pub state: TaskStateMachine, + pub sched_data: SpinLock>, +} + + +impl Deref for Work { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.task.t_shared + } +} + +impl DerefMut for Work { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.task.t_shared + } +} + +impl Work { + pub fn new(task: Box) -> Arc { + let sched_data = SchedulerData::new(&task); + + Arc::new(Self { + task, + state: TaskStateMachine::new(), + sched_data: SpinLock::new(Some(sched_data)), + }) + } + + pub fn into_runnable(self: Arc) -> RunnableTask { + let mut sd = self + .sched_data + .lock_save_irq() + .take() + .expect("Should have sched data"); + + // Refresh priority. + sd.priority = self.task.priority(); + + RunnableTask { + work: self, + sched_data: sd, } } } pub struct RunnableTask { - pub(super) task: Arc, + pub(super) work: Arc, pub(super) sched_data: SchedulerData, } impl Drop for RunnableTask { // Replace the hot sched info back into the struct. fn drop(&mut self) { - *self.task.sched_data.lock_save_irq() = Some(self.sched_data.clone()); + *self.work.sched_data.lock_save_irq() = Some(self.sched_data.clone()); } } -impl Deref for Work { - type Target = OwnedTask; - - fn deref(&self) -> &Self::Target { - &self.task - } -} - -impl DerefMut for Work { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.task - } -} - -impl Work { - pub fn new(task: Box) -> Arc { - Arc::new(Self { - task, - state: TaskStateMachine::new(), - sched_data: SpinLock::new(Some(SchedulerData::new())), - }) - } - - pub fn into_runnable(self: Arc) -> RunnableTask { - let sd = self - .sched_data - .lock_save_irq() - .take() - .expect("Should have sched data"); - - RunnableTask { - task: self, - sched_data: sd, - } - } -} impl Deref for RunnableTask { type Target = SchedulerData; @@ -161,7 +170,7 @@ impl RunnableTask { /// weight = priority + SCHED_WEIGHT_BASE /// The sum is clamped to a minimum of 1 pub fn weight(&self) -> u32 { - let w = self.task.priority() as i32 + SCHED_WEIGHT_BASE; + let w = self.sched_data.priority as i32 + SCHED_WEIGHT_BASE; if w <= 0 { 1 } else { w as u32 } } @@ -199,7 +208,7 @@ impl RunnableTask { /// Setup task accounting info such that it is about to be executed. pub fn about_to_execute(&mut self, now: Instant) { self.exec_start = Some(now); - self.task.state.activate(); + self.work.state.activate(); // Deadline logic if self.deadline.is_none_or(|d| d <= now + DEFAULT_TIME_SLICE) { @@ -212,6 +221,10 @@ impl RunnableTask { } pub fn switch_context(&self) { - ArchImpl::context_switch(self.task.t_shared.clone()); + ArchImpl::context_switch(self.work.task.t_shared.clone()); + } + + pub fn refresh_priority(&mut self) { + self.sched_data.priority = self.work.task.priority(); } }