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