svn commit: r291074 - in head: share/man/man9 sys/kern sys/vm

Jonathan T. Looney jtl at FreeBSD.org
Thu Nov 19 14:04:55 UTC 2015


Author: jtl
Date: Thu Nov 19 14:04:53 2015
New Revision: 291074
URL: https://svnweb.freebsd.org/changeset/base/291074

Log:
  Consistently enforce the restriction against calling malloc/free when in a
  critical section.
  
  uma_zalloc_arg()/uma_zalloc_free() may acquire a sleepable lock on the
  zone. The malloc() family of functions may call uma_zalloc_arg() or
  uma_zalloc_free().
  
  The malloc(9) man page currently claims that free() will never sleep.
  It also implies that the malloc() family of functions will not sleep
  when called with M_NOWAIT. However, it is more correct to say that
  these functions will not sleep indefinitely. Indeed, they may acquire
  a sleepable lock. However, a developer may overlook this restriction
  because the WITNESS check that catches attempts to call the malloc()
  family of functions within a critical section is inconsistenly
  applied.
  
  This change clarifies the language of the malloc(9) man page to clarify
  the restriction against calling the malloc() family of functions
  while in a critical section or holding a spin lock. It also adds
  KASSERTs at appropriate points to make the enforcement of this
  restriction more consistent.
  
  PR:		204633
  Differential Revision:	https://reviews.freebsd.org/D4197
  Reviewed by:	markj
  Approved by:	gnn (mentor)
  Sponsored by:	Juniper Networks

Modified:
  head/share/man/man9/malloc.9
  head/sys/kern/kern_malloc.c
  head/sys/vm/uma_core.c

Modified: head/share/man/man9/malloc.9
==============================================================================
--- head/share/man/man9/malloc.9	Thu Nov 19 13:36:53 2015	(r291073)
+++ head/share/man/man9/malloc.9	Thu Nov 19 14:04:53 2015	(r291074)
@@ -29,7 +29,7 @@
 .\" $NetBSD: malloc.9,v 1.3 1996/11/11 00:05:11 lukem Exp $
 .\" $FreeBSD$
 .\"
-.Dd January 16, 2014
+.Dd November 19, 2015
 .Dt MALLOC 9
 .Os
 .Sh NAME
@@ -227,6 +227,13 @@ may sleep when called with
 .Dv M_WAITOK .
 .Fn free
 never sleeps.
+However,
+.Fn malloc ,
+.Fn realloc,
+.Fn reallocf
+and
+.Fn free
+may not be called in a critical section or while holding a spin lock.
 .Pp
 Any calls to
 .Fn malloc

Modified: head/sys/kern/kern_malloc.c
==============================================================================
--- head/sys/kern/kern_malloc.c	Thu Nov 19 13:36:53 2015	(r291073)
+++ head/sys/kern/kern_malloc.c	Thu Nov 19 14:04:53 2015	(r291074)
@@ -476,6 +476,9 @@ malloc(unsigned long size, struct malloc
 		KASSERT(curthread->td_intr_nesting_level == 0,
 		   ("malloc(M_WAITOK) in interrupt context"));
 
+	KASSERT(curthread->td_critnest == 0,
+	    ("malloc: called with spinlock or critical section held"));
+
 #ifdef DEBUG_MEMGUARD
 	if (memguard_cmp_mtp(mtp, size)) {
 		va = memguard_alloc(size, flags);
@@ -542,6 +545,9 @@ free(void *addr, struct malloc_type *mtp
 
 	KASSERT(mtp->ks_magic == M_MAGIC, ("free: bad malloc type magic"));
 
+	KASSERT(curthread->td_critnest == 0,
+	    ("free: called with spinlock or critical section held"));
+
 	/* free(NULL, ...) does nothing */
 	if (addr == NULL)
 		return;
@@ -605,6 +611,9 @@ realloc(void *addr, unsigned long size, 
 	KASSERT(mtp->ks_magic == M_MAGIC,
 	    ("realloc: bad malloc type magic"));
 
+	KASSERT(curthread->td_critnest == 0,
+	    ("realloc: called with spinlock or critical section held"));
+
 	/* realloc(NULL, ...) is equivalent to malloc(...) */
 	if (addr == NULL)
 		return (malloc(size, mtp, flags));

Modified: head/sys/vm/uma_core.c
==============================================================================
--- head/sys/vm/uma_core.c	Thu Nov 19 13:36:53 2015	(r291073)
+++ head/sys/vm/uma_core.c	Thu Nov 19 14:04:53 2015	(r291074)
@@ -2149,6 +2149,10 @@ uma_zalloc_arg(uma_zone_t zone, void *ud
 		WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
 		    "uma_zalloc_arg: zone \"%s\"", zone->uz_name);
 	}
+
+	KASSERT(curthread->td_critnest == 0,
+	    ("uma_zalloc_arg: called with spinlock or critical section held"));
+
 #ifdef DEBUG_MEMGUARD
 	if (memguard_cmp_zone(zone)) {
 		item = memguard_alloc(zone->uz_size, flags);
@@ -2686,6 +2690,9 @@ uma_zfree_arg(uma_zone_t zone, void *ite
 	CTR2(KTR_UMA, "uma_zfree_arg thread %x zone %s", curthread,
 	    zone->uz_name);
 
+	KASSERT(curthread->td_critnest == 0,
+	    ("uma_zfree_arg: called with spinlock or critical section held"));
+
         /* uma_zfree(..., NULL) does nothing, to match free(9). */
         if (item == NULL)
                 return;


More information about the svn-src-head mailing list