博客 / 詳情

返回

risc-v--多任務切換原理

rust 代碼實現。current_task_cx_ptr 當前任務是一段空的內存區域。 用來存放當前任務的寄存器環境。

fn run_next_task(&self) {
        if let Some(next) = self.find_next_task() {
            let mut inner = self.inner.exclusive_access();
            let current = inner.current_task;
            inner.tasks[next].task_status = TaskStatus::Running;
            inner.current_task = next;
            let current_task_cx_ptr = &mut inner.tasks[current].task_cx as *mut TaskContext;
            let next_task_cx_ptr = &inner.tasks[next].task_cx as *const TaskContext;
            drop(inner);
            // before this, we should drop local variables that must be dropped manually
            unsafe {
                __switch(current_task_cx_ptr, next_task_cx_ptr);
            }
            // go back to user mode
        } else {
            println!("All applications completed!");
            shutdown(false);
        }
    }

把當前寄存器的內容, 存到當前任務的內存裏面。
把下一個任務的數據加載到寄存器。尤其注意 ra 寄存器
ret 就是切換到觸發,將跳轉到ra哪裏。

__switch:
    # __switch(
    #     current_task_cx_ptr: *mut TaskContext
    #     next_task_cx_ptr: *const TaskContext
    # )
    # save kernel stack of current task
    sd sp, 8(a0)
    # save ra & s0~s11 of current execution
    sd ra, 0(a0)
    .set n, 0
    .rept 12
        SAVE_SN %n
        .set n, n + 1
    .endr
    # restore ra & s0~s11 of next execution
    ld ra, 0(a1)
    .set n, 0
    .rept 12
        LOAD_SN %n
        .set n, n + 1
    .endr
    # restore kernel stack of next task
    ld sp, 8(a1)
    ret

ra 裏面讓放入的是啥?__restore 中斷處理邏輯, sp 用的事自己的。

pub fn goto_restore(kstack_ptr: usize) -> Self {
        extern "C" {
            fn __restore();
        }
        Self {
            ra: __restore as usize,
            sp: kstack_ptr,
            s: [0; 12],
        }
    }
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.