svn commit: r351175 - head/sys/kern
Mateusz Guzik
mjg at FreeBSD.org
Sat Aug 17 18:19:50 UTC 2019
Author: mjg
Date: Sat Aug 17 18:19:49 2019
New Revision: 351175
URL: https://svnweb.freebsd.org/changeset/base/351175
Log:
fork: rework locking around do_fork
- move allproc lock into the func, it is of no use prior to it
- the code would lock p1 and p2 while holding allproc to partially
construct it after it gets added to the list. instead we can do the
work prior to adding anything.
- protect lastpid with procid_lock
As a side effect we do less work with allproc held.
Sponsored by: The FreeBSD Foundation
Modified:
head/sys/kern/kern_fork.c
Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c Sat Aug 17 17:56:43 2019 (r351174)
+++ head/sys/kern/kern_fork.c Sat Aug 17 18:19:49 2019 (r351175)
@@ -246,17 +246,24 @@ static int
fork_findpid(int flags)
{
pid_t result;
- int trypid;
+ int trypid, random;
+ /*
+ * Avoid calling arc4random with procid_lock held.
+ */
+ random = 0;
+ if (__predict_false(randompid))
+ random = arc4random() % randompid;
+
+ mtx_lock(&procid_lock);
+
trypid = lastpid + 1;
if (flags & RFHIGHPID) {
if (trypid < 10)
trypid = 10;
} else {
- if (randompid)
- trypid += arc4random() % randompid;
+ trypid += random;
}
- mtx_lock(&procid_lock);
retry:
if (trypid >= pid_max)
trypid = 2;
@@ -341,33 +348,16 @@ do_fork(struct thread *td, struct fork_req *fr, struct
struct vmspace *vm2, struct file *fp_procdesc)
{
struct proc *p1, *pptr;
- int trypid;
struct filedesc *fd;
struct filedesc_to_leader *fdtol;
struct sigacts *newsigacts;
- sx_assert(&allproc_lock, SX_XLOCKED);
-
p1 = td->td_proc;
- trypid = fork_findpid(fr->fr_flags);
- p2->p_state = PRS_NEW; /* protect against others */
- p2->p_pid = trypid;
- AUDIT_ARG_PID(p2->p_pid);
- LIST_INSERT_HEAD(&allproc, p2, p_list);
- allproc_gen++;
- sx_xlock(PIDHASHLOCK(p2->p_pid));
- LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
- sx_xunlock(PIDHASHLOCK(p2->p_pid));
- PROC_LOCK(p2);
PROC_LOCK(p1);
-
- sx_xunlock(&allproc_lock);
-
bcopy(&p1->p_startcopy, &p2->p_startcopy,
__rangeof(struct proc, p_startcopy, p_endcopy));
pargs_hold(p2->p_args);
-
PROC_UNLOCK(p1);
bzero(&p2->p_startzero,
@@ -376,8 +366,19 @@ do_fork(struct thread *td, struct fork_req *fr, struct
/* Tell the prison that we exist. */
prison_proc_hold(p2->p_ucred->cr_prison);
- PROC_UNLOCK(p2);
+ p2->p_state = PRS_NEW; /* protect against others */
+ p2->p_pid = fork_findpid(fr->fr_flags);
+ AUDIT_ARG_PID(p2->p_pid);
+ sx_xlock(&allproc_lock);
+ LIST_INSERT_HEAD(&allproc, p2, p_list);
+ allproc_gen++;
+ sx_xunlock(&allproc_lock);
+
+ sx_xlock(PIDHASHLOCK(p2->p_pid));
+ LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
+ sx_xunlock(PIDHASHLOCK(p2->p_pid));
+
tidhash_add(td2);
/*
@@ -969,8 +970,6 @@ fork1(struct thread *td, struct fork_req *fr)
newproc->p_klist = knlist_alloc(&newproc->p_mtx);
STAILQ_INIT(&newproc->p_ktr);
- sx_xlock(&allproc_lock);
-
/*
* Increment the count of procs running with this uid. Don't allow
* a nonprivileged user to exceed their current limit.
@@ -986,7 +985,6 @@ fork1(struct thread *td, struct fork_req *fr)
return (0);
fail0:
error = EAGAIN;
- sx_xunlock(&allproc_lock);
#ifdef MAC
mac_proc_destroy(newproc);
#endif
More information about the svn-src-all
mailing list