svn commit: r224569 - head/lib/libmemstat

Sergey Kandaurov pluknet at FreeBSD.org
Mon Aug 1 09:43:35 UTC 2011


Author: pluknet
Date: Mon Aug  1 09:43:35 2011
New Revision: 224569
URL: http://svn.freebsd.org/changeset/base/224569

Log:
  Get rid of MAXCPU knowledge used for internal needs only. Switch to
  dynamic memory allocation to hold per-CPU memory types data (sized to
  mp_maxid for UMA, and to mp_maxcpus for malloc to match the kernel).
  
  That fixes libmemstat with arbitrary large MAXCPU values and therefore
  eliminates MEMSTAT_ERROR_TOOMANYCPUS error type.
  
  Reviewed by:	jhb
  Approved by:	re (kib)

Modified:
  head/lib/libmemstat/libmemstat.3
  head/lib/libmemstat/memstat.c
  head/lib/libmemstat/memstat.h
  head/lib/libmemstat/memstat_internal.h
  head/lib/libmemstat/memstat_malloc.c
  head/lib/libmemstat/memstat_uma.c

Modified: head/lib/libmemstat/libmemstat.3
==============================================================================
--- head/lib/libmemstat/libmemstat.3	Mon Aug  1 08:52:05 2011	(r224568)
+++ head/lib/libmemstat/libmemstat.3	Mon Aug  1 09:43:35 2011	(r224569)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 27, 2005
+.Dd July 21, 2011
 .Dt LIBMEMSTAT 3
 .Os
 .Sh NAME
@@ -412,10 +412,6 @@ values of
 .Er EACCES
 or
 .Er EPERM .
-.It Dv MEMSTAT_ERROR_TOOMANYCPUS
-Returned if the compile-time limit on the number of CPUs in
-.Nm
-is lower than the number of CPUs returned by a statistics data source.
 .It Dv MEMSTAT_ERROR_DATAERROR
 Returned if
 .Nm

Modified: head/lib/libmemstat/memstat.c
==============================================================================
--- head/lib/libmemstat/memstat.c	Mon Aug  1 08:52:05 2011	(r224568)
+++ head/lib/libmemstat/memstat.c	Mon Aug  1 09:43:35 2011	(r224569)
@@ -49,8 +49,6 @@ memstat_strerror(int error)
 		return ("Version mismatch");
 	case MEMSTAT_ERROR_PERMISSION:
 		return ("Permission denied");
-	case MEMSTAT_ERROR_TOOMANYCPUS:
-		return ("Too many CPUs");
 	case MEMSTAT_ERROR_DATAERROR:
 		return ("Data format error");
 	case MEMSTAT_ERROR_KVM:
