summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libmemstat/memstat.c21
-rw-r--r--lib/libmemstat/memstat.h16
-rw-r--r--lib/libmemstat/memstat_internal.h5
-rw-r--r--lib/libmemstat/memstat_malloc.c51
-rw-r--r--lib/libmemstat/memstat_uma.c51
5 files changed, 78 insertions, 66 deletions
diff --git a/lib/libmemstat/memstat.c b/lib/libmemstat/memstat.c
index 29dd19e..f053e95 100644
--- a/lib/libmemstat/memstat.c
+++ b/lib/libmemstat/memstat.c
@@ -47,7 +47,8 @@ memstat_mtl_alloc(void)
if (mtlp == NULL)
return (NULL);
- LIST_INIT(mtlp);
+ LIST_INIT(&mtlp->mtl_list);
+ mtlp->mtl_error = MEMSTAT_ERROR_UNDEFINED;
return (mtlp);
}
@@ -55,7 +56,7 @@ struct memory_type *
memstat_mtl_first(struct memory_type_list *list)
{
- return (LIST_FIRST(list));
+ return (LIST_FIRST(&list->mtl_list));
}
struct memory_type *
@@ -70,16 +71,24 @@ memstat_mtl_free(struct memory_type_list *list)
{
struct memory_type *mtp;
- while ((mtp = LIST_FIRST(list))) {
+ while ((mtp = LIST_FIRST(&list->mtl_list))) {
LIST_REMOVE(mtp, mt_list);
free(mtp);
}
free(list);
}
+int
+memstat_mtl_geterror(struct memory_type_list *list)
+{
+
+ return (list->mtl_error);
+}
+
/*
* Look for an existing memory_type entry in a memory_type list, based on the
- * allocator and name of the type. If not found, return NULL. O(n).
+ * allocator and name of the type. If not found, return NULL. No errno or
+ * memstat error.
*/
struct memory_type *
memstat_mtl_find(struct memory_type_list *list, int allocator,
@@ -87,7 +96,7 @@ memstat_mtl_find(struct memory_type_list *list, int allocator,
{
struct memory_type *mtp;
- LIST_FOREACH(mtp, list, mt_list) {
+ LIST_FOREACH(mtp, &list->mtl_list, mt_list) {
if ((mtp->mt_allocator == allocator ||
allocator == ALLOCATOR_ANY) &&
strcmp(mtp->mt_name, name) == 0)
@@ -116,7 +125,7 @@ _memstat_mt_allocate(struct memory_type_list *list, int allocator,
mtp->mt_allocator = allocator;
strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME);
- LIST_INSERT_HEAD(list, mtp, mt_list);
+ LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list);
return (mtp);
}
diff --git a/lib/libmemstat/memstat.h b/lib/libmemstat/memstat.h
index 823338b..c2e3174 100644
--- a/lib/libmemstat/memstat.h
+++ b/lib/libmemstat/memstat.h
@@ -61,6 +61,19 @@
#define MEMTYPE_MAXNAME 32
/*
+ * Library error conditions, mostly from the underlying data sources. On
+ * failure, functions typically return (-1) or (NULL); on success, (0) or a
+ * valid data pointer. The error from the last operation is stored in
+ * struct memory_type, and accessed via memstat_get_error(mtp).
+ */
+#define MEMSTAT_ERROR_UNDEFINED 0 /* Initialization value. */
+#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. */
+
+/*
* Forward declare struct memory_type, which holds per-type properties and
* statistics. This is an opaque type, to be frobbed only from within the
* library, in order to avoid building ABI assumptions into the application.
@@ -85,6 +98,7 @@ struct memory_type *memstat_mtl_next(struct memory_type *mtp);
struct memory_type *memstat_mtl_find(struct memory_type_list *list,
int allocator, const char *name);
void memstat_mtl_free(struct memory_type_list *list);
+int memstat_mtl_geterror(struct memory_type_list *list);
/*
* Functions to retrieve data from a live kernel using sysctl.
@@ -94,7 +108,7 @@ int memstat_sysctl_malloc(struct memory_type_list *list, int flags);
int memstat_sysctl_uma(struct memory_type_list *list, int flags);
/*
- * Accessor methods for struct memory_type_list.
+ * Accessor methods for struct memory_type.
*/
const char *memstat_get_name(const struct memory_type *mtp);
int memstat_get_allocator(const struct memory_type *mtp);
diff --git a/lib/libmemstat/memstat_internal.h b/lib/libmemstat/memstat_internal.h
index edbf562..838eaa6 100644
--- a/lib/libmemstat/memstat_internal.h
+++ b/lib/libmemstat/memstat_internal.h
@@ -111,7 +111,10 @@ struct memory_type {
/*
* Description of struct memory_type_list is in memstat.h.
*/
-LIST_HEAD(memory_type_list, memory_type);
+struct memory_type_list {
+ LIST_HEAD(, memory_type) mtl_list;
+ int mtl_error;
+};
struct memory_type *_memstat_mt_allocate(struct memory_type_list *list,
int allocator, const char *name);
diff --git a/lib/libmemstat/memstat_malloc.c b/lib/libmemstat/memstat_malloc.c
index 3aed1cf..4170812 100644
--- a/lib/libmemstat/memstat_malloc.c
+++ b/lib/libmemstat/memstat_malloc.c
@@ -58,11 +58,11 @@ memstat_sysctl_malloc(struct memory_type_list *list, int flags)
struct malloc_type_header *mthp;
struct malloc_type_stats *mtsp;
struct memory_type *mtp;
- int count, error, hint_dontsearch, i, j, maxcpus;
+ int count, hint_dontsearch, i, j, maxcpus;
char *buffer, *p;
size_t size;
- hint_dontsearch = LIST_EMPTY(list);
+ hint_dontsearch = LIST_EMPTY(&list->mtl_list);
/*
* Query the number of CPUs, number of malloc types so that we can
@@ -74,33 +74,32 @@ memstat_sysctl_malloc(struct memory_type_list *list, int flags)
retry:
size = sizeof(maxcpus);
if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
- error = errno;
- perror("kern.smp.maxcpus");
- errno = error;
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
return (-1);
}
if (size != sizeof(maxcpus)) {
- fprintf(stderr, "kern.smp.maxcpus: wrong size");
- errno = EINVAL;
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
return (-1);
}
if (maxcpus > MEMSTAT_MAXCPU) {
- fprintf(stderr, "kern.smp.maxcpus: too many CPUs\n");
- errno = EINVAL;
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
return (-1);
}
size = sizeof(count);
if (sysctlbyname("kern.malloc_count", &count, &size, NULL, 0) < 0) {
- error = errno;
- perror("kern.malloc_count");
- errno = error;
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
return (-1);
}
if (size != sizeof(count)) {
- fprintf(stderr, "kern.malloc_count: wrong size");
- errno = EINVAL;
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
return (-1);
}
@@ -109,9 +108,7 @@ retry:
buffer = malloc(size);
if (buffer == NULL) {
- error = errno;
- perror("malloc");
- errno = error;
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
return (-1);
}
@@ -124,10 +121,11 @@ retry:
free(buffer);
goto retry;
}
- error = errno;
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
free(buffer);
- perror("kern.malloc_stats");
- errno = error;
return (-1);
}
@@ -137,9 +135,8 @@ retry:
}
if (size < sizeof(*mtshp)) {
- fprintf(stderr, "sysctl_malloc: invalid malloc header");
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
free(buffer);
- errno = EINVAL;
return (-1);
}
p = buffer;
@@ -147,16 +144,14 @@ retry:
p += sizeof(*mtshp);
if (mtshp->mtsh_version != MALLOC_TYPE_STREAM_VERSION) {
- fprintf(stderr, "sysctl_malloc: unknown malloc version");
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
free(buffer);
- errno = EINVAL;
return (-1);
}
if (mtshp->mtsh_maxcpus > MEMSTAT_MAXCPU) {
- fprintf(stderr, "sysctl_malloc: too many CPUs");
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
free(buffer);
- errno = EINVAL;
return (-1);
}
@@ -182,9 +177,7 @@ retry:
if (mtp == NULL) {
memstat_mtl_free(list);
free(buffer);
- errno = ENOMEM;
- perror("malloc");
- errno = ENOMEM;
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
return (-1);
}
diff --git a/lib/libmemstat/memstat_uma.c b/lib/libmemstat/memstat_uma.c
index 49cc73a..b35c4d9 100644
--- a/lib/libmemstat/memstat_uma.c
+++ b/lib/libmemstat/memstat_uma.c
@@ -59,11 +59,11 @@ memstat_sysctl_uma(struct memory_type_list *list, int flags)
struct uma_type_header *uthp;
struct uma_percpu_stat *upsp;
struct memory_type *mtp;
- int count, error, hint_dontsearch, i, j, maxcpus;
+ int count, hint_dontsearch, i, j, maxcpus;
char *buffer, *p;
size_t size;
- hint_dontsearch = LIST_EMPTY(list);
+ hint_dontsearch = LIST_EMPTY(&list->mtl_list);
/*
* Query the number of CPUs, number of malloc types so that we can
@@ -75,33 +75,32 @@ memstat_sysctl_uma(struct memory_type_list *list, int flags)
retry:
size = sizeof(maxcpus);
if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
- error = errno;
- perror("kern.smp.maxcpus");
- errno = error;
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
return (-1);
}
if (size != sizeof(maxcpus)) {
- fprintf(stderr, "kern.smp.maxcpus: wrong size");
- errno = EINVAL;
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
return (-1);
}
if (maxcpus > MEMSTAT_MAXCPU) {
- fprintf(stderr, "kern.smp.maxcpus: too many CPUs\n");
- errno = EINVAL;
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
return (-1);
}
size = sizeof(count);
if (sysctlbyname("vm.zone_count", &count, &size, NULL, 0) < 0) {
- error = errno;
- perror("vm.zone_count");
- errno = error;
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
return (-1);
}
if (size != sizeof(count)) {
- fprintf(stderr, "vm.zone_count: wrong size");
- errno = EINVAL;
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
return (-1);
}
@@ -110,9 +109,7 @@ retry:
buffer = malloc(size);
if (buffer == NULL) {
- error = errno;
- perror("malloc");
- errno = error;
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
return (-1);
}
@@ -125,10 +122,11 @@ retry:
free(buffer);
goto retry;
}
- error = errno;
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
free(buffer);
- perror("vm.zone_stats");
- errno = error;
return (-1);
}
@@ -138,9 +136,8 @@ retry:
}
if (size < sizeof(*ushp)) {
- fprintf(stderr, "sysctl_uma: invalid malloc header");
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
free(buffer);
- errno = EINVAL;
return (-1);
}
p = buffer;
@@ -148,16 +145,14 @@ retry:
p += sizeof(*ushp);
if (ushp->ush_version != UMA_STREAM_VERSION) {
- fprintf(stderr, "sysctl_uma: unknown malloc version");
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
free(buffer);
- errno = EINVAL;
return (-1);
}
if (ushp->ush_maxcpus > MEMSTAT_MAXCPU) {
- fprintf(stderr, "sysctl_uma: too many CPUs");
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
free(buffer);
- errno = EINVAL;
return (-1);
}
@@ -183,9 +178,7 @@ retry:
if (mtp == NULL) {
memstat_mtl_free(list);
free(buffer);
- errno = ENOMEM;
- perror("malloc");
- errno = ENOMEM;
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
return (-1);
}
OpenPOWER on IntegriCloud