Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Oct 2014 04:09:47 +0000 (UTC)
From:      Bryan Venteicher <bryanv@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r273451 - stable/10/sys/vm
Message-ID:  <201410220409.s9M49lWH093815@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bryanv
Date: Wed Oct 22 04:09:47 2014
New Revision: 273451
URL: https://svnweb.freebsd.org/changeset/base/273451

Log:
  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.

Modified:
  stable/10/sys/vm/uma_core.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/vm/uma_core.c
==============================================================================
--- stable/10/sys/vm/uma_core.c	Wed Oct 22 04:01:27 2014	(r273450)
+++ stable/10/sys/vm/uma_core.c	Wed Oct 22 04:09:47 2014	(r273451)
@@ -135,8 +135,8 @@ static LIST_HEAD(,uma_keg) uma_kegs = LI
 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 wai
 	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 *udat
 
 	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 *uda
 		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 *uda
 		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 *uda
 			}
 		}
 		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 *uda
 	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 *uda
 	 * 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_page
 #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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410220409.s9M49lWH093815>