Subject: re: GCC3.3.1 switch coming soon.
To: matthew green <mrg@eterna.com.au>
From: enami tsugutomo <enami@but-b.or.jp>
List: port-sparc64
Date: 09/01/2003 22:09:29
> i've seen the reports about topdown VM but i have not investigated
> them.  someone who uses that option should, i have enough other
> things on my plate right now.

It isn't compiler matter since the kernel built by 2.95.3 as well.  It
is actually a bug in topdown vm code.  It incorrectly re-uses space
already in-use under some condition which began to met recently.

Attached is a change I'm currently playing with.  It includes a fix
among other cleanups.

enami.

Index: uvm_map.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_map.c,v
retrieving revision 1.137
diff -c -r1.137 uvm_map.c
*** uvm_map.c	26 Aug 2003 15:12:18 -0000	1.137
--- uvm_map.c	1 Sep 2003 07:54:05 -0000
***************
*** 199,204 ****
--- 199,206 ----
  static void uvm_map_entry_unwire __P((struct vm_map *, struct vm_map_entry *));
  static void uvm_map_reference_amap __P((struct vm_map_entry *, int));
  static void uvm_map_unreference_amap __P((struct vm_map_entry *, int));
+ static int uvm_map_space_avail __P((vaddr_t *, vsize_t, voff_t, vsize_t, int,
+ 	       struct vm_map_entry *));
  
  /*
   * local inlines
***************
*** 1010,1016 ****
  		 */
  
  		last = &map->header;
