Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/uvm - uvmspace_exec(), uvmspace_free(): if pmap_remove_a...



details:   https://anonhg.NetBSD.org/src/rev/622acb2ace69
branches:  trunk
changeset: 745857:622acb2ace69
user:      ad <ad%NetBSD.org@localhost>
date:      Sat Mar 14 14:15:43 2020 +0000

description:
- uvmspace_exec(), uvmspace_free(): if pmap_remove_all() returns true the
  pmap is emptied.  Pass UVM_FLAG_VAONLY when clearing out the map and avoid
  needless extra work to tear down each mapping individually.

- uvm_map_lookup_entry(): remove the code to do a linear scan of map entries
  for small maps, in preference to using the RB tree.  It's questionable,
  and I think the code is almost never triggered because the average number
  of map entries has probably exceeded the hard-coded threshold for quite
  some time.

- vm_map_entry: get it aligned on a cacheline boundary, and cluster fields
  used during rbtree lookup at the beginning.

diffstat:

 sys/uvm/uvm_map.c |  125 +++++++++++++++--------------------------------------
 sys/uvm/uvm_map.h |   22 +++++---
 2 files changed, 48 insertions(+), 99 deletions(-)

diffs (280 lines):

diff -r 43c248b1ffe8 -r 622acb2ace69 sys/uvm/uvm_map.c
--- a/sys/uvm/uvm_map.c Sat Mar 14 14:05:42 2020 +0000
+++ b/sys/uvm/uvm_map.c Sat Mar 14 14:15:43 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_map.c,v 1.372 2020/02/23 15:46:43 ad Exp $ */
+/*     $NetBSD: uvm_map.c,v 1.373 2020/03/14 14:15:43 ad Exp $ */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.372 2020/02/23 15:46:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.373 2020/03/14 14:15:43 ad Exp $");
 
 #include "opt_ddb.h"
 #include "opt_pax.h"
@@ -141,10 +141,8 @@
 UVMMAP_EVCNT_DEFINE(map_call)
 UVMMAP_EVCNT_DEFINE(mlk_call)
 UVMMAP_EVCNT_DEFINE(mlk_hint)
-UVMMAP_EVCNT_DEFINE(mlk_list)
 UVMMAP_EVCNT_DEFINE(mlk_tree)
 UVMMAP_EVCNT_DEFINE(mlk_treeloop)
-UVMMAP_EVCNT_DEFINE(mlk_listloop)
 
 const char vmmapbsy[] = "vmmapbsy";
 
@@ -823,8 +821,8 @@
 uvm_mapent_copy(struct vm_map_entry *src, struct vm_map_entry *dst)
 {
 
-       memcpy(dst, src, ((char *)&src->uvm_map_entry_stop_copy) -
-           ((char *)src));
+       memcpy(dst, src, sizeof(*dst));
+       dst->flags = 0;
 }
 
 #if defined(DEBUG)
@@ -940,7 +938,7 @@
         */
 
        pool_cache_bootstrap(&uvm_map_entry_cache, sizeof(struct vm_map_entry),
-           0, 0, 0, "vmmpepl", NULL, IPL_NONE, NULL, NULL, NULL);
+           coherency_unit, 0, 0, "vmmpepl", NULL, IPL_NONE, NULL, NULL, NULL);
        pool_cache_bootstrap(&uvm_vmspace_cache, sizeof(struct vmspace),
            0, 0, 0, "vmsppl", NULL, IPL_NONE, NULL, NULL, NULL);
 }
@@ -1679,7 +1677,6 @@
     struct vm_map_entry **entry        /* OUT */)
 {
        struct vm_map_entry *cur;
-       bool use_tree = false;
        UVMHIST_FUNC("uvm_map_lookup_entry");
        UVMHIST_CALLED(maphist);
 
@@ -1687,95 +1684,41 @@
            (uintptr_t)map, address, (uintptr_t)entry, 0);
 
        /*
-        * start looking either from the head of the
-        * list, or from the hint.
+        * make a quick check to see if we are already looking at
+        * the entry we want (which is usually the case).  note also
+        * that we don't need to save the hint here...  it is the
+        * same hint (unless we are at the header, in which case the
+        * hint didn't buy us anything anyway).
         */
 
        cur = map->hint;
