summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorbryanv <bryanv@FreeBSD.org>2014-10-22 04:09:47 +0000
committerbryanv <bryanv@FreeBSD.org>2014-10-22 04:09:47 +0000
commit0895e1be7fb426c7fbc533e86b8e366cead1e094 (patch)
treecaf222a7907608499d9d6764ebd18b74cf906337 /sys/vm
parent137a650c1121f5fb5f94f7db8b804e5ea2dee73b (diff)
downloadFreeBSD-src-0895e1be7fb426c7fbc533e86b8e366cead1e094.zip
FreeBSD-src-0895e1be7fb426c7fbc533e86b8e366cead1e094.tar.gz
MFC r272573:
Change the UMA mutex into a rwlock Acquire the lock in read mode when just needed to ensure the stability of the keg list. The UMA lock may be held for a long time (relatively speaking) in uma_reclaim() on machines with lots of zones/kegs. If the uma_timeout() would fire during that period, subsequent callouts on that CPU may be significantly delayed.
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/uma_core.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index f327d22..ff460fb 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -135,8 +135,8 @@ static LIST_HEAD(,uma_keg) uma_kegs = LIST_HEAD_INITIALIZER(uma_kegs);
static LIST_HEAD(,uma_zone) uma_cachezones =
LIST_HEAD_INITIALIZER(uma_cachezones);
-/* This mutex protects the keg list */
-static struct mtx_padalign uma_mtx;
+/* This RW lock protects the keg list */
+static struct rwlock_padalign uma_rwlock;
/* Linked list of boot time pages */
static LIST_HEAD(,uma_slab) uma_boot_pages =
@@ -905,7 +905,7 @@ zone_drain_wait(uma_zone_t zone, int waitok)
ZONE_UNLOCK(zone);
/*
* The DRAINING flag protects us from being freed while
- * we're running. Normally the uma_mtx would protect us but we
+ * we're running. Normally the uma_rwlock would protect us but we
* must be able to release and acquire the right lock for each keg.
*/
zone_foreach_keg(zone, &keg_drain);
@@ -1541,9 +1541,9 @@ keg_ctor(void *mem, int size, void *udata, int flags)
LIST_INSERT_HEAD(&keg->uk_zones, zone, uz_link);
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_INSERT_HEAD(&uma_kegs, keg, uk_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
return (0);
}
@@ -1593,9 +1593,9 @@ zone_ctor(void *mem, int size, void *udata, int flags)
zone->uz_release = arg->release;
zone->uz_arg = arg->arg;
zone->uz_lockptr = &zone->uz_lock;
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_INSERT_HEAD(&uma_cachezones, zone, uz_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
goto out;
}
@@ -1612,7 +1612,7 @@ zone_ctor(void *mem, int size, void *udata, int flags)
zone->uz_fini = arg->fini;
zone->uz_lockptr = &keg->uk_lock;
zone->uz_flags |= UMA_ZONE_SECONDARY;
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
ZONE_LOCK(zone);
LIST_FOREACH(z, &keg->uk_zones, uz_link) {
if (LIST_NEXT(z, uz_link) == NULL) {
@@ -1621,7 +1621,7 @@ zone_ctor(void *mem, int size, void *udata, int flags)
}
}
ZONE_UNLOCK(zone);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
} else if (keg == NULL) {
if ((keg = uma_kcreate(zone, arg->size, arg->uminit, arg->fini,
arg->align, arg->flags)) == NULL)
@@ -1719,9 +1719,9 @@ zone_dtor(void *arg, int size, void *udata)
if (!(zone->uz_flags & UMA_ZFLAG_INTERNAL))
cache_drain(zone);
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_REMOVE(zone, uz_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
/*
* XXX there are some races here where
* the zone can be drained but zone lock
@@ -1743,9 +1743,9 @@ zone_dtor(void *arg, int size, void *udata)
* We only destroy kegs from non secondary zones.
*/
if (keg != NULL && (zone->uz_flags & UMA_ZONE_SECONDARY) == 0) {
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_REMOVE(keg, uk_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
zone_free_item(kegs, keg, NULL, SKIP_NONE);
}
ZONE_LOCK_FINI(zone);
@@ -1767,12 +1767,12 @@ zone_foreach(void (*zfunc)(uma_zone_t))
uma_keg_t keg;
uma_zone_t zone;
- mtx_lock(&uma_mtx);
+ rw_rlock(&uma_rwlock);
LIST_FOREACH(keg, &uma_kegs, uk_link) {
LIST_FOREACH(zone, &keg->uk_zones, uz_link)
zfunc(zone);
}
- mtx_unlock(&uma_mtx);
+ rw_runlock(&uma_rwlock);
}
/* Public functions */
@@ -1788,7 +1788,7 @@ uma_startup(void *bootmem, int boot_pages)
#ifdef UMA_DEBUG
printf("Creating uma keg headers zone and keg.\n");
#endif
- mtx_init(&uma_mtx, "UMA lock", NULL, MTX_DEF);
+ rw_init(&uma_rwlock, "UMA lock");
/* "manually" create the initial zone */
memset(&args, 0, sizeof(args));
@@ -3363,12 +3363,12 @@ sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS)
int count;
count = 0;
- mtx_lock(&uma_mtx);
+ rw_rlock(&uma_rwlock);
LIST_FOREACH(kz, &uma_kegs, uk_link) {
LIST_FOREACH(z, &kz->uk_zones, uz_link)
count++;
}
- mtx_unlock(&uma_mtx);
+ rw_runlock(&uma_rwlock);
return (sysctl_handle_int(oidp, &count, 0, req));
}
@@ -3393,7 +3393,7 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS)
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
count = 0;
- mtx_lock(&uma_mtx);
+ rw_rlock(&uma_rwlock);
LIST_FOREACH(kz, &uma_kegs, uk_link) {
LIST_FOREACH(z, &kz->uk_zones, uz_link)
count++;
@@ -3469,7 +3469,7 @@ skip:
ZONE_UNLOCK(z);
}
}
- mtx_unlock(&uma_mtx);
+ rw_runlock(&uma_rwlock);
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
return (error);
OpenPOWER on IntegriCloud