Skip to content

Commit

Permalink
[refactor] use a dependent migration task to perform migrating
Browse files Browse the repository at this point in the history
  • Loading branch information
hky1999 committed Nov 22, 2024
1 parent f6091f0 commit a8c37a1
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 22 deletions.
41 changes: 20 additions & 21 deletions modules/axtask/src/run_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ percpu_static! {
/// Stores the weak reference to the previous task that is running on this CPU.
#[cfg(feature = "smp")]
PREV_TASK: Weak<crate::AxTask> = Weak::new(),
/// Stores the migrating task that is being migrated to another CPU, if any.
#[cfg(feature = "smp")]
MIGRATING_TASK: Option<AxTaskRef> = None,
}

/// An array of references to run queues, one for each CPU, indexed by cpu_id.
Expand Down Expand Up @@ -300,19 +297,26 @@ impl<'a, G: BaseGuard> CurrentRunQueueRef<'a, G> {
/// in `finish_task_switch()` after the context switch is completed.
#[cfg(feature = "smp")]
pub fn migrate_current(&mut self) {
let curr = &self.current_task;
let curr = self.current_task.clone();
trace!("task migrate: {}", curr.id_name());
assert!(curr.is_running());

// Mark current task as Ready but do not put it back to the run queue.
curr.set_state(TaskState::Ready);
// Instead, store the task in `MIGRATING_TASK`, which will be put into the target run queue
// in `finish_task_switch()` after the context switch is completed.
unsafe {
*MIGRATING_TASK.current_ref_mut_raw() = Some(curr.clone());
}

self.inner.resched();
const MIGRATION_TASK_STACK_SIZE: usize = 4096;

// Do not put current task to the run queue,
// instead, spawn a new task for migrating.
let migration = TaskInner::new(
move || {
curr.set_state(TaskState::Ready);
select_run_queue::<kernel_guard::NoPreemptIrqSave>(&curr).add_task(curr);
},
"migration-task".into(),
MIGRATION_TASK_STACK_SIZE,
)
.into_arc();

// Call `switch_to` to reschedule to the migration task that performs the migration directly.
self.inner.switch_to(crate::current(), migration);
}

/// Preempts the current task and reschedules.
Expand Down Expand Up @@ -568,7 +572,7 @@ impl AxRunQueue {
// Current it's **next_task** running on this CPU, clear the `prev_task`'s `on_cpu` field
// to indicate that it has finished its scheduling process and no longer running on this CPU.
#[cfg(feature = "smp")]
finish_task_switch();
clear_prev_task_on_cpu();
}
}
}
Expand Down Expand Up @@ -598,19 +602,14 @@ fn gc_entry() {
}
}

/// Clear the `on_cpu` field of previous task running on this CPU.
#[cfg(feature = "smp")]
pub(crate) unsafe fn finish_task_switch() {
// Clears the `on_cpu` field of previous task running on this CPU.
pub(crate) unsafe fn clear_prev_task_on_cpu() {
PREV_TASK
.current_ref_raw()
.upgrade()
.expect("Invalid prev_task pointer or prev_task has been dropped")
.set_on_cpu(false);

// Migrate the previous task to the run queue of correct CPU if necessary.
if let Some(task) = MIGRATING_TASK.current_ref_mut_raw().take() {
select_run_queue::<kernel_guard::NoOp>(&task).add_task(task);
}
}

pub(crate) fn init() {
Expand Down
2 changes: 1 addition & 1 deletion modules/axtask/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ extern "C" fn task_entry() -> ! {
#[cfg(feature = "smp")]
unsafe {
// Clear the prev task on CPU before running the task entry function.
crate::run_queue::finish_task_switch();
crate::run_queue::clear_prev_task_on_cpu();
}
// Enable irq (if feature "irq" is enabled) before running the task entry function.
#[cfg(feature = "irq")]
Expand Down

0 comments on commit a8c37a1

Please sign in to comment.