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 39c3aac50fSPeter Wemm * $FreeBSD$ 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> 5135e0e5b3SJohn Baldwin #include <sys/mutex.h> 52df8bae1dSRodney W. Grimes #include <sys/proc.h> 53df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 54a7b124c3SJohn Baldwin #include <sys/syscall.h> 55df8bae1dSRodney W. Grimes #include <sys/vnode.h> 56df8bae1dSRodney W. Grimes #include <sys/acct.h> 570384fff8SJason Evans #include <sys/ktr.h> 58df8bae1dSRodney W. Grimes #include <sys/ktrace.h> 59a7b124c3SJohn Baldwin #include <sys/kthread.h> 60b71fec07SBruce Evans #include <sys/unistd.h> 6175c13541SPoul-Henning Kamp #include <sys/jail.h> 6257934cd3SJohn Baldwin #include <sys/sx.h> 63df8bae1dSRodney W. Grimes 64d93f860cSPoul-Henning Kamp #include <vm/vm.h> 65996c772fSJohn Dyson #include <sys/lock.h> 66dabee6feSPeter Wemm #include <vm/pmap.h> 67dabee6feSPeter Wemm #include <vm/vm_map.h> 68efeaf95aSDavid Greenman #include <vm/vm_extern.h> 692d8acc0fSJohn Dyson #include <vm/vm_zone.h> 70d93f860cSPoul-Henning Kamp 715d22597fSHajimu UMEMOTO #include <sys/vmmeter.h> 72dc9c271aSJulian Elischer #include <sys/user.h> 7388c5ea45SJulian Elischer 7493efcae8SPoul-Henning Kamp static MALLOC_DEFINE(M_ATFORK, "atfork", "atfork callback"); 7593efcae8SPoul-Henning Kamp 76be67169aSBruce Evans static int fast_vfork = 1; 7747fdd692SNeil Blakey-Milner SYSCTL_INT(_kern, OID_AUTO, fast_vfork, CTLFLAG_RW, &fast_vfork, 0, 7847fdd692SNeil Blakey-Milner "flag to indicate whether we have a fast vfork()"); 79c76e95c3SPeter Wemm 80fed06968SJulian Elischer /* 81e0d898b4SJulian Elischer * These are the stuctures used to create a callout list for things to do 82e0d898b4SJulian Elischer * when forking a process 83fed06968SJulian Elischer */ 8493efcae8SPoul-Henning Kamp struct forklist { 85fed06968SJulian Elischer forklist_fn function; 86e3975643SJake Burkholder TAILQ_ENTRY(forklist) next; 8793efcae8SPoul-Henning Kamp }; 88fed06968SJulian Elischer 8957934cd3SJohn Baldwin static struct sx fork_list_lock; 9057934cd3SJohn Baldwin 91e3975643SJake Burkholder TAILQ_HEAD(forklist_head, forklist); 9293efcae8SPoul-Henning Kamp static struct forklist_head fork_list = TAILQ_HEAD_INITIALIZER(fork_list); 93fed06968SJulian Elischer 94d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 95ad7507e2SSteven Wallace struct fork_args { 96ad7507e2SSteven Wallace int dummy; 97ad7507e2SSteven Wallace }; 98d2d3e875SBruce Evans #endif 99ad7507e2SSteven Wallace 10057934cd3SJohn Baldwin static void 10157934cd3SJohn Baldwin init_fork_list(void *data __unused) 10257934cd3SJohn Baldwin { 10357934cd3SJohn Baldwin 10457934cd3SJohn Baldwin sx_init(&fork_list_lock, "fork list"); 10557934cd3SJohn Baldwin } 10657934cd3SJohn Baldwin SYSINIT(fork_list, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_fork_list, NULL); 10757934cd3SJohn Baldwin 108df8bae1dSRodney W. Grimes /* ARGSUSED */ 10926f9a767SRodney W. Grimes int 110cb226aaaSPoul-Henning Kamp fork(p, uap) 111df8bae1dSRodney W. Grimes struct proc *p; 112df8bae1dSRodney W. Grimes struct fork_args *uap; 113df8bae1dSRodney W. Grimes { 114df8abd0bSPeter Wemm int error; 115df8abd0bSPeter Wemm struct proc *p2; 116be67169aSBruce Evans 117df8abd0bSPeter Wemm error = fork1(p, RFFDG | RFPROC, &p2); 118df8abd0bSPeter Wemm if (error == 0) { 119df8abd0bSPeter Wemm p->p_retval[0] = p2->p_pid; 120df8abd0bSPeter Wemm p->p_retval[1] = 0; 121df8abd0bSPeter Wemm } 122df8abd0bSPeter Wemm return error; 123df8bae1dSRodney W. Grimes } 124df8bae1dSRodney W. Grimes 125df8bae1dSRodney W. Grimes /* ARGSUSED */ 12626f9a767SRodney W. Grimes int 127cb226aaaSPoul-Henning Kamp vfork(p, uap) 128df8bae1dSRodney W. Grimes struct proc *p; 129dabee6feSPeter Wemm struct vfork_args *uap; 130df8bae1dSRodney W. Grimes { 131df8abd0bSPeter Wemm int error; 132df8abd0bSPeter Wemm struct proc *p2; 133be67169aSBruce Evans 134df8abd0bSPeter Wemm error = fork1(p, RFFDG | RFPROC | RFPPWAIT | RFMEM, &p2); 135df8abd0bSPeter Wemm if (error == 0) { 136df8abd0bSPeter Wemm p->p_retval[0] = p2->p_pid; 137df8abd0bSPeter Wemm p->p_retval[1] = 0; 138df8abd0bSPeter Wemm } 139df8abd0bSPeter Wemm return error; 140df8bae1dSRodney W. Grimes } 141df8bae1dSRodney W. Grimes 142dabee6feSPeter Wemm int 143cb226aaaSPoul-Henning Kamp rfork(p, uap) 144dabee6feSPeter Wemm struct proc *p; 145dabee6feSPeter Wemm struct rfork_args *uap; 146dabee6feSPeter Wemm { 147df8abd0bSPeter Wemm int error; 148df8abd0bSPeter Wemm struct proc *p2; 149be67169aSBruce Evans 1500384fff8SJason Evans /* mask kernel only flags out of the user flags */ 1510384fff8SJason Evans error = fork1(p, uap->flags & ~RFKERNELONLY, &p2); 152df8abd0bSPeter Wemm if (error == 0) { 1531943af61SPeter Wemm p->p_retval[0] = p2 ? p2->p_pid : 0; 154df8abd0bSPeter Wemm p->p_retval[1] = 0; 155df8abd0bSPeter Wemm } 156df8abd0bSPeter Wemm return error; 157dabee6feSPeter Wemm } 158dabee6feSPeter Wemm 159dabee6feSPeter Wemm 160df8bae1dSRodney W. Grimes int nprocs = 1; /* process 0 */ 16151068190SWolfram Schneider static int nextpid = 0; 162d941d475SRobert Watson SYSCTL_INT(_kern, OID_AUTO, lastpid, CTLFLAG_RD, &nextpid, 0, 163d941d475SRobert Watson "Last used PID"); 164df8bae1dSRodney W. Grimes 165bb6a234eSPeter Wemm /* 166bb6a234eSPeter Wemm * Random component to nextpid generation. We mix in a random factor to make 167bb6a234eSPeter Wemm * it a little harder to predict. We sanity check the modulus value to avoid 168bb6a234eSPeter Wemm * doing it in critical paths. Don't let it be too small or we pointlessly 169bb6a234eSPeter Wemm * waste randomness entropy, and don't let it be impossibly large. Using a 170bb6a234eSPeter Wemm * modulus that is too big causes a LOT more process table scans and slows 171bb6a234eSPeter Wemm * down fork processing as the pidchecked caching is defeated. 172bb6a234eSPeter Wemm */ 173ee3fd601SDan Moschuk static int randompid = 0; 174bb6a234eSPeter Wemm 175bb6a234eSPeter Wemm static int 17682d9ae4eSPoul-Henning Kamp sysctl_kern_randompid(SYSCTL_HANDLER_ARGS) 177bb6a234eSPeter Wemm { 178bb6a234eSPeter Wemm int error, pid; 179bb6a234eSPeter Wemm 180bb6a234eSPeter Wemm pid = randompid; 181bb6a234eSPeter Wemm error = sysctl_handle_int(oidp, &pid, 0, req); 182bb6a234eSPeter Wemm if (error || !req->newptr) 183bb6a234eSPeter Wemm return (error); 184bb6a234eSPeter Wemm if (pid < 0 || pid > PID_MAX - 100) /* out of range */ 185bb6a234eSPeter Wemm pid = PID_MAX - 100; 186bb6a234eSPeter Wemm else if (pid < 2) /* NOP */ 187bb6a234eSPeter Wemm pid = 0; 188bb6a234eSPeter Wemm else if (pid < 100) /* Make it reasonable */ 189bb6a234eSPeter Wemm pid = 100; 190bb6a234eSPeter Wemm randompid = pid; 191bb6a234eSPeter Wemm return (error); 192bb6a234eSPeter Wemm } 193bb6a234eSPeter Wemm 194bb6a234eSPeter Wemm SYSCTL_PROC(_kern, OID_AUTO, randompid, CTLTYPE_INT|CTLFLAG_RW, 195bb6a234eSPeter Wemm 0, 0, sysctl_kern_randompid, "I", "Random PID modulus"); 196ee3fd601SDan Moschuk 19774b2192aSJohn Dyson int 198df8abd0bSPeter Wemm fork1(p1, flags, procp) 1990384fff8SJason Evans struct proc *p1; /* parent proc */ 2000e3eb7eeSSujal Patel int flags; 2010384fff8SJason Evans struct proc **procp; /* child proc */ 202df8bae1dSRodney W. Grimes { 203df8abd0bSPeter Wemm struct proc *p2, *pptr; 204df8abd0bSPeter Wemm uid_t uid; 205df8bae1dSRodney W. Grimes struct proc *newproc; 2060384fff8SJason Evans int trypid; 207c6362551SAlfred Perlstein int ok; 20851068190SWolfram Schneider static int pidchecked = 0; 20993efcae8SPoul-Henning Kamp struct forklist *ep; 2105641ae5dSJohn Baldwin struct filedesc *fd; 2115856e12eSJohn Dyson 2120384fff8SJason Evans /* Can't copy and clear */ 2130e3eb7eeSSujal Patel if ((flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) 214dabee6feSPeter Wemm return (EINVAL); 215df8bae1dSRodney W. Grimes 216df8bae1dSRodney W. Grimes /* 2175856e12eSJohn Dyson * Here we don't create a new process, but we divorce 2185856e12eSJohn Dyson * certain parts of a process from itself. 2195856e12eSJohn Dyson */ 2205856e12eSJohn Dyson if ((flags & RFPROC) == 0) { 2215856e12eSJohn Dyson 22291c28bfdSLuoqi Chen vm_fork(p1, 0, flags); 2235856e12eSJohn Dyson 2245856e12eSJohn Dyson /* 2255856e12eSJohn Dyson * Close all file descriptors. 2265856e12eSJohn Dyson */ 2275856e12eSJohn Dyson if (flags & RFCFDG) { 2285856e12eSJohn Dyson struct filedesc *fdtmp; 2295856e12eSJohn Dyson fdtmp = fdinit(p1); 2305641ae5dSJohn Baldwin PROC_LOCK(p1); 2315856e12eSJohn Dyson fdfree(p1); 2325856e12eSJohn Dyson p1->p_fd = fdtmp; 2335641ae5dSJohn Baldwin PROC_UNLOCK(p1); 2345856e12eSJohn Dyson } 2355856e12eSJohn Dyson 2365856e12eSJohn Dyson /* 2375856e12eSJohn Dyson * Unshare file descriptors (from parent.) 2385856e12eSJohn Dyson */ 2395856e12eSJohn Dyson if (flags & RFFDG) { 2405856e12eSJohn Dyson if (p1->p_fd->fd_refcnt > 1) { 2415856e12eSJohn Dyson struct filedesc *newfd; 2425856e12eSJohn Dyson newfd = fdcopy(p1); 2435641ae5dSJohn Baldwin PROC_LOCK(p1); 2445856e12eSJohn Dyson fdfree(p1); 2455856e12eSJohn Dyson p1->p_fd = newfd; 2465641ae5dSJohn Baldwin PROC_UNLOCK(p1); 2475856e12eSJohn Dyson } 2485856e12eSJohn Dyson } 2491943af61SPeter Wemm *procp = NULL; 2505856e12eSJohn Dyson return (0); 2515856e12eSJohn Dyson } 2525856e12eSJohn Dyson 2535856e12eSJohn Dyson /* 254df8bae1dSRodney W. Grimes * Although process entries are dynamically created, we still keep 255df8bae1dSRodney W. Grimes * a global limit on the maximum number we will create. Don't allow 256df8bae1dSRodney W. Grimes * a nonprivileged user to use the last process; don't let root 257df8bae1dSRodney W. Grimes * exceed the limit. The variable nprocs is the current number of 258df8bae1dSRodney W. Grimes * processes, maxproc is the limit. 259df8bae1dSRodney W. Grimes */ 260df8bae1dSRodney W. Grimes uid = p1->p_cred->p_ruid; 261df8bae1dSRodney W. Grimes if ((nprocs >= maxproc - 1 && uid != 0) || nprocs >= maxproc) { 262df8bae1dSRodney W. Grimes tablefull("proc"); 263df8bae1dSRodney W. Grimes return (EAGAIN); 264df8bae1dSRodney W. Grimes } 265df8bae1dSRodney W. Grimes /* 266ef5dc8a9SJohn Dyson * Increment the nprocs resource before blocking can occur. There 267ef5dc8a9SJohn Dyson * are hard-limits as to the number of processes that can run. 268ef5dc8a9SJohn Dyson */ 269ef5dc8a9SJohn Dyson nprocs++; 270ef5dc8a9SJohn Dyson 271ef5dc8a9SJohn Dyson /* 272df8bae1dSRodney W. Grimes * Increment the count of procs running with this uid. Don't allow 273df8bae1dSRodney W. Grimes * a nonprivileged user to exceed their current limit. 274df8bae1dSRodney W. Grimes */ 275f535380cSDon Lewis ok = chgproccnt(p1->p_cred->p_uidinfo, 1, 27642fd51ceSDon Lewis (uid != 0) ? p1->p_rlimit[RLIMIT_NPROC].rlim_cur : 0); 27742fd51ceSDon Lewis if (!ok) { 278ef5dc8a9SJohn Dyson /* 279ef5dc8a9SJohn Dyson * Back out the process count 280ef5dc8a9SJohn Dyson */ 281ef5dc8a9SJohn Dyson nprocs--; 282df8bae1dSRodney W. Grimes return (EAGAIN); 283df8bae1dSRodney W. Grimes } 284df8bae1dSRodney W. Grimes 285df8bae1dSRodney W. Grimes /* Allocate new proc. */ 2862d8acc0fSJohn Dyson newproc = zalloc(proc_zone); 287df8bae1dSRodney W. Grimes 288df8bae1dSRodney W. Grimes /* 2892c1011f7SJohn Dyson * Setup linkage for kernel based threading 2902c1011f7SJohn Dyson */ 2912c1011f7SJohn Dyson if((flags & RFTHREAD) != 0) { 2922c1011f7SJohn Dyson newproc->p_peers = p1->p_peers; 2932c1011f7SJohn Dyson p1->p_peers = newproc; 2942c1011f7SJohn Dyson newproc->p_leader = p1->p_leader; 2952c1011f7SJohn Dyson } else { 296a7b124c3SJohn Baldwin newproc->p_peers = NULL; 2972c1011f7SJohn Dyson newproc->p_leader = newproc; 2982c1011f7SJohn Dyson } 2992c1011f7SJohn Dyson 300d4da2dbaSAlan Cox newproc->p_vmspace = NULL; 301d4da2dbaSAlan Cox 3022c1011f7SJohn Dyson /* 303df8bae1dSRodney W. Grimes * Find an unused process ID. We remember a range of unused IDs 304df8bae1dSRodney W. Grimes * ready to use (from nextpid+1 through pidchecked-1). 3050384fff8SJason Evans * 3060384fff8SJason Evans * If RFHIGHPID is set (used during system boot), do not allocate 3070384fff8SJason Evans * low-numbered pids. 308df8bae1dSRodney W. Grimes */ 309c0c25570SJake Burkholder ALLPROC_LOCK(AP_EXCLUSIVE); 3100384fff8SJason Evans trypid = nextpid + 1; 3110384fff8SJason Evans if (flags & RFHIGHPID) { 3120384fff8SJason Evans if (trypid < 10) { 3130384fff8SJason Evans trypid = 10; 3140384fff8SJason Evans } 3150384fff8SJason Evans } else { 316bb6a234eSPeter Wemm if (randompid) 3170384fff8SJason Evans trypid += arc4random() % randompid; 3180384fff8SJason Evans } 319df8bae1dSRodney W. Grimes retry: 320df8bae1dSRodney W. Grimes /* 321df8bae1dSRodney W. Grimes * If the process ID prototype has wrapped around, 322df8bae1dSRodney W. Grimes * restart somewhat above 0, as the low-numbered procs 323df8bae1dSRodney W. Grimes * tend to include daemons that don't exit. 324df8bae1dSRodney W. Grimes */ 3250384fff8SJason Evans if (trypid >= PID_MAX) { 3260384fff8SJason Evans trypid = trypid % PID_MAX; 3270384fff8SJason Evans if (trypid < 100) 3280384fff8SJason Evans trypid += 100; 329df8bae1dSRodney W. Grimes pidchecked = 0; 330df8bae1dSRodney W. Grimes } 3310384fff8SJason Evans if (trypid >= pidchecked) { 332df8bae1dSRodney W. Grimes int doingzomb = 0; 333df8bae1dSRodney W. Grimes 334df8bae1dSRodney W. Grimes pidchecked = PID_MAX; 335df8bae1dSRodney W. Grimes /* 336df8bae1dSRodney W. Grimes * Scan the active and zombie procs to check whether this pid 337df8bae1dSRodney W. Grimes * is in use. Remember the lowest pid that's greater 3380384fff8SJason Evans * than trypid, so we can avoid checking for a while. 339df8bae1dSRodney W. Grimes */ 3402e3c8fcbSPoul-Henning Kamp p2 = LIST_FIRST(&allproc); 341df8bae1dSRodney W. Grimes again: 342a7b124c3SJohn Baldwin for (; p2 != NULL; p2 = LIST_NEXT(p2, p_list)) { 3430384fff8SJason Evans while (p2->p_pid == trypid || 3440384fff8SJason Evans p2->p_pgrp->pg_id == trypid || 3450384fff8SJason Evans p2->p_session->s_sid == trypid) { 3460384fff8SJason Evans trypid++; 3470384fff8SJason Evans if (trypid >= pidchecked) 348df8bae1dSRodney W. Grimes goto retry; 349df8bae1dSRodney W. Grimes } 3500384fff8SJason Evans if (p2->p_pid > trypid && pidchecked > p2->p_pid) 351df8bae1dSRodney W. Grimes pidchecked = p2->p_pid; 3520384fff8SJason Evans if (p2->p_pgrp->pg_id > trypid && 353df8bae1dSRodney W. Grimes pidchecked > p2->p_pgrp->pg_id) 354df8bae1dSRodney W. Grimes pidchecked = p2->p_pgrp->pg_id; 3550384fff8SJason Evans if (p2->p_session->s_sid > trypid && 356643a8daaSDon Lewis pidchecked > p2->p_session->s_sid) 357643a8daaSDon Lewis pidchecked = p2->p_session->s_sid; 358df8bae1dSRodney W. Grimes } 359df8bae1dSRodney W. Grimes if (!doingzomb) { 360df8bae1dSRodney W. Grimes doingzomb = 1; 3612e3c8fcbSPoul-Henning Kamp p2 = LIST_FIRST(&zombproc); 362df8bae1dSRodney W. Grimes goto again; 363df8bae1dSRodney W. Grimes } 364df8bae1dSRodney W. Grimes } 365df8bae1dSRodney W. Grimes 366df8bae1dSRodney W. Grimes /* 3670384fff8SJason Evans * RFHIGHPID does not mess with the nextpid counter during boot. 3680384fff8SJason Evans */ 3690384fff8SJason Evans if (flags & RFHIGHPID) 3700384fff8SJason Evans pidchecked = 0; 3710384fff8SJason Evans else 3720384fff8SJason Evans nextpid = trypid; 3730384fff8SJason Evans 374553629ebSJake Burkholder p2 = newproc; 375a448b62aSJake Burkholder p2->p_intr_nesting_level = 0; 376553629ebSJake Burkholder p2->p_stat = SIDL; /* protect against others */ 377553629ebSJake Burkholder p2->p_pid = trypid; 378553629ebSJake Burkholder LIST_INSERT_HEAD(&allproc, p2, p_list); 379553629ebSJake Burkholder LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash); 380c0c25570SJake Burkholder ALLPROC_LOCK(AP_RELEASE); 381553629ebSJake Burkholder 3820384fff8SJason Evans /* 383df8bae1dSRodney W. Grimes * Make a proc table entry for the new process. 384df8bae1dSRodney W. Grimes * Start by zeroing the section of proc that is zero-initialized, 385df8bae1dSRodney W. Grimes * then copy the section that is copied directly from the parent. 386df8bae1dSRodney W. Grimes */ 387df8bae1dSRodney W. Grimes bzero(&p2->p_startzero, 388df8bae1dSRodney W. Grimes (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero)); 38957934cd3SJohn Baldwin PROC_LOCK(p1); 390df8bae1dSRodney W. Grimes bcopy(&p1->p_startcopy, &p2->p_startcopy, 391df8bae1dSRodney W. Grimes (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy)); 39257934cd3SJohn Baldwin PROC_UNLOCK(p1); 393df8bae1dSRodney W. Grimes 3944971f62aSJohn Baldwin mtx_init(&p2->p_mtx, "process lock", MTX_DEF); 39557934cd3SJohn Baldwin PROC_LOCK(p2); 3962244ea07SJohn Dyson p2->p_aioinfo = NULL; 3972244ea07SJohn Dyson 398df8bae1dSRodney W. Grimes /* 399df8bae1dSRodney W. Grimes * Duplicate sub-structures as needed. 400df8bae1dSRodney W. Grimes * Increase reference counts on shared objects. 401df8bae1dSRodney W. Grimes * The p_stats and p_sigacts substructs are set in vm_fork. 402df8bae1dSRodney W. Grimes */ 403a7b124c3SJohn Baldwin p2->p_flag = 0; 4049ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 405a7b124c3SJohn Baldwin p2->p_sflag = PS_INMEM; 406a7b124c3SJohn Baldwin if (p1->p_sflag & PS_PROFIL) 407df8bae1dSRodney W. Grimes startprofclock(p2); 4089ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 40957934cd3SJohn Baldwin PROC_UNLOCK(p2); 410df8bae1dSRodney W. Grimes MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred), 411df8bae1dSRodney W. Grimes M_SUBPROC, M_WAITOK); 41257934cd3SJohn Baldwin PROC_LOCK(p2); 41357934cd3SJohn Baldwin PROC_LOCK(p1); 414df8bae1dSRodney W. Grimes bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred)); 415df8bae1dSRodney W. Grimes p2->p_cred->p_refcnt = 1; 416df8bae1dSRodney W. Grimes crhold(p1->p_ucred); 417f535380cSDon Lewis uihold(p1->p_cred->p_uidinfo); 418df8bae1dSRodney W. Grimes 419b9df5231SPoul-Henning Kamp if (p2->p_args) 420b9df5231SPoul-Henning Kamp p2->p_args->ar_ref++; 421b9df5231SPoul-Henning Kamp 4226626c604SJulian Elischer if (flags & RFSIGSHARE) { 423dc9c271aSJulian Elischer p2->p_procsig = p1->p_procsig; 4246626c604SJulian Elischer p2->p_procsig->ps_refcnt++; 425dc9c271aSJulian Elischer if (p1->p_sigacts == &p1->p_addr->u_sigacts) { 426dc9c271aSJulian Elischer struct sigacts *newsigacts; 427dc9c271aSJulian Elischer 42857934cd3SJohn Baldwin PROC_UNLOCK(p1); 42957934cd3SJohn Baldwin PROC_UNLOCK(p2); 430dc9c271aSJulian Elischer /* Create the shared sigacts structure */ 431df8abd0bSPeter Wemm MALLOC(newsigacts, struct sigacts *, 432df8abd0bSPeter Wemm sizeof(struct sigacts), M_SUBPROC, M_WAITOK); 43357934cd3SJohn Baldwin PROC_LOCK(p2); 43457934cd3SJohn Baldwin PROC_LOCK(p1); 435df8abd0bSPeter Wemm /* 436df8abd0bSPeter Wemm * Set p_sigacts to the new shared structure. 437df8abd0bSPeter Wemm * Note that this is updating p1->p_sigacts at the 438df8abd0bSPeter Wemm * same time, since p_sigacts is just a pointer to 439df8abd0bSPeter Wemm * the shared p_procsig->ps_sigacts. 440dc9c271aSJulian Elischer */ 441dc9c271aSJulian Elischer p2->p_sigacts = newsigacts; 442df8abd0bSPeter Wemm bcopy(&p1->p_addr->u_sigacts, p2->p_sigacts, 443df8abd0bSPeter Wemm sizeof(*p2->p_sigacts)); 444dc9c271aSJulian Elischer *p2->p_sigacts = p1->p_addr->u_sigacts; 445dc9c271aSJulian Elischer } 4466626c604SJulian Elischer } else { 44757934cd3SJohn Baldwin PROC_UNLOCK(p1); 44857934cd3SJohn Baldwin PROC_UNLOCK(p2); 449dc9c271aSJulian Elischer MALLOC(p2->p_procsig, struct procsig *, sizeof(struct procsig), 450dc9c271aSJulian Elischer M_SUBPROC, M_WAITOK); 45157934cd3SJohn Baldwin PROC_LOCK(p2); 45257934cd3SJohn Baldwin PROC_LOCK(p1); 453df8abd0bSPeter Wemm bcopy(p1->p_procsig, p2->p_procsig, sizeof(*p2->p_procsig)); 454dc9c271aSJulian Elischer p2->p_procsig->ps_refcnt = 1; 455df8abd0bSPeter Wemm p2->p_sigacts = NULL; /* finished in vm_fork() */ 4566626c604SJulian Elischer } 4574ac9ae70SJulian Elischer if (flags & RFLINUXTHPN) 4586626c604SJulian Elischer p2->p_sigparent = SIGUSR1; 4594ac9ae70SJulian Elischer else 4604ac9ae70SJulian Elischer p2->p_sigparent = SIGCHLD; 46188c5ea45SJulian Elischer 462df8bae1dSRodney W. Grimes /* bump references to the text vnode (for procfs) */ 463df8bae1dSRodney W. Grimes p2->p_textvp = p1->p_textvp; 4645641ae5dSJohn Baldwin PROC_UNLOCK(p1); 4655641ae5dSJohn Baldwin PROC_UNLOCK(p2); 466df8bae1dSRodney W. Grimes if (p2->p_textvp) 467df8bae1dSRodney W. Grimes VREF(p2->p_textvp); 468df8bae1dSRodney W. Grimes 4690e3eb7eeSSujal Patel if (flags & RFCFDG) 4705641ae5dSJohn Baldwin fd = fdinit(p1); 4710e3eb7eeSSujal Patel else if (flags & RFFDG) 4725641ae5dSJohn Baldwin fd = fdcopy(p1); 473dabee6feSPeter Wemm else 4745641ae5dSJohn Baldwin fd = fdshare(p1); 4755641ae5dSJohn Baldwin PROC_LOCK(p2); 4765641ae5dSJohn Baldwin p2->p_fd = fd; 477dabee6feSPeter Wemm 478df8bae1dSRodney W. Grimes /* 479df8bae1dSRodney W. Grimes * If p_limit is still copy-on-write, bump refcnt, 480df8bae1dSRodney W. Grimes * otherwise get a copy that won't be modified. 481df8bae1dSRodney W. Grimes * (If PL_SHAREMOD is clear, the structure is shared 482df8bae1dSRodney W. Grimes * copy-on-write.) 483df8bae1dSRodney W. Grimes */ 4845641ae5dSJohn Baldwin PROC_LOCK(p1); 485df8bae1dSRodney W. Grimes if (p1->p_limit->p_lflags & PL_SHAREMOD) 486df8bae1dSRodney W. Grimes p2->p_limit = limcopy(p1->p_limit); 487df8bae1dSRodney W. Grimes else { 488df8bae1dSRodney W. Grimes p2->p_limit = p1->p_limit; 489df8bae1dSRodney W. Grimes p2->p_limit->p_refcnt++; 490df8bae1dSRodney W. Grimes } 491df8bae1dSRodney W. Grimes 49270e534e7SDavid Greenman /* 49357934cd3SJohn Baldwin * Preserve some more flags in subprocess. PS_PROFIL has already 494be67169aSBruce Evans * been preserved. 49570e534e7SDavid Greenman */ 49670e534e7SDavid Greenman p2->p_flag |= p1->p_flag & P_SUGID; 497df8bae1dSRodney W. Grimes if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) 498df8bae1dSRodney W. Grimes p2->p_flag |= P_CONTROLT; 4990e3eb7eeSSujal Patel if (flags & RFPPWAIT) 500df8bae1dSRodney W. Grimes p2->p_flag |= P_PPWAIT; 501be67169aSBruce Evans 502b75356e1SJeffrey Hsu LIST_INSERT_AFTER(p1, p2, p_pglist); 50357934cd3SJohn Baldwin PROC_UNLOCK(p1); 50457934cd3SJohn Baldwin PROC_UNLOCK(p2); 5050e3eb7eeSSujal Patel 5060e3eb7eeSSujal Patel /* 5070e3eb7eeSSujal Patel * Attach the new process to its parent. 5080e3eb7eeSSujal Patel * 5090e3eb7eeSSujal Patel * If RFNOWAIT is set, the newly created process becomes a child 5100e3eb7eeSSujal Patel * of init. This effectively disassociates the child from the 5110e3eb7eeSSujal Patel * parent. 5120e3eb7eeSSujal Patel */ 5130e3eb7eeSSujal Patel if (flags & RFNOWAIT) 5140e3eb7eeSSujal Patel pptr = initproc; 5150e3eb7eeSSujal Patel else 5160e3eb7eeSSujal Patel pptr = p1; 51798f03f90SJake Burkholder PROCTREE_LOCK(PT_EXCLUSIVE); 51857934cd3SJohn Baldwin PROC_LOCK(p2); 5190e3eb7eeSSujal Patel p2->p_pptr = pptr; 52057934cd3SJohn Baldwin PROC_UNLOCK(p2); 5210e3eb7eeSSujal Patel LIST_INSERT_HEAD(&pptr->p_children, p2, p_sibling); 52298f03f90SJake Burkholder PROCTREE_LOCK(PT_RELEASE); 52357934cd3SJohn Baldwin PROC_LOCK(p2); 524b75356e1SJeffrey Hsu LIST_INIT(&p2->p_children); 5250384fff8SJason Evans LIST_INIT(&p2->p_heldmtx); 5260384fff8SJason Evans LIST_INIT(&p2->p_contested); 527b75356e1SJeffrey Hsu 5284f559836SJake Burkholder callout_init(&p2->p_itcallout, 0); 5291512b5d6SJake Burkholder callout_init(&p2->p_slpcallout, 1); 5304f559836SJake Burkholder 53157934cd3SJohn Baldwin PROC_LOCK(p1); 532df8bae1dSRodney W. Grimes #ifdef KTRACE 533df8bae1dSRodney W. Grimes /* 534df8bae1dSRodney W. Grimes * Copy traceflag and tracefile if enabled. 535df8bae1dSRodney W. Grimes * If not inherited, these were zeroed above. 536df8bae1dSRodney W. Grimes */ 537df8bae1dSRodney W. Grimes if (p1->p_traceflag & KTRFAC_INHERIT) { 538df8bae1dSRodney W. Grimes p2->p_traceflag = p1->p_traceflag; 5395641ae5dSJohn Baldwin if ((p2->p_tracep = p1->p_tracep) != NULL) { 5405641ae5dSJohn Baldwin PROC_UNLOCK(p1); 5415641ae5dSJohn Baldwin PROC_UNLOCK(p2); 542df8bae1dSRodney W. Grimes VREF(p2->p_tracep); 5435641ae5dSJohn Baldwin PROC_LOCK(p2); 5445641ae5dSJohn Baldwin PROC_LOCK(p1); 5455641ae5dSJohn Baldwin } 546df8bae1dSRodney W. Grimes } 547df8bae1dSRodney W. Grimes #endif 548df8bae1dSRodney W. Grimes 549df8bae1dSRodney W. Grimes /* 5500d2afceeSDavid Greenman * set priority of child to be that of parent 5510d2afceeSDavid Greenman */ 5525641ae5dSJohn Baldwin mtx_lock_spin(&sched_lock); 5530d2afceeSDavid Greenman p2->p_estcpu = p1->p_estcpu; 5545641ae5dSJohn Baldwin mtx_unlock_spin(&sched_lock); 5550d2afceeSDavid Greenman 5560d2afceeSDavid Greenman /* 557df8bae1dSRodney W. Grimes * This begins the section where we must prevent the parent 558df8bae1dSRodney W. Grimes * from being swapped. 559df8bae1dSRodney W. Grimes */ 56057934cd3SJohn Baldwin _PHOLD(p1); 56157934cd3SJohn Baldwin PROC_UNLOCK(p1); 56257934cd3SJohn Baldwin PROC_UNLOCK(p2); 5630d2afceeSDavid Greenman 564df8bae1dSRodney W. Grimes /* 565a2a1c95cSPeter Wemm * Finish creating the child process. It will return via a different 566a2a1c95cSPeter Wemm * execution path later. (ie: directly into user mode) 567dabee6feSPeter Wemm */ 568a2a1c95cSPeter Wemm vm_fork(p1, p2, flags); 569df8bae1dSRodney W. Grimes 5705d22597fSHajimu UMEMOTO if (flags == (RFFDG | RFPROC)) { 5715d22597fSHajimu UMEMOTO cnt.v_forks++; 5725d22597fSHajimu UMEMOTO cnt.v_forkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize; 5735d22597fSHajimu UMEMOTO } else if (flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) { 5745d22597fSHajimu UMEMOTO cnt.v_vforks++; 5755d22597fSHajimu UMEMOTO cnt.v_vforkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize; 5765d22597fSHajimu UMEMOTO } else if (p1 == &proc0) { 5775d22597fSHajimu UMEMOTO cnt.v_kthreads++; 5785d22597fSHajimu UMEMOTO cnt.v_kthreadpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize; 5795d22597fSHajimu UMEMOTO } else { 5805d22597fSHajimu UMEMOTO cnt.v_rforks++; 5815d22597fSHajimu UMEMOTO cnt.v_rforkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize; 5825d22597fSHajimu UMEMOTO } 5835d22597fSHajimu UMEMOTO 584df8bae1dSRodney W. Grimes /* 585e9189611SPeter Wemm * Both processes are set up, now check if any loadable modules want 586e0d898b4SJulian Elischer * to adjust anything. 587fed06968SJulian Elischer * What if they have an error? XXX 588fed06968SJulian Elischer */ 58957934cd3SJohn Baldwin sx_slock(&fork_list_lock); 59093efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &fork_list, next) { 591fed06968SJulian Elischer (*ep->function)(p1, p2, flags); 592fed06968SJulian Elischer } 59357934cd3SJohn Baldwin sx_sunlock(&fork_list_lock); 594fed06968SJulian Elischer 595fed06968SJulian Elischer /* 5960384fff8SJason Evans * If RFSTOPPED not requested, make child runnable and add to 5970384fff8SJason Evans * run queue. 598df8bae1dSRodney W. Grimes */ 599a2a1c95cSPeter Wemm microtime(&(p2->p_stats->p_start)); 600a2a1c95cSPeter Wemm p2->p_acflag = AFORK; 6010384fff8SJason Evans if ((flags & RFSTOPPED) == 0) { 6029ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 603df8bae1dSRodney W. Grimes p2->p_stat = SRUN; 604df8bae1dSRodney W. Grimes setrunqueue(p2); 6059ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 6060384fff8SJason Evans } 607df8bae1dSRodney W. Grimes 608df8bae1dSRodney W. Grimes /* 609df8bae1dSRodney W. Grimes * Now can be swapped. 610df8bae1dSRodney W. Grimes */ 61157934cd3SJohn Baldwin PROC_LOCK(p1); 61257934cd3SJohn Baldwin _PRELE(p1); 613df8bae1dSRodney W. Grimes 614df8bae1dSRodney W. Grimes /* 615cb679c38SJonathan Lemon * tell any interested parties about the new process 616cb679c38SJonathan Lemon */ 617cb679c38SJonathan Lemon KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid); 61857934cd3SJohn Baldwin PROC_UNLOCK(p1); 619cb679c38SJonathan Lemon 620cb679c38SJonathan Lemon /* 621df8bae1dSRodney W. Grimes * Preserve synchronization semantics of vfork. If waiting for 622df8bae1dSRodney W. Grimes * child to exec or exit, set P_PPWAIT on child, and sleep on our 623df8bae1dSRodney W. Grimes * proc (in case of exit). 624df8bae1dSRodney W. Grimes */ 62557934cd3SJohn Baldwin PROC_LOCK(p2); 626df8bae1dSRodney W. Grimes while (p2->p_flag & P_PPWAIT) 62757934cd3SJohn Baldwin msleep(p1, &p2->p_mtx, PWAIT, "ppwait", 0); 62857934cd3SJohn Baldwin PROC_UNLOCK(p2); 629df8bae1dSRodney W. Grimes 630df8bae1dSRodney W. Grimes /* 631df8abd0bSPeter Wemm * Return child proc pointer to parent. 632df8bae1dSRodney W. Grimes */ 633df8abd0bSPeter Wemm *procp = p2; 634df8bae1dSRodney W. Grimes return (0); 635df8bae1dSRodney W. Grimes } 636fed06968SJulian Elischer 637e0d898b4SJulian Elischer /* 638e0d898b4SJulian Elischer * The next two functionms are general routines to handle adding/deleting 639e0d898b4SJulian Elischer * items on the fork callout list. 640e0d898b4SJulian Elischer * 641e0d898b4SJulian Elischer * at_fork(): 642e0d898b4SJulian Elischer * Take the arguments given and put them onto the fork callout list, 643fed06968SJulian Elischer * However first make sure that it's not already there. 644e0d898b4SJulian Elischer * Returns 0 on success or a standard error number. 645fed06968SJulian Elischer */ 64693efcae8SPoul-Henning Kamp 647fed06968SJulian Elischer int 648eb776aeaSBruce Evans at_fork(function) 649eb776aeaSBruce Evans forklist_fn function; 650fed06968SJulian Elischer { 65193efcae8SPoul-Henning Kamp struct forklist *ep; 652e0d898b4SJulian Elischer 65393efcae8SPoul-Henning Kamp #ifdef INVARIANTS 654e0d898b4SJulian Elischer /* let the programmer know if he's been stupid */ 655e0d898b4SJulian Elischer if (rm_at_fork(function)) 65693efcae8SPoul-Henning Kamp printf("WARNING: fork callout entry (%p) already present\n", 65793efcae8SPoul-Henning Kamp function); 65893efcae8SPoul-Henning Kamp #endif 65993efcae8SPoul-Henning Kamp ep = malloc(sizeof(*ep), M_ATFORK, M_NOWAIT); 660e0d898b4SJulian Elischer if (ep == NULL) 661e0d898b4SJulian Elischer return (ENOMEM); 662fed06968SJulian Elischer ep->function = function; 66357934cd3SJohn Baldwin sx_xlock(&fork_list_lock); 66493efcae8SPoul-Henning Kamp TAILQ_INSERT_TAIL(&fork_list, ep, next); 66557934cd3SJohn Baldwin sx_xunlock(&fork_list_lock); 666e0d898b4SJulian Elischer return (0); 667fed06968SJulian Elischer } 668e0d898b4SJulian Elischer 669fed06968SJulian Elischer /* 67093efcae8SPoul-Henning Kamp * Scan the exit callout list for the given item and remove it.. 67193efcae8SPoul-Henning Kamp * Returns the number of items removed (0 or 1) 672fed06968SJulian Elischer */ 67393efcae8SPoul-Henning Kamp 674fed06968SJulian Elischer int 675eb776aeaSBruce Evans rm_at_fork(function) 676eb776aeaSBruce Evans forklist_fn function; 677fed06968SJulian Elischer { 67893efcae8SPoul-Henning Kamp struct forklist *ep; 679fed06968SJulian Elischer 68057934cd3SJohn Baldwin sx_xlock(&fork_list_lock); 68193efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &fork_list, next) { 682fed06968SJulian Elischer if (ep->function == function) { 68393efcae8SPoul-Henning Kamp TAILQ_REMOVE(&fork_list, ep, next); 68457934cd3SJohn Baldwin sx_xunlock(&fork_list_lock); 68593efcae8SPoul-Henning Kamp free(ep, M_ATFORK); 68693efcae8SPoul-Henning Kamp return(1); 687fed06968SJulian Elischer } 688fed06968SJulian Elischer } 68957934cd3SJohn Baldwin sx_xunlock(&fork_list_lock); 69093efcae8SPoul-Henning Kamp return (0); 691fed06968SJulian Elischer } 692a7b124c3SJohn Baldwin 693a7b124c3SJohn Baldwin /* 694a7b124c3SJohn Baldwin * Handle the return of a child process from fork1(). This function 695a7b124c3SJohn Baldwin * is called from the MD fork_trampoline() entry point. 696a7b124c3SJohn Baldwin */ 697a7b124c3SJohn Baldwin void 698a7b124c3SJohn Baldwin fork_exit(callout, arg, frame) 6998865286bSJohn Baldwin void (*callout)(void *, struct trapframe *); 700a7b124c3SJohn Baldwin void *arg; 7012a36ec35SJohn Baldwin struct trapframe *frame; 702a7b124c3SJohn Baldwin { 703a7b124c3SJohn Baldwin struct proc *p; 704a7b124c3SJohn Baldwin 70557934cd3SJohn Baldwin p = curproc; 70657934cd3SJohn Baldwin 7075813dc03SJohn Baldwin /* 7085813dc03SJohn Baldwin * Setup the sched_lock state so that we can release it. 7095813dc03SJohn Baldwin */ 71057934cd3SJohn Baldwin sched_lock.mtx_lock = (uintptr_t)p; 7115813dc03SJohn Baldwin sched_lock.mtx_recurse = 0; 7129ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 713a7b124c3SJohn Baldwin /* 714a7b124c3SJohn Baldwin * XXX: We really shouldn't have to do this. 715a7b124c3SJohn Baldwin */ 716a7b124c3SJohn Baldwin enable_intr(); 717a7b124c3SJohn Baldwin 718a7b124c3SJohn Baldwin #ifdef SMP 719a7b124c3SJohn Baldwin if (PCPU_GET(switchtime.tv_sec) == 0) 720a7b124c3SJohn Baldwin microuptime(PCPU_PTR(switchtime)); 721a7b124c3SJohn Baldwin PCPU_SET(switchticks, ticks); 722a7b124c3SJohn Baldwin #endif 723a7b124c3SJohn Baldwin 724a7b124c3SJohn Baldwin /* 725a7b124c3SJohn Baldwin * cpu_set_fork_handler intercepts this function call to 726a7b124c3SJohn Baldwin * have this call a non-return function to stay in kernel mode. 727a7b124c3SJohn Baldwin * initproc has its own fork handler, but it does return. 728a7b124c3SJohn Baldwin */ 7295813dc03SJohn Baldwin KASSERT(callout != NULL, ("NULL callout in fork_exit")); 7308865286bSJohn Baldwin callout(arg, frame); 731a7b124c3SJohn Baldwin 732a7b124c3SJohn Baldwin /* 733a7b124c3SJohn Baldwin * Check if a kernel thread misbehaved and returned from its main 734a7b124c3SJohn Baldwin * function. 735a7b124c3SJohn Baldwin */ 73657934cd3SJohn Baldwin PROC_LOCK(p); 737a7b124c3SJohn Baldwin if (p->p_flag & P_KTHREAD) { 73857934cd3SJohn Baldwin PROC_UNLOCK(p); 7399ed346baSBosko Milekic mtx_lock(&Giant); 740a7b124c3SJohn Baldwin printf("Kernel thread \"%s\" (pid %d) exited prematurely.\n", 741a7b124c3SJohn Baldwin p->p_comm, p->p_pid); 742a7b124c3SJohn Baldwin kthread_exit(0); 743a7b124c3SJohn Baldwin } 74457934cd3SJohn Baldwin PROC_UNLOCK(p); 745a7b124c3SJohn Baldwin mtx_assert(&Giant, MA_NOTOWNED); 746a7b124c3SJohn Baldwin } 747a7b124c3SJohn Baldwin 748a7b124c3SJohn Baldwin /* 749a7b124c3SJohn Baldwin * Simplified back end of syscall(), used when returning from fork() 750a7b124c3SJohn Baldwin * directly into user mode. Giant is not held on entry, and must not 751a7b124c3SJohn Baldwin * be held on return. This function is passed in to fork_exit() as the 752a7b124c3SJohn Baldwin * first parameter and is called when returning to a new userland process. 753a7b124c3SJohn Baldwin */ 754a7b124c3SJohn Baldwin void 755a7b124c3SJohn Baldwin fork_return(p, frame) 756a7b124c3SJohn Baldwin struct proc *p; 757a7b124c3SJohn Baldwin struct trapframe *frame; 758a7b124c3SJohn Baldwin { 759a7b124c3SJohn Baldwin 760a7b124c3SJohn Baldwin userret(p, frame, 0); 761a7b124c3SJohn Baldwin #ifdef KTRACE 762a7b124c3SJohn Baldwin if (KTRPOINT(p, KTR_SYSRET)) { 763a7b124c3SJohn Baldwin if (!mtx_owned(&Giant)) 7649ed346baSBosko Milekic mtx_lock(&Giant); 765a7b124c3SJohn Baldwin ktrsysret(p->p_tracep, SYS_fork, 0, 0); 766a7b124c3SJohn Baldwin } 767a7b124c3SJohn Baldwin #endif 768a7b124c3SJohn Baldwin if (mtx_owned(&Giant)) 7699ed346baSBosko Milekic mtx_unlock(&Giant); 770a7b124c3SJohn Baldwin mtx_assert(&Giant, MA_NOTOWNED); 771a7b124c3SJohn Baldwin } 772