Fix crack-smoking code that was panicing on the quad xeon:

- If either of proc or kse are NULL during thread_exit(), then
          the kernel is going to fault because parts of the function
          assume they aren't NULL.  Instead, just assert they aren't NULL
          (as well as the kse group) and assume they are in all of the
          code.  It doesn't make sense for them to be NULL here anyways.
        - Move the PROC_UNLOCK(p) up above clearing td_proc, etc. since
          otherwise we will panic if the proc's lock is contested.

Submitted by:	jhb@freebsd.org
This commit is contained in:
julian 2002-08-29 19:49:53 +00:00
parent 1986a94b82
commit a9901abd65
2 changed files with 46 additions and 52 deletions

View File

@ -320,6 +320,9 @@ thread_exit(void)
ke = td->td_kse;
mtx_assert(&sched_lock, MA_OWNED);
KASSERT(p != NULL, ("thread exiting without a process"));
KASSERT(ke != NULL, ("thread exiting without a kse"));
KASSERT(kg != NULL, ("thread exiting without a kse group"));
PROC_LOCK_ASSERT(p, MA_OWNED);
CTR1(KTR_PROC, "thread_exit: thread %p", td);
KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
@ -331,41 +334,35 @@ thread_exit(void)
cpu_thread_exit(td); /* XXXSMP */
/* Reassign this thread's KSE. */
if (ke != NULL) {
ke->ke_thread = NULL;
td->td_kse = NULL;
ke->ke_state = KES_UNQUEUED;
kse_reassign(ke);
}
ke->ke_thread = NULL;
td->td_kse = NULL;
ke->ke_state = KES_UNQUEUED;
kse_reassign(ke);
/* Unlink this thread from its proc. and the kseg */
if (p != NULL) {
TAILQ_REMOVE(&p->p_threads, td, td_plist);
p->p_numthreads--;
if (kg != NULL) {
TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
kg->kg_numthreads--;
}
/*
* The test below is NOT true if we are the
* sole exiting thread. P_STOPPED_SNGL is unset
* in exit1() after it is the only survivor.
*/
if (P_SHOULDSTOP(p) == P_STOPPED_SNGL) {
if (p->p_numthreads == p->p_suspcount) {
TAILQ_REMOVE(&p->p_suspended,
p->p_singlethread, td_runq);
setrunqueue(p->p_singlethread);
p->p_suspcount--;
}
TAILQ_REMOVE(&p->p_threads, td, td_plist);
p->p_numthreads--;
TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
kg->kg_numthreads--;
/*
* The test below is NOT true if we are the
* sole exiting thread. P_STOPPED_SNGL is unset
* in exit1() after it is the only survivor.
*/
if (P_SHOULDSTOP(p) == P_STOPPED_SNGL) {
if (p->p_numthreads == p->p_suspcount) {
TAILQ_REMOVE(&p->p_suspended,
p->p_singlethread, td_runq);
setrunqueue(p->p_singlethread);
p->p_suspcount--;
}
}
PROC_UNLOCK(p);
td->td_state = TDS_SURPLUS;
td->td_proc = NULL;
td->td_ksegrp = NULL;
td->td_last_kse = NULL;
ke->ke_tdspare = td;
PROC_UNLOCK(p);
cpu_throw();
/* NOTREACHED */
}

View File

@ -320,6 +320,9 @@ thread_exit(void)
ke = td->td_kse;
mtx_assert(&sched_lock, MA_OWNED);
KASSERT(p != NULL, ("thread exiting without a process"));
KASSERT(ke != NULL, ("thread exiting without a kse"));
KASSERT(kg != NULL, ("thread exiting without a kse group"));
PROC_LOCK_ASSERT(p, MA_OWNED);
CTR1(KTR_PROC, "thread_exit: thread %p", td);
KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
@ -331,41 +334,35 @@ thread_exit(void)
cpu_thread_exit(td); /* XXXSMP */
/* Reassign this thread's KSE. */
if (ke != NULL) {
ke->ke_thread = NULL;
td->td_kse = NULL;
ke->ke_state = KES_UNQUEUED;
kse_reassign(ke);
}
ke->ke_thread = NULL;
td->td_kse = NULL;
ke->ke_state = KES_UNQUEUED;
kse_reassign(ke);
/* Unlink this thread from its proc. and the kseg */
if (p != NULL) {
TAILQ_REMOVE(&p->p_threads, td, td_plist);
p->p_numthreads--;
if (kg != NULL) {
TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
kg->kg_numthreads--;
}
/*
* The test below is NOT true if we are the
* sole exiting thread. P_STOPPED_SNGL is unset
* in exit1() after it is the only survivor.
*/
if (P_SHOULDSTOP(p) == P_STOPPED_SNGL) {
if (p->p_numthreads == p->p_suspcount) {
TAILQ_REMOVE(&p->p_suspended,
p->p_singlethread, td_runq);
setrunqueue(p->p_singlethread);
p->p_suspcount--;
}
TAILQ_REMOVE(&p->p_threads, td, td_plist);
p->p_numthreads--;
TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
kg->kg_numthreads--;
/*
* The test below is NOT true if we are the
* sole exiting thread. P_STOPPED_SNGL is unset
* in exit1() after it is the only survivor.
*/
if (P_SHOULDSTOP(p) == P_STOPPED_SNGL) {
if (p->p_numthreads == p->p_suspcount) {
TAILQ_REMOVE(&p->p_suspended,
p->p_singlethread, td_runq);
setrunqueue(p->p_singlethread);
p->p_suspcount--;
}
}
PROC_UNLOCK(p);
td->td_state = TDS_SURPLUS;
td->td_proc = NULL;
td->td_ksegrp = NULL;
td->td_last_kse = NULL;
ke->ke_tdspare = td;
PROC_UNLOCK(p);
cpu_throw();
/* NOTREACHED */
}