Source-Changes-HG archive

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

[src/trunk]: src/sys/uvm (try to) merge map entries in fault handler.



details:   https://anonhg.NetBSD.org/src/rev/5611c9fa2efb
branches:  trunk
changeset: 580956:5611c9fa2efb
user:      yamt <yamt%NetBSD.org@localhost>
date:      Tue May 17 13:55:33 2005 +0000

description:
(try to) merge map entries in fault handler.

diffstat:

 sys/uvm/uvm_amap.c |    8 +-
 sys/uvm/uvm_map.c  |  173 ++++++++++++++++++++++++++++++++++++++++------------
 sys/uvm/uvm_map.h  |    5 +-
 3 files changed, 142 insertions(+), 44 deletions(-)

diffs (290 lines):

diff -r 6b442fb0d8cc -r 5611c9fa2efb sys/uvm/uvm_amap.c
--- a/sys/uvm/uvm_amap.c        Tue May 17 13:54:19 2005 +0000
+++ b/sys/uvm/uvm_amap.c        Tue May 17 13:55:33 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_amap.c,v 1.60 2005/05/11 13:02:25 yamt Exp $       */
+/*     $NetBSD: uvm_amap.c,v 1.61 2005/05/17 13:55:33 yamt Exp $       */
 
 /*
  *
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.60 2005/05/11 13:02:25 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.61 2005/05/17 13:55:33 yamt Exp $");
 
 #undef UVM_AMAP_INLINE         /* enable/disable amap inlines */
 
@@ -788,6 +788,10 @@
                                UVM_MAP_CLIP_END(map, entry, endva, NULL);
                }
 
+               if (uvm_mapent_trymerge(map, entry, UVM_MERGE_COPYING)) {
+                       return;
+               }
+
                UVMHIST_LOG(maphist, "<- done [creating new amap 0x%x->0x%x]",
                entry->start, entry->end, 0, 0);
                entry->aref.ar_pageoff = 0;
diff -r 6b442fb0d8cc -r 5611c9fa2efb sys/uvm/uvm_map.c
--- a/sys/uvm/uvm_map.c Tue May 17 13:54:19 2005 +0000
+++ b/sys/uvm/uvm_map.c Tue May 17 13:55:33 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_map.c,v 1.193 2005/05/17 13:54:19 yamt Exp $       */
+/*     $NetBSD: uvm_map.c,v 1.194 2005/05/17 13:55:33 yamt Exp $       */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.193 2005/05/17 13:54:19 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.194 2005/05/17 13:55:33 yamt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_uvmhist.h"
@@ -188,6 +188,22 @@
        (((map)->flags & VM_MAP_INTRSAFE) || (map) == kernel_map)
 
 /*
+ * UVM_ET_ISCOMPATIBLE: check some requirements for map entry merging
+ */
+
+#define        UVM_ET_ISCOMPATIBLE(ent, type, uobj, meflags, \
+    prot, maxprot, inh, adv, wire) \
+       ((ent)->etype == (type) && \
+       (((ent)->flags ^ (meflags)) & (UVM_MAP_NOMERGE | UVM_MAP_QUANTUM)) \
+       == 0 && \
+       (ent)->object.uvm_obj == (uobj) && \
+       (ent)->protection == (prot) && \
+       (ent)->max_protection == (maxprot) && \
+       (ent)->inheritance == (inh) && \
+       (ent)->advice == (adv) && \
+       (ent)->wired_count == (wire))
+
+/*
  * uvm_map_entry_link: insert entry into a map
  *
  * => map must be locked
@@ -509,10 +525,10 @@
 }
 
 /*
- * uvm_mapent_free_merge: free merged map entry
+ * uvm_mapent_free_merged: free merged map entry
  *
  * => keep the entry if needed.
- * => caller shouldn't hold map locked.
+ * => caller shouldn't hold map locked if VM_MAP_USE_KMAPENT(map) is true.
  */
 
 static __inline void
