2020301918-os/kern/wait.c
2022-11-30 10:21:29 +08:00

101 lines
2.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <assert.h>
#include <mmu.h>
#include <errno.h>
#include <x86.h>
#include <kern/syscall.h>
#include <kern/wait.h>
#include <kern/process.h>
#include <kern/pmap.h>
#include <kern/sche.h>
#include <kern/kmalloc.h>
/*
The wait() system call suspends execution of the calling thread
until one of its children terminates.
RETURN VALUE
on success, returns the process ID of the terminated child;
on failure, -1 is returned.
! however the testwait.bin expects a valued return other than simply -1
*/
ssize_t
kern_wait(int *wstatus)
{
again:
while (xchg(&p_proc_ready->pcb.lock, 1) == 1)
schedule();
PROCESS_0 *p_fa = &p_proc_ready->pcb;
int child_pid = -1;
struct son_node* p_son = p_fa->fork_tree.sons;
if (p_son == NULL) {
xchg(&p_fa->lock, 0);
return -ECHILD;
}
assert(p_son->pre == NULL); // make sure it is the head of the list
/*
struct s_proc {
user_regs; // let it be
kern_regs; // let it be
lock; // get and release before kfree
statu; // set to IDLE
pid; // keep it util return
cr3; // let it be
page_list; // recycle it
exit_code; // set to wstatus
priority; // let it be
ticks; // let it be
fork_tree; // already cleared
};
*/
while (p_son != NULL) {
if (p_son->p_son->statu == ZOMBIE) {
while (xchg(&p_son->p_son->lock, 1) == 1)
schedule();
// just use this value, which is '(status & 0xFF) << 8' in exit.c::do_exit
if (wstatus != NULL)
*wstatus = p_son->p_son->exit_code;
// recycle_pages in pmap.c
recycle_pages(p_son->p_son->page_list);
// remove p_son from p_fa's son list
if (p_son->pre != NULL) {
p_son->pre->nxt = p_son->nxt;
}
else {
p_fa->fork_tree.sons = p_son->nxt;
}
if (p_son->nxt != NULL) {
p_son->nxt->pre = p_son->pre;
}
// keep p_son's pid for retval, 'cause the pointer will get freed before return
child_pid = p_son->p_son->pid;
kfree(p_son);
// free it in proc table, 'cause in fork I judge free by statu
xchg(&proc_table[child_pid].pcb.lock, 0);
proc_table[child_pid].pcb.statu = IDLE; // ! set status be the last state, or die
goto done;
}
p_son = p_son->nxt;
}
xchg(&p_fa->lock, 0);
p_fa->statu = SLEEP; //! sleep after release lock, or it will deadlock
schedule();
goto again;
// 接下来就是你自己的实现了,我们在设计的时候这段代码不会有太大问题
// 在实现完后你任然要对自己来个灵魂拷问
// 1. 上锁上了吗?所有临界情况都考虑到了吗?(永远要相信有各种奇奇怪怪的并发问题)
// 2. 所有错误情况都判断到了吗错误情况怎么处理RTFM->`man 2 wait`
// 3. 是否所有的资源都正确回收了?
// 4. 你写的代码真的符合wait语义吗
done:
xchg(&p_fa->lock, 0);
// panic("Unimplement! soul torture");
return child_pid;
}
ssize_t
do_wait(int *wstatus)
{
assert((uintptr_t)wstatus < KERNBASE);
assert((uintptr_t)wstatus + sizeof(wstatus) < KERNBASE);
return kern_wait(wstatus);
}