Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Sep 2018 18:29:39 +0000 (UTC)
From:      Alan Cox <alc@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r338431 - head/sys/vm
Message-ID:  <201809021829.w82ITdvi047687@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: alc
Date: Sun Sep  2 18:29:38 2018
New Revision: 338431
URL: https://svnweb.freebsd.org/changeset/base/338431

Log:
  Recent changes have created, for the first time, physical memory segments
  that can be coalesced.  To be clear, fragmentation of phys_avail[] is not
  the cause.  This fragmentation of vm_phys_segs[] arises from the "special"
  calls to vm_phys_add_seg(), in other words, not those that derive directly
  from phys_avail[], but those that we create for the initial kernel page
  table pages and now for the kernel and modules loaded at boot time.  Since
  we sometimes iterate over the physical memory segments, coalescing these
  segments at initialization time is a worthwhile change.
  
  Reviewed by:	kib, markj
  Approved by:	re (rgrimes)
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D16976

Modified:
  head/sys/vm/vm_phys.c

Modified: head/sys/vm/vm_phys.c
==============================================================================
--- head/sys/vm/vm_phys.c	Sun Sep  2 17:02:13 2018	(r338430)
+++ head/sys/vm/vm_phys.c	Sun Sep  2 18:29:38 2018	(r338431)
@@ -460,7 +460,7 @@ void
 vm_phys_init(void)
 {
 	struct vm_freelist *fl;
-	struct vm_phys_seg *seg;
+	struct vm_phys_seg *end_seg, *prev_seg, *seg, *tmp_seg;
 	u_long npages;
 	int dom, flind, freelist, oind, pind, segind;
 
@@ -544,6 +544,29 @@ vm_phys_init(void)
 			    ("vm_phys_init: DEFAULT flind < 0"));
 		}
 		seg->free_queues = &vm_phys_free_queues[seg->domain][flind];
+	}
+
+	/*
+	 * Coalesce physical memory segments that are contiguous and share the
+	 * same per-domain free queues.
+	 */
+	prev_seg = vm_phys_segs;
+	seg = &vm_phys_segs[1];
+	end_seg = &vm_phys_segs[vm_phys_nsegs];
+	while (seg < end_seg) {
+		if (prev_seg->end == seg->start &&
+		    prev_seg->free_queues == seg->free_queues) {
+			prev_seg->end = seg->end;
+			KASSERT(prev_seg->domain == seg->domain,
+			    ("vm_phys_init: free queues cannot span domains"));
+			vm_phys_nsegs--;
+			end_seg--;
+			for (tmp_seg = seg; tmp_seg < end_seg; tmp_seg++)
+				*tmp_seg = *(tmp_seg + 1);
+		} else {
+			prev_seg = seg;
+			seg++;
+		}
 	}
 
 	/*



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