@@ -964,7 +980,6 @@
        const int amapwaitflag = (flags & UVM_FLAG_NOWAIT) ?
            AMAP_EXTEND_NOWAIT : 0;
        const int advice = UVM_ADVICE(flags);
-       const int meflagmask = UVM_MAP_NOMERGE | UVM_MAP_QUANTUM;
        const int meflagval = (flags & UVM_FLAG_QUANTUM) ?
            UVM_MAP_QUANTUM : 0;
 
@@ -1010,30 +1025,15 @@
        if (flags & UVM_FLAG_NOMERGE)
                goto nomerge;
 
-       if (prev_entry->etype == newetype &&
-           prev_entry->end == start &&
+       if (prev_entry->end == start &&
            prev_entry != &map->header &&
-           prev_entry->object.uvm_obj == uobj) {
-
-               if ((prev_entry->flags & meflagmask) != meflagval)
-                       goto forwardmerge;
+           UVM_ET_ISCOMPATIBLE(prev_entry, newetype, uobj, meflagval,
+           prot, maxprot, inherit, advice, 0)) {
 
                if (uobj && prev_entry->offset +
                    (prev_entry->end - prev_entry->start) != uoffset)
                        goto forwardmerge;
 
-               if (prev_entry->protection != prot ||
-                   prev_entry->max_protection != maxprot)
-                       goto forwardmerge;
-
-               if (prev_entry->inheritance != inherit ||
-                   prev_entry->advice != advice)
-                       goto forwardmerge;
-
-               /* wiring status must match (new area is unwired) */
-               if (VM_MAPENT_ISWIRED(prev_entry))
-                       goto forwardmerge;
-
                /*
                 * can't extend a shared amap.  note: no need to lock amap to
                 * look at refs since we don't care about its exact value.
@@ -1076,29 +1076,14 @@
        }
 
 forwardmerge:
-       if (prev_entry->next->etype == newetype &&
-           prev_entry->next->start == (start + size) &&
+       if (prev_entry->next->start == (start + size) &&
            prev_entry->next != &map->header &&
-           prev_entry->next->object.uvm_obj == uobj) {
-
-               if ((prev_entry->next->flags & meflagmask) != meflagval)
-                       goto nomerge;
+           UVM_ET_ISCOMPATIBLE(prev_entry->next, newetype, uobj, meflagval,
+           prot, maxprot, inherit, advice, 0)) {
 
                if (uobj && prev_entry->next->offset != uoffset + size)
                        goto nomerge;
 
-               if (prev_entry->next->protection != prot ||
-                   prev_entry->next->max_protection != maxprot)
-                       goto nomerge;
-
-               if (prev_entry->next->inheritance != inherit ||
-                   prev_entry->next->advice != advice)
-                       goto nomerge;
-
-               /* wiring status must match (new area is unwired) */
-               if (VM_MAPENT_ISWIRED(prev_entry->next))
-                       goto nomerge;
-
                /*
                 * can't extend a shared amap.  note: no need to lock amap to
                 * look at refs since we don't care about its exact value.
@@ -4376,6 +4361,112 @@
                uvm_kmapent_free(UMR_GETENTRY(umr));
 }
 
+/*
+ * uvm_mapent_trymerge: try to merge an entry with its neighbors.
+ *
+ * => called with map locked.
+ * => return non zero if successfully merged.
+ */
+
+int
+uvm_mapent_trymerge(struct vm_map *map, struct vm_map_entry *entry, int flags)
+{
+       struct uvm_object *uobj;
+       struct vm_map_entry *next;
+       struct vm_map_entry *prev;
+       int merged = 0;
+       boolean_t copying;
+       int newetype;
+
+       if (VM_MAP_USE_KMAPENT(map)) {
+               return 0;
+       }
+       if (entry->aref.ar_amap != NULL) {
+               return 0;
+       }
+       if ((entry->flags & UVM_MAP_NOMERGE) != 0) {
+               return 0;
+       }
+
+       uobj = entry->object.uvm_obj;
+       copying = (flags & UVM_MERGE_COPYING) != 0;
+       newetype = copying ? (entry->etype & ~UVM_ET_NEEDSCOPY) : entry->etype;
+
+       next = entry->next;
+       if (next != &map->header &&
+           next->start == entry->end &&
+           ((copying && next->aref.ar_amap != NULL &&
+           amap_refs(next->aref.ar_amap) == 1) ||
+           (!copying && next->aref.ar_amap == NULL)) &&
+           UVM_ET_ISCOMPATIBLE(next, newetype,
+           uobj, entry->flags, entry->protection,
+           entry->max_protection, entry->inheritance, entry->advice,
+           entry->wired_count)) {
+               int error;
+
+               if (copying) {
+                       error = amap_extend(next,
+                           entry->end - entry->start,
+                           AMAP_EXTEND_NOWAIT|AMAP_EXTEND_BACKWARDS);
+               } else {
+                       error = 0;
+               }
+               if (error == 0) {
+                       if (uobj && uobj->pgops->pgo_detach) {
+                               uobj->pgops->pgo_detach(uobj);
+                       }
+
+                       entry->end = next->end;
+                       uvm_map_entry_unlink(map, next);
+                       if (copying) {
+                               entry->aref = next->aref;
+                               entry->etype &= ~UVM_ET_NEEDSCOPY;
+                       }
+                       uvm_tree_sanity(map, "trymerge forwardmerge");
+                       uvm_mapent_free_merged(map, next);
+                       merged++;
+               }
+       }
+
+       prev = entry->prev;
+       if (prev != &map->header &&
+           prev->end == entry->start &&
+           ((copying && !merged && prev->aref.ar_amap != NULL &&
+           amap_refs(prev->aref.ar_amap) == 1) ||
+           (!copying && prev->aref.ar_amap == NULL)) &&
+           UVM_ET_ISCOMPATIBLE(prev, newetype,
+           uobj, entry->flags, entry->protection,
+           entry->max_protection, entry->inheritance, entry->advice,
+           entry->wired_count)) {
+               int error;
+
+               if (copying) {
+                       error = amap_extend(prev,
+                           entry->end - entry->start,
+                           AMAP_EXTEND_NOWAIT|AMAP_EXTEND_FORWARDS);
+               } else {
+                       error = 0;
+               }
+               if (error == 0) {
+                       if (uobj && uobj->pgops->pgo_detach) {
+                               uobj->pgops->pgo_detach(uobj);
+                       }
+
+                       entry->start = prev->start;
+                       uvm_map_entry_unlink(map, prev);
+                       if (copying) {
+                               entry->aref = prev->aref;
+                               entry->etype &= ~UVM_ET_NEEDSCOPY;
+                       }
+                       uvm_tree_sanity(map, "trymerge backmerge");
+                       uvm_mapent_free_merged(map, prev);
+                       merged++;
+               }
+       }
+
+       return merged;
+}
+
 #if defined(DDB)
 
 /*
diff -r 6b442fb0d8cc -r 5611c9fa2efb sys/uvm/uvm_map.h
--- a/sys/uvm/uvm_map.h Tue May 17 13:54:19 2005 +0000
+++ b/sys/uvm/uvm_map.h Tue May 17 13:55:33 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_map.h,v 1.46 2005/04/01 11:59:39 yamt Exp $        */
+/*     $NetBSD: uvm_map.h,v 1.47 2005/05/17 13:55:33 yamt Exp $        */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -370,6 +370,9 @@
 void           uvm_mapent_unreserve(struct vm_map *,
                    struct uvm_mapent_reservation *);
 
+int            uvm_mapent_trymerge(struct vm_map *,
+                   struct vm_map_entry *, int);
+#define        UVM_MERGE_COPYING       1
 
 #endif /* _KERNEL */
 



Home | Main Index | Thread Index | Old Index