Voluntary Context Switch
先從最基本的開始,想要達成 multi-tasking,至少需要有 voluntary context switch 的功能,也就是說 context switch 發生的時機在程式主動呼叫 scheduler 來進行 schedule。
注意:scheduler 指的是一段程式,用來決定下一個 task 該跑誰,而非一個 process
Task Structure
用來保存 task 的一些資訊。
schedule.h
|
|
task_state
沒有IDLE
是因為我還想不到要用 IDLE 的時機。目前我是直接從一個 priority queue 拿,有需要被 schedule 到就 push 進去,所以有沒有 IDLE 好像也沒差了 (?) (歡迎糾正)
schedule.c
|
|
Task Priority Queue
這邊也順便做了 elective 2 的需求,task_t
上的 prority
用來表示該 task 的優先程度,優先程度越高會先被 schedule 到。
queue.h
|
|
queue.c
我偷懶直接用 linked list 在 push 的時候檢查順序,然後找對的地方 insert 進去,使用 heap 應該效果更佳。
|
|
schedule.c
|
|
Create privilege tasks
傳進 function pointer 與 priority,找到沒在用的 task,初始化他的 task structure,並將該 task 的 cpu_context 做設定:
- lr 指到 function pointer
- fp 指到該 task 所屬的 kernel stack
- sp 指到該 task 所屬的 kernel stack
目前還沒有 Dynamic Allocator,所以 stack 先使用靜態宣告
schedule.c
我在這邊採到一個雷,一開始我將 KSTACK_TOP_IDX
設成 KSTACK_SIZE - 1
,發現 QEMU 上可以動,但是實體機上卻出現問題,後來才發現sp
需要 16 bytes 的 alignment,把它設成 KSTACK_SIZE - 16
就可以了。
|
|
Context switch
從 task queue 取出一個 target task,將目前的 task push 進 task queue,將目前的 task 更新成 target task,並執行 context switch。
schedule.c
|
|
schedule.S
|
|
將狀態保存在自己的 kernel stack,以 task 1 換到 task 2 為例:
+------------------------+ 0
| . |
+------------------------+
| kernel image |
|------------------------|
| . |
| . |
|------------------------| <- 3. sp before task 2 context restoring
| task 2 saved registers |
|------------------------| <- 4. sp after switch_to
| . |
+------------------------+ <- task 2 kenrel stack
| . |
| . |
|------------------------| <- 2. sp after task 1 context saving
| task 1 saved registers |
|------------------------| <- 1. sp before switch_to
| . |
+------------------------+ <- task 1 kenrel stack
備註:
sp
是往記憶體位址低的方向長的
|
|
Idle task
我把一開始在 EL1 進行初始化的 task 當作是 idle task (task 0),在初始化結束後會主動呼叫 schedule()
來 context switch 到別的 task。如果 idle task 被 scheduler 給 schedule 到,那他會進入無限迴圈主動呼叫 schedule()
,直到有其他 task 被 schedule 到。
main.c
|
|
schedule.c
|
|
狀態轉移範例
圖片來自 Lab 4 Spec
![](state-transition.png)
Voluntary context switch 的缺點在於,若要進行 context switch,必須由程式主動呼叫 schedule()
才能切換 task,可能會因此產生 starvation 的問題。