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.

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/kmem.c
          +++ new/usr/src/uts/common/os/kmem.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  23   24   */
  24   25  
  25   26  /*
  26   27   * Kernel memory allocator, as described in the following two papers and a
  27   28   * statement about the consolidator:
  28   29   *
  29   30   * Jeff Bonwick,
  30   31   * The Slab Allocator: An Object-Caching Kernel Memory Allocator.
  31   32   * Proceedings of the Summer 1994 Usenix Conference.
  32   33   * Available as /shared/sac/PSARC/1994/028/materials/kmem.pdf.
↓ open down ↓ 2129 lines elided ↑ open up ↑
2162 2163  {
2163 2164          mutex_enter(&cp->cache_depot_lock);
2164 2165          cp->cache_full.ml_reaplimit = cp->cache_full.ml_min;
2165 2166          cp->cache_full.ml_min = cp->cache_full.ml_total;
2166 2167          cp->cache_empty.ml_reaplimit = cp->cache_empty.ml_min;
2167 2168          cp->cache_empty.ml_min = cp->cache_empty.ml_total;
2168 2169          mutex_exit(&cp->cache_depot_lock);
2169 2170  }
2170 2171  
2171 2172  /*
     2173 + * Set the working set statistics for cp's depot to zero.  (Everything is
     2174 + * eligible for reaping.)
     2175 + */
     2176 +static void
     2177 +kmem_depot_ws_zero(kmem_cache_t *cp)
     2178 +{
     2179 +        mutex_enter(&cp->cache_depot_lock);
     2180 +        cp->cache_full.ml_reaplimit = cp->cache_full.ml_total;
     2181 +        cp->cache_full.ml_min = cp->cache_full.ml_total;
     2182 +        cp->cache_empty.ml_reaplimit = cp->cache_empty.ml_total;
     2183 +        cp->cache_empty.ml_min = cp->cache_empty.ml_total;
     2184 +        mutex_exit(&cp->cache_depot_lock);
     2185 +}
     2186 +
     2187 +/*
2172 2188   * Reap all magazines that have fallen out of the depot's working set.
2173 2189   */
2174 2190  static void
2175 2191  kmem_depot_ws_reap(kmem_cache_t *cp)
2176 2192  {
2177 2193          long reap;
2178 2194          kmem_magazine_t *mp;
2179 2195  
2180 2196          ASSERT(!list_link_active(&cp->cache_link) ||
2181 2197              taskq_member(kmem_taskq, curthread));
↓ open down ↓ 1049 lines elided ↑ open up ↑
3231 3247                  ccp->cc_prounds = -1;
3232 3248                  ccp->cc_magsize = 0;
3233 3249                  mutex_exit(&ccp->cc_lock);
3234 3250  
3235 3251                  if (mp)
3236 3252                          kmem_magazine_destroy(cp, mp, rounds);
3237 3253                  if (pmp)
3238 3254                          kmem_magazine_destroy(cp, pmp, prounds);
3239 3255          }
3240 3256  
3241      -        /*
3242      -         * Updating the working set statistics twice in a row has the
3243      -         * effect of setting the working set size to zero, so everything
3244      -         * is eligible for reaping.
3245      -         */
3246      -        kmem_depot_ws_update(cp);
3247      -        kmem_depot_ws_update(cp);
3248      -
     3257 +        kmem_depot_ws_zero(cp);
3249 3258          kmem_depot_ws_reap(cp);
3250 3259  }
3251 3260  
3252 3261  /*
3253 3262   * Enable per-cpu magazines on a cache.
3254 3263   */
3255 3264  static void
3256 3265  kmem_cache_magazine_enable(kmem_cache_t *cp)
3257 3266  {
3258 3267          int cpu_seqid;
↓ open down ↓ 4 lines elided ↑ open up ↑
3263 3272          for (cpu_seqid = 0; cpu_seqid < max_ncpus; cpu_seqid++) {
3264 3273                  kmem_cpu_cache_t *ccp = &cp->cache_cpu[cpu_seqid];
3265 3274                  mutex_enter(&ccp->cc_lock);
3266 3275                  ccp->cc_magsize = cp->cache_magtype->mt_magsize;
3267 3276                  mutex_exit(&ccp->cc_lock);
3268 3277          }
3269 3278  
3270 3279  }
3271 3280  
3272 3281  /*
3273      - * Reap (almost) everything right now.  See kmem_cache_magazine_purge()
3274      - * for explanation of the back-to-back kmem_depot_ws_update() calls.
     3282 + * Reap (almost) everything right now.
3275 3283   */
3276 3284  void
3277 3285  kmem_cache_reap_now(kmem_cache_t *cp)
3278 3286  {
3279 3287          ASSERT(list_link_active(&cp->cache_link));
3280 3288  
3281      -        kmem_depot_ws_update(cp);
3282      -        kmem_depot_ws_update(cp);
     3289 +        kmem_depot_ws_zero(cp);
3283 3290  
3284 3291          (void) taskq_dispatch(kmem_taskq,
3285 3292              (task_func_t *)kmem_depot_ws_reap, cp, TQ_SLEEP);
3286 3293          taskq_wait(kmem_taskq);
3287 3294  }
3288 3295  
3289 3296  /*
3290 3297   * Recompute a cache's magazine size.  The trade-off is that larger magazines
3291 3298   * provide a higher transfer rate with the depot, while smaller magazines
3292 3299   * reduce memory consumption.  Magazine resizing is an expensive operation;
↓ open down ↓ 2295 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX