Print this page
@@ -116,11 +116,11 @@
* - per vnode (entity->vme_vnode_hash)
* - per shared amp (entity->vme_amp_hash)
* For accurate counting of map-shared and COW-shared pages.
*
* - visited private anons (refcnt > 1) for each collective.
- * (entity->vme_anon)
+ * (entity->vme_anon_hash)
* For accurate counting of COW-shared pages.
*
* The common accounting structure is the vmu_entity_t, which represents
* collectives:
*
@@ -154,11 +154,10 @@
#include <sys/systm.h>
#include <sys/var.h>
#include <sys/vm_usage.h>
#include <sys/zone.h>
#include <sys/sunddi.h>
-#include <sys/sysmacros.h>
#include <sys/avl.h>
#include <vm/anon.h>
#include <vm/as.h>
#include <vm/seg_vn.h>
#include <vm/seg_spt.h>
@@ -202,18 +201,10 @@
short vmo_type;
avl_tree_t vmo_bounds;
} vmu_object_t;
/*
- * Node for tree of visited COW anons.
- */
-typedef struct vmu_anon {
- avl_node_t vma_node;
- uintptr_t vma_addr;
-} vmu_anon_t;
-
-/*
* Entity by which to count results.
*
* The entity structure keeps the current rss/swap counts for each entity
* (zone, project, etc), and hashes of vm structures that have already
* been visited for the entity.
@@ -232,11 +223,11 @@
typedef struct vmu_entity {
struct vmu_entity *vme_next;
struct vmu_entity *vme_next_calc;
mod_hash_t *vme_vnode_hash; /* vnodes visited for entity */
mod_hash_t *vme_amp_hash; /* shared amps visited for entity */
- avl_tree_t vme_anon; /* COW anons visited for entity */
+ mod_hash_t *vme_anon_hash; /* COW anons visited for entity */
vmusage_t vme_result; /* identifies entity and results */
} vmu_entity_t;
/*
* Hash of entities visited within a zone, and an entity for the zone
@@ -335,27 +326,10 @@
return (1);
}
/*
- * Comparison routine for our AVL tree of anon structures.
- */
-static int
-vmu_anon_cmp(const void *lhs, const void *rhs)
-{
- const vmu_anon_t *l = lhs, *r = rhs;
-
- if (l->vma_addr == r->vma_addr)
- return (0);
-
- if (l->vma_addr < r->vma_addr)
- return (-1);
-
- return (1);
-}
-
-/*
* Save a bound on the free list.
*/
static void
vmu_free_bound(vmu_bound_t *bound)
{
@@ -391,23 +365,18 @@
*/
static void
vmu_free_entity(mod_hash_val_t val)
{
vmu_entity_t *entity = (vmu_entity_t *)val;
- vmu_anon_t *anon;
- void *cookie = NULL;
if (entity->vme_vnode_hash != NULL)
i_mod_hash_clear_nosync(entity->vme_vnode_hash);
if (entity->vme_amp_hash != NULL)
i_mod_hash_clear_nosync(entity->vme_amp_hash);
+ if (entity->vme_anon_hash != NULL)
+ i_mod_hash_clear_nosync(entity->vme_anon_hash);
- while ((anon = avl_destroy_nodes(&entity->vme_anon, &cookie)) != NULL)
- kmem_free(anon, sizeof (vmu_anon_t));
-
- avl_destroy(&entity->vme_anon);
-
entity->vme_next = vmu_data.vmu_free_entities;
vmu_data.vmu_free_entities = entity;
}
/*
@@ -518,15 +487,15 @@
if (entity->vme_amp_hash == NULL)
entity->vme_amp_hash = mod_hash_create_ptrhash(
"vmusage amp hash", VMUSAGE_HASH_SIZE, vmu_free_object,
sizeof (struct anon_map));
- VERIFY(avl_first(&entity->vme_anon) == NULL);
+ if (entity->vme_anon_hash == NULL)
+ entity->vme_anon_hash = mod_hash_create_ptrhash(
+ "vmusage anon hash", VMUSAGE_HASH_SIZE,
+ mod_hash_null_valdtor, sizeof (struct anon));
- avl_create(&entity->vme_anon, vmu_anon_cmp, sizeof (struct vmu_anon),
- offsetof(struct vmu_anon, vma_node));
-
entity->vme_next = vmu_data.vmu_entities;
vmu_data.vmu_entities = entity;
vmu_data.vmu_nentities++;
return (entity);
@@ -647,23 +616,25 @@
}
return (object);
}
static int
-vmu_find_insert_anon(vmu_entity_t *entity, void *key)
+vmu_find_insert_anon(mod_hash_t *hash, caddr_t key)
{
- vmu_anon_t anon, *ap;
+ int ret;
+ caddr_t val;
- anon.vma_addr = (uintptr_t)key;
+ ret = i_mod_hash_find_nosync(hash, (mod_hash_key_t)key,
+ (mod_hash_val_t *)&val);
- if (avl_find(&entity->vme_anon, &anon, NULL) != NULL)
+ if (ret == 0)
return (0);
- ap = kmem_alloc(sizeof (vmu_anon_t), KM_SLEEP);
- ap->vma_addr = (uintptr_t)key;
+ ret = i_mod_hash_insert_nosync(hash, (mod_hash_key_t)key,
+ (mod_hash_val_t)key, (mod_hash_hndl_t)0);
- avl_add(&entity->vme_anon, ap);
+ ASSERT(ret == 0);
return (1);
}
static vmu_entity_t *
@@ -1371,11 +1342,12 @@
result = &entity->vme_result;
/*
* Track COW anons per entity so
* they are not double counted.
*/
- if (vmu_find_insert_anon(entity, ap) == 0)
+ if (vmu_find_insert_anon(entity->vme_anon_hash,
+ (caddr_t)ap) == 0)
continue;
result->vmu_rss_all += (pgcnt << PAGESHIFT);
result->vmu_rss_private +=
(pgcnt << PAGESHIFT);
@@ -1645,11 +1617,12 @@
vmu_data.vmu_free_entities->vme_next;
if (te->vme_vnode_hash != NULL)
mod_hash_destroy_hash(te->vme_vnode_hash);
if (te->vme_amp_hash != NULL)
mod_hash_destroy_hash(te->vme_amp_hash);
- VERIFY(avl_first(&te->vme_anon) == NULL);
+ if (te->vme_anon_hash != NULL)
+ mod_hash_destroy_hash(te->vme_anon_hash);
kmem_free(te, sizeof (vmu_entity_t));
}
while (vmu_data.vmu_free_zones != NULL) {
tz = vmu_data.vmu_free_zones;
vmu_data.vmu_free_zones =