Update outdated comments near switch_to_task

This commit is contained in:
Ruihan Li
2025-04-02 22:33:53 +08:00
committed by Junyang Zhang
parent d378dc51ff
commit 5ed5647d42
3 changed files with 17 additions and 12 deletions

View File

@ -210,7 +210,8 @@ impl TaskOptions {
/// all task will entering this function /// all task will entering this function
/// this function is mean to executing the task_fn in Task /// this function is mean to executing the task_fn in Task
extern "C" fn kernel_task_entry() -> ! { extern "C" fn kernel_task_entry() -> ! {
// SAFETY: This is called only once when we are switched to a CPU. // SAFETY: The new task is switched on a CPU for the first time, `after_switching_to`
// hasn't been called yet.
unsafe { processor::after_switching_to() }; unsafe { processor::after_switching_to() };
let current_task = Task::current() let current_task = Task::current()

View File

@ -49,20 +49,22 @@ pub(super) fn switch_to_task(next_task: Arc<Task>) {
let current_task_ctx_ptr = if !current_task_ptr.is_null() { let current_task_ctx_ptr = if !current_task_ptr.is_null() {
// SAFETY: The pointer is set by `switch_to_task` and is guaranteed to be // SAFETY: The pointer is set by `switch_to_task` and is guaranteed to be
// built with `Arc::into_raw`. It will only be dropped as a previous task, // built with `Arc::into_raw`. It will only be dropped as a previous task,
// So reference will be valid across this function. // so its reference will be valid until `after_switching_to`.
let current_task = unsafe { &*current_task_ptr }; let current_task = unsafe { &*current_task_ptr };
current_task.save_fpu_state(); current_task.save_fpu_state();
// Throughout this method, the task's context is alive and can be exclusively used. // Until `after_switching_to`, the task's context is alive and can be exclusively used.
current_task.ctx.get() current_task.ctx.get()
} else { } else {
// Throughout this method, interrupts are disabled and the context can be exclusively used. // Until `after_switching_to`, IRQs are disabled and the context can be exclusively used.
BOOTSTRAP_CONTEXT.as_mut_ptr() BOOTSTRAP_CONTEXT.as_mut_ptr()
}; };
before_switching_to(&next_task, &irq_guard); before_switching_to(&next_task, &irq_guard);
// `before_switching_to` guarantees that from now on, and while the next task is running on the
// CPU, its context can be used exclusively.
let next_task_ctx_ptr = next_task.ctx().get().cast_const(); let next_task_ctx_ptr = next_task.ctx().get().cast_const();
CURRENT_TASK_PTR.store(Arc::into_raw(next_task)); CURRENT_TASK_PTR.store(Arc::into_raw(next_task));
@ -73,16 +75,16 @@ pub(super) fn switch_to_task(next_task: Arc<Task>) {
let _ = core::mem::ManuallyDrop::new(irq_guard); let _ = core::mem::ManuallyDrop::new(irq_guard);
// SAFETY: // SAFETY:
// 1. `ctx` is only used in `reschedule()`. We have exclusive access to both the current task // 1. We have exclusive access to both the current context and the next context (see above).
// context and the next task context. // 2. The next context is valid (because it is either correctly initialized or written by a
// 2. The next task context is a valid task context. // previous `context_switch`).
unsafe { unsafe {
// This function may not return, for example, when the current task exits. So make sure // This function may not return, for example, when the current task exits. So make sure
// that all variables on the stack can be forgotten without causing resource leakage. // that all variables on the stack can be forgotten without causing resource leakage.
context_switch(current_task_ctx_ptr, next_task_ctx_ptr); context_switch(current_task_ctx_ptr, next_task_ctx_ptr);
} }
// SAFETY: We would only call once after switching back to this task. // SAFETY: The task is just switched back, `after_switching_to` hasn't been called yet.
unsafe { after_switching_to() }; unsafe { after_switching_to() };
if let Some(current) = Task::current() { if let Some(current) = Task::current() {

View File

@ -259,10 +259,12 @@ where
}; };
}; };
// FIXME: At this point, we need to prevent the current task from being scheduled on another // `switch_to_task` will spin if it finds that the next task is still running on some CPU core,
// CPU core. However, we currently have no way to ensure this. This is a soundness hole and // which guarantees soundness regardless of the scheduler implementation.
// should be fixed. See <https://github.com/asterinas/asterinas/issues/1471> for details. //
// FIXME: The scheduler decision and context switching are not atomic, which can lead to some
// strange behavior even if the scheduler is implemented correctly. See "Problem 2" at
// <https://github.com/asterinas/asterinas/issues/1633> for details.
cpu_local::clear_need_preempt(); cpu_local::clear_need_preempt();
processor::switch_to_task(next_task); processor::switch_to_task(next_task);
} }