-
-       if (cur == &map->header)
-               cur = cur->next;
-
        UVMMAP_EVCNT_INCR(mlk_call);
-       if (address >= cur->start) {
-
-               /*
-                * go from hint to end of list.
-                *
-                * but first, make a quick check to see if
-                * we are already looking at the entry we
-                * want (which is usually the case).
-                * note also that we don't need to save the hint
-                * here... it is the same hint (unless we are
-                * at the header, in which case the hint didn't
-                * buy us anything anyway).
-                */
-
-               if (cur != &map->header && cur->end > address) {
-                       UVMMAP_EVCNT_INCR(mlk_hint);
-                       *entry = cur;
-                       UVMHIST_LOG(maphist,"<- got it via hint (%#jx)",
-                           (uintptr_t)cur, 0, 0, 0);
-                       uvm_mapent_check(*entry);
-                       return (true);
-               }
-
-               if (map->nentries > 15)
-                       use_tree = true;
-       } else {
-
-               /*
-                * invalid hint.  use tree.
-                */
-               use_tree = true;
+       if (cur != &map->header &&
+           address >= cur->start && cur->end > address) {
+               UVMMAP_EVCNT_INCR(mlk_hint);
+               *entry = cur;
+               UVMHIST_LOG(maphist,"<- got it via hint (%#jx)",
+                   (uintptr_t)cur, 0, 0, 0);
+               uvm_mapent_check(*entry);
+               return (true);
        }
-
        uvm_map_check(map, __func__);
 
-       if (use_tree) {
-               /*
-                * Simple lookup in the tree.  Happens when the hint is
-                * invalid, or nentries reach a threshold.
-                */
-               UVMMAP_EVCNT_INCR(mlk_tree);
-               if (uvm_map_lookup_entry_bytree(map, address, entry)) {
-                       goto got;
-               } else {
-                       goto failed;
-               }
-       }
-
        /*
-        * search linearly
+        * lookup in the tree.
         */
 
-       UVMMAP_EVCNT_INCR(mlk_list);
-       while (cur != &map->header) {
-               UVMMAP_EVCNT_INCR(mlk_listloop);
-               if (cur->end > address) {
-                       if (address >= cur->start) {
-                               /*
-                                * save this lookup for future
-                                * hints, and return
-                                */
-
-                               *entry = cur;
-got:
-                               SAVE_HINT(map, map->hint, *entry);
-                               UVMHIST_LOG(maphist,"<- search got it (%#jx)",
-                                       (uintptr_t)cur, 0, 0, 0);
-                               KDASSERT((*entry)->start <= address);
-                               KDASSERT(address < (*entry)->end);
-                               uvm_mapent_check(*entry);
-                               return (true);
-                       }
-                       break;
-               }
-               cur = cur->next;
+       UVMMAP_EVCNT_INCR(mlk_tree);
+       if (__predict_true(uvm_map_lookup_entry_bytree(map, address, entry))) {
+               SAVE_HINT(map, map->hint, *entry);
+               UVMHIST_LOG(maphist,"<- search got it (%#jx)",
+                   (uintptr_t)cur, 0, 0, 0);
+               KDASSERT((*entry)->start <= address);
+               KDASSERT(address < (*entry)->end);
+               uvm_mapent_check(*entry);
+               return (true);
        }
-       *entry = cur->prev;
-failed:
-       SAVE_HINT(map, map->hint, *entry);
+
        UVMHIST_LOG(maphist,"<- failed!",0,0,0,0);
        KDASSERT((*entry) == &map->header || (*entry)->end <= address);
        KDASSERT((*entry)->next == &map->header ||
@@ -4176,6 +4119,7 @@
        struct proc *p = l->l_proc;
        struct vmspace *nvm, *ovm = p->p_vmspace;
        struct vm_map *map;
+       int flags;
 
        KASSERT(ovm != NULL);
 #ifdef __HAVE_CPU_VMSPACE_EXEC
@@ -4214,8 +4158,8 @@
                 * now unmap the old program
                 */
 
-               pmap_remove_all(map->pmap);
-               uvm_unmap(map, vm_map_min(map), vm_map_max(map));
+               flags = pmap_remove_all(map->pmap) ? UVM_FLAG_VAONLY : 0;
+               uvm_unmap1(map, vm_map_min(map), vm_map_max(map), flags);
                KASSERT(map->header.prev == &map->header);
                KASSERT(map->nentries == 0);
 
@@ -4271,6 +4215,7 @@
 {
        struct vm_map_entry *dead_entries;
        struct vm_map *map = &vm->vm_map;
+       int flags;
 
        UVMHIST_FUNC("uvmspace_free"); UVMHIST_CALLED(maphist);
 
@@ -4285,7 +4230,7 @@
         */
 
        map->flags |= VM_MAP_DYING;
-       pmap_remove_all(map->pmap);
+       flags = pmap_remove_all(map->pmap) ? UVM_FLAG_VAONLY : 0;
 
        /* Get rid of any SYSV shared memory segments. */
        if (uvm_shmexit && vm->vm_shm != NULL)
@@ -4293,7 +4238,7 @@
 
        if (map->nentries) {
                uvm_unmap_remove(map, vm_map_min(map), vm_map_max(map),
-                   &dead_entries, 0);
+                   &dead_entries, flags);
                if (dead_entries != NULL)
                        uvm_unmap_detach(dead_entries, 0);
        }
diff -r 43c248b1ffe8 -r 622acb2ace69 sys/uvm/uvm_map.h
--- a/sys/uvm/uvm_map.h Sat Mar 14 14:05:42 2020 +0000
+++ b/sys/uvm/uvm_map.h Sat Mar 14 14:15:43 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_map.h,v 1.78 2020/02/23 15:46:43 ad Exp $  */
+/*     $NetBSD: uvm_map.h,v 1.79 2020/03/14 14:15:43 ad Exp $  */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -125,36 +125,40 @@
  * a VM object (or sharing map) and offset into that object,
  * and user-exported inheritance and protection information.
  * Also included is control information for virtual copy operations.
+ *
+ * At runtime this is aligned on a cacheline boundary, with fields
+ * used during fault processing to do RB tree lookup clustered at
+ * the beginning.
  */
 struct vm_map_entry {
        struct rb_node          rb_node;        /* tree information */
+       vaddr_t                 start;          /* start address */
+       vaddr_t                 end;            /* end address */
        vsize_t                 gap;            /* free space after */
        vsize_t                 maxgap;         /* space in subtree */
        struct vm_map_entry     *prev;          /* previous entry */
        struct vm_map_entry     *next;          /* next entry */
-       vaddr_t                 start;          /* start address */
-       vaddr_t                 end;            /* end address */
        union {
                struct uvm_object *uvm_obj;     /* uvm object */
                struct vm_map   *sub_map;       /* belongs to another map */
        } object;                               /* object I point to */
        voff_t                  offset;         /* offset into object */
-       int                     etype;          /* entry type */
+       uint8_t                 etype;          /* entry type */
+       uint8_t                 flags;          /* flags */
+       uint8_t                 advice;         /* madvise advice */
+       uint8_t                 unused;         /* unused */
        vm_prot_t               protection;     /* protection code */
        vm_prot_t               max_protection; /* maximum protection */
        vm_inherit_t            inheritance;    /* inheritance */
        int                     wired_count;    /* can be paged if == 0 */
        struct vm_aref          aref;           /* anonymous overlay */
-       int                     advice;         /* madvise advice */
-#define uvm_map_entry_stop_copy flags
-       u_int8_t                flags;          /* flags */
+};
 
+/* flags */
 #define        UVM_MAP_KERNEL          0x01            /* kernel map entry */
 #define        UVM_MAP_STATIC          0x04            /* special static entries */
 #define        UVM_MAP_NOMERGE         0x08            /* this entry is not mergable */
 
-};
-
 #define        VM_MAPENT_ISWIRED(entry)        ((entry)->wired_count != 0)
 
 /*



Home | Main Index | Thread Index | Old Index