Index: lib/libmemstat/memstat.h =================================================================== --- lib/libmemstat/memstat.h +++ lib/libmemstat/memstat.h @@ -117,6 +117,12 @@ int memstat_kvm_malloc(struct memory_type_list *list, void *kvm_handle); int memstat_kvm_uma(struct memory_type_list *list, void *kvm_handle); +/* + * General malloc routines. + */ +size_t memstat_zone_get_count(void); +size_t memstat_zone_get_size(size_t n); + /* * Accessor methods for struct memory_type. */ Index: lib/libmemstat/memstat.c =================================================================== --- lib/libmemstat/memstat.c +++ lib/libmemstat/memstat.c @@ -66,6 +66,59 @@ } } +static size_t memstat_zone_count; +static int memstat_zone_sizes[32]; + +static int +memstat_zone_init(void) +{ + size_t size; + + size = sizeof(memstat_zone_count); + if (sysctlbyname("vm.malloc.zone_count", &memstat_zone_count, &size, NULL, 0) < 0) { + return (-1); + } + + if (memstat_zone_count > nitems(memstat_zone_sizes)) { + return (-1); + } + + size = sizeof(memstat_zone_sizes); + if (sysctlbyname("vm.malloc.zone_sizes", &memstat_zone_sizes, &size, NULL, 0) < 0) { + return (-1); + } + + return (0); +} + +size_t +memstat_zone_get_count(void) +{ + + if (memstat_zone_count == 0) { + if (memstat_zone_init() != 0) + return (-1); + } + + return (memstat_zone_count); +} + +size_t +memstat_zone_get_size(size_t n) +{ + + if (memstat_zone_count == 0) { + if (memstat_zone_init() != 0) + return (-1); + } + + if (n >= nitems(memstat_zone_sizes)) { + return (-1); + } + + return (memstat_zone_sizes[n]); +} + struct memory_type_list * memstat_mtl_alloc(void) { Index: sys/kern/kern_malloc.c =================================================================== --- sys/kern/kern_malloc.c +++ sys/kern/kern_malloc.c @@ -217,6 +217,19 @@ CTLFLAG_RD | CTLTYPE_ULONG | CTLFLAG_MPSAFE, NULL, 0, sysctl_kmem_map_free, "LU", "Free space in kmem"); +static SYSCTL_NODE(_vm, OID_AUTO, malloc, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, + "Malloc information"); + +static int sysctl_vm_malloc_zone_count(SYSCTL_HANDLER_ARGS); +SYSCTL_PROC(_vm_malloc, OID_AUTO, zone_count, + CTLFLAG_RD | CTLTYPE_UINT | CTLFLAG_MPSAFE, NULL, 0, + sysctl_vm_malloc_zone_count, "IU", "Number of malloc zones"); + +static int sysctl_vm_malloc_zone_sizes(SYSCTL_HANDLER_ARGS); +SYSCTL_PROC(_vm_malloc, OID_AUTO, zone_sizes, + CTLFLAG_RD | CTLTYPE_OPAQUE | CTLFLAG_MPSAFE, NULL, 0, + sysctl_vm_malloc_zone_sizes, "S", "Number of malloc zones"); + /* * The malloc_mtx protects the kmemstatistics linked list. */ @@ -278,6 +291,29 @@ return (sysctl_handle_long(oidp, &size, 0, req)); } +static int +sysctl_vm_malloc_zone_count(SYSCTL_HANDLER_ARGS) +{ + int i; + + i = nitems(kmemzones); + + return (SYSCTL_OUT(req, &i, sizeof(i))); +} + +static int +sysctl_vm_malloc_zone_sizes(SYSCTL_HANDLER_ARGS) +{ + int sizes[nitems(kmemzones)]; + int i; + + for (i = 0; i < nitems(kmemzones); i++) { + sizes[i] = kmemzones[i].kz_size; + } + + return (SYSCTL_OUT(req, &sizes, sizeof(sizes))); +} + /* * malloc(9) uma zone separation -- sub-page buffer overruns in one * malloc type will affect only a subset of other malloc types. Index: usr.bin/vmstat/vmstat.c =================================================================== --- usr.bin/vmstat/vmstat.c +++ usr.bin/vmstat/vmstat.c @@ -1407,13 +1407,20 @@ { struct memory_type_list *mtlp; struct memory_type *mtp; - int error, first, i; + ssize_t i, zones; + int error, first; mtlp = memstat_mtl_alloc(); if (mtlp == NULL) { xo_warn("memstat_mtl_alloc"); return; } + zones = memstat_zone_get_count(); + if (zones == -1) { + xo_warn("memstat_zone_get_count"); + memstat_mtl_free(mtlp); + return; + } if (kd == NULL) { if (memstat_sysctl_malloc(mtlp, 0) < 0) { xo_warnx("memstat_sysctl_malloc: %s", @@ -1449,11 +1456,11 @@ (uintmax_t)memstat_get_numallocs(mtp)); first = 1; xo_open_list("size"); - for (i = 0; i < 32; i++) { + for (i = 0; i < zones; i++) { if (memstat_get_sizemask(mtp) & (1 << i)) { if (!first) xo_emit(","); - xo_emit("{l:size/%d}", 1 << (i + 4)); + xo_emit("{l:size/%d}", memstat_zone_get_size(i)); first = 0; } }