! 		if ((cur != last) && (cur->end > address)) {
  			UVMCNT_INCR(uvm_mlk_hint);
  			*entry = cur;
  			UVMHIST_LOG(maphist,"<- got it via hint (0x%x)",
--- 1012,1019 ----
  		 */
  
  		last = &map->header;
! 		if (cur->end > address) {
! 			KASSERT(cur != last);
  			UVMCNT_INCR(uvm_mlk_hint);
  			*entry = cur;
  			UVMHIST_LOG(maphist,"<- got it via hint (0x%x)",
***************
*** 1056,1061 ****
--- 1059,1117 ----
  }
  
  /*
+  * See if the range between start and start + length fits in the gap
+  * entry->next->start and entry->end.  Returns 1 if fits, 0 if doesn't
+  * fit, and -1 address wraps around.
+  */
+ static __inline int
+ uvm_map_space_avail(start, length, uoffset, align, topdown, entry)
+ 	vaddr_t *start;
+ 	vsize_t length;
+ 	voff_t uoffset;
+ 	vsize_t align;
+ 	int topdown;
+ 	struct vm_map_entry *entry;
+ {
+ 	vaddr_t end;
+ 
+ #ifdef PMAP_PREFER
+ 	/*
+ 	 * push start address forward as needed to avoid VAC alias problems.
+ 	 * we only do this if a valid offset is specified.
+ 	 */
+ 
+ 	if (uoffset != UVM_UNKNOWN_OFFSET)
+ 		PMAP_PREFER(uoffset, start);
+ #endif
+ 	if (align != 0) {
+ 		if ((*start & (align - 1)) != 0) {
+ 			if (topdown)
+ 				*start &= ~(align - 1);
+ 			else
+ 				*start = roundup(*start, align);
+ 		}
+ 		/*
+ 		 * XXX Should we PMAP_PREFER() here again?
+ 		 */
+ 	}
+ 
+ 	/*
+ 	 * Find the end of the proposed new region.  Be sure we didn't
+ 	 * wrap around the address; if so, we lose.  Otherwise, if the
+ 	 * proposed new region fits before the next entry, we win.
+ 	 */
+ 
+ 	end = *start + length;
+ 	if (end < *start)
+ 		return (-1);
+ 
+ 	if (entry->next->start >= end && *start >= entry->end)
+ 		return (1);
+ 
+ 	return (0);
+ }
+ 
+ /*
   * uvm_map_findspace: find "length" sized space in "map".
   *
   * => "hint" is a hint about where we want it, unless FINDSPACE_FIXED is
***************
*** 1079,1092 ****
  	vsize_t align;
  	int flags;
  {
! 	struct vm_map_entry *entry, *next, *tmp;
! 	vaddr_t end, orig_hint;
  	const int topdown = map->flags & VM_MAP_TOPDOWN;
  	UVMHIST_FUNC("uvm_map_findspace");
  	UVMHIST_CALLED(maphist);
  
  	UVMHIST_LOG(maphist, "(map=0x%x, hint=0x%x, len=%d, flags=0x%x)",
! 		    map, hint, length, flags);
  	KASSERT((align & (align - 1)) == 0);
  	KASSERT((flags & UVM_FLAG_FIXED) == 0 || align == 0);
  
--- 1135,1148 ----
  	vsize_t align;
  	int flags;
  {
! 	struct vm_map_entry *entry;
! 	vaddr_t orig_hint;
  	const int topdown = map->flags & VM_MAP_TOPDOWN;
  	UVMHIST_FUNC("uvm_map_findspace");
  	UVMHIST_CALLED(maphist);
  
  	UVMHIST_LOG(maphist, "(map=0x%x, hint=0x%x, len=%d, flags=0x%x)",
! 	    map, hint, length, flags);
  	KASSERT((align & (align - 1)) == 0);
  	KASSERT((flags & UVM_FLAG_FIXED) == 0 || align == 0);
  
***************
*** 1100,1113 ****
  	if (hint < map->min_offset) {	/* check ranges ... */
  		if (flags & UVM_FLAG_FIXED) {
  			UVMHIST_LOG(maphist,"<- VA below map range",0,0,0,0);
! 			return(NULL);
  		}
  		hint = map->min_offset;
  	}
  	if (hint > map->max_offset) {
  		UVMHIST_LOG(maphist,"<- VA 0x%x > range [0x%x->0x%x]",
! 				hint, map->min_offset, map->max_offset, 0);
! 		return(NULL);
  	}
  
  	/*
--- 1156,1169 ----
  	if (hint < map->min_offset) {	/* check ranges ... */
  		if (flags & UVM_FLAG_FIXED) {
  			UVMHIST_LOG(maphist,"<- VA below map range",0,0,0,0);
! 			return (NULL);
  		}
  		hint = map->min_offset;
  	}
  	if (hint > map->max_offset) {
  		UVMHIST_LOG(maphist,"<- VA 0x%x > range [0x%x->0x%x]",
! 		    hint, map->min_offset, map->max_offset, 0);
! 		return (NULL);
  	}
  
  	/*
***************
*** 1120,1131 ****
  	 *
  	 * 0: found,     fixed,     bottom up -> fail
  	 * 1: found,     fixed,     top down  -> fail
! 	 * 2: found,     not fixed, bottom up -> start after tmp->end, loop up
! 	 * 3: found,     not fixed, top down  -> start before tmp->start, loop down
! 	 * 4: not found, fixed,     bottom up -> check tmp->next->start, fail
! 	 * 5: not found, fixed,     top down  -> check tmp->next->start, fail
! 	 * 6: not found, not fixed, bottom up -> check tmp->next->start, loop up
! 	 * 7: not found, not fixed, top down  -> check tmp->next->start, loop down
  	 *
  	 * as you can see, it reduces to roughly five cases, and that
  	 * adding top down mapping only adds one unique case (without
--- 1176,1191 ----
  	 *
  	 * 0: found,     fixed,     bottom up -> fail
  	 * 1: found,     fixed,     top down  -> fail
! 	 * 2: found,     not fixed, bottom up -> start after entry->end,
! 	 *                                       loop up
! 	 * 3: found,     not fixed, top down  -> start before entry->start,
! 	 *                                       loop down
! 	 * 4: not found, fixed,     bottom up -> check entry->next->start, fail
! 	 * 5: not found, fixed,     top down  -> check entry->next->start, fail
! 	 * 6: not found, not fixed, bottom up -> check entry->next->start,
! 	 *                                       loop up
! 	 * 7: not found, not fixed, top down  -> check entry->next->start,
! 	 *                                       loop down
  	 *
  	 * as you can see, it reduces to roughly five cases, and that
  	 * adding top down mapping only adds one unique case (without
***************
*** 1133,1229 ****
  	 */
  
  	if ((flags & UVM_FLAG_FIXED) == 0 && hint == map->min_offset) {
! 		if ((entry = map->first_free) != &map->header)
! 			hint = entry->end;
  	} else {
! 		if (uvm_map_lookup_entry(map, hint, &tmp)) {
  			/* "hint" address already in use ... */
  			if (flags & UVM_FLAG_FIXED) {
! 				UVMHIST_LOG(maphist,"<- fixed & VA in use",
  				    0, 0, 0, 0);
! 				return(NULL);
  			}
! 			hint = topdown ? tmp->start - length : tmp->end;
! 		} else if ((tmp->next == &map->header ||
! 			    tmp->next->start >= hint + length)) {
! 			entry = tmp;
! 			goto quickfind;
  		}
- 		entry = tmp;
  	}
  
  	/*
  	 * Look through the rest of the map, trying to fit a new region in
  	 * the gap between existing regions, or after the very last region.
! 	 * note: entry->end   = base VA of current gap,
! 	 *	 next->start  = VA of end of current gap
  	 */
  
! 	for (next = NULL;; hint = topdown ?
! 		(entry = next)->start - length :
! 		(entry = next)->end) {
! 
! 		/*
! 		 * Find the end of the proposed new region.  Be sure we didn't
! 		 * go beyond the end of the map, or wrap around the address;
! 		 * if so, we lose.  Otherwise, if this is the last entry, or
! 		 * if the proposed new region fits before the next entry, we
! 		 * win.
! 		 */
! 
! #ifdef PMAP_PREFER
! 		/*
! 		 * push hint forward as needed to avoid VAC alias problems.
! 		 * we only do this if a valid offset is specified.
! 		 */
! 
! 		if ((flags & UVM_FLAG_FIXED) == 0 &&
! 		    uoffset != UVM_UNKNOWN_OFFSET)
! 			PMAP_PREFER(uoffset, &hint);
! #endif
! 		if (align != 0) {
! 			if ((hint & (align - 1)) != 0) {
! 				if (topdown)
! 					hint &= ~(align-1);
! 				else
! 					hint = roundup(hint, align);
  			}
! 			/*
! 			 * XXX Should we PMAP_PREFER() here again?
! 			 */
! 		}
! 		end = hint + length;
! 		if (end > map->max_offset || end < hint) {
! 			UVMHIST_LOG(maphist,"<- failed (off end)", 0,0,0,0);
! 			if (align != 0) {
! 				UVMHIST_LOG(maphist,
! 				    "calling recursively, no align",
  				    0,0,0,0);
! 				return (uvm_map_findspace(map, orig_hint,
! 				    length, result, uobj, uoffset, 0, flags));
  			}
- 			return (NULL);
- 		}
- 		if (!topdown || next == NULL) {
- 			next = entry->next;
- 		} else
- 			next = entry->prev;
- 		if (next == &map->header ||
- 		    (!topdown && next->start >= end) ||
- 		    ( topdown && next->end   <= hint))
- 			break;
- 		if (flags & UVM_FLAG_FIXED) {
- 			UVMHIST_LOG(maphist,"<- fixed mapping failed", 0,0,0,0);
- 			return(NULL); /* only one shot at it ... */
  		}
  	}
!  quickfind:
  	SAVE_HINT(map, map->hint, entry);
- 	if (topdown && entry->start >= hint + length)
- 		entry = entry->prev;
  	*result = hint;
  	UVMHIST_LOG(maphist,"<- got it!  (result=0x%x)", hint, 0,0,0);
  	return (entry);
  }
  
  /*
--- 1193,1301 ----
  	 */
  
  	if ((flags & UVM_FLAG_FIXED) == 0 && hint == map->min_offset) {
! 		entry = map->first_free;
  	} else {
! 		if (uvm_map_lookup_entry(map, hint, &entry)) {
  			/* "hint" address already in use ... */
  			if (flags & UVM_FLAG_FIXED) {
! 				UVMHIST_LOG(maphist, "<- fixed & VA in use",
  				    0, 0, 0, 0);
! 				return (NULL);
! 			}
! 			if (topdown)
! 				/* Start from lower gap. */
! 				entry = entry->prev;
! 		} else if (flags & UVM_FLAG_FIXED) {
! 			if (entry->next->start >= hint + length &&
! 			    hint + length > hint)
! 				goto found;
! 
! 			/* "hint" address is gap but too small */
! 			UVMHIST_LOG(maphist, "<- fixed mapping failed",
! 			    0, 0, 0, 0);
! 			return (NULL); /* only one shot at it ... */
! 		} else {
! 			/*
! 			 * See if given hint fits in this gap.
! 			 */
! 			switch (uvm_map_space_avail(&hint, length,
! 			    uoffset, align, topdown, entry)) {
! 			case 1:
! 				goto found;
! 			case -1:
! 				goto wraparound;
  			}
! 
! 			if (topdown)
! 				/*
! 				 * Still there is a chance to fit
! 				 * if hint > entry->end.
! 				 */
! 				;
! 			else
! 				goto nextgap;
  		}
  	}
  
  	/*
  	 * Look through the rest of the map, trying to fit a new region in
  	 * the gap between existing regions, or after the very last region.
! 	 * note: entry->end = base VA of current gap,
! 	 *	 entry->next->start = VA of end of current gap
! 	 *
! 	 * Also note that all UVM_FLAGS_FIXED case is already handled.
  	 */
