Day-2
Paging
We delve into paging.
Example
1 | /// Physical address for pflash#1 |
PFlash is the simulation of flash memory of qemu. When qemu boot, it will automatically load file to fixed MMIO, and can be directly accessed.
Paging: feature = ["paging"]
is the way to evoke virtual memory management tu support MMIO
. Located in axruntime
.
The workflow would be:
- qemu fdt: from
0x0c00_0000
to0x3000_0000
. Construct the space of device. - SBI: from
0x8000_0000
to0x8020_0000
. RISC-V Supervisor Binary Interface, it construct a interface for programming language to manipulate device level things. - Kernel Image: from
0x8020_0000
._skernel
contains S-level things like static data, code etc…_ekernel
is user thing.
1 |
|
Each entry of page table will map 1G(0x4000_0000
) memory. From 0x8000_0000
to 0xc0000_0000
at pgd_idx = 2
to 0xffff_ffc0_8000_0000
to 0xffff_ffc0_c000_0000
at pgd_idx = 102
. This will map to a bigger range.
Task
Example
1 | let worker = thread::spawn(move || { |
Each task will be in concurrency and dispatched by strategy. If it’s blocked, it will be moved to wait_queue
to wait. If it’s ready, it will be moved to run_queue
which is scheduler to be dispatched.
Message Communication
Example
1 | let q1 = Arc::new(SpinNoIrq::new(VecDeque::new())); |
Cooperative Scheduling: Each tasks kindly yield themselves or exit otherwise it will block everyone because the power of CPU occupation is ownned by each tasks.
Preemptive Scheduling: Each tasks will be automatically suspended by external condition: No lock, no device access; inner condition: run out of current time slice. We can use a disable_count
to record this, even for multiple condition restriction, we can sum them up.
1 | axhal::irq::register_handler(TIMER_IRQ_NUM, || { |
on_timer_tick
will be trigger in time slice. When time ticker ticks, run_queue
will check and suspend task if possible.
We can make it more dynamic. Which means each task has priority and during the implementation of cpu, each task has a vruntime
to be dynamically adjusted by init_vruntime + (delta/weight(nice))
where delta
and nice
are dynamic adjustment number. delta
will be incremented by timer
, weight(nice)
is actually the priority of the task. We ensure that task with lowest vruntime
will be placed at top.