123370Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423370Smckusick * 537728Smckusick * Redistribution and use in source and binary forms are permitted 637728Smckusick * provided that the above copyright notice and this paragraph are 737728Smckusick * duplicated in all such forms and that any documentation, 837728Smckusick * advertising materials, and other materials related to such 937728Smckusick * distribution and use acknowledge that the software was developed 1037728Smckusick * by the University of California, Berkeley. The name of the 1137728Smckusick * University may not be used to endorse or promote products derived 1237728Smckusick * from this software without specific prior written permission. 1337728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637728Smckusick * 17*42921Smckusick * @(#)kern_fork.c 7.17 (Berkeley) 06/05/90 1823370Smckusick */ 1912791Ssam 2017090Sbloom #include "param.h" 2117090Sbloom #include "systm.h" 2217090Sbloom #include "map.h" 23*42921Smckusick #include "syscontext.h" 2417090Sbloom #include "kernel.h" 2517090Sbloom #include "proc.h" 2637728Smckusick #include "vnode.h" 2717090Sbloom #include "seg.h" 2817090Sbloom #include "vm.h" 2917090Sbloom #include "text.h" 3017090Sbloom #include "file.h" 3117090Sbloom #include "acct.h" 3240812Smarc #include "ktrace.h" 3337728Smckusick #include "../ufs/quota.h" 3412791Ssam 3537523Smckusick #include "machine/reg.h" 3637523Smckusick #include "machine/pte.h" 3737523Smckusick #include "machine/psl.h" 3837523Smckusick 3912791Ssam /* 4012791Ssam * fork system call. 4112791Ssam */ 42*42921Smckusick /* ARGSUSED */ 43*42921Smckusick fork(p, uap, retval) 44*42921Smckusick struct proc *p; 45*42921Smckusick struct args *uap; 46*42921Smckusick int retval[]; 4712791Ssam { 48*42921Smckusick int error; 4912791Ssam 5012791Ssam u.u_cdmap = zdmap; 5112791Ssam u.u_csmap = zdmap; 52*42921Smckusick if (error = swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap)) { 53*42921Smckusick retval[1] = 0; 54*42921Smckusick RETURN (error); 5512791Ssam } 56*42921Smckusick RETURN (fork1(p, 0, retval)); 5712791Ssam } 5812791Ssam 59*42921Smckusick /* ARGSUSED */ 60*42921Smckusick vfork(p, uap, retval) 61*42921Smckusick struct proc *p; 62*42921Smckusick struct args *uap; 63*42921Smckusick int retval[]; 6412791Ssam { 6512791Ssam 66*42921Smckusick RETURN (fork1(p, 1, retval)); 6712791Ssam } 6812791Ssam 69*42921Smckusick fork1(p1, isvfork, retval) 70*42921Smckusick register struct proc *p1; 71*42921Smckusick int isvfork, retval[]; 7212791Ssam { 73*42921Smckusick register struct proc *p2; 74*42921Smckusick register int a; 7512791Ssam 7612791Ssam a = 0; 77*42921Smckusick if (p1->p_uid != 0) { 78*42921Smckusick for (p2 = allproc; p2; p2 = p2->p_nxt) 79*42921Smckusick if (p2->p_uid == p1->p_uid) 8012791Ssam a++; 81*42921Smckusick for (p2 = zombproc; p2; p2 = p2->p_nxt) 82*42921Smckusick if (p2->p_uid == p1->p_uid) 8316528Skarels a++; 8412791Ssam } 8512791Ssam /* 8612791Ssam * Disallow if 8712791Ssam * No processes at all; 8812791Ssam * not su and too many procs owned; or 8912791Ssam * not su and would take last slot. 9012791Ssam */ 9116528Skarels p2 = freeproc; 9212791Ssam if (p2==NULL) 9312791Ssam tablefull("proc"); 94*42921Smckusick if (p2 == NULL || 95*42921Smckusick (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) { 9612791Ssam if (!isvfork) { 9742087Sbostic (void) vsexpand((segsz_t)0, &u.u_cdmap, 1); 9842087Sbostic (void) vsexpand((segsz_t)0, &u.u_csmap, 1); 9912791Ssam } 100*42921Smckusick retval[1] = 0; 101*42921Smckusick return (EAGAIN); 10212791Ssam } 10312791Ssam if (newproc(isvfork)) { 104*42921Smckusick retval[0] = p1->p_pid; 105*42921Smckusick retval[1] = 1; /* child */ 10612791Ssam u.u_acflag = AFORK; 107*42921Smckusick return (0); 10812791Ssam } 109*42921Smckusick retval[0] = p2->p_pid; 110*42921Smckusick retval[1] = 0; 111*42921Smckusick return (0); 11212791Ssam } 11312791Ssam 11412791Ssam /* 11512791Ssam * Create a new process-- the internal version of 11612791Ssam * sys fork. 11712791Ssam * It returns 1 in the new process, 0 in the old. 11812791Ssam */ 11912791Ssam newproc(isvfork) 12012791Ssam int isvfork; 12112791Ssam { 12212791Ssam register struct proc *rpp, *rip; 12312791Ssam register int n; 12412791Ssam register struct file *fp; 12516528Skarels static int pidchecked = 0; 12612791Ssam 12712791Ssam /* 12812791Ssam * First, just locate a slot for a process 12912791Ssam * and copy the useful info from this process into it. 13012791Ssam * The panic "cannot happen" because fork has already 13112791Ssam * checked for the existence of a slot. 13212791Ssam */ 13316528Skarels mpid++; 13412791Ssam retry: 13512791Ssam if (mpid >= 30000) { 13616528Skarels mpid = 100; 13716528Skarels pidchecked = 0; 13812791Ssam } 13916528Skarels if (mpid >= pidchecked) { 14016528Skarels int doingzomb = 0; 14116578Ssam 14216528Skarels pidchecked = 30000; 14316528Skarels /* 14416528Skarels * Scan the proc table to check whether this pid 14516528Skarels * is in use. Remember the lowest pid that's greater 14616528Skarels * than mpid, so we can avoid checking for a while. 14716528Skarels */ 14816528Skarels rpp = allproc; 14916528Skarels again: 15016528Skarels for (; rpp != NULL; rpp = rpp->p_nxt) { 15135810Smarc if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) { 15216528Skarels mpid++; 15316528Skarels if (mpid >= pidchecked) 15416528Skarels goto retry; 15516528Skarels } 15616578Ssam if (rpp->p_pid > mpid && pidchecked > rpp->p_pid) 15716528Skarels pidchecked = rpp->p_pid; 15835810Smarc if (rpp->p_pgrp->pg_id > mpid && 15935810Smarc pidchecked > rpp->p_pgrp->pg_id) 16035810Smarc pidchecked = rpp->p_pgrp->pg_id; 16116528Skarels } 16216528Skarels if (!doingzomb) { 16316528Skarels doingzomb = 1; 16416528Skarels rpp = zombproc; 16516528Skarels goto again; 16616528Skarels } 16712791Ssam } 16816528Skarels if ((rpp = freeproc) == NULL) 16912791Ssam panic("no procs"); 17012791Ssam 17116528Skarels freeproc = rpp->p_nxt; /* off freeproc */ 17216528Skarels rpp->p_nxt = allproc; /* onto allproc */ 17316528Skarels rpp->p_nxt->p_prev = &rpp->p_nxt; /* (allproc is never NULL) */ 17416528Skarels rpp->p_prev = &allproc; 17516528Skarels allproc = rpp; 17616528Skarels 17712791Ssam /* 17812791Ssam * Make a proc table entry for the new process. 17912791Ssam */ 18012791Ssam rip = u.u_procp; 18129946Skarels #if defined(tahoe) 18229946Skarels rpp->p_ckey = rip->p_ckey; 18329946Skarels rpp->p_dkey = 0; 18429946Skarels #endif 18512791Ssam rpp->p_stat = SIDL; 18612791Ssam timerclear(&rpp->p_realtimer.it_value); 18742206Smarc rpp->p_flag = SLOAD | (rip->p_flag & (SPAGV|SHPUX)); 18842206Smarc if (rip->p_session->s_ttyvp != NULL && rip->p_flag & SCTTY) 18942206Smarc rpp->p_flag |= SCTTY; 19012791Ssam if (isvfork) { 19112791Ssam rpp->p_flag |= SVFORK; 19212791Ssam rpp->p_ndx = rip->p_ndx; 19312791Ssam } else 19412791Ssam rpp->p_ndx = rpp - proc; 19540812Smarc bcopy(rip->p_comm, rpp->p_comm, MAXCOMLEN+1); 19640812Smarc bcopy(rip->p_logname, rpp->p_logname, MAXLOGNAME); 19712791Ssam rpp->p_uid = rip->p_uid; 19838929Skarels rpp->p_ruid = rip->p_ruid; 19938929Skarels rpp->p_rgid = rip->p_rgid; 20012791Ssam rpp->p_pgrp = rip->p_pgrp; 20135810Smarc rpp->p_pgrpnxt = rip->p_pgrpnxt; 20235810Smarc rip->p_pgrpnxt = rpp; 20312791Ssam rpp->p_nice = rip->p_nice; 20412791Ssam rpp->p_textp = isvfork ? 0 : rip->p_textp; 20512791Ssam rpp->p_pid = mpid; 20612791Ssam rpp->p_ppid = rip->p_pid; 20712791Ssam rpp->p_pptr = rip; 20812791Ssam rpp->p_osptr = rip->p_cptr; 20912791Ssam if (rip->p_cptr) 21012791Ssam rip->p_cptr->p_ysptr = rpp; 21112791Ssam rpp->p_ysptr = NULL; 21212791Ssam rpp->p_cptr = NULL; 21312791Ssam rip->p_cptr = rpp; 21412791Ssam rpp->p_time = 0; 21541180Smarc bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval)); 21641180Smarc bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval)); 21712791Ssam rpp->p_cpu = 0; 21812882Ssam rpp->p_sigmask = rip->p_sigmask; 21912882Ssam rpp->p_sigcatch = rip->p_sigcatch; 22012882Ssam rpp->p_sigignore = rip->p_sigignore; 22112882Ssam /* take along any pending signals like stops? */ 22212791Ssam if (isvfork) { 22341571Smckusick rpp->p_tsize = rpp->p_dsize = rpp->p_mmsize = rpp->p_ssize = 0; 22441571Smckusick rpp->p_szpt = clrnd(ctopt(HIGHPAGES)); 22512791Ssam forkstat.cntvfork++; 22612791Ssam forkstat.sizvfork += rip->p_dsize + rip->p_ssize; 22712791Ssam } else { 22812791Ssam rpp->p_tsize = rip->p_tsize; 22912791Ssam rpp->p_dsize = rip->p_dsize; 23041571Smckusick rpp->p_mmsize = rip->p_mmsize; 23112791Ssam rpp->p_ssize = rip->p_ssize; 23212791Ssam rpp->p_szpt = rip->p_szpt; 23312791Ssam forkstat.cntfork++; 23412791Ssam forkstat.sizfork += rip->p_dsize + rip->p_ssize; 23512791Ssam } 23637592Smarc #ifdef KTRACE 23740812Smarc if (rip->p_traceflag&KTRFAC_INHERIT) { 23840812Smarc rpp->p_traceflag = rip->p_traceflag; 23938422Smarc if ((rpp->p_tracep = rip->p_tracep) != NULL) 24038422Smarc VREF(rpp->p_tracep); 24137592Smarc } else { 24237592Smarc rpp->p_tracep = NULL; 24337592Smarc rpp->p_traceflag = 0; 24437592Smarc } 24537592Smarc #endif 24612791Ssam rpp->p_rssize = 0; 24712791Ssam rpp->p_maxrss = rip->p_maxrss; 24812791Ssam rpp->p_wchan = 0; 24912791Ssam rpp->p_slptime = 0; 25012791Ssam rpp->p_pctcpu = 0; 25112791Ssam rpp->p_cpticks = 0; 25240812Smarc { 25340812Smarc struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)]; 25440812Smarc 25540812Smarc rpp->p_hash = *hash; 25640812Smarc *hash = rpp; 25740812Smarc } 25812791Ssam multprog++; 25912791Ssam 26012791Ssam /* 26112791Ssam * Increase reference counts on shared objects. 26212791Ssam */ 26321102Skarels for (n = 0; n <= u.u_lastfile; n++) { 26412791Ssam fp = u.u_ofile[n]; 26512791Ssam if (fp == NULL) 26612791Ssam continue; 26712791Ssam fp->f_count++; 26812791Ssam } 26938347Smckusick VREF(u.u_cdir); 27012791Ssam if (u.u_rdir) 27138347Smckusick VREF(u.u_rdir); 27237728Smckusick crhold(u.u_cred); 27312791Ssam 27412791Ssam /* 27512791Ssam * This begins the section where we must prevent the parent 27612791Ssam * from being swapped. 27712791Ssam */ 27812791Ssam rip->p_flag |= SKEEP; 27941180Smarc if (procdup(rpp, isvfork)) { 28041180Smarc (void) splclock(); 28141180Smarc u.u_start = time; 28241180Smarc (void) spl0(); 28312791Ssam return (1); 28441180Smarc } 28512791Ssam 28612791Ssam /* 28712791Ssam * Make child runnable and add to run queue. 28812791Ssam */ 28926277Skarels (void) splclock(); 29012791Ssam rpp->p_stat = SRUN; 29112791Ssam setrq(rpp); 29212791Ssam (void) spl0(); 29312791Ssam 29412791Ssam /* 29512791Ssam * Cause child to take a non-local goto as soon as it runs. 29612791Ssam * On older systems this was done with SSWAP bit in proc 29712791Ssam * table; on VAX we use u.u_pcb.pcb_sswap so don't need 29812791Ssam * to do rpp->p_flag |= SSWAP. Actually do nothing here. 29912791Ssam */ 30012791Ssam /* rpp->p_flag |= SSWAP; */ 30112791Ssam 30212791Ssam /* 30312791Ssam * Now can be swapped. 30412791Ssam */ 30512791Ssam rip->p_flag &= ~SKEEP; 30612791Ssam 30712791Ssam /* 30812791Ssam * If vfork make chain from parent process to child 30912791Ssam * (where virtal memory is temporarily). Wait for 31012791Ssam * child to finish, steal virtual memory back, 31112791Ssam * and wakeup child to let it die. 31212791Ssam */ 31312791Ssam if (isvfork) { 31412791Ssam u.u_procp->p_xlink = rpp; 31512791Ssam u.u_procp->p_flag |= SNOVM; 31612791Ssam while (rpp->p_flag & SVFORK) 31712791Ssam sleep((caddr_t)rpp, PZERO - 1); 31812791Ssam if ((rpp->p_flag & SLOAD) == 0) 31912791Ssam panic("newproc vfork"); 32012791Ssam uaccess(rpp, Vfmap, &vfutl); 32112791Ssam u.u_procp->p_xlink = 0; 32212791Ssam vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 32312791Ssam u.u_procp->p_flag &= ~SNOVM; 32412791Ssam rpp->p_ndx = rpp - proc; 32512791Ssam rpp->p_flag |= SVFDONE; 32612791Ssam wakeup((caddr_t)rpp); 32712791Ssam } 32812791Ssam 32912791Ssam /* 33012791Ssam * 0 return means parent. 33112791Ssam */ 33212791Ssam return (0); 33312791Ssam } 334