+ 	KDASSERT((flags & UVM_FLAG_FIXED) == 0);
  
! 	for (;;) {
! 		/* Update hint for current gap. */
! 		hint = topdown ? entry->next->start - length : entry->end;
! 
! 		/* See if it fits. */
! 		switch (uvm_map_space_avail(&hint, length, uoffset, align,
! 		    topdown, entry)) {
! 		case 1:
! 			goto found;
! 		case -1:
! 			goto wraparound;
! 		}
! 
! 		/* Advance to next/previous gap */
! 		if (topdown) {
! 			if (entry == &map->header) {
! 				UVMHIST_LOG(maphist, "<- failed (off start)",
! 				    0,0,0,0);
! 				goto notfound;
  			}
! 			entry = entry->prev;
! 		} else {
!  nextgap:
! 			entry = entry->next;
! 			if (entry == &map->header) {
! 				UVMHIST_LOG(maphist, "<- failed (off end)",
  				    0,0,0,0);
! 				goto notfound;
  			}
  		}
  	}
! 
!  found:
  	SAVE_HINT(map, map->hint, entry);
  	*result = hint;
  	UVMHIST_LOG(maphist,"<- got it!  (result=0x%x)", hint, 0,0,0);
  	return (entry);
+ 
+  wraparound:
+ 	UVMHIST_LOG(maphist, "<- failed (wrap around)", 0,0,0,0);
+ 
+  notfound:
+ 	if (align != 0) {
+ 		UVMHIST_LOG(maphist, "calling recursively, no align",
+ 		    0,0,0,0);
+ 		return (uvm_map_findspace(map, orig_hint,
+ 		    length, result, uobj, uoffset, 0, flags));
+ 	}
+ 	return (NULL);
  }
  
  /*
***************
*** 1299,1305 ****
  	 * up with a mapping to a page on the free list which would be very bad)
  	 */
  
