vm2 = uvmspace_alloc(old_map->min_offset, old_map->max_offset);
vm2 = uvmspace_alloc(old_map->min_offset, old_map->max_offset, (old_map->flags & VM_MAP_PAGEABLE) ? TRUE : FALSE);
uvmspace_fork(vm1)	struct vmspace *vm1;{	struct vmspace *vm2;	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;	pmap_t new_pmap;	boolean_t protect_child;	UVMHIST_FUNC("uvmspace_fork"); UVMHIST_CALLED(maphist);	vm_map_lock(old_map);	vm2 = uvmspace_alloc(old_map->min_offset, old_map->max_offset);	memcpy(&vm2->vm_startcopy, &vm1->vm_startcopy,	(caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy);	new_map = &vm2->vm_map;		  /* XXX */	new_pmap = new_map->pmap;	old_entry = old_map->header.next;	/*	 * go entry-by-entry	 */	while (old_entry != &old_map->header) {		/*		 * first, some sanity checks on the old entry		 */		KASSERT(!UVM_ET_ISSUBMAP(old_entry));		KASSERT(UVM_ET_ISCOPYONWRITE(old_entry) ||			!UVM_ET_ISNEEDSCOPY(old_entry));		switch (old_entry->inheritance) {		case MAP_INHERIT_NONE:			/*			 * drop the mapping			 */			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, M_WAITOK, FALSE,				    0, 0);				/* XXXCDC: WAITOK??? */			}			new_entry = uvm_mapent_alloc(new_map);			/* 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);			/*			 * pmap_copy the mappings: this routine is optional			 * but if it is there it will reduce the number of			 * page faults in the new proc.			 */			pmap_copy(new_pmap, old_map->pmap, new_entry->start,			    (old_entry->end - old_entry->start),			    old_entry->start);			break;		case MAP_INHERIT_COPY:			/*			 * 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);			/* 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, M_WAITOK,					    FALSE, 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).			   * XXX: is it worthwhile to bother with pmap_copy			   * in this case?			   */			  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 we do not write-protect the parent, then			   * we must be sure to write-protect the child			   * after the pmap_copy() operation.			   *			   * XXX: pmap_copy should have some way of telling			   * us that it didn't do anything so we can avoid			   * calling pmap_protect needlessly.			   */			  if (old_entry->aref.ar_amap) {			    if (!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);				pmap_update(old_map->pmap);			      }			      old_entry->etype |= UVM_ET_NEEDSCOPY;			    }			    /*			     * parent must now be write-protected			     */			    protect_child = FALSE;			  } else {			    /*			     * we only need to protect the child if the			     * parent has write access.			     */			    if (old_entry->max_protection & VM_PROT_WRITE)			      protect_child = TRUE;			    else			      protect_child = FALSE;			  }			  /*			   * copy the mappings			   * XXX: need a way to tell if this does anything			   */			  pmap_copy(new_pmap, old_map->pmap,				    new_entry->start,				    (old_entry->end - old_entry->start),				    old_entry->start);			  /*			   * protect the child's mappings if necessary			   */			  if (protect_child) {			    pmap_protect(new_pmap, new_entry->start,					 new_entry->end,					 new_entry->protection &					          ~VM_PROT_WRITE);			    pmap_update(new_pmap);			  }			}			break;		}  /* end of switch statement */		old_entry = old_entry->next;	}	new_map->size = old_map->size;	vm_map_unlock(old_map);#ifdef SYSVSHM	if (vm1->vm_shm)		shmfork(vm1, vm2);#endif#ifdef PMAP_FORK	pmap_fork(vm1->vm_map.pmap, vm2->vm_map.pmap);#endif	UVMHIST_LOG(maphist,"<- done",0,0,0,0);	return(vm2);}