Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jun 2009 12:07:52 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r193906 - in stable/7/sys: . amd64/linux32 contrib/pf dev/ath/ath_hal dev/cxgb i386/linux kern sys
Message-ID:  <200906101207.n5AC7q9M012551@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Jun 10 12:07:52 2009
New Revision: 193906
URL: http://svn.freebsd.org/changeset/base/193906

Log:
  MFC r185647;
  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.
  
  Silent the assertion by using conditional variable allocated in the
  child. Broadcast the variable event on exec() and exit().
  
  MFC r188750:
  Adapt linux emulation to use cv for vfork wait.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/amd64/linux32/linux32_machdep.c
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/i386/linux/linux_machdep.c
  stable/7/sys/kern/kern_exec.c
  stable/7/sys/kern/kern_exit.c
  stable/7/sys/kern/kern_fork.c
  stable/7/sys/kern/kern_proc.c
  stable/7/sys/sys/proc.h

Modified: stable/7/sys/amd64/linux32/linux32_machdep.c
==============================================================================
--- stable/7/sys/amd64/linux32/linux32_machdep.c	Wed Jun 10 12:03:55 2009	(r193905)
+++ stable/7/sys/amd64/linux32/linux32_machdep.c	Wed Jun 10 12:07:52 2009	(r193906)
@@ -537,7 +537,7 @@ linux_vfork(struct thread *td, struct li
 	/* wait for the children to exit, ie. emulate vfork */
 	PROC_LOCK(p2);
 	while (p2->p_flag & P_PPWAIT)
-	   	msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+		cv_wait(&p2->p_pwait, &p2->p_mtx);
 	PROC_UNLOCK(p2);
 
 	return (0);
@@ -726,7 +726,7 @@ linux_clone(struct thread *td, struct li
 		/* wait for the children to exit, ie. emulate vfork */
 		PROC_LOCK(p2);
 		while (p2->p_flag & P_PPWAIT)
-			msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+			cv_wait(&p2->p_pwait, &p2->p_mtx);
 		PROC_UNLOCK(p2);
 	}
 

Modified: stable/7/sys/i386/linux/linux_machdep.c
==============================================================================
--- stable/7/sys/i386/linux/linux_machdep.c	Wed Jun 10 12:03:55 2009	(r193905)
+++ stable/7/sys/i386/linux/linux_machdep.c	Wed Jun 10 12:07:52 2009	(r193906)
@@ -376,7 +376,7 @@ linux_vfork(struct thread *td, struct li
 	/* wait for the children to exit, ie. emulate vfork */
 	PROC_LOCK(p2);
 	while (p2->p_flag & P_PPWAIT)
-	   	msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+		cv_wait(&p2->p_pwait, &p2->p_mtx);
 	PROC_UNLOCK(p2);
 
 	return (0);
@@ -581,7 +581,7 @@ linux_clone(struct thread *td, struct li
    	   	/* wait for the children to exit, ie. emulate vfork */
    	   	PROC_LOCK(p2);
 		while (p2->p_flag & P_PPWAIT)
-   		   	msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+			cv_wait(&p2->p_pwait, &p2->p_mtx);
 		PROC_UNLOCK(p2);
 	}
 

Modified: stable/7/sys/kern/kern_exec.c
==============================================================================
--- stable/7/sys/kern/kern_exec.c	Wed Jun 10 12:03:55 2009	(r193905)
+++ stable/7/sys/kern/kern_exec.c	Wed Jun 10 12:07:52 2009	(r193906)
@@ -559,7 +559,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: stable/7/sys/kern/kern_exit.c
==============================================================================
--- stable/7/sys/kern/kern_exit.c	Wed Jun 10 12:03:55 2009	(r193905)
+++ stable/7/sys/kern/kern_exit.c	Wed Jun 10 12:07:52 2009	(r193906)
@@ -550,6 +550,7 @@ retry:
 	 * proc lock.
 	 */
 	wakeup(p->p_pptr);
+	cv_broadcast(&p->p_pwait);
 	PROC_SLOCK(p->p_pptr);
 	sched_exit(p->p_pptr, td);
 	PROC_SUNLOCK(p->p_pptr);
@@ -783,6 +784,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: stable/7/sys/kern/kern_fork.c
==============================================================================
--- stable/7/sys/kern/kern_fork.c	Wed Jun 10 12:03:55 2009	(r193905)
+++ stable/7/sys/kern/kern_fork.c	Wed Jun 10 12:07:52 2009	(r193906)
@@ -744,7 +744,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: stable/7/sys/kern/kern_proc.c
==============================================================================
--- stable/7/sys/kern/kern_proc.c	Wed Jun 10 12:03:55 2009	(r193905)
+++ stable/7/sys/kern/kern_proc.c	Wed Jun 10 12:07:52 2009	(r193906)
@@ -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: stable/7/sys/sys/proc.h
==============================================================================
--- stable/7/sys/sys/proc.h	Wed Jun 10 12:03:55 2009	(r193905)
+++ stable/7/sys/sys/proc.h	Wed Jun 10 12:07:52 2009	(r193906)
@@ -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
@@ -598,6 +599,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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906101207.n5AC7q9M012551>