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$ 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 41 struct memory_type_list * 42 memstat_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 54 struct memory_type * 55 memstat_mtl_first(struct memory_type_list *list) 56 { 57 58 return (LIST_FIRST(list)); 59 } 60 61 struct memory_type * 62 memstat_mtl_next(struct memory_type *mtp) 63 { 64 65 return (LIST_NEXT(mtp, mt_list)); 66 } 67 68 void 69 memstat_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 */ 84 struct memory_type * 85 memstat_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 struct memory_type * 104 memstat_mt_allocate(struct memory_type_list *list, int allocator, 105 const char *name) 106 { 107 struct memory_type *mtp; 108 109 mtp = malloc(sizeof(*mtp)); 110 if (mtp == NULL) 111 return (NULL); 112 113 bzero(mtp, sizeof(*mtp)); 114 115 mtp->mt_allocator = allocator; 116 strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME); 117 LIST_INSERT_HEAD(list, mtp, mt_list); 118 return (mtp); 119 } 120 121 /* 122 * Reset any libmemstat(3)-owned statistics in a memory_type record so that 123 * it can be reused without incremental addition problems. Caller-owned 124 * memory is left "as-is", and must be updated by the caller if desired. 125 */ 126 void 127 memstat_mt_reset_stats(struct memory_type *mtp) 128 { 129 int i; 130 131 mtp->mt_countlimit = 0; 132 mtp->mt_byteslimit = 0; 133 mtp->mt_sizemask = 0; 134 mtp->mt_size = 0; 135 136 mtp->mt_memalloced = 0; 137 mtp->mt_memfreed = 0; 138 mtp->mt_numallocs = 0; 139 mtp->mt_numfrees = 0; 140 mtp->mt_bytes = 0; 141 mtp->mt_count = 0; 142 mtp->mt_free = 0; 143 mtp->mt_failures = 0; 144 145 mtp->mt_zonefree = 0; 146 mtp->mt_kegfree = 0; 147 148 for (i = 0; i < MEMSTAT_MAXCPU; i++) { 149 mtp->mt_percpu_alloc[i].mtp_memalloced = 0; 150 mtp->mt_percpu_alloc[i].mtp_memfreed = 0; 151 mtp->mt_percpu_alloc[i].mtp_numallocs = 0; 152 mtp->mt_percpu_alloc[i].mtp_numfrees = 0; 153 mtp->mt_percpu_alloc[i].mtp_sizemask = 0; 154 mtp->mt_percpu_cache[i].mtp_free = 0; 155 } 156 } 157 158 /* 159 * Accessor methods for struct memory_type. Avoids encoding the structure 160 * ABI into the application. 161 */ 162 const char * 163 memstat_get_name(const struct memory_type *mtp) 164 { 165 166 return (mtp->mt_name); 167 } 168 169 int 170 memstat_get_allocator(const struct memory_type *mtp) 171 { 172 173 return (mtp->mt_allocator); 174 } 175 176 uint64_t 177 memstat_get_countlimit(const struct memory_type *mtp) 178 { 179 180 return (mtp->mt_countlimit); 181 } 182 183 uint64_t 184 memstat_get_byteslimit(const struct memory_type *mtp) 185 { 186 187 return (mtp->mt_byteslimit); 188 } 189 190 uint64_t 191 memstat_get_sizemask(const struct memory_type *mtp) 192 { 193 194 return (mtp->mt_sizemask); 195 } 196 197 uint64_t 198 memstat_get_size(const struct memory_type *mtp) 199 { 200 201 return (mtp->mt_size); 202 } 203 204 uint64_t 205 memstat_get_memalloced(const struct memory_type *mtp) 206 { 207 208 return (mtp->mt_memalloced); 209 } 210 211 uint64_t 212 memstat_get_memfreed(const struct memory_type *mtp) 213 { 214 215 return (mtp->mt_memfreed); 216 } 217 218 uint64_t 219 memstat_get_numallocs(const struct memory_type *mtp) 220 { 221 222 return (mtp->mt_numallocs); 223 } 224 225 uint64_t 226 memstat_get_numfrees(const struct memory_type *mtp) 227 { 228 229 return (mtp->mt_numfrees); 230 } 231 232 uint64_t 233 memstat_get_bytes(const struct memory_type *mtp) 234 { 235 236 return (mtp->mt_bytes); 237 } 238 239 uint64_t 240 memstat_get_count(const struct memory_type *mtp) 241 { 242 243 return (mtp->mt_count); 244 } 245 246 uint64_t 247 memstat_get_free(const struct memory_type *mtp) 248 { 249 250 return (mtp->mt_free); 251 } 252 253 uint64_t 254 memstat_get_failures(const struct memory_type *mtp) 255 { 256 257 return (mtp->mt_failures); 258 } 259 260 void * 261 memstat_get_caller_pointer(const struct memory_type *mtp, int index) 262 { 263 264 return (mtp->mt_caller_pointer[index]); 265 } 266 267 void 268 memstat_set_caller_pointer(struct memory_type *mtp, int index, void *value) 269 { 270 271 mtp->mt_caller_pointer[index] = value; 272 } 273 274 uint64_t 275 memstat_get_caller_uint64(const struct memory_type *mtp, int index) 276 { 277 278 return (mtp->mt_caller_uint64[index]); 279 } 280 281 void 282 memstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value) 283 { 284 285 mtp->mt_caller_uint64[index] = value; 286 } 287 288 uint64_t 289 memstat_get_zonefree(const struct memory_type *mtp) 290 { 291 292 return (mtp->mt_zonefree); 293 } 294 295 uint64_t 296 memstat_get_kegfree(const struct memory_type *mtp) 297 { 298 299 return (mtp->mt_kegfree); 300 } 301 302 uint64_t 303 memstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu) 304 { 305 306 return (mtp->mt_percpu_alloc[cpu].mtp_memalloced); 307 } 308 309 uint64_t 310 memstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu) 311 { 312 313 return (mtp->mt_percpu_alloc[cpu].mtp_memfreed); 314 } 315 316 uint64_t 317 memstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu) 318 { 319 320 return (mtp->mt_percpu_alloc[cpu].mtp_numallocs); 321 } 322 323 uint64_t 324 memstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu) 325 { 326 327 return (mtp->mt_percpu_alloc[cpu].mtp_numfrees); 328 } 329 330 uint64_t 331 memstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu) 332 { 333 334 return (mtp->mt_percpu_alloc[cpu].mtp_sizemask); 335 } 336 337 void * 338 memstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu, 339 int index) 340 { 341 342 return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]); 343 } 344 345 void 346 memstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu, 347 int index, void *value) 348 { 349 350 mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value; 351 } 352 353 uint64_t 354 memstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu, 355 int index) 356 { 357 358 return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]); 359 } 360 361 void 362 memstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index, 363 uint64_t value) 364 { 365 366 mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value; 367 } 368 369 uint64_t 370 memstat_get_percpu_free(const struct memory_type *mtp, int cpu) 371 { 372 373 return (mtp->mt_percpu_cache[cpu].mtp_free); 374 } 375