Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Oct 2001 20:47:30 +0200
From:      Thomas Moestl <tmoestl@gmx.net>
To:        Matt Dillon <dillon@earth.backplane.com>
Cc:        Patrick Cipiere <Patrick.Cipiere@udcast.com>, tinguely@web.cs.ndsu.nodak.edu, freebsd-hackers@FreeBSD.ORG
Subject:   Re: contigfree, free what?
Message-ID:  <20011012204730.F407@crow.dom2ip.de>
In-Reply-To: <200110121707.f9CH7Ax34395@earth.backplane.com>; from dillon@earth.backplane.com on Fri, Oct 12, 2001 at 10:07:10AM -0700
References:  <200110121605.f9CG5F726010@ra.udcast.com> <200110121707.f9CH7Ax34395@earth.backplane.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--TakKZr9L6Hm6aLOc
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Fri, 2001/10/12 at 10:07:10 -0700, Matt Dillon wrote:
> 
> :Mark,
> :
> :> I also placed some checks on vm_map_delete
> :
> :I did that also, and as far as I understand everything works fine.
> :The only thing I found was the fact that when contigmalloc() grabs the
> :contig pages it sets the value of pga[i] (for i in allocated pages)
> :note that: vm_page_t pga = vm_page_array;
> :
> :Then contigfree() does a pretty good job, but does not reset the values
> :of pga[i] to pqtype == PQ_FREE (pqtype = pga[i].queue - pga[i].pc)
> :
> :So the next contigmalloc() requiring the same number of pages fails on
> :the previously released pages because they are not PQ_FREE
> :
> :The other thing that puzzled me is the fact that in vm_map_delete()
> :called by contgigfree() has a variable
> :...

I have also looked into this a while ago, but got stuck at some
point. I have just looked at it again, and I think I have found a solution.

>     I think what is going on is that contigmalloc() is wiring the pages
>     but placing them in a pageable container (entry->wired_count == 0),
>     so when contigfree() kmem_free()'s the block the system does not know
>     that it must unwire the pages.  This leaves the pages wired and prevents
>     them from being freed.
> 
>     I haven't found a quick and easy solution to the problem yet.  kmem_alloc()
>     doesn't do what we want either.  I tried calling vm_map_pageable() in
>     contigmalloc1() but it crashed the machine, so there might be something
>     else going on as well.

This is probably because the map entries do have a NULL object
pointer. vm_map_pageable() calls vm_fault_wire(), so this will fail.

I have attached a patch which works for me. It duplicates most of the
logic of kmem_alloc in that it calls vm_map_findspace() first, then
vm_map_insert() (which basically is what is done in
kmem_alloc_pageable() too, but here, kernel_object is passed instead
of a NULL pointer, so that the map entry will have a valid object
pointer). Then, the pages are inserted into the object as before, and
finally, the map entries are marked as wired by using
vm_map_pageable(). Because this will also call vm_fault_wire(), which
will among other things do a vm_page_wire(), contigmalloc does not
need to wire the pages itself. 

The pmap_kenter() calls can also be reomved, since the pages will be
mapped in any case by vm_fault(). 

	- thomas

--TakKZr9L6Hm6aLOc
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="vm_contig.diff"

--- vm_contig.c.orig	Fri Oct 12 20:05:09 2001
+++ vm_contig.c	Fri Oct 12 20:44:03 2001
@@ -76,6 +76,8 @@
 #include <vm/vm.h>
 #include <vm/vm_param.h>
 #include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
 #include <vm/vm_object.h>
 #include <vm/vm_page.h>
 #include <vm/vm_pageout.h>
@@ -232,7 +234,6 @@
 			m->busy = 0;
 			m->queue = PQ_NONE;
 			m->object = NULL;
-			vm_page_wire(m);
 		}
 
 		/*
@@ -240,24 +241,31 @@
 		 * Allocate kernel VM, unfree and assign the physical pages to it and
 		 * return kernel VM pointer.
 		 */
-		tmp_addr = addr = kmem_alloc_pageable(map, size);
-		if (addr == 0) {
+		vm_map_lock(map);
+		if (vm_map_findspace(map, vm_map_min(map), size, &addr) !=
+		    KERN_SUCCESS) {
 			/*
 			 * XXX We almost never run out of kernel virtual
 			 * space, so we don't make the allocated memory
 			 * above available.
 			 */
+			vm_map_unlock(map);
 			splx(s);
 			return (NULL);
 		}
+		vm_object_reference(kernel_object);
+		vm_map_insert(map, kernel_object, addr - VM_MIN_KERNEL_ADDRESS,
+		    addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0);
+		vm_map_unlock(map);
 
+		tmp_addr = addr;
 		for (i = start; i < (start + size / PAGE_SIZE); i++) {
 			vm_page_t m = &pga[i];
 			vm_page_insert(m, kernel_object,
 				OFF_TO_IDX(tmp_addr - VM_MIN_KERNEL_ADDRESS));
-			pmap_kenter(tmp_addr, VM_PAGE_TO_PHYS(m));
 			tmp_addr += PAGE_SIZE;
 		}
+		vm_map_pageable(map, addr, addr + size, FALSE);
 
 		splx(s);
 		return ((void *)addr);

--TakKZr9L6Hm6aLOc--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011012204730.F407>