diff options
-rw-r--r-- | lib/libmemstat/memstat.c | 21 | ||||
-rw-r--r-- | lib/libmemstat/memstat.h | 16 | ||||
-rw-r--r-- | lib/libmemstat/memstat_internal.h | 5 | ||||
-rw-r--r-- | lib/libmemstat/memstat_malloc.c | 51 | ||||
-rw-r--r-- | lib/libmemstat/memstat_uma.c | 51 |
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); } |