diff options
author | julian <julian@FreeBSD.org> | 2002-08-29 19:49:53 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 2002-08-29 19:49:53 +0000 |
commit | a9901abd65684d503ef81966ede6f2b7bb982af3 (patch) | |
tree | da5eca802efcec024b6c7bd781571db5a107cb8b | |
parent | 1986a94b82132d3e7898ec24ee7e632c5e884ad7 (diff) | |
download | FreeBSD-src-a9901abd65684d503ef81966ede6f2b7bb982af3.zip FreeBSD-src-a9901abd65684d503ef81966ede6f2b7bb982af3.tar.gz |
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
-rw-r--r-- | sys/kern/kern_kse.c | 49 | ||||
-rw-r--r-- | sys/kern/kern_thread.c | 49 |
2 files changed, 46 insertions, 52 deletions
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c index 0214237..fd4f0b3 100644 --- a/sys/kern/kern_kse.c +++ b/sys/kern/kern_kse.c @@ -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 */ } diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 0214237..fd4f0b3 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -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 */ } |