summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2020-11-02 17:38:08 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2020-11-02 17:38:08 +0000
commit828afdda17cae119594b21cac689bbe681b5aa58 (patch)
treea135e30ccd5f0290c88ce4b2da6eead7f604b4d8 /lib
parent26c29e743bbdbb82762540f72d4bc449bae2e092 (diff)
downloadsrc-test2-828afdda17cae119594b21cac689bbe681b5aa58.tar.gz
src-test2-828afdda17cae119594b21cac689bbe681b5aa58.zip
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/libmemstat/memstat.h7
-rw-r--r--lib/libmemstat/memstat_malloc.c131
2 files changed, 137 insertions, 1 deletions
diff --git a/lib/libmemstat/memstat.h b/lib/libmemstat/memstat.h
index 27f1405fa8f9..f57b7fbc96a4 100644
--- a/lib/libmemstat/memstat.h
+++ b/lib/libmemstat/memstat.h
@@ -118,6 +118,13 @@ 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_malloc_zone_get_count(void);
+size_t memstat_malloc_zone_get_size(size_t n);
+int memstat_malloc_zone_used(const struct memory_type *mtp, size_t n);
+
+/*
* Accessor methods for struct memory_type.
*/
const char *memstat_get_name(const struct memory_type *mtp);
diff --git a/lib/libmemstat/memstat_malloc.c b/lib/libmemstat/memstat_malloc.c
index 9094ee123137..63e72105ef7a 100644
--- a/lib/libmemstat/memstat_malloc.c
+++ b/lib/libmemstat/memstat_malloc.c
@@ -44,10 +44,22 @@
#include "memstat.h"
#include "memstat_internal.h"
+static int memstat_malloc_zone_count;
+static int memstat_malloc_zone_sizes[32];
+
+static int memstat_malloc_zone_init(void);
+static int memstat_malloc_zone_init_kvm(kvm_t *kvm);
+
static struct nlist namelist[] = {
#define X_KMEMSTATISTICS 0
{ .n_name = "_kmemstatistics" },
-#define X_MP_MAXCPUS 1
+#define X_KMEMZONES 1
+ { .n_name = "_kmemzones" },
+#define X_NUMZONES 2
+ { .n_name = "_numzones" },
+#define X_VM_MALLOC_ZONE_COUNT 3
+ { .n_name = "_vm_malloc_zone_count" },
+#define X_MP_MAXCPUS 4
{ .n_name = "_mp_maxcpus" },
{ .n_name = "" },
};
@@ -111,6 +123,11 @@ retry:
return (-1);
}
+ if (memstat_malloc_zone_init() == -1) {
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ return (-1);
+ }
+
size = sizeof(*mthp) + count * (sizeof(*mthp) + sizeof(*mtsp) *
maxcpus);
@@ -333,6 +350,12 @@ memstat_kvm_malloc(struct memory_type_list *list, void *kvm_handle)
return (-1);
}
+ ret = memstat_malloc_zone_init_kvm(kvm);
+ if (ret != 0) {
+ list->mtl_error = ret;
+ return (-1);
+ }
+
mp_ncpus = kvm_getncpus(kvm);
for (typep = kmemstatistics; typep != NULL; typep = type.ks_next) {
@@ -416,3 +439,109 @@ memstat_kvm_malloc(struct memory_type_list *list, void *kvm_handle)
return (0);
}
+
+static int
+memstat_malloc_zone_init(void)
+{
+ size_t size;
+
+ size = sizeof(memstat_malloc_zone_count);
+ if (sysctlbyname("vm.malloc.zone_count", &memstat_malloc_zone_count,
+ &size, NULL, 0) < 0) {
+ return (-1);
+ }
+
+ if (memstat_malloc_zone_count > (int)nitems(memstat_malloc_zone_sizes)) {
+ return (-1);
+ }
+
+ size = sizeof(memstat_malloc_zone_sizes);
+ if (sysctlbyname("vm.malloc.zone_sizes", &memstat_malloc_zone_sizes,
+ &size, NULL, 0) < 0) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Copied from kern_malloc.c
+ *
+ * kz_zone is an array sized at compilation time, the size is exported in
+ * "numzones". Below we need to iterate kz_size.
+ */
+struct memstat_kmemzone {
+ int kz_size;
+ const char *kz_name;
+ void *kz_zone[1];
+};
+
+static int
+memstat_malloc_zone_init_kvm(kvm_t *kvm)
+{
+ struct memstat_kmemzone *kmemzones, *kz;
+ int numzones, objsize, allocsize, ret;
+ int i;
+
+ ret = kread_symbol(kvm, X_VM_MALLOC_ZONE_COUNT,
+ &memstat_malloc_zone_count, sizeof(memstat_malloc_zone_count), 0);
+ if (ret != 0) {
+ return (ret);
+ }
+
+ ret = kread_symbol(kvm, X_NUMZONES, &numzones, sizeof(numzones), 0);
+ if (ret != 0) {
+ return (ret);
+ }
+
+ objsize = __offsetof(struct memstat_kmemzone, kz_zone) +
+ sizeof(void *) * numzones;
+
+ allocsize = objsize * memstat_malloc_zone_count;
+ kmemzones = malloc(allocsize);
+ if (kmemzones == NULL) {
+ return (MEMSTAT_ERROR_NOMEMORY);
+ }
+ ret = kread_symbol(kvm, X_KMEMZONES, kmemzones, allocsize, 0);
+ if (ret != 0) {
+ free(kmemzones);
+ return (ret);
+ }
+
+ kz = kmemzones;
+ for (i = 0; i < (int)nitems(memstat_malloc_zone_sizes); i++) {
+ memstat_malloc_zone_sizes[i] = kz->kz_size;
+ kz = (struct memstat_kmemzone *)((char *)kz + objsize);
+ }
+
+ free(kmemzones);
+ return (0);
+}
+
+size_t
+memstat_malloc_zone_get_count(void)
+{
+
+ return (memstat_malloc_zone_count);
+}
+
+size_t
+memstat_malloc_zone_get_size(size_t n)
+{
+
+ if (n >= nitems(memstat_malloc_zone_sizes)) {
+ return (-1);
+ }
+
+ return (memstat_malloc_zone_sizes[n]);
+}
+
+int
+memstat_malloc_zone_used(const struct memory_type *mtp, size_t n)
+{
+
+ if (memstat_get_sizemask(mtp) & (1 << n))
+ return (1);
+
+ return (0);
+}