Print this page
XXXX kmem: double-calling kmem_depot_ws_update isn't obvious
While the double-call is documented in a comment, it's not obvious what
exactly it is trying to accomplish. The easiest way to address this is to
introduce a new function that "zeroes-out" the working set statistics to
force everything to be eligible for reaping.
*** 18,27 ****
--- 18,28 ----
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Kernel memory allocator, as described in the following two papers and a
* statement about the consolidator:
*** 2167,2176 ****
--- 2168,2192 ----
cp->cache_empty.ml_min = cp->cache_empty.ml_total;
mutex_exit(&cp->cache_depot_lock);
}
/*
+ * Set the working set statistics for cp's depot to zero. (Everything is
+ * eligible for reaping.)
+ */
+ static void
+ kmem_depot_ws_zero(kmem_cache_t *cp)
+ {
+ mutex_enter(&cp->cache_depot_lock);
+ cp->cache_full.ml_reaplimit = cp->cache_full.ml_total;
+ cp->cache_full.ml_min = cp->cache_full.ml_total;
+ cp->cache_empty.ml_reaplimit = cp->cache_empty.ml_total;
+ cp->cache_empty.ml_min = cp->cache_empty.ml_total;
+ mutex_exit(&cp->cache_depot_lock);
+ }
+
+ /*
* Reap all magazines that have fallen out of the depot's working set.
*/
static void
kmem_depot_ws_reap(kmem_cache_t *cp)
{
*** 3236,3253 ****
kmem_magazine_destroy(cp, mp, rounds);
if (pmp)
kmem_magazine_destroy(cp, pmp, prounds);
}
! /*
! * Updating the working set statistics twice in a row has the
! * effect of setting the working set size to zero, so everything
! * is eligible for reaping.
! */
! kmem_depot_ws_update(cp);
! kmem_depot_ws_update(cp);
!
kmem_depot_ws_reap(cp);
}
/*
* Enable per-cpu magazines on a cache.
--- 3252,3262 ----
kmem_magazine_destroy(cp, mp, rounds);
if (pmp)
kmem_magazine_destroy(cp, pmp, prounds);
}
! kmem_depot_ws_zero(cp);
kmem_depot_ws_reap(cp);
}
/*
* Enable per-cpu magazines on a cache.
*** 3268,3287 ****
}
}
/*
! * Reap (almost) everything right now. See kmem_cache_magazine_purge()
! * for explanation of the back-to-back kmem_depot_ws_update() calls.
*/
void
kmem_cache_reap_now(kmem_cache_t *cp)
{
ASSERT(list_link_active(&cp->cache_link));
! kmem_depot_ws_update(cp);
! kmem_depot_ws_update(cp);
(void) taskq_dispatch(kmem_taskq,
(task_func_t *)kmem_depot_ws_reap, cp, TQ_SLEEP);
taskq_wait(kmem_taskq);
}
--- 3277,3294 ----
}
}
/*
! * Reap (almost) everything right now.
*/
void
kmem_cache_reap_now(kmem_cache_t *cp)
{
ASSERT(list_link_active(&cp->cache_link));
! kmem_depot_ws_zero(cp);
(void) taskq_dispatch(kmem_taskq,
(task_func_t *)kmem_depot_ws_reap, cp, TQ_SLEEP);
taskq_wait(kmem_taskq);
}