- Slightly reorder the events around the setting of PRS_ZOMBIE to be less

hokie and much more readable and expand the comment to explain why it is
  the way that it is.
- Close a race where one CPU could free the process belonging to a thread
  on another CPU that hasn't quite finished exiting yet but is beyond the
  point of setting the process state as PRS_ZOMBIE.

Reported and tested by:	ps (2)
MFC after:	3 days
This commit is contained in:
John Baldwin 2005-07-18 20:08:14 +00:00
parent 75c5e81854
commit ddf9c4f771
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=148137

View file

@ -495,18 +495,16 @@ exit1(struct thread *td, int rv)
* We have to wait until after acquiring all locks before
* changing p_state. We need to avoid all possible context
* switches (including ones from blocking on a mutex) while
* marked as a zombie.
* marked as a zombie. We also have to set the zombie state
* before we release the parent process' proc lock to avoid
* a lost wakeup. So, we first call wakeup, then we grab the
* sched lock, update the state, and release the parent process'
* proc lock.
*/
wakeup(p->p_pptr);
mtx_lock_spin(&sched_lock);
p->p_state = PRS_ZOMBIE;
critical_enter();
mtx_unlock_spin(&sched_lock);
wakeup(p->p_pptr);
PROC_UNLOCK(p->p_pptr);
mtx_lock_spin(&sched_lock);
critical_exit();
/* Do the same timestamp bookkeeping that mi_switch() would do. */
binuptime(&new_switchtime);
@ -624,6 +622,20 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
nfound++;
if (p->p_state == PRS_ZOMBIE) {
/*
* It is possible that the last thread of this
* process is still running on another CPU
* in thread_exit() after having dropped the process
* lock via PROC_UNLOCK() but before it has completed
* cpu_throw(). In that case, the other thread must
* still hold sched_lock, so simply by acquiring
* sched_lock once we will wait long enough for the
* thread to exit in that case.
*/
mtx_lock_spin(&sched_lock);
mtx_unlock_spin(&sched_lock);
td->td_retval[0] = p->p_pid;
if (status)
*status = p->p_xstat; /* convert to int */