so all allocators obey it, not just uvm_pagealloc (which is increasingly
rarely called). This actually makes it a lot harder to deadlock the
machine under very heavy memory pressure (uvm_pglistalloc for 7 pages
when you have 7 pages left, for example).

I have been using variants of this  diff on my machines for months.

I have discussed doing this with ariane@ many many times. here's the
diff:

ok?
-0-


Index: uvm/uvm_page.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_page.c,v
retrieving revision 1.111
diff -u -p -r1.111 uvm_page.c
--- uvm/uvm_page.c      3 Jul 2011 18:34:14 -0000       1.111
+++ uvm/uvm_page.c      3 Jul 2011 20:14:37 -0000
@@ -76,7 +76,6 @@
 #include <sys/sched.h>
 #include <sys/kernel.h>
 #include <sys/vnode.h>
-#include <sys/mount.h>
 #include <sys/proc.h>
 
 #include <uvm/uvm.h>
@@ -885,43 +884,19 @@ uvm_pagealloc(struct uvm_object *obj, vo
        struct vm_page *pg;
        struct pglist pgl;
        int pmr_flags;
-       boolean_t use_reserve;
 
        KASSERT(obj == NULL || anon == NULL);
        KASSERT(off == trunc_page(off));
 
-       /*
-        * check to see if we need to generate some free pages waking
-        * the pagedaemon.
-        */
-       if ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freemin ||
-           ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freetarg &&
-           (uvmexp.inactive + BUFPAGES_INACT) < uvmexp.inactarg))
-               wakeup(&uvm.pagedaemon);
-
-       /*
-        * fail if any of these conditions is true:
-        * [1]  there really are no free pages, or
-        * [2]  only kernel "reserved" pages remain and
-        *        the page isn't being allocated to a kernel object.
-        * [3]  only pagedaemon "reserved" pages remain and
-        *        the requestor isn't the pagedaemon.
-        */
-
-       use_reserve = (flags & UVM_PGA_USERESERVE) ||
-               (obj && UVM_OBJ_IS_KERN_OBJECT(obj));
-       if ((uvmexp.free <= uvmexp.reserve_kernel && !use_reserve) ||
-           (uvmexp.free <= uvmexp.reserve_pagedaemon &&
-            !((curproc == uvm.pagedaemon_proc) ||
-             (curproc == syncerproc))))
-               goto fail;
-
+       /* XXX these functions should share flags */
        pmr_flags = UVM_PLA_NOWAIT;
        if (flags & UVM_PGA_ZERO)
                pmr_flags |= UVM_PLA_ZERO;
+       if (flags & UVM_PGA_USERESERVE)
+               pmr_flags |= UVM_PLA_USERESERVE;
        TAILQ_INIT(&pgl);
        if (uvm_pmr_getpages(1, 0, 0, 1, 0, 1, pmr_flags, &pgl) != 0)
-               goto fail;
+               return (NULL);
 
        pg = TAILQ_FIRST(&pgl);
        KASSERT(pg != NULL && TAILQ_NEXT(pg, pageq) == NULL);
@@ -932,10 +907,7 @@ uvm_pagealloc(struct uvm_object *obj, vo
        if (flags & UVM_PGA_ZERO)
                atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
 
-       return(pg);
-
- fail:
-       return (NULL);
+       return (pg);
 }
 
 /*
Index: uvm/uvm_pmemrange.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_pmemrange.c,v
retrieving revision 1.25
diff -u -p -r1.25 uvm_pmemrange.c
--- uvm/uvm_pmemrange.c 22 Jun 2011 00:16:47 -0000      1.25
+++ uvm/uvm_pmemrange.c 3 Jul 2011 20:14:37 -0000
@@ -19,6 +19,7 @@
 #include <sys/param.h>
 #include <uvm/uvm.h>
 #include <sys/malloc.h>
+#include <sys/mount.h>         /* for BUFPAGES defines */
 #include <sys/proc.h>          /* XXX for atomic */
 
 /*
@@ -747,6 +748,7 @@ uvm_pmr_getpages(psize_t count, paddr_t 
        int     memtype;                /* Requested memtype. */
        int     memtype_init;           /* Best memtype. */
        int     desperate;              /* True if allocation failed. */
+       int     is_pdaemon;
 #ifdef DIAGNOSTIC
        struct  vm_page *diag_prev;     /* Used during validation. */
 #endif /* DIAGNOSTIC */
@@ -762,6 +764,27 @@ uvm_pmr_getpages(psize_t count, paddr_t 
            (boundary == 0 || maxseg * boundary >= count) &&
            TAILQ_EMPTY(result));
 
+       is_pdaemon = ((curproc == uvm.pagedaemon_proc) ||
+             (curproc == syncerproc));
+
+       /*
+        * All allocations by the pagedaemon automatically get access to
+        * the kernel reserve of pages so swapping can catch up with memory
+        * exhaustion
+        */
+       if (is_pdaemon)
+               flags |= UVM_PLA_USERESERVE;
+
+       /*
+        * check to see if we need to generate some free pages waking
+        * the pagedaemon.
+        */
+       if ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freemin ||
+           ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freetarg &&
+           (uvmexp.inactive + BUFPAGES_INACT) < uvmexp.inactarg))
+               wakeup(&uvm.pagedaemon);
+
+
        /*
         * TRYCONTIG is a noop if you only want a single segment.
         * Remove it if that's the case: otherwise it'll deny the fast
@@ -835,6 +858,20 @@ retry:             /* Return point after sleeping. 
        fnsegs = 0;
 
        uvm_lock_fpageq();
+
+       /*
+        * fail if any of these conditions are true:
+        * [1]  there really are no free pages, or
+        * [2]  only kernel "reserved" pages remain and
+        *        the we are not allowed to use them.
+        * [3]  only pagedaemon "reserved" pages remain and
+        *        the requestor isn't the pagedaemon.
+        */
+       if (((uvmexp.free - ptoa(count)) <= uvmexp.reserve_kernel &&
+           (flags & UVM_PLA_USERESERVE) == 0) ||
+           ((uvmexp.free -ptoa(count)) <= uvmexp.reserve_pagedaemon &&
+           !is_pdaemon))
+               goto fail;
 
 retry_desperate:
        /*

-- 
He flung himself on his horse and rode madly off in all directions
                -- Stephen Leacock

Reply via email to