From owner-svn-src-head@freebsd.org Thu Jan 4 18:14:59 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id BA8B5EAB06C; Thu, 4 Jan 2018 18:14:59 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 91DDB77126; Thu, 4 Jan 2018 18:14:59 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w04IEw89001610; Thu, 4 Jan 2018 18:14:58 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w04IEwWa001609; Thu, 4 Jan 2018 18:14:58 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201801041814.w04IEwWa001609@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Thu, 4 Jan 2018 18:14:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r327555 - head/sys/vm X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: head/sys/vm X-SVN-Commit-Revision: 327555 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 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: Thu, 04 Jan 2018 18:14:59 -0000 Author: kib Date: Thu Jan 4 18:14:58 2018 New Revision: 327555 URL: https://svnweb.freebsd.org/changeset/base/327555 Log: Restructure swapout tests after vm map locking was removed. Consolidate the regions covered by the process lock. Combine similar conditions tests into one, e.g. all process flags can be test with one logical operation. Add check for in-exec state, since p_vmspace is dererenced. Remove labels and goto by explicitly tracking state. Update comments. Reviewed by: alc, markj (previous version) Tested by: pho (previous version) Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D13693 Modified: head/sys/vm/vm_swapout.c Modified: head/sys/vm/vm_swapout.c ============================================================================== --- head/sys/vm/vm_swapout.c Thu Jan 4 17:58:48 2018 (r327554) +++ head/sys/vm/vm_swapout.c Thu Jan 4 18:14:58 2018 (r327555) @@ -734,126 +734,73 @@ swapout_procs(int action) struct proc *p; struct thread *td; int slptime; - bool didswap; + bool didswap, doswap; + MPASS((action & (VM_SWAP_NORMAL | VM_SWAP_IDLE)) != 0); + didswap = false; -retry: sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { - PROC_LOCK(p); /* - * Watch out for a process in - * creation. It may have no - * address space or lock yet. + * Filter out not yet fully constructed processes. Do + * not swap out held processes. Avoid processes which + * are system, exiting, execing, traced, already swapped + * out or are in the process of being swapped in or out. */ - if (p->p_state == PRS_NEW) { + PROC_LOCK(p); + if (p->p_state != PRS_NORMAL || p->p_lock != 0 || (p->p_flag & + (P_SYSTEM | P_WEXIT | P_INEXEC | P_STOPPED_SINGLE | + P_TRACED | P_SWAPPINGOUT | P_SWAPPINGIN | P_INMEM)) != + P_INMEM) { PROC_UNLOCK(p); continue; } + /* - * An aio daemon switches its - * address space while running. - * Perform a quick check whether - * a process has P_SYSTEM. - * Filter out exiting processes. + * Further consideration of this process for swap out + * requires iterating over its threads. We release + * allproc_lock here so that process creation and + * destruction are not blocked while we iterate. + * + * To later reacquire allproc_lock and resume + * iteration over the allproc list, we will first have + * to release the lock on the process. We place a + * hold on the process so that it remains in the + * allproc list while it is unlocked. */ - if ((p->p_flag & (P_SYSTEM | P_WEXIT)) != 0) { - PROC_UNLOCK(p); - continue; - } _PHOLD_LITE(p); - PROC_UNLOCK(p); sx_sunlock(&allproc_lock); - PROC_LOCK(p); - if (p->p_lock != 1 || (p->p_flag & (P_STOPPED_SINGLE | - P_TRACED | P_SYSTEM)) != 0) - goto nextproc; - /* - * Only aiod changes vmspace. However, it will be - * skipped because of the if statement above checking - * for P_SYSTEM. + * Do not swapout a realtime process. + * Guarantee swap_idle_threshold1 time in memory. + * If the system is under memory stress, or if we are + * swapping idle processes >= swap_idle_threshold2, + * then swap the process out. */ - if ((p->p_flag & (P_INMEM | P_SWAPPINGOUT | P_SWAPPINGIN)) != - P_INMEM) - goto nextproc; - - switch (p->p_state) { - default: - /* - * Don't swap out processes in any sort - * of 'special' state. - */ - break; - - case PRS_NORMAL: - /* - * do not swapout a realtime process - * Check all the thread groups.. - */ - FOREACH_THREAD_IN_PROC(p, td) { - thread_lock(td); - if (PRI_IS_REALTIME(td->td_pri_class)) { - thread_unlock(td); - goto nextproc; - } - slptime = (ticks - td->td_slptick) / hz; - /* - * Guarantee swap_idle_threshold1 - * time in memory. - */ - if (slptime < swap_idle_threshold1) { - thread_unlock(td); - goto nextproc; - } - - /* - * Do not swapout a process if it is - * waiting on a critical event of some - * kind or there is a thread whose - * pageable memory may be accessed. - * - * This could be refined to support - * swapping out a thread. - */ - if (!thread_safetoswapout(td)) { - thread_unlock(td); - goto nextproc; - } - /* - * If the system is under memory stress, - * or if we are swapping - * idle processes >= swap_idle_threshold2, - * then swap the process out. - */ - if ((action & VM_SWAP_NORMAL) == 0 && - ((action & VM_SWAP_IDLE) == 0 || - slptime < swap_idle_threshold2)) { - thread_unlock(td); - goto nextproc; - } - - thread_unlock(td); - } - - /* - * If the pageout daemon didn't free enough pages, - * or if this process is idle and the system is - * configured to swap proactively, swap it out. - */ - _PRELE(p); - if (swapout(p) == 0) - didswap = true; - PROC_UNLOCK(p); - goto retry; + doswap = true; + FOREACH_THREAD_IN_PROC(p, td) { + thread_lock(td); + slptime = (ticks - td->td_slptick) / hz; + if (PRI_IS_REALTIME(td->td_pri_class) || + slptime < swap_idle_threshold1 || + !thread_safetoswapout(td) || + ((action & VM_SWAP_NORMAL) == 0 && + slptime < swap_idle_threshold2)) + doswap = false; + thread_unlock(td); + if (!doswap) + break; } -nextproc: + if (doswap && swapout(p) == 0) + didswap = true; + PROC_UNLOCK(p); sx_slock(&allproc_lock); PRELE(p); } sx_sunlock(&allproc_lock); + /* * If we swapped something out, and another process needed memory, * then wakeup the sched process.