core-os-riscv icon indicating copy to clipboard operation
core-os-riscv copied to clipboard

Proposal: Async-like way in handling user process

Open skyzh opened this issue 4 years ago • 3 comments

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_threads, which solves the RAII issue.

Furthermore, I would like to have this issue solved with async-std crate, which supports no-std environment.

skyzh avatar Feb 20 '20 06:02 skyzh

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 avatar Feb 27 '20 09:02 wangrunji0408

@wangrunji0408 Thank you! That's exactly what I would like to implement!

skyzh avatar Feb 27 '20 11:02 skyzh

osblog wrote a new article on this! https://os.phil-opp.com/async-await/

skyzh avatar Mar 28 '20 03:03 skyzh