Module Name:    src
Committed By:   ad
Date:           Sat Mar 14 14:15:43 UTC 2020

Modified Files:
        src/sys/uvm: uvm_map.c uvm_map.h

Log Message:
- 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.


To generate a diff of this commit:
cvs rdiff -u -r1.372 -r1.373 src/sys/uvm/uvm_map.c
cvs rdiff -u -r1.78 -r1.79 src/sys/uvm/uvm_map.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/uvm/uvm_map.c
diff -u src/sys/uvm/uvm_map.c:1.372 src/sys/uvm/uvm_map.c:1.373
--- src/sys/uvm/uvm_map.c:1.372	Sun Feb 23 15:46:43 2020
+++ src/sys/uvm/uvm_map.c	Sat Mar 14 14:15:43 2020
@@ -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(knomerge)
 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 @@ static inline void
 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 @@ uvm_map_init_caches(void)
 	 */
 
 	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 @@ uvm_map_lookup_entry(struct vm_map *map,
     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 @@ uvm_map_lookup_entry(struct vm_map *map,
 	    (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 @@ uvmspace_exec(struct lwp *l, vaddr_t sta
 	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 @@ uvmspace_exec(struct lwp *l, vaddr_t sta
 		 * 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 @@ uvmspace_free(struct vmspace *vm)
 {
 	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 @@ uvmspace_free(struct vmspace *vm)
 	 */
 
 	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 @@ uvmspace_free(struct vmspace *vm)
 
 	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);
 	}

Index: src/sys/uvm/uvm_map.h
diff -u src/sys/uvm/uvm_map.h:1.78 src/sys/uvm/uvm_map.h:1.79
--- src/sys/uvm/uvm_map.h:1.78	Sun Feb 23 15:46:43 2020
+++ src/sys/uvm/uvm_map.h	Sat Mar 14 14:15:43 2020
@@ -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)
 
 /*

Reply via email to