#include #include #include #include #include #include #include #include #include #include /* 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); }