// A fork child's very first scheduling by scheduler() // will swtch to forkret. void forkret(void) { staticint first = 1;
// Still holding p->lock from scheduler. release(&myproc()->lock);
if (first) { // File system initialization must be run in the context of a // regular process (e.g., because it calls sleep), and thus cannot // be run from main(). fsinit(ROOTDEV);
first = 0; // ensure other cores see first=0. __sync_synchronize(); }
// // return to user space // void usertrapret(void) { ... // we're about to switch the destination of traps from // kerneltrap() to usertrap(), so turn off interrupts until // we're back in user space, where usertrap() is correct. intr_off();
...
// jump to userret in trampoline.S at the top of memory, which // switches to the user page table, restores user registers, // and switches to user mode with sret. uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline); ((void (*)(uint64))trampoline_userret)(satp); }
// Give up the CPU for one scheduling round. void yield(void) { structproc *p = myproc(); acquire(&p->lock); p->state = RUNNABLE; sched(); release(&p->lock); }