diff options
author | davidxu <davidxu@FreeBSD.org> | 2010-10-17 11:01:52 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2010-10-17 11:01:52 +0000 |
commit | c8ed8cb6af826805c05f3c01989c38878c5c158d (patch) | |
tree | 98bc1f465b25929349062dfad4a31b58f0a89e3c /sys/kern/kern_thread.c | |
parent | 0d755a144bd1f830a6e0842e888e0102f1974fe3 (diff) | |
download | FreeBSD-src-c8ed8cb6af826805c05f3c01989c38878c5c158d.zip FreeBSD-src-c8ed8cb6af826805c05f3c01989c38878c5c158d.tar.gz |
- Insert thread0 into correct thread hash link list.
- In thr_exit() and kthread_exit(), only remove thread from
hash if it can directly exit, otherwise let exit1() do it.
- In thread_suspend_check(), fix cleanup code when thread needs
to exit.
This change seems fixed the "Bad link elm " panic found by
Peter Holm.
Stress testing: pho
Diffstat (limited to 'sys/kern/kern_thread.c')
-rw-r--r-- | sys/kern/kern_thread.c | 26 |
1 files changed, 7 insertions, 19 deletions
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 40652b6..5f07590 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -746,25 +746,23 @@ thread_suspend_check(int return_instead) (p->p_flag & P_SINGLE_BOUNDARY) && return_instead) return (ERESTART); - /* If thread will exit, flush its pending signals */ - if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) - sigqueue_flush(&td->td_sigqueue); - - PROC_SLOCK(p); - thread_stopped(p); /* * If the process is waiting for us to exit, * this thread should just suicide. * Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE. */ if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) { - PROC_SUNLOCK(p); PROC_UNLOCK(p); tidhash_remove(td); PROC_LOCK(p); + tdsigcleanup(td); PROC_SLOCK(p); + thread_stopped(p); thread_exit(); } + + PROC_SLOCK(p); + thread_stopped(p); if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) { if (p->p_numthreads == p->p_suspcount + 1) { thread_lock(p->p_singlethread); @@ -981,12 +979,7 @@ void tidhash_add(struct thread *td) { rw_wlock(&tidhash_lock); - thread_lock(td); - if ((td->td_flags & TDF_TIDHASH) == 0) { - LIST_INSERT_HEAD(TIDHASH(td->td_tid), td, td_hash); - td->td_flags |= TDF_TIDHASH; - } - thread_unlock(td); + LIST_INSERT_HEAD(TIDHASH(td->td_tid), td, td_hash); rw_wunlock(&tidhash_lock); } @@ -994,11 +987,6 @@ void tidhash_remove(struct thread *td) { rw_wlock(&tidhash_lock); - thread_lock(td); - if ((td->td_flags & TDF_TIDHASH) != 0) { - LIST_REMOVE(td, td_hash); - td->td_flags &= ~TDF_TIDHASH; - } - thread_unlock(td); + LIST_REMOVE(td, td_hash); rw_wunlock(&tidhash_lock); } |