On Tue, Jun 16, 2015 at 23:57 +0200, Mark Kettenis wrote:
> You're definitely on to something.  It certainly looks like your diff
> fixes the bug.  However, if there is no constraint, it would make
> sense to pick a page from the size tree of the right type.  Not sure
> if that optimization would really matter though.

How about the following patch? It adds an opportunistic size tree check
before the address tree search. If there are no constraints, the
opportunistically checked entry will be selected directly.

The updated patch does not seem to have any clear impact on
performance, at least when there is no heavy memory contention. In my
cursory tests, kernel build times were effectively the same on an amd64
with and without the fix. The octeon fared similarly.


Index: uvm/uvm_pmemrange.c
===================================================================
RCS file: src/sys/uvm/uvm_pmemrange.c,v
retrieving revision 1.44
diff -u -p -r1.44 uvm_pmemrange.c
--- uvm/uvm_pmemrange.c 13 Nov 2014 00:47:44 -0000      1.44
+++ uvm/uvm_pmemrange.c 17 Jun 2015 07:12:14 -0000
@@ -1708,11 +1708,35 @@ uvm_pmr_get1page(psize_t count, int memt
                                found = TAILQ_NEXT(found, pageq);
 
                        if (found == NULL) {
-                               found = RB_ROOT(&pmr->size[memtype]);
-                               /* Size tree gives pg[1] instead of pg[0] */
+                               /*
+                                * Check if the size tree contains a range
+                                * that intersects with the boundaries. As the
+                                * allocation is for any page, try the smallest
+                                * range so that large ranges are preserved for
+                                * more constrained cases. Only one entry is
+                                * checked here, to avoid a brute-force search.
+                                *
+                                * Note that a size tree gives pg[1] instead of
+                                * pg[0].
+                                */
+                               found = RB_MIN(uvm_pmr_size,
+                                   &pmr->size[memtype]);
                                if (found != NULL) {
                                        found--;
-
+                                       if (!PMR_INTERSECTS_WITH(
+                                           atop(VM_PAGE_TO_PHYS(found)),
+                                           atop(VM_PAGE_TO_PHYS(found)) +
+                                           found->fpgsz, start, end))
+                                               found = NULL;
+                               }
+                       }
+                       if (found == NULL) {
+                               /*
+                                * Try address-guided search to meet the page
+                                * number constraints.
+                                */
+                               found = RB_ROOT(&pmr->addr);
+                               if (found != NULL) {
                                        found = uvm_pmr_rootupdate(pmr, found,
                                            start, end, memtype);
                                }

Reply via email to