struct vm_map *map;
vm_map_t map;
uvm_map(map, startp, size, uobj, uoffset, align, flags)	struct vm_map *map;	vaddr_t *startp;	/* IN/OUT */	vsize_t size;	struct uvm_object *uobj;	voff_t uoffset;	vsize_t align;	uvm_flag_t flags;{	struct vm_map_entry *prev_entry, *new_entry;	vm_prot_t prot = UVM_PROTECTION(flags), maxprot =	    UVM_MAXPROTECTION(flags);	vm_inherit_t inherit = UVM_INHERIT(flags);	int advice = UVM_ADVICE(flags);	UVMHIST_FUNC("uvm_map");	UVMHIST_CALLED(maphist);	UVMHIST_LOG(maphist, "(map=0x%x, *startp=0x%x, size=%d, flags=0x%x)",	    map, *startp, size, flags);	UVMHIST_LOG(maphist, "  uobj/offset 0x%x/%d", uobj, uoffset,0,0);	/*	 * step 0: sanity check of protection code	 */	if ((prot & maxprot) != prot) {		UVMHIST_LOG(maphist, "<- prot. failure:  prot=0x%x, max=0x%x",		prot, maxprot,0,0);		return EACCES;	}	/*	 * step 1: figure out where to put new VM range	 */	if (vm_map_lock_try(map) == FALSE) {		if (flags & UVM_FLAG_TRYLOCK)			return EAGAIN;		vm_map_lock(map); /* could sleep here */	}	if ((prev_entry = uvm_map_findspace(map, *startp, size, startp,	    uobj, uoffset, align, flags)) == NULL) {		UVMHIST_LOG(maphist,"<- uvm_map_findspace failed!",0,0,0,0);		vm_map_unlock(map);		return ENOMEM;	}#ifdef PMAP_GROWKERNEL	{		/*		 * If the kernel pmap can't map the requested space,		 * then allocate more resources for it.		 */		if (map == kernel_map && uvm_maxkaddr < (*startp + size))			uvm_maxkaddr = pmap_growkernel(*startp + size);	}#endif	UVMCNT_INCR(uvm_map_call);	/*	 * if uobj is null, then uoffset is either a VAC hint for PMAP_PREFER	 * [typically from uvm_map_reserve] or it is UVM_UNKNOWN_OFFSET.   in	 * either case we want to zero it  before storing it in the map entry	 * (because it looks strange and confusing when debugging...)	 *	 * if uobj is not null	 *   if uoffset is not UVM_UNKNOWN_OFFSET then we have a normal mapping	 *      and we do not need to change uoffset.	 *   if uoffset is UVM_UNKNOWN_OFFSET then we need to find the offset	 *      now (based on the starting address of the map).   this case is	 *      for kernel object mappings where we don't know the offset until	 *      the virtual address is found (with uvm_map_findspace).   the	 *      offset is the distance we are from the start of the map.	 */	if (uobj == NULL) {		uoffset = 0;	} else {		if (uoffset == UVM_UNKNOWN_OFFSET) {			KASSERT(UVM_OBJ_IS_KERN_OBJECT(uobj));			uoffset = *startp - vm_map_min(kernel_map);		}	}	/*	 * step 2: try and insert in map by extending previous entry, if	 * possible	 * XXX: we don't try and pull back the next entry.   might be useful	 * for a stack, but we are currently allocating our stack in advance.	 */	if ((flags & UVM_FLAG_NOMERGE) == 0 &&	    prev_entry->end == *startp && prev_entry != &map->header &&	    prev_entry->object.uvm_obj == uobj) {		if (uobj && prev_entry->offset +		    (prev_entry->end - prev_entry->start) != uoffset)			goto step3;		if (UVM_ET_ISSUBMAP(prev_entry))			goto step3;		if (prev_entry->protection != prot ||		    prev_entry->max_protection != maxprot)			goto step3;		if (prev_entry->inheritance != inherit ||		    prev_entry->advice != advice)			goto step3;		/* wiring status must match (new area is unwired) */		if (VM_MAPENT_ISWIRED(prev_entry))			goto step3;		/*		 * 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.		 * if it is one (i.e. we have only reference) it will stay there		 */		if (prev_entry->aref.ar_amap &&		    amap_refs(prev_entry->aref.ar_amap) != 1) {			goto step3;		}		/* got it! */		UVMCNT_INCR(map_backmerge);		UVMHIST_LOG(maphist,"  starting back merge", 0, 0, 0, 0);		/*		 * drop our reference to uobj since we are extending a reference		 * that we already have (the ref count can not drop to zero).		 */		if (uobj && uobj->pgops->pgo_detach)			uobj->pgops->pgo_detach(uobj);		if (prev_entry->aref.ar_amap) {			amap_extend(prev_entry, size);		}		prev_entry->end += size;		map->size += size;		UVMHIST_LOG(maphist,"<- done (via backmerge)!", 0, 0, 0, 0);		vm_map_unlock(map);		return 0;	}step3:	UVMHIST_LOG(maphist,"  allocating new map entry", 0, 0, 0, 0);	/*	 * check for possible forward merge (which we don't do) and count	 * the number of times we missed a *possible* chance to merge more	 */	if ((flags & UVM_FLAG_NOMERGE) == 0 &&	    prev_entry->next != &map->header &&	    prev_entry->next->start == (*startp + size))		UVMCNT_INCR(map_forwmerge);	/*	 * step 3: allocate new entry and link it in	 */	new_entry = uvm_mapent_alloc(map);	new_entry->start = *startp;	new_entry->end = new_entry->start + size;	new_entry->object.uvm_obj = uobj;	new_entry->offset = uoffset;	if (uobj)		new_entry->etype = UVM_ET_OBJ;	else		new_entry->etype = 0;	if (flags & UVM_FLAG_COPYONW) {		new_entry->etype |= UVM_ET_COPYONWRITE;		if ((flags & UVM_FLAG_OVERLAY) == 0)			new_entry->etype |= UVM_ET_NEEDSCOPY;	}	new_entry->protection = prot;	new_entry->max_protection = maxprot;	new_entry->inheritance = inherit;	new_entry->wired_count = 0;	new_entry->advice = advice;	if (flags & UVM_FLAG_OVERLAY) {		/*		 * to_add: for BSS we overallocate a little since we		 * are likely to extend		 */		vaddr_t to_add = (flags & UVM_FLAG_AMAPPAD) ?			UVM_AMAP_CHUNK << PAGE_SHIFT : 0;		struct vm_amap *amap = amap_alloc(size, to_add, M_WAITOK);		new_entry->aref.ar_pageoff = 0;		new_entry->aref.ar_amap = amap;	} else {		new_entry->aref.ar_pageoff = 0;		new_entry->aref.ar_amap = NULL;	}	uvm_map_entry_link(map, prev_entry, new_entry);	map->size += size;	/*	 *      Update the free space hint	 */	if ((map->first_free == prev_entry) &&	    (prev_entry->end >= new_entry->start))		map->first_free = new_entry;	UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0);	vm_map_unlock(map);	return 0;}