xref: /freebsd/sys/kern/kern_proc.c (revision b9f009b08da97f99c596289b146208c0d0dcb094)
1df8bae1dSRodney W. Grimes /*
2df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1989, 1991, 1993
3df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4df8bae1dSRodney W. Grimes  *
5df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
6df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
7df8bae1dSRodney W. Grimes  * are met:
8df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
9df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
10df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
11df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
12df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
13df8bae1dSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
14df8bae1dSRodney W. Grimes  *    must display the following acknowledgement:
15df8bae1dSRodney W. Grimes  *	This product includes software developed by the University of
16df8bae1dSRodney W. Grimes  *	California, Berkeley and its contributors.
17df8bae1dSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
18df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
19df8bae1dSRodney W. Grimes  *    without specific prior written permission.
20df8bae1dSRodney W. Grimes  *
21df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
32df8bae1dSRodney W. Grimes  *
33b75356e1SJeffrey Hsu  *	@(#)kern_proc.c	8.7 (Berkeley) 2/14/95
34c3aac50fSPeter Wemm  * $FreeBSD$
35df8bae1dSRodney W. Grimes  */
36df8bae1dSRodney W. Grimes 
376c84de02SJohn Baldwin #include "opt_ktrace.h"
38b9f009b0SPeter Wemm #include "opt_kstack_pages.h"
396c84de02SJohn Baldwin 
40df8bae1dSRodney W. Grimes #include <sys/param.h>
41df8bae1dSRodney W. Grimes #include <sys/systm.h>
42df8bae1dSRodney W. Grimes #include <sys/kernel.h>
43fb919e4dSMark Murray #include <sys/lock.h>
44df8bae1dSRodney W. Grimes #include <sys/malloc.h>
45fb919e4dSMark Murray #include <sys/mutex.h>
46b9df5231SPoul-Henning Kamp #include <sys/proc.h>
47079b7badSJulian Elischer #include <sys/sysproto.h>
48e602ba25SJulian Elischer #include <sys/kse.h>
49fb919e4dSMark Murray #include <sys/sysctl.h>
5062d6ce3aSDon Lewis #include <sys/filedesc.h>
51df8bae1dSRodney W. Grimes #include <sys/tty.h>
52bb56ec4aSPoul-Henning Kamp #include <sys/signalvar.h>
531005a129SJohn Baldwin #include <sys/sx.h>
54fb919e4dSMark Murray #include <sys/user.h>
55fb919e4dSMark Murray #include <sys/jail.h>
566c84de02SJohn Baldwin #ifdef KTRACE
576c84de02SJohn Baldwin #include <sys/uio.h>
586c84de02SJohn Baldwin #include <sys/ktrace.h>
596c84de02SJohn Baldwin #endif
60fb919e4dSMark Murray 
61efeaf95aSDavid Greenman #include <vm/vm.h>
62a136efe9SPeter Wemm #include <vm/vm_extern.h>
63efeaf95aSDavid Greenman #include <vm/pmap.h>
64efeaf95aSDavid Greenman #include <vm/vm_map.h>
65c897b813SJeff Roberson #include <vm/uma.h>
66182da820SMatthew Dillon #include <machine/critical.h>
67df8bae1dSRodney W. Grimes 
68f591779bSSeigo Tanimura MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
69a1c995b6SPoul-Henning Kamp MALLOC_DEFINE(M_SESSION, "session", "session header");
70876a94eeSBruce Evans static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
71a1c995b6SPoul-Henning Kamp MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
7255166637SPoul-Henning Kamp 
734d77a549SAlfred Perlstein static struct proc *dopfind(register pid_t);
74f591779bSSeigo Tanimura 
754d77a549SAlfred Perlstein static void doenterpgrp(struct proc *, struct pgrp *);
76f591779bSSeigo Tanimura 
774d77a549SAlfred Perlstein static void pgdelete(struct pgrp *);
7826f9a767SRodney W. Grimes 
794d77a549SAlfred Perlstein static void orphanpg(struct pgrp *pg);
8098d93822SBruce Evans 
81a136efe9SPeter Wemm static void proc_ctor(void *mem, int size, void *arg);
82a136efe9SPeter Wemm static void proc_dtor(void *mem, int size, void *arg);
83a136efe9SPeter Wemm static void proc_init(void *mem, int size);
84a136efe9SPeter Wemm static void proc_fini(void *mem, int size);
85a136efe9SPeter Wemm 
86df8bae1dSRodney W. Grimes /*
87b75356e1SJeffrey Hsu  * Other process lists
88b75356e1SJeffrey Hsu  */
89b75356e1SJeffrey Hsu struct pidhashhead *pidhashtbl;
90b75356e1SJeffrey Hsu u_long pidhash;
91b75356e1SJeffrey Hsu struct pgrphashhead *pgrphashtbl;
92b75356e1SJeffrey Hsu u_long pgrphash;
93b75356e1SJeffrey Hsu struct proclist allproc;
94b75356e1SJeffrey Hsu struct proclist zombproc;
951005a129SJohn Baldwin struct sx allproc_lock;
961005a129SJohn Baldwin struct sx proctree_lock;
978899023fSAlfred Perlstein struct mtx pargs_ref_lock;
98c897b813SJeff Roberson uma_zone_t proc_zone;
99c897b813SJeff Roberson uma_zone_t ithread_zone;
100b75356e1SJeffrey Hsu 
101a136efe9SPeter Wemm static int active_procs;
102a136efe9SPeter Wemm static int cached_procs;
103a136efe9SPeter Wemm static int allocated_procs;
104a136efe9SPeter Wemm 
105b9f009b0SPeter Wemm int kstack_pages = KSTACK_PAGES;
106b9f009b0SPeter Wemm int uarea_pages = UAREA_PAGES;
107b9f009b0SPeter Wemm SYSCTL_INT(_kern, OID_AUTO, kstack_pages, CTLFLAG_RD, &kstack_pages, 0, "");
108b9f009b0SPeter Wemm SYSCTL_INT(_kern, OID_AUTO, uarea_pages, CTLFLAG_RD, &uarea_pages, 0, "");
109b9f009b0SPeter Wemm 
110a136efe9SPeter Wemm #define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
111a136efe9SPeter Wemm 
112a30d7c60SJake Burkholder CTASSERT(sizeof(struct kinfo_proc) == KINFO_PROC_SIZE);
113a30d7c60SJake Burkholder 
114b75356e1SJeffrey Hsu /*
115b75356e1SJeffrey Hsu  * Initialize global process hashing structures.
116df8bae1dSRodney W. Grimes  */
11726f9a767SRodney W. Grimes void
118b75356e1SJeffrey Hsu procinit()
119df8bae1dSRodney W. Grimes {
120df8bae1dSRodney W. Grimes 
1211005a129SJohn Baldwin 	sx_init(&allproc_lock, "allproc");
1221005a129SJohn Baldwin 	sx_init(&proctree_lock, "proctree");
1236008862bSJohn Baldwin 	mtx_init(&pargs_ref_lock, "struct pargs.ref", NULL, MTX_DEF);
124b75356e1SJeffrey Hsu 	LIST_INIT(&allproc);
125b75356e1SJeffrey Hsu 	LIST_INIT(&zombproc);
126b75356e1SJeffrey Hsu 	pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
127b75356e1SJeffrey Hsu 	pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
128a136efe9SPeter Wemm 	proc_zone = uma_zcreate("PROC", sizeof (struct proc),
129a136efe9SPeter Wemm 	    proc_ctor, proc_dtor, proc_init, proc_fini,
130a136efe9SPeter Wemm 	    UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
131f535380cSDon Lewis 	uihashinit();
132df8bae1dSRodney W. Grimes }
133df8bae1dSRodney W. Grimes 
134df8bae1dSRodney W. Grimes /*
135a136efe9SPeter Wemm  * Prepare a proc for use.
136a136efe9SPeter Wemm  */
137a136efe9SPeter Wemm static void
138a136efe9SPeter Wemm proc_ctor(void *mem, int size, void *arg)
139a136efe9SPeter Wemm {
140a136efe9SPeter Wemm 	struct proc *p;
141a136efe9SPeter Wemm 
142a136efe9SPeter Wemm 	KASSERT((size == sizeof(struct proc)),
143a136efe9SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct proc)));
144a136efe9SPeter Wemm 	p = (struct proc *)mem;
145a136efe9SPeter Wemm 	cached_procs--;
146a136efe9SPeter Wemm 	active_procs++;
147a136efe9SPeter Wemm }
148a136efe9SPeter Wemm 
149a136efe9SPeter Wemm /*
150a136efe9SPeter Wemm  * Reclaim a proc after use.
151a136efe9SPeter Wemm  */
152a136efe9SPeter Wemm static void
153a136efe9SPeter Wemm proc_dtor(void *mem, int size, void *arg)
154a136efe9SPeter Wemm {
155a136efe9SPeter Wemm 	struct proc *p;
1561faf202eSJulian Elischer 	struct thread *td;
1571faf202eSJulian Elischer 	struct ksegrp *kg;
1581faf202eSJulian Elischer 	struct kse *ke;
159a136efe9SPeter Wemm 
1601faf202eSJulian Elischer 	/* INVARIANTS checks go here */
161a136efe9SPeter Wemm 	KASSERT((size == sizeof(struct proc)),
162a136efe9SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct proc)));
163a136efe9SPeter Wemm 	p = (struct proc *)mem;
1641faf202eSJulian Elischer 	KASSERT((p->p_numthreads == 1),
1651faf202eSJulian Elischer 	    ("bad number of threads in exiting process"));
1661faf202eSJulian Elischer         td = FIRST_THREAD_IN_PROC(p);
1671faf202eSJulian Elischer 	KASSERT((td != NULL), ("proc_dtor: bad thread pointer"));
1681faf202eSJulian Elischer         kg = FIRST_KSEGRP_IN_PROC(p);
1691faf202eSJulian Elischer 	KASSERT((kg != NULL), ("proc_dtor: bad kg pointer"));
1701faf202eSJulian Elischer         ke = FIRST_KSE_IN_KSEGRP(kg);
1711faf202eSJulian Elischer 	KASSERT((ke != NULL), ("proc_dtor: bad ke pointer"));
1721faf202eSJulian Elischer 	/*
1731faf202eSJulian Elischer 	 * We want to make sure we know the initial linkages.
1741faf202eSJulian Elischer 	 * so for now tear them down and remake them.
1756f22742bSRobert Watson 	 * This is probably un-needed as we can probably rely
1761faf202eSJulian Elischer 	 * on the state coming in here from wait4().
1771faf202eSJulian Elischer 	 */
1781faf202eSJulian Elischer 	proc_linkup(p, kg, ke, td);
1791faf202eSJulian Elischer 
1801faf202eSJulian Elischer 	/* Stats only */
181a136efe9SPeter Wemm 	active_procs--;
182a136efe9SPeter Wemm 	cached_procs++;
183a136efe9SPeter Wemm }
184a136efe9SPeter Wemm 
185a136efe9SPeter Wemm /*
186a136efe9SPeter Wemm  * Initialize type-stable parts of a proc (when newly created).
187a136efe9SPeter Wemm  */
188a136efe9SPeter Wemm static void
189a136efe9SPeter Wemm proc_init(void *mem, int size)
190a136efe9SPeter Wemm {
191a136efe9SPeter Wemm 	struct proc *p;
1921faf202eSJulian Elischer 	struct thread *td;
1931faf202eSJulian Elischer 	struct ksegrp *kg;
1941faf202eSJulian Elischer 	struct kse *ke;
195a136efe9SPeter Wemm 
196a136efe9SPeter Wemm 	KASSERT((size == sizeof(struct proc)),
197a136efe9SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct proc)));
198a136efe9SPeter Wemm 	p = (struct proc *)mem;
199a136efe9SPeter Wemm 	vm_proc_new(p);
2001faf202eSJulian Elischer 	td = thread_alloc();
2011faf202eSJulian Elischer 	ke = &p->p_kse;
2021faf202eSJulian Elischer 	kg = &p->p_ksegrp;
2031faf202eSJulian Elischer 	proc_linkup(p, kg, ke, td);
204a136efe9SPeter Wemm 	cached_procs++;
205a136efe9SPeter Wemm 	allocated_procs++;
206a136efe9SPeter Wemm }
207a136efe9SPeter Wemm 
208a136efe9SPeter Wemm /*
209a136efe9SPeter Wemm  * Tear down type-stable parts of a proc (just before being discarded)
210a136efe9SPeter Wemm  */
211a136efe9SPeter Wemm static void
212a136efe9SPeter Wemm proc_fini(void *mem, int size)
213a136efe9SPeter Wemm {
214a136efe9SPeter Wemm 	struct proc *p;
215a136efe9SPeter Wemm 
216a136efe9SPeter Wemm 	KASSERT((size == sizeof(struct proc)),
217a136efe9SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct proc)));
218a136efe9SPeter Wemm 	p = (struct proc *)mem;
219a136efe9SPeter Wemm 	vm_proc_dispose(p);
220a136efe9SPeter Wemm 	cached_procs--;
221a136efe9SPeter Wemm 	allocated_procs--;
2221faf202eSJulian Elischer 	thread_free(FIRST_THREAD_IN_PROC(p));
223a136efe9SPeter Wemm }
224a136efe9SPeter Wemm 
225a136efe9SPeter Wemm /*
226079b7badSJulian Elischer  * KSE is linked onto the idle queue.
227079b7badSJulian Elischer  */
228e602ba25SJulian Elischer void
229079b7badSJulian Elischer kse_link(struct kse *ke, struct ksegrp *kg)
230079b7badSJulian Elischer {
231079b7badSJulian Elischer 	struct proc *p = kg->kg_proc;
232079b7badSJulian Elischer 
233079b7badSJulian Elischer 	TAILQ_INSERT_HEAD(&kg->kg_kseq, ke, ke_kglist);
234079b7badSJulian Elischer 	kg->kg_kses++;
235e602ba25SJulian Elischer 	ke->ke_state = KES_IDLE;
236079b7badSJulian Elischer 	TAILQ_INSERT_HEAD(&kg->kg_iq, ke, ke_kgrlist);
237e602ba25SJulian Elischer 	kg->kg_idle_kses++;
238079b7badSJulian Elischer 	ke->ke_proc	= p;
239079b7badSJulian Elischer 	ke->ke_ksegrp	= kg;
240079b7badSJulian Elischer 	ke->ke_thread	= NULL;
241079b7badSJulian Elischer 	ke->ke_oncpu = NOCPU;
242079b7badSJulian Elischer }
243079b7badSJulian Elischer 
244e602ba25SJulian Elischer void
245079b7badSJulian Elischer ksegrp_link(struct ksegrp *kg, struct proc *p)
246079b7badSJulian Elischer {
2472b8a08afSPeter Wemm 
248079b7badSJulian Elischer 	TAILQ_INIT(&kg->kg_threads);
249079b7badSJulian Elischer 	TAILQ_INIT(&kg->kg_runq);	/* links with td_runq */
250079b7badSJulian Elischer 	TAILQ_INIT(&kg->kg_slpq);	/* links with td_runq */
251079b7badSJulian Elischer 	TAILQ_INIT(&kg->kg_kseq);	/* all kses in ksegrp */
252079b7badSJulian Elischer 	TAILQ_INIT(&kg->kg_iq);		/* all kses in ksegrp */
253079b7badSJulian Elischer 	kg->kg_proc	= p;
254079b7badSJulian Elischer /* the following counters are in the -zero- section and may not need clearing */
255e602ba25SJulian Elischer 	kg->kg_numthreads = 0;
256079b7badSJulian Elischer 	kg->kg_runnable = 0;
257079b7badSJulian Elischer 	kg->kg_kses = 0;
258e602ba25SJulian Elischer 	kg->kg_idle_kses = 0;
259079b7badSJulian Elischer 	kg->kg_runq_kses = 0; /* XXXKSE change name */
2602b239dd1SJens Schweikhardt /* link it in now that it's consistent */
261e602ba25SJulian Elischer 	p->p_numksegrps++;
262079b7badSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_ksegrps, kg, kg_ksegrp);
263079b7badSJulian Elischer }
264079b7badSJulian Elischer 
265079b7badSJulian Elischer /*
266079b7badSJulian Elischer  * for a newly created process,
267079b7badSJulian Elischer  * link up a the structure and its initial threads etc.
268b40ce416SJulian Elischer  */
269b40ce416SJulian Elischer void
270079b7badSJulian Elischer proc_linkup(struct proc *p, struct ksegrp *kg,
271079b7badSJulian Elischer 			struct kse *ke, struct thread *td)
272b40ce416SJulian Elischer {
2732b8a08afSPeter Wemm 
274b40ce416SJulian Elischer 	TAILQ_INIT(&p->p_ksegrps);	     /* all ksegrps in proc */
275b40ce416SJulian Elischer 	TAILQ_INIT(&p->p_threads);	     /* all threads in proc */
276e602ba25SJulian Elischer 	TAILQ_INIT(&p->p_suspended);	     /* Threads suspended */
2771faf202eSJulian Elischer 	p->p_numksegrps = 0;
2781faf202eSJulian Elischer 	p->p_numthreads = 0;
279b40ce416SJulian Elischer 
280079b7badSJulian Elischer 	ksegrp_link(kg, p);
281079b7badSJulian Elischer 	kse_link(ke, kg);
282079b7badSJulian Elischer 	thread_link(td, kg);
283079b7badSJulian Elischer }
284b40ce416SJulian Elischer 
285c28841c1SJulian Elischer int
286c28841c1SJulian Elischer thread_wakeup(struct thread *td, struct  thread_wakeup_args *uap)
287c28841c1SJulian Elischer {
288c28841c1SJulian Elischer 
289fd21c2b5SJulian Elischer 	return(ENOSYS);
290c28841c1SJulian Elischer }
291c28841c1SJulian Elischer 
292c28841c1SJulian Elischer int
293c28841c1SJulian Elischer kse_exit(struct thread *td, struct kse_exit_args *uap)
294c28841c1SJulian Elischer {
295c28841c1SJulian Elischer 
296fd21c2b5SJulian Elischer 	return(ENOSYS);
297c28841c1SJulian Elischer }
298c28841c1SJulian Elischer 
299c28841c1SJulian Elischer int
300c28841c1SJulian Elischer kse_yield(struct thread *td, struct kse_yield_args *uap)
301c28841c1SJulian Elischer {
302c28841c1SJulian Elischer 
303e602ba25SJulian Elischer 	PROC_LOCK(td->td_proc);
304e602ba25SJulian Elischer 	mtx_lock_spin(&sched_lock);
305e602ba25SJulian Elischer 	thread_exit();
306e602ba25SJulian Elischer 	/* NOTREACHED */
307e602ba25SJulian Elischer 	return(0);
308c28841c1SJulian Elischer }
309c28841c1SJulian Elischer 
310c28841c1SJulian Elischer int kse_wakeup(struct thread *td, struct kse_wakeup_args *uap)
311c28841c1SJulian Elischer {
312c28841c1SJulian Elischer 
313fd21c2b5SJulian Elischer 	return(ENOSYS);
314c28841c1SJulian Elischer }
315c28841c1SJulian Elischer 
316e602ba25SJulian Elischer /*
317e602ba25SJulian Elischer  * No new KSEG: first call: use current KSE, don't schedule an upcall
3182b239dd1SJens Schweikhardt  * All other situations, do allocate a new KSE and schedule an upcall on it.
319e602ba25SJulian Elischer  */
320c28841c1SJulian Elischer /* struct kse_new_args {
321c28841c1SJulian Elischer 	struct kse_mailbox *mbx;
322c28841c1SJulian Elischer 	int	new_grp_flag;
323c28841c1SJulian Elischer }; */
324e602ba25SJulian Elischer int
325e602ba25SJulian Elischer kse_new(struct thread *td, struct kse_new_args *uap)
326c28841c1SJulian Elischer {
327e602ba25SJulian Elischer 	struct kse *newkse;
328e602ba25SJulian Elischer 	struct proc *p;
329e602ba25SJulian Elischer 	struct kse_mailbox mbx;
330e602ba25SJulian Elischer 	int err;
331c28841c1SJulian Elischer 
332e602ba25SJulian Elischer 	p = td->td_proc;
333e602ba25SJulian Elischer 	if ((err = copyin(uap->mbx, &mbx, sizeof(mbx))))
334e602ba25SJulian Elischer 		return (err);
335e602ba25SJulian Elischer 	PROC_LOCK(p);
336e602ba25SJulian Elischer 	/*
337e602ba25SJulian Elischer 	 * If we have no KSE mode set, just set it, and skip KSE and KSEGRP
338e602ba25SJulian Elischer 	 * creation.  You cannot request a new group with the first one as
339e602ba25SJulian Elischer 	 * you are effectively getting one. Instead, go directly to saving
340e602ba25SJulian Elischer 	 * the upcall info.
341e602ba25SJulian Elischer 	 */
342e602ba25SJulian Elischer 	if ((td->td_proc->p_flag & P_KSES) || (uap->new_grp_flag)) {
343e602ba25SJulian Elischer 
344e602ba25SJulian Elischer 		return (EINVAL);	/* XXX */
345e602ba25SJulian Elischer 		/*
346e602ba25SJulian Elischer 		 * If newgroup then create the new group.
347e602ba25SJulian Elischer 		 * Check we have the resources for this.
348e602ba25SJulian Elischer 		 */
349e602ba25SJulian Elischer 		/* Copy lots of fields from the current KSEGRP.  */
350e602ba25SJulian Elischer 		/* Create the new KSE */
351e602ba25SJulian Elischer 		/* Copy lots of fields from the current KSE.  */
352e602ba25SJulian Elischer 	} else {
353e602ba25SJulian Elischer 		/*
354e602ba25SJulian Elischer 		 * We are switching to KSEs so just
355e602ba25SJulian Elischer 		 * use the preallocated ones for this call.
356e602ba25SJulian Elischer 		 * XXXKSE if we have to initialise any fields for KSE
357e602ba25SJulian Elischer 		 * mode operation, do it here.
358e602ba25SJulian Elischer 		 */
359e602ba25SJulian Elischer 		newkse = td->td_kse;
360e602ba25SJulian Elischer 	}
361e602ba25SJulian Elischer 	/*
362e602ba25SJulian Elischer 	 * Fill out the KSE-mode specific fields of the new kse.
363e602ba25SJulian Elischer 	 */
364e602ba25SJulian Elischer 	PROC_UNLOCK(p);
365e602ba25SJulian Elischer 	mtx_lock_spin(&sched_lock);
366e602ba25SJulian Elischer 	mi_switch();	/* Save current registers to PCB. */
367e602ba25SJulian Elischer 	mtx_unlock_spin(&sched_lock);
368e602ba25SJulian Elischer 	newkse->ke_upcall = mbx.kmbx_upcall;
369e602ba25SJulian Elischer 	newkse->ke_stackbase  = mbx.kmbx_stackbase;
370e602ba25SJulian Elischer 	newkse->ke_stacksize = mbx.kmbx_stacksize;
371e602ba25SJulian Elischer 	newkse->ke_mailbox = uap->mbx;
372e602ba25SJulian Elischer 	cpu_save_upcall(td, newkse);
373e602ba25SJulian Elischer 	/* Note that we are the returning syscall */
374e602ba25SJulian Elischer 	td->td_retval[0] = 0;
375e602ba25SJulian Elischer 	td->td_retval[1] = 0;
376e602ba25SJulian Elischer 
377e602ba25SJulian Elischer 	if ((td->td_proc->p_flag & P_KSES) || (uap->new_grp_flag)) {
378e602ba25SJulian Elischer 		thread_schedule_upcall(td, newkse);
379e602ba25SJulian Elischer 	} else {
380e602ba25SJulian Elischer 		/*
3812b239dd1SJens Schweikhardt 		 * Don't set this until we are truly ready, because
382e602ba25SJulian Elischer 		 * things will start acting differently.  Return to the
383e602ba25SJulian Elischer 		 * calling code for the first time.  Assuming we set up
384e602ba25SJulian Elischer 		 * the mailboxes right, all syscalls after this will be
385e602ba25SJulian Elischer 		 * asynchronous.
386e602ba25SJulian Elischer 		 */
387e602ba25SJulian Elischer 		td->td_proc->p_flag |= P_KSES;
388e602ba25SJulian Elischer 	}
389e602ba25SJulian Elischer 	return (0);
390c28841c1SJulian Elischer }
391c28841c1SJulian Elischer 
392b40ce416SJulian Elischer /*
393df8bae1dSRodney W. Grimes  * Is p an inferior of the current process?
394df8bae1dSRodney W. Grimes  */
3951a432a2fSDima Ruban int
396df8bae1dSRodney W. Grimes inferior(p)
397df8bae1dSRodney W. Grimes 	register struct proc *p;
398df8bae1dSRodney W. Grimes {
399df8bae1dSRodney W. Grimes 
4005b29d6e9SJohn Baldwin 	sx_assert(&proctree_lock, SX_LOCKED);
4015b29d6e9SJohn Baldwin 	for (; p != curproc; p = p->p_pptr)
40200f13cb3SJohn Baldwin 		if (p->p_pid == 0)
40300f13cb3SJohn Baldwin 			return (0);
40400f13cb3SJohn Baldwin 	return (1);
405df8bae1dSRodney W. Grimes }
406df8bae1dSRodney W. Grimes 
407df8bae1dSRodney W. Grimes /*
408df8bae1dSRodney W. Grimes  * Locate a process by number
409df8bae1dSRodney W. Grimes  */
410df8bae1dSRodney W. Grimes struct proc *
411df8bae1dSRodney W. Grimes pfind(pid)
412df8bae1dSRodney W. Grimes 	register pid_t pid;
413df8bae1dSRodney W. Grimes {
414df8bae1dSRodney W. Grimes 	register struct proc *p;
415df8bae1dSRodney W. Grimes 
4161005a129SJohn Baldwin 	sx_slock(&allproc_lock);
417f591779bSSeigo Tanimura 	p = dopfind(pid);
418f591779bSSeigo Tanimura 	sx_sunlock(&allproc_lock);
419f591779bSSeigo Tanimura 	return (p);
420f591779bSSeigo Tanimura }
421f591779bSSeigo Tanimura 
422f591779bSSeigo Tanimura static struct proc *
423f591779bSSeigo Tanimura dopfind(pid)
424f591779bSSeigo Tanimura 	register pid_t pid;
425f591779bSSeigo Tanimura {
426f591779bSSeigo Tanimura 	register struct proc *p;
427f591779bSSeigo Tanimura 
428f591779bSSeigo Tanimura 	sx_assert(&allproc_lock, SX_LOCKED);
429f591779bSSeigo Tanimura 
4301b727751SPoul-Henning Kamp 	LIST_FOREACH(p, PIDHASH(pid), p_hash)
43133a9ed9dSJohn Baldwin 		if (p->p_pid == pid) {
43233a9ed9dSJohn Baldwin 			PROC_LOCK(p);
433553629ebSJake Burkholder 			break;
43433a9ed9dSJohn Baldwin 		}
435df8bae1dSRodney W. Grimes 	return (p);
436df8bae1dSRodney W. Grimes }
437df8bae1dSRodney W. Grimes 
438df8bae1dSRodney W. Grimes /*
439f591779bSSeigo Tanimura  * Locate a process group by number.
440f089b570SJohn Baldwin  * The caller must hold proctree_lock.
441df8bae1dSRodney W. Grimes  */
442df8bae1dSRodney W. Grimes struct pgrp *
443df8bae1dSRodney W. Grimes pgfind(pgid)
444df8bae1dSRodney W. Grimes 	register pid_t pgid;
445df8bae1dSRodney W. Grimes {
446df8bae1dSRodney W. Grimes 	register struct pgrp *pgrp;
447df8bae1dSRodney W. Grimes 
448f089b570SJohn Baldwin 	sx_assert(&proctree_lock, SX_LOCKED);
449f591779bSSeigo Tanimura 
450f591779bSSeigo Tanimura 	LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) {
451f591779bSSeigo Tanimura 		if (pgrp->pg_id == pgid) {
452f591779bSSeigo Tanimura 			PGRP_LOCK(pgrp);
453df8bae1dSRodney W. Grimes 			return (pgrp);
454f591779bSSeigo Tanimura 		}
455f591779bSSeigo Tanimura 	}
456df8bae1dSRodney W. Grimes 	return (NULL);
457df8bae1dSRodney W. Grimes }
458df8bae1dSRodney W. Grimes 
459df8bae1dSRodney W. Grimes /*
460f591779bSSeigo Tanimura  * Create a new process group.
461f591779bSSeigo Tanimura  * pgid must be equal to the pid of p.
462f591779bSSeigo Tanimura  * Begin a new session if required.
463df8bae1dSRodney W. Grimes  */
46426f9a767SRodney W. Grimes int
465f591779bSSeigo Tanimura enterpgrp(p, pgid, pgrp, sess)
466df8bae1dSRodney W. Grimes 	register struct proc *p;
467df8bae1dSRodney W. Grimes 	pid_t pgid;
468f591779bSSeigo Tanimura 	struct pgrp *pgrp;
469f591779bSSeigo Tanimura 	struct session *sess;
470df8bae1dSRodney W. Grimes {
471f591779bSSeigo Tanimura 	struct pgrp *pgrp2;
472df8bae1dSRodney W. Grimes 
473f089b570SJohn Baldwin 	sx_assert(&proctree_lock, SX_XLOCKED);
474f591779bSSeigo Tanimura 
475f591779bSSeigo Tanimura 	KASSERT(pgrp != NULL, ("enterpgrp: pgrp == NULL"));
476f591779bSSeigo Tanimura 	KASSERT(p->p_pid == pgid,
477f591779bSSeigo Tanimura 	    ("enterpgrp: new pgrp and pid != pgid"));
478f591779bSSeigo Tanimura 
479f591779bSSeigo Tanimura 	pgrp2 = pgfind(pgid);
480f591779bSSeigo Tanimura 
481f591779bSSeigo Tanimura 	KASSERT(pgrp2 == NULL,
482f591779bSSeigo Tanimura 	    ("enterpgrp: pgrp with pgid exists"));
4835526d2d9SEivind Eklund 	KASSERT(!SESS_LEADER(p),
4845526d2d9SEivind Eklund 	    ("enterpgrp: session leader attempted setpgrp"));
485219cbf59SEivind Eklund 
4866008862bSJohn Baldwin 	mtx_init(&pgrp->pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK);
487df8bae1dSRodney W. Grimes 
488f591779bSSeigo Tanimura 	if (sess != NULL) {
489df8bae1dSRodney W. Grimes 		/*
490df8bae1dSRodney W. Grimes 		 * new session
491df8bae1dSRodney W. Grimes 		 */
4926008862bSJohn Baldwin 		mtx_init(&sess->s_mtx, "session", NULL, MTX_DEF);
493f591779bSSeigo Tanimura 		PROC_LOCK(p);
494f591779bSSeigo Tanimura 		p->p_flag &= ~P_CONTROLT;
495f591779bSSeigo Tanimura 		PROC_UNLOCK(p);
496f591779bSSeigo Tanimura 		PGRP_LOCK(pgrp);
497df8bae1dSRodney W. Grimes 		sess->s_leader = p;
498643a8daaSDon Lewis 		sess->s_sid = p->p_pid;
499df8bae1dSRodney W. Grimes 		sess->s_count = 1;
500df8bae1dSRodney W. Grimes 		sess->s_ttyvp = NULL;
501df8bae1dSRodney W. Grimes 		sess->s_ttyp = NULL;
502df8bae1dSRodney W. Grimes 		bcopy(p->p_session->s_login, sess->s_login,
503df8bae1dSRodney W. Grimes 			    sizeof(sess->s_login));
504df8bae1dSRodney W. Grimes 		pgrp->pg_session = sess;
5055526d2d9SEivind Eklund 		KASSERT(p == curproc,
5065526d2d9SEivind Eklund 		    ("enterpgrp: mksession and p != curproc"));
507df8bae1dSRodney W. Grimes 	} else {
508df8bae1dSRodney W. Grimes 		pgrp->pg_session = p->p_session;
509f591779bSSeigo Tanimura 		SESS_LOCK(pgrp->pg_session);
510df8bae1dSRodney W. Grimes 		pgrp->pg_session->s_count++;
511f591779bSSeigo Tanimura 		SESS_UNLOCK(pgrp->pg_session);
512f591779bSSeigo Tanimura 		PGRP_LOCK(pgrp);
513df8bae1dSRodney W. Grimes 	}
514df8bae1dSRodney W. Grimes 	pgrp->pg_id = pgid;
515b75356e1SJeffrey Hsu 	LIST_INIT(&pgrp->pg_members);
516f591779bSSeigo Tanimura 
517f591779bSSeigo Tanimura 	/*
518f089b570SJohn Baldwin 	 * As we have an exclusive lock of proctree_lock,
519f591779bSSeigo Tanimura 	 * this should not deadlock.
520f591779bSSeigo Tanimura 	 */
521b75356e1SJeffrey Hsu 	LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
522df8bae1dSRodney W. Grimes 	pgrp->pg_jobc = 0;
523831d27a9SDon Lewis 	SLIST_INIT(&pgrp->pg_sigiolst);
524f591779bSSeigo Tanimura 	PGRP_UNLOCK(pgrp);
525f591779bSSeigo Tanimura 
526f591779bSSeigo Tanimura 	doenterpgrp(p, pgrp);
527f591779bSSeigo Tanimura 
528df8bae1dSRodney W. Grimes 	return (0);
529f591779bSSeigo Tanimura }
530f591779bSSeigo Tanimura 
531f591779bSSeigo Tanimura /*
532f591779bSSeigo Tanimura  * Move p to an existing process group
533f591779bSSeigo Tanimura  */
534f591779bSSeigo Tanimura int
535f591779bSSeigo Tanimura enterthispgrp(p, pgrp)
536f591779bSSeigo Tanimura 	register struct proc *p;
537f591779bSSeigo Tanimura 	struct pgrp *pgrp;
538f591779bSSeigo Tanimura {
539f089b570SJohn Baldwin 
540f089b570SJohn Baldwin 	sx_assert(&proctree_lock, SX_XLOCKED);
541f591779bSSeigo Tanimura 	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
542f591779bSSeigo Tanimura 	PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
543f591779bSSeigo Tanimura 	PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED);
544f591779bSSeigo Tanimura 	SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
545f591779bSSeigo Tanimura 	KASSERT(pgrp->pg_session == p->p_session,
546f591779bSSeigo Tanimura 		("%s: pgrp's session %p, p->p_session %p.\n",
547f591779bSSeigo Tanimura 		__func__,
548f591779bSSeigo Tanimura 		pgrp->pg_session,
549f591779bSSeigo Tanimura 		p->p_session));
550f591779bSSeigo Tanimura 	KASSERT(pgrp != p->p_pgrp,
551f591779bSSeigo Tanimura 		("%s: p belongs to pgrp.", __func__));
552f591779bSSeigo Tanimura 
553f591779bSSeigo Tanimura 	doenterpgrp(p, pgrp);
554f591779bSSeigo Tanimura 
555f591779bSSeigo Tanimura 	return (0);
556f591779bSSeigo Tanimura }
557f591779bSSeigo Tanimura 
558f591779bSSeigo Tanimura /*
559f591779bSSeigo Tanimura  * Move p to a process group
560f591779bSSeigo Tanimura  */
561f591779bSSeigo Tanimura static void
562f591779bSSeigo Tanimura doenterpgrp(p, pgrp)
563f591779bSSeigo Tanimura 	struct proc *p;
564f591779bSSeigo Tanimura 	struct pgrp *pgrp;
565f591779bSSeigo Tanimura {
566f591779bSSeigo Tanimura 	struct pgrp *savepgrp;
567f591779bSSeigo Tanimura 
568f089b570SJohn Baldwin 	sx_assert(&proctree_lock, SX_XLOCKED);
569f591779bSSeigo Tanimura 	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
570f591779bSSeigo Tanimura 	PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
571f591779bSSeigo Tanimura 	PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED);
572f591779bSSeigo Tanimura 	SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
573f591779bSSeigo Tanimura 
574f591779bSSeigo Tanimura 	savepgrp = p->p_pgrp;
575df8bae1dSRodney W. Grimes 
576df8bae1dSRodney W. Grimes 	/*
577df8bae1dSRodney W. Grimes 	 * Adjust eligibility of affected pgrps to participate in job control.
578df8bae1dSRodney W. Grimes 	 * Increment eligibility counts before decrementing, otherwise we
579df8bae1dSRodney W. Grimes 	 * could reach 0 spuriously during the first call.
580df8bae1dSRodney W. Grimes 	 */
581df8bae1dSRodney W. Grimes 	fixjobc(p, pgrp, 1);
582df8bae1dSRodney W. Grimes 	fixjobc(p, p->p_pgrp, 0);
583df8bae1dSRodney W. Grimes 
584f591779bSSeigo Tanimura 	PGRP_LOCK(pgrp);
585f591779bSSeigo Tanimura 	PGRP_LOCK(savepgrp);
58615e9ec51SJohn Baldwin 	PROC_LOCK(p);
587b75356e1SJeffrey Hsu 	LIST_REMOVE(p, p_pglist);
588df8bae1dSRodney W. Grimes 	p->p_pgrp = pgrp;
58915e9ec51SJohn Baldwin 	PROC_UNLOCK(p);
590f591779bSSeigo Tanimura 	LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
591f591779bSSeigo Tanimura 	PGRP_UNLOCK(savepgrp);
592f591779bSSeigo Tanimura 	PGRP_UNLOCK(pgrp);
593f591779bSSeigo Tanimura 	if (LIST_EMPTY(&savepgrp->pg_members))
594f591779bSSeigo Tanimura 		pgdelete(savepgrp);
595df8bae1dSRodney W. Grimes }
596df8bae1dSRodney W. Grimes 
597df8bae1dSRodney W. Grimes /*
598df8bae1dSRodney W. Grimes  * remove process from process group
599df8bae1dSRodney W. Grimes  */
60026f9a767SRodney W. Grimes int
601df8bae1dSRodney W. Grimes leavepgrp(p)
602df8bae1dSRodney W. Grimes 	register struct proc *p;
603df8bae1dSRodney W. Grimes {
604f591779bSSeigo Tanimura 	struct pgrp *savepgrp;
605df8bae1dSRodney W. Grimes 
606f089b570SJohn Baldwin 	sx_assert(&proctree_lock, SX_XLOCKED);
607f591779bSSeigo Tanimura 	savepgrp = p->p_pgrp;
608f591779bSSeigo Tanimura 	PGRP_LOCK(savepgrp);
60915e9ec51SJohn Baldwin 	PROC_LOCK(p);
610b75356e1SJeffrey Hsu 	LIST_REMOVE(p, p_pglist);
61115e9ec51SJohn Baldwin 	p->p_pgrp = NULL;
61215e9ec51SJohn Baldwin 	PROC_UNLOCK(p);
613f591779bSSeigo Tanimura 	PGRP_UNLOCK(savepgrp);
614f591779bSSeigo Tanimura 	if (LIST_EMPTY(&savepgrp->pg_members))
615f591779bSSeigo Tanimura 		pgdelete(savepgrp);
616df8bae1dSRodney W. Grimes 	return (0);
617df8bae1dSRodney W. Grimes }
618df8bae1dSRodney W. Grimes 
619df8bae1dSRodney W. Grimes /*
620df8bae1dSRodney W. Grimes  * delete a process group
621df8bae1dSRodney W. Grimes  */
62287b6de2bSPoul-Henning Kamp static void
623df8bae1dSRodney W. Grimes pgdelete(pgrp)
624df8bae1dSRodney W. Grimes 	register struct pgrp *pgrp;
625df8bae1dSRodney W. Grimes {
626f591779bSSeigo Tanimura 	struct session *savesess;
627f591779bSSeigo Tanimura 
628f089b570SJohn Baldwin 	sx_assert(&proctree_lock, SX_XLOCKED);
629f591779bSSeigo Tanimura 	PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
630f591779bSSeigo Tanimura 	SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
631f591779bSSeigo Tanimura 
632831d27a9SDon Lewis 	/*
633831d27a9SDon Lewis 	 * Reset any sigio structures pointing to us as a result of
634831d27a9SDon Lewis 	 * F_SETOWN with our pgid.
635831d27a9SDon Lewis 	 */
636831d27a9SDon Lewis 	funsetownlst(&pgrp->pg_sigiolst);
637831d27a9SDon Lewis 
638e649887bSAlfred Perlstein 	PGRP_LOCK(pgrp);
639df8bae1dSRodney W. Grimes 	if (pgrp->pg_session->s_ttyp != NULL &&
640df8bae1dSRodney W. Grimes 	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
641df8bae1dSRodney W. Grimes 		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
642b75356e1SJeffrey Hsu 	LIST_REMOVE(pgrp, pg_hash);
643f591779bSSeigo Tanimura 	savesess = pgrp->pg_session;
644f591779bSSeigo Tanimura 	SESS_LOCK(savesess);
645f591779bSSeigo Tanimura 	savesess->s_count--;
646f591779bSSeigo Tanimura 	SESS_UNLOCK(savesess);
647f591779bSSeigo Tanimura 	PGRP_UNLOCK(pgrp);
648f591779bSSeigo Tanimura 	if (savesess->s_count == 0) {
649f591779bSSeigo Tanimura 		mtx_destroy(&savesess->s_mtx);
650df8bae1dSRodney W. Grimes 		FREE(pgrp->pg_session, M_SESSION);
651f591779bSSeigo Tanimura 	}
6526041fa0aSSeigo Tanimura 	mtx_destroy(&pgrp->pg_mtx);
653df8bae1dSRodney W. Grimes 	FREE(pgrp, M_PGRP);
654df8bae1dSRodney W. Grimes }
655df8bae1dSRodney W. Grimes 
656df8bae1dSRodney W. Grimes /*
657df8bae1dSRodney W. Grimes  * Adjust pgrp jobc counters when specified process changes process group.
658df8bae1dSRodney W. Grimes  * We count the number of processes in each process group that "qualify"
659df8bae1dSRodney W. Grimes  * the group for terminal job control (those with a parent in a different
660df8bae1dSRodney W. Grimes  * process group of the same session).  If that count reaches zero, the
661df8bae1dSRodney W. Grimes  * process group becomes orphaned.  Check both the specified process'
662df8bae1dSRodney W. Grimes  * process group and that of its children.
663df8bae1dSRodney W. Grimes  * entering == 0 => p is leaving specified group.
664df8bae1dSRodney W. Grimes  * entering == 1 => p is entering specified group.
665df8bae1dSRodney W. Grimes  */
66626f9a767SRodney W. Grimes void
667df8bae1dSRodney W. Grimes fixjobc(p, pgrp, entering)
668df8bae1dSRodney W. Grimes 	register struct proc *p;
669df8bae1dSRodney W. Grimes 	register struct pgrp *pgrp;
670df8bae1dSRodney W. Grimes 	int entering;
671df8bae1dSRodney W. Grimes {
672df8bae1dSRodney W. Grimes 	register struct pgrp *hispgrp;
673f591779bSSeigo Tanimura 	register struct session *mysession;
674f591779bSSeigo Tanimura 
675f089b570SJohn Baldwin 	sx_assert(&proctree_lock, SX_LOCKED);
676f591779bSSeigo Tanimura 	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
677f591779bSSeigo Tanimura 	PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
678f591779bSSeigo Tanimura 	SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
679df8bae1dSRodney W. Grimes 
680df8bae1dSRodney W. Grimes 	/*
681df8bae1dSRodney W. Grimes 	 * Check p's parent to see whether p qualifies its own process
682df8bae1dSRodney W. Grimes 	 * group; if so, adjust count for p's process group.
683df8bae1dSRodney W. Grimes 	 */
684f591779bSSeigo Tanimura 	mysession = pgrp->pg_session;
685df8bae1dSRodney W. Grimes 	if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
686dfd5dee1SPeter Wemm 	    hispgrp->pg_session == mysession) {
687f591779bSSeigo Tanimura 		PGRP_LOCK(pgrp);
688df8bae1dSRodney W. Grimes 		if (entering)
689df8bae1dSRodney W. Grimes 			pgrp->pg_jobc++;
690f591779bSSeigo Tanimura 		else {
691f591779bSSeigo Tanimura 			--pgrp->pg_jobc;
692f591779bSSeigo Tanimura 			if (pgrp->pg_jobc == 0)
693df8bae1dSRodney W. Grimes 				orphanpg(pgrp);
694dfd5dee1SPeter Wemm 		}
695f591779bSSeigo Tanimura 		PGRP_UNLOCK(pgrp);
696f591779bSSeigo Tanimura 	}
697df8bae1dSRodney W. Grimes 
698df8bae1dSRodney W. Grimes 	/*
699df8bae1dSRodney W. Grimes 	 * Check this process' children to see whether they qualify
700df8bae1dSRodney W. Grimes 	 * their process groups; if so, adjust counts for children's
701df8bae1dSRodney W. Grimes 	 * process groups.
702df8bae1dSRodney W. Grimes 	 */
703f591779bSSeigo Tanimura 	LIST_FOREACH(p, &p->p_children, p_sibling) {
704df8bae1dSRodney W. Grimes 		if ((hispgrp = p->p_pgrp) != pgrp &&
705df8bae1dSRodney W. Grimes 		    hispgrp->pg_session == mysession &&
706e602ba25SJulian Elischer 		    p->p_state != PRS_ZOMBIE) {
707f591779bSSeigo Tanimura 			PGRP_LOCK(hispgrp);
708df8bae1dSRodney W. Grimes 			if (entering)
709df8bae1dSRodney W. Grimes 				hispgrp->pg_jobc++;
710f591779bSSeigo Tanimura 			else {
711f591779bSSeigo Tanimura 				--hispgrp->pg_jobc;
712f591779bSSeigo Tanimura 				if (hispgrp->pg_jobc == 0)
713df8bae1dSRodney W. Grimes 					orphanpg(hispgrp);
714df8bae1dSRodney W. Grimes 			}
715f591779bSSeigo Tanimura 			PGRP_UNLOCK(hispgrp);
716f591779bSSeigo Tanimura 		}
717f591779bSSeigo Tanimura 	}
718dfd5dee1SPeter Wemm }
719df8bae1dSRodney W. Grimes 
720df8bae1dSRodney W. Grimes /*
721df8bae1dSRodney W. Grimes  * A process group has become orphaned;
722df8bae1dSRodney W. Grimes  * if there are any stopped processes in the group,
723df8bae1dSRodney W. Grimes  * hang-up all process in that group.
724df8bae1dSRodney W. Grimes  */
725df8bae1dSRodney W. Grimes static void
726df8bae1dSRodney W. Grimes orphanpg(pg)
727df8bae1dSRodney W. Grimes 	struct pgrp *pg;
728df8bae1dSRodney W. Grimes {
729df8bae1dSRodney W. Grimes 	register struct proc *p;
730df8bae1dSRodney W. Grimes 
731f591779bSSeigo Tanimura 	PGRP_LOCK_ASSERT(pg, MA_OWNED);
732f591779bSSeigo Tanimura 
73315e9ec51SJohn Baldwin 	mtx_lock_spin(&sched_lock);
7341b727751SPoul-Henning Kamp 	LIST_FOREACH(p, &pg->pg_members, p_pglist) {
735e602ba25SJulian Elischer 		if (P_SHOULDSTOP(p)) {
73615e9ec51SJohn Baldwin 			mtx_unlock_spin(&sched_lock);
7371b727751SPoul-Henning Kamp 			LIST_FOREACH(p, &pg->pg_members, p_pglist) {
73815e9ec51SJohn Baldwin 				PROC_LOCK(p);
739df8bae1dSRodney W. Grimes 				psignal(p, SIGHUP);
740df8bae1dSRodney W. Grimes 				psignal(p, SIGCONT);
74115e9ec51SJohn Baldwin 				PROC_UNLOCK(p);
742df8bae1dSRodney W. Grimes 			}
743df8bae1dSRodney W. Grimes 			return;
744df8bae1dSRodney W. Grimes 		}
745df8bae1dSRodney W. Grimes 	}
74615e9ec51SJohn Baldwin 	mtx_unlock_spin(&sched_lock);
747df8bae1dSRodney W. Grimes }
748df8bae1dSRodney W. Grimes 
749831031ceSBruce Evans #include "opt_ddb.h"
750831031ceSBruce Evans #ifdef DDB
751831031ceSBruce Evans #include <ddb/ddb.h>
752831031ceSBruce Evans 
753831031ceSBruce Evans DB_SHOW_COMMAND(pgrpdump, pgrpdump)
754df8bae1dSRodney W. Grimes {
755df8bae1dSRodney W. Grimes 	register struct pgrp *pgrp;
756df8bae1dSRodney W. Grimes 	register struct proc *p;
757876a94eeSBruce Evans 	register int i;
758df8bae1dSRodney W. Grimes 
759b75356e1SJeffrey Hsu 	for (i = 0; i <= pgrphash; i++) {
7601b727751SPoul-Henning Kamp 		if (!LIST_EMPTY(&pgrphashtbl[i])) {
761df8bae1dSRodney W. Grimes 			printf("\tindx %d\n", i);
7621b727751SPoul-Henning Kamp 			LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) {
763ac1e407bSBruce Evans 				printf(
764ac1e407bSBruce Evans 			"\tpgrp %p, pgid %ld, sess %p, sesscnt %d, mem %p\n",
765ac1e407bSBruce Evans 				    (void *)pgrp, (long)pgrp->pg_id,
766ac1e407bSBruce Evans 				    (void *)pgrp->pg_session,
767b75356e1SJeffrey Hsu 				    pgrp->pg_session->s_count,
7681b727751SPoul-Henning Kamp 				    (void *)LIST_FIRST(&pgrp->pg_members));
7691b727751SPoul-Henning Kamp 				LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
770ac1e407bSBruce Evans 					printf("\t\tpid %ld addr %p pgrp %p\n",
771ac1e407bSBruce Evans 					    (long)p->p_pid, (void *)p,
772ac1e407bSBruce Evans 					    (void *)p->p_pgrp);
773df8bae1dSRodney W. Grimes 				}
774df8bae1dSRodney W. Grimes 			}
775df8bae1dSRodney W. Grimes 		}
776df8bae1dSRodney W. Grimes 	}
777df8bae1dSRodney W. Grimes }
778831031ceSBruce Evans #endif /* DDB */
779972f9b20SPoul-Henning Kamp 
780972f9b20SPoul-Henning Kamp /*
7811f7d2501SKirk McKusick  * Fill in an kinfo_proc structure for the specified process.
78265c9b430SJohn Baldwin  * Must be called with the target process locked.
783972f9b20SPoul-Henning Kamp  */
784972f9b20SPoul-Henning Kamp void
7851f7d2501SKirk McKusick fill_kinfo_proc(p, kp)
7861f7d2501SKirk McKusick 	struct proc *p;
7871f7d2501SKirk McKusick 	struct kinfo_proc *kp;
788972f9b20SPoul-Henning Kamp {
789b40ce416SJulian Elischer 	struct thread *td;
7901f7d2501SKirk McKusick 	struct tty *tp;
7911f7d2501SKirk McKusick 	struct session *sp;
7921cbb9c3bSPoul-Henning Kamp 	struct timeval tv;
793972f9b20SPoul-Henning Kamp 
7941f7d2501SKirk McKusick 	bzero(kp, sizeof(*kp));
795972f9b20SPoul-Henning Kamp 
7961f7d2501SKirk McKusick 	kp->ki_structsize = sizeof(*kp);
7971f7d2501SKirk McKusick 	kp->ki_paddr = p;
79865c9b430SJohn Baldwin 	PROC_LOCK_ASSERT(p, MA_OWNED);
799b40ce416SJulian Elischer 	kp->ki_addr =/* p->p_addr; */0; /* XXXKSE */
8001f7d2501SKirk McKusick 	kp->ki_args = p->p_args;
8011f7d2501SKirk McKusick 	kp->ki_textvp = p->p_textvp;
8026c84de02SJohn Baldwin #ifdef KTRACE
8036c84de02SJohn Baldwin 	kp->ki_tracep = p->p_tracep;
8046c84de02SJohn Baldwin 	mtx_lock(&ktrace_mtx);
8056c84de02SJohn Baldwin 	kp->ki_traceflag = p->p_traceflag;
8066c84de02SJohn Baldwin 	mtx_unlock(&ktrace_mtx);
8076c84de02SJohn Baldwin #endif
8081f7d2501SKirk McKusick 	kp->ki_fd = p->p_fd;
8091f7d2501SKirk McKusick 	kp->ki_vmspace = p->p_vmspace;
810b1fc0ec1SRobert Watson 	if (p->p_ucred) {
811b1fc0ec1SRobert Watson 		kp->ki_uid = p->p_ucred->cr_uid;
812b1fc0ec1SRobert Watson 		kp->ki_ruid = p->p_ucred->cr_ruid;
813b1fc0ec1SRobert Watson 		kp->ki_svuid = p->p_ucred->cr_svuid;
8140ecd57adSPeter Wemm 		/* XXX bde doesn't like KI_NGROUPS */
8150ecd57adSPeter Wemm 		kp->ki_ngroups = min(p->p_ucred->cr_ngroups, KI_NGROUPS);
816b1fc0ec1SRobert Watson 		bcopy(p->p_ucred->cr_groups, kp->ki_groups,
8170ecd57adSPeter Wemm 		    kp->ki_ngroups * sizeof(gid_t));
818b1fc0ec1SRobert Watson 		kp->ki_rgid = p->p_ucred->cr_rgid;
819b1fc0ec1SRobert Watson 		kp->ki_svgid = p->p_ucred->cr_svgid;
820972f9b20SPoul-Henning Kamp 	}
821d8c85307SJulian Elischer 	if (p->p_procsig) {
8221f7d2501SKirk McKusick 		kp->ki_sigignore = p->p_procsig->ps_sigignore;
8231f7d2501SKirk McKusick 		kp->ki_sigcatch = p->p_procsig->ps_sigcatch;
824d8c85307SJulian Elischer 	}
8259ed346baSBosko Milekic 	mtx_lock_spin(&sched_lock);
826e602ba25SJulian Elischer 	if (p->p_state != PRS_NEW &&
827e602ba25SJulian Elischer 	    p->p_state != PRS_ZOMBIE &&
828e602ba25SJulian Elischer 	    p->p_vmspace != NULL) {
8291f7d2501SKirk McKusick 		struct vmspace *vm = p->p_vmspace;
830cd73303cSDavid Greenman 
8311f7d2501SKirk McKusick 		kp->ki_size = vm->vm_map.size;
8321f7d2501SKirk McKusick 		kp->ki_rssize = vmspace_resident_count(vm); /*XXX*/
833e414d9aaSPeter Wemm 		if (p->p_sflag & PS_INMEM)
834b40ce416SJulian Elischer 			kp->ki_rssize += UAREA_PAGES;
835b40ce416SJulian Elischer 		FOREACH_THREAD_IN_PROC(p, td) /* XXXKSE: thread swapout check */
836b40ce416SJulian Elischer 			kp->ki_rssize += KSTACK_PAGES;
8371f7d2501SKirk McKusick 		kp->ki_swrss = vm->vm_swrss;
8381f7d2501SKirk McKusick 		kp->ki_tsize = vm->vm_tsize;
8391f7d2501SKirk McKusick 		kp->ki_dsize = vm->vm_dsize;
8401f7d2501SKirk McKusick 		kp->ki_ssize = vm->vm_ssize;
8411f7d2501SKirk McKusick 	}
84242a4ed99SJohn Baldwin 	if ((p->p_sflag & PS_INMEM) && p->p_stats) {
8431f7d2501SKirk McKusick 		kp->ki_start = p->p_stats->p_start;
8441f7d2501SKirk McKusick 		kp->ki_rusage = p->p_stats->p_ru;
8451f7d2501SKirk McKusick 		kp->ki_childtime.tv_sec = p->p_stats->p_cru.ru_utime.tv_sec +
8461f7d2501SKirk McKusick 		    p->p_stats->p_cru.ru_stime.tv_sec;
8471f7d2501SKirk McKusick 		kp->ki_childtime.tv_usec = p->p_stats->p_cru.ru_utime.tv_usec +
8481f7d2501SKirk McKusick 		    p->p_stats->p_cru.ru_stime.tv_usec;
8491f7d2501SKirk McKusick 	}
8507c7a6f22SJulian Elischer 	if (p->p_state != PRS_ZOMBIE) {
85196347d1eSAlan Cox 		td = FIRST_THREAD_IN_PROC(p);
852e602ba25SJulian Elischer 		if (!(p->p_flag & P_KSES)) {
853e602ba25SJulian Elischer 			if (td->td_wmesg != NULL) {
854e602ba25SJulian Elischer 				strncpy(kp->ki_wmesg, td->td_wmesg,
855e602ba25SJulian Elischer 				    sizeof(kp->ki_wmesg) - 1);
856e602ba25SJulian Elischer 			}
857e602ba25SJulian Elischer 			if (td->td_state == TDS_MTX) {
85842a4ed99SJohn Baldwin 				kp->ki_kiflag |= KI_MTXBLOCK;
859079b7badSJulian Elischer 				strncpy(kp->ki_mtxname, td->td_mtxname,
86077330eebSPeter Wemm 				    sizeof(kp->ki_mtxname) - 1);
86142a4ed99SJohn Baldwin 			}
862e602ba25SJulian Elischer 		}
863e602ba25SJulian Elischer 
8642b239dd1SJens Schweikhardt 		if (p->p_state == PRS_NORMAL) { /*  XXXKSE very approximate */
865e602ba25SJulian Elischer 			if ((td->td_state == TDS_RUNQ) ||
866e602ba25SJulian Elischer 			    (td->td_state == TDS_RUNNING)) {
867e602ba25SJulian Elischer 				kp->ki_stat = SRUN;
868e602ba25SJulian Elischer 			} else if (td->td_state == TDS_SLP) {
869e602ba25SJulian Elischer 				kp->ki_stat = SSLEEP;
870e602ba25SJulian Elischer 			} else if (P_SHOULDSTOP(p)) {
871e602ba25SJulian Elischer 				kp->ki_stat = SSTOP;
872e602ba25SJulian Elischer 			} else if (td->td_state == TDS_MTX) {
873e602ba25SJulian Elischer 				kp->ki_stat = SMTX;
874e602ba25SJulian Elischer 			} else {
875e602ba25SJulian Elischer 				kp->ki_stat = SWAIT;
876e602ba25SJulian Elischer 			}
877e602ba25SJulian Elischer 		} else {
878e602ba25SJulian Elischer 			kp->ki_stat = SIDL;
879e602ba25SJulian Elischer 		}
880e602ba25SJulian Elischer 
8816d3e7b9bSJohn Baldwin 		kp->ki_sflag = p->p_sflag;
88242a4ed99SJohn Baldwin 		kp->ki_swtime = p->p_swtime;
8831f7d2501SKirk McKusick 		kp->ki_pid = p->p_pid;
884b40ce416SJulian Elischer 		/* vvv XXXKSE */
885e602ba25SJulian Elischer 		if (!(p->p_flag & P_KSES)) {
8861cbb9c3bSPoul-Henning Kamp 			bintime2timeval(&p->p_runtime, &tv);
8871cbb9c3bSPoul-Henning Kamp 			kp->ki_runtime = tv.tv_sec * (u_int64_t)1000000 + tv.tv_usec;
888b40ce416SJulian Elischer 			kp->ki_pctcpu = p->p_kse.ke_pctcpu;
889e602ba25SJulian Elischer 			kp->ki_estcpu = p->p_ksegrp.kg_estcpu;
890e602ba25SJulian Elischer 			kp->ki_slptime = p->p_ksegrp.kg_slptime;
891079b7badSJulian Elischer 			kp->ki_wchan = td->td_wchan;
8922c100766SJulian Elischer 			kp->ki_pri.pri_level = td->td_priority;
893e602ba25SJulian Elischer 			kp->ki_pri.pri_user = p->p_ksegrp.kg_user_pri;
894e602ba25SJulian Elischer 			kp->ki_pri.pri_class = p->p_ksegrp.kg_pri_class;
8952c100766SJulian Elischer 			kp->ki_pri.pri_native = td->td_base_pri;
896e602ba25SJulian Elischer 			kp->ki_nice = p->p_ksegrp.kg_nice;
897b40ce416SJulian Elischer 			kp->ki_rqindex = p->p_kse.ke_rqindex;
898b40ce416SJulian Elischer 			kp->ki_oncpu = p->p_kse.ke_oncpu;
899079b7badSJulian Elischer 			kp->ki_lastcpu = td->td_lastcpu;
900079b7badSJulian Elischer 			kp->ki_tdflags = td->td_flags;
901079b7badSJulian Elischer 			kp->ki_pcb = td->td_pcb;
902079b7badSJulian Elischer 			kp->ki_kstack = (void *)td->td_kstack;
903e602ba25SJulian Elischer 		} else {
904e602ba25SJulian Elischer 			kp->ki_oncpu = -1;
905e602ba25SJulian Elischer 			kp->ki_lastcpu = -1;
906e602ba25SJulian Elischer 			kp->ki_tdflags = -1;
907e602ba25SJulian Elischer 			/* All the reast are 0 */
908e602ba25SJulian Elischer 		}
9097c7a6f22SJulian Elischer 	} else {
9107c7a6f22SJulian Elischer 		kp->ki_stat = SZOMB;
9117c7a6f22SJulian Elischer 	}
912b40ce416SJulian Elischer 	/* ^^^ XXXKSE */
9139ed346baSBosko Milekic 	mtx_unlock_spin(&sched_lock);
9141f7d2501SKirk McKusick 	sp = NULL;
915f591779bSSeigo Tanimura 	tp = NULL;
9161f7d2501SKirk McKusick 	if (p->p_pgrp) {
9171f7d2501SKirk McKusick 		kp->ki_pgid = p->p_pgrp->pg_id;
9181f7d2501SKirk McKusick 		kp->ki_jobc = p->p_pgrp->pg_jobc;
9191f7d2501SKirk McKusick 		sp = p->p_pgrp->pg_session;
9201f7d2501SKirk McKusick 
9211f7d2501SKirk McKusick 		if (sp != NULL) {
9221f7d2501SKirk McKusick 			kp->ki_sid = sp->s_sid;
923f591779bSSeigo Tanimura 			SESS_LOCK(sp);
92477330eebSPeter Wemm 			strncpy(kp->ki_login, sp->s_login,
92577330eebSPeter Wemm 			    sizeof(kp->ki_login) - 1);
9261f7d2501SKirk McKusick 			if (sp->s_ttyvp)
927b8e6bf1eSJohn Baldwin 				kp->ki_kiflag |= KI_CTTY;
9281f7d2501SKirk McKusick 			if (SESS_LEADER(p))
9291f7d2501SKirk McKusick 				kp->ki_kiflag |= KI_SLEADER;
930f591779bSSeigo Tanimura 			tp = sp->s_ttyp;
931f591779bSSeigo Tanimura 			SESS_UNLOCK(sp);
932cd73303cSDavid Greenman 		}
933cd73303cSDavid Greenman 	}
934f591779bSSeigo Tanimura 	if ((p->p_flag & P_CONTROLT) && tp != NULL) {
9351f7d2501SKirk McKusick 		kp->ki_tdev = dev2udev(tp->t_dev);
9361f7d2501SKirk McKusick 		kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
9371f7d2501SKirk McKusick 		if (tp->t_session)
9381f7d2501SKirk McKusick 			kp->ki_tsid = tp->t_session->s_sid;
939972f9b20SPoul-Henning Kamp 	} else
9401f7d2501SKirk McKusick 		kp->ki_tdev = NOUDEV;
94177330eebSPeter Wemm 	if (p->p_comm[0] != '\0') {
94277330eebSPeter Wemm 		strncpy(kp->ki_comm, p->p_comm, sizeof(kp->ki_comm) - 1);
94377330eebSPeter Wemm 		strncpy(kp->ki_ocomm, p->p_comm, sizeof(kp->ki_ocomm) - 1);
94462ca2477SJohn Baldwin 	}
9451f7d2501SKirk McKusick 	kp->ki_siglist = p->p_siglist;
9461f7d2501SKirk McKusick 	kp->ki_sigmask = p->p_sigmask;
9471f7d2501SKirk McKusick 	kp->ki_xstat = p->p_xstat;
9481f7d2501SKirk McKusick 	kp->ki_acflag = p->p_acflag;
9491f7d2501SKirk McKusick 	kp->ki_flag = p->p_flag;
95091421ba2SRobert Watson 	/* If jailed(p->p_ucred), emulate the old P_JAILED flag. */
95191421ba2SRobert Watson 	if (jailed(p->p_ucred))
95291421ba2SRobert Watson 		kp->ki_flag |= P_JAILED;
9531f7d2501SKirk McKusick 	kp->ki_lock = p->p_lock;
95442a4ed99SJohn Baldwin 	if (p->p_pptr)
95542a4ed99SJohn Baldwin 		kp->ki_ppid = p->p_pptr->p_pid;
956972f9b20SPoul-Henning Kamp }
957972f9b20SPoul-Henning Kamp 
95842a4ed99SJohn Baldwin /*
95942a4ed99SJohn Baldwin  * Locate a zombie process by number
96042a4ed99SJohn Baldwin  */
96142a4ed99SJohn Baldwin struct proc *
9623ce93e4eSPoul-Henning Kamp zpfind(pid_t pid)
9633ce93e4eSPoul-Henning Kamp {
9643ce93e4eSPoul-Henning Kamp 	struct proc *p;
9653ce93e4eSPoul-Henning Kamp 
9661005a129SJohn Baldwin 	sx_slock(&allproc_lock);
9671b727751SPoul-Henning Kamp 	LIST_FOREACH(p, &zombproc, p_list)
96833a9ed9dSJohn Baldwin 		if (p->p_pid == pid) {
96933a9ed9dSJohn Baldwin 			PROC_LOCK(p);
970c0c25570SJake Burkholder 			break;
97133a9ed9dSJohn Baldwin 		}
9721005a129SJohn Baldwin 	sx_sunlock(&allproc_lock);
9733ce93e4eSPoul-Henning Kamp 	return (p);
9743ce93e4eSPoul-Henning Kamp }
9753ce93e4eSPoul-Henning Kamp 
9763ce93e4eSPoul-Henning Kamp 
97765c9b430SJohn Baldwin /*
97865c9b430SJohn Baldwin  * Must be called with the process locked and will return with it unlocked.
97965c9b430SJohn Baldwin  */
9803ce93e4eSPoul-Henning Kamp static int
9813ce93e4eSPoul-Henning Kamp sysctl_out_proc(struct proc *p, struct sysctl_req *req, int doingzomb)
9823ce93e4eSPoul-Henning Kamp {
9831f7d2501SKirk McKusick 	struct kinfo_proc kinfo_proc;
9843ce93e4eSPoul-Henning Kamp 	int error;
98533a9ed9dSJohn Baldwin 	struct proc *np;
9863ce93e4eSPoul-Henning Kamp 	pid_t pid = p->p_pid;
9873ce93e4eSPoul-Henning Kamp 
98865c9b430SJohn Baldwin 	PROC_LOCK_ASSERT(p, MA_OWNED);
9891f7d2501SKirk McKusick 	fill_kinfo_proc(p, &kinfo_proc);
99065c9b430SJohn Baldwin 	PROC_UNLOCK(p);
9911f7d2501SKirk McKusick 	error = SYSCTL_OUT(req, (caddr_t)&kinfo_proc, sizeof(kinfo_proc));
9923ce93e4eSPoul-Henning Kamp 	if (error)
9933ce93e4eSPoul-Henning Kamp 		return (error);
99433a9ed9dSJohn Baldwin 	if (doingzomb)
99533a9ed9dSJohn Baldwin 		np = zpfind(pid);
99633a9ed9dSJohn Baldwin 	else {
99733a9ed9dSJohn Baldwin 		if (pid == 0)
99833a9ed9dSJohn Baldwin 			return (0);
99933a9ed9dSJohn Baldwin 		np = pfind(pid);
100033a9ed9dSJohn Baldwin 	}
100133a9ed9dSJohn Baldwin 	if (np == NULL)
10023ce93e4eSPoul-Henning Kamp 		return EAGAIN;
100333a9ed9dSJohn Baldwin 	if (np != p) {
100433a9ed9dSJohn Baldwin 		PROC_UNLOCK(np);
10053ce93e4eSPoul-Henning Kamp 		return EAGAIN;
100633a9ed9dSJohn Baldwin 	}
100733a9ed9dSJohn Baldwin 	PROC_UNLOCK(np);
10083ce93e4eSPoul-Henning Kamp 	return (0);
10093ce93e4eSPoul-Henning Kamp }
10103ce93e4eSPoul-Henning Kamp 
1011972f9b20SPoul-Henning Kamp static int
101282d9ae4eSPoul-Henning Kamp sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
1013972f9b20SPoul-Henning Kamp {
1014972f9b20SPoul-Henning Kamp 	int *name = (int*) arg1;
1015972f9b20SPoul-Henning Kamp 	u_int namelen = arg2;
1016972f9b20SPoul-Henning Kamp 	struct proc *p;
1017972f9b20SPoul-Henning Kamp 	int doingzomb;
1018972f9b20SPoul-Henning Kamp 	int error = 0;
1019972f9b20SPoul-Henning Kamp 
10203ce93e4eSPoul-Henning Kamp 	if (oidp->oid_number == KERN_PROC_PID) {
10213ce93e4eSPoul-Henning Kamp 		if (namelen != 1)
1022972f9b20SPoul-Henning Kamp 			return (EINVAL);
10233ce93e4eSPoul-Henning Kamp 		p = pfind((pid_t)name[0]);
10243ce93e4eSPoul-Henning Kamp 		if (!p)
10253ce93e4eSPoul-Henning Kamp 			return (0);
1026f44d9e24SJohn Baldwin 		if (p_cansee(curthread, p)) {
102733a9ed9dSJohn Baldwin 			PROC_UNLOCK(p);
102875c13541SPoul-Henning Kamp 			return (0);
102933a9ed9dSJohn Baldwin 		}
10303ce93e4eSPoul-Henning Kamp 		error = sysctl_out_proc(p, req, 0);
10313ce93e4eSPoul-Henning Kamp 		return (error);
10323ce93e4eSPoul-Henning Kamp 	}
10333ce93e4eSPoul-Henning Kamp 	if (oidp->oid_number == KERN_PROC_ALL && !namelen)
10343ce93e4eSPoul-Henning Kamp 		;
10353ce93e4eSPoul-Henning Kamp 	else if (oidp->oid_number != KERN_PROC_ALL && namelen == 1)
10363ce93e4eSPoul-Henning Kamp 		;
10373ce93e4eSPoul-Henning Kamp 	else
10383ce93e4eSPoul-Henning Kamp 		return (EINVAL);
10393ce93e4eSPoul-Henning Kamp 
1040972f9b20SPoul-Henning Kamp 	if (!req->oldptr) {
10413ce93e4eSPoul-Henning Kamp 		/* overestimate by 5 procs */
1042972f9b20SPoul-Henning Kamp 		error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5);
1043972f9b20SPoul-Henning Kamp 		if (error)
1044972f9b20SPoul-Henning Kamp 			return (error);
1045972f9b20SPoul-Henning Kamp 	}
10465c38b6dbSDon Lewis 	sysctl_wire_old_buffer(req, 0);
10471005a129SJohn Baldwin 	sx_slock(&allproc_lock);
10483ce93e4eSPoul-Henning Kamp 	for (doingzomb=0 ; doingzomb < 2 ; doingzomb++) {
10493ce93e4eSPoul-Henning Kamp 		if (!doingzomb)
10501b727751SPoul-Henning Kamp 			p = LIST_FIRST(&allproc);
10513ce93e4eSPoul-Henning Kamp 		else
10521b727751SPoul-Henning Kamp 			p = LIST_FIRST(&zombproc);
10531b727751SPoul-Henning Kamp 		for (; p != 0; p = LIST_NEXT(p, p_list)) {
105465c9b430SJohn Baldwin 			PROC_LOCK(p);
1055972f9b20SPoul-Henning Kamp 			/*
1056387d2c03SRobert Watson 			 * Show a user only appropriate processes.
105703f808c5SPaul Saab 			 */
1058f44d9e24SJohn Baldwin 			if (p_cansee(curthread, p)) {
105965c9b430SJohn Baldwin 				PROC_UNLOCK(p);
106003f808c5SPaul Saab 				continue;
106165c9b430SJohn Baldwin 			}
106203f808c5SPaul Saab 			/*
1063972f9b20SPoul-Henning Kamp 			 * Skip embryonic processes.
1064972f9b20SPoul-Henning Kamp 			 */
1065e602ba25SJulian Elischer 			if (p->p_state == PRS_NEW) {
106665c9b430SJohn Baldwin 				PROC_UNLOCK(p);
1067972f9b20SPoul-Henning Kamp 				continue;
106865c9b430SJohn Baldwin 			}
1069972f9b20SPoul-Henning Kamp 			/*
1070972f9b20SPoul-Henning Kamp 			 * TODO - make more efficient (see notes below).
1071972f9b20SPoul-Henning Kamp 			 * do by session.
1072972f9b20SPoul-Henning Kamp 			 */
10733ce93e4eSPoul-Henning Kamp 			switch (oidp->oid_number) {
1074972f9b20SPoul-Henning Kamp 
1075972f9b20SPoul-Henning Kamp 			case KERN_PROC_PGRP:
1076972f9b20SPoul-Henning Kamp 				/* could do this by traversing pgrp */
10773ce93e4eSPoul-Henning Kamp 				if (p->p_pgrp == NULL ||
1078f591779bSSeigo Tanimura 				    p->p_pgrp->pg_id != (pid_t)name[0]) {
1079f591779bSSeigo Tanimura 					PROC_UNLOCK(p);
1080972f9b20SPoul-Henning Kamp 					continue;
1081f591779bSSeigo Tanimura 				}
1082972f9b20SPoul-Henning Kamp 				break;
1083972f9b20SPoul-Henning Kamp 
1084972f9b20SPoul-Henning Kamp 			case KERN_PROC_TTY:
1085972f9b20SPoul-Henning Kamp 				if ((p->p_flag & P_CONTROLT) == 0 ||
1086f591779bSSeigo Tanimura 				    p->p_session == NULL) {
1087f591779bSSeigo Tanimura 					PROC_UNLOCK(p);
1088972f9b20SPoul-Henning Kamp 					continue;
1089f591779bSSeigo Tanimura 				}
1090f591779bSSeigo Tanimura 				SESS_LOCK(p->p_session);
1091f591779bSSeigo Tanimura 				if (p->p_session->s_ttyp == NULL ||
1092f591779bSSeigo Tanimura 				    dev2udev(p->p_session->s_ttyp->t_dev) !=
1093f591779bSSeigo Tanimura 				    (udev_t)name[0]) {
1094f591779bSSeigo Tanimura 					SESS_UNLOCK(p->p_session);
1095f591779bSSeigo Tanimura 					PROC_UNLOCK(p);
1096f591779bSSeigo Tanimura 					continue;
1097f591779bSSeigo Tanimura 				}
1098f591779bSSeigo Tanimura 				SESS_UNLOCK(p->p_session);
1099972f9b20SPoul-Henning Kamp 				break;
1100972f9b20SPoul-Henning Kamp 
1101972f9b20SPoul-Henning Kamp 			case KERN_PROC_UID:
11023ce93e4eSPoul-Henning Kamp 				if (p->p_ucred == NULL ||
110365c9b430SJohn Baldwin 				    p->p_ucred->cr_uid != (uid_t)name[0]) {
110465c9b430SJohn Baldwin 					PROC_UNLOCK(p);
1105972f9b20SPoul-Henning Kamp 					continue;
110665c9b430SJohn Baldwin 				}
1107972f9b20SPoul-Henning Kamp 				break;
1108972f9b20SPoul-Henning Kamp 
1109972f9b20SPoul-Henning Kamp 			case KERN_PROC_RUID:
11103ce93e4eSPoul-Henning Kamp 				if (p->p_ucred == NULL ||
111165c9b430SJohn Baldwin 				    p->p_ucred->cr_ruid != (uid_t)name[0]) {
111265c9b430SJohn Baldwin 					PROC_UNLOCK(p);
1113972f9b20SPoul-Henning Kamp 					continue;
111465c9b430SJohn Baldwin 				}
1115972f9b20SPoul-Henning Kamp 				break;
1116972f9b20SPoul-Henning Kamp 			}
1117972f9b20SPoul-Henning Kamp 
11183ce93e4eSPoul-Henning Kamp 			error = sysctl_out_proc(p, req, doingzomb);
1119553629ebSJake Burkholder 			if (error) {
11201005a129SJohn Baldwin 				sx_sunlock(&allproc_lock);
1121972f9b20SPoul-Henning Kamp 				return (error);
1122972f9b20SPoul-Henning Kamp 			}
1123972f9b20SPoul-Henning Kamp 		}
1124553629ebSJake Burkholder 	}
11251005a129SJohn Baldwin 	sx_sunlock(&allproc_lock);
1126972f9b20SPoul-Henning Kamp 	return (0);
1127972f9b20SPoul-Henning Kamp }
1128972f9b20SPoul-Henning Kamp 
1129c1508b28SAlfred Perlstein struct pargs *
1130c1508b28SAlfred Perlstein pargs_alloc(int len)
1131c1508b28SAlfred Perlstein {
1132c1508b28SAlfred Perlstein 	struct pargs *pa;
1133c1508b28SAlfred Perlstein 
1134c1508b28SAlfred Perlstein 	MALLOC(pa, struct pargs *, sizeof(struct pargs) + len, M_PARGS,
1135c1508b28SAlfred Perlstein 		M_WAITOK);
1136c1508b28SAlfred Perlstein 	pa->ar_ref = 1;
1137c1508b28SAlfred Perlstein 	pa->ar_length = len;
1138c1508b28SAlfred Perlstein 	return (pa);
1139c1508b28SAlfred Perlstein }
1140c1508b28SAlfred Perlstein 
1141c1508b28SAlfred Perlstein void
1142c1508b28SAlfred Perlstein pargs_free(struct pargs *pa)
1143c1508b28SAlfred Perlstein {
1144c1508b28SAlfred Perlstein 
1145c1508b28SAlfred Perlstein 	FREE(pa, M_PARGS);
1146c1508b28SAlfred Perlstein }
1147c1508b28SAlfred Perlstein 
1148c1508b28SAlfred Perlstein void
1149c1508b28SAlfred Perlstein pargs_hold(struct pargs *pa)
1150c1508b28SAlfred Perlstein {
1151c1508b28SAlfred Perlstein 
1152c1508b28SAlfred Perlstein 	if (pa == NULL)
1153c1508b28SAlfred Perlstein 		return;
1154c1508b28SAlfred Perlstein 	PARGS_LOCK(pa);
1155c1508b28SAlfred Perlstein 	pa->ar_ref++;
1156c1508b28SAlfred Perlstein 	PARGS_UNLOCK(pa);
1157c1508b28SAlfred Perlstein }
1158c1508b28SAlfred Perlstein 
1159c1508b28SAlfred Perlstein void
1160c1508b28SAlfred Perlstein pargs_drop(struct pargs *pa)
1161c1508b28SAlfred Perlstein {
1162c1508b28SAlfred Perlstein 
1163c1508b28SAlfred Perlstein 	if (pa == NULL)
1164c1508b28SAlfred Perlstein 		return;
1165c1508b28SAlfred Perlstein 	PARGS_LOCK(pa);
1166c1508b28SAlfred Perlstein 	if (--pa->ar_ref == 0) {
1167c1508b28SAlfred Perlstein 		PARGS_UNLOCK(pa);
1168c1508b28SAlfred Perlstein 		pargs_free(pa);
1169c1508b28SAlfred Perlstein 	} else
1170c1508b28SAlfred Perlstein 		PARGS_UNLOCK(pa);
1171c1508b28SAlfred Perlstein }
1172c1508b28SAlfred Perlstein 
1173b9df5231SPoul-Henning Kamp /*
1174b9df5231SPoul-Henning Kamp  * This sysctl allows a process to retrieve the argument list or process
1175b9df5231SPoul-Henning Kamp  * title for another process without groping around in the address space
1176b9df5231SPoul-Henning Kamp  * of the other process.  It also allow a process to set its own "process
1177b9df5231SPoul-Henning Kamp  * title to a string of its own choice.
1178b9df5231SPoul-Henning Kamp  */
1179b9df5231SPoul-Henning Kamp static int
118082d9ae4eSPoul-Henning Kamp sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
1181b9df5231SPoul-Henning Kamp {
1182b9df5231SPoul-Henning Kamp 	int *name = (int*) arg1;
1183b9df5231SPoul-Henning Kamp 	u_int namelen = arg2;
1184b9df5231SPoul-Henning Kamp 	struct proc *p;
1185b9df5231SPoul-Henning Kamp 	struct pargs *pa;
1186b9df5231SPoul-Henning Kamp 	int error = 0;
1187b9df5231SPoul-Henning Kamp 
1188b9df5231SPoul-Henning Kamp 	if (namelen != 1)
1189b9df5231SPoul-Henning Kamp 		return (EINVAL);
1190b9df5231SPoul-Henning Kamp 
1191b9df5231SPoul-Henning Kamp 	p = pfind((pid_t)name[0]);
1192b9df5231SPoul-Henning Kamp 	if (!p)
1193b9df5231SPoul-Henning Kamp 		return (0);
1194b9df5231SPoul-Henning Kamp 
1195f44d9e24SJohn Baldwin 	if ((!ps_argsopen) && p_cansee(curthread, p)) {
119633a9ed9dSJohn Baldwin 		PROC_UNLOCK(p);
1197b9df5231SPoul-Henning Kamp 		return (0);
119833a9ed9dSJohn Baldwin 	}
119933a9ed9dSJohn Baldwin 	PROC_UNLOCK(p);
1200b9df5231SPoul-Henning Kamp 
1201b9df5231SPoul-Henning Kamp 	if (req->newptr && curproc != p)
1202b9df5231SPoul-Henning Kamp 		return (EPERM);
1203b9df5231SPoul-Henning Kamp 
12047b11fea6SAlfred Perlstein 	PROC_LOCK(p);
12057b11fea6SAlfred Perlstein 	pa = p->p_args;
12067b11fea6SAlfred Perlstein 	pargs_hold(pa);
12077b11fea6SAlfred Perlstein 	PROC_UNLOCK(p);
12087b11fea6SAlfred Perlstein 	if (req->oldptr && pa != NULL) {
12097b11fea6SAlfred Perlstein 		error = SYSCTL_OUT(req, pa->ar_args, pa->ar_length);
12107b11fea6SAlfred Perlstein 	}
12117b11fea6SAlfred Perlstein 	pargs_drop(pa);
12129718382dSJonathan Mini 	if (req->newptr == NULL)
1213b9df5231SPoul-Henning Kamp 		return (error);
1214b9df5231SPoul-Henning Kamp 
121533a9ed9dSJohn Baldwin 	PROC_LOCK(p);
1216fbd26f75SJohn Baldwin 	pa = p->p_args;
1217b9df5231SPoul-Henning Kamp 	p->p_args = NULL;
121815e9ec51SJohn Baldwin 	PROC_UNLOCK(p);
12198899023fSAlfred Perlstein 	pargs_drop(pa);
1220b9df5231SPoul-Henning Kamp 
1221b9df5231SPoul-Henning Kamp 	if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit)
1222b9df5231SPoul-Henning Kamp 		return (error);
1223b9df5231SPoul-Henning Kamp 
12248899023fSAlfred Perlstein 	pa = pargs_alloc(req->newlen);
1225b9df5231SPoul-Henning Kamp 	error = SYSCTL_IN(req, pa->ar_args, req->newlen);
122615e9ec51SJohn Baldwin 	if (!error) {
122715e9ec51SJohn Baldwin 		PROC_LOCK(p);
1228b9df5231SPoul-Henning Kamp 		p->p_args = pa;
122915e9ec51SJohn Baldwin 		PROC_UNLOCK(p);
123015e9ec51SJohn Baldwin 	} else
12318899023fSAlfred Perlstein 		pargs_free(pa);
1232b9df5231SPoul-Henning Kamp 	return (error);
1233b9df5231SPoul-Henning Kamp }
12343ce93e4eSPoul-Henning Kamp 
12353ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD,  0, "Process table");
12363ce93e4eSPoul-Henning Kamp 
12373ce93e4eSPoul-Henning Kamp SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT,
12383d177f46SBill Fumerola 	0, 0, sysctl_kern_proc, "S,proc", "Return entire process table");
12393ce93e4eSPoul-Henning Kamp 
12403ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_PGRP, pgrp, CTLFLAG_RD,
12413ce93e4eSPoul-Henning Kamp 	sysctl_kern_proc, "Process table");
12423ce93e4eSPoul-Henning Kamp 
12433ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_TTY, tty, CTLFLAG_RD,
12443ce93e4eSPoul-Henning Kamp 	sysctl_kern_proc, "Process table");
12453ce93e4eSPoul-Henning Kamp 
12463ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_UID, uid, CTLFLAG_RD,
12473ce93e4eSPoul-Henning Kamp 	sysctl_kern_proc, "Process table");
12483ce93e4eSPoul-Henning Kamp 
12493ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_RUID, ruid, CTLFLAG_RD,
12503ce93e4eSPoul-Henning Kamp 	sysctl_kern_proc, "Process table");
12513ce93e4eSPoul-Henning Kamp 
12523ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_PID, pid, CTLFLAG_RD,
1253972f9b20SPoul-Henning Kamp 	sysctl_kern_proc, "Process table");
1254b9df5231SPoul-Henning Kamp 
12559b6d9dbaSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args, CTLFLAG_RW | CTLFLAG_ANYBODY,
12569b6d9dbaSPoul-Henning Kamp 	sysctl_kern_proc_args, "Process argument list");
1257a136efe9SPeter Wemm 
1258a136efe9SPeter Wemm SYSCTL_INT(_kern_proc, OID_AUTO, active, CTLFLAG_RD,
1259a136efe9SPeter Wemm 	&active_procs, 0, "Number of active procs in system.");
1260a136efe9SPeter Wemm 
1261a136efe9SPeter Wemm SYSCTL_INT(_kern_proc, OID_AUTO, cached, CTLFLAG_RD,
1262a136efe9SPeter Wemm 	&cached_procs, 0, "Number of procs in proc cache.");
1263a136efe9SPeter Wemm 
1264a136efe9SPeter Wemm SYSCTL_INT(_kern_proc, OID_AUTO, allocated, CTLFLAG_RD,
1265a136efe9SPeter Wemm 	&allocated_procs, 0, "Number of procs in zone.");
1266