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

Konstantin Belousov kib at FreeBSD.org
Fri Dec 5 12:50:25 PST 2008


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.
  
  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-all mailing list