Date: Wed, 3 Sep 2014 08:18:08 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271000 - head/sys/kern Message-ID: <201409030818.s838I8uY084843@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Sep 3 08:18:07 2014 New Revision: 271000 URL: http://svnweb.freebsd.org/changeset/base/271000 Log: Right now, thread_single(SINGLE_EXIT) returns after the p_numthreads reaches 1. The p_numthreads counter is decremented in thread_exit() by a call to thread_unlink(). This means that the exiting threads may still execute on other CPUs when thread_single(SINGLE_EXIT) returns. As result, vmspace could be destroyed while paging structures are still used on other CPUs by exiting threads. Delay the return from thread_single(SINGLE_EXIT) until all threads are really destroyed by thread_stash() after the last switch out. The p_exitthreads counter already provides the required mechanism, move the wait from the thread_wait() (which is called from wait(2) code) into thread_single(). Reported by: many (as "panic: pmap active <addr>") Reviewed by: alc, jhb Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Modified: head/sys/kern/kern_thread.c Modified: head/sys/kern/kern_thread.c ============================================================================== --- head/sys/kern/kern_thread.c Wed Sep 3 08:14:07 2014 (r270999) +++ head/sys/kern/kern_thread.c Wed Sep 3 08:18:07 2014 (r271000) @@ -432,6 +432,7 @@ thread_exit(void) */ if (p->p_flag & P_HADTHREADS) { if (p->p_numthreads > 1) { + atomic_add_int(&td->td_proc->p_exitthreads, 1); thread_unlink(td); td2 = FIRST_THREAD_IN_PROC(p); sched_exit_thread(td2, td); @@ -452,7 +453,6 @@ thread_exit(void) } } - atomic_add_int(&td->td_proc->p_exitthreads, 1); PCPU_SET(deadthread, td); } else { /* @@ -507,14 +507,12 @@ thread_wait(struct proc *p) struct thread *td; mtx_assert(&Giant, MA_NOTOWNED); - KASSERT((p->p_numthreads == 1), ("Multiple threads in wait1()")); + KASSERT((p->p_numthreads == 1), ("multiple threads in thread_wait()")); + KASSERT((p->p_exitthreads == 0), ("p_exitthreads leaking")); td = FIRST_THREAD_IN_PROC(p); /* Lock the last thread so we spin until it exits cpu_throw(). */ thread_lock(td); thread_unlock(td); - /* Wait for any remaining threads to exit cpu_throw(). */ - while (p->p_exitthreads) - sched_relinquish(curthread); lock_profile_thread_exit(td); cpuset_rel(td->td_cpuset); td->td_cpuset = NULL; @@ -722,6 +720,17 @@ stopme: p->p_singlethread = NULL; p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT); thread_unthread(td); + + /* + * Wait for any remaining threads to exit cpu_throw(). + */ + while (p->p_exitthreads != 0) { + PROC_SUNLOCK(p); + PROC_UNLOCK(p); + sched_relinquish(td); + PROC_LOCK(p); + PROC_SLOCK(p); + } } PROC_SUNLOCK(p); return (0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409030818.s838I8uY084843>