goto end; break; }check_continued: /* * It's running now, so it might later * exit, stop, or stop and then continue. */ flag = 1; if (!unlikely(options & WCONTINUED)) continue; retval = wait_task_continued( p, (options & WNOWAIT), infop, stat_addr, ru); if (retval != 0) /* He released the lock. */ goto end; break; } } if (!flag) { list_for_each(_p, &tsk->ptrace_children) { p = list_entry(_p, struct task_struct, ptrace_list); if (!eligible_child(pid, options, p)) continue; flag = 1; break; } } if (options & __WNOTHREAD) break; tsk = next_thread(tsk); if (tsk->signal != current->signal) BUG(); } while (tsk != current); read_unlock(&tasklist_lock); if (flag) { retval = 0; if (options & WNOHANG) goto end; retval = -ERESTARTSYS; if (signal_pending(current)) goto end; schedule(); goto repeat; } retval = -ECHILD;end: current->state = TASK_RUNNING; remove_wait_queue(¤t->signal->wait_chldexit,&wait); if (infop) { if (retval > 0) retval = 0; else { /* * For a WNOHANG return, clear out all the fields * we would set so the user can easily tell the * difference. */ if (!retval) retval = put_user(0, &infop->si_signo); if (!retval) retval = put_user(0, &infop->si_errno); if (!retval) retval = put_user(0, &infop->si_code); if (!retval) retval = put_user(0, &infop->si_pid); if (!retval) retval = put_user(0, &infop->si_uid); if (!retval) retval = put_user(0, &infop->si_status); } } return retval;} asmlinkage long sys_waitid(int which, pid_t pid, struct siginfo __user *infop, int options, struct rusage __user *ru){ long ret; if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED)) return -EINVAL; if (!(options & (WEXITED|WSTOPPED|WCONTINUED))) return -EINVAL; switch (which) { case P_ALL: pid = -1; break; case P_PID: if (pid <= 0) return -EINVAL; break; case P_PGID: if (pid <= 0) return -EINVAL; pid = -pid; break; default: return -EINVAL; } ret = do_wait(pid, options, infop, NULL, ru); /* avoid REGPARM breakage on x86: */ prevent_tail_call(ret); return ret;} asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, int options, struct rusage __user *ru){ long ret; if (options & ~(WNOHANG|WUNTRACED|WCONTINUED| __WNOTHREAD|__WCLONE|__WALL)) return -EINVAL; ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru); /* avoid REGPARM breakage on x86: */ prevent_tail_call(ret); return ret;} #ifdef __ARCH_WANT_SYS_WAITPID /* * sys_waitpid() remains for compatibility. waitpid() should be * implemented by calling sys_wait4() from libc.a. */asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options){ return sys_wait4(pid, stat_addr, options, NULL);} #endifLines 1501–1639 of 1639. Previous lines
goto end; break; } check_continued: /* * It's running now, so it might later * exit, stop, or stop and then continue. */ flag = 1; if (!unlikely(options & WCONTINUED)) continue; retval = wait_task_continued( p, (options & WNOWAIT), infop, stat_addr, ru); if (retval != 0) /* He released the lock. */ goto end; break; } } if (!flag) { list_for_each(_p, &tsk->ptrace_children) { p = list_entry(_p, struct task_struct, ptrace_list); if (!eligible_child(pid, options, p)) continue; flag = 1; break; } } if (options & __WNOTHREAD) break; tsk = next_thread(tsk); if (tsk->signal != current->signal) BUG(); } while (tsk != current); read_unlock(&tasklist_lock); if (flag) { retval = 0; if (options & WNOHANG) goto end; retval = -ERESTARTSYS; if (signal_pending(current)) goto end; schedule(); goto repeat; } retval = -ECHILD; end: current->state = TASK_RUNNING; remove_wait_queue(¤t->signal->wait_chldexit,&wait); if (infop) { if (retval > 0) retval = 0; else { /* * For a WNOHANG return, clear out all the fields * we would set so the user can easily tell the * difference. */ if (!retval) retval = put_user(0, &infop->si_signo); if (!retval) retval = put_user(0, &infop->si_errno); if (!retval) retval = put_user(0, &infop->si_code); if (!retval) retval = put_user(0, &infop->si_pid); if (!retval) retval = put_user(0, &infop->si_uid); if (!retval) retval = put_user(0, &infop->si_status); } } return retval; } asmlinkage long sys_waitid(int which, pid_t pid, struct siginfo __user *infop, int options, struct rusage __user *ru) { long ret; if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED)) return -EINVAL; if (!(options & (WEXITED|WSTOPPED|WCONTINUED))) return -EINVAL; switch (which) { case P_ALL: pid = -1; break; case P_PID: if (pid <= 0) return -EINVAL; break; case P_PGID: if (pid <= 0) return -EINVAL; pid = -pid; break; default: return -EINVAL; } ret = do_wait(pid, options, infop, NULL, ru); /* avoid REGPARM breakage on x86: */ prevent_tail_call(ret); return ret; } asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, int options, struct rusage __user *ru) { long ret; if (options & ~(WNOHANG|WUNTRACED|WCONTINUED| __WNOTHREAD|__WCLONE|__WALL)) return -EINVAL; ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru); /* avoid REGPARM breakage on x86: */ prevent_tail_call(ret); return ret; } #ifdef __ARCH_WANT_SYS_WAITPID /* * sys_waitpid() remains for compatibility. waitpid() should be * implemented by calling sys_wait4() from libc.a. */ asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options) { return sys_wait4(pid, stat_addr, options, NULL); } #endif