On 9/3/2014 3:18 AM, Konstantin Belousov wrote: > 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); >
Thanks! -- Regards, Bryan Drewery
signature.asc
Description: OpenPGP digital signature