! 	while ((entry != &map->header) && (entry->start < end)) {
  		UVM_MAP_CLIP_END(map, entry, end);
  		next = entry->next;
  		len = entry->end - entry->start;
--- 1371,1378 ----
  	 * up with a mapping to a page on the free list which would be very bad)
  	 */
  
! 	while (entry->start < end) {
! 		KASSERT(entry != &map->header);
  		UVM_MAP_CLIP_END(map, entry, end);
  		next = entry->next;
  		len = entry->end - entry->start;
***************
*** 1730,1736 ****
  	 * as we go.
  	 */
  
! 	while (entry->start < end && entry != &srcmap->header) {
  
  		/* if we are not doing a quick reference, clip it */
  		if ((flags & UVM_EXTRACT_QREF) == 0)
--- 1803,1810 ----
  	 * as we go.
  	 */
  
! 	while (entry->start < end) {
! 		KASSERT(entry != &srcmap->header);
  
  		/* if we are not doing a quick reference, clip it */
  		if ((flags & UVM_EXTRACT_QREF) == 0)
***************
*** 1809,1819 ****
  		}
  
  		/* end of 'while' loop! */
! 		if ((flags & UVM_EXTRACT_CONTIG) && entry->end < end &&
! 		    (entry->next == &srcmap->header ||
! 		    entry->next->start != entry->end)) {
! 			error = EINVAL;
! 			goto bad;
  		}
  		entry = entry->next;
  		fudge = 0;
--- 1883,1894 ----
  		}
  
  		/* end of 'while' loop! */
! 		if ((flags & UVM_EXTRACT_CONTIG) && entry->end < end) {
! 			if (entry->next->start != entry->end) {
! 				error = EINVAL;
! 				goto bad;
! 			} else
! 				KASSERT(entry->next != &srcmap->header);
  		}
  		entry = entry->next;
  		fudge = 0;
***************
*** 1867,1873 ****
  		fudge = orig_fudge;
  		deadentry = NULL;	/* for UVM_EXTRACT_REMOVE */
  
! 		while (entry->start < end && entry != &srcmap->header) {
  			if (copy_ok) {
  				oldoffset = (entry->start + fudge) - start;
  				elen = MIN(end, entry->end) -
--- 1942,1949 ----
  		fudge = orig_fudge;
  		deadentry = NULL;	/* for UVM_EXTRACT_REMOVE */
  
! 		while (entry->start < end) {
! 			KASSERT(entry != &srcmap->header);
  			if (copy_ok) {
  				oldoffset = (entry->start + fudge) - start;
  				elen = MIN(end, entry->end) -
***************
*** 2035,2041 ****
  	 */
  
  	current = entry;
! 	while ((current != &map->header) && (current->start < end)) {
  		if (UVM_ET_ISSUBMAP(current)) {
  			error = EINVAL;
  			goto out;
--- 2111,2118 ----
  	 */
  
  	current = entry;
! 	while (current->start < end) {
! 		KASSERT(current != &map->header);
  		if (UVM_ET_ISSUBMAP(current)) {
  			error = EINVAL;
  			goto out;
***************
*** 2066,2074 ****
  	/* go back and fix up protections (no need to clip this time). */
  
  	current = entry;
! 	while ((current != &map->header) && (current->start < end)) {
  		vm_prot_t old_prot;
  
  		UVM_MAP_CLIP_END(map, current, end);
  		old_prot = current->protection;
  		if (set_max)
--- 2143,2152 ----
  	/* go back and fix up protections (no need to clip this time). */
  
  	current = entry;
! 	while (current->start < end) {
  		vm_prot_t old_prot;
  
+ 		KASSERT(current != &map->header);
  		UVM_MAP_CLIP_END(map, current, end);
  		old_prot = current->protection;
  		if (set_max)
***************
*** 2183,2189 ****
  	}  else {
  		entry = temp_entry->next;
  	}
! 	while ((entry != &map->header) && (entry->start < end)) {
  		UVM_MAP_CLIP_END(map, entry, end);
  		entry->inheritance = new_inheritance;
  		entry = entry->next;
--- 2261,2268 ----
  	}  else {
  		entry = temp_entry->next;
  	}
! 	while (entry->start < end) {
! 		KASSERT(entry != &map->header);
  		UVM_MAP_CLIP_END(map, entry, end);
  		entry->inheritance = new_inheritance;
  		entry = entry->next;
***************
*** 2224,2230 ****
  	 * XXXJRT: disallow holes?
  	 */
  
! 	while ((entry != &map->header) && (entry->start < end)) {
  		UVM_MAP_CLIP_END(map, entry, end);
  
  		switch (new_advice) {
--- 2303,2310 ----
  	 * XXXJRT: disallow holes?
  	 */
  
! 	while (entry->start < end) {
! 		KASSERT(entry != &map->header);
  		UVM_MAP_CLIP_END(map, entry, end);
  
  		switch (new_advice) {
***************
*** 2312,2327 ****
  		 * really wired down and that there are no holes.
  		 */
  
! 		while ((entry != &map->header) && (entry->start < end)) {
  			if (entry->wired_count == 0 ||
  			    (entry->end < end &&
! 			     (entry->next == &map->header ||
! 			      entry->next->start > entry->end))) {
  				if ((lockflags & UVM_LK_EXIT) == 0)
  					vm_map_unlock(map);
  				UVMHIST_LOG(maphist, "<- done (INVAL)",0,0,0,0);
  				return EINVAL;
! 			}
  			entry = entry->next;
  		}
  
--- 2392,2410 ----
  		 * really wired down and that there are no holes.
  		 */
  
! 		while (entry->start < end) {
! 			KASSERT(entry != &map->header);
  			if (entry->wired_count == 0 ||
  			    (entry->end < end &&
! 			     entry->next->start > entry->end)) {
  				if ((lockflags & UVM_LK_EXIT) == 0)
  					vm_map_unlock(map);
  				UVMHIST_LOG(maphist, "<- done (INVAL)",0,0,0,0);
  				return EINVAL;
! 			} else
! 				KASSERT(entry->wired_count == 0 ||
! 				    entry->end >= end ||
! 				    entry->next != &map->header);
  			entry = entry->next;
  		}
  
***************
*** 2332,2338 ****
  		 */
  
  		entry = start_entry;
! 		while ((entry != &map->header) && (entry->start < end)) {
  			UVM_MAP_CLIP_END(map, entry, end);
  			if (VM_MAPENT_ISWIRED(entry))
  				uvm_map_entry_unwire(map, entry);
--- 2415,2422 ----
  		 */
  
  		entry = start_entry;
! 		while (entry->start < end) {
! 			KASSERT(entry != &map->header);
  			UVM_MAP_CLIP_END(map, entry, end);
  			if (VM_MAPENT_ISWIRED(entry))
  				uvm_map_entry_unwire(map, entry);
***************
*** 2365,2371 ****
  	 *    entries we modify here cannot change.
  	 */
  
! 	while ((entry != &map->header) && (entry->start < end)) {
  		if (VM_MAPENT_ISWIRED(entry) == 0) { /* not already wired? */
  
  			/*
--- 2449,2456 ----
  	 *    entries we modify here cannot change.
  	 */
  
! 	while (entry->start < end) {
! 		KASSERT(entry != &map->header);
  		if (VM_MAPENT_ISWIRED(entry) == 0) { /* not already wired? */
  
  			/*
***************
*** 2395,2410 ****
  		 */
  
  		if (entry->protection == VM_PROT_NONE ||
! 		    (entry->end < end &&
! 		     (entry->next == &map->header ||
! 		      entry->next->start > entry->end))) {
  
  			/*
  			 * found one.  amap creation actions do not need to
  			 * be undone, but the wired counts need to be restored.
  			 */
  
! 			while (entry != &map->header && entry->end > start) {
  				entry->wired_count--;
  				entry = entry->prev;
  			}
--- 2480,2494 ----
  		 */
  
  		if (entry->protection == VM_PROT_NONE ||
! 		    (entry->end < end && entry->next->start > entry->end)) {
  
  			/*
  			 * found one.  amap creation actions do not need to
  			 * be undone, but the wired counts need to be restored.
  			 */
  
! 			while (entry->end > start) {
! 				KASSERT(entry != &map->header);
  				entry->wired_count--;
  				entry = entry->prev;
  			}
***************
*** 2428,2434 ****
  
  	rv = 0;
  	entry = start_entry;
! 	while (entry != &map->header && entry->start < end) {
  		if (entry->wired_count == 1) {
  			rv = uvm_fault_wire(map, entry->start, entry->end,
  			    VM_FAULT_WIREMAX, entry->max_protection);
--- 2512,2519 ----
  
  	rv = 0;
  	entry = start_entry;
! 	while (entry->start < end) {
! 		KASSERT(entry != &map->header);
  		if (entry->wired_count == 1) {
  			rv = uvm_fault_wire(map, entry->start, entry->end,
  			    VM_FAULT_WIREMAX, entry->max_protection);
***************
*** 2466,2472 ****
  		 */
  
  		failed_entry = entry;
! 		while (entry != &map->header && entry->start < end) {
  			entry->wired_count--;
  			entry = entry->next;
  		}
--- 2551,2558 ----
  		 */
  
  		failed_entry = entry;
! 		while (entry->start < end) {
! 			KASSERT(entry != &map->header);
  			entry->wired_count--;
  			entry = entry->next;
  		}
Index: uvm_map.h
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_map.h,v
retrieving revision 1.34
diff -c -r1.34 uvm_map.h
*** uvm_map.h	20 Feb 2003 22:16:08 -0000	1.34
--- uvm_map.h	28 Aug 2003 02:18:08 -0000
***************
*** 219,226 ****
  	int			flags;		/* flags */
  	struct simplelock	flags_lock;	/* Lock for flags field */
  	unsigned int		timestamp;	/* Version number */
! #define	min_offset		header.start
! #define max_offset		header.end
  };
  
  /* vm_map flags */
--- 219,226 ----
  	int			flags;		/* flags */
  	struct simplelock	flags_lock;	/* Lock for flags field */
  	unsigned int		timestamp;	/* Version number */
! #define	min_offset		header.end
! #define	max_offset		header.start
  };
  
  /* vm_map flags */
Index: uvm_mmap.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_mmap.c,v
retrieving revision 1.77
diff -c -r1.77 uvm_mmap.c
*** uvm_mmap.c	24 Aug 2003 18:12:25 -0000	1.77
--- uvm_mmap.c	28 Aug 2003 13:56:58 -0000
***************
*** 184,194 ****
  		KASSERT(start >= entry->start);
  
  		/* Make sure there are no holes. */
! 		if (entry->end < end &&
! 		     (entry->next == &map->header ||
! 		      entry->next->start > entry->end)) {
! 			error = ENOMEM;
! 			goto out;
  		}
  
  		lim = end < entry->end ? end : entry->end;
--- 184,195 ----
  		KASSERT(start >= entry->start);
  
  		/* Make sure there are no holes. */
! 		if (entry->end < end) {
! 			if (entry->next->start > entry->end) {
! 				error = ENOMEM;
! 				goto out;
! 			} else
! 				KASSERT(entry->next != &map->header);
  		}
  
  		lim = end < entry->end ? end : entry->end;