xref: /freebsd/sys/kern/kern_fork.c (revision af8ad83e5ce4b8d3f02b6c211879b51ba7fcfb5e)
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  * (c) UNIX System Laboratories, Inc.
5df8bae1dSRodney W. Grimes  * All or some portions of this file are derived from material licensed
6df8bae1dSRodney W. Grimes  * to the University of California by American Telephone and Telegraph
7df8bae1dSRodney W. Grimes  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8df8bae1dSRodney W. Grimes  * the permission of UNIX System Laboratories, Inc.
9df8bae1dSRodney W. Grimes  *
10df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
11df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
12df8bae1dSRodney W. Grimes  * are met:
13df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
14df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
15df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
16df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
17df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
18df8bae1dSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
19df8bae1dSRodney W. Grimes  *    must display the following acknowledgement:
20df8bae1dSRodney W. Grimes  *	This product includes software developed by the University of
21df8bae1dSRodney W. Grimes  *	California, Berkeley and its contributors.
22df8bae1dSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
23df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
24df8bae1dSRodney W. Grimes  *    without specific prior written permission.
25df8bae1dSRodney W. Grimes  *
26df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
37df8bae1dSRodney W. Grimes  *
38df8bae1dSRodney W. Grimes  *	@(#)kern_fork.c	8.6 (Berkeley) 4/8/94
39af8ad83eSPeter Wemm  * $Id: kern_fork.c,v 1.56 1999/03/02 00:28:08 julian Exp $
40df8bae1dSRodney W. Grimes  */
41df8bae1dSRodney W. Grimes 
42db6a20e2SGarrett Wollman #include "opt_ktrace.h"
43db6a20e2SGarrett Wollman 
44df8bae1dSRodney W. Grimes #include <sys/param.h>
45df8bae1dSRodney W. Grimes #include <sys/systm.h>
46d2d3e875SBruce Evans #include <sys/sysproto.h>
47df8bae1dSRodney W. Grimes #include <sys/filedesc.h>
48df8bae1dSRodney W. Grimes #include <sys/kernel.h>
49c76e95c3SPeter Wemm #include <sys/sysctl.h>
50df8bae1dSRodney W. Grimes #include <sys/malloc.h>
51df8bae1dSRodney W. Grimes #include <sys/proc.h>
52df8bae1dSRodney W. Grimes #include <sys/resourcevar.h>
53df8bae1dSRodney W. Grimes #include <sys/vnode.h>
54df8bae1dSRodney W. Grimes #include <sys/acct.h>
55df8bae1dSRodney W. Grimes #include <sys/ktrace.h>
56b71fec07SBruce Evans #include <sys/unistd.h>
57df8bae1dSRodney W. Grimes 
58d93f860cSPoul-Henning Kamp #include <vm/vm.h>
59996c772fSJohn Dyson #include <sys/lock.h>
60dabee6feSPeter Wemm #include <vm/pmap.h>
61dabee6feSPeter Wemm #include <vm/vm_map.h>
62efeaf95aSDavid Greenman #include <vm/vm_extern.h>
632d8acc0fSJohn Dyson #include <vm/vm_zone.h>
64d93f860cSPoul-Henning Kamp 
656626c604SJulian Elischer #include <machine/frame.h>
66dc9c271aSJulian Elischer #include <sys/user.h>
6788c5ea45SJulian Elischer 
68c76e95c3SPeter Wemm #ifdef SMP
69be67169aSBruce Evans static int	fast_vfork = 0;	/* Doesn't work on SMP yet. */
70c76e95c3SPeter Wemm #else
71be67169aSBruce Evans static int	fast_vfork = 1;
72c76e95c3SPeter Wemm #endif
73c76e95c3SPeter Wemm SYSCTL_INT(_kern, OID_AUTO, fast_vfork, CTLFLAG_RW, &fast_vfork, 0, "");
74c76e95c3SPeter Wemm 
75fed06968SJulian Elischer /*
76e0d898b4SJulian Elischer  * These are the stuctures used to create a callout list for things to do
77e0d898b4SJulian Elischer  * when forking a process
78fed06968SJulian Elischer  */
79fed06968SJulian Elischer typedef struct fork_list_element {
80fed06968SJulian Elischer 	struct fork_list_element *next;
81fed06968SJulian Elischer 	forklist_fn function;
82fed06968SJulian Elischer } *fle_p;
83fed06968SJulian Elischer 
84fed06968SJulian Elischer static fle_p	fork_list;
85fed06968SJulian Elischer 
86d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
87ad7507e2SSteven Wallace struct fork_args {
88ad7507e2SSteven Wallace 	int     dummy;
89ad7507e2SSteven Wallace };
90d2d3e875SBruce Evans #endif
91ad7507e2SSteven Wallace 
92df8bae1dSRodney W. Grimes /* ARGSUSED */
9326f9a767SRodney W. Grimes int
94cb226aaaSPoul-Henning Kamp fork(p, uap)
95df8bae1dSRodney W. Grimes 	struct proc *p;
96df8bae1dSRodney W. Grimes 	struct fork_args *uap;
97df8bae1dSRodney W. Grimes {
98be67169aSBruce Evans 
99be67169aSBruce Evans 	return (fork1(p, RFFDG | RFPROC));
100df8bae1dSRodney W. Grimes }
101df8bae1dSRodney W. Grimes 
102df8bae1dSRodney W. Grimes /* ARGSUSED */
10326f9a767SRodney W. Grimes int
104cb226aaaSPoul-Henning Kamp vfork(p, uap)
105df8bae1dSRodney W. Grimes 	struct proc *p;
106dabee6feSPeter Wemm 	struct vfork_args *uap;
107df8bae1dSRodney W. Grimes {
108be67169aSBruce Evans 
109be67169aSBruce Evans 	return (fork1(p, RFFDG | RFPROC | RFPPWAIT | (fast_vfork ? RFMEM : 0)));
110df8bae1dSRodney W. Grimes }
111df8bae1dSRodney W. Grimes 
112dabee6feSPeter Wemm /* ARGSUSED */
113dabee6feSPeter Wemm int
114cb226aaaSPoul-Henning Kamp rfork(p, uap)
115dabee6feSPeter Wemm 	struct proc *p;
116dabee6feSPeter Wemm 	struct rfork_args *uap;
117dabee6feSPeter Wemm {
118be67169aSBruce Evans 
119be67169aSBruce Evans 	return (fork1(p, uap->flags));
120dabee6feSPeter Wemm }
121dabee6feSPeter Wemm 
122dabee6feSPeter Wemm 
123df8bae1dSRodney W. Grimes int	nprocs = 1;		/* process 0 */
12451068190SWolfram Schneider static int nextpid = 0;
125df8bae1dSRodney W. Grimes 
12674b2192aSJohn Dyson int
127be67169aSBruce Evans fork1(p1, flags)
128df8bae1dSRodney W. Grimes 	register struct proc *p1;
1290e3eb7eeSSujal Patel 	int flags;
130df8bae1dSRodney W. Grimes {
1310e3eb7eeSSujal Patel 	register struct proc *p2, *pptr;
132df8bae1dSRodney W. Grimes 	register uid_t uid;
133df8bae1dSRodney W. Grimes 	struct proc *newproc;
134df8bae1dSRodney W. Grimes 	int count;
13551068190SWolfram Schneider 	static int pidchecked = 0;
136e0d898b4SJulian Elischer 	fle_p ep ;
137dabee6feSPeter Wemm 
138e0d898b4SJulian Elischer 	ep = fork_list;
1395856e12eSJohn Dyson 
1400e3eb7eeSSujal Patel 	if ((flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
141dabee6feSPeter Wemm 		return (EINVAL);
142df8bae1dSRodney W. Grimes 
143b3196e4bSPeter Wemm #ifdef SMP
144b3196e4bSPeter Wemm 	/*
145b3196e4bSPeter Wemm 	 * FATAL now, we cannot have the same PTD on both cpus, the PTD
146b3196e4bSPeter Wemm 	 * needs to move out of PTmap and be per-process, even for shared
147b3196e4bSPeter Wemm 	 * page table processes.  Unfortunately, this means either removing
148b3196e4bSPeter Wemm 	 * PTD[] as a fixed virtual address, or move it to the per-cpu map
149b3196e4bSPeter Wemm 	 * area for SMP mode.  Both cases require seperate management of
150b3196e4bSPeter Wemm 	 * the per-process-even-if-PTmap-is-shared PTD.
151b3196e4bSPeter Wemm 	 */
152e384a980SPeter Wemm 	if (flags & RFMEM) {
153e384a980SPeter Wemm 		printf("shared address space fork attempted: pid: %d\n",
154e384a980SPeter Wemm 		    p1->p_pid);
155b3196e4bSPeter Wemm 		return (EOPNOTSUPP);
156e384a980SPeter Wemm 	}
157b3196e4bSPeter Wemm #endif
158b3196e4bSPeter Wemm 
159df8bae1dSRodney W. Grimes 	/*
1605856e12eSJohn Dyson 	 * Here we don't create a new process, but we divorce
1615856e12eSJohn Dyson 	 * certain parts of a process from itself.
1625856e12eSJohn Dyson 	 */
1635856e12eSJohn Dyson 	if ((flags & RFPROC) == 0) {
1645856e12eSJohn Dyson 
1655856e12eSJohn Dyson 		/*
1665856e12eSJohn Dyson 		 * Divorce the memory, if it is shared, essentially
1675856e12eSJohn Dyson 		 * this changes shared memory amongst threads, into
1685856e12eSJohn Dyson 		 * COW locally.
1695856e12eSJohn Dyson 		 */
1705856e12eSJohn Dyson 		if ((flags & RFMEM) == 0) {
1715856e12eSJohn Dyson 			if (p1->p_vmspace->vm_refcnt > 1) {
1725856e12eSJohn Dyson 				vmspace_unshare(p1);
1735856e12eSJohn Dyson 			}
1745856e12eSJohn Dyson 		}
1755856e12eSJohn Dyson 
1765856e12eSJohn Dyson 		/*
1775856e12eSJohn Dyson 		 * Close all file descriptors.
1785856e12eSJohn Dyson 		 */
1795856e12eSJohn Dyson 		if (flags & RFCFDG) {
1805856e12eSJohn Dyson 			struct filedesc *fdtmp;
1815856e12eSJohn Dyson 			fdtmp = fdinit(p1);
1825856e12eSJohn Dyson 			fdfree(p1);
1835856e12eSJohn Dyson 			p1->p_fd = fdtmp;
1845856e12eSJohn Dyson 		}
1855856e12eSJohn Dyson 
1865856e12eSJohn Dyson 		/*
1875856e12eSJohn Dyson 		 * Unshare file descriptors (from parent.)
1885856e12eSJohn Dyson 		 */
1895856e12eSJohn Dyson 		if (flags & RFFDG) {
1905856e12eSJohn Dyson 			if (p1->p_fd->fd_refcnt > 1) {
1915856e12eSJohn Dyson 				struct filedesc *newfd;
1925856e12eSJohn Dyson 				newfd = fdcopy(p1);
1935856e12eSJohn Dyson 				fdfree(p1);
1945856e12eSJohn Dyson 				p1->p_fd = newfd;
1955856e12eSJohn Dyson 			}
1965856e12eSJohn Dyson 		}
1975856e12eSJohn Dyson 		return (0);
1985856e12eSJohn Dyson 	}
1995856e12eSJohn Dyson 
2005856e12eSJohn Dyson 	/*
201df8bae1dSRodney W. Grimes 	 * Although process entries are dynamically created, we still keep
202df8bae1dSRodney W. Grimes 	 * a global limit on the maximum number we will create.  Don't allow
203df8bae1dSRodney W. Grimes 	 * a nonprivileged user to use the last process; don't let root
204df8bae1dSRodney W. Grimes 	 * exceed the limit. The variable nprocs is the current number of
205df8bae1dSRodney W. Grimes 	 * processes, maxproc is the limit.
206df8bae1dSRodney W. Grimes 	 */
207df8bae1dSRodney W. Grimes 	uid = p1->p_cred->p_ruid;
208df8bae1dSRodney W. Grimes 	if ((nprocs >= maxproc - 1 && uid != 0) || nprocs >= maxproc) {
209df8bae1dSRodney W. Grimes 		tablefull("proc");
210df8bae1dSRodney W. Grimes 		return (EAGAIN);
211df8bae1dSRodney W. Grimes 	}
212df8bae1dSRodney W. Grimes 	/*
213ef5dc8a9SJohn Dyson 	 * Increment the nprocs resource before blocking can occur.  There
214ef5dc8a9SJohn Dyson 	 * are hard-limits as to the number of processes that can run.
215ef5dc8a9SJohn Dyson 	 */
216ef5dc8a9SJohn Dyson 	nprocs++;
217ef5dc8a9SJohn Dyson 
218ef5dc8a9SJohn Dyson 	/*
219df8bae1dSRodney W. Grimes 	 * Increment the count of procs running with this uid. Don't allow
220df8bae1dSRodney W. Grimes 	 * a nonprivileged user to exceed their current limit.
221df8bae1dSRodney W. Grimes 	 */
222df8bae1dSRodney W. Grimes 	count = chgproccnt(uid, 1);
223df8bae1dSRodney W. Grimes 	if (uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur) {
224df8bae1dSRodney W. Grimes 		(void)chgproccnt(uid, -1);
225ef5dc8a9SJohn Dyson 		/*
226ef5dc8a9SJohn Dyson 		 * Back out the process count
227ef5dc8a9SJohn Dyson 		 */
228ef5dc8a9SJohn Dyson 		nprocs--;
229df8bae1dSRodney W. Grimes 		return (EAGAIN);
230df8bae1dSRodney W. Grimes 	}
231df8bae1dSRodney W. Grimes 
232df8bae1dSRodney W. Grimes 	/* Allocate new proc. */
2332d8acc0fSJohn Dyson 	newproc = zalloc(proc_zone);
234df8bae1dSRodney W. Grimes 
235df8bae1dSRodney W. Grimes /*
2362c1011f7SJohn Dyson  * Setup linkage for kernel based threading
2372c1011f7SJohn Dyson  */
2382c1011f7SJohn Dyson 	if((flags & RFTHREAD) != 0) {
2392c1011f7SJohn Dyson 		newproc->p_peers = p1->p_peers;
2402c1011f7SJohn Dyson 		p1->p_peers = newproc;
2412c1011f7SJohn Dyson 		newproc->p_leader = p1->p_leader;
2422c1011f7SJohn Dyson 	} else {
2432c1011f7SJohn Dyson 		newproc->p_peers = 0;
2442c1011f7SJohn Dyson 		newproc->p_leader = newproc;
2452c1011f7SJohn Dyson 	}
2462c1011f7SJohn Dyson 
2472c1011f7SJohn Dyson 	newproc->p_wakeup = 0;
2482c1011f7SJohn Dyson 
2492c1011f7SJohn Dyson 	/*
250df8bae1dSRodney W. Grimes 	 * Find an unused process ID.  We remember a range of unused IDs
251df8bae1dSRodney W. Grimes 	 * ready to use (from nextpid+1 through pidchecked-1).
252df8bae1dSRodney W. Grimes 	 */
253df8bae1dSRodney W. Grimes 	nextpid++;
254df8bae1dSRodney W. Grimes retry:
255df8bae1dSRodney W. Grimes 	/*
256df8bae1dSRodney W. Grimes 	 * If the process ID prototype has wrapped around,
257df8bae1dSRodney W. Grimes 	 * restart somewhat above 0, as the low-numbered procs
258df8bae1dSRodney W. Grimes 	 * tend to include daemons that don't exit.
259df8bae1dSRodney W. Grimes 	 */
260df8bae1dSRodney W. Grimes 	if (nextpid >= PID_MAX) {
261df8bae1dSRodney W. Grimes 		nextpid = 100;
262df8bae1dSRodney W. Grimes 		pidchecked = 0;
263df8bae1dSRodney W. Grimes 	}
264df8bae1dSRodney W. Grimes 	if (nextpid >= pidchecked) {
265df8bae1dSRodney W. Grimes 		int doingzomb = 0;
266df8bae1dSRodney W. Grimes 
267df8bae1dSRodney W. Grimes 		pidchecked = PID_MAX;
268df8bae1dSRodney W. Grimes 		/*
269df8bae1dSRodney W. Grimes 		 * Scan the active and zombie procs to check whether this pid
270df8bae1dSRodney W. Grimes 		 * is in use.  Remember the lowest pid that's greater
271df8bae1dSRodney W. Grimes 		 * than nextpid, so we can avoid checking for a while.
272df8bae1dSRodney W. Grimes 		 */
273b75356e1SJeffrey Hsu 		p2 = allproc.lh_first;
274df8bae1dSRodney W. Grimes again:
275b75356e1SJeffrey Hsu 		for (; p2 != 0; p2 = p2->p_list.le_next) {
276df8bae1dSRodney W. Grimes 			while (p2->p_pid == nextpid ||
277643a8daaSDon Lewis 			    p2->p_pgrp->pg_id == nextpid ||
278643a8daaSDon Lewis 			    p2->p_session->s_sid == nextpid) {
279df8bae1dSRodney W. Grimes 				nextpid++;
280df8bae1dSRodney W. Grimes 				if (nextpid >= pidchecked)
281df8bae1dSRodney W. Grimes 					goto retry;
282df8bae1dSRodney W. Grimes 			}
283df8bae1dSRodney W. Grimes 			if (p2->p_pid > nextpid && pidchecked > p2->p_pid)
284df8bae1dSRodney W. Grimes 				pidchecked = p2->p_pid;
285df8bae1dSRodney W. Grimes 			if (p2->p_pgrp->pg_id > nextpid &&
286df8bae1dSRodney W. Grimes 			    pidchecked > p2->p_pgrp->pg_id)
287df8bae1dSRodney W. Grimes 				pidchecked = p2->p_pgrp->pg_id;
288643a8daaSDon Lewis 			if (p2->p_session->s_sid > nextpid &&
289643a8daaSDon Lewis 			    pidchecked > p2->p_session->s_sid)
290643a8daaSDon Lewis 				pidchecked = p2->p_session->s_sid;
291df8bae1dSRodney W. Grimes 		}
292df8bae1dSRodney W. Grimes 		if (!doingzomb) {
293df8bae1dSRodney W. Grimes 			doingzomb = 1;
294b75356e1SJeffrey Hsu 			p2 = zombproc.lh_first;
295df8bae1dSRodney W. Grimes 			goto again;
296df8bae1dSRodney W. Grimes 		}
297df8bae1dSRodney W. Grimes 	}
298df8bae1dSRodney W. Grimes 
299df8bae1dSRodney W. Grimes 	p2 = newproc;
300b75356e1SJeffrey Hsu 	p2->p_stat = SIDL;			/* protect against others */
301b75356e1SJeffrey Hsu 	p2->p_pid = nextpid;
302b75356e1SJeffrey Hsu 	LIST_INSERT_HEAD(&allproc, p2, p_list);
303b75356e1SJeffrey Hsu 	LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
304df8bae1dSRodney W. Grimes 
305df8bae1dSRodney W. Grimes 	/*
306df8bae1dSRodney W. Grimes 	 * Make a proc table entry for the new process.
307df8bae1dSRodney W. Grimes 	 * Start by zeroing the section of proc that is zero-initialized,
308df8bae1dSRodney W. Grimes 	 * then copy the section that is copied directly from the parent.
309df8bae1dSRodney W. Grimes 	 */
310df8bae1dSRodney W. Grimes 	bzero(&p2->p_startzero,
311df8bae1dSRodney W. Grimes 	    (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
312df8bae1dSRodney W. Grimes 	bcopy(&p1->p_startcopy, &p2->p_startcopy,
313df8bae1dSRodney W. Grimes 	    (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
314df8bae1dSRodney W. Grimes 
3152244ea07SJohn Dyson 	p2->p_aioinfo = NULL;
3162244ea07SJohn Dyson 
317df8bae1dSRodney W. Grimes 	/*
318df8bae1dSRodney W. Grimes 	 * Duplicate sub-structures as needed.
319df8bae1dSRodney W. Grimes 	 * Increase reference counts on shared objects.
320df8bae1dSRodney W. Grimes 	 * The p_stats and p_sigacts substructs are set in vm_fork.
321df8bae1dSRodney W. Grimes 	 */
322df8bae1dSRodney W. Grimes 	p2->p_flag = P_INMEM;
323df8bae1dSRodney W. Grimes 	if (p1->p_flag & P_PROFIL)
324df8bae1dSRodney W. Grimes 		startprofclock(p2);
325df8bae1dSRodney W. Grimes 	MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
326df8bae1dSRodney W. Grimes 	    M_SUBPROC, M_WAITOK);
327df8bae1dSRodney W. Grimes 	bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
328df8bae1dSRodney W. Grimes 	p2->p_cred->p_refcnt = 1;
329df8bae1dSRodney W. Grimes 	crhold(p1->p_ucred);
330df8bae1dSRodney W. Grimes 
3316626c604SJulian Elischer 	if (flags & RFSIGSHARE) {
332dc9c271aSJulian Elischer 		p2->p_procsig = p1->p_procsig;
3336626c604SJulian Elischer 		p2->p_procsig->ps_refcnt++;
334dc9c271aSJulian Elischer 		if (p1->p_sigacts == &p1->p_addr->u_sigacts) {
335dc9c271aSJulian Elischer 			struct sigacts *newsigacts;
336dc9c271aSJulian Elischer 			int s;
337dc9c271aSJulian Elischer 
338dc9c271aSJulian Elischer 			if (p2->p_procsig->ps_refcnt != 2)
339dc9c271aSJulian Elischer 				printf ("PID:%d Creating shared sigacts with procsig->ps_refcnt %d\n",
340dc9c271aSJulian Elischer 					p2->p_pid, p2->p_procsig->ps_refcnt);
341dc9c271aSJulian Elischer 			/* Create the shared sigacts structure */
342dc9c271aSJulian Elischer 			MALLOC (newsigacts, struct sigacts *, sizeof (struct sigacts),
343dc9c271aSJulian Elischer 				M_SUBPROC, M_WAITOK);
344dc9c271aSJulian Elischer 			s = splhigh();
345dc9c271aSJulian Elischer 			/* Set p_sigacts to the new shared structure.  Note that this
346dc9c271aSJulian Elischer 			 * is updating p1->p_sigacts at the same time, since p_sigacts
347dc9c271aSJulian Elischer 			 * is just a pointer to the shared p_procsig->ps_sigacts.
348dc9c271aSJulian Elischer 			 */
349dc9c271aSJulian Elischer 			p2->p_sigacts  = newsigacts;
350dc9c271aSJulian Elischer 			/* Copy in the values from the u area */
351dc9c271aSJulian Elischer 			*p2->p_sigacts = p1->p_addr->u_sigacts;
352dc9c271aSJulian Elischer 			splx (s);
353dc9c271aSJulian Elischer 		}
3546626c604SJulian Elischer 	} else {
355dc9c271aSJulian Elischer 		MALLOC (p2->p_procsig, struct procsig *, sizeof(struct procsig),
356dc9c271aSJulian Elischer 			M_SUBPROC, M_WAITOK);
3576626c604SJulian Elischer 		bcopy(&p1->p_procsig->ps_begincopy, &p2->p_procsig->ps_begincopy,
3586626c604SJulian Elischer 			(unsigned)&p1->p_procsig->ps_endcopy -
3596626c604SJulian Elischer 			(unsigned)&p1->p_procsig->ps_begincopy);
360dc9c271aSJulian Elischer 		p2->p_procsig->ps_refcnt = 1;
361dc9c271aSJulian Elischer 		/* Note that we fill in the values of sigacts in vm_fork */
362dc9c271aSJulian Elischer 		p2->p_sigacts = NULL;
3636626c604SJulian Elischer 	}
3644ac9ae70SJulian Elischer 	if (flags & RFLINUXTHPN)
3656626c604SJulian Elischer 	        p2->p_sigparent = SIGUSR1;
3664ac9ae70SJulian Elischer 	else
3674ac9ae70SJulian Elischer 	        p2->p_sigparent = SIGCHLD;
36888c5ea45SJulian Elischer 
369df8bae1dSRodney W. Grimes 	/* bump references to the text vnode (for procfs) */
370df8bae1dSRodney W. Grimes 	p2->p_textvp = p1->p_textvp;
371df8bae1dSRodney W. Grimes 	if (p2->p_textvp)
372df8bae1dSRodney W. Grimes 		VREF(p2->p_textvp);
373df8bae1dSRodney W. Grimes 
3740e3eb7eeSSujal Patel 	if (flags & RFCFDG)
375dabee6feSPeter Wemm 		p2->p_fd = fdinit(p1);
3760e3eb7eeSSujal Patel 	else if (flags & RFFDG)
377df8bae1dSRodney W. Grimes 		p2->p_fd = fdcopy(p1);
378dabee6feSPeter Wemm 	else
379dabee6feSPeter Wemm 		p2->p_fd = fdshare(p1);
380dabee6feSPeter Wemm 
381df8bae1dSRodney W. Grimes 	/*
382df8bae1dSRodney W. Grimes 	 * If p_limit is still copy-on-write, bump refcnt,
383df8bae1dSRodney W. Grimes 	 * otherwise get a copy that won't be modified.
384df8bae1dSRodney W. Grimes 	 * (If PL_SHAREMOD is clear, the structure is shared
385df8bae1dSRodney W. Grimes 	 * copy-on-write.)
386df8bae1dSRodney W. Grimes 	 */
387df8bae1dSRodney W. Grimes 	if (p1->p_limit->p_lflags & PL_SHAREMOD)
388df8bae1dSRodney W. Grimes 		p2->p_limit = limcopy(p1->p_limit);
389df8bae1dSRodney W. Grimes 	else {
390df8bae1dSRodney W. Grimes 		p2->p_limit = p1->p_limit;
391df8bae1dSRodney W. Grimes 		p2->p_limit->p_refcnt++;
392df8bae1dSRodney W. Grimes 	}
393df8bae1dSRodney W. Grimes 
39470e534e7SDavid Greenman 	/*
395be67169aSBruce Evans 	 * Preserve some more flags in subprocess.  P_PROFIL has already
396be67169aSBruce Evans 	 * been preserved.
39770e534e7SDavid Greenman 	 */
39870e534e7SDavid Greenman 	p2->p_flag |= p1->p_flag & P_SUGID;
399df8bae1dSRodney W. Grimes 	if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
400df8bae1dSRodney W. Grimes 		p2->p_flag |= P_CONTROLT;
4010e3eb7eeSSujal Patel 	if (flags & RFPPWAIT)
402df8bae1dSRodney W. Grimes 		p2->p_flag |= P_PPWAIT;
403be67169aSBruce Evans 
404b75356e1SJeffrey Hsu 	LIST_INSERT_AFTER(p1, p2, p_pglist);
4050e3eb7eeSSujal Patel 
4060e3eb7eeSSujal Patel 	/*
4070e3eb7eeSSujal Patel 	 * Attach the new process to its parent.
4080e3eb7eeSSujal Patel 	 *
4090e3eb7eeSSujal Patel 	 * If RFNOWAIT is set, the newly created process becomes a child
4100e3eb7eeSSujal Patel 	 * of init.  This effectively disassociates the child from the
4110e3eb7eeSSujal Patel 	 * parent.
4120e3eb7eeSSujal Patel 	 */
4130e3eb7eeSSujal Patel 	if (flags & RFNOWAIT)
4140e3eb7eeSSujal Patel 		pptr = initproc;
4150e3eb7eeSSujal Patel 	else
4160e3eb7eeSSujal Patel 		pptr = p1;
4170e3eb7eeSSujal Patel 	p2->p_pptr = pptr;
4180e3eb7eeSSujal Patel 	LIST_INSERT_HEAD(&pptr->p_children, p2, p_sibling);
419b75356e1SJeffrey Hsu 	LIST_INIT(&p2->p_children);
420b75356e1SJeffrey Hsu 
421df8bae1dSRodney W. Grimes #ifdef KTRACE
422df8bae1dSRodney W. Grimes 	/*
423df8bae1dSRodney W. Grimes 	 * Copy traceflag and tracefile if enabled.
424df8bae1dSRodney W. Grimes 	 * If not inherited, these were zeroed above.
425df8bae1dSRodney W. Grimes 	 */
426df8bae1dSRodney W. Grimes 	if (p1->p_traceflag&KTRFAC_INHERIT) {
427df8bae1dSRodney W. Grimes 		p2->p_traceflag = p1->p_traceflag;
428df8bae1dSRodney W. Grimes 		if ((p2->p_tracep = p1->p_tracep) != NULL)
429df8bae1dSRodney W. Grimes 			VREF(p2->p_tracep);
430df8bae1dSRodney W. Grimes 	}
431df8bae1dSRodney W. Grimes #endif
432df8bae1dSRodney W. Grimes 
433df8bae1dSRodney W. Grimes 	/*
4340d2afceeSDavid Greenman 	 * set priority of child to be that of parent
4350d2afceeSDavid Greenman 	 */
4360d2afceeSDavid Greenman 	p2->p_estcpu = p1->p_estcpu;
4370d2afceeSDavid Greenman 
4380d2afceeSDavid Greenman 	/*
439df8bae1dSRodney W. Grimes 	 * This begins the section where we must prevent the parent
440df8bae1dSRodney W. Grimes 	 * from being swapped.
441df8bae1dSRodney W. Grimes 	 */
442af8ad83eSPeter Wemm 	PHOLD(p1);
4430d2afceeSDavid Greenman 
444df8bae1dSRodney W. Grimes 	/*
445a2a1c95cSPeter Wemm 	 * Finish creating the child process.  It will return via a different
446a2a1c95cSPeter Wemm 	 * execution path later.  (ie: directly into user mode)
447dabee6feSPeter Wemm 	 */
448a2a1c95cSPeter Wemm 	vm_fork(p1, p2, flags);
449df8bae1dSRodney W. Grimes 
450df8bae1dSRodney W. Grimes 	/*
451e0d898b4SJulian Elischer 	 * Both processes are set up, now check if any LKMs want
452e0d898b4SJulian Elischer 	 * to adjust anything.
453fed06968SJulian Elischer 	 *   What if they have an error? XXX
454fed06968SJulian Elischer 	 */
455fed06968SJulian Elischer 	while (ep) {
456fed06968SJulian Elischer 		(*ep->function)(p1, p2, flags);
457fed06968SJulian Elischer 		ep = ep->next;
458fed06968SJulian Elischer 	}
459fed06968SJulian Elischer 
460fed06968SJulian Elischer 	/*
461df8bae1dSRodney W. Grimes 	 * Make child runnable and add to run queue.
462df8bae1dSRodney W. Grimes 	 */
463a2a1c95cSPeter Wemm 	microtime(&(p2->p_stats->p_start));
464a2a1c95cSPeter Wemm 	p2->p_acflag = AFORK;
465df8bae1dSRodney W. Grimes 	(void) splhigh();
466df8bae1dSRodney W. Grimes 	p2->p_stat = SRUN;
467df8bae1dSRodney W. Grimes 	setrunqueue(p2);
468df8bae1dSRodney W. Grimes 	(void) spl0();
469df8bae1dSRodney W. Grimes 
470df8bae1dSRodney W. Grimes 	/*
471df8bae1dSRodney W. Grimes 	 * Now can be swapped.
472df8bae1dSRodney W. Grimes 	 */
473af8ad83eSPeter Wemm 	PRELE(p1);
474df8bae1dSRodney W. Grimes 
475df8bae1dSRodney W. Grimes 	/*
476df8bae1dSRodney W. Grimes 	 * Preserve synchronization semantics of vfork.  If waiting for
477df8bae1dSRodney W. Grimes 	 * child to exec or exit, set P_PPWAIT on child, and sleep on our
478df8bae1dSRodney W. Grimes 	 * proc (in case of exit).
479df8bae1dSRodney W. Grimes 	 */
480df8bae1dSRodney W. Grimes 	while (p2->p_flag & P_PPWAIT)
481df8bae1dSRodney W. Grimes 		tsleep(p1, PWAIT, "ppwait", 0);
482df8bae1dSRodney W. Grimes 
483df8bae1dSRodney W. Grimes 	/*
484df8bae1dSRodney W. Grimes 	 * Return child pid to parent process,
485be67169aSBruce Evans 	 * marking us as parent via p1->p_retval[1].
486df8bae1dSRodney W. Grimes 	 */
487be67169aSBruce Evans 	p1->p_retval[0] = p2->p_pid;
488be67169aSBruce Evans 	p1->p_retval[1] = 0;
489df8bae1dSRodney W. Grimes 	return (0);
490df8bae1dSRodney W. Grimes }
491fed06968SJulian Elischer 
492e0d898b4SJulian Elischer /*
493e0d898b4SJulian Elischer  * The next two functionms are general routines to handle adding/deleting
494e0d898b4SJulian Elischer  * items on the fork callout list.
495e0d898b4SJulian Elischer  *
496e0d898b4SJulian Elischer  * at_fork():
497e0d898b4SJulian Elischer  * Take the arguments given and put them onto the fork callout list,
498fed06968SJulian Elischer  * However first make sure that it's not already there.
499e0d898b4SJulian Elischer  * Returns 0 on success or a standard error number.
500fed06968SJulian Elischer  */
501fed06968SJulian Elischer int
502eb776aeaSBruce Evans at_fork(function)
503eb776aeaSBruce Evans 	forklist_fn function;
504fed06968SJulian Elischer {
505fed06968SJulian Elischer 	fle_p ep;
506e0d898b4SJulian Elischer 
507e0d898b4SJulian Elischer 	/* let the programmer know if he's been stupid */
508e0d898b4SJulian Elischer 	if (rm_at_fork(function))
509fed06968SJulian Elischer 		printf("fork callout entry already present\n");
510fed06968SJulian Elischer 	ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
511e0d898b4SJulian Elischer 	if (ep == NULL)
512e0d898b4SJulian Elischer 		return (ENOMEM);
513fed06968SJulian Elischer 	ep->next = fork_list;
514fed06968SJulian Elischer 	ep->function = function;
515fed06968SJulian Elischer 	fork_list = ep;
516e0d898b4SJulian Elischer 	return (0);
517fed06968SJulian Elischer }
518e0d898b4SJulian Elischer 
519fed06968SJulian Elischer /*
520fed06968SJulian Elischer  * Scan the exit callout list for the given items and remove them.
521fed06968SJulian Elischer  * Returns the number of items removed.
522e0d898b4SJulian Elischer  * Theoretically this value can only be 0 or 1.
523fed06968SJulian Elischer  */
524fed06968SJulian Elischer int
525eb776aeaSBruce Evans rm_at_fork(function)
526eb776aeaSBruce Evans 	forklist_fn function;
527fed06968SJulian Elischer {
528fed06968SJulian Elischer 	fle_p *epp, ep;
529e0d898b4SJulian Elischer 	int count;
530fed06968SJulian Elischer 
531e0d898b4SJulian Elischer 	count= 0;
532fed06968SJulian Elischer 	epp = &fork_list;
533fed06968SJulian Elischer 	ep = *epp;
534fed06968SJulian Elischer 	while (ep) {
535fed06968SJulian Elischer 		if (ep->function == function) {
536fed06968SJulian Elischer 			*epp = ep->next;
537fed06968SJulian Elischer 			free(ep, M_TEMP);
538fed06968SJulian Elischer 			count++;
539fed06968SJulian Elischer 		} else {
540fed06968SJulian Elischer 			epp = &ep->next;
541fed06968SJulian Elischer 		}
542fed06968SJulian Elischer 		ep = *epp;
543fed06968SJulian Elischer 	}
544e0d898b4SJulian Elischer 	return (count);
545fed06968SJulian Elischer }
546