memstat.c revision 224569
1228753Smm/*- 2228753Smm * Copyright (c) 2005 Robert N. M. Watson 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15228753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16228753Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17228753Smm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18228753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22228753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23228753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24228753Smm * SUCH DAMAGE. 25228753Smm * 26228753Smm * $FreeBSD: head/lib/libmemstat/memstat.c 224569 2011-08-01 09:43:35Z pluknet $ 27228753Smm */ 28228753Smm 29228753Smm#include <sys/param.h> 30228753Smm#include <sys/sysctl.h> 31228753Smm 32228753Smm#include <err.h> 33228753Smm#include <errno.h> 34228753Smm#include <stdio.h> 35228753Smm#include <stdlib.h> 36228753Smm#include <string.h> 37228753Smm 38228753Smm#include "memstat.h" 39228753Smm#include "memstat_internal.h" 40228753Smm 41228753Smmconst char * 42228753Smmmemstat_strerror(int error) 43228753Smm{ 44228753Smm 45228753Smm switch (error) { 46228753Smm case MEMSTAT_ERROR_NOMEMORY: 47228753Smm return ("Cannot allocate memory"); 48228753Smm case MEMSTAT_ERROR_VERSION: 49228753Smm return ("Version mismatch"); 50228753Smm case MEMSTAT_ERROR_PERMISSION: 51228753Smm return ("Permission denied"); 52228753Smm case MEMSTAT_ERROR_DATAERROR: 53228753Smm return ("Data format error"); 54228753Smm case MEMSTAT_ERROR_KVM: 55228753Smm return ("KVM error"); 56228753Smm case MEMSTAT_ERROR_KVM_NOSYMBOL: 57228753Smm return ("KVM unable to find symbol"); 58228753Smm case MEMSTAT_ERROR_KVM_SHORTREAD: 59228753Smm return ("KVM short read"); 60228753Smm case MEMSTAT_ERROR_UNDEFINED: 61228753Smm default: 62228753Smm return ("Unknown error"); 63228753Smm } 64228753Smm} 65228753Smm 66228753Smmstruct memory_type_list * 67228753Smmmemstat_mtl_alloc(void) 68228753Smm{ 69228753Smm struct memory_type_list *mtlp; 70228753Smm 71228753Smm mtlp = malloc(sizeof(*mtlp)); 72228753Smm if (mtlp == NULL) 73228753Smm return (NULL); 74228753Smm 75228753Smm LIST_INIT(&mtlp->mtl_list); 76228753Smm mtlp->mtl_error = MEMSTAT_ERROR_UNDEFINED; 77228753Smm return (mtlp); 78228753Smm} 79228753Smm 80228753Smmstruct memory_type * 81228753Smmmemstat_mtl_first(struct memory_type_list *list) 82228753Smm{ 83228753Smm 84228753Smm return (LIST_FIRST(&list->mtl_list)); 85228753Smm} 86228753Smm 87228753Smmstruct memory_type * 88228753Smmmemstat_mtl_next(struct memory_type *mtp) 89228753Smm{ 90228753Smm 91228753Smm return (LIST_NEXT(mtp, mt_list)); 92228753Smm} 93228753Smm 94228753Smmvoid 95228753Smm_memstat_mtl_empty(struct memory_type_list *list) 96228753Smm{ 97228753Smm struct memory_type *mtp; 98228753Smm 99228753Smm while ((mtp = LIST_FIRST(&list->mtl_list))) { 100228753Smm free(mtp->mt_percpu_alloc); 101228753Smm free(mtp->mt_percpu_cache); 102228753Smm LIST_REMOVE(mtp, mt_list); 103228753Smm free(mtp); 104228753Smm } 105228753Smm} 106228753Smm 107228753Smmvoid 108228753Smmmemstat_mtl_free(struct memory_type_list *list) 109228753Smm{ 110228753Smm 111228753Smm _memstat_mtl_empty(list); 112228753Smm free(list); 113228753Smm} 114228753Smm 115228753Smmint 116228753Smmmemstat_mtl_geterror(struct memory_type_list *list) 117228753Smm{ 118228753Smm 119228753Smm return (list->mtl_error); 120228753Smm} 121228753Smm 122228753Smm/* 123228753Smm * Look for an existing memory_type entry in a memory_type list, based on the 124228753Smm * allocator and name of the type. If not found, return NULL. No errno or 125228753Smm * memstat error. 126228753Smm */ 127228753Smmstruct memory_type * 128228753Smmmemstat_mtl_find(struct memory_type_list *list, int allocator, 129228753Smm const char *name) 130228753Smm{ 131228753Smm struct memory_type *mtp; 132228753Smm 133228753Smm LIST_FOREACH(mtp, &list->mtl_list, mt_list) { 134228753Smm if ((mtp->mt_allocator == allocator || 135228753Smm allocator == ALLOCATOR_ANY) && 136228753Smm strcmp(mtp->mt_name, name) == 0) 137228753Smm return (mtp); 138228753Smm } 139228753Smm return (NULL); 140228753Smm} 141228753Smm 142228753Smm/* 143228753Smm * Allocate a new memory_type with the specificed allocator type and name, 144228753Smm * then insert into the list. The structure will be zero'd. 145228753Smm * 146228753Smm * libmemstat(3) internal function. 147228753Smm */ 148228753Smmstruct memory_type * 149228753Smm_memstat_mt_allocate(struct memory_type_list *list, int allocator, 150228753Smm const char *name, int maxcpus) 151228753Smm{ 152228753Smm struct memory_type *mtp; 153228753Smm 154228753Smm mtp = malloc(sizeof(*mtp)); 155228753Smm if (mtp == NULL) 156228753Smm return (NULL); 157228753Smm 158228753Smm bzero(mtp, sizeof(*mtp)); 159228753Smm 160228753Smm mtp->mt_allocator = allocator; 161228753Smm mtp->mt_percpu_alloc = malloc(sizeof(struct mt_percpu_alloc_s) * 162228753Smm maxcpus); 163228753Smm mtp->mt_percpu_cache = malloc(sizeof(struct mt_percpu_cache_s) * 164228753Smm maxcpus); 165228753Smm strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME); 166228753Smm LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list); 167228753Smm return (mtp); 168228753Smm} 169228753Smm 170228753Smm/* 171228753Smm * Reset any libmemstat(3)-owned statistics in a memory_type record so that 172228753Smm * it can be reused without incremental addition problems. Caller-owned 173228753Smm * memory is left "as-is", and must be updated by the caller if desired. 174228753Smm * 175228753Smm * libmemstat(3) internal function. 176228753Smm */ 177228753Smmvoid 178228753Smm_memstat_mt_reset_stats(struct memory_type *mtp, int maxcpus) 179228753Smm{ 180228753Smm int i; 181228753Smm 182228753Smm mtp->mt_countlimit = 0; 183228753Smm mtp->mt_byteslimit = 0; 184228753Smm mtp->mt_sizemask = 0; 185228753Smm mtp->mt_size = 0; 186228753Smm 187228753Smm mtp->mt_memalloced = 0; 188228753Smm mtp->mt_memfreed = 0; 189228753Smm mtp->mt_numallocs = 0; 190228753Smm mtp->mt_numfrees = 0; 191228753Smm mtp->mt_bytes = 0; 192228753Smm mtp->mt_count = 0; 193228753Smm mtp->mt_free = 0; 194228753Smm mtp->mt_failures = 0; 195228753Smm mtp->mt_sleeps = 0; 196228753Smm 197228753Smm mtp->mt_zonefree = 0; 198228753Smm mtp->mt_kegfree = 0; 199228753Smm 200228753Smm for (i = 0; i < maxcpus; i++) { 201228753Smm mtp->mt_percpu_alloc[i].mtp_memalloced = 0; 202228753Smm mtp->mt_percpu_alloc[i].mtp_memfreed = 0; 203228753Smm mtp->mt_percpu_alloc[i].mtp_numallocs = 0; 204228753Smm mtp->mt_percpu_alloc[i].mtp_numfrees = 0; 205228753Smm mtp->mt_percpu_alloc[i].mtp_sizemask = 0; 206228753Smm mtp->mt_percpu_cache[i].mtp_free = 0; 207228753Smm } 208228753Smm} 209228753Smm 210228753Smm/* 211228753Smm * Accessor methods for struct memory_type. Avoids encoding the structure 212228753Smm * ABI into the application. 213228753Smm */ 214228753Smmconst char * 215228753Smmmemstat_get_name(const struct memory_type *mtp) 216228753Smm{ 217228753Smm 218228753Smm return (mtp->mt_name); 219228753Smm} 220228753Smm 221228753Smmint 222228753Smmmemstat_get_allocator(const struct memory_type *mtp) 223228753Smm{ 224228753Smm 225228753Smm return (mtp->mt_allocator); 226228753Smm} 227228753Smm 228228753Smmuint64_t 229228753Smmmemstat_get_countlimit(const struct memory_type *mtp) 230228753Smm{ 231228753Smm 232228753Smm return (mtp->mt_countlimit); 233228753Smm} 234228753Smm 235228753Smmuint64_t 236228753Smmmemstat_get_byteslimit(const struct memory_type *mtp) 237228753Smm{ 238228753Smm 239228753Smm return (mtp->mt_byteslimit); 240228753Smm} 241228753Smm 242228753Smmuint64_t 243228753Smmmemstat_get_sizemask(const struct memory_type *mtp) 244228753Smm{ 245228753Smm 246228753Smm return (mtp->mt_sizemask); 247228753Smm} 248228753Smm 249228753Smmuint64_t 250228753Smmmemstat_get_size(const struct memory_type *mtp) 251228753Smm{ 252228753Smm 253228753Smm return (mtp->mt_size); 254228753Smm} 255228753Smm 256228753Smmuint64_t 257228753Smmmemstat_get_memalloced(const struct memory_type *mtp) 258228753Smm{ 259228753Smm 260228753Smm return (mtp->mt_memalloced); 261228753Smm} 262228753Smm 263228753Smmuint64_t 264228753Smmmemstat_get_memfreed(const struct memory_type *mtp) 265228753Smm{ 266228753Smm 267228753Smm return (mtp->mt_memfreed); 268228753Smm} 269228753Smm 270228753Smmuint64_t 271228753Smmmemstat_get_numallocs(const struct memory_type *mtp) 272228753Smm{ 273228753Smm 274228753Smm return (mtp->mt_numallocs); 275228753Smm} 276228753Smm 277228753Smmuint64_t 278228753Smmmemstat_get_numfrees(const struct memory_type *mtp) 279228753Smm{ 280228753Smm 281228753Smm return (mtp->mt_numfrees); 282228753Smm} 283228753Smm 284228753Smmuint64_t 285228753Smmmemstat_get_bytes(const struct memory_type *mtp) 286228753Smm{ 287228753Smm 288228753Smm return (mtp->mt_bytes); 289228753Smm} 290228753Smm 291228753Smmuint64_t 292228753Smmmemstat_get_count(const struct memory_type *mtp) 293228753Smm{ 294228753Smm 295228753Smm return (mtp->mt_count); 296228753Smm} 297228753Smm 298228753Smmuint64_t 299228753Smmmemstat_get_free(const struct memory_type *mtp) 300228753Smm{ 301228753Smm 302228753Smm return (mtp->mt_free); 303228753Smm} 304228753Smm 305228753Smmuint64_t 306228753Smmmemstat_get_failures(const struct memory_type *mtp) 307228753Smm{ 308228753Smm 309228753Smm return (mtp->mt_failures); 310228753Smm} 311228753Smm 312228753Smmuint64_t 313228753Smmmemstat_get_sleeps(const struct memory_type *mtp) 314228753Smm{ 315228753Smm 316228753Smm return (mtp->mt_sleeps); 317228753Smm} 318228753Smm 319228753Smmvoid * 320228753Smmmemstat_get_caller_pointer(const struct memory_type *mtp, int index) 321228753Smm{ 322228753Smm 323228753Smm return (mtp->mt_caller_pointer[index]); 324228753Smm} 325228753Smm 326228753Smmvoid 327228753Smmmemstat_set_caller_pointer(struct memory_type *mtp, int index, void *value) 328228753Smm{ 329228753Smm 330228753Smm mtp->mt_caller_pointer[index] = value; 331228753Smm} 332228753Smm 333228753Smmuint64_t 334228753Smmmemstat_get_caller_uint64(const struct memory_type *mtp, int index) 335228753Smm{ 336228753Smm 337228753Smm return (mtp->mt_caller_uint64[index]); 338228753Smm} 339228753Smm 340228753Smmvoid 341228753Smmmemstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value) 342228753Smm{ 343228753Smm 344228753Smm mtp->mt_caller_uint64[index] = value; 345228753Smm} 346228753Smm 347228753Smmuint64_t 348228753Smmmemstat_get_zonefree(const struct memory_type *mtp) 349228753Smm{ 350228753Smm 351228753Smm return (mtp->mt_zonefree); 352228753Smm} 353228753Smm 354228753Smmuint64_t 355228753Smmmemstat_get_kegfree(const struct memory_type *mtp) 356228753Smm{ 357228753Smm 358228753Smm return (mtp->mt_kegfree); 359228753Smm} 360228753Smm 361228753Smmuint64_t 362228753Smmmemstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu) 363228753Smm{ 364228753Smm 365228753Smm return (mtp->mt_percpu_alloc[cpu].mtp_memalloced); 366228753Smm} 367228753Smm 368228753Smmuint64_t 369228753Smmmemstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu) 370228753Smm{ 371228753Smm 372228753Smm return (mtp->mt_percpu_alloc[cpu].mtp_memfreed); 373228753Smm} 374228753Smm 375228753Smmuint64_t 376228753Smmmemstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu) 377228753Smm{ 378228753Smm 379228753Smm return (mtp->mt_percpu_alloc[cpu].mtp_numallocs); 380228753Smm} 381228753Smm 382228753Smmuint64_t 383228753Smmmemstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu) 384228753Smm{ 385228753Smm 386228753Smm return (mtp->mt_percpu_alloc[cpu].mtp_numfrees); 387228753Smm} 388228753Smm 389228753Smmuint64_t 390228753Smmmemstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu) 391228753Smm{ 392228753Smm 393228753Smm return (mtp->mt_percpu_alloc[cpu].mtp_sizemask); 394228753Smm} 395228753Smm 396228753Smmvoid * 397228753Smmmemstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu, 398228753Smm int index) 399228753Smm{ 400228753Smm 401228753Smm return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]); 402228753Smm} 403228753Smm 404228753Smmvoid 405228753Smmmemstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu, 406228753Smm int index, void *value) 407228753Smm{ 408228753Smm 409228753Smm mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value; 410228753Smm} 411228753Smm 412228753Smmuint64_t 413228753Smmmemstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu, 414228753Smm int index) 415228753Smm{ 416228753Smm 417228753Smm return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]); 418228753Smm} 419228753Smm 420228753Smmvoid 421228753Smmmemstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index, 422228753Smm uint64_t value) 423228753Smm{ 424228753Smm 425228753Smm mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value; 426228753Smm} 427228753Smm 428228753Smmuint64_t 429228753Smmmemstat_get_percpu_free(const struct memory_type *mtp, int cpu) 430228753Smm{ 431228753Smm 432228753Smm return (mtp->mt_percpu_cache[cpu].mtp_free); 433228753Smm} 434228753Smm