svn commit: r252040 - head/sys/vm

Jeff Roberson jeff at FreeBSD.org
Thu Jun 20 19:08:13 UTC 2013


Author: jeff
Date: Thu Jun 20 19:08:12 2013
New Revision: 252040
URL: http://svnweb.freebsd.org/changeset/base/252040

Log:
   - Add a per-zone lock for zones without kegs.
   - Be more explicit about zone vs keg locking.  This functionally changes
     almost nothing.
   - Add a size parameter to uma_zcache_create() so we can size the buckets.
   - Pass the zone to bucket_alloc() so it can modify allocation flags
     as appropriate.
   - Fix a bug in zone_alloc_bucket() where I missed an address of operator
     in a failure case.  (Found by pho)
  
  Sponsored by:	EMC / Isilon Storage Division

Modified:
  head/sys/vm/uma.h
  head/sys/vm/uma_core.c
  head/sys/vm/uma_dbg.c
  head/sys/vm/uma_int.h

Modified: head/sys/vm/uma.h
==============================================================================
--- head/sys/vm/uma.h	Thu Jun 20 18:25:10 2013	(r252039)
+++ head/sys/vm/uma.h	Thu Jun 20 19:08:12 2013	(r252040)
@@ -234,7 +234,7 @@ int uma_zsecond_add(uma_zone_t zone, uma
  * zones.  The 'arg' parameter is passed to import/release and is caller
  * specific.
  */
-uma_zone_t uma_zcache_create(char *name, uma_ctor ctor, uma_dtor dtor,
+uma_zone_t uma_zcache_create(char *name, int size, uma_ctor ctor, uma_dtor dtor,
 		    uma_init zinit, uma_fini zfini, uma_import zimport,
 		    uma_release zrelease, void *arg, int flags);
 

Modified: head/sys/vm/uma_core.c
==============================================================================
--- head/sys/vm/uma_core.c	Thu Jun 20 18:25:10 2013	(r252039)
+++ head/sys/vm/uma_core.c	Thu Jun 20 19:08:12 2013	(r252040)
@@ -246,8 +246,8 @@ static void *zone_alloc_item(uma_zone_t,
 static void zone_free_item(uma_zone_t, void *, void *, enum zfreeskip);
 static void bucket_enable(void);
 static void bucket_init(void);
-static uma_bucket_t bucket_alloc(int, int);
-static void bucket_free(uma_bucket_t);
+static uma_bucket_t bucket_alloc(uma_zone_t zone, int);
+static void bucket_free(uma_zone_t zone, uma_bucket_t);
 static void bucket_zone_drain(void);
 static uma_bucket_t zone_alloc_bucket(uma_zone_t zone, int flags);
 static uma_slab_t zone_fetch_slab(uma_zone_t zone, uma_keg_t last, int flags);
@@ -256,8 +256,6 @@ static void *slab_alloc_item(uma_keg_t k
 static void slab_free_item(uma_keg_t keg, uma_slab_t slab, void *item);
 static uma_keg_t uma_kcreate(uma_zone_t zone, size_t size, uma_init uminit,
     uma_fini fini, int align, uint32_t flags);
-static inline void zone_relock(uma_zone_t zone, uma_keg_t keg);
-static inline void keg_relock(uma_keg_t keg, uma_zone_t zone);
 static int zone_import(uma_zone_t zone, void **bucket, int max, int flags);
 static void zone_release(uma_zone_t zone, void **bucket, int cnt);
 
@@ -352,7 +350,7 @@ bucket_select(int size)
 }
 
 static uma_bucket_t
-bucket_alloc(int entries, int bflags)
+bucket_alloc(uma_zone_t zone, int flags)
 {
 	struct uma_bucket_zone *ubz;
 	uma_bucket_t bucket;
@@ -366,8 +364,10 @@ bucket_alloc(int entries, int bflags)
 	if (bucketdisable)
 		return (NULL);
 
-	ubz = bucket_zone_lookup(entries);
-	bucket = uma_zalloc(ubz->ubz_zone, bflags);
+	if (zone->uz_flags & UMA_ZFLAG_CACHEONLY)
+		flags |= M_NOVM;
+	ubz = bucket_zone_lookup(zone->uz_count);
+	bucket = uma_zalloc(ubz->ubz_zone, flags);
 	if (bucket) {
 #ifdef INVARIANTS
 		bzero(bucket->ub_bucket, sizeof(void *) * ubz->ubz_entries);
@@ -380,7 +380,7 @@ bucket_alloc(int entries, int bflags)
 }
 
 static void
-bucket_free(uma_bucket_t bucket)
+bucket_free(uma_zone_t zone, uma_bucket_t bucket)
 {
 	struct uma_bucket_zone *ubz;
 
@@ -662,9 +662,9 @@ cache_drain(uma_zone_t zone)
 		bucket_drain(zone, cache->uc_allocbucket);
 		bucket_drain(zone, cache->uc_freebucket);
 		if (cache->uc_allocbucket != NULL)
-			bucket_free(cache->uc_allocbucket);
+			bucket_free(zone, cache->uc_allocbucket);
 		if (cache->uc_freebucket != NULL)
-			bucket_free(cache->uc_freebucket);
+			bucket_free(zone, cache->uc_freebucket);
 		cache->uc_allocbucket = cache->uc_freebucket = NULL;
 	}
 	ZONE_LOCK(zone);
@@ -688,7 +688,7 @@ bucket_cache_drain(uma_zone_t zone)
 		LIST_REMOVE(bucket, ub_link);
 		ZONE_UNLOCK(zone);
 		bucket_drain(zone, bucket);
-		bucket_free(bucket);
+		bucket_free(zone, bucket);
 		ZONE_LOCK(zone);
 	}
 }
@@ -801,7 +801,7 @@ zone_drain_wait(uma_zone_t zone, int wai
 		if (waitok == M_NOWAIT)
 			goto out;
 		mtx_unlock(&uma_mtx);
-		msleep(zone, zone->uz_lock, PVM, "zonedrain", 1);
+		msleep(zone, zone->uz_lockptr, PVM, "zonedrain", 1);
 		mtx_lock(&uma_mtx);
 	}
 	zone->uz_flags |= UMA_ZFLAG_DRAINING;
@@ -1375,12 +1375,9 @@ keg_ctor(void *mem, int size, void *udat
 		keg->uk_allocf = startup_alloc;
 
 	/*
-	 * Initialize keg's lock (shared among zones).
+	 * Initialize keg's lock
 	 */
-	if (arg->flags & UMA_ZONE_MTXCLASS)
-		KEG_LOCK_INIT(keg, 1);
-	else
-		KEG_LOCK_INIT(keg, 0);
+	KEG_LOCK_INIT(keg, (arg->flags & UMA_ZONE_MTXCLASS));
 
 	/*
 	 * If we're putting the slab header in the actual page we need to
@@ -1469,15 +1466,18 @@ zone_ctor(void *mem, int size, void *uda
 	timevalclear(&zone->uz_ratecheck);
 	keg = arg->keg;
 
+	ZONE_LOCK_INIT(zone, (arg->flags & UMA_ZONE_MTXCLASS));
+
 	/*
 	 * This is a pure cache zone, no kegs.
 	 */
 	if (arg->import) {
+		zone->uz_size = arg->size;
 		zone->uz_import = arg->import;
 		zone->uz_release = arg->release;
 		zone->uz_arg = arg->arg;
-		zone->uz_count = BUCKET_MAX;
-		return (0);
+		zone->uz_lockptr = &zone->uz_lock;
+		goto out;
 	}
 
 	/*
@@ -1491,7 +1491,7 @@ zone_ctor(void *mem, int size, void *uda
 		KASSERT(arg->keg != NULL, ("Secondary zone on zero'd keg"));
 		zone->uz_init = arg->uminit;
 		zone->uz_fini = arg->fini;
-		zone->uz_lock = &keg->uk_lock;
+		zone->uz_lockptr = &keg->uk_lock;
 		zone->uz_flags |= UMA_ZONE_SECONDARY;
 		mtx_lock(&uma_mtx);
 		ZONE_LOCK(zone);
@@ -1529,7 +1529,7 @@ zone_ctor(void *mem, int size, void *uda
 	 */
 	zone->uz_klink.kl_keg = keg;
 	LIST_INSERT_HEAD(&zone->uz_kegs, &zone->uz_klink, kl_link);
-	zone->uz_lock = &keg->uk_lock;
+	zone->uz_lockptr = &keg->uk_lock;
 	zone->uz_size = keg->uk_size;
 	zone->uz_flags |= (keg->uk_flags &
 	    (UMA_ZONE_INHERIT | UMA_ZFLAG_INHERIT));
@@ -1544,8 +1544,9 @@ zone_ctor(void *mem, int size, void *uda
 		return (0);
 	}
 
-	if ((keg->uk_flags & UMA_ZONE_MAXBUCKET) == 0)
-		zone->uz_count = bucket_select(keg->uk_rsize);
+out:
+	if ((arg->flags & UMA_ZONE_MAXBUCKET) == 0)
+		zone->uz_count = bucket_select(zone->uz_size);
 	else
 		zone->uz_count = BUCKET_MAX;
 
@@ -1626,6 +1627,7 @@ zone_dtor(void *arg, int size, void *uda
 		mtx_unlock(&uma_mtx);
 		zone_free_item(kegs, keg, NULL, SKIP_NONE);
 	}
+	ZONE_LOCK_FINI(zone);
 }
 
 /*
@@ -1849,15 +1851,15 @@ uma_zsecond_create(char *name, uma_ctor 
 
 /* See uma.h */
 uma_zone_t
-uma_zcache_create(char *name, uma_ctor ctor, uma_dtor dtor, uma_init zinit,
-		    uma_fini zfini, uma_import zimport, uma_release zrelease,
-		    void *arg, int flags)
+uma_zcache_create(char *name, int size, uma_ctor ctor, uma_dtor dtor,
+		    uma_init zinit, uma_fini zfini, uma_import zimport,
+		    uma_release zrelease, void *arg, int flags)
 {
 	struct uma_zctor_args args;
 
 	memset(&args, 0, sizeof(args));
 	args.name = name;
-	args.size = 0;
+	args.size = size;
 	args.ctor = ctor;
 	args.dtor = dtor;
 	args.uminit = zinit;
@@ -1876,10 +1878,10 @@ zone_lock_pair(uma_zone_t a, uma_zone_t 
 {
 	if (a < b) {
 		ZONE_LOCK(a);
-		mtx_lock_flags(b->uz_lock, MTX_DUPOK);
+		mtx_lock_flags(b->uz_lockptr, MTX_DUPOK);
 	} else {
 		ZONE_LOCK(b);
-		mtx_lock_flags(a->uz_lock, MTX_DUPOK);
+		mtx_lock_flags(a->uz_lockptr, MTX_DUPOK);
 	}
 }
 
@@ -2071,7 +2073,7 @@ zalloc_start:
 	cache->uc_allocbucket = NULL;
 	critical_exit();
 	if (bucket != NULL)
-		bucket_free(bucket);
+		bucket_free(zone, bucket);
 
 	/* Short-circuit for zones without buckets and low memory. */
 	if (zone->uz_count == 0 || bucketdisable)
@@ -2241,31 +2243,15 @@ keg_fetch_slab(uma_keg_t keg, uma_zone_t
 	return (slab);
 }
 
-static inline void
-zone_relock(uma_zone_t zone, uma_keg_t keg)
-{
-	if (zone->uz_lock != &keg->uk_lock) {
-		KEG_UNLOCK(keg);
-		ZONE_LOCK(zone);
-	}
-}
-
-static inline void
-keg_relock(uma_keg_t keg, uma_zone_t zone)
-{
-	if (zone->uz_lock != &keg->uk_lock) {
-		ZONE_UNLOCK(zone);
-		KEG_LOCK(keg);
-	}
-}
-
 static uma_slab_t
 zone_fetch_slab(uma_zone_t zone, uma_keg_t keg, int flags)
 {
 	uma_slab_t slab;
 
-	if (keg == NULL)
+	if (keg == NULL) {
 		keg = zone_first_keg(zone);
+		KEG_LOCK(keg);
+	}
 
 	for (;;) {
 		slab = keg_fetch_slab(keg, zone, flags);
@@ -2274,13 +2260,13 @@ zone_fetch_slab(uma_zone_t zone, uma_keg
 		if (flags & (M_NOWAIT | M_NOVM))
 			break;
 	}
+	KEG_UNLOCK(keg);
 	return (NULL);
 }
 
 /*
  * uma_zone_fetch_slab_multi:  Fetches a slab from one available keg.  Returns
- * with the keg locked.  Caller must call zone_relock() afterwards if the
- * zone lock is required.  On NULL the zone lock is held.
+ * with the keg locked.  On NULL no lock is held.
  *
  * The last pointer is used to seed the search.  It is not required.
  */
@@ -2304,12 +2290,11 @@ zone_fetch_slab_multi(uma_zone_t zone, u
 	 * Use the last slab allocated as a hint for where to start
 	 * the search.
 	 */
-	if (last) {
+	if (last != NULL) {
 		slab = keg_fetch_slab(last, zone, flags);
 		if (slab)
 			return (slab);
-		zone_relock(zone, last);
-		last = NULL;
+		KEG_UNLOCK(last);
 	}
 	/*
 	 * Loop until we have a slab incase of transient failures
@@ -2325,7 +2310,7 @@ zone_fetch_slab_multi(uma_zone_t zone, u
 		 */
 		LIST_FOREACH(klink, &zone->uz_kegs, kl_link) {
 			keg = klink->kl_keg;
-			keg_relock(keg, zone);
+			KEG_LOCK(keg);
 			if ((keg->uk_flags & UMA_ZFLAG_FULL) == 0) {
 				slab = keg_fetch_slab(keg, zone, flags);
 				if (slab)
@@ -2335,7 +2320,7 @@ zone_fetch_slab_multi(uma_zone_t zone, u
 				full++;
 			else
 				empty++;
-			zone_relock(zone, keg);
+			KEG_UNLOCK(keg);
 		}
 		if (rflags & (M_NOWAIT | M_NOVM))
 			break;
@@ -2345,11 +2330,14 @@ zone_fetch_slab_multi(uma_zone_t zone, u
 		 * and sleep so just sleep for a short period and retry.
 		 */
 		if (full && !empty) {
+			ZONE_LOCK(zone);
 			zone->uz_flags |= UMA_ZFLAG_FULL;
 			zone->uz_sleeps++;
 			zone_log_warning(zone);
-			msleep(zone, zone->uz_lock, PVM, "zonelimit", hz/100);
+			msleep(zone, zone->uz_lockptr, PVM,
+			    "zonelimit", hz/100);
 			zone->uz_flags &= ~UMA_ZFLAG_FULL;
+			ZONE_UNLOCK(zone);
 			continue;
 		}
 	}
@@ -2387,15 +2375,14 @@ zone_import(uma_zone_t zone, void **buck
 	uma_keg_t keg;
 	int i;
 
-	ZONE_LOCK(zone);
-	/* Try to keep the buckets totally full */
 	slab = NULL;
 	keg = NULL;
+	/* Try to keep the buckets totally full */
 	for (i = 0; i < max; ) {
 		if ((slab = zone->uz_slab(zone, keg, flags)) == NULL)
 			break;
 		keg = slab->us_keg;
-		while (slab->us_freecount && i < max) 
+		while (slab->us_freecount && i < max)
 			bucket[i++] = slab_alloc_item(keg, slab);
 
 		/* Don't block on the next fill */
@@ -2404,8 +2391,6 @@ zone_import(uma_zone_t zone, void **buck
 	}
 	if (slab != NULL)
 		KEG_UNLOCK(keg);
-	else
-		ZONE_UNLOCK(zone);
 
 	return i;
 }
@@ -2414,18 +2399,13 @@ static uma_bucket_t
 zone_alloc_bucket(uma_zone_t zone, int flags)
 {
 	uma_bucket_t bucket;
-	int bflags;
 	int max;
 
-	max = zone->uz_count;
-	bflags = (flags & ~M_WAITOK) | M_NOWAIT;
-	if (zone->uz_flags & UMA_ZFLAG_CACHEONLY)
-		bflags |= M_NOVM;
-	bucket = bucket_alloc(zone->uz_count, bflags);
+	bucket = bucket_alloc(zone, M_NOWAIT | (flags & M_NOVM));
 	if (bucket == NULL)
 		goto out;
 
-	max = MIN(bucket->ub_entries, max);
+	max = MIN(bucket->ub_entries, zone->uz_count);
 	bucket->ub_cnt = zone->uz_import(zone->uz_arg, bucket->ub_bucket,
 	    max, flags);
 
@@ -2444,7 +2424,7 @@ zone_alloc_bucket(uma_zone_t zone, int f
 		 * rest back onto the freelist.
 		 */
 		if (i != bucket->ub_cnt) {
-			zone->uz_release(zone->uz_arg, bucket->ub_bucket[i],
+			zone->uz_release(zone->uz_arg, &bucket->ub_bucket[i],
 			    bucket->ub_cnt - i);
 #ifdef INVARIANTS
 			bzero(&bucket->ub_bucket[i],
@@ -2457,7 +2437,7 @@ zone_alloc_bucket(uma_zone_t zone, int f
 out:
 	if (bucket == NULL || bucket->ub_cnt == 0) {
 		if (bucket != NULL)
-			bucket_free(bucket);
+			bucket_free(zone, bucket);
 		atomic_add_long(&zone->uz_fails, 1);
 		return (NULL);
 	}
@@ -2529,7 +2509,6 @@ uma_zfree_arg(uma_zone_t zone, void *ite
 {
 	uma_cache_t cache;
 	uma_bucket_t bucket;
-	int bflags;
 	int cpu;
 
 #ifdef UMA_DEBUG_ALLOC_1
@@ -2654,10 +2633,7 @@ zfree_start:
 #ifdef UMA_DEBUG_ALLOC
 	printf("uma_zfree: Allocating new free bucket.\n");
 #endif
-	bflags = M_NOWAIT;
-	if (zone->uz_flags & UMA_ZFLAG_CACHEONLY)
-		bflags |= M_NOVM;
-	bucket = bucket_alloc(zone->uz_count, bflags);
+	bucket = bucket_alloc(zone, M_NOWAIT);
 	if (bucket) {
 		critical_enter();
 		cpu = curcpu;
@@ -2671,7 +2647,7 @@ zfree_start:
 		 * critical section to free the bucket.
 		 */
 		critical_exit();
-		bucket_free(bucket);
+		bucket_free(zone, bucket);
 		goto zfree_restart;
 	}
 
@@ -2721,8 +2697,8 @@ zone_release(uma_zone_t zone, void **buc
 	int i;
 
 	clearfull = 0;
-	ZONE_LOCK(zone);
 	keg = zone_first_keg(zone);
+	KEG_LOCK(keg);
 	for (i = 0; i < cnt; i++) {
 		item = bucket[i];
 		if (!(zone->uz_flags & UMA_ZONE_VTOSLAB)) {
@@ -2758,12 +2734,13 @@ zone_release(uma_zone_t zone, void **buc
 			wakeup(keg);
 		}
 	}
-	zone_relock(zone, keg);
+	KEG_UNLOCK(keg);
 	if (clearfull) {
+		ZONE_LOCK(zone);
 		zone->uz_flags &= ~UMA_ZFLAG_FULL;
 		wakeup(zone);
+		ZONE_UNLOCK(zone);
 	}
-	ZONE_UNLOCK(zone);
 
 }
 
@@ -2807,12 +2784,12 @@ uma_zone_set_max(uma_zone_t zone, int ni
 	keg = zone_first_keg(zone);
 	if (keg == NULL)
 		return (0);
-	ZONE_LOCK(zone);
+	KEG_LOCK(keg);
 	keg->uk_maxpages = (nitems / keg->uk_ipers) * keg->uk_ppera;
 	if (keg->uk_maxpages * keg->uk_ipers < nitems)
 		keg->uk_maxpages += keg->uk_ppera;
 	nitems = keg->uk_maxpages * keg->uk_ipers;
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
 
 	return (nitems);
 }
@@ -2827,9 +2804,9 @@ uma_zone_get_max(uma_zone_t zone)
 	keg = zone_first_keg(zone);
 	if (keg == NULL)
 		return (0);
-	ZONE_LOCK(zone);
+	KEG_LOCK(keg);
 	nitems = keg->uk_maxpages * keg->uk_ipers;
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
 
 	return (nitems);
 }
@@ -2873,13 +2850,13 @@ uma_zone_set_init(uma_zone_t zone, uma_i
 {
 	uma_keg_t keg;
 
-	ZONE_LOCK(zone);
 	keg = zone_first_keg(zone);
 	KASSERT(keg != NULL, ("uma_zone_set_init: Invalid zone type"));
+	KEG_LOCK(keg);
 	KASSERT(keg->uk_pages == 0,
 	    ("uma_zone_set_init on non-empty keg"));
 	keg->uk_init = uminit;
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
 }
 
 /* See uma.h */
@@ -2888,19 +2865,20 @@ uma_zone_set_fini(uma_zone_t zone, uma_f
 {
 	uma_keg_t keg;
 
-	ZONE_LOCK(zone);
 	keg = zone_first_keg(zone);
 	KASSERT(keg != NULL, ("uma_zone_set_init: Invalid zone type"));
+	KEG_LOCK(keg);
 	KASSERT(keg->uk_pages == 0,
 	    ("uma_zone_set_fini on non-empty keg"));
 	keg->uk_fini = fini;
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
 }
 
 /* See uma.h */
 void
 uma_zone_set_zinit(uma_zone_t zone, uma_init zinit)
 {
+
 	ZONE_LOCK(zone);
 	KASSERT(zone_first_keg(zone)->uk_pages == 0,
 	    ("uma_zone_set_zinit on non-empty keg"));
@@ -2912,6 +2890,7 @@ uma_zone_set_zinit(uma_zone_t zone, uma_
 void
 uma_zone_set_zfini(uma_zone_t zone, uma_fini zfini)
 {
+
 	ZONE_LOCK(zone);
 	KASSERT(zone_first_keg(zone)->uk_pages == 0,
 	    ("uma_zone_set_zfini on non-empty keg"));
@@ -2926,11 +2905,11 @@ uma_zone_set_freef(uma_zone_t zone, uma_
 {
 	uma_keg_t keg;
 
-	ZONE_LOCK(zone);
 	keg = zone_first_keg(zone);
 	KASSERT(keg != NULL, ("uma_zone_set_init: Invalid zone type"));
+	KEG_LOCK(keg);
 	keg->uk_freef = freef;
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
 }
 
 /* See uma.h */
@@ -2940,11 +2919,11 @@ uma_zone_set_allocf(uma_zone_t zone, uma
 {
 	uma_keg_t keg;
 
-	ZONE_LOCK(zone);
 	keg = zone_first_keg(zone);
+	KEG_LOCK(keg);
 	keg->uk_flags |= UMA_ZFLAG_PRIVALLOC;
 	keg->uk_allocf = allocf;
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
 }
 
 /* See uma.h */
@@ -2973,7 +2952,7 @@ uma_zone_reserve_kva(uma_zone_t zone, in
 			return (0);
 	} else
 		kva = 0;
-	ZONE_LOCK(zone);
+	KEG_LOCK(keg);
 	keg->uk_kva = kva;
 	keg->uk_offset = 0;
 	keg->uk_maxpages = pages;
@@ -2983,7 +2962,8 @@ uma_zone_reserve_kva(uma_zone_t zone, in
 	keg->uk_allocf = noobj_alloc;
 #endif
 	keg->uk_flags |= UMA_ZONE_NOFREE | UMA_ZFLAG_PRIVALLOC;
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
+
 	return (1);
 }
 
@@ -2998,7 +2978,7 @@ uma_prealloc(uma_zone_t zone, int items)
 	keg = zone_first_keg(zone);
 	if (keg == NULL)
 		return;
-	ZONE_LOCK(zone);
+	KEG_LOCK(keg);
 	slabs = items / keg->uk_ipers;
 	if (slabs * keg->uk_ipers < items)
 		slabs++;
@@ -3010,7 +2990,7 @@ uma_prealloc(uma_zone_t zone, int items)
 		LIST_INSERT_HEAD(&keg->uk_free_slab, slab, us_link);
 		slabs--;
 	}
-	ZONE_UNLOCK(zone);
+	KEG_UNLOCK(keg);
 }
 
 /* See uma.h */

Modified: head/sys/vm/uma_dbg.c
==============================================================================
--- head/sys/vm/uma_dbg.c	Thu Jun 20 18:25:10 2013	(r252039)
+++ head/sys/vm/uma_dbg.c	Thu Jun 20 19:08:12 2013	(r252040)
@@ -231,6 +231,8 @@ uma_dbg_alloc(uma_zone_t zone, uma_slab_
 	uma_keg_t keg;
 	int freei;
 
+	if (zone_first_keg(zone) == NULL)
+		return;
 	if (slab == NULL) {
 		slab = uma_dbg_getslab(zone, item);
 		if (slab == NULL) 
@@ -259,6 +261,8 @@ uma_dbg_free(uma_zone_t zone, uma_slab_t
 	uma_keg_t keg;
 	int freei;
 
+	if (zone_first_keg(zone) == NULL)
+		return;
 	if (slab == NULL) {
 		slab = uma_dbg_getslab(zone, item);
 		if (slab == NULL) 

Modified: head/sys/vm/uma_int.h
==============================================================================
--- head/sys/vm/uma_int.h	Thu Jun 20 18:25:10 2013	(r252039)
+++ head/sys/vm/uma_int.h	Thu Jun 20 19:08:12 2013	(r252040)
@@ -189,7 +189,7 @@ typedef struct uma_cache * uma_cache_t;
  *
  */
 struct uma_keg {
-	struct mtx	uk_lock;	/* Lock for the keg */
+	struct mtx_padalign	uk_lock;	/* Lock for the keg */
 	struct uma_hash	uk_hash;
 
 	LIST_HEAD(,uma_zone)	uk_zones;	/* Keg's zones */
@@ -281,8 +281,9 @@ typedef struct uma_klink *uma_klink_t;
  *
  */
 struct uma_zone {
-	const char	*uz_name;	/* Text name of the zone */
-	struct mtx	*uz_lock;	/* Lock for the zone (keg's lock) */
+	struct mtx_padalign	uz_lock;	/* Lock for the zone */
+	struct mtx_padalign	*uz_lockptr;
+	const char		*uz_name;	/* Text name of the zone */
 
 	LIST_ENTRY(uma_zone)	uz_link;	/* List of all zones in keg */
 	LIST_HEAD(,uma_bucket)	uz_buckets;	/* full buckets */
@@ -334,8 +335,10 @@ struct uma_zone {
 static inline uma_keg_t
 zone_first_keg(uma_zone_t zone)
 {
+	uma_klink_t klink;
 
-	return (LIST_FIRST(&zone->uz_kegs)->kl_keg);
+	klink = LIST_FIRST(&zone->uz_kegs);
+	return (klink != NULL) ? klink->kl_keg : NULL;
 }
 
 #undef UMA_ALIGN
@@ -357,13 +360,25 @@ void uma_large_free(uma_slab_t slab);
 			mtx_init(&(k)->uk_lock, (k)->uk_name,	\
 			    "UMA zone", MTX_DEF | MTX_DUPOK);	\
 	} while (0)
-	    
+
 #define	KEG_LOCK_FINI(k)	mtx_destroy(&(k)->uk_lock)
 #define	KEG_LOCK(k)	mtx_lock(&(k)->uk_lock)
 #define	KEG_UNLOCK(k)	mtx_unlock(&(k)->uk_lock)
-#define	ZONE_LOCK(z)	mtx_lock((z)->uz_lock)
-#define	ZONE_TRYLOCK(z)	mtx_trylock((z)->uz_lock)
-#define ZONE_UNLOCK(z)	mtx_unlock((z)->uz_lock)
+
+#define	ZONE_LOCK_INIT(z, lc)					\
+	do {							\
+		if ((lc))					\
+			mtx_init(&(z)->uz_lock, (z)->uz_name,	\
+			    (z)->uz_name, MTX_DEF | MTX_DUPOK);	\
+		else						\
+			mtx_init(&(z)->uz_lock, (z)->uz_name,	\
+			    "UMA zone", MTX_DEF | MTX_DUPOK);	\
+	} while (0)
+	    
+#define	ZONE_LOCK(z)	mtx_lock((z)->uz_lockptr)
+#define	ZONE_TRYLOCK(z)	mtx_trylock((z)->uz_lockptr)
+#define	ZONE_UNLOCK(z)	mtx_unlock((z)->uz_lockptr)
+#define	ZONE_LOCK_FINI(z)	mtx_destroy(&(z)->uz_lock)
 
 /*
  * Find a slab within a hash table.  This is used for OFFPAGE zones to lookup


More information about the svn-src-all mailing list