core-os-riscv
core-os-riscv copied to clipboard
Proposal: Async-like way in handling user process
In xv6, code path for trapping into user-space and back is really confusing. Typically this is done with:
forkret()
-> usertrap()
-> making syscalls, etc. -> usertrapret()
I've encountered the issue of RAII. As we call usertrap
in forkret
, any object created in forkret
won't be dropped as usertrap
won't return.
Previously I thought this could been done by introducing a return_to
function, in which RISC-V return address register ra
is rewritten with the address of that function. For example,
fn forkret() -> NeverReturn {
return_to(usertrap)
}
Therefore, object can be correctly dropped before jumping to usertrap. However, there're many issues with that.
After that, I propose to use a k_thread()
function to represent full code path for trapping into and returning from user-space.
func k_thread() {
// forkret contents
loop {
// usertrap contents
await_into_userspace(); // A function calls into user space and returns on trap
if scause == timer { yield(); }
syscall();
// usertrapret contents
}
}
And the scheduler just schedules those k_thread
s, which solves the RAII issue.
Furthermore, I would like to have this issue solved with async-std
crate, which supports no-std environment.
Hi! Glad to see your excellent project!
I've made some attempts on this topic:
Hope it helps! And looking forward to further communication if you have any ideas.
Thanks!
@wangrunji0408 Thank you! That's exactly what I would like to implement!
osblog wrote a new article on this! https://os.phil-opp.com/async-await/