/* kern_fork.c 4.3 83/06/14 */
#include "../machine/reg.h"
#include "../machine/pte.h"
#include "../machine/psl.h"
if (swpexpand(u
.u_dsize
, u
.u_ssize
, &u
.u_cdmap
, &u
.u_csmap
) == 0) {
register struct proc
*p1
, *p2
;
for (p1
= proc
; p1
< procNPROC
; p1
++) {
if (p1
->p_stat
==NULL
&& p2
==NULL
)
if (p1
->p_uid
==u
.u_uid
&& p1
->p_stat
!=NULL
)
* not su and too many procs owned; or
* not su and would take last slot.
if (p2
==NULL
|| (u
.u_uid
!=0 && (p2
==procNPROC
-1 || a
>MAXUPRC
))) {
(void) vsexpand(0, &u
.u_cdmap
, 1);
(void) vsexpand(0, &u
.u_csmap
, 1);
u
.u_r
.r_val1
= p1
->p_pid
;
u
.u_r
.r_val2
= 1; /* child */
u
.u_r
.r_val1
= p2
->p_pid
;
* Create a new process-- the internal version of
* It returns 1 in the new process, 0 in the old.
register struct proc
*rpp
, *rip
;
register struct file
*fp
;
* First, just locate a slot for a process
* and copy the useful info from this process into it.
* The panic "cannot happen" because fork has already
* checked for the existence of a slot.
for (rpp
= proc
; rpp
< procNPROC
; rpp
++) {
if (rpp
->p_stat
== NULL
&& p
==NULL
)
if (rpp
->p_pid
==mpid
|| rpp
->p_pgrp
==mpid
)
* Make a proc table entry for the new process.
rpp
->p_quota
= rip
->p_quota
;
timerclear(&rpp
->p_realtimer
.it_value
);
rpp
->p_flag
= SLOAD
| (rip
->p_flag
& (SPAGI
|SOUSIG
));
rpp
->p_pgrp
= rip
->p_pgrp
;
rpp
->p_nice
= rip
->p_nice
;
rpp
->p_textp
= isvfork
? 0 : rip
->p_textp
;
rpp
->p_ppid
= rip
->p_pid
;
rpp
->p_osptr
= rip
->p_cptr
;
rip
->p_cptr
->p_ysptr
= rpp
;
rpp
->p_sigmask
= rip
->p_sigmask
;
rpp
->p_sigcatch
= rip
->p_sigcatch
;
rpp
->p_sigignore
= rip
->p_sigignore
;
/* take along any pending signals like stops? */
rpp
->p_tsize
= rpp
->p_dsize
= rpp
->p_ssize
= 0;
rpp
->p_szpt
= clrnd(ctopt(UPAGES
));
forkstat
.sizvfork
+= rip
->p_dsize
+ rip
->p_ssize
;
rpp
->p_tsize
= rip
->p_tsize
;
rpp
->p_dsize
= rip
->p_dsize
;
rpp
->p_ssize
= rip
->p_ssize
;
rpp
->p_szpt
= rip
->p_szpt
;
forkstat
.sizfork
+= rip
->p_dsize
+ rip
->p_ssize
;
rpp
->p_maxrss
= rip
->p_maxrss
;
p
->p_idhash
= pidhash
[n
];
* Increase reference counts on shared objects.
for (n
= 0; n
< NOFILE
; n
++) {
* Partially simulate the environment
* of the new process so that when it is actually
* created (by copying) it will look right.
* This begins the section where we must prevent the parent
if (procdup(rpp
, isvfork
))
* Make child runnable and add to run queue.
* Cause child to take a non-local goto as soon as it runs.
* On older systems this was done with SSWAP bit in proc
* table; on VAX we use u.u_pcb.pcb_sswap so don't need
* to do rpp->p_flag |= SSWAP. Actually do nothing here.
/* rpp->p_flag |= SSWAP; */
* If vfork make chain from parent process to child
* (where virtal memory is temporarily). Wait for
* child to finish, steal virtual memory back,
* and wakeup child to let it die.
u
.u_procp
->p_xlink
= rpp
;
u
.u_procp
->p_flag
|= SNOVM
;
while (rpp
->p_flag
& SVFORK
)
sleep((caddr_t
)rpp
, PZERO
- 1);
if ((rpp
->p_flag
& SLOAD
) == 0)
uaccess(rpp
, Vfmap
, &vfutl
);
vpassvm(rpp
, u
.u_procp
, &vfutl
, &u
, Vfmap
);
u
.u_procp
->p_flag
&= ~SNOVM
;