svn commit: r343051 - in head/sys: compat/linuxkpi/common/src vm
Gleb Smirnoff
glebius at FreeBSD.org
Tue Jan 15 18:24:36 UTC 2019
Author: glebius
Date: Tue Jan 15 18:24:34 2019
New Revision: 343051
URL: https://svnweb.freebsd.org/changeset/base/343051
Log:
Make uz_allocs, uz_frees and uz_fails counter(9). This removes some
atomic updates and reduces amount of data protected by zone lock.
During startup point these fields to EARLY_COUNTER. After startup
allocate them for all early zones.
Tested by: pho
Modified:
head/sys/compat/linuxkpi/common/src/linux_page.c
head/sys/vm/uma_core.c
head/sys/vm/uma_dbg.c
head/sys/vm/uma_int.h
Modified: head/sys/compat/linuxkpi/common/src/linux_page.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_page.c Tue Jan 15 18:22:16 2019 (r343050)
+++ head/sys/compat/linuxkpi/common/src/linux_page.c Tue Jan 15 18:24:34 2019 (r343051)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/counter.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
Modified: head/sys/vm/uma_core.c
==============================================================================
--- head/sys/vm/uma_core.c Tue Jan 15 18:22:16 2019 (r343050)
+++ head/sys/vm/uma_core.c Tue Jan 15 18:24:34 2019 (r343051)
@@ -1715,6 +1715,15 @@ keg_ctor(void *mem, int size, void *udata, int flags)
return (0);
}
+static void
+zone_alloc_counters(uma_zone_t zone)
+{
+
+ zone->uz_allocs = counter_u64_alloc(M_WAITOK);
+ zone->uz_frees = counter_u64_alloc(M_WAITOK);
+ zone->uz_fails = counter_u64_alloc(M_WAITOK);
+}
+
/*
* Zone header ctor. This initializes all fields, locks, etc.
*
@@ -1736,9 +1745,6 @@ zone_ctor(void *mem, int size, void *udata, int flags)
zone->uz_slab = zone_fetch_slab;
zone->uz_init = NULL;
zone->uz_fini = NULL;
- zone->uz_allocs = 0;
- zone->uz_frees = 0;
- zone->uz_fails = 0;
zone->uz_sleeps = 0;
zone->uz_count = 0;
zone->uz_count_min = 0;
@@ -1750,6 +1756,14 @@ zone_ctor(void *mem, int size, void *udata, int flags)
zone->uz_bkt_max = ULONG_MAX;
timevalclear(&zone->uz_ratecheck);
+ if (__predict_true(booted == BOOT_RUNNING))
+ zone_alloc_counters(zone);
+ else {
+ zone->uz_allocs = EARLY_COUNTER;
+ zone->uz_frees = EARLY_COUNTER;
+ zone->uz_fails = EARLY_COUNTER;
+ }
+
/*
* This is a pure cache zone, no kegs.
*/
@@ -1908,6 +1922,9 @@ zone_dtor(void *arg, int size, void *udata)
rw_wunlock(&uma_rwlock);
zone_free_item(kegs, keg, NULL, SKIP_NONE);
}
+ counter_u64_free(zone->uz_allocs);
+ counter_u64_free(zone->uz_frees);
+ counter_u64_free(zone->uz_fails);
if (zone->uz_lockptr == &zone->uz_lock)
ZONE_LOCK_FINI(zone);
}
@@ -1928,12 +1945,19 @@ zone_foreach(void (*zfunc)(uma_zone_t))
uma_keg_t keg;
uma_zone_t zone;
- rw_rlock(&uma_rwlock);
+ /*
+ * Before BOOT_RUNNING we are guaranteed to be single
+ * threaded, so locking isn't needed. Startup functions
+ * are allowed to use M_WAITOK.
+ */
+ if (__predict_true(booted == BOOT_RUNNING))
+ rw_rlock(&uma_rwlock);
LIST_FOREACH(keg, &uma_kegs, uk_link) {
LIST_FOREACH(zone, &keg->uk_zones, uz_link)
zfunc(zone);
}
- rw_runlock(&uma_rwlock);
+ if (__predict_true(booted == BOOT_RUNNING))
+ rw_runlock(&uma_rwlock);
}
/*
@@ -2109,6 +2133,7 @@ uma_startup3(void)
uma_dbg_cnt = counter_u64_alloc(M_WAITOK);
uma_skip_cnt = counter_u64_alloc(M_WAITOK);
#endif
+ zone_foreach(zone_alloc_counters);
callout_init(&uma_callout, 1);
callout_reset(&uma_callout, UMA_TIMEOUT * hz, uma_timeout, NULL);
booted = BOOT_RUNNING;
@@ -2387,7 +2412,7 @@ zalloc_start:
zone->uz_dtor != trash_dtor) &&
#endif
zone->uz_ctor(item, zone->uz_size, udata, flags) != 0) {
- atomic_add_long(&zone->uz_fails, 1);
+ counter_u64_add(zone->uz_fails, 1);
zone_free_item(zone, item, udata, SKIP_DTOR | SKIP_CNT);
return (NULL);
}
@@ -2845,7 +2870,7 @@ zone_alloc_bucket(uma_zone_t zone, void *udata, int do
if (bucket->ub_cnt == 0) {
bucket_free(zone, bucket, udata);
- atomic_add_long(&zone->uz_fails, 1);
+ counter_u64_add(zone->uz_fails, 1);
return (NULL);
}
@@ -2905,7 +2930,6 @@ zone_alloc_item_locked(uma_zone_t zone, void *udata, i
}
zone->uz_items++;
- zone->uz_allocs++;
ZONE_UNLOCK(zone);
if (domain != UMA_ANYDOMAIN) {
@@ -2947,6 +2971,7 @@ zone_alloc_item_locked(uma_zone_t zone, void *udata, i
if (flags & M_ZERO)
uma_zero_item(item, zone);
+ counter_u64_add(zone->uz_allocs, 1);
CTR3(KTR_UMA, "zone_alloc_item item %p from %s(%p)", item,
zone->uz_name, zone);
@@ -2955,9 +2980,8 @@ zone_alloc_item_locked(uma_zone_t zone, void *udata, i
fail:
ZONE_LOCK(zone);
zone->uz_items--;
- zone->uz_allocs--;
ZONE_UNLOCK(zone);
- atomic_add_long(&zone->uz_fails, 1);
+ counter_u64_add(zone->uz_fails, 1);
CTR2(KTR_UMA, "zone_alloc_item failed from %s(%p)",
zone->uz_name, zone);
return (NULL);
@@ -3268,8 +3292,9 @@ zone_free_item(uma_zone_t zone, void *item, void *udat
if (skip & SKIP_CNT)
return;
+ counter_u64_add(zone->uz_frees, 1);
+
ZONE_LOCK(zone);
- zone->uz_frees++;
zone->uz_items--;
if (zone->uz_sleepers > 0 && zone->uz_items < zone->uz_max_items)
wakeup_one(zone);
@@ -3358,7 +3383,8 @@ uma_zone_get_cur(uma_zone_t zone)
u_int i;
ZONE_LOCK(zone);
- nitems = zone->uz_allocs - zone->uz_frees;
+ nitems = counter_u64_fetch(zone->uz_allocs) -
+ counter_u64_fetch(zone->uz_frees);
CPU_FOREACH(i) {
/*
* See the comment in sysctl_vm_zone_stats() regarding the
@@ -3801,8 +3827,8 @@ uma_zone_sumstat(uma_zone_t z, long *cachefreep, uint6
allocs += cache->uc_allocs;
frees += cache->uc_frees;
}
- allocs += z->uz_allocs;
- frees += z->uz_frees;
+ allocs += counter_u64_fetch(z->uz_allocs);
+ frees += counter_u64_fetch(z->uz_frees);
sleeps += z->uz_sleeps;
if (cachefreep != NULL)
*cachefreep = cachefree;
@@ -3895,9 +3921,9 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS)
zdom = &z->uz_domain[i];
uth.uth_zone_free += zdom->uzd_nitems;
}
- uth.uth_allocs = z->uz_allocs;
- uth.uth_frees = z->uz_frees;
- uth.uth_fails = z->uz_fails;
+ uth.uth_allocs = counter_u64_fetch(z->uz_allocs);
+ uth.uth_frees = counter_u64_fetch(z->uz_frees);
+ uth.uth_fails = counter_u64_fetch(z->uz_fails);
uth.uth_sleeps = z->uz_sleeps;
/*
* While it is not normally safe to access the cache
@@ -4105,8 +4131,8 @@ DB_SHOW_COMMAND(uma, db_show_uma)
LIST_FOREACH(kz, &uma_kegs, uk_link) {
LIST_FOREACH(z, &kz->uk_zones, uz_link) {
if (kz->uk_flags & UMA_ZFLAG_INTERNAL) {
- allocs = z->uz_allocs;
- frees = z->uz_frees;
+ allocs = counter_u64_fetch(z->uz_allocs);
+ frees = counter_u64_fetch(z->uz_frees);
sleeps = z->uz_sleeps;
cachefree = 0;
} else
Modified: head/sys/vm/uma_dbg.c
==============================================================================
--- head/sys/vm/uma_dbg.c Tue Jan 15 18:22:16 2019 (r343050)
+++ head/sys/vm/uma_dbg.c Tue Jan 15 18:24:34 2019 (r343051)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitset.h>
+#include <sys/counter.h>
#include <sys/kernel.h>
#include <sys/types.h>
#include <sys/queue.h>
Modified: head/sys/vm/uma_int.h
==============================================================================
--- head/sys/vm/uma_int.h Tue Jan 15 18:22:16 2019 (r343050)
+++ head/sys/vm/uma_int.h Tue Jan 15 18:24:34 2019 (r343051)
@@ -364,10 +364,10 @@ struct uma_zone {
uint16_t uz_count_min; /* Minimal amount of items in bucket */
/* Offset 256, stats. */
- uint64_t uz_allocs UMA_ALIGN; /* Total number of allocations */
+ counter_u64_t uz_allocs; /* Total number of allocations */
+ counter_u64_t uz_frees; /* Total number of frees */
+ counter_u64_t uz_fails; /* Total number of alloc failures */
uint64_t uz_sleeps; /* Total number of alloc sleeps */
- uint64_t uz_frees; /* Total number of frees */
- volatile u_long uz_fails; /* Total number of alloc failures */
/*
* This HAS to be the last item because we adjust the zone size
More information about the svn-src-all
mailing list