@@ -99,6 +97,8 @@ _memstat_mtl_empty(struct memory_type_li
 	struct memory_type *mtp;
 
 	while ((mtp = LIST_FIRST(&list->mtl_list))) {
+		free(mtp->mt_percpu_alloc);
+		free(mtp->mt_percpu_cache);
 		LIST_REMOVE(mtp, mt_list);
 		free(mtp);
 	}
@@ -147,7 +147,7 @@ memstat_mtl_find(struct memory_type_list
  */
 struct memory_type *
 _memstat_mt_allocate(struct memory_type_list *list, int allocator,
-    const char *name)
+    const char *name, int maxcpus)
 {
 	struct memory_type *mtp;
 
@@ -158,6 +158,10 @@ _memstat_mt_allocate(struct memory_type_
 	bzero(mtp, sizeof(*mtp));
 
 	mtp->mt_allocator = allocator;
+	mtp->mt_percpu_alloc = malloc(sizeof(struct mt_percpu_alloc_s) *
+	    maxcpus);
+	mtp->mt_percpu_cache = malloc(sizeof(struct mt_percpu_cache_s) *
+	    maxcpus);
 	strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME);
 	LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list);
 	return (mtp);
@@ -171,7 +175,7 @@ _memstat_mt_allocate(struct memory_type_
  * libmemstat(3) internal function.
  */
 void
-_memstat_mt_reset_stats(struct memory_type *mtp)
+_memstat_mt_reset_stats(struct memory_type *mtp, int maxcpus)
 {
 	int i;
 
@@ -193,7 +197,7 @@ _memstat_mt_reset_stats(struct memory_ty
 	mtp->mt_zonefree = 0;
 	mtp->mt_kegfree = 0;
 
-	for (i = 0; i < MEMSTAT_MAXCPU; i++) {
+	for (i = 0; i < maxcpus; i++) {
 		mtp->mt_percpu_alloc[i].mtp_memalloced = 0;
 		mtp->mt_percpu_alloc[i].mtp_memfreed = 0;
 		mtp->mt_percpu_alloc[i].mtp_numallocs = 0;

Modified: head/lib/libmemstat/memstat.h
==============================================================================
--- head/lib/libmemstat/memstat.h	Mon Aug  1 08:52:05 2011	(r224568)
+++ head/lib/libmemstat/memstat.h	Mon Aug  1 09:43:35 2011	(r224569)
@@ -30,12 +30,6 @@
 #define	_MEMSTAT_H_
 
 /*
- * Number of CPU slots in library-internal data structures.  This should be
- * at least the value of MAXCPU from param.h.
- */
-#define	MEMSTAT_MAXCPU	32
-
-/*
  * Amount of caller data to maintain for each caller data slot.  Applications
  * must not request more than this number of caller save data, or risk
  * corrupting internal libmemstat(3) data structures.  A compile time check
@@ -70,7 +64,6 @@
 #define	MEMSTAT_ERROR_NOMEMORY		1	/* Out of memory. */
 #define	MEMSTAT_ERROR_VERSION		2	/* Unsupported version. */
 #define	MEMSTAT_ERROR_PERMISSION	3	/* Permission denied. */
-#define	MEMSTAT_ERROR_TOOMANYCPUS	4	/* Too many CPUs. */
 #define	MEMSTAT_ERROR_DATAERROR		5	/* Error in stat data. */
 #define	MEMSTAT_ERROR_KVM		6	/* See kvm_geterr() for err. */
 #define	MEMSTAT_ERROR_KVM_NOSYMBOL	7	/* Symbol not available. */

Modified: head/lib/libmemstat/memstat_internal.h
==============================================================================
--- head/lib/libmemstat/memstat_internal.h	Mon Aug  1 08:52:05 2011	(r224568)
+++ head/lib/libmemstat/memstat_internal.h	Mon Aug  1 09:43:35 2011	(r224569)
@@ -92,7 +92,7 @@ struct memory_type {
 	 * Per-CPU measurements fall into two categories: per-CPU allocation,
 	 * and per-CPU cache state.
 	 */
-	struct {
+	struct mt_percpu_alloc_s {
 		uint64_t	 mtp_memalloced;/* Per-CPU mt_memalloced. */
 		uint64_t	 mtp_memfreed;	/* Per-CPU mt_memfreed. */
 		uint64_t	 mtp_numallocs;	/* Per-CPU mt_numallocs. */
@@ -100,11 +100,11 @@ struct memory_type {
 		uint64_t	 mtp_sizemask;	/* Per-CPU mt_sizemask. */
 		void		*mtp_caller_pointer[MEMSTAT_MAXCALLER];
 		uint64_t	 mtp_caller_uint64[MEMSTAT_MAXCALLER];
-	}	mt_percpu_alloc[MEMSTAT_MAXCPU];
+	}	*mt_percpu_alloc;
 
-	struct {
+	struct mt_percpu_cache_s {
 		uint64_t	 mtp_free;	/* Per-CPU cache free items. */
-	}	mt_percpu_cache[MEMSTAT_MAXCPU];
+	}	*mt_percpu_cache;
 
 	LIST_ENTRY(memory_type)	mt_list;	/* List of types. */
 };
@@ -119,7 +119,8 @@ struct memory_type_list {
 
 void			 _memstat_mtl_empty(struct memory_type_list *list);
 struct memory_type	*_memstat_mt_allocate(struct memory_type_list *list,
-			    int allocator, const char *name);
-void			 _memstat_mt_reset_stats(struct memory_type *mtp);
+			    int allocator, const char *name, int maxcpus);
+void			 _memstat_mt_reset_stats(struct memory_type *mtp,
+			    int maxcpus);
 
 #endif /* !_MEMSTAT_INTERNAL_H_ */

Modified: head/lib/libmemstat/memstat_malloc.c
==============================================================================
--- head/lib/libmemstat/memstat_malloc.c	Mon Aug  1 08:52:05 2011	(r224568)
+++ head/lib/libmemstat/memstat_malloc.c	Mon Aug  1 09:43:35 2011	(r224569)
@@ -96,11 +96,6 @@ retry:
 		return (-1);
 	}
 
-	if (maxcpus > MEMSTAT_MAXCPU) {
-		list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
-		return (-1);
-	}
-
 	size = sizeof(count);
 	if (sysctlbyname("kern.malloc_count", &count, &size, NULL, 0) < 0) {
 		if (errno == EACCES || errno == EPERM)
@@ -160,12 +155,6 @@ retry:
 		return (-1);
 	}
 
-	if (mtshp->mtsh_maxcpus > MEMSTAT_MAXCPU) {
-		list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
-		free(buffer);
-		return (-1);
-	}
-
 	/*
 	 * For the remainder of this function, we are quite trusting about
 	 * the layout of structures and sizes, since we've determined we have
@@ -184,7 +173,7 @@ retry:
 			mtp = NULL;
 		if (mtp == NULL)
 			mtp = _memstat_mt_allocate(list, ALLOCATOR_MALLOC,
-			    mthp->mth_name);
+			    mthp->mth_name, maxcpus);
 		if (mtp == NULL) {
 			_memstat_mtl_empty(list);
 			free(buffer);
@@ -195,7 +184,7 @@ retry:
 		/*
 		 * Reset the statistics on a current node.
 		 */
-		_memstat_mt_reset_stats(mtp);
+		_memstat_mt_reset_stats(mtp, maxcpus);
 
 		for (j = 0; j < maxcpus; j++) {
 			mtsp = (struct malloc_type_stats *)p;
@@ -295,7 +284,7 @@ memstat_kvm_malloc(struct memory_type_li
 	void *kmemstatistics;
 	int hint_dontsearch, j, mp_maxcpus, ret;
 	char name[MEMTYPE_MAXNAME];
-	struct malloc_type_stats mts[MEMSTAT_MAXCPU], *mtsp;
+	struct malloc_type_stats *mts, *mtsp;
 	struct malloc_type_internal *mtip;
 	struct malloc_type type, *typep;
 	kvm_t *kvm;
@@ -322,11 +311,6 @@ memstat_kvm_malloc(struct memory_type_li
 		return (-1);
 	}
 
-	if (mp_maxcpus > MEMSTAT_MAXCPU) {
-		list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
-		return (-1);
-	}
-
 	ret = kread_symbol(kvm, X_KMEMSTATISTICS, &kmemstatistics,
 	    sizeof(kmemstatistics), 0);
 	if (ret != 0) {
@@ -334,10 +318,17 @@ memstat_kvm_malloc(struct memory_type_li
 		return (-1);
 	}
 
+	mts = malloc(sizeof(struct malloc_type_stats) * mp_maxcpus);
+	if (mts == NULL) {
+		list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+		return (-1);
+	}
+
 	for (typep = kmemstatistics; typep != NULL; typep = type.ks_next) {
 		ret = kread(kvm, typep, &type, sizeof(type), 0);
 		if (ret != 0) {
 			_memstat_mtl_empty(list);
+			free(mts);
 			list->mtl_error = ret;
 			return (-1);
 		}
@@ -345,6 +336,7 @@ memstat_kvm_malloc(struct memory_type_li
 		    MEMTYPE_MAXNAME);
 		if (ret != 0) {
 			_memstat_mtl_empty(list);
+			free(mts);
 			list->mtl_error = ret;
 			return (-1);
 		}
@@ -358,6 +350,7 @@ memstat_kvm_malloc(struct memory_type_li
 		    sizeof(struct malloc_type_stats), 0);
 		if (ret != 0) {
 			_memstat_mtl_empty(list);
+			free(mts);
 			list->mtl_error = ret;
 			return (-1);
 		}
@@ -368,9 +361,10 @@ memstat_kvm_malloc(struct memory_type_li
 			mtp = NULL;
 		if (mtp == NULL)
 			mtp = _memstat_mt_allocate(list, ALLOCATOR_MALLOC,
-			    name);
+			    name, mp_maxcpus);
 		if (mtp == NULL) {
 			_memstat_mtl_empty(list);
+			free(mts);
 			list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
 			return (-1);
 		}
@@ -379,7 +373,7 @@ memstat_kvm_malloc(struct memory_type_li
 		 * This logic is replicated from kern_malloc.c, and should
 		 * be kept in sync.
 		 */
-		_memstat_mt_reset_stats(mtp);
+		_memstat_mt_reset_stats(mtp, mp_maxcpus);
 		for (j = 0; j < mp_maxcpus; j++) {
 			mtsp = &mts[j];
 			mtp->mt_memalloced += mtsp->mts_memalloced;

Modified: head/lib/libmemstat/memstat_uma.c
==============================================================================
--- head/lib/libmemstat/memstat_uma.c	Mon Aug  1 08:52:05 2011	(r224568)
+++ head/lib/libmemstat/memstat_uma.c	Mon Aug  1 09:43:35 2011	(r224569)
@@ -79,7 +79,7 @@ memstat_sysctl_uma(struct memory_type_li
 	struct uma_type_header *uthp;
 	struct uma_percpu_stat *upsp;
 	struct memory_type *mtp;
-	int count, hint_dontsearch, i, j, maxcpus;
+	int count, hint_dontsearch, i, j, maxcpus, maxid;
 	char *buffer, *p;
 	size_t size;
 
@@ -93,24 +93,19 @@ memstat_sysctl_uma(struct memory_type_li
 	 * from the header.
 	 */
 retry:
-	size = sizeof(maxcpus);
-	if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
+	size = sizeof(maxid);
+	if (sysctlbyname("kern.smp.maxid", &maxid, &size, NULL, 0) < 0) {
 		if (errno == EACCES || errno == EPERM)
 			list->mtl_error = MEMSTAT_ERROR_PERMISSION;
 		else
 			list->mtl_error = MEMSTAT_ERROR_DATAERROR;
 		return (-1);
 	}
-	if (size != sizeof(maxcpus)) {
+	if (size != sizeof(maxid)) {
 		list->mtl_error = MEMSTAT_ERROR_DATAERROR;
 		return (-1);
 	}
 
-	if (maxcpus > MEMSTAT_MAXCPU) {
-		list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
-		return (-1);
-	}
-
 	size = sizeof(count);
 	if (sysctlbyname("vm.zone_count", &count, &size, NULL, 0) < 0) {
 		if (errno == EACCES || errno == EPERM)
@@ -125,7 +120,7 @@ retry:
 	}
 
 	size = sizeof(*uthp) + count * (sizeof(*uthp) + sizeof(*upsp) *
-	    maxcpus);
+	    (maxid + 1));
 
 	buffer = malloc(size);
 	if (buffer == NULL) {
@@ -170,12 +165,6 @@ retry:
 		return (-1);
 	}
 
-	if (ushp->ush_maxcpus > MEMSTAT_MAXCPU) {
-		list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
-		free(buffer);
-		return (-1);
-	}
-
 	/*
 	 * For the remainder of this function, we are quite trusting about
 	 * the layout of structures and sizes, since we've determined we have
@@ -194,7 +183,7 @@ retry:
 			mtp = NULL;
 		if (mtp == NULL)
 			mtp = _memstat_mt_allocate(list, ALLOCATOR_UMA,
-			    uthp->uth_name);
+			    uthp->uth_name, maxid + 1);
 		if (mtp == NULL) {
 			_memstat_mtl_empty(list);
 			free(buffer);
@@ -205,7 +194,7 @@ retry:
 		/*
 		 * Reset the statistics on a current node.
 		 */
-		_memstat_mt_reset_stats(mtp);
+		_memstat_mt_reset_stats(mtp, maxid + 1);
 
 		mtp->mt_numallocs = uthp->uth_allocs;
 		mtp->mt_numfrees = uthp->uth_frees;
@@ -398,7 +387,7 @@ memstat_kvm_uma(struct memory_type_list 
 				mtp = NULL;
 			if (mtp == NULL)
 				mtp = _memstat_mt_allocate(list, ALLOCATOR_UMA,
-				    name);
+				    name, mp_maxid + 1);
 			if (mtp == NULL) {
 				free(ucp_array);
 				_memstat_mtl_empty(list);
@@ -408,7 +397,7 @@ memstat_kvm_uma(struct memory_type_list 
 			/*
 			 * Reset the statistics on a current node.
 			 */
-			_memstat_mt_reset_stats(mtp);
+			_memstat_mt_reset_stats(mtp, mp_maxid + 1);
 			mtp->mt_numallocs = uz.uz_allocs;
 			mtp->mt_numfrees = uz.uz_frees;
 			mtp->mt_failures = uz.uz_fails;


More information about the svn-src-all mailing list