memstat.c revision 148354
1/*- 2 * Copyright (c) 2005 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/lib/libmemstat/memstat.c 148354 2005-07-23 21:17:15Z rwatson $ 27 */ 28 29#include <sys/param.h> 30#include <sys/sysctl.h> 31 32#include <err.h> 33#include <errno.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37 38#include "memstat.h" 39#include "memstat_internal.h" 40 41struct memory_type_list * 42memstat_mtl_alloc(void) 43{ 44 struct memory_type_list *mtlp; 45 46 mtlp = malloc(sizeof(*mtlp)); 47 if (mtlp == NULL) 48 return (NULL); 49 50 LIST_INIT(mtlp); 51 return (mtlp); 52} 53 54struct memory_type * 55memstat_mtl_first(struct memory_type_list *list) 56{ 57 58 return (LIST_FIRST(list)); 59} 60 61struct memory_type * 62memstat_mtl_next(struct memory_type *mtp) 63{ 64 65 return (LIST_NEXT(mtp, mt_list)); 66} 67 68void 69memstat_mtl_free(struct memory_type_list *list) 70{ 71 struct memory_type *mtp; 72 73 while ((mtp = LIST_FIRST(list))) { 74 LIST_REMOVE(mtp, mt_list); 75 free(mtp); 76 } 77 free(list); 78} 79 80/* 81 * Look for an existing memory_type entry in a memory_type list, based on the 82 * allocator and name of the type. If not found, return NULL. O(n). 83 */ 84struct memory_type * 85memstat_mtl_find(struct memory_type_list *list, int allocator, 86 const char *name) 87{ 88 struct memory_type *mtp; 89 90 LIST_FOREACH(mtp, list, mt_list) { 91 if ((mtp->mt_allocator == allocator || 92 allocator == ALLOCATOR_ANY) && 93 strcmp(mtp->mt_name, name) == 0) 94 return (mtp); 95 } 96 return (NULL); 97} 98 99/* 100 * Allocate a new memory_type with the specificed allocator type and name, 101 * then insert into the list. The structure will be zero'd. 102 * 103 * libmemstat(3) internal function. 104 */ 105struct memory_type * 106_memstat_mt_allocate(struct memory_type_list *list, int allocator, 107 const char *name) 108{ 109 struct memory_type *mtp; 110 111 mtp = malloc(sizeof(*mtp)); 112 if (mtp == NULL) 113 return (NULL); 114 115 bzero(mtp, sizeof(*mtp)); 116 117 mtp->mt_allocator = allocator; 118 strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME); 119 LIST_INSERT_HEAD(list, mtp, mt_list); 120 return (mtp); 121} 122 123/* 124 * Reset any libmemstat(3)-owned statistics in a memory_type record so that 125 * it can be reused without incremental addition problems. Caller-owned 126 * memory is left "as-is", and must be updated by the caller if desired. 127 * 128 * libmemstat(3) internal function. 129 */ 130void 131_memstat_mt_reset_stats(struct memory_type *mtp) 132{ 133 int i; 134 135 mtp->mt_countlimit = 0; 136 mtp->mt_byteslimit = 0; 137 mtp->mt_sizemask = 0; 138 mtp->mt_size = 0; 139 140 mtp->mt_memalloced = 0; 141 mtp->mt_memfreed = 0; 142 mtp->mt_numallocs = 0; 143 mtp->mt_numfrees = 0; 144 mtp->mt_bytes = 0; 145 mtp->mt_count = 0; 146 mtp->mt_free = 0; 147 mtp->mt_failures = 0; 148 149 mtp->mt_zonefree = 0; 150 mtp->mt_kegfree = 0; 151 152 for (i = 0; i < MEMSTAT_MAXCPU; i++) { 153 mtp->mt_percpu_alloc[i].mtp_memalloced = 0; 154 mtp->mt_percpu_alloc[i].mtp_memfreed = 0; 155 mtp->mt_percpu_alloc[i].mtp_numallocs = 0; 156 mtp->mt_percpu_alloc[i].mtp_numfrees = 0; 157 mtp->mt_percpu_alloc[i].mtp_sizemask = 0; 158 mtp->mt_percpu_cache[i].mtp_free = 0; 159 } 160} 161 162/* 163 * Accessor methods for struct memory_type. Avoids encoding the structure 164 * ABI into the application. 165 */ 166const char * 167memstat_get_name(const struct memory_type *mtp) 168{ 169 170 return (mtp->mt_name); 171} 172 173int 174memstat_get_allocator(const struct memory_type *mtp) 175{ 176 177 return (mtp->mt_allocator); 178} 179 180uint64_t 181memstat_get_countlimit(const struct memory_type *mtp) 182{ 183 184 return (mtp->mt_countlimit); 185} 186 187uint64_t 188memstat_get_byteslimit(const struct memory_type *mtp) 189{ 190 191 return (mtp->mt_byteslimit); 192} 193 194uint64_t 195memstat_get_sizemask(const struct memory_type *mtp) 196{ 197 198 return (mtp->mt_sizemask); 199} 200 201uint64_t 202memstat_get_size(const struct memory_type *mtp) 203{ 204 205 return (mtp->mt_size); 206} 207 208uint64_t 209memstat_get_memalloced(const struct memory_type *mtp) 210{ 211 212 return (mtp->mt_memalloced); 213} 214 215uint64_t 216memstat_get_memfreed(const struct memory_type *mtp) 217{ 218 219 return (mtp->mt_memfreed); 220} 221 222uint64_t 223memstat_get_numallocs(const struct memory_type *mtp) 224{ 225 226 return (mtp->mt_numallocs); 227} 228 229uint64_t 230memstat_get_numfrees(const struct memory_type *mtp) 231{ 232 233 return (mtp->mt_numfrees); 234} 235 236uint64_t 237memstat_get_bytes(const struct memory_type *mtp) 238{ 239 240 return (mtp->mt_bytes); 241} 242 243uint64_t 244memstat_get_count(const struct memory_type *mtp) 245{ 246 247 return (mtp->mt_count); 248} 249 250uint64_t 251memstat_get_free(const struct memory_type *mtp) 252{ 253 254 return (mtp->mt_free); 255} 256 257uint64_t 258memstat_get_failures(const struct memory_type *mtp) 259{ 260 261 return (mtp->mt_failures); 262} 263 264void * 265memstat_get_caller_pointer(const struct memory_type *mtp, int index) 266{ 267 268 return (mtp->mt_caller_pointer[index]); 269} 270 271void 272memstat_set_caller_pointer(struct memory_type *mtp, int index, void *value) 273{ 274 275 mtp->mt_caller_pointer[index] = value; 276} 277 278uint64_t 279memstat_get_caller_uint64(const struct memory_type *mtp, int index) 280{ 281 282 return (mtp->mt_caller_uint64[index]); 283} 284 285void 286memstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value) 287{ 288 289 mtp->mt_caller_uint64[index] = value; 290} 291 292uint64_t 293memstat_get_zonefree(const struct memory_type *mtp) 294{ 295 296 return (mtp->mt_zonefree); 297} 298 299uint64_t 300memstat_get_kegfree(const struct memory_type *mtp) 301{ 302 303 return (mtp->mt_kegfree); 304} 305 306uint64_t 307memstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu) 308{ 309 310 return (mtp->mt_percpu_alloc[cpu].mtp_memalloced); 311} 312 313uint64_t 314memstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu) 315{ 316 317 return (mtp->mt_percpu_alloc[cpu].mtp_memfreed); 318} 319 320uint64_t 321memstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu) 322{ 323 324 return (mtp->mt_percpu_alloc[cpu].mtp_numallocs); 325} 326 327uint64_t 328memstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu) 329{ 330 331 return (mtp->mt_percpu_alloc[cpu].mtp_numfrees); 332} 333 334uint64_t 335memstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu) 336{ 337 338 return (mtp->mt_percpu_alloc[cpu].mtp_sizemask); 339} 340 341void * 342memstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu, 343 int index) 344{ 345 346 return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]); 347} 348 349void 350memstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu, 351 int index, void *value) 352{ 353 354 mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value; 355} 356 357uint64_t 358memstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu, 359 int index) 360{ 361 362 return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]); 363} 364 365void 366memstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index, 367 uint64_t value) 368{ 369 370 mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value; 371} 372 373uint64_t 374memstat_get_percpu_free(const struct memory_type *mtp, int cpu) 375{ 376 377 return (mtp->mt_percpu_cache[cpu].mtp_free); 378} 379