int do_linux_waitpid(int pid, int *code_store) { struct mm_struct *mm = current->mm; if (code_store != NULL) { if (!user_mem_check(mm, (uintptr_t)code_store, sizeof(int), 1)) { return -E_INVAL; } } struct proc_struct *proc, *cproc; bool intr_flag, haskid; repeat: cproc = current; haskid = 0; if (pid > 0) { proc = find_proc(pid); if (proc != NULL) { do { if (proc->parent == cproc) { haskid = 1; if (proc->state == PROC_ZOMBIE) { goto found; } break; } cproc = next_thread(cproc); } while (cproc != current); } } /* we do NOT have group id, so..*/ else if(pid==0 || pid==-1){ /* pid == 0 */ do { proc = cproc->cptr; for (; proc != NULL; proc = proc->optr) { haskid = 1; if (proc->state == PROC_ZOMBIE) { goto found; } } cproc = next_thread(cproc); } while (cproc != current); }else{ //pid<-1 //TODO return -E_INVAL; } if (haskid) { current->state = PROC_SLEEPING; current->wait_state = WT_CHILD; schedule(); may_killed(); goto repeat; } return -E_BAD_PROC; found: if (proc == idleproc || proc == initproc) { panic("wait idleproc or initproc.\n"); } int exit_code = proc->exit_code; int return_pid = proc->pid; local_intr_save(intr_flag); { unhash_proc(proc); remove_links(proc); } local_intr_restore(intr_flag); put_kstack(proc); kfree(proc); int ret = 0; if (code_store != NULL) { lock_mm(mm); { int status = exit_code << 8; if (!copy_to_user(mm, code_store, &status, sizeof(int))) { ret = -E_INVAL; } } unlock_mm(mm); } return (ret == 0) ? return_pid : ret; }
// do_wait - wait one OR any children with PROC_ZOMBIE state, and free memory space of kernel stack // - proc struct of this child. // NOTE: only after do_wait function, all resources of the child proces are free. int do_wait(int pid, int *code_store) { struct mm_struct *mm = current->mm; if (code_store != NULL) { if (!user_mem_check(mm, (uintptr_t) code_store, sizeof(int), 1)) { return -E_INVAL; } } struct proc_struct *proc, *cproc; bool intr_flag, haskid; repeat: cproc = current; haskid = 0; if (pid != 0) { proc = find_proc(pid); if (proc != NULL) { do { if (proc->parent == cproc) { haskid = 1; if (proc->state == PROC_ZOMBIE) { goto found; } break; } cproc = next_thread(cproc); } while (cproc != current); } } else { do { proc = cproc->cptr; for (; proc != NULL; proc = proc->optr) { haskid = 1; if (proc->state == PROC_ZOMBIE) { goto found; } } cproc = next_thread(cproc); } while (cproc != current); } if (haskid) { current->state = PROC_SLEEPING; current->wait_state = WT_CHILD; schedule(); may_killed(); goto repeat; } return -E_BAD_PROC; found: if (proc == idleproc || proc == initproc) { panic("wait idleproc or initproc.\n"); } int exit_code = proc->exit_code; spin_lock_irqsave(&proc_lock, intr_flag); { unhash_proc(proc); remove_links(proc); } spin_unlock_irqrestore(&proc_lock, intr_flag); put_kstack(proc); kfree(proc); int ret = 0; if (code_store != NULL) { lock_mm(mm); { if (!copy_to_user (mm, code_store, &exit_code, sizeof(int))) { ret = -E_INVAL; } } unlock_mm(mm); } return ret; }