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;
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to