summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2004-03-17 20:00:00 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2004-03-17 20:00:00 +0000
commitb7e23e826c650173f9175c42f1b03cd80fdb0a93 (patch)
treee960ffc0a863b368d852fa094d1f4ccb757fe3c7
parentcb8c2e1cd289a58a84b0fb4b9703c8847e507a73 (diff)
Notes
-rw-r--r--sys/alpha/osf1/osf1_misc.c27
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c22
-rw-r--r--sys/compat/linux/linux_misc.c47
-rw-r--r--sys/compat/svr4/svr4_misc.c32
-rw-r--r--sys/i386/ibcs2/ibcs2_misc.c38
-rw-r--r--sys/kern/kern_exit.c123
-rw-r--r--sys/sys/wait.h6
7 files changed, 105 insertions, 190 deletions
diff --git a/sys/alpha/osf1/osf1_misc.c b/sys/alpha/osf1/osf1_misc.c
index 8e2557d17c43..373fcc1fe133 100644
--- a/sys/alpha/osf1/osf1_misc.c
+++ b/sys/alpha/osf1/osf1_misc.c
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/user.h>
#include <sys/utsname.h>
#include <sys/vnode.h>
+#include <sys/wait.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
@@ -1376,27 +1377,23 @@ osf1_wait4(td, uap)
struct thread *td;
struct osf1_wait4_args *uap;
{
- int error;
- caddr_t sg;
- struct osf1_rusage *orusage, oru;
- struct rusage *rusage = NULL, ru;
+ int error, status;
+ struct osf1_rusage oru;
+ struct rusage ru;
- orusage = uap->rusage;
- if (orusage) {
- sg = stackgap_init();
- rusage = stackgap_alloc(&sg, sizeof(struct rusage));
- uap->rusage = (struct osf1_rusage *)rusage;
- }
- if ((error = wait4(td, (struct wait_args *)uap)))
- return error;
- if (orusage && (error = copyin(rusage, &ru, sizeof(ru)) == 0)){
+ error = kern_wait(td, uap->pid, &status, uap->options, &ru);
+ if (error)
+ return (error);
+ if (uap->status != NULL)
+ error = copyout(&status, uap->status, sizeof(status));
+ if (uap->rusage != NULL && error == 0) {
TV_CP(ru.ru_utime, oru.ru_utime);
TV_CP(ru.ru_stime, oru.ru_stime);
bcopy(&ru.ru_first, &oru.ru_first,
(&(oru.ru_last) - &(oru.ru_first)));
- copyout(&oru, orusage, sizeof (struct osf1_rusage));
+ error = copyout(&oru, uap->rusage, sizeof (struct osf1_rusage));
}
- return (0);
+ return (error);
}
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 511321d9a4fb..deccaf8fc710 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$");
#include <sys/user.h>
#include <sys/utsname.h>
#include <sys/vnode.h>
+#include <sys/wait.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
@@ -88,21 +89,16 @@ CTASSERT(sizeof(struct rusage32) == 72);
int
freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
{
- int error;
- caddr_t sg;
- struct rusage32 *rusage32, ru32;
- struct rusage *rusage = NULL, ru;
+ int error, status;
+ struct rusage32 ru32;
+ struct rusage ru;
- rusage32 = uap->rusage;
- if (rusage32) {
- sg = stackgap_init();
- rusage = stackgap_alloc(&sg, sizeof(struct rusage));
- uap->rusage = (struct rusage32 *)rusage;
- }
- error = wait4(td, (struct wait_args *)uap);
+ error = kern_wait(td, uap->pid, &status, uap->options, &ru);
if (error)
return (error);
- if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
+ if (uap->status != NULL)
+ error = copyout(&status, uap->status, sizeof(status));
+ if (uap->rusage != NULL && error == 0) {
TV_CP(ru, ru32, ru_utime);
TV_CP(ru, ru32, ru_stime);
CP(ru, ru32, ru_maxrss);
@@ -119,7 +115,7 @@ freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
CP(ru, ru32, ru_nsignals);
CP(ru, ru32, ru_nvcsw);
CP(ru, ru32, ru_nivcsw);
- error = copyout(&ru32, rusage32, sizeof(ru32));
+ error = copyout(&ru32, uap->rusage, sizeof(ru32));
}
return (error);
}
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 9e38f91f1f94..8a81dec689ed 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -795,13 +795,7 @@ linux_utime(struct thread *td, struct linux_utime_args *args)
int
linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
{
- struct wait_args /* {
- int pid;
- int *status;
- int options;
- struct rusage *rusage;
- } */ tmp;
- int error, tmpstat;
+ int error, options, tmpstat;
#ifdef DEBUG
if (ldebug(waitpid))
@@ -809,20 +803,16 @@ linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
args->pid, (void *)args->status, args->options);
#endif
- tmp.pid = args->pid;
- tmp.status = args->status;
- tmp.options = (args->options & (WNOHANG | WUNTRACED));
+ options = (args->options & (WNOHANG | WUNTRACED));
/* WLINUXCLONE should be equal to __WCLONE, but we make sure */
if (args->options & __WCLONE)
- tmp.options |= WLINUXCLONE;
- tmp.rusage = NULL;
+ options |= WLINUXCLONE;
- if ((error = wait4(td, &tmp)) != 0)
+ error = kern_wait(td, args->pid, &tmpstat, options, NULL);
+ if (error)
return error;
if (args->status) {
- if ((error = copyin(args->status, &tmpstat, sizeof(int))) != 0)
- return error;
tmpstat &= 0xffff;
if (WIFSIGNALED(tmpstat))
tmpstat = (tmpstat & 0xffffff80) |
@@ -840,13 +830,8 @@ linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
int
linux_wait4(struct thread *td, struct linux_wait4_args *args)
{
- struct wait_args /* {
- int pid;
- int *status;
- int options;
- struct rusage *rusage;
- } */ tmp;
- int error, tmpstat;
+ int error, options, tmpstat;
+ struct rusage ru;
struct proc *p;
#ifdef DEBUG
@@ -856,15 +841,13 @@ linux_wait4(struct thread *td, struct linux_wait4_args *args)
(void *)args->rusage);
#endif
- tmp.pid = args->pid;
- tmp.status = args->status;
- tmp.options = (args->options & (WNOHANG | WUNTRACED));
+ options = (args->options & (WNOHANG | WUNTRACED));
/* WLINUXCLONE should be equal to __WCLONE, but we make sure */
if (args->options & __WCLONE)
- tmp.options |= WLINUXCLONE;
- tmp.rusage = (struct rusage *)args->rusage;
+ options |= WLINUXCLONE;
- if ((error = wait4(td, &tmp)) != 0)
+ error = kern_wait(td, args->pid, &tmpstat, options, &ru);
+ if (error)
return error;
p = td->td_proc;
@@ -873,8 +856,6 @@ linux_wait4(struct thread *td, struct linux_wait4_args *args)
PROC_UNLOCK(p);
if (args->status) {
- if ((error = copyin(args->status, &tmpstat, sizeof(int))) != 0)
- return error;
tmpstat &= 0xffff;
if (WIFSIGNALED(tmpstat))
tmpstat = (tmpstat & 0xffffff80) |
@@ -882,10 +863,12 @@ linux_wait4(struct thread *td, struct linux_wait4_args *args)
else if (WIFSTOPPED(tmpstat))
tmpstat = (tmpstat & 0xffff00ff) |
(BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
- return copyout(&tmpstat, args->status, sizeof(int));
+ error = copyout(&tmpstat, args->status, sizeof(int));
}
+ if (args->rusage != NULL && error == 0)
+ error = copyout(&ru, args->rusage, sizeof(ru));
- return 0;
+ return (error);
}
int
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index c568a5dc16f2..243dc226aa30 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -130,29 +130,12 @@ svr4_sys_wait(td, uap)
struct thread *td;
struct svr4_sys_wait_args *uap;
{
- struct wait_args w4;
- int error, *retval = td->td_retval, st, sig;
- size_t sz = sizeof(*w4.status);
+ int error, st, sig;
- w4.rusage = NULL;
- w4.options = 0;
-
- if (uap->status == NULL) {
- caddr_t sg = stackgap_init();
-
- w4.status = stackgap_alloc(&sg, sz);
- }
- else
- w4.status = uap->status;
-
- w4.pid = WAIT_ANY;
-
- if ((error = wait4(td, &w4)) != 0)
- return error;
+ error = kern_wait(td, WAIT_ANY, &st, 0, NULL);
+ if (error)
+ return (error);
- if ((error = copyin(w4.status, &st, sizeof(st))) != 0)
- return error;
-
if (WIFSIGNALED(st)) {
sig = WTERMSIG(st);
if (sig >= 0 && sig < NSIG)
@@ -167,13 +150,12 @@ svr4_sys_wait(td, uap)
* It looks like wait(2) on svr4/solaris/2.4 returns
* the status in retval[1], and the pid on retval[0].
*/
- retval[1] = st;
+ td->td_retval[1] = st;
if (uap->status)
- if ((error = copyout(&st, uap->status, sizeof(st))) != 0)
- return error;
+ error = copyout(&st, uap->status, sizeof(st));
- return 0;
+ return (error);
}
int
diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c
index d4162ea6dbde..c3edf1569e2c 100644
--- a/sys/i386/ibcs2/ibcs2_misc.c
+++ b/sys/i386/ibcs2/ibcs2_misc.c
@@ -144,36 +144,29 @@ ibcs2_wait(td, uap)
struct thread *td;
struct ibcs2_wait_args *uap;
{
- int error, status;
- struct wait_args w4;
+ int error, options, status;
+ int *statusp;
+ pid_t pid;
struct trapframe *tf = td->td_frame;
- w4.rusage = NULL;
- if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V))
+ if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V))
== (PSL_Z|PSL_PF|PSL_N|PSL_V)) {
/* waitpid */
- w4.pid = uap->a1;
- w4.status = (int *)uap->a2;
- w4.options = uap->a3;
+ pid = uap->a1;
+ statusp = (int *)uap->a2;
+ options = uap->a3;
} else {
/* wait */
- w4.pid = WAIT_ANY;
- w4.status = (int *)uap->a1;
- w4.options = 0;
+ pid = WAIT_ANY;
+ statusp = (int *)uap->a1;
+ options = 0;
}
- if ((error = wait4(td, &w4)) != 0)
+ error = kern_wait(td, pid, &status, options, NULL);
+ if (error)
return error;
- if (w4.status) { /* this is real iBCS brain-damage */
- error = copyin((caddr_t)w4.status, (caddr_t)&status,
- sizeof(w4.status));
- if(error)
- return error;
-
+ if (statusp) {
/*
- * Convert status/signal result. We must validate the
- * signal number stored in the exit status in case
- * the user changed it between wait4()'s copyout()
- * and our copyin().
+ * Convert status/signal result.
*/
if (WIFSTOPPED(status)) {
if (WSTOPSIG(status) <= 0 ||
@@ -191,8 +184,7 @@ ibcs2_wait(td, uap)
/* record result/status */
td->td_retval[1] = status;
- return copyout((caddr_t)&status, (caddr_t)w4.status,
- sizeof(w4.status));
+ return copyout(&status, statusp, sizeof(status));
}
return 0;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index dec3a976fb9d..5f37ca63c7c7 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -85,8 +85,6 @@ __FBSDID("$FreeBSD$");
/* Required to be non-static for SysVR4 emulator */
MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status");
-static int wait1(struct thread *, struct wait_args *, int);
-
/*
* exit --
* Death of process.
@@ -551,57 +549,59 @@ exit1(struct thread *td, int rv)
#ifdef COMPAT_43
/*
- * MPSAFE. The dirty work is handled by wait1().
+ * MPSAFE. The dirty work is handled by kern_wait().
*/
int
owait(struct thread *td, struct owait_args *uap __unused)
{
- struct wait_args w;
+ int error, status;
- w.options = 0;
- w.rusage = NULL;
- w.pid = WAIT_ANY;
- w.status = NULL;
- return (wait1(td, &w, 1));
+ error = kern_wait(td, WAIT_ANY, &status, 0, NULL);
+ if (error == 0)
+ td->td_retval[1] = status;
+ return (error);
}
#endif /* COMPAT_43 */
/*
- * MPSAFE. The dirty work is handled by wait1().
+ * MPSAFE. The dirty work is handled by kern_wait().
*/
int
wait4(struct thread *td, struct wait_args *uap)
{
-
- return (wait1(td, uap, 0));
+ struct rusage ru;
+ int error, status;
+
+ error = kern_wait(td, uap->pid, &status, uap->options, &ru);
+ if (uap->status != NULL && error == 0)
+ error = copyout(&status, uap->status, sizeof(status));
+ if (uap->rusage != NULL && error == 0)
+ error = copyout(&ru, uap->rusage, sizeof(struct rusage));
+ return (error);
}
-/*
- * MPSAFE
- */
-static int
-wait1(struct thread *td, struct wait_args *uap, int compat)
+int
+kern_wait(struct thread *td, pid_t pid, int *status, int options, struct rusage *rusage)
{
- struct rusage ru;
int nfound;
struct proc *p, *q, *t;
- int status, error;
+ int error;
q = td->td_proc;
- if (uap->pid == 0) {
+ if (pid == 0) {
PROC_LOCK(q);
- uap->pid = -q->p_pgid;
+ pid = -q->p_pgid;
PROC_UNLOCK(q);
}
- if (uap->options &~ (WUNTRACED|WNOHANG|WCONTINUED|WLINUXCLONE))
+ if (options &~ (WUNTRACED|WNOHANG|WCONTINUED|WLINUXCLONE))
return (EINVAL);
loop:
nfound = 0;
sx_xlock(&proctree_lock);
LIST_FOREACH(p, &q->p_children, p_sibling) {
PROC_LOCK(p);
- if (uap->pid != WAIT_ANY &&
- p->p_pid != uap->pid && p->p_pgid != -uap->pid) {
+ if (pid != WAIT_ANY &&
+ p->p_pid != pid && p->p_pgid != -pid) {
PROC_UNLOCK(p);
continue;
}
@@ -615,7 +615,7 @@ loop:
* signifies we want to wait for threads and not processes.
*/
if ((p->p_sigparent != SIGCHLD) ^
- ((uap->options & WLINUXCLONE) != 0)) {
+ ((options & WLINUXCLONE) != 0)) {
PROC_UNLOCK(p);
continue;
}
@@ -623,37 +623,16 @@ loop:
nfound++;
if (p->p_state == PRS_ZOMBIE) {
td->td_retval[0] = p->p_pid;
-#ifdef COMPAT_43
- if (compat)
- td->td_retval[1] = p->p_xstat;
- else
-#endif
- if (uap->status) {
- status = p->p_xstat; /* convert to int */
- PROC_UNLOCK(p);
- if ((error = copyout(&status,
- uap->status, sizeof(status)))) {
- sx_xunlock(&proctree_lock);
- mtx_unlock(&Giant);
- return (error);
- }
- PROC_LOCK(p);
- }
- if (uap->rusage) {
- bcopy(p->p_ru, &ru, sizeof(ru));
- PROC_UNLOCK(p);
- if ((error = copyout(&ru,
- uap->rusage, sizeof (struct rusage)))) {
- sx_xunlock(&proctree_lock);
- mtx_unlock(&Giant);
- return (error);
- }
- } else
- PROC_UNLOCK(p);
+ if (status)
+ *status = p->p_xstat; /* convert to int */
+ if (rusage)
+ bcopy(p->p_ru, rusage, sizeof(struct rusage));
+
/*
* If we got the child via a ptrace 'attach',
* we need to give it back to the old parent.
*/
+ PROC_UNLOCK(p);
if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) {
PROC_LOCK(p);
p->p_oppid = 0;
@@ -725,7 +704,7 @@ loop:
mac_destroy_proc(p);
#endif
KASSERT(FIRST_THREAD_IN_PROC(p),
- ("wait1: no residual thread!"));
+ ("kern_wait: no residual thread!"));
uma_zfree(proc_zone, p);
sx_xlock(&allproc_lock);
nprocs--;
@@ -735,44 +714,26 @@ loop:
mtx_lock_spin(&sched_lock);
if (P_SHOULDSTOP(p) && (p->p_suspcount == p->p_numthreads) &&
((p->p_flag & P_WAITED) == 0) &&
- (p->p_flag & P_TRACED || uap->options & WUNTRACED)) {
+ (p->p_flag & P_TRACED || options & WUNTRACED)) {
mtx_unlock_spin(&sched_lock);
p->p_flag |= P_WAITED;
sx_xunlock(&proctree_lock);
td->td_retval[0] = p->p_pid;
-#ifdef COMPAT_43
- if (compat) {
- td->td_retval[1] = W_STOPCODE(p->p_xstat);
- PROC_UNLOCK(p);
- error = 0;
- } else
-#endif
- if (uap->status) {
- status = W_STOPCODE(p->p_xstat);
- PROC_UNLOCK(p);
- error = copyout(&status,
- uap->status, sizeof(status));
- } else {
- PROC_UNLOCK(p);
- error = 0;
- }
- return (error);
+ if (status)
+ *status = W_STOPCODE(p->p_xstat);
+ PROC_UNLOCK(p);
+ return (0);
}
mtx_unlock_spin(&sched_lock);
- if (uap->options & WCONTINUED && (p->p_flag & P_CONTINUED)) {
+ if (options & WCONTINUED && (p->p_flag & P_CONTINUED)) {
sx_xunlock(&proctree_lock);
td->td_retval[0] = p->p_pid;
p->p_flag &= ~P_CONTINUED;
PROC_UNLOCK(p);
- if (uap->status) {
- status = SIGCONT;
- error = copyout(&status,
- uap->status, sizeof(status));
- } else
- error = 0;
-
- return (error);
+ if (status)
+ *status = SIGCONT;
+ return (0);
}
PROC_UNLOCK(p);
}
@@ -780,7 +741,7 @@ loop:
sx_xunlock(&proctree_lock);
return (ECHILD);
}
- if (uap->options & WNOHANG) {
+ if (options & WNOHANG) {
sx_xunlock(&proctree_lock);
td->td_retval[0] = 0;
return (0);
diff --git a/sys/sys/wait.h b/sys/sys/wait.h
index 74ed683068fe..965c470a40ea 100644
--- a/sys/sys/wait.h
+++ b/sys/sys/wait.h
@@ -96,7 +96,11 @@
#define WAIT_MYPGRP 0 /* any process in my process group */
#endif /* __BSD_VISIBLE */
-#ifndef _KERNEL
+#ifdef _KERNEL
+int kern_wait(struct thread *td, pid_t pid, int *status, int options,
+ struct rusage *rusage);
+
+#else
#include <sys/types.h>
__BEGIN_DECLS