diff options
author | jhb <jhb@FreeBSD.org> | 2001-03-07 05:21:47 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-03-07 05:21:47 +0000 |
commit | da8355ca0f95dda99540d8f3e6cc1619464e2e8c (patch) | |
tree | ec51bed70cf551b4251aae2eec341765827f2407 /sys | |
parent | 79952149e8d94375de440960fe74166ef8f12919 (diff) | |
download | FreeBSD-src-da8355ca0f95dda99540d8f3e6cc1619464e2e8c.zip FreeBSD-src-da8355ca0f95dda99540d8f3e6cc1619464e2e8c.tar.gz |
- Don't hold the proc lock across VREF and the fd* functions to avoid lock
order reversals.
- Add some preliminary locking in the !RF_PROC case.
- Protect p_estcpu with sched_lock.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_fork.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index cc90a52..c6776de 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -207,6 +207,7 @@ fork1(p1, flags, procp) int ok; static int pidchecked = 0; struct forklist *ep; + struct filedesc *fd; /* Can't copy and clear */ if ((flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) @@ -226,8 +227,10 @@ fork1(p1, flags, procp) if (flags & RFCFDG) { struct filedesc *fdtmp; fdtmp = fdinit(p1); + PROC_LOCK(p1); fdfree(p1); p1->p_fd = fdtmp; + PROC_UNLOCK(p1); } /* @@ -237,8 +240,10 @@ fork1(p1, flags, procp) if (p1->p_fd->fd_refcnt > 1) { struct filedesc *newfd; newfd = fdcopy(p1); + PROC_LOCK(p1); fdfree(p1); p1->p_fd = newfd; + PROC_UNLOCK(p1); } } *procp = NULL; @@ -456,15 +461,19 @@ again: /* bump references to the text vnode (for procfs) */ p2->p_textvp = p1->p_textvp; + PROC_UNLOCK(p1); + PROC_UNLOCK(p2); if (p2->p_textvp) VREF(p2->p_textvp); if (flags & RFCFDG) - p2->p_fd = fdinit(p1); + fd = fdinit(p1); else if (flags & RFFDG) - p2->p_fd = fdcopy(p1); + fd = fdcopy(p1); else - p2->p_fd = fdshare(p1); + fd = fdshare(p1); + PROC_LOCK(p2); + p2->p_fd = fd; /* * If p_limit is still copy-on-write, bump refcnt, @@ -472,6 +481,7 @@ again: * (If PL_SHAREMOD is clear, the structure is shared * copy-on-write.) */ + PROC_LOCK(p1); if (p1->p_limit->p_lflags & PL_SHAREMOD) p2->p_limit = limcopy(p1->p_limit); else { @@ -526,15 +536,22 @@ again: */ if (p1->p_traceflag & KTRFAC_INHERIT) { p2->p_traceflag = p1->p_traceflag; - if ((p2->p_tracep = p1->p_tracep) != NULL) + if ((p2->p_tracep = p1->p_tracep) != NULL) { + PROC_UNLOCK(p1); + PROC_UNLOCK(p2); VREF(p2->p_tracep); + PROC_LOCK(p2); + PROC_LOCK(p1); + } } #endif /* * set priority of child to be that of parent */ + mtx_lock_spin(&sched_lock); p2->p_estcpu = p1->p_estcpu; + mtx_unlock_spin(&sched_lock); /* * This begins the section where we must prevent the parent |