memstat.c revision 261726
1170530Ssam/*- 2178354Ssam * Copyright (c) 2005 Robert N. M. Watson 3170530Ssam * All rights reserved. 4170530Ssam * 5170530Ssam * Redistribution and use in source and binary forms, with or without 6170530Ssam * modification, are permitted provided that the following conditions 7170530Ssam * are met: 8170530Ssam * 1. Redistributions of source code must retain the above copyright 9170530Ssam * notice, this list of conditions and the following disclaimer. 10170530Ssam * 2. Redistributions in binary form must reproduce the above copyright 11170530Ssam * notice, this list of conditions and the following disclaimer in the 12170530Ssam * documentation and/or other materials provided with the distribution. 13170530Ssam * 14170530Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15170530Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16170530Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17170530Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18170530Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19170530Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20170530Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21170530Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22170530Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23170530Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24170530Ssam * SUCH DAMAGE. 25170530Ssam * 26170530Ssam * $FreeBSD: head/lib/libmemstat/memstat.c 261726 2014-02-10 20:09:10Z glebius $ 27170530Ssam */ 28170530Ssam 29170530Ssam#include <sys/param.h> 30170530Ssam#include <sys/sysctl.h> 31170530Ssam 32178354Ssam#include <err.h> 33178354Ssam#include <errno.h> 34170530Ssam#include <stdio.h> 35170530Ssam#include <stdlib.h> 36170530Ssam#include <string.h> 37170530Ssam 38170530Ssam#include "memstat.h" 39170530Ssam#include "memstat_internal.h" 40170530Ssam 41170530Ssamconst char * 42170530Ssammemstat_strerror(int error) 43170530Ssam{ 44170530Ssam 45170530Ssam switch (error) { 46170530Ssam case MEMSTAT_ERROR_NOMEMORY: 47170530Ssam return ("Cannot allocate memory"); 48178354Ssam case MEMSTAT_ERROR_VERSION: 49178354Ssam return ("Version mismatch"); 50170530Ssam case MEMSTAT_ERROR_PERMISSION: 51227293Sed return ("Permission denied"); 52178354Ssam case MEMSTAT_ERROR_DATAERROR: 53170530Ssam return ("Data format error"); 54170530Ssam case MEMSTAT_ERROR_KVM: 55170530Ssam return ("KVM error"); 56178354Ssam case MEMSTAT_ERROR_KVM_NOSYMBOL: 57178354Ssam return ("KVM unable to find symbol"); 58178354Ssam case MEMSTAT_ERROR_KVM_SHORTREAD: 59178354Ssam return ("KVM short read"); 60178354Ssam case MEMSTAT_ERROR_UNDEFINED: 61178354Ssam default: 62178354Ssam return ("Unknown error"); 63178354Ssam } 64178354Ssam} 65178354Ssam 66178354Ssamstruct memory_type_list * 67178354Ssammemstat_mtl_alloc(void) 68170530Ssam{ 69178354Ssam struct memory_type_list *mtlp; 70178354Ssam 71170530Ssam mtlp = malloc(sizeof(*mtlp)); 72241138Sadrian if (mtlp == NULL) 73241138Sadrian return (NULL); 74170530Ssam 75170530Ssam LIST_INIT(&mtlp->mtl_list); 76170530Ssam mtlp->mtl_error = MEMSTAT_ERROR_UNDEFINED; 77178354Ssam return (mtlp); 78170530Ssam} 79170530Ssam 80170530Ssamstruct memory_type * 81170530Ssammemstat_mtl_first(struct memory_type_list *list) 82170530Ssam{ 83178354Ssam 84178354Ssam return (LIST_FIRST(&list->mtl_list)); 85186302Ssam} 86178354Ssam 87178354Ssamstruct memory_type * 88170530Ssammemstat_mtl_next(struct memory_type *mtp) 89170530Ssam{ 90178354Ssam 91170530Ssam return (LIST_NEXT(mtp, mt_list)); 92170530Ssam} 93170530Ssam 94170530Ssamvoid 95170530Ssam_memstat_mtl_empty(struct memory_type_list *list) 96178354Ssam{ 97170530Ssam struct memory_type *mtp; 98178354Ssam 99186302Ssam while ((mtp = LIST_FIRST(&list->mtl_list))) { 100178354Ssam free(mtp->mt_percpu_alloc); 101170530Ssam free(mtp->mt_percpu_cache); 102170530Ssam LIST_REMOVE(mtp, mt_list); 103170530Ssam free(mtp); 104184288Ssam } 105184288Ssam} 106184288Ssam 107223842Skevlovoid 108184288Ssammemstat_mtl_free(struct memory_type_list *list) 109184288Ssam{ 110184288Ssam 111184288Ssam _memstat_mtl_empty(list); 112184288Ssam free(list); 113184288Ssam} 114184288Ssam 115184288Ssamint 116184288Ssammemstat_mtl_geterror(struct memory_type_list *list) 117184288Ssam{ 118184288Ssam 119184288Ssam return (list->mtl_error); 120184288Ssam} 121184288Ssam 122184288Ssam/* 123170530Ssam * Look for an existing memory_type entry in a memory_type list, based on the 124184288Ssam * allocator and name of the type. If not found, return NULL. No errno or 125184288Ssam * memstat error. 126184288Ssam */ 127184288Ssamstruct memory_type * 128184288Ssammemstat_mtl_find(struct memory_type_list *list, int allocator, 129184288Ssam const char *name) 130184288Ssam{ 131184288Ssam struct memory_type *mtp; 132184288Ssam 133184288Ssam LIST_FOREACH(mtp, &list->mtl_list, mt_list) { 134184288Ssam if ((mtp->mt_allocator == allocator || 135184288Ssam allocator == ALLOCATOR_ANY) && 136184288Ssam strcmp(mtp->mt_name, name) == 0) 137184288Ssam return (mtp); 138184288Ssam } 139184288Ssam return (NULL); 140184288Ssam} 141184288Ssam 142184288Ssam/* 143184288Ssam * Allocate a new memory_type with the specificed allocator type and name, 144184288Ssam * then insert into the list. The structure will be zero'd. 145184288Ssam * 146184288Ssam * libmemstat(3) internal function. 147184288Ssam */ 148184288Ssamstruct memory_type * 149184288Ssam_memstat_mt_allocate(struct memory_type_list *list, int allocator, 150184288Ssam const char *name, int maxcpus) 151184288Ssam{ 152184288Ssam struct memory_type *mtp; 153184288Ssam 154184288Ssam mtp = malloc(sizeof(*mtp)); 155184288Ssam if (mtp == NULL) 156184288Ssam return (NULL); 157184288Ssam 158184288Ssam bzero(mtp, sizeof(*mtp)); 159184288Ssam 160184288Ssam mtp->mt_allocator = allocator; 161184288Ssam mtp->mt_percpu_alloc = malloc(sizeof(struct mt_percpu_alloc_s) * 162184288Ssam maxcpus); 163184288Ssam mtp->mt_percpu_cache = malloc(sizeof(struct mt_percpu_cache_s) * 164184288Ssam maxcpus); 165184288Ssam strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME); 166184288Ssam LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list); 167184288Ssam return (mtp); 168184288Ssam} 169184288Ssam 170184288Ssam/* 171184288Ssam * Reset any libmemstat(3)-owned statistics in a memory_type record so that 172184288Ssam * it can be reused without incremental addition problems. Caller-owned 173170530Ssam * memory is left "as-is", and must be updated by the caller if desired. 174170530Ssam * 175184288Ssam * libmemstat(3) internal function. 176184288Ssam */ 177170530Ssamvoid 178184288Ssam_memstat_mt_reset_stats(struct memory_type *mtp, int maxcpus) 179184288Ssam{ 180170530Ssam int i; 181170530Ssam 182184288Ssam mtp->mt_countlimit = 0; 183184288Ssam mtp->mt_byteslimit = 0; 184184288Ssam mtp->mt_sizemask = 0; 185184288Ssam mtp->mt_size = 0; 186184288Ssam 187184288Ssam mtp->mt_memalloced = 0; 188184288Ssam mtp->mt_memfreed = 0; 189184288Ssam mtp->mt_numallocs = 0; 190184288Ssam mtp->mt_numfrees = 0; 191184288Ssam mtp->mt_bytes = 0; 192184288Ssam mtp->mt_count = 0; 193184288Ssam mtp->mt_free = 0; 194184288Ssam mtp->mt_failures = 0; 195184288Ssam mtp->mt_sleeps = 0; 196184288Ssam 197184288Ssam mtp->mt_zonefree = 0; 198170530Ssam mtp->mt_kegfree = 0; 199170530Ssam 200170530Ssam for (i = 0; i < maxcpus; i++) { 201170530Ssam mtp->mt_percpu_alloc[i].mtp_memalloced = 0; 202170530Ssam mtp->mt_percpu_alloc[i].mtp_memfreed = 0; 203184288Ssam mtp->mt_percpu_alloc[i].mtp_numallocs = 0; 204184288Ssam mtp->mt_percpu_alloc[i].mtp_numfrees = 0; 205184288Ssam mtp->mt_percpu_alloc[i].mtp_sizemask = 0; 206184288Ssam mtp->mt_percpu_cache[i].mtp_free = 0; 207184288Ssam } 208184288Ssam} 209184288Ssam 210184288Ssam/* 211184288Ssam * Accessor methods for struct memory_type. Avoids encoding the structure 212184288Ssam * ABI into the application. 213170530Ssam */ 214170530Ssamconst char * 215170530Ssammemstat_get_name(const struct memory_type *mtp) 216170530Ssam{ 217170530Ssam 218170530Ssam return (mtp->mt_name); 219170530Ssam} 220170530Ssam 221170530Ssamint 222170530Ssammemstat_get_allocator(const struct memory_type *mtp) 223184288Ssam{ 224170530Ssam 225184288Ssam return (mtp->mt_allocator); 226170530Ssam} 227170530Ssam 228184288Ssamuint64_t 229178354Ssammemstat_get_countlimit(const struct memory_type *mtp) 230178354Ssam{ 231178354Ssam 232184288Ssam return (mtp->mt_countlimit); 233170530Ssam} 234170530Ssam 235184288Ssamuint64_t 236184288Ssammemstat_get_byteslimit(const struct memory_type *mtp) 237184288Ssam{ 238184288Ssam 239184288Ssam return (mtp->mt_byteslimit); 240178354Ssam} 241178354Ssam 242184288Ssamuint64_t 243184288Ssammemstat_get_sizemask(const struct memory_type *mtp) 244184288Ssam{ 245184288Ssam 246184288Ssam return (mtp->mt_sizemask); 247184288Ssam} 248184288Ssam 249170530Ssamuint64_t 250170530Ssammemstat_get_size(const struct memory_type *mtp) 251184288Ssam{ 252184288Ssam 253184288Ssam return (mtp->mt_size); 254184288Ssam} 255170530Ssam 256170530Ssamuint64_t 257184288Ssammemstat_get_rsize(const struct memory_type *mtp) 258170530Ssam{ 259178354Ssam 260170530Ssam return (mtp->mt_rsize); 261170530Ssam} 262170530Ssam 263170530Ssamuint64_t 264170530Ssammemstat_get_memalloced(const struct memory_type *mtp) 265170530Ssam{ 266170530Ssam 267178354Ssam return (mtp->mt_memalloced); 268178354Ssam} 269178354Ssam 270178354Ssamuint64_t 271178354Ssammemstat_get_memfreed(const struct memory_type *mtp) 272178354Ssam{ 273178354Ssam 274178354Ssam return (mtp->mt_memfreed); 275178354Ssam} 276178354Ssam 277178354Ssamuint64_t 278178354Ssammemstat_get_numallocs(const struct memory_type *mtp) 279170530Ssam{ 280170530Ssam 281178354Ssam return (mtp->mt_numallocs); 282170530Ssam} 283170530Ssam 284178354Ssamuint64_t 285170530Ssammemstat_get_numfrees(const struct memory_type *mtp) 286170530Ssam{ 287178354Ssam 288170530Ssam return (mtp->mt_numfrees); 289178354Ssam} 290178354Ssam 291178354Ssamuint64_t 292170530Ssammemstat_get_bytes(const struct memory_type *mtp) 293170530Ssam{ 294178354Ssam 295178354Ssam return (mtp->mt_bytes); 296170530Ssam} 297178354Ssam 298178354Ssamuint64_t 299178354Ssammemstat_get_count(const struct memory_type *mtp) 300170530Ssam{ 301178354Ssam 302178354Ssam return (mtp->mt_count); 303170530Ssam} 304178354Ssam 305178354Ssamuint64_t 306170530Ssammemstat_get_free(const struct memory_type *mtp) 307178354Ssam{ 308178354Ssam 309170530Ssam return (mtp->mt_free); 310178354Ssam} 311178354Ssam 312178354Ssamuint64_t 313170530Ssammemstat_get_failures(const struct memory_type *mtp) 314170530Ssam{ 315170530Ssam 316170530Ssam return (mtp->mt_failures); 317170530Ssam} 318170530Ssam 319170530Ssamuint64_t 320184288Ssammemstat_get_sleeps(const struct memory_type *mtp) 321170530Ssam{ 322170530Ssam 323184288Ssam return (mtp->mt_sleeps); 324178354Ssam} 325170530Ssam 326184288Ssamvoid * 327170530Ssammemstat_get_caller_pointer(const struct memory_type *mtp, int index) 328170530Ssam{ 329184288Ssam 330184288Ssam return (mtp->mt_caller_pointer[index]); 331184288Ssam} 332184288Ssam 333178354Ssamvoid 334178354Ssammemstat_set_caller_pointer(struct memory_type *mtp, int index, void *value) 335184288Ssam{ 336170530Ssam 337178354Ssam mtp->mt_caller_pointer[index] = value; 338178354Ssam} 339178354Ssam 340170530Ssamuint64_t 341184288Ssammemstat_get_caller_uint64(const struct memory_type *mtp, int index) 342184288Ssam{ 343170530Ssam 344170530Ssam return (mtp->mt_caller_uint64[index]); 345184288Ssam} 346184288Ssam 347184288Ssamvoid 348184288Ssammemstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value) 349184288Ssam{ 350170530Ssam 351170530Ssam mtp->mt_caller_uint64[index] = value; 352170530Ssam} 353184288Ssam 354184288Ssamuint64_t 355184288Ssammemstat_get_zonefree(const struct memory_type *mtp) 356184288Ssam{ 357184288Ssam 358184288Ssam return (mtp->mt_zonefree); 359184288Ssam} 360184288Ssam 361184288Ssamuint64_t 362184288Ssammemstat_get_kegfree(const struct memory_type *mtp) 363184288Ssam{ 364184288Ssam 365170530Ssam return (mtp->mt_kegfree); 366184288Ssam} 367184288Ssam 368184288Ssamuint64_t 369184288Ssammemstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu) 370184288Ssam{ 371184288Ssam 372184288Ssam return (mtp->mt_percpu_alloc[cpu].mtp_memalloced); 373184288Ssam} 374184288Ssam 375184288Ssamuint64_t 376184288Ssammemstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu) 377184288Ssam{ 378184288Ssam 379184288Ssam return (mtp->mt_percpu_alloc[cpu].mtp_memfreed); 380184288Ssam} 381184288Ssam 382184288Ssamuint64_t 383184288Ssammemstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu) 384184288Ssam{ 385184288Ssam 386184288Ssam return (mtp->mt_percpu_alloc[cpu].mtp_numallocs); 387184288Ssam} 388184288Ssam 389184288Ssamuint64_t 390184288Ssammemstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu) 391184288Ssam{ 392184288Ssam 393184288Ssam return (mtp->mt_percpu_alloc[cpu].mtp_numfrees); 394184288Ssam} 395184288Ssam 396184288Ssamuint64_t 397178354Ssammemstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu) 398178354Ssam{ 399170530Ssam 400178354Ssam return (mtp->mt_percpu_alloc[cpu].mtp_sizemask); 401178354Ssam} 402184288Ssam 403184288Ssamvoid * 404170530Ssammemstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu, 405170530Ssam int index) 406170530Ssam{ 407184288Ssam 408184288Ssam return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]); 409184288Ssam} 410184288Ssam 411170530Ssamvoid 412178354Ssammemstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu, 413178354Ssam int index, void *value) 414170530Ssam{ 415184288Ssam 416248069Sadrian mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value; 417184288Ssam} 418184288Ssam 419184288Ssamuint64_t 420245464Sadrianmemstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu, 421245464Sadrian int index) 422170530Ssam{ 423184288Ssam 424184288Ssam return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]); 425184288Ssam} 426184288Ssam 427184288Ssamvoid 428184288Ssammemstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index, 429184288Ssam uint64_t value) 430184288Ssam{ 431170530Ssam 432178354Ssam mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value; 433245464Sadrian} 434184288Ssam 435184288Ssamuint64_t 436184288Ssammemstat_get_percpu_free(const struct memory_type *mtp, int cpu) 437184288Ssam{ 438184288Ssam 439184288Ssam return (mtp->mt_percpu_cache[cpu].mtp_free); 440184288Ssam} 441184288Ssam