diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2014-01-20 21:19:29 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2014-01-20 21:19:29 +0000 |
commit | ee0ecd963da884228886664033fd7694a2eb8316 (patch) | |
tree | 52a9fc57aabaf3a0c1918697e14b24bc5f30528e | |
parent | d97b363c4b36ac6fd5d7bd23bce2badd8549c7ee (diff) |
Threads can't be zombies, only processes, so change zombproc to zombprocess,
make it a list of processes, and change P_NOZOMBIE and P_STOPPED from thread
flags to process flags. Add allprocess list for the code that just wants
to see processes.
ok tedu@
-rw-r--r-- | lib/libkvm/kvm_file2.c | 80 | ||||
-rw-r--r-- | lib/libkvm/kvm_proc2.c | 178 | ||||
-rw-r--r-- | sys/arch/sh/sh/db_interface.c | 11 | ||||
-rw-r--r-- | sys/arch/sh/sh/pmap.c | 16 | ||||
-rw-r--r-- | sys/compat/linux/linux_sched.c | 10 | ||||
-rw-r--r-- | sys/kern/init_main.c | 13 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 181 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 22 | ||||
-rw-r--r-- | sys/kern/kern_ktrace.c | 18 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 79 | ||||
-rw-r--r-- | sys/kern/kern_resource.c | 23 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 27 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 99 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_vnops.c | 31 | ||||
-rw-r--r-- | sys/sys/proc.h | 25 |
15 files changed, 434 insertions, 379 deletions
diff --git a/lib/libkvm/kvm_file2.c b/lib/libkvm/kvm_file2.c index b970247380e..bd18d4b1a0b 100644 --- a/lib/libkvm/kvm_file2.c +++ b/lib/libkvm/kvm_file2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kvm_file2.c,v 1.32 2014/01/20 04:27:32 guenther Exp $ */ +/* $OpenBSD: kvm_file2.c,v 1.33 2014/01/20 21:19:28 guenther Exp $ */ /* * Copyright (c) 2009 Todd C. Miller <Todd.Miller@courtesan.com> @@ -124,7 +124,7 @@ static int fill_file(kvm_t *, struct kinfo_file *, struct file *, u_long, struct vnode *, struct proc *, int, pid_t); static int filestat(kvm_t *, struct kinfo_file *, struct vnode *); -LIST_HEAD(proclist, proc); +LIST_HEAD(processlist, process); struct kinfo_file * kvm_getfiles(kvm_t *kd, int op, int arg, size_t esize, int *cnt) @@ -268,9 +268,9 @@ kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt) struct filelist filehead; struct filedesc0 filed0; #define filed filed0.fd_fd - struct proclist allproc; - struct proc *p, proc, proc2; - struct process process; + struct processlist allprocess; + struct proc proc, proc2; + struct process *pr, process; struct pcred pcred; struct ucred ucred; char *filebuf = NULL; @@ -279,7 +279,7 @@ kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt) nl[0].n_name = "_filehead"; nl[1].n_name = "_nfiles"; - nl[2].n_name = "_allproc"; + nl[2].n_name = "_allprocess"; nl[3].n_name = 0; if (kvm_nlist(kd, nl) != 0) { @@ -297,8 +297,8 @@ kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt) _kvm_err(kd, kd->program, "can't read nfiles"); return (NULL); } - if (KREAD(kd, nl[2].n_value, &allproc)) { - _kvm_err(kd, kd->program, "can't read allproc"); + if (KREAD(kd, nl[2].n_value, &allprocess)) { + _kvm_err(kd, kd->program, "can't read allprocess"); return (NULL); } /* this may be more room than we need but counting is expensive */ @@ -308,52 +308,32 @@ kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt) if (kd->filebase == NULL) return (NULL); - for (p = LIST_FIRST(&allproc); - p != NULL; - p = LIST_NEXT(&proc, p_list)) { - if (KREAD(kd, (u_long)p, &proc)) { - _kvm_err(kd, kd->program, "can't read proc at %lx", - (u_long)p); + for (pr = LIST_FIRST(&allprocess); + pr != NULL; + pr = LIST_NEXT(&process, ps_list)) { + if (KREAD(kd, (u_long)pr, &process)) { + _kvm_err(kd, kd->program, "can't read process at %lx", + (u_long)pr); goto cleanup; } - /* skip system, embryonic and undead processes */ - if ((proc.p_flag & P_SYSTEM) || (proc.p_flag & P_THREAD) || - proc.p_stat == SIDL || proc.p_stat == SZOMB) + if (process.ps_mainproc == NULL) continue; - if (op == KERN_FILE_BYPID) { - if (arg > 0 && proc.p_pid != (pid_t)arg) { - /* not the pid we are looking for */ - continue; - } - } else /* if (op == KERN_FILE_BYUID) */ { - if (arg >= 0 && proc.p_ucred->cr_uid != (uid_t)arg) { - /* not the uid we are looking for */ - continue; - } + if (KREAD(kd, (u_long)process.ps_mainproc, &proc)) { + _kvm_err(kd, kd->program, "can't read proc at %lx", + (u_long)process.ps_mainproc); + goto cleanup; } - if (proc.p_fd == NULL || proc.p_p == NULL) + /* skip system, exiting, embryonic and undead processes */ + if (proc.p_flag & P_SYSTEM || process.ps_flags & PS_EXITING || + proc.p_stat == SIDL || proc.p_stat == SZOMB) continue; - if (KREAD(kd, (u_long)proc.p_p, &process)) { - _kvm_err(kd, kd->program, "can't read process at %lx", - (u_long)proc.p_p); - goto cleanup; - } - if (process.ps_flags & PS_EXITING) - continue; - proc.p_p = &process; - if ((proc.p_flag & P_THREAD) == 0) - pid = proc.p_pid; - else { - if (KREAD(kd, (u_long)process.ps_mainproc, &proc2)) { - _kvm_err(kd, kd->program, - "can't read proc at %lx", - (u_long)process.ps_mainproc); - goto cleanup; - } - pid = proc2.p_pid; + if (op == KERN_FILE_BYPID && arg > 0 && + proc.p_pid != (pid_t)arg) { + /* not the pid we are looking for */ + continue; } if (KREAD(kd, (u_long)process.ps_cred, &pcred)) { @@ -366,9 +346,17 @@ kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt) (u_long)pcred.pc_ucred); goto cleanup; } + process.ps_mainproc = &proc; + proc.p_p = &process; process.ps_cred = &pcred; pcred.pc_ucred = &ucred; + if (op == KERN_FILE_BYUID && arg >= 0 && + proc.p_ucred->cr_uid != (uid_t)arg) { + /* not the uid we are looking for */ + continue; + } + if (KREAD(kd, (u_long)proc.p_fd, &filed0)) { _kvm_err(kd, kd->program, "can't read filedesc at %lx", (u_long)proc.p_fd); diff --git a/lib/libkvm/kvm_proc2.c b/lib/libkvm/kvm_proc2.c index 4a9604e5dc6..b3c3feb0600 100644 --- a/lib/libkvm/kvm_proc2.c +++ b/lib/libkvm/kvm_proc2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kvm_proc2.c,v 1.17 2013/11/12 14:49:41 guenther Exp $ */ +/* $OpenBSD: kvm_proc2.c,v 1.18 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: kvm_proc.c,v 1.30 1999/03/24 05:50:50 mrg Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -103,14 +103,14 @@ * at most maxcnt procs. */ static int -kvm_proclist(kvm_t *kd, int op, int arg, struct proc *p, +kvm_proclist(kvm_t *kd, int op, int arg, struct process *pr, char *bp, int maxcnt, size_t esize) { struct kinfo_proc kp; struct session sess; struct pcred pcred; struct ucred ucred; - struct proc proc, proc2; + struct proc proc, proc2, *p; struct process process, process2; struct pgrp pgrp; struct tty tty; @@ -124,33 +124,30 @@ kvm_proclist(kvm_t *kd, int op, int arg, struct proc *p, dothreads = op & KERN_PROC_SHOW_THREADS; op &= ~KERN_PROC_SHOW_THREADS; - for (; cnt < maxcnt && p != NULL; p = LIST_NEXT(&proc, p_list)) { - if (KREAD(kd, (u_long)p, &proc)) { - _kvm_err(kd, kd->program, "can't read proc at %lx", - (u_long)p); + /* + * Modelled on sysctl_doproc() in sys/kern/kern_sysctl.c + */ + for (; cnt < maxcnt && pr != NULL; pr = LIST_NEXT(&process, ps_list)) { + if (KREAD(kd, (u_long)pr, &process)) { + _kvm_err(kd, kd->program, "can't read process at %lx", + (u_long)pr); return (-1); } - if (KREAD(kd, (u_long)proc.p_p, &process)) { - _kvm_err(kd, kd->program, "can't read process at %lx", - (u_long)proc.p_p); + if (process.ps_pgrp == NULL) + continue; + if (KREAD(kd, (u_long)process.ps_mainproc, &proc)) { + _kvm_err(kd, kd->program, "can't read proc at %lx", + (u_long)process.ps_mainproc); return (-1); } + if (proc.p_stat == SIDL) + continue; if (KREAD(kd, (u_long)process.ps_cred, &pcred)) { _kvm_err(kd, kd->program, "can't read pcred at %lx", (u_long)process.ps_cred); return (-1); } - if ((proc.p_flag & P_THREAD) == 0) - process_pid = proc.p_pid; - else { - if (KREAD(kd, (u_long)process.ps_mainproc, &proc2)) { - _kvm_err(kd, kd->program, - "can't read proc at %lx", - (u_long)process.ps_mainproc); - return (-1); - } - process_pid = proc2.p_pid; - } + process_pid = proc.p_pid; if (KREAD(kd, (u_long)pcred.pc_ucred, &ucred)) { _kvm_err(kd, kd->program, "can't read ucred at %lx", (u_long)pcred.pc_ucred); @@ -277,24 +274,80 @@ kvm_proclist(kvm_t *kd, int op, int arg, struct proc *p, } /* set up stuff that might not always be there */ - vmp = &vm; - if (proc.p_stat == SIDL || - P_ZOMBIE(&proc) || - KREAD(kd, (u_long)proc.p_vmspace, &vm)) - vmp = NULL; - limp = &limits; if (!process.ps_limit || KREAD(kd, (u_long)process.ps_limit, &limits)) limp = NULL; + vmp = NULL; + + if (proc.p_stat != SIDL && !P_ZOMBIE(&proc) && + !KREAD(kd, (u_long)proc.p_vmspace, &vm)) + vmp = &vm; + #define do_copy_str(_d, _s, _l) kvm_read(kd, (u_long)(_s), (_d), (_l)-1) - if ((proc.p_flag & P_THREAD) == 0) { + FILL_KPROC(&kp, do_copy_str, &proc, &process, &pcred, + &ucred, &pgrp, p, proc.p_p, &sess, vmp, limp, sap, + 0, 1); + + /* stuff that's too painful to generalize */ + kp.p_pid = process_pid; + kp.p_ppid = parent_pid; + kp.p_sid = leader_pid; + if ((process.ps_flags & PS_CONTROLT) && sess.s_ttyp != NULL) { + kp.p_tdev = tty.t_dev; + if (tty.t_pgrp != NULL && + tty.t_pgrp != process.ps_pgrp && + KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) { + _kvm_err(kd, kd->program, + "can't read tpgrp at %lx", + (u_long)tty.t_pgrp); + return (-1); + } + kp.p_tpgid = tty.t_pgrp ? pgrp.pg_id : -1; + kp.p_tsess = PTRTOINT64(tty.t_session); + } else { + kp.p_tpgid = -1; + kp.p_tdev = NODEV; + } + + /* update %cpu for all threads */ + if (!dothreads) { + for (p = TAILQ_FIRST(&process.ps_threads); p != NULL; + p = TAILQ_NEXT(&proc, p_thr_link)) { + if (KREAD(kd, (u_long)p, &proc)) { + _kvm_err(kd, kd->program, + "can't read proc at %lx", + (u_long)p); + return (-1); + } + if (p == process.ps_mainproc) + continue; + kp.p_pctcpu += proc.p_pctcpu; + } + } + + memcpy(bp, &kp, esize); + bp += esize; + ++cnt; + + /* Skip per-thread entries if not required by op */ + if (!dothreads) + continue; + + for (p = TAILQ_FIRST(&process.ps_threads); p != NULL; + p = TAILQ_NEXT(&proc, p_thr_link)) { + if (KREAD(kd, (u_long)p, &proc)) { + _kvm_err(kd, kd->program, + "can't read proc at %lx", + (u_long)p); + return (-1); + } FILL_KPROC(&kp, do_copy_str, &proc, &process, &pcred, &ucred, &pgrp, p, proc.p_p, &sess, vmp, limp, sap, - 0, 1); + 1, 1); - /* stuff that's too painful to generalize */ + /* see above */ kp.p_pid = process_pid; kp.p_ppid = parent_pid; kp.p_sid = leader_pid; @@ -315,37 +368,6 @@ kvm_proclist(kvm_t *kd, int op, int arg, struct proc *p, kp.p_tpgid = -1; kp.p_tdev = NODEV; } - - memcpy(bp, &kp, esize); - bp += esize; - ++cnt; - } - - if (!dothreads) - continue; - - FILL_KPROC(&kp, do_copy_str, &proc, &process, &pcred, &ucred, - &pgrp, p, proc.p_p, &sess, vmp, limp, sap, 1, 1); - - /* stuff that's too painful to generalize into the macros */ - kp.p_pid = process_pid; - kp.p_ppid = parent_pid; - kp.p_sid = leader_pid; - if ((process.ps_flags & PS_CONTROLT) && sess.s_ttyp != NULL) { - kp.p_tdev = tty.t_dev; - if (tty.t_pgrp != NULL && - tty.t_pgrp != process.ps_pgrp && - KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) { - _kvm_err(kd, kd->program, - "can't read tpgrp at %lx", - (u_long)tty.t_pgrp); - return (-1); - } - kp.p_tpgid = tty.t_pgrp ? pgrp.pg_id : -1; - kp.p_tsess = PTRTOINT64(tty.t_session); - } else { - kp.p_tpgid = -1; - kp.p_tdev = NODEV; } memcpy(bp, &kp, esize); @@ -399,9 +421,9 @@ kvm_getprocs(kvm_t *kd, int op, int arg, size_t esize, int *cnt) } nthreads = size / esize; } else { - struct nlist nl[4]; - int i, maxthread; - struct proc *p; + struct nlist nl[5]; + int i, maxthread, maxprocess; + struct process *pr; char *bp; if (esize > sizeof(struct kinfo_proc)) { @@ -412,9 +434,10 @@ kvm_getprocs(kvm_t *kd, int op, int arg, size_t esize, int *cnt) memset(nl, 0, sizeof(nl)); nl[0].n_name = "_nthreads"; - nl[1].n_name = "_allproc"; - nl[2].n_name = "_zombproc"; - nl[3].n_name = NULL; + nl[1].n_name = "_nprocesses"; + nl[2].n_name = "_allprocess"; + nl[3].n_name = "_zombprocess"; + nl[4].n_name = NULL; if (kvm_nlist(kd, nl) != 0) { for (i = 0; nl[i].n_type != 0; ++i) @@ -427,27 +450,32 @@ kvm_getprocs(kvm_t *kd, int op, int arg, size_t esize, int *cnt) _kvm_err(kd, kd->program, "can't read nthreads"); return (NULL); } + if (KREAD(kd, nl[1].n_value, &maxprocess)) { + _kvm_err(kd, kd->program, "can't read nprocesses"); + return (NULL); + } + maxthread += maxprocess; kd->procbase = _kvm_malloc(kd, maxthread * esize); if (kd->procbase == 0) return (NULL); bp = (char *)kd->procbase; - /* allproc */ - if (KREAD(kd, nl[1].n_value, &p)) { - _kvm_err(kd, kd->program, "cannot read allproc"); + /* allprocess */ + if (KREAD(kd, nl[2].n_value, &pr)) { + _kvm_err(kd, kd->program, "cannot read allprocess"); return (NULL); } - nthreads = kvm_proclist(kd, op, arg, p, bp, maxthread, esize); + nthreads = kvm_proclist(kd, op, arg, pr, bp, maxthread, esize); if (nthreads < 0) return (NULL); - /* zombproc */ - if (KREAD(kd, nl[2].n_value, &p)) { - _kvm_err(kd, kd->program, "cannot read zombproc"); + /* zombprocess */ + if (KREAD(kd, nl[3].n_value, &pr)) { + _kvm_err(kd, kd->program, "cannot read zombprocess"); return (NULL); } - i = kvm_proclist(kd, op, arg, p, bp + (esize * nthreads), + i = kvm_proclist(kd, op, arg, pr, bp + (esize * nthreads), maxthread - nthreads, esize); if (i > 0) nthreads += i; diff --git a/sys/arch/sh/sh/db_interface.c b/sys/arch/sh/sh/db_interface.c index b74e46673ea..5b69acf7068 100644 --- a/sys/arch/sh/sh/db_interface.c +++ b/sys/arch/sh/sh/db_interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_interface.c,v 1.3 2010/04/21 03:03:26 deraadt Exp $ */ +/* $OpenBSD: db_interface.c,v 1.4 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: db_interface.c,v 1.37 2006/09/06 00:11:49 uwe Exp $ */ /*- @@ -368,10 +368,15 @@ char * __db_procname_by_asid(int asid) { static char notfound[] = "---"; + struct process *pr; struct proc *p; - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_vmspace->vm_map.pmap->pm_asid == asid) + LIST_FOREACH(pr, &allprocess, ps_list) { + /* find a thread that still has the process vmspace attached */ + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) + if (p->p_vmspace != NULL) + break; + if (p != NULL && p->p_vmspace->vm_map.pmap->pm_asid == asid) return (p->p_comm); } diff --git a/sys/arch/sh/sh/pmap.c b/sys/arch/sh/sh/pmap.c index a79035a7874..085df11e5fc 100644 --- a/sys/arch/sh/sh/pmap.c +++ b/sys/arch/sh/sh/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.20 2013/03/02 22:44:47 guenther Exp $ */ +/* $OpenBSD: pmap.c,v 1.21 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: pmap.c,v 1.55 2006/08/07 23:19:36 tsutsui Exp $ */ /*- @@ -1066,6 +1066,7 @@ __pmap_pte_load(pmap_t pmap, vaddr_t va, int flags) int __pmap_asid_alloc() { + struct process *pr; struct proc *p; int i, j, k, n, map, asid; @@ -1085,7 +1086,18 @@ __pmap_asid_alloc() } /* Steal ASID */ - LIST_FOREACH(p, &allproc, p_list) { + /* + * XXX this always steals the ASID of the *newest* proc with one, + * so it's far from LRU but rather almost pessimal once you have + * too many processes. + */ + LIST_FOREACH(pr, &allprocess, ps_list) { + /* find a thread that still has the process vmspace attached */ + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) + if (p->p_vmspace != NULL) + break; + if (p == NULL) + continue; if ((asid = p->p_vmspace->vm_map.pmap->pm_asid) > 0) { pmap_t pmap = p->p_vmspace->vm_map.pmap; pmap->pm_asid = -1; diff --git a/sys/compat/linux/linux_sched.c b/sys/compat/linux/linux_sched.c index 599dc9ffc7a..04fb2fec1b8 100644 --- a/sys/compat/linux/linux_sched.c +++ b/sys/compat/linux/linux_sched.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_sched.c,v 1.14 2012/05/25 04:39:40 guenther Exp $ */ +/* $OpenBSD: linux_sched.c,v 1.15 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: linux_sched.c,v 1.6 2000/05/28 05:49:05 thorpej Exp $ */ /*- @@ -110,13 +110,7 @@ linux_sys_clone(struct proc *p, void *v, register_t *retval) LINUX_CLONE_VFORK if ((cflags & (REQUIRED | BANNED)) != REQUIRED) return (EINVAL); - /* - * Linux says that CLONE_THREAD means no signal - * will be sent on exit (even if a non-standard - * signal is requested via CLONE_CSIGNAL), so pass - * FORK_NOZOMBIE too. - */ - flags |= FORK_THREAD | FORK_NOZOMBIE; + flags |= FORK_THREAD; } else { /* * These are only supported with CLONE_THREAD. Arguably, diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 14dff21a4d4..7e35cf205d2 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.202 2014/01/19 23:52:54 deraadt Exp $ */ +/* $OpenBSD: init_main.c,v 1.203 2014/01/20 21:19:27 guenther Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -266,6 +266,7 @@ main(void *framep) TAILQ_INSERT_TAIL(&process0.ps_threads, p, p_thr_link); process0.ps_refcnt = 1; p->p_p = pr = &process0; + LIST_INSERT_HEAD(&allprocess, pr, ps_list); /* Set the default routing table/domain. */ process0.ps_rtableid = 0; @@ -492,10 +493,12 @@ main(void *framep) * munched in mi_switch() after the time got set. */ nanotime(&boottime); - LIST_FOREACH(p, &allproc, p_list) { - p->p_p->ps_start = boottime; - nanouptime(&p->p_cpu->ci_schedstate.spc_runtime); - timespecclear(&p->p_rtime); + LIST_FOREACH(pr, &allprocess, ps_list) { + pr->ps_start = boottime; + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { + nanouptime(&p->p_cpu->ci_schedstate.spc_runtime); + timespecclear(&p->p_rtime); + } } uvm_swap_init(); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 40366f27390..eabd41c4dd6 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.130 2014/01/20 03:23:42 guenther Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.131 2014/01/20 21:19:27 guenther Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -235,6 +235,14 @@ exit1(struct proc *p, int rv, int flags) if (pr->ps_tracevp) ktrcleartrace(pr); #endif + + /* + * If parent has the SAS_NOCLDWAIT flag set, we're not + * going to become a zombie. + */ + if (pr->ps_pptr->ps_mainproc->p_sigacts->ps_flags & + SAS_NOCLDWAIT) + atomic_setbits_int(&pr->ps_flags, PS_NOZOMBIE); } #if NSYSTRACE > 0 @@ -249,12 +257,13 @@ exit1(struct proc *p, int rv, int flags) (*p->p_emul->e_proc_exit)(p); /* - * Remove proc from pidhash chain so looking it up won't - * work. Move it from allproc to zombproc, but do not yet - * wake up the reaper. We will put the proc on the - * deadproc list later (using the p_hash member), and - * wake up the reaper when we do. - */ + * Remove proc from pidhash chain and allproc so looking + * it up won't work. We will put the proc on the + * deadproc list later (using the p_hash member), and + * wake up the reaper when we do. If this is the last + * thread of a process that isn't PS_NOZOMBIE, we'll put + * the process on the zombprocess list below. + */ /* * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP! */ @@ -262,12 +271,24 @@ exit1(struct proc *p, int rv, int flags) LIST_REMOVE(p, p_hash); LIST_REMOVE(p, p_list); - LIST_INSERT_HEAD(&zombproc, p, p_list); - /* - * Give orphaned children to init(8). - */ if ((p->p_flag & P_THREAD) == 0) { + LIST_REMOVE(pr, ps_list); + + if ((pr->ps_flags & PS_NOZOMBIE) == 0) + LIST_INSERT_HEAD(&zombprocess, pr, ps_list); + else { + /* + * Not going to be a zombie, so it's now off all + * the lists scanned by ispidtaken(), so block + * fast reuse of the pid now. + */ + freepid(p->p_pid); + } + + /* + * Give orphaned children to init(8). + */ qr = LIST_FIRST(&pr->ps_children); if (qr) /* only need this if any child is S_ZOMB */ wakeup(initproc->p_p); @@ -295,7 +316,6 @@ exit1(struct proc *p, int rv, int flags) } } - /* add thread's accumulated rusage into the process's total */ ruadd(rup, &p->p_ru); @@ -316,21 +336,14 @@ exit1(struct proc *p, int rv, int flags) knote_processexit(pr); /* - * Notify parent that we're gone. If we have P_NOZOMBIE - * or parent has the SAS_NOCLDWAIT flag set, notify process 1 - * instead (and hope it will handle this situation). + * Notify parent that we're gone. If we're not going to + * become a zombie, reparent to process 1 (init) so that + * we can wake our original parent to possibly unblock + * wait4() to return ECHILD. */ - if ((p->p_flag & P_NOZOMBIE) || - (pr->ps_pptr->ps_mainproc->p_sigacts->ps_flags & - SAS_NOCLDWAIT)) { + if (pr->ps_flags & PS_NOZOMBIE) { struct process *ppr = pr->ps_pptr; proc_reparent(pr, initproc->p_p); - - /* - * Notify parent, so in case he was wait(2)ing or - * executing waitpid(2) with our pid, he will - * continue. - */ wakeup(ppr); } } @@ -340,6 +353,14 @@ exit1(struct proc *p, int rv, int flags) */ sigactsfree(p); + /* just a thread? detach it from its process */ + if (p->p_flag & P_THREAD) { + /* scheduler_wait_hook(pr->ps_mainproc, p); XXX */ + --pr->ps_refcnt; + KASSERT(pr->ps_refcnt > 0); + p->p_p = NULL; + } + /* * Other substructures are freed from reaper and wait(). */ @@ -363,8 +384,7 @@ exit1(struct proc *p, int rv, int flags) * Locking of this proclist is special; it's accessed in a * critical section of process exit, and thus locking it can't * modify interrupt state. We use a simple spin lock for this - * proclist. Processes on this proclist are also on zombproc; - * we use the p_hash member to linkup to deadproc. + * proclist. We use the p_hash member to linkup to deadproc. */ struct mutex deadproc_mutex = MUTEX_INITIALIZER(IPL_NONE); struct proclist deadproc = LIST_HEAD_INITIALIZER(deadproc); @@ -390,6 +410,13 @@ exit2(struct proc *p) wakeup(&deadproc); } +void +proc_free(struct proc *p) +{ + pool_put(&proc_pool, p); + nthreads--; +} + /* * Process reaper. This is run by a kernel thread to free the resources * of a dead process. Once the resources are free, the process becomes @@ -422,17 +449,25 @@ reaper(void) */ uvm_exit(p); - /* Process is now a true zombie. */ - if ((p->p_flag & P_NOZOMBIE) == 0) { - p->p_stat = SZOMB; - - if (P_EXITSIG(p) != 0) - prsignal(p->p_p->ps_pptr, P_EXITSIG(p)); - /* Wake up the parent so it can get exit status. */ - wakeup(p->p_p->ps_pptr); + if (p->p_flag & P_THREAD) { + /* Just a thread */ + proc_free(p); } else { - /* Noone will wait for us. Just zap the process now */ - proc_zap(p); + struct process *pr = p->p_p; + + if ((pr->ps_flags & PS_NOZOMBIE) == 0) { + /* Process is now a true zombie. */ + p->p_stat = SZOMB; + + if (P_EXITSIG(p) != 0) + prsignal(pr->ps_pptr, P_EXITSIG(p)); + + /* Wake up the parent so it can get exit status. */ + wakeup(pr->ps_pptr); + } else { + /* No one will wait for us. Just zap the process now */ + process_zap(pr); + } } KERNEL_UNLOCK(); @@ -481,7 +516,7 @@ loop: nfound = 0; LIST_FOREACH(pr, &q->p_p->ps_children, ps_sibling) { p = pr->ps_mainproc; - if ((p->p_flag & P_NOZOMBIE) || + if ((pr->ps_flags & PS_NOZOMBIE) || (pid != WAIT_ANY && p->p_pid != pid && pr->ps_pgid != -pid)) @@ -489,7 +524,7 @@ loop: /* * Wait for processes with p_exitsig != SIGCHLD processes only - * if WALTSIG is set; wait for processes with pexitsig == + * if WALTSIG is set; wait for processes with p_exitsig == * SIGCHLD only if WALTSIG is clear. */ if ((options & WALTSIG) ? @@ -561,8 +596,7 @@ proc_finish_wait(struct proc *waiter, struct proc *p) * we need to give it back to the old parent. */ pr = p->p_p; - if ((p->p_flag & P_THREAD) == 0 && pr->ps_oppid && - (tr = prfind(pr->ps_oppid))) { + if (pr->ps_oppid && (tr = prfind(pr->ps_oppid))) { atomic_clearbits_int(&pr->ps_flags, PS_TRACED); pr->ps_oppid = 0; proc_reparent(pr, tr); @@ -574,7 +608,9 @@ proc_finish_wait(struct proc *waiter, struct proc *p) p->p_xstat = 0; rup = &waiter->p_p->ps_cru; ruadd(rup, pr->ps_ru); - proc_zap(p); + LIST_REMOVE(pr, ps_list); /* off zombprocess */ + freepid(p->p_pid); + process_zap(pr); } } @@ -597,52 +633,41 @@ proc_reparent(struct process *child, struct process *parent) } void -proc_zap(struct proc *p) +process_zap(struct process *pr) { - struct process *pr = p->p_p; struct vnode *otvp; + struct proc *p = pr->ps_mainproc; /* * Finally finished with old proc entry. * Unlink it from its process group and free it. */ - if ((p->p_flag & P_THREAD) == 0) - leavepgrp(pr); - LIST_REMOVE(p, p_list); /* off zombproc */ - if ((p->p_flag & P_THREAD) == 0) { - LIST_REMOVE(pr, ps_sibling); - - /* - * Decrement the count of procs running with this uid. - */ - (void)chgproccnt(p->p_cred->p_ruid, -1); - - /* - * Release reference to text vnode - */ - otvp = pr->ps_textvp; - pr->ps_textvp = NULL; - if (otvp) - vrele(otvp); - } + leavepgrp(pr); + LIST_REMOVE(pr, ps_sibling); /* - * Remove us from our process list, possibly killing the process - * in the process (pun intended). + * Decrement the count of procs running with this uid. */ - if (--pr->ps_refcnt == 0) { - if (pr->ps_ptstat != NULL) - free(pr->ps_ptstat, M_SUBPROC); - pool_put(&rusage_pool, pr->ps_ru); - KASSERT(TAILQ_EMPTY(&pr->ps_threads)); - limfree(pr->ps_limit); - crfree(pr->ps_cred->pc_ucred); - pool_put(&pcred_pool, pr->ps_cred); - pool_put(&process_pool, pr); - nprocesses--; - } + (void)chgproccnt(pr->ps_cred->p_ruid, -1); - freepid(p->p_pid); - pool_put(&proc_pool, p); - nthreads--; + /* + * Release reference to text vnode + */ + otvp = pr->ps_textvp; + pr->ps_textvp = NULL; + if (otvp) + vrele(otvp); + + KASSERT(pr->ps_refcnt == 1); + if (pr->ps_ptstat != NULL) + free(pr->ps_ptstat, M_SUBPROC); + pool_put(&rusage_pool, pr->ps_ru); + KASSERT(TAILQ_EMPTY(&pr->ps_threads)); + limfree(pr->ps_limit); + crfree(pr->ps_cred->pc_ucred); + pool_put(&pcred_pool, pr->ps_cred); + pool_put(&process_pool, pr); + nprocesses--; + + proc_free(p); } diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 5a426374126..9188a7d50a3 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.155 2014/01/20 03:23:42 guenther Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.156 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -134,7 +134,7 @@ sys___tfork(struct proc *p, void *v, register_t *retval) #endif flags = FORK_TFORK | FORK_THREAD | FORK_SIGHAND | FORK_SHAREVM - | FORK_NOZOMBIE | FORK_SHAREFILES; + | FORK_SHAREFILES; return (fork1(p, 0, flags, param.tf_stack, param.tf_tid, tfork_child_return, param.tf_tcb, retval, NULL)); @@ -195,6 +195,9 @@ process_new(struct proc *p, struct process *parent) atomic_setbits_int(&pr->ps_flags, PS_CONTROLT); p->p_p = pr; + + /* it's sufficiently inited to be globally visible */ + LIST_INSERT_HEAD(&allprocess, pr, ps_list); } /* print the 'table full' message once per 10 seconds */ @@ -220,8 +223,7 @@ fork1(struct proc *curp, int exitsig, int flags, void *stack, pid_t *tidptr, /* sanity check some flag combinations */ if (flags & FORK_THREAD) { - if ((flags & (FORK_SIGHAND | FORK_NOZOMBIE)) != - (FORK_SIGHAND | FORK_NOZOMBIE)) + if ((flags & FORK_SIGHAND) == 0) return (EINVAL); } if (flags & FORK_SIGHAND && (flags & FORK_SHAREVM) == 0) @@ -330,6 +332,8 @@ fork1(struct proc *curp, int exitsig, int flags, void *stack, pid_t *tidptr, startprofclock(pr); if ((flags & FORK_PTRACE) && (curpr->ps_flags & PS_TRACED)) atomic_setbits_int(&pr->ps_flags, PS_TRACED); + if (flags & FORK_NOZOMBIE) + atomic_setbits_int(&pr->ps_flags, PS_NOZOMBIE); } if (flags & FORK_SHAREFILES) @@ -341,8 +345,6 @@ fork1(struct proc *curp, int exitsig, int flags, void *stack, pid_t *tidptr, atomic_setbits_int(&pr->ps_flags, PS_PPWAIT); atomic_setbits_int(&curpr->ps_flags, PS_ISPWAIT); } - if (flags & FORK_NOZOMBIE) - atomic_setbits_int(&p->p_flag, P_NOZOMBIE); #ifdef KTRACE /* @@ -538,7 +540,7 @@ int ispidtaken(pid_t pid) { uint32_t i; - struct proc *p; + struct process *pr; for (i = 0; i < nitems(oldpids); i++) if (pid == oldpids[i]) @@ -548,9 +550,9 @@ ispidtaken(pid_t pid) return (1); if (pgfind(pid) != NULL) return (1); - LIST_FOREACH(p, &zombproc, p_list) { - if (p->p_pid == pid || - (p->p_p->ps_pgrp && p->p_p->ps_pgrp->pg_id == pid)) + LIST_FOREACH(pr, &zombprocess, ps_list) { + if (pr->ps_pid == pid || + (pr->ps_pgrp && pr->ps_pgrp->pg_id == pid)) return (1); } return (0); diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 50e29d13398..da050c9e7fd 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_ktrace.c,v 1.61 2013/09/14 02:28:01 guenther Exp $ */ +/* $OpenBSD: kern_ktrace.c,v 1.62 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $ */ /* @@ -403,7 +403,6 @@ sys_ktrace(struct proc *curp, void *v, register_t *retval) syscallarg(pid_t) pid; } */ *uap = v; struct vnode *vp = NULL; - struct proc *p = NULL; struct process *pr = NULL; struct ucred *cred = NULL; struct pgrp *pg; @@ -437,10 +436,10 @@ sys_ktrace(struct proc *curp, void *v, register_t *retval) * Clear all uses of the tracefile */ if (ops == KTROP_CLEARFILE) { - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_p->ps_tracevp == vp) { - if (ktrcanset(curp, p->p_p)) - ktrcleartrace(p->p_p); + LIST_FOREACH(pr, &allprocess, ps_list) { + if (pr->ps_tracevp == vp) { + if (ktrcanset(curp, pr)) + ktrcleartrace(pr); else error = EPERM; } @@ -587,6 +586,7 @@ ktrwriteraw(struct proc *p, struct vnode *vp, struct ucred *cred, { struct uio auio; struct iovec aiov[2]; + struct process *pr; int error; auio.uio_iov = &aiov[0]; @@ -615,9 +615,9 @@ ktrwriteraw(struct proc *p, struct vnode *vp, struct ucred *cred, */ log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", error); - LIST_FOREACH(p, &allproc, p_list) - if (p->p_p->ps_tracevp == vp && p->p_p->ps_tracecred == cred) - ktrcleartrace(p->p_p); + LIST_FOREACH(pr, &allprocess, ps_list) + if (pr->ps_tracevp == vp && pr->ps_tracecred == cred) + ktrcleartrace(pr); vput(vp); return (error); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 4d028a557c6..a22597aa23e 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_proc.c,v 1.54 2013/10/02 21:17:32 sf Exp $ */ +/* $OpenBSD: kern_proc.c,v 1.55 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* @@ -60,8 +60,9 @@ struct pidhashhead *pidhashtbl; u_long pidhash; struct pgrphashhead *pgrphashtbl; u_long pgrphash; +struct processlist allprocess; +struct processlist zombprocess; struct proclist allproc; -struct proclist zombproc; struct pool proc_pool; struct pool process_pool; @@ -82,8 +83,9 @@ void pgrpdump(void); void procinit(void) { + LIST_INIT(&allprocess); + LIST_INIT(&zombprocess); LIST_INIT(&allproc); - LIST_INIT(&zombproc); pidhashtbl = hashinit(maxthread / 4, M_PROC, M_NOWAIT, &pidhash); @@ -437,7 +439,7 @@ db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) return; } - p = LIST_FIRST(&allproc); + pr = LIST_FIRST(&allprocess); switch (*mode) { @@ -455,45 +457,46 @@ db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) break; } - while (p != 0) { - pr = p->p_p; + while (pr != NULL) { ppr = pr->ps_pptr; - if (p->p_stat) { - - db_printf("%c%5d ", p == curproc ? '*' : ' ', - p->p_pid); - - switch (*mode) { - - case 'a': - db_printf("%-10.10s %18p %18p %18p\n", - p->p_comm, p, p->p_addr, p->p_vmspace); - break; - - case 'n': - db_printf("%5d %5d %5d %d %#10x " - "%-12.12s %-16s\n", - ppr ? ppr->ps_pid : -1, - pr->ps_pgrp ? pr->ps_pgrp->pg_id : -1, - pr->ps_cred->p_ruid, p->p_stat, - p->p_flag | p->p_p->ps_flags, - (p->p_wchan && p->p_wmesg) ? - p->p_wmesg : "", p->p_comm); - break; - - case 'w': - db_printf("%-16s %-8s %18p %s\n", p->p_comm, - p->p_emul->e_name, p->p_wchan, - (p->p_wchan && p->p_wmesg) ? - p->p_wmesg : ""); - break; + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { + if (p->p_stat) { + db_printf("%c%5d ", p == curproc ? '*' : ' ', + p->p_pid); + + switch (*mode) { + + case 'a': + db_printf("%-10.10s %18p %18p %18p\n", + p->p_comm, p, p->p_addr, p->p_vmspace); + break; + + case 'n': + db_printf("%5d %5d %5d %d %#10x " + "%-12.12s %-16s\n", + ppr ? ppr->ps_pid : -1, + pr->ps_pgrp ? pr->ps_pgrp->pg_id : -1, + pr->ps_cred->p_ruid, p->p_stat, + p->p_flag | pr->ps_flags, + (p->p_wchan && p->p_wmesg) ? + p->p_wmesg : "", p->p_comm); + break; + + case 'w': + db_printf("%-16s %-8s %18p %s\n", p->p_comm, + p->p_emul->e_name, p->p_wchan, + (p->p_wchan && p->p_wmesg) ? + p->p_wmesg : ""); + break; + + } } } - p = LIST_NEXT(p, p_list); - if (p == 0 && doingzomb == 0) { + pr = LIST_NEXT(pr, ps_list); + if (pr == NULL && doingzomb == 0) { doingzomb = 1; - p = LIST_FIRST(&zombproc); + pr = LIST_FIRST(&zombprocess); } } } diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 4ba85ea9da5..6a6100da684 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_resource.c,v 1.46 2013/10/25 04:42:48 guenther Exp $ */ +/* $OpenBSD: kern_resource.c,v 1.47 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: kern_resource.c,v 1.38 1996/10/23 07:19:38 matthias Exp $ */ /*- @@ -73,7 +73,6 @@ sys_getpriority(struct proc *curp, void *v, register_t *retval) syscallarg(id_t) who; } */ *uap = v; struct process *pr; - struct proc *p; int low = NZERO + PRIO_MAX + 1; switch (SCARG(uap, which)) { @@ -105,11 +104,10 @@ sys_getpriority(struct proc *curp, void *v, register_t *retval) case PRIO_USER: if (SCARG(uap, who) == 0) SCARG(uap, who) = curp->p_ucred->cr_uid; - LIST_FOREACH(p, &allproc, p_list) - if ((p->p_flag & P_THREAD) == 0 && - p->p_ucred->cr_uid == SCARG(uap, who) && - p->p_p->ps_nice < low) - low = p->p_p->ps_nice; + LIST_FOREACH(pr, &allprocess, ps_list) + if (pr->ps_cred->pc_ucred->cr_uid == SCARG(uap, who) && + pr->ps_nice < low) + low = pr->ps_nice; break; default: @@ -160,18 +158,15 @@ sys_setpriority(struct proc *curp, void *v, register_t *retval) break; } - case PRIO_USER: { - struct proc *p; + case PRIO_USER: if (SCARG(uap, who) == 0) SCARG(uap, who) = curp->p_ucred->cr_uid; - LIST_FOREACH(p, &allproc, p_list) - if ((p->p_flag & P_THREAD) == 0 && - p->p_ucred->cr_uid == SCARG(uap, who)) { - error = donice(curp, p->p_p, SCARG(uap, prio)); + LIST_FOREACH(pr, &allprocess, ps_list) + if (pr->ps_cred->pc_ucred->cr_uid == SCARG(uap, who)) { + error = donice(curp, pr, SCARG(uap, prio)); found++; } break; - } default: return (EINVAL); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index dd8fbfcc83e..a1b210e3f3e 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.155 2013/10/08 03:50:07 guenther Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.156 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -616,8 +616,9 @@ killpg1(struct proc *cp, int signum, int pgid, int all) /* * broadcast */ - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_pid <= 1 || p->p_flag & (P_SYSTEM|P_THREAD) || + LIST_FOREACH(pr, &allprocess, ps_list) { + p = pr->ps_mainproc; + if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == cp || !cansignal(cp, pc, p, signum)) continue; nfound++; @@ -1222,6 +1223,7 @@ keep: void proc_stop(struct proc *p, int sw) { + struct process *pr = p->p_p; extern void *softclock_si; #ifdef MULTIPROCESSOR @@ -1229,8 +1231,9 @@ proc_stop(struct proc *p, int sw) #endif p->p_stat = SSTOP; - atomic_clearbits_int(&p->p_p->ps_flags, PS_WAITED); - atomic_setbits_int(&p->p_flag, P_STOPPED|P_SUSPSIG); + atomic_clearbits_int(&pr->ps_flags, PS_WAITED); + atomic_setbits_int(&pr->ps_flags, PS_STOPPED); + atomic_setbits_int(&p->p_flag, P_SUSPSIG); if (!timeout_pending(&proc_stop_to)) { timeout_add(&proc_stop_to, 0); /* @@ -1251,17 +1254,17 @@ proc_stop(struct proc *p, int sw) void proc_stop_sweep(void *v) { - struct proc *p; + struct process *pr; - LIST_FOREACH(p, &allproc, p_list) { - if ((p->p_flag & P_STOPPED) == 0) + LIST_FOREACH(pr, &allprocess, ps_list) { + if ((pr->ps_flags & PS_STOPPED) == 0) continue; - atomic_clearbits_int(&p->p_flag, P_STOPPED); + atomic_clearbits_int(&pr->ps_flags, PS_STOPPED); - if ((p->p_p->ps_pptr->ps_mainproc->p_sigacts->ps_flags & + if ((pr->ps_pptr->ps_mainproc->p_sigacts->ps_flags & SAS_NOCLDSTOP) == 0) - prsignal(p->p_p->ps_pptr, SIGCHLD); - wakeup(p->p_p->ps_pptr); + prsignal(pr->ps_pptr, SIGCHLD); + wakeup(pr->ps_pptr); } } diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 41ef093684b..2e36b845fee 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.242 2014/01/20 03:23:42 guenther Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.243 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -1188,6 +1188,7 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, struct filedesc *fdp; struct file *fp; struct proc *pp; + struct process *pr; size_t buflen, elem_size, elem_count, outsize; char *dp = where; int arg, i, error = 0, needed = 0; @@ -1245,13 +1246,13 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, error = EINVAL; break; } - LIST_FOREACH(pp, &allproc, p_list) { + LIST_FOREACH(pr, &allprocess, ps_list) { /* * skip system, exiting, embryonic and undead - * processes, as well as threads + * processes */ - if ((pp->p_flag & P_SYSTEM) || (pp->p_flag & P_THREAD) - || (pp->p_p->ps_flags & PS_EXITING) + pp = pr->ps_mainproc; + if ((pp->p_flag & P_SYSTEM) || (pr->ps_flags & PS_EXITING) || pp->p_stat == SIDL || pp->p_stat == SZOMB) continue; if (arg > 0 && pp->p_pid != (pid_t)arg) { @@ -1259,14 +1260,14 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, continue; } fdp = pp->p_fd; - if (pp->p_p->ps_textvp) - FILLIT(NULL, NULL, KERN_FILE_TEXT, pp->p_p->ps_textvp, pp); + if (pr->ps_textvp) + FILLIT(NULL, NULL, KERN_FILE_TEXT, pr->ps_textvp, pp); if (fdp->fd_cdir) FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pp); if (fdp->fd_rdir) FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pp); - if (pp->p_p->ps_tracevp) - FILLIT(NULL, NULL, KERN_FILE_TRACE, pp->p_p->ps_tracevp, pp); + if (pr->ps_tracevp) + FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pp); for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fdp->fd_ofiles[i]) == NULL) continue; @@ -1277,13 +1278,13 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, } break; case KERN_FILE_BYUID: - LIST_FOREACH(pp, &allproc, p_list) { + LIST_FOREACH(pr, &allprocess, ps_list) { + pp = pr->ps_mainproc; /* * skip system, exiting, embryonic and undead - * processes, as well as threads + * processes */ - if ((pp->p_flag & P_SYSTEM) || (pp->p_flag & P_THREAD) - || (pp->p_p->ps_flags & PS_EXITING) + if ((pp->p_flag & P_SYSTEM) || (pr->ps_flags & PS_EXITING) || pp->p_stat == SIDL || pp->p_stat == SZOMB) continue; if (arg >= 0 && pp->p_ucred->cr_uid != (uid_t)arg) { @@ -1295,8 +1296,8 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pp); if (fdp->fd_rdir) FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pp); - if (pp->p_p->ps_tracevp) - FILLIT(NULL, NULL, KERN_FILE_TRACE, pp->p_p->ps_tracevp, pp); + if (pr->ps_tracevp) + FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pp); for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fdp->fd_ofiles[i]) == NULL) continue; @@ -1360,21 +1361,22 @@ sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) if (where != NULL) kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK); - p = LIST_FIRST(&allproc); + pr = LIST_FIRST(&allprocess); doingzomb = 0; again: - for (; p != 0; p = LIST_NEXT(p, p_list)) { + for (; pr != NULL; pr = LIST_NEXT(pr, ps_list)) { + /* XXX skip processes in the middle of being zapped */ + if (pr->ps_pgrp == NULL) + continue; + + p = pr->ps_mainproc; + /* * Skip embryonic processes. */ if (p->p_stat == SIDL) continue; - /* XXX skip processes in the middle of being zapped */ - pr = p->p_p; - if (pr->ps_pgrp == NULL) - continue; - /* * TODO - make more efficient (see notes below). */ @@ -1429,33 +1431,17 @@ again: goto err; } - if ((p->p_flag & P_THREAD) == 0) { - if (buflen >= elem_size && elem_count > 0) { - fill_kproc(p, kproc, 0, show_pointers); - /* Update %cpu for all threads */ - if (!dothreads) { - TAILQ_FOREACH(pp, &pr->ps_threads, - p_thr_link) { - if (pp == p) - continue; - kproc->p_pctcpu += pp->p_pctcpu; - } + if (buflen >= elem_size && elem_count > 0) { + fill_kproc(p, kproc, 0, show_pointers); + /* Update %cpu for all threads */ + if (!dothreads) { + TAILQ_FOREACH(pp, &pr->ps_threads, + p_thr_link) { + if (pp == p) + continue; + kproc->p_pctcpu += pp->p_pctcpu; } - error = copyout(kproc, dp, elem_size); - if (error) - goto err; - dp += elem_size; - buflen -= elem_size; - elem_count--; } - needed += elem_size; - } - /* Skip the second entry if not required by op */ - if (!dothreads) - continue; - - if (buflen >= elem_size && elem_count > 0) { - fill_kproc(p, kproc, 1, show_pointers); error = copyout(kproc, dp, elem_size); if (error) goto err; @@ -1464,9 +1450,26 @@ again: elem_count--; } needed += elem_size; + + /* Skip per-thread entries if not required by op */ + if (!dothreads) + continue; + + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { + if (buflen >= elem_size && elem_count > 0) { + fill_kproc(p, kproc, 1, show_pointers); + error = copyout(kproc, dp, elem_size); + if (error) + goto err; + dp += elem_size; + buflen -= elem_size; + elem_count--; + } + needed += elem_size; + } } if (doingzomb == 0) { - p = LIST_FIRST(&zombproc); + pr = LIST_FIRST(&zombprocess); doingzomb++; goto again; } diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c index 7b60dcbf196..92de9db8bd3 100644 --- a/sys/miscfs/procfs/procfs_vnops.c +++ b/sys/miscfs/procfs/procfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: procfs_vnops.c,v 1.57 2014/01/20 03:23:42 guenther Exp $ */ +/* $OpenBSD: procfs_vnops.c,v 1.58 2014/01/20 21:19:28 guenther Exp $ */ /* $NetBSD: procfs_vnops.c,v 1.40 1996/03/16 23:52:55 christos Exp $ */ /* @@ -845,9 +845,9 @@ procfs_readdir(void *v) /* * this is for the root of the procfs filesystem * what is needed is a special entry for "curproc" - * followed by an entry for each process on allproc + * followed by an entry for each process on allprocess #ifdef PROCFS_ZOMBIE - * and zombproc. + * and zombprocess. #endif */ @@ -856,16 +856,14 @@ procfs_readdir(void *v) int doingzomb = 0; #endif int pcnt = i; - volatile struct proc *p = LIST_FIRST(&allproc); + volatile struct process *pr = LIST_FIRST(&allprocess); if (pcnt > 3) pcnt = 3; #ifdef PROCFS_ZOMBIE again: #endif - while (p && (p->p_flag & P_THREAD)) - p = LIST_NEXT(p, p_list); - for (; p && uio->uio_resid >= UIO_MX; i++, pcnt++) { + for (; pr && uio->uio_resid >= UIO_MX; i++, pcnt++) { switch (i) { case 0: /* `.' */ case 1: /* `..' */ @@ -913,21 +911,12 @@ procfs_readdir(void *v) /* fall through */ default: - while (pcnt < i) { + while (pcnt < i) pcnt++; - do { - p = LIST_NEXT(p, p_list); - } while (p && (p->p_flag & P_THREAD)); - if (!p) - goto done; - } - d.d_fileno = PROCFS_FILENO(p->p_pid, Pproc); + d.d_fileno = PROCFS_FILENO(pr->ps_pid, Pproc); d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), - "%ld", (long)p->p_pid); + "%ld", (long)pr->ps_pid); d.d_type = DT_REG; - do { - p = LIST_NEXT(p, p_list); - } while (p && (p->p_flag & P_THREAD)); break; } @@ -937,9 +926,9 @@ procfs_readdir(void *v) done: #ifdef PROCFS_ZOMBIE - if (p == 0 && doingzomb == 0) { + if (pr == NULL && doingzomb == 0) { doingzomb = 1; - p = LIST_FIRST(&zombproc); + pr = LIST_FIRST(&zombprocess); goto again; } #endif diff --git a/sys/sys/proc.h b/sys/sys/proc.h index b1525f20cd9..5e842066c79 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.173 2014/01/20 03:23:42 guenther Exp $ */ +/* $OpenBSD: proc.h,v 1.174 2014/01/20 21:19:27 guenther Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -156,6 +156,7 @@ struct process { struct proc *ps_mainproc; struct pcred *ps_cred; /* Process owner's identity. */ + LIST_ENTRY(process) ps_list; /* List of all processes. */ TAILQ_HEAD(,proc) ps_threads; /* Threads in this process. */ LIST_ENTRY(process) ps_pglist; /* List of processes in pgrp. */ @@ -238,16 +239,19 @@ struct process { #define PS_COREDUMP 0x00000800 /* Busy coredumping */ #define PS_SINGLEEXIT 0x00001000 /* Other threads must die. */ #define PS_SINGLEUNWIND 0x00002000 /* Other threads must unwind. */ +#define PS_NOZOMBIE 0x00004000 /* Pid 1 waits for me instead of dad */ +#define PS_STOPPED 0x00008000 /* Just stopped, need sig to parent. */ #define PS_BITS \ ("\20\01CONTROLT\02EXEC\03INEXEC\04EXITING\05SUGID" \ "\06SUGIDEXEC\07PPWAIT\010ISPWAIT\011PROFIL\012TRACED" \ - "\013WAITED\014COREDUMP\015SINGLEEXIT\016SINGLEUNWIND") + "\013WAITED\014COREDUMP\015SINGLEEXIT\016SINGLEUNWIND" \ + "\017NOZOMBIE\018STOPPED") struct proc { TAILQ_ENTRY(proc) p_runq; - LIST_ENTRY(proc) p_list; /* List of all processes. */ + LIST_ENTRY(proc) p_list; /* List of all threads. */ struct process *p_p; /* The process of this thread. */ TAILQ_ENTRY(proc) p_thr_link;/* Threads in a process linkage. */ @@ -370,21 +374,19 @@ struct proc { #define P_WEXIT 0x002000 /* Working on exiting. */ #define P_OWEUPC 0x008000 /* Owe proc an addupc() at next ast. */ #define P_SUSPSINGLE 0x080000 /* Need to stop for single threading. */ -#define P_NOZOMBIE 0x100000 /* Pid 1 waits for me instead of dad */ #define P_SYSTRACE 0x400000 /* Process system call tracing active*/ #define P_CONTINUED 0x800000 /* Proc has continued from a stopped state. */ #define P_THREAD 0x4000000 /* Only a thread, not a real process */ #define P_SUSPSIG 0x8000000 /* Stopped from signal. */ #define P_SOFTDEP 0x10000000 /* Stuck processing softdep worklist */ -#define P_STOPPED 0x20000000 /* Just stopped, need sig to parent. */ #define P_CPUPEG 0x40000000 /* Do not move to another cpu. */ #define P_BITS \ ("\20\01INKTR\02PROFPEND\03ALRMPEND\04SIGSUSPEND\07SELECT" \ "\010SINTR\012SYSTEM" \ "\013TIMEOUT\016WEXIT\020OWEUPC\024SUSPSINGLE" \ - "\025NOZOMBIE\027SYSTRACE\030CONTINUED\033THREAD" \ - "\034SUSPSIG\035SOFTDEP\036STOPPED\037CPUPEG") + "\027SYSTRACE\030CONTINUED\033THREAD" \ + "\034SUSPSIG\035SOFTDEP\037CPUPEG") /* Macro to compute the exit signal to be delivered. */ #define P_EXITSIG(p) \ @@ -467,8 +469,10 @@ extern int nthreads, maxthread; /* Cur and max number of threads. */ extern int randompid; /* fork() should create random pid's */ LIST_HEAD(proclist, proc); -extern struct proclist allproc; /* List of all processes. */ -extern struct proclist zombproc; /* List of zombie processes. */ +LIST_HEAD(processlist, process); +extern struct processlist allprocess; /* List of all processes. */ +extern struct processlist zombprocess; /* List of zombie processes. */ +extern struct proclist allproc; /* List of all threads. */ extern struct proc *initproc; /* Process slot for init. */ extern struct proc *reaperproc; /* Process slot for reaper. */ @@ -527,7 +531,8 @@ void child_return(void *); int proc_cansugid(struct proc *); void proc_finish_wait(struct proc *, struct proc *); -void proc_zap(struct proc *); +void process_zap(struct process *); +void proc_free(struct proc *); struct sleep_state { int sls_s; |