svn commit: r185647 - in head/sys: kern sys

Julian Elischer julian at elischer.org
Fri Dec 5 12:54:42 PST 2008


Konstantin Belousov wrote:
> Author: kib
> Date: Fri Dec  5 20:50:24 2008
> New Revision: 185647
> URL: http://svn.freebsd.org/changeset/base/185647
> 
> Log:
>   Several threads in a process may do vfork() simultaneously. Then, all
>   parent threads sleep on the parent' struct proc until corresponding
>   child releases the vmspace. Each sleep is interlocked with proc mutex of
>   the child, that triggers assertion in the sleepq_add(). The assertion
>   requires that at any time, all simultaneous sleepers for the channel use
>   the same interlock.

We DID have a thread_single() in the fork code so that
only one thread would proceed through the fork itself at a time.
However it was removed last year as it proved to be a problem in some 
cases. Maybe we need to look at replacing it in some way.

>   
>   Silent the assertion by using conditional variable allocated in the
>   child. Broadcast the variable event on exec() and exit().
>   
>   Since struct proc * sleep wait channel is overloaded for several
>   unrelated events, I was unable to remove wakeups from the places where
>   cv_broadcast() is added, except exec().
>   
>   Reported and tested by:	ganbold
>   Suggested and reviewed by:	jhb
>   MFC after:	2 week
> 
> Modified:
>   head/sys/kern/kern_exec.c
>   head/sys/kern/kern_exit.c
>   head/sys/kern/kern_fork.c
>   head/sys/kern/kern_proc.c
>   head/sys/sys/proc.h
> 
> Modified: head/sys/kern/kern_exec.c
> ==============================================================================
> --- head/sys/kern/kern_exec.c	Fri Dec  5 20:40:02 2008	(r185646)
> +++ head/sys/kern/kern_exec.c	Fri Dec  5 20:50:24 2008	(r185647)
> @@ -609,7 +609,7 @@ interpret:
>  	p->p_flag |= P_EXEC;
>  	if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
>  		p->p_flag &= ~P_PPWAIT;
> -		wakeup(p->p_pptr);
> +		cv_broadcast(&p->p_pwait);
>  	}
>  
>  	/*
> 
> Modified: head/sys/kern/kern_exit.c
> ==============================================================================
> --- head/sys/kern/kern_exit.c	Fri Dec  5 20:40:02 2008	(r185646)
> +++ head/sys/kern/kern_exit.c	Fri Dec  5 20:50:24 2008	(r185647)
> @@ -543,6 +543,7 @@ exit1(struct thread *td, int rv)
>  	 * proc lock.
>  	 */
>  	wakeup(p->p_pptr);
> +	cv_broadcast(&p->p_pwait);
>  	sched_exit(p->p_pptr, td);
>  	PROC_SLOCK(p);
>  	p->p_state = PRS_ZOMBIE;
> @@ -774,6 +775,7 @@ loop:
>  				PROC_UNLOCK(p);
>  				tdsignal(t, NULL, SIGCHLD, p->p_ksi);
>  				wakeup(t);
> +				cv_broadcast(&p->p_pwait);
>  				PROC_UNLOCK(t);
>  				sx_xunlock(&proctree_lock);
>  				return (0);
> 
> Modified: head/sys/kern/kern_fork.c
> ==============================================================================
> --- head/sys/kern/kern_fork.c	Fri Dec  5 20:40:02 2008	(r185646)
> +++ head/sys/kern/kern_fork.c	Fri Dec  5 20:50:24 2008	(r185647)
> @@ -754,7 +754,7 @@ again:
>  	 */
>  	PROC_LOCK(p2);
>  	while (p2->p_flag & P_PPWAIT)
> -		msleep(p1, &p2->p_mtx, PWAIT, "ppwait", 0);
> +		cv_wait(&p2->p_pwait, &p2->p_mtx);
>  	PROC_UNLOCK(p2);
>  
>  	/*
> 
> Modified: head/sys/kern/kern_proc.c
> ==============================================================================
> --- head/sys/kern/kern_proc.c	Fri Dec  5 20:40:02 2008	(r185646)
> +++ head/sys/kern/kern_proc.c	Fri Dec  5 20:50:24 2008	(r185647)
> @@ -231,6 +231,7 @@ proc_init(void *mem, int size, int flags
>  	bzero(&p->p_mtx, sizeof(struct mtx));
>  	mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK);
>  	mtx_init(&p->p_slock, "process slock", NULL, MTX_SPIN | MTX_RECURSE);
> +	cv_init(&p->p_pwait, "ppwait");
>  	TAILQ_INIT(&p->p_threads);	     /* all threads in proc */
>  	EVENTHANDLER_INVOKE(process_init, p);
>  	p->p_stats = pstats_alloc();
> 
> Modified: head/sys/sys/proc.h
> ==============================================================================
> --- head/sys/sys/proc.h	Fri Dec  5 20:40:02 2008	(r185646)
> +++ head/sys/sys/proc.h	Fri Dec  5 20:50:24 2008	(r185647)
> @@ -40,6 +40,7 @@
>  
>  #include <sys/callout.h>		/* For struct callout. */
>  #include <sys/event.h>			/* For struct klist. */
> +#include <sys/condvar.h>
>  #ifndef _KERNEL
>  #include <sys/filedesc.h>
>  #endif
> @@ -540,6 +541,7 @@ struct proc {
>  	STAILQ_HEAD(, ktr_request)	p_ktr;	/* (o) KTR event queue. */
>  	LIST_HEAD(, mqueue_notifier)	p_mqnotifier; /* (c) mqueue notifiers.*/
>  	struct kdtrace_proc	*p_dtrace; /* (*) DTrace-specific data. */
> +	struct cv	p_pwait;	/* (*) wait cv for exit/exec */
>  };
>  
>  #define	p_session	p_pgrp->pg_session



More information about the svn-src-head mailing list