Author: alc
Date: Fri Jul 14 02:15:48 2017
New Revision: 320980
URL: https://svnweb.freebsd.org/changeset/base/320980

Log:
  Generalize vm_page_ps_is_valid() to support testing other predicates on
  the (super)page, renaming the function to vm_page_ps_test().
  
  Reviewed by:  kib, markj
  MFC after:    1 week

Modified:
  head/sys/vm/vm_map.c
  head/sys/vm/vm_page.c
  head/sys/vm/vm_page.h

Modified: head/sys/vm/vm_map.c
==============================================================================
--- head/sys/vm/vm_map.c        Fri Jul 14 01:45:43 2017        (r320979)
+++ head/sys/vm/vm_map.c        Fri Jul 14 02:15:48 2017        (r320980)
@@ -1962,7 +1962,7 @@ vm_map_pmap_enter(vm_map_t map, vm_offset_t addr, vm_p
                            (pagesizes[p->psind] - 1)) == 0) {
                                mask = atop(pagesizes[p->psind]) - 1;
                                if (tmpidx + mask < psize &&
-                                   vm_page_ps_is_valid(p)) {
+                                   vm_page_ps_test(p, PS_ALL_VALID, NULL)) {
                                        p += mask;
                                        threshold += mask;
                                }

Modified: head/sys/vm/vm_page.c
==============================================================================
--- head/sys/vm/vm_page.c       Fri Jul 14 01:45:43 2017        (r320979)
+++ head/sys/vm/vm_page.c       Fri Jul 14 02:15:48 2017        (r320980)
@@ -3472,12 +3472,11 @@ vm_page_is_valid(vm_page_t m, int base, int size)
 }
 
 /*
- *     vm_page_ps_is_valid:
- *
- *     Returns TRUE if the entire (super)page is valid and FALSE otherwise.
+ * Returns true if all of the specified predicates are true for the entire
+ * (super)page and false otherwise.
  */
-boolean_t
-vm_page_ps_is_valid(vm_page_t m)
+bool
+vm_page_ps_test(vm_page_t m, int flags, vm_page_t skip_m)
 {
        int i, npages;
 
@@ -3490,10 +3489,25 @@ vm_page_ps_is_valid(vm_page_t m)
         * occupy adjacent entries in vm_page_array[].
         */
        for (i = 0; i < npages; i++) {
-               if (m[i].valid != VM_PAGE_BITS_ALL)
-                       return (FALSE);
+               if (&m[i] == skip_m)
+                       continue;
+               if ((flags & PS_NONE_BUSY) != 0 && vm_page_busied(&m[i]))
+                       return (false);
+               if ((flags & PS_ALL_DIRTY) != 0) {
+                       /*
+                        * Calling vm_page_test_dirty() or pmap_is_modified()
+                        * might stop this case from spuriously returning
+                        * "false".  However, that would require a write lock
+                        * on the object containing "m[i]".
+                        */
+                       if (m[i].dirty != VM_PAGE_BITS_ALL)
+                               return (false);
+               }
+               if ((flags & PS_ALL_VALID) != 0 &&
+                   m[i].valid != VM_PAGE_BITS_ALL)
+                       return (false);
        }
-       return (TRUE);
+       return (true);
 }
 
 /*

Modified: head/sys/vm/vm_page.h
==============================================================================
--- head/sys/vm/vm_page.h       Fri Jul 14 01:45:43 2017        (r320979)
+++ head/sys/vm/vm_page.h       Fri Jul 14 02:15:48 2017        (r320980)
@@ -438,6 +438,18 @@ malloc2vm_flags(int malloc_flags)
 }
 #endif
 
+/*
+ * Predicates supported by vm_page_ps_test():
+ *
+ *     PS_ALL_DIRTY is true only if the entire (super)page is dirty.
+ *     However, it can be spuriously false when the (super)page has become
+ *     dirty in the pmap but that information has not been propagated to the
+ *     machine-independent layer.
+ */
+#define        PS_ALL_DIRTY    0x1
+#define        PS_ALL_VALID    0x2
+#define        PS_NONE_BUSY    0x4
+
 void vm_page_busy_downgrade(vm_page_t m);
 void vm_page_busy_sleep(vm_page_t m, const char *msg, bool nonshared);
 void vm_page_flash(vm_page_t m);
@@ -469,7 +481,7 @@ vm_page_t vm_page_next(vm_page_t m);
 int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *);
 struct vm_pagequeue *vm_page_pagequeue(vm_page_t m);
 vm_page_t vm_page_prev(vm_page_t m);
-boolean_t vm_page_ps_is_valid(vm_page_t m);
+bool vm_page_ps_test(vm_page_t m, int flags, vm_page_t skip_m);
 void vm_page_putfake(vm_page_t m);
 void vm_page_readahead_finish(vm_page_t m);
 bool vm_page_reclaim_contig(int req, u_long npages, vm_paddr_t low,
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to