svn commit: r226980 - user/attilio/vmcontention/sys/vm
Attilio Rao
attilio at FreeBSD.org
Tue Nov 1 03:40:38 UTC 2011
Author: attilio
Date: Tue Nov 1 03:40:38 2011
New Revision: 226980
URL: http://svn.freebsd.org/changeset/base/226980
Log:
vm_object_terminate() doesn't actually free the pages in the splay
tree.
Reclaim all the nodes related to the radix tree for a specified
vm_object when calling vm_object_terminate() via the newly added
interface vm_radix_reclaim_nodes().
The function is recursive, but we have a well-defined maximum depth,
thus the amount of necessary stack can be easilly calculated.
Reported by: alc
Discussed and reviewed by: jeff
Modified:
user/attilio/vmcontention/sys/vm/vm_object.c
user/attilio/vmcontention/sys/vm/vm_radix.c
user/attilio/vmcontention/sys/vm/vm_radix.h
Modified: user/attilio/vmcontention/sys/vm/vm_object.c
==============================================================================
--- user/attilio/vmcontention/sys/vm/vm_object.c Tue Nov 1 02:04:52 2011 (r226979)
+++ user/attilio/vmcontention/sys/vm/vm_object.c Tue Nov 1 03:40:38 2011 (r226980)
@@ -756,6 +756,9 @@ vm_object_terminate(vm_object_t object)
* assignment is that vm_page_free()'s call to
* vm_page_remove() will return immediately without
* modifying the page or the object.
+ * Anyway, the radix tree cannot be accessed anymore
+ * from within the object, thus all the nodes need
+ * to be reclaimed later on.
*/
p->object = NULL;
if (p->wire_count == 0) {
@@ -767,6 +770,7 @@ vm_object_terminate(vm_object_t object)
if (n < VM_RADIX_STACK)
break;
}
+ vm_radix_reclaim_allnodes(&object->rtree);
/*
* If the object contained any pages, then reset it to an empty state.
* None of the object's fields, including "resident_page_count", were
Modified: user/attilio/vmcontention/sys/vm/vm_radix.c
==============================================================================
--- user/attilio/vmcontention/sys/vm/vm_radix.c Tue Nov 1 02:04:52 2011 (r226979)
+++ user/attilio/vmcontention/sys/vm/vm_radix.c Tue Nov 1 03:40:38 2011 (r226980)
@@ -223,6 +223,38 @@ vm_radix_match(void *child, int color)
return ((void *)(c & ~VM_RADIX_FLAGS));
}
+static void
+vm_radix_reclaim_allnodes_internal(struct vm_radix_node *rnode, int level)
+{
+ int slot;
+
+ MPASS(rnode != NULL && level >= 0);
+
+ /*
+ * Level 0 just contains pages as children, thus make it a special
+ * case, free the node and return.
+ */
+ if (level == 0) {
+ CTR2(KTR_VM, "reclaiming: node %p, level %d", rnode, level);
+ rnode->rn_count = 0;
+ vm_radix_node_put(rnode);
+ return;
+ }
+ for (slot = 0; slot < VM_RADIX_COUNT && rnode->rn_count != 0; slot++) {
+ if (rnode->rn_child[slot] == NULL)
+ continue;
+ CTR3(KTR_VM,
+ "reclaiming: node %p, level %d recursing in slot %d",
+ rnode, level, slot);
+ vm_radix_reclaim_allnodes_internal(rnode->rn_child[slot],
+ level - 1);
+ rnode->rn_count--;
+ }
+ MPASS(rnode->rn_count == 0);
+ CTR2(KTR_VM, "reclaiming: node %p, level %d", rnode, level);
+ vm_radix_node_put(rnode);
+}
+
/*
* Inserts the key-value pair in to the radix tree. Returns errno.
* Panics if the key already exists.
@@ -640,6 +672,24 @@ vm_radix_remove(struct vm_radix *rtree,
}
/*
+ * Remove and free all the nodes from the radix tree.
+ * This function is recrusive but there is a tight control on it as the
+ * maximum depth of the tree is fixed.
+ */
+void
+vm_radix_reclaim_allnodes(struct vm_radix *rtree)
+{
+ struct vm_radix_node *root;
+ int level;
+
+ if (rtree->rt_root == 0)
+ return;
+ level = vm_radix_height(rtree, &root);
+ vm_radix_reclaim_allnodes_internal(root, level - 1);
+ rtree->rt_root = 0;
+}
+
+/*
* Attempts to reduce the height of the tree.
*/
void
Modified: user/attilio/vmcontention/sys/vm/vm_radix.h
==============================================================================
--- user/attilio/vmcontention/sys/vm/vm_radix.h Tue Nov 1 02:04:52 2011 (r226979)
+++ user/attilio/vmcontention/sys/vm/vm_radix.h Tue Nov 1 03:40:38 2011 (r226980)
@@ -79,6 +79,7 @@ void *vm_radix_lookup(struct vm_radix *,
int vm_radix_lookupn(struct vm_radix *, vm_pindex_t, vm_pindex_t, int,
void **, int, vm_pindex_t *);
void *vm_radix_lookup_le(struct vm_radix *, vm_pindex_t, int);
+void vm_radix_reclaim_allnodes(struct vm_radix *);
void *vm_radix_remove(struct vm_radix *, vm_pindex_t, int);
void vm_radix_foreach(struct vm_radix *, vm_pindex_t, vm_pindex_t, int,
void (*)(void *));
More information about the svn-src-user
mailing list