Module Name:    src
Committed By:   christos
Date:           Fri Jul 18 12:19:10 UTC 2014

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

Log Message:
Split out the minherit code into separate functions for readability (allows
us to indent them properly), and merge the new vm_map_entry creation into
a common function to avoid code duplication. No functional change.


To generate a diff of this commit:
cvs rdiff -u -r1.328 -r1.329 src/sys/uvm/uvm_map.c

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.328 src/sys/uvm/uvm_map.c:1.329
--- src/sys/uvm/uvm_map.c:1.328	Wed Mar  5 00:35:55 2014
+++ src/sys/uvm/uvm_map.c	Fri Jul 18 08:19:09 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_map.c,v 1.328 2014/03/05 05:35:55 matt Exp $	*/
+/*	$NetBSD: uvm_map.c,v 1.329 2014/07/18 12:19:09 christos 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.328 2014/03/05 05:35:55 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.329 2014/07/18 12:19:09 christos Exp $");
 
 #include "opt_ddb.h"
 #include "opt_uvmhist.h"
@@ -4183,6 +4183,168 @@ uvmspace_free(struct vmspace *vm)
 	pool_cache_put(&uvm_vmspace_cache, vm);
 }
 
+static struct vm_map_entry *
+uvm_mapent_clone(struct vm_map *new_map, struct vm_map_entry *old_entry,
+    int flags)
+{
+	struct vm_map_entry *new_entry;
+
+	new_entry = uvm_mapent_alloc(new_map, 0);
+	/* old_entry -> new_entry */
+	uvm_mapent_copy(old_entry, new_entry);
+
+	/* new pmap has nothing wired in it */
+	new_entry->wired_count = 0;
+
+	/*
+	 * gain reference to object backing the map (can't
+	 * be a submap, already checked this case).
+	 */
+
+	if (new_entry->aref.ar_amap)
+		uvm_map_reference_amap(new_entry, flags);
+
+	if (new_entry->object.uvm_obj &&
+	    new_entry->object.uvm_obj->pgops->pgo_reference)
+		new_entry->object.uvm_obj->pgops->pgo_reference(
+			new_entry->object.uvm_obj);
+
+	/* insert entry at end of new_map's entry list */
+	uvm_map_entry_link(new_map, new_map->header.prev,
+	    new_entry);
+
+	return new_entry;
+}
+
+/*
+ * share the mapping: this means we want the old and
+ * new entries to share amaps and backing objects.
+ */
+static void
+uvm_mapent_forkshared(struct vm_map *new_map, struct vm_map *old_map,
+    struct vm_map_entry *old_entry)
+{
+	/*
+	 * if the old_entry needs a new amap (due to prev fork)
+	 * then we need to allocate it now so that we have
+	 * something we own to share with the new_entry.   [in
+	 * other words, we need to clear needs_copy]
+	 */
+
+	if (UVM_ET_ISNEEDSCOPY(old_entry)) {
+		/* get our own amap, clears needs_copy */
+		amap_copy(old_map, old_entry, AMAP_COPY_NOCHUNK,
+		    0, 0);
+		/* XXXCDC: WAITOK??? */
+	}
+
+	uvm_mapent_clone(new_map, old_entry, AMAP_SHARED);
+}
+
+
+static void
+uvm_mapent_forkcopy(struct vm_map *new_map, struct vm_map *old_map,
+    struct vm_map_entry *old_entry)
+{
+	struct vm_map_entry *new_entry;
+
+	/*
+	 * copy-on-write the mapping (using mmap's
+	 * MAP_PRIVATE semantics)
+	 *
+	 * allocate new_entry, adjust reference counts.
+	 * (note that new references are read-only).
+	 */
+
+	new_entry = uvm_mapent_clone(new_map, old_entry, 0);
+
+	new_entry->etype |=
+	    (UVM_ET_COPYONWRITE|UVM_ET_NEEDSCOPY);
+
+	/*
+	 * the new entry will need an amap.  it will either
+	 * need to be copied from the old entry or created
+	 * from scratch (if the old entry does not have an
+	 * amap).  can we defer this process until later
+	 * (by setting "needs_copy") or do we need to copy
+	 * the amap now?
+	 *
+	 * we must copy the amap now if any of the following
+	 * conditions hold:
+	 * 1. the old entry has an amap and that amap is
+	 *    being shared.  this means that the old (parent)
+	 *    process is sharing the amap with another
+	 *    process.  if we do not clear needs_copy here
+	 *    we will end up in a situation where both the
+	 *    parent and child process are refering to the
+	 *    same amap with "needs_copy" set.  if the
+	 *    parent write-faults, the fault routine will
+	 *    clear "needs_copy" in the parent by allocating
+	 *    a new amap.   this is wrong because the
+	 *    parent is supposed to be sharing the old amap
+	 *    and the new amap will break that.
+	 *
+	 * 2. if the old entry has an amap and a non-zero
+	 *    wire count then we are going to have to call
+	 *    amap_cow_now to avoid page faults in the
+	 *    parent process.   since amap_cow_now requires
+	 *    "needs_copy" to be clear we might as well
+	 *    clear it here as well.
+	 *
+	 */
+
+	if (old_entry->aref.ar_amap != NULL) {
+		if ((amap_flags(old_entry->aref.ar_amap) & AMAP_SHARED) != 0 ||
+		    VM_MAPENT_ISWIRED(old_entry)) {
+
+			amap_copy(new_map, new_entry,
+			    AMAP_COPY_NOCHUNK, 0, 0);
+			/* XXXCDC: M_WAITOK ... ok? */
+		}
+	}
+
+	/*
+	 * if the parent's entry is wired down, then the
+	 * parent process does not want page faults on
+	 * access to that memory.  this means that we
+	 * cannot do copy-on-write because we can't write
+	 * protect the old entry.   in this case we
+	 * resolve all copy-on-write faults now, using
+	 * amap_cow_now.   note that we have already
+	 * allocated any needed amap (above).
+	 */
+
+	if (VM_MAPENT_ISWIRED(old_entry)) {
+
+		/*
+		 * resolve all copy-on-write faults now
+		 * (note that there is nothing to do if
+		 * the old mapping does not have an amap).
+		 */
+		if (old_entry->aref.ar_amap)
+			amap_cow_now(new_map, new_entry);
+
+	} else {
+		/*
+		 * setup mappings to trigger copy-on-write faults
+		 * we must write-protect the parent if it has
+		 * an amap and it is not already "needs_copy"...
+		 * if it is already "needs_copy" then the parent
+		 * has already been write-protected by a previous
+		 * fork operation.
+		 */
+		if (old_entry->aref.ar_amap &&
+		    !UVM_ET_ISNEEDSCOPY(old_entry)) {
+			if (old_entry->max_protection & VM_PROT_WRITE) {
+				pmap_protect(old_map->pmap,
+				    old_entry->start, old_entry->end,
+				    old_entry->protection & ~VM_PROT_WRITE);
+			}
+			old_entry->etype |= UVM_ET_NEEDSCOPY;
+		}
+	}
+}
+
 /*
  *   F O R K   -   m a i n   e n t r y   p o i n t
  */
@@ -4200,7 +4362,6 @@ uvmspace_fork(struct vmspace *vm1)
 	struct vm_map *old_map = &vm1->vm_map;
 	struct vm_map *new_map;
 	struct vm_map_entry *old_entry;
-	struct vm_map_entry *new_entry;
 	UVMHIST_FUNC("uvmspace_fork"); UVMHIST_CALLED(maphist);
 
 	vm_map_lock(old_map);
@@ -4230,7 +4391,6 @@ uvmspace_fork(struct vmspace *vm1)
 
 		switch (old_entry->inheritance) {
 		case MAP_INHERIT_NONE:
-
 			/*
 			 * drop the mapping, modify size
 			 */
@@ -4238,171 +4398,17 @@ uvmspace_fork(struct vmspace *vm1)
 			break;
 
 		case MAP_INHERIT_SHARE:
-
-			/*
-			 * share the mapping: this means we want the old and
-			 * new entries to share amaps and backing objects.
-			 */
-			/*
-			 * if the old_entry needs a new amap (due to prev fork)
-			 * then we need to allocate it now so that we have
-			 * something we own to share with the new_entry.   [in
-			 * other words, we need to clear needs_copy]
-			 */
-
-			if (UVM_ET_ISNEEDSCOPY(old_entry)) {
-				/* get our own amap, clears needs_copy */
-				amap_copy(old_map, old_entry, AMAP_COPY_NOCHUNK,
-				    0, 0);
-				/* XXXCDC: WAITOK??? */
-			}
-
-			new_entry = uvm_mapent_alloc(new_map, 0);
-			/* old_entry -> new_entry */
-			uvm_mapent_copy(old_entry, new_entry);
-
-			/* new pmap has nothing wired in it */
-			new_entry->wired_count = 0;
-
-			/*
-			 * gain reference to object backing the map (can't
-			 * be a submap, already checked this case).
-			 */
-
-			if (new_entry->aref.ar_amap)
-				uvm_map_reference_amap(new_entry, AMAP_SHARED);
-
-			if (new_entry->object.uvm_obj &&
-			    new_entry->object.uvm_obj->pgops->pgo_reference)
-				new_entry->object.uvm_obj->
-				    pgops->pgo_reference(
-				        new_entry->object.uvm_obj);
-
-			/* insert entry at end of new_map's entry list */
-			uvm_map_entry_link(new_map, new_map->header.prev,
-			    new_entry);
-
+			uvm_mapent_forkshared(new_map, old_map, old_entry);
 			break;
 
 		case MAP_INHERIT_COPY:
+			uvm_mapent_forkcopy(new_map, old_map, old_entry);
+			break;
 
-			/*
-			 * copy-on-write the mapping (using mmap's
-			 * MAP_PRIVATE semantics)
-			 *
-			 * allocate new_entry, adjust reference counts.
-			 * (note that new references are read-only).
-			 */
-
-			new_entry = uvm_mapent_alloc(new_map, 0);
-			/* old_entry -> new_entry */
-			uvm_mapent_copy(old_entry, new_entry);
-
-			if (new_entry->aref.ar_amap)
-				uvm_map_reference_amap(new_entry, 0);
-
-			if (new_entry->object.uvm_obj &&
-			    new_entry->object.uvm_obj->pgops->pgo_reference)
-				new_entry->object.uvm_obj->pgops->pgo_reference
-				    (new_entry->object.uvm_obj);
-
-			/* new pmap has nothing wired in it */
-			new_entry->wired_count = 0;
-
-			new_entry->etype |=
-			    (UVM_ET_COPYONWRITE|UVM_ET_NEEDSCOPY);
-			uvm_map_entry_link(new_map, new_map->header.prev,
-			    new_entry);
-
-			/*
-			 * the new entry will need an amap.  it will either
-			 * need to be copied from the old entry or created
-			 * from scratch (if the old entry does not have an
-			 * amap).  can we defer this process until later
-			 * (by setting "needs_copy") or do we need to copy
-			 * the amap now?
-			 *
-			 * we must copy the amap now if any of the following
-			 * conditions hold:
-			 * 1. the old entry has an amap and that amap is
-			 *    being shared.  this means that the old (parent)
-			 *    process is sharing the amap with another
-			 *    process.  if we do not clear needs_copy here
-			 *    we will end up in a situation where both the
-			 *    parent and child process are refering to the
-			 *    same amap with "needs_copy" set.  if the
-			 *    parent write-faults, the fault routine will
-			 *    clear "needs_copy" in the parent by allocating
-			 *    a new amap.   this is wrong because the
-			 *    parent is supposed to be sharing the old amap
-			 *    and the new amap will break that.
-			 *
-			 * 2. if the old entry has an amap and a non-zero
-			 *    wire count then we are going to have to call
-			 *    amap_cow_now to avoid page faults in the
-			 *    parent process.   since amap_cow_now requires
-			 *    "needs_copy" to be clear we might as well
-			 *    clear it here as well.
-			 *
-			 */
-
-			if (old_entry->aref.ar_amap != NULL) {
-				if ((amap_flags(old_entry->aref.ar_amap) &
-				     AMAP_SHARED) != 0 ||
-				    VM_MAPENT_ISWIRED(old_entry)) {
-
-					amap_copy(new_map, new_entry,
-					    AMAP_COPY_NOCHUNK, 0, 0);
-					/* XXXCDC: M_WAITOK ... ok? */
-				}
-			}
-
-			/*
-			 * if the parent's entry is wired down, then the
-			 * parent process does not want page faults on
-			 * access to that memory.  this means that we
-			 * cannot do copy-on-write because we can't write
-			 * protect the old entry.   in this case we
-			 * resolve all copy-on-write faults now, using
-			 * amap_cow_now.   note that we have already
-			 * allocated any needed amap (above).
-			 */
-
-			if (VM_MAPENT_ISWIRED(old_entry)) {
-
-			  /*
-			   * resolve all copy-on-write faults now
-			   * (note that there is nothing to do if
-			   * the old mapping does not have an amap).
-			   */
-			  if (old_entry->aref.ar_amap)
-			    amap_cow_now(new_map, new_entry);
-
-			} else {
-
-			  /*
-			   * setup mappings to trigger copy-on-write faults
-			   * we must write-protect the parent if it has
-			   * an amap and it is not already "needs_copy"...
-			   * if it is already "needs_copy" then the parent
-			   * has already been write-protected by a previous
-			   * fork operation.
-			   */
-
-			  if (old_entry->aref.ar_amap &&
-			      !UVM_ET_ISNEEDSCOPY(old_entry)) {
-			      if (old_entry->max_protection & VM_PROT_WRITE) {
-				pmap_protect(old_map->pmap,
-					     old_entry->start,
-					     old_entry->end,
-					     old_entry->protection &
-					     ~VM_PROT_WRITE);
-			      }
-			      old_entry->etype |= UVM_ET_NEEDSCOPY;
-			  }
-			}
+		default:
+			KASSERT(0);
 			break;
-		}  /* end of switch statement */
+		}
 		old_entry = old_entry->next;
 	}
 

Reply via email to