summaryrefslogtreecommitdiff
path: root/libhurd-mm/anonymous.c
diff options
context:
space:
mode:
authorneal <neal>2008-06-20 08:58:14 +0000
committerneal <neal>2008-06-20 08:58:14 +0000
commitae7ee9d5890eed4854c150b46d37cbe36b2e691f (patch)
treee265ca30f5c6da982c7a4d61c34de0153e636a31 /libhurd-mm/anonymous.c
parentf91025d06a22726ffa59fd657c354252b8b845b5 (diff)
2008-06-20 Neal H. Walfield <neal@gnu.org>
* anonymous.c (mdestroy): Optimize storage destruction when MAP is the last reference. (destroy): Assert that PAGER has no allocated storage.
Diffstat (limited to 'libhurd-mm/anonymous.c')
-rw-r--r--libhurd-mm/anonymous.c117
1 files changed, 66 insertions, 51 deletions
diff --git a/libhurd-mm/anonymous.c b/libhurd-mm/anonymous.c
index a58fa07..66eb7d3 100644
--- a/libhurd-mm/anonymous.c
+++ b/libhurd-mm/anonymous.c
@@ -340,53 +340,83 @@ mdestroy (struct map *map)
We may have to reexamine this assumption if we allow multiple
mappings onto the same part of a pager (e.g., via mremap). */
- /* Free the storage in this region. */
-
- uintptr_t offset[2];
- offset[0] = map->offset | 1;
- offset[1] = map->region.length;
-
hurd_btree_storage_desc_t *storage_descs;
storage_descs = (hurd_btree_storage_desc_t *) &anon->storage;
- struct storage_desc *next
- = hurd_btree_storage_desc_find (storage_descs, &offset[0]);
- if (next)
- {
- int count = 0;
+ int count = 0;
- /* We destory STORAGE_DESC. Grab its pervious pointer
- first. */
- struct storage_desc *prev = hurd_btree_storage_desc_prev (next);
+ /* Free the storage in this region. */
+ if (anon->pager.maps == map && ! map->map_list_next)
+ /* This is the last reference. As we know that the tree will be
+ empty when we are done, we can avoid the costs of the
+ detaches. */
+ {
+ struct storage_desc *node, *next;
+ for (node = hurd_btree_storage_desc_first (storage_descs);
+ node;
+ node = next)
+ {
+ next = hurd_btree_storage_desc_next (node);
- int dir;
- struct storage_desc *storage_desc;
- for (dir = 0; dir < 2; dir ++, next = prev)
- while ((storage_desc = next))
- {
- next = (dir == 0 ? hurd_btree_storage_desc_next (storage_desc)
- : hurd_btree_storage_desc_prev (storage_desc));
+ storage_free (node->storage, false);
- if (storage_desc->offset < map->offset
- || (storage_desc->offset
- > map->offset + map->region.length - 1))
- break;
+#ifndef NDEBUG
+ /* When reallocating, we expect that the node field is 0.
+ libhurd-btree asserts this, so make it so. */
+ memset (node, 0, sizeof (struct storage_desc));
+#endif
+ storage_desc_free (node);
- storage_free (storage_desc->storage, false);
+ count ++;
+ }
- hurd_btree_storage_desc_detach (storage_descs, storage_desc);
#ifndef NDEBUG
- /* When reallocating, we expect that the node field is 0.
- libhurd-btree asserts this, so make it so. */
- memset (storage_desc, 0, sizeof (struct storage_desc));
+ memset (storage_descs, 0, sizeof (*storage_descs));
#endif
- storage_desc_free (storage_desc);
+ }
+ else
+ {
+ uintptr_t offset[2];
+ offset[0] = map->offset | 1;
+ offset[1] = map->region.length;
- count ++;
- }
+ struct storage_desc *next
+ = hurd_btree_storage_desc_find (storage_descs, &offset[0]);
+ if (next)
+ {
+ /* We destory STORAGE_DESC. Grab its pervious pointer
+ first. */
+ struct storage_desc *prev = hurd_btree_storage_desc_prev (next);
+
+ int dir;
+ struct storage_desc *storage_desc;
+ for (dir = 0; dir < 2; dir ++, next = prev)
+ while ((storage_desc = next))
+ {
+ next = (dir == 0 ? hurd_btree_storage_desc_next (storage_desc)
+ : hurd_btree_storage_desc_prev (storage_desc));
+
+ if (storage_desc->offset < map->offset
+ || (storage_desc->offset
+ > map->offset + map->region.length - 1))
+ break;
+
+ storage_free (storage_desc->storage, false);
+
+ hurd_btree_storage_desc_detach (storage_descs, storage_desc);
+#ifndef NDEBUG
+ /* When reallocating, we expect that the node field is 0.
+ libhurd-btree asserts this, so make it so. */
+ memset (storage_desc, 0, sizeof (struct storage_desc));
+#endif
+ storage_desc_free (storage_desc);
- debug (5, "Freed %d pages", count);
+ count ++;
+ }
+ }
}
+ if (count > 0)
+ debug (5, "Freed %d pages", count);
/* Free the map area. Should we also free the staging area? */
as_free (PTR_TO_ADDR (map->region.start), map->region.length);
@@ -410,25 +440,10 @@ destroy (struct pager *pager)
else
assert (! (anon->flags & ANONYMOUS_STAGING_AREA));
- /* Free the allocated storage. */
+ /* Since there are no maps, all storage should have been freed. */
hurd_btree_storage_desc_t *storage_descs;
storage_descs = (hurd_btree_storage_desc_t *) &anon->storage;
-
- struct storage_desc *node, *next;
- for (node = hurd_btree_storage_desc_first (storage_descs); node; node = next)
- {
- next = hurd_btree_storage_desc_next (node);
-
- storage_free (node->storage, false);
-
-#ifndef NDEBUG
- /* When reallocating, we expect that the node field is 0.
- libhurd-btree asserts this, so make it so. */
- memset (node, 0, sizeof (struct storage_desc));
-#endif
- storage_desc_free (node);
- }
-
+ assert (! hurd_btree_storage_desc_first (storage_descs));
/* There is no need to unlock &anon->pager.lock: we free it. */