* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)kern_fork.c 7.35 (Berkeley) %G%
return (fork1(p
, 0, retval
));
return (fork1(p
, 1, retval
));
int nprocs
= 1; /* process 0 */
fork1(p1
, isvfork
, retval
)
register struct proc
*p1
;
register struct proc
*p2
;
static int nextpid
, pidchecked
= 0;
if ((uid
= p1
->p_ucred
->cr_uid
) != 0) {
for (p2
= allproc
; p2
; p2
= p2
->p_nxt
)
if (p2
->p_ucred
->cr_uid
== uid
)
for (p2
= zombproc
; p2
; p2
= p2
->p_nxt
)
if (p2
->p_ucred
->cr_uid
== uid
)
* Although process entries are dynamically created, we still keep
* a global limit on the maximum number we will create. Don't allow
* a nonprivileged user to exceed its current limit or to bring us
* within one of the global limit; don't let root exceed the limit.
* nprocs is the current number of processes, maxproc is the limit.
if (nprocs
>= maxproc
|| uid
== 0 && nprocs
>= maxproc
+ 1) {
if (count
> p1
->p_rlimit
[RLIMIT_NPROC
].rlim_cur
)
MALLOC(newproc
, struct proc
*, sizeof(struct proc
), M_PROC
, M_WAITOK
);
* Find an unused process ID. We remember a range of unused IDs
* ready to use (from nextpid+1 through pidchecked-1).
* If the process ID prototype has wrapped around,
* restart somewhat above 0, as the low-numbered procs
* tend to include daemons that don't exit.
if (nextpid
>= PID_MAX
) {
if (nextpid
>= pidchecked
) {
* Scan the active and zombie procs to check whether this pid
* is in use. Remember the lowest pid that's greater
* than nextpid, so we can avoid checking for a while.
for (; p2
!= NULL
; p2
= p2
->p_nxt
) {
while (p2
->p_pid
== nextpid
||
p2
->p_pgrp
->pg_id
== nextpid
) {
if (nextpid
>= pidchecked
)
if (p2
->p_pid
> nextpid
&& pidchecked
> p2
->p_pid
)
if (p2
->p_pgrp
->pg_id
> nextpid
&&
pidchecked
> p2
->p_pgrp
->pg_id
)
pidchecked
= p2
->p_pgrp
->pg_id
;
/* Link onto allproc (this should probably be delayed). */
p2
->p_stat
= SIDL
; /* protect against others */
p2
->p_nxt
->p_prev
= &p2
->p_nxt
; /* allproc is never NULL */
p2
->p_link
= NULL
; /* shouldn't be necessary */
p2
->p_rlink
= NULL
; /* shouldn't be necessary */
/* Insert on the hash chain. */
hash
= &pidhash
[PIDHASH(p2
->p_pid
)];
* Make a proc table entry for the new process.
* Start by zeroing the section of proc that is zero-initialized,
* then copy the section that is copied directly from the parent.
(unsigned) ((caddr_t
)&p2
->p_endzero
- (caddr_t
)&p2
->p_startzero
));
bcopy(&p1
->p_startcopy
, &p2
->p_startcopy
,
(unsigned) ((caddr_t
)&p2
->p_endcopy
- (caddr_t
)&p2
->p_startcopy
));
p2
->p_wmesg
= NULL
; /* XXX - should be in zero range */
p2
->p_spare
[0] = 0; /* XXX - should be in zero range */
p2
->p_spare
[1] = 0; /* XXX - should be in zero range */
p2
->p_spare
[2] = 0; /* XXX - should be in zero range */
p2
->p_spare
[3] = 0; /* XXX - should be in zero range */
* Duplicate sub-structures as needed.
* Increase reference counts on shared objects.
* The p_stats and p_sigacts substructs are set in vm_fork.
MALLOC(p2
->p_cred
, struct pcred
*, sizeof(struct pcred
),
bcopy(p1
->p_cred
, p2
->p_cred
, sizeof(*p2
->p_cred
));
p2
->p_cred
->p_refcnt
= 1;
* If p_limit is still copy-on-write, bump refcnt,
* otherwise get a copy that won't be modified.
* (If PL_SHAREMOD is clear, the structure is shared
if (p1
->p_limit
->p_lflags
& PL_SHAREMOD
)
p2
->p_limit
= limcopy(p1
->p_limit
);
p2
->p_limit
= p1
->p_limit
;
p2
->p_flag
= SLOAD
| (p1
->p_flag
& SHPUX
);
if (p1
->p_session
->s_ttyvp
!= NULL
&& p1
->p_flag
& SCTTY
)
p2
->p_pgrpnxt
= p1
->p_pgrpnxt
;
p2
->p_osptr
= p1
->p_cptr
;
p1
->p_cptr
->p_ysptr
= p2
;
* Copy traceflag and tracefile if enabled.
* If not inherited, these were zeroed above.
if (p1
->p_traceflag
&KTRFAC_INHERIT
) {
p2
->p_traceflag
= p1
->p_traceflag
;
if ((p2
->p_tracep
= p1
->p_tracep
) != NULL
)
p2
->p_vmspace
->p_ckey
= p1
->p_vmspace
->p_ckey
; /* XXX move this */
* This begins the section where we must prevent the parent
* Set return values for child before vm_fork,
* so they can be copied to child stack.
* We return parent pid, and mark as child in retval[1].
* NOTE: the kernel stack may be at a different location in the child
* process, and thus addresses of automatic variables (including retval)
* may be invalid after vm_fork returns in the child process.
if (vm_fork(p1
, p2
, isvfork
)) {
* Child process. Set start time and get to work.
p2
->p_stats
->p_start
= time
;
* Make child runnable and add to run queue.
* Preserve synchronization semantics of vfork.
* If waiting for child to exec or exit, set SPPWAIT
* on child, and sleep on our proc (in case of exit).
while (p2
->p_flag
& SPPWAIT
)
tsleep((caddr_t
)p1
, PWAIT
, "ppwait", 0);
* Return child pid to parent process,
* marking us as parent via retval[1].