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

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to