Date: Sat, 17 Aug 2019 18:19:49 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r351175 - head/sys/kern Message-ID: <201908171819.x7HIJnAF089691@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908171819.x7HIJnAF089691>