1147997Srwatson/*- 2147997Srwatson * Copyright (c) 2005 Robert N. M. Watson 3147997Srwatson * All rights reserved. 4147997Srwatson * 5147997Srwatson * Redistribution and use in source and binary forms, with or without 6147997Srwatson * modification, are permitted provided that the following conditions 7147997Srwatson * are met: 8147997Srwatson * 1. Redistributions of source code must retain the above copyright 9147997Srwatson * notice, this list of conditions and the following disclaimer. 10147997Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11147997Srwatson * notice, this list of conditions and the following disclaimer in the 12147997Srwatson * documentation and/or other materials provided with the distribution. 13147997Srwatson * 14147997Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15147997Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16147997Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17147997Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18147997Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19147997Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20147997Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21147997Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22147997Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23147997Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24147997Srwatson * SUCH DAMAGE. 25147997Srwatson * 26147997Srwatson * $FreeBSD$ 27147997Srwatson */ 28147997Srwatson 29147997Srwatson#include <sys/param.h> 30147997Srwatson#include <sys/sysctl.h> 31147997Srwatson 32147997Srwatson#include <err.h> 33147997Srwatson#include <errno.h> 34147997Srwatson#include <stdio.h> 35147997Srwatson#include <stdlib.h> 36147997Srwatson#include <string.h> 37147997Srwatson 38147997Srwatson#include "memstat.h" 39147997Srwatson#include "memstat_internal.h" 40147997Srwatson 41148359Srwatsonconst char * 42148359Srwatsonmemstat_strerror(int error) 43148359Srwatson{ 44148359Srwatson 45148359Srwatson switch (error) { 46148359Srwatson case MEMSTAT_ERROR_NOMEMORY: 47148359Srwatson return ("Cannot allocate memory"); 48148359Srwatson case MEMSTAT_ERROR_VERSION: 49148359Srwatson return ("Version mismatch"); 50148359Srwatson case MEMSTAT_ERROR_PERMISSION: 51148359Srwatson return ("Permission denied"); 52148359Srwatson case MEMSTAT_ERROR_DATAERROR: 53148359Srwatson return ("Data format error"); 54148627Srwatson case MEMSTAT_ERROR_KVM: 55148627Srwatson return ("KVM error"); 56148627Srwatson case MEMSTAT_ERROR_KVM_NOSYMBOL: 57148627Srwatson return ("KVM unable to find symbol"); 58148627Srwatson case MEMSTAT_ERROR_KVM_SHORTREAD: 59148627Srwatson return ("KVM short read"); 60148359Srwatson case MEMSTAT_ERROR_UNDEFINED: 61148359Srwatson default: 62148359Srwatson return ("Unknown error"); 63148359Srwatson } 64148359Srwatson} 65148359Srwatson 66147997Srwatsonstruct memory_type_list * 67147997Srwatsonmemstat_mtl_alloc(void) 68147997Srwatson{ 69147997Srwatson struct memory_type_list *mtlp; 70147997Srwatson 71147997Srwatson mtlp = malloc(sizeof(*mtlp)); 72147997Srwatson if (mtlp == NULL) 73147997Srwatson return (NULL); 74147997Srwatson 75148357Srwatson LIST_INIT(&mtlp->mtl_list); 76148357Srwatson mtlp->mtl_error = MEMSTAT_ERROR_UNDEFINED; 77147997Srwatson return (mtlp); 78147997Srwatson} 79147997Srwatson 80147997Srwatsonstruct memory_type * 81147997Srwatsonmemstat_mtl_first(struct memory_type_list *list) 82147997Srwatson{ 83147997Srwatson 84148357Srwatson return (LIST_FIRST(&list->mtl_list)); 85147997Srwatson} 86147997Srwatson 87147997Srwatsonstruct memory_type * 88147997Srwatsonmemstat_mtl_next(struct memory_type *mtp) 89147997Srwatson{ 90147997Srwatson 91147997Srwatson return (LIST_NEXT(mtp, mt_list)); 92147997Srwatson} 93147997Srwatson 94147997Srwatsonvoid 95148619Srwatson_memstat_mtl_empty(struct memory_type_list *list) 96147997Srwatson{ 97147997Srwatson struct memory_type *mtp; 98147997Srwatson 99148357Srwatson while ((mtp = LIST_FIRST(&list->mtl_list))) { 100224569Spluknet free(mtp->mt_percpu_alloc); 101224569Spluknet free(mtp->mt_percpu_cache); 102147997Srwatson LIST_REMOVE(mtp, mt_list); 103147997Srwatson free(mtp); 104147997Srwatson } 105148619Srwatson} 106148619Srwatson 107148619Srwatsonvoid 108148619Srwatsonmemstat_mtl_free(struct memory_type_list *list) 109148619Srwatson{ 110148619Srwatson 111148619Srwatson _memstat_mtl_empty(list); 112147997Srwatson free(list); 113147997Srwatson} 114147997Srwatson 115148357Srwatsonint 116148357Srwatsonmemstat_mtl_geterror(struct memory_type_list *list) 117148357Srwatson{ 118148357Srwatson 119148357Srwatson return (list->mtl_error); 120148357Srwatson} 121148357Srwatson 122147997Srwatson/* 123147997Srwatson * Look for an existing memory_type entry in a memory_type list, based on the 124148357Srwatson * allocator and name of the type. If not found, return NULL. No errno or 125148357Srwatson * memstat error. 126147997Srwatson */ 127147997Srwatsonstruct memory_type * 128147997Srwatsonmemstat_mtl_find(struct memory_type_list *list, int allocator, 129147997Srwatson const char *name) 130147997Srwatson{ 131147997Srwatson struct memory_type *mtp; 132147997Srwatson 133148357Srwatson LIST_FOREACH(mtp, &list->mtl_list, mt_list) { 134147997Srwatson if ((mtp->mt_allocator == allocator || 135147997Srwatson allocator == ALLOCATOR_ANY) && 136147997Srwatson strcmp(mtp->mt_name, name) == 0) 137147997Srwatson return (mtp); 138147997Srwatson } 139147997Srwatson return (NULL); 140147997Srwatson} 141147997Srwatson 142147997Srwatson/* 143147997Srwatson * Allocate a new memory_type with the specificed allocator type and name, 144147997Srwatson * then insert into the list. The structure will be zero'd. 145148354Srwatson * 146148354Srwatson * libmemstat(3) internal function. 147147997Srwatson */ 148147997Srwatsonstruct memory_type * 149148354Srwatson_memstat_mt_allocate(struct memory_type_list *list, int allocator, 150224569Spluknet const char *name, int maxcpus) 151147997Srwatson{ 152147997Srwatson struct memory_type *mtp; 153147997Srwatson 154147997Srwatson mtp = malloc(sizeof(*mtp)); 155147997Srwatson if (mtp == NULL) 156147997Srwatson return (NULL); 157147997Srwatson 158147997Srwatson bzero(mtp, sizeof(*mtp)); 159147997Srwatson 160147997Srwatson mtp->mt_allocator = allocator; 161224569Spluknet mtp->mt_percpu_alloc = malloc(sizeof(struct mt_percpu_alloc_s) * 162224569Spluknet maxcpus); 163224569Spluknet mtp->mt_percpu_cache = malloc(sizeof(struct mt_percpu_cache_s) * 164224569Spluknet maxcpus); 165147997Srwatson strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME); 166148357Srwatson LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list); 167147997Srwatson return (mtp); 168147997Srwatson} 169147997Srwatson 170147997Srwatson/* 171147997Srwatson * Reset any libmemstat(3)-owned statistics in a memory_type record so that 172147997Srwatson * it can be reused without incremental addition problems. Caller-owned 173147997Srwatson * memory is left "as-is", and must be updated by the caller if desired. 174148354Srwatson * 175148354Srwatson * libmemstat(3) internal function. 176147997Srwatson */ 177147997Srwatsonvoid 178224569Spluknet_memstat_mt_reset_stats(struct memory_type *mtp, int maxcpus) 179147997Srwatson{ 180147997Srwatson int i; 181147997Srwatson 182147997Srwatson mtp->mt_countlimit = 0; 183147997Srwatson mtp->mt_byteslimit = 0; 184147997Srwatson mtp->mt_sizemask = 0; 185147997Srwatson mtp->mt_size = 0; 186147997Srwatson 187147997Srwatson mtp->mt_memalloced = 0; 188147997Srwatson mtp->mt_memfreed = 0; 189147997Srwatson mtp->mt_numallocs = 0; 190147997Srwatson mtp->mt_numfrees = 0; 191147997Srwatson mtp->mt_bytes = 0; 192147997Srwatson mtp->mt_count = 0; 193147997Srwatson mtp->mt_free = 0; 194147997Srwatson mtp->mt_failures = 0; 195209215Ssbruno mtp->mt_sleeps = 0; 196147997Srwatson 197147997Srwatson mtp->mt_zonefree = 0; 198148170Srwatson mtp->mt_kegfree = 0; 199147997Srwatson 200224569Spluknet for (i = 0; i < maxcpus; i++) { 201147997Srwatson mtp->mt_percpu_alloc[i].mtp_memalloced = 0; 202147997Srwatson mtp->mt_percpu_alloc[i].mtp_memfreed = 0; 203147997Srwatson mtp->mt_percpu_alloc[i].mtp_numallocs = 0; 204147997Srwatson mtp->mt_percpu_alloc[i].mtp_numfrees = 0; 205147997Srwatson mtp->mt_percpu_alloc[i].mtp_sizemask = 0; 206147997Srwatson mtp->mt_percpu_cache[i].mtp_free = 0; 207147997Srwatson } 208147997Srwatson} 209147997Srwatson 210147997Srwatson/* 211147997Srwatson * Accessor methods for struct memory_type. Avoids encoding the structure 212147997Srwatson * ABI into the application. 213147997Srwatson */ 214147997Srwatsonconst char * 215147997Srwatsonmemstat_get_name(const struct memory_type *mtp) 216147997Srwatson{ 217147997Srwatson 218147997Srwatson return (mtp->mt_name); 219147997Srwatson} 220147997Srwatson 221147997Srwatsonint 222147997Srwatsonmemstat_get_allocator(const struct memory_type *mtp) 223147997Srwatson{ 224147997Srwatson 225147997Srwatson return (mtp->mt_allocator); 226147997Srwatson} 227147997Srwatson 228147997Srwatsonuint64_t 229147997Srwatsonmemstat_get_countlimit(const struct memory_type *mtp) 230147997Srwatson{ 231147997Srwatson 232147997Srwatson return (mtp->mt_countlimit); 233147997Srwatson} 234147997Srwatson 235147997Srwatsonuint64_t 236147997Srwatsonmemstat_get_byteslimit(const struct memory_type *mtp) 237147997Srwatson{ 238147997Srwatson 239147997Srwatson return (mtp->mt_byteslimit); 240147997Srwatson} 241147997Srwatson 242147997Srwatsonuint64_t 243147997Srwatsonmemstat_get_sizemask(const struct memory_type *mtp) 244147997Srwatson{ 245147997Srwatson 246147997Srwatson return (mtp->mt_sizemask); 247147997Srwatson} 248147997Srwatson 249147997Srwatsonuint64_t 250147997Srwatsonmemstat_get_size(const struct memory_type *mtp) 251147997Srwatson{ 252147997Srwatson 253147997Srwatson return (mtp->mt_size); 254147997Srwatson} 255147997Srwatson 256147997Srwatsonuint64_t 257147997Srwatsonmemstat_get_memalloced(const struct memory_type *mtp) 258147997Srwatson{ 259147997Srwatson 260147997Srwatson return (mtp->mt_memalloced); 261147997Srwatson} 262147997Srwatson 263147997Srwatsonuint64_t 264147997Srwatsonmemstat_get_memfreed(const struct memory_type *mtp) 265147997Srwatson{ 266147997Srwatson 267147997Srwatson return (mtp->mt_memfreed); 268147997Srwatson} 269147997Srwatson 270147997Srwatsonuint64_t 271147997Srwatsonmemstat_get_numallocs(const struct memory_type *mtp) 272147997Srwatson{ 273147997Srwatson 274147997Srwatson return (mtp->mt_numallocs); 275147997Srwatson} 276147997Srwatson 277147997Srwatsonuint64_t 278147997Srwatsonmemstat_get_numfrees(const struct memory_type *mtp) 279147997Srwatson{ 280147997Srwatson 281147997Srwatson return (mtp->mt_numfrees); 282147997Srwatson} 283147997Srwatson 284147997Srwatsonuint64_t 285147997Srwatsonmemstat_get_bytes(const struct memory_type *mtp) 286147997Srwatson{ 287147997Srwatson 288147997Srwatson return (mtp->mt_bytes); 289147997Srwatson} 290147997Srwatson 291147997Srwatsonuint64_t 292147997Srwatsonmemstat_get_count(const struct memory_type *mtp) 293147997Srwatson{ 294147997Srwatson 295147997Srwatson return (mtp->mt_count); 296147997Srwatson} 297147997Srwatson 298147997Srwatsonuint64_t 299147997Srwatsonmemstat_get_free(const struct memory_type *mtp) 300147997Srwatson{ 301147997Srwatson 302147997Srwatson return (mtp->mt_free); 303147997Srwatson} 304147997Srwatson 305147997Srwatsonuint64_t 306147997Srwatsonmemstat_get_failures(const struct memory_type *mtp) 307147997Srwatson{ 308147997Srwatson 309147997Srwatson return (mtp->mt_failures); 310147997Srwatson} 311147997Srwatson 312209215Ssbrunouint64_t 313209215Ssbrunomemstat_get_sleeps(const struct memory_type *mtp) 314209215Ssbruno{ 315209215Ssbruno 316209215Ssbruno return (mtp->mt_sleeps); 317209215Ssbruno} 318209215Ssbruno 319147997Srwatsonvoid * 320147997Srwatsonmemstat_get_caller_pointer(const struct memory_type *mtp, int index) 321147997Srwatson{ 322147997Srwatson 323147997Srwatson return (mtp->mt_caller_pointer[index]); 324147997Srwatson} 325147997Srwatson 326147997Srwatsonvoid 327147997Srwatsonmemstat_set_caller_pointer(struct memory_type *mtp, int index, void *value) 328147997Srwatson{ 329147997Srwatson 330147997Srwatson mtp->mt_caller_pointer[index] = value; 331147997Srwatson} 332147997Srwatson 333147997Srwatsonuint64_t 334147997Srwatsonmemstat_get_caller_uint64(const struct memory_type *mtp, int index) 335147997Srwatson{ 336147997Srwatson 337147997Srwatson return (mtp->mt_caller_uint64[index]); 338147997Srwatson} 339147997Srwatson 340147997Srwatsonvoid 341147997Srwatsonmemstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value) 342147997Srwatson{ 343147997Srwatson 344147997Srwatson mtp->mt_caller_uint64[index] = value; 345147997Srwatson} 346147997Srwatson 347147997Srwatsonuint64_t 348147997Srwatsonmemstat_get_zonefree(const struct memory_type *mtp) 349147997Srwatson{ 350147997Srwatson 351147997Srwatson return (mtp->mt_zonefree); 352147997Srwatson} 353147997Srwatson 354147997Srwatsonuint64_t 355148170Srwatsonmemstat_get_kegfree(const struct memory_type *mtp) 356148170Srwatson{ 357148170Srwatson 358148170Srwatson return (mtp->mt_kegfree); 359148170Srwatson} 360148170Srwatson 361148170Srwatsonuint64_t 362147997Srwatsonmemstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu) 363147997Srwatson{ 364147997Srwatson 365147997Srwatson return (mtp->mt_percpu_alloc[cpu].mtp_memalloced); 366147997Srwatson} 367147997Srwatson 368147997Srwatsonuint64_t 369147997Srwatsonmemstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu) 370147997Srwatson{ 371147997Srwatson 372147997Srwatson return (mtp->mt_percpu_alloc[cpu].mtp_memfreed); 373147997Srwatson} 374147997Srwatson 375147997Srwatsonuint64_t 376147997Srwatsonmemstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu) 377147997Srwatson{ 378147997Srwatson 379147997Srwatson return (mtp->mt_percpu_alloc[cpu].mtp_numallocs); 380147997Srwatson} 381147997Srwatson 382147997Srwatsonuint64_t 383147997Srwatsonmemstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu) 384147997Srwatson{ 385147997Srwatson 386147997Srwatson return (mtp->mt_percpu_alloc[cpu].mtp_numfrees); 387147997Srwatson} 388147997Srwatson 389147997Srwatsonuint64_t 390147997Srwatsonmemstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu) 391147997Srwatson{ 392147997Srwatson 393147997Srwatson return (mtp->mt_percpu_alloc[cpu].mtp_sizemask); 394147997Srwatson} 395147997Srwatson 396147997Srwatsonvoid * 397147997Srwatsonmemstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu, 398147997Srwatson int index) 399147997Srwatson{ 400147997Srwatson 401147997Srwatson return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]); 402147997Srwatson} 403147997Srwatson 404147997Srwatsonvoid 405147997Srwatsonmemstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu, 406147997Srwatson int index, void *value) 407147997Srwatson{ 408147997Srwatson 409147997Srwatson mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value; 410147997Srwatson} 411147997Srwatson 412147997Srwatsonuint64_t 413147997Srwatsonmemstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu, 414147997Srwatson int index) 415147997Srwatson{ 416147997Srwatson 417147997Srwatson return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]); 418147997Srwatson} 419147997Srwatson 420147997Srwatsonvoid 421147997Srwatsonmemstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index, 422147997Srwatson uint64_t value) 423147997Srwatson{ 424147997Srwatson 425147997Srwatson mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value; 426147997Srwatson} 427147997Srwatson 428147997Srwatsonuint64_t 429147997Srwatsonmemstat_get_percpu_free(const struct memory_type *mtp, int cpu) 430147997Srwatson{ 431147997Srwatson 432147997Srwatson return (mtp->mt_percpu_cache[cpu].mtp_free); 433147997Srwatson} 434