From owner-svn-src-head@FreeBSD.ORG Fri Dec 5 20:50:25 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1B5D81065672; Fri, 5 Dec 2008 20:50:25 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0A15D8FC12; Fri, 5 Dec 2008 20:50:25 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mB5KoOYY072653; Fri, 5 Dec 2008 20:50:24 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mB5KoOcV072648; Fri, 5 Dec 2008 20:50:24 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200812052050.mB5KoOcV072648@svn.freebsd.org> From: Konstantin Belousov Date: Fri, 5 Dec 2008 20:50:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r185647 - in head/sys: kern sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Dec 2008 20:50:25 -0000 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 /* For struct callout. */ #include /* For struct klist. */ +#include #ifndef _KERNEL #include #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