1 /* 2 * Copyright (c) 1987, 1991, 1993 3 * The Regents of the University of California. 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 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include "opt_vm.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/mbuf.h> 43 #include <sys/mutex.h> 44 #include <sys/vmmeter.h> 45 #include <sys/proc.h> 46 #include <sys/sysctl.h> 47 #include <sys/time.h> 48 49 #include <vm/vm.h> 50 #include <vm/pmap.h> 51 #include <vm/vm_param.h> 52 #include <vm/vm_kern.h> 53 #include <vm/vm_extern.h> 54 #include <vm/vm_map.h> 55 #include <vm/vm_page.h> 56 #include <vm/uma.h> 57 #include <vm/uma_int.h> 58 #include <vm/uma_dbg.h> 59 60 #if defined(INVARIANTS) && defined(__i386__) 61 #include <machine/cpu.h> 62 #endif 63 64 /* 65 * When realloc() is called, if the new size is sufficiently smaller than 66 * the old size, realloc() will allocate a new, smaller block to avoid 67 * wasting memory. 'Sufficiently smaller' is defined as: newsize <= 68 * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'. 69 */ 70 #ifndef REALLOC_FRACTION 71 #define REALLOC_FRACTION 1 /* new block if <= half the size */ 72 #endif 73 74 MALLOC_DEFINE(M_CACHE, "cache", "Various Dynamically allocated caches"); 75 MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); 76 MALLOC_DEFINE(M_TEMP, "temp", "misc temporary data buffers"); 77 78 MALLOC_DEFINE(M_IP6OPT, "ip6opt", "IPv6 options"); 79 MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery"); 80 81 static void kmeminit(void *); 82 SYSINIT(kmem, SI_SUB_KMEM, SI_ORDER_FIRST, kmeminit, NULL) 83 84 static MALLOC_DEFINE(M_FREE, "free", "should be on free list"); 85 86 static struct malloc_type *kmemstatistics; 87 static char *kmembase; 88 static char *kmemlimit; 89 90 #define KMEM_ZSHIFT 4 91 #define KMEM_ZBASE 16 92 #define KMEM_ZMASK (KMEM_ZBASE - 1) 93 94 #define KMEM_ZMAX PAGE_SIZE 95 #define KMEM_ZSIZE (KMEM_ZMAX >> KMEM_ZSHIFT) 96 static u_int8_t kmemsize[KMEM_ZSIZE + 1]; 97 98 /* These won't be powers of two for long */ 99 struct { 100 int kz_size; 101 char *kz_name; 102 uma_zone_t kz_zone; 103 } kmemzones[] = { 104 {16, "16", NULL}, 105 {32, "32", NULL}, 106 {64, "64", NULL}, 107 {128, "128", NULL}, 108 {256, "256", NULL}, 109 {512, "512", NULL}, 110 {1024, "1024", NULL}, 111 {2048, "2048", NULL}, 112 {4096, "4096", NULL}, 113 #if PAGE_SIZE > 4096 114 {8192, "8192", NULL}, 115 #if PAGE_SIZE > 8192 116 {16384, "16384", NULL}, 117 #if PAGE_SIZE > 16384 118 {32768, "32768", NULL}, 119 #if PAGE_SIZE > 32768 120 {65536, "65536", NULL}, 121 #if PAGE_SIZE > 65536 122 #error "Unsupported PAGE_SIZE" 123 #endif /* 65536 */ 124 #endif /* 32768 */ 125 #endif /* 16384 */ 126 #endif /* 8192 */ 127 #endif /* 4096 */ 128 {0, NULL}, 129 }; 130 131 u_int vm_kmem_size; 132 SYSCTL_UINT(_vm, OID_AUTO, kmem_size, CTLFLAG_RD, &vm_kmem_size, 0, 133 "Size of kernel memory"); 134 135 /* 136 * The malloc_mtx protects the kmemstatistics linked list. 137 */ 138 139 struct mtx malloc_mtx; 140 141 #ifdef MALLOC_PROFILE 142 uint64_t krequests[KMEM_ZSIZE + 1]; 143 144 static int sysctl_kern_mprof(SYSCTL_HANDLER_ARGS); 145 #endif 146 147 static int sysctl_kern_malloc(SYSCTL_HANDLER_ARGS); 148 149 /* time_uptime of last malloc(9) failure */ 150 static time_t t_malloc_fail; 151 152 #ifdef MALLOC_MAKE_FAILURES 153 /* 154 * Causes malloc failures every (n) mallocs with M_NOWAIT. If set to 0, 155 * doesn't cause failures. 156 */ 157 SYSCTL_NODE(_debug, OID_AUTO, malloc, CTLFLAG_RD, 0, 158 "Kernel malloc debugging options"); 159 160 static int malloc_failure_rate; 161 static int malloc_nowait_count; 162 static int malloc_failure_count; 163 SYSCTL_INT(_debug_malloc, OID_AUTO, failure_rate, CTLFLAG_RW, 164 &malloc_failure_rate, 0, "Every (n) mallocs with M_NOWAIT will fail"); 165 TUNABLE_INT("debug.malloc.failure_rate", &malloc_failure_rate); 166 SYSCTL_INT(_debug_malloc, OID_AUTO, failure_count, CTLFLAG_RD, 167 &malloc_failure_count, 0, "Number of imposed M_NOWAIT malloc failures"); 168 #endif 169 170 int 171 malloc_last_fail(void) 172 { 173 174 return (time_uptime - t_malloc_fail); 175 } 176 177 /* 178 * malloc: 179 * 180 * Allocate a block of memory. 181 * 182 * If M_NOWAIT is set, this routine will not block and return NULL if 183 * the allocation fails. 184 */ 185 void * 186 malloc(size, type, flags) 187 unsigned long size; 188 struct malloc_type *type; 189 int flags; 190 { 191 int indx; 192 caddr_t va; 193 uma_zone_t zone; 194 #ifdef DIAGNOSTIC 195 unsigned long osize = size; 196 #endif 197 register struct malloc_type *ksp = type; 198 199 #ifdef INVARIANTS 200 /* 201 * To make sure that WAITOK or NOWAIT is set, but not more than 202 * one, and check against the API botches that are common. 203 */ 204 indx = flags & (M_WAITOK | M_NOWAIT | M_DONTWAIT | M_TRYWAIT); 205 if (indx != M_NOWAIT && indx != M_WAITOK) { 206 static struct timeval lasterr; 207 static int curerr, once; 208 if (once == 0 && ppsratecheck(&lasterr, &curerr, 1)) { 209 printf("Bad malloc flags: %x\n", indx); 210 backtrace(); 211 flags |= M_WAITOK; 212 once++; 213 } 214 } 215 #endif 216 #if 0 217 if (size == 0) 218 Debugger("zero size malloc"); 219 #endif 220 #ifdef MALLOC_MAKE_FAILURES 221 if ((flags & M_NOWAIT) && (malloc_failure_rate != 0)) { 222 atomic_add_int(&malloc_nowait_count, 1); 223 if ((malloc_nowait_count % malloc_failure_rate) == 0) { 224 atomic_add_int(&malloc_failure_count, 1); 225 t_malloc_fail = time_uptime; 226 return (NULL); 227 } 228 } 229 #endif 230 if (flags & M_WAITOK) 231 KASSERT(curthread->td_intr_nesting_level == 0, 232 ("malloc(M_WAITOK) in interrupt context")); 233 if (size <= KMEM_ZMAX) { 234 if (size & KMEM_ZMASK) 235 size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; 236 indx = kmemsize[size >> KMEM_ZSHIFT]; 237 zone = kmemzones[indx].kz_zone; 238 #ifdef MALLOC_PROFILE 239 krequests[size >> KMEM_ZSHIFT]++; 240 #endif 241 va = uma_zalloc(zone, flags); 242 mtx_lock(&ksp->ks_mtx); 243 if (va == NULL) 244 goto out; 245 246 ksp->ks_size |= 1 << indx; 247 size = zone->uz_size; 248 } else { 249 size = roundup(size, PAGE_SIZE); 250 zone = NULL; 251 va = uma_large_malloc(size, flags); 252 mtx_lock(&ksp->ks_mtx); 253 if (va == NULL) 254 goto out; 255 } 256 ksp->ks_memuse += size; 257 ksp->ks_inuse++; 258 out: 259 ksp->ks_calls++; 260 if (ksp->ks_memuse > ksp->ks_maxused) 261 ksp->ks_maxused = ksp->ks_memuse; 262 263 mtx_unlock(&ksp->ks_mtx); 264 if (flags & M_WAITOK) 265 KASSERT(va != NULL, ("malloc(M_WAITOK) returned NULL")); 266 else if (va == NULL) 267 t_malloc_fail = time_uptime; 268 #ifdef DIAGNOSTIC 269 if (va != NULL && !(flags & M_ZERO)) { 270 memset(va, 0x70, osize); 271 } 272 #endif 273 return ((void *) va); 274 } 275 276 /* 277 * free: 278 * 279 * Free a block of memory allocated by malloc. 280 * 281 * This routine may not block. 282 */ 283 void 284 free(addr, type) 285 void *addr; 286 struct malloc_type *type; 287 { 288 register struct malloc_type *ksp = type; 289 uma_slab_t slab; 290 u_long size; 291 292 /* free(NULL, ...) does nothing */ 293 if (addr == NULL) 294 return; 295 296 KASSERT(ksp->ks_memuse > 0, 297 ("malloc(9)/free(9) confusion.\n%s", 298 "Probably freeing with wrong type, but maybe not here.")); 299 size = 0; 300 301 slab = vtoslab((vm_offset_t)addr & (~UMA_SLAB_MASK)); 302 303 if (slab == NULL) 304 panic("free: address %p(%p) has not been allocated.\n", 305 addr, (void *)((u_long)addr & (~UMA_SLAB_MASK))); 306 307 308 if (!(slab->us_flags & UMA_SLAB_MALLOC)) { 309 #ifdef INVARIANTS 310 struct malloc_type **mtp = addr; 311 #endif 312 size = slab->us_zone->uz_size; 313 #ifdef INVARIANTS 314 /* 315 * Cache a pointer to the malloc_type that most recently freed 316 * this memory here. This way we know who is most likely to 317 * have stepped on it later. 318 * 319 * This code assumes that size is a multiple of 8 bytes for 320 * 64 bit machines 321 */ 322 mtp = (struct malloc_type **) 323 ((unsigned long)mtp & ~UMA_ALIGN_PTR); 324 mtp += (size - sizeof(struct malloc_type *)) / 325 sizeof(struct malloc_type *); 326 *mtp = type; 327 #endif 328 uma_zfree_arg(slab->us_zone, addr, slab); 329 } else { 330 size = slab->us_size; 331 uma_large_free(slab); 332 } 333 mtx_lock(&ksp->ks_mtx); 334 KASSERT(size <= ksp->ks_memuse, 335 ("malloc(9)/free(9) confusion.\n%s", 336 "Probably freeing with wrong type, but maybe not here.")); 337 ksp->ks_memuse -= size; 338 ksp->ks_inuse--; 339 mtx_unlock(&ksp->ks_mtx); 340 } 341 342 /* 343 * realloc: change the size of a memory block 344 */ 345 void * 346 realloc(addr, size, type, flags) 347 void *addr; 348 unsigned long size; 349 struct malloc_type *type; 350 int flags; 351 { 352 uma_slab_t slab; 353 unsigned long alloc; 354 void *newaddr; 355 356 /* realloc(NULL, ...) is equivalent to malloc(...) */ 357 if (addr == NULL) 358 return (malloc(size, type, flags)); 359 360 slab = vtoslab((vm_offset_t)addr & ~(UMA_SLAB_MASK)); 361 362 /* Sanity check */ 363 KASSERT(slab != NULL, 364 ("realloc: address %p out of range", (void *)addr)); 365 366 /* Get the size of the original block */ 367 if (slab->us_zone) 368 alloc = slab->us_zone->uz_size; 369 else 370 alloc = slab->us_size; 371 372 /* Reuse the original block if appropriate */ 373 if (size <= alloc 374 && (size > (alloc >> REALLOC_FRACTION) || alloc == MINALLOCSIZE)) 375 return (addr); 376 377 /* Allocate a new, bigger (or smaller) block */ 378 if ((newaddr = malloc(size, type, flags)) == NULL) 379 return (NULL); 380 381 /* Copy over original contents */ 382 bcopy(addr, newaddr, min(size, alloc)); 383 free(addr, type); 384 return (newaddr); 385 } 386 387 /* 388 * reallocf: same as realloc() but free memory on failure. 389 */ 390 void * 391 reallocf(addr, size, type, flags) 392 void *addr; 393 unsigned long size; 394 struct malloc_type *type; 395 int flags; 396 { 397 void *mem; 398 399 if ((mem = realloc(addr, size, type, flags)) == NULL) 400 free(addr, type); 401 return (mem); 402 } 403 404 /* 405 * Initialize the kernel memory allocator 406 */ 407 /* ARGSUSED*/ 408 static void 409 kmeminit(dummy) 410 void *dummy; 411 { 412 u_int8_t indx; 413 u_long npg; 414 u_long mem_size; 415 int i; 416 417 mtx_init(&malloc_mtx, "malloc", NULL, MTX_DEF); 418 419 /* 420 * Try to auto-tune the kernel memory size, so that it is 421 * more applicable for a wider range of machine sizes. 422 * On an X86, a VM_KMEM_SIZE_SCALE value of 4 is good, while 423 * a VM_KMEM_SIZE of 12MB is a fair compromise. The 424 * VM_KMEM_SIZE_MAX is dependent on the maximum KVA space 425 * available, and on an X86 with a total KVA space of 256MB, 426 * try to keep VM_KMEM_SIZE_MAX at 80MB or below. 427 * 428 * Note that the kmem_map is also used by the zone allocator, 429 * so make sure that there is enough space. 430 */ 431 vm_kmem_size = VM_KMEM_SIZE; 432 mem_size = cnt.v_page_count; 433 434 #if defined(VM_KMEM_SIZE_SCALE) 435 if ((mem_size / VM_KMEM_SIZE_SCALE) > (vm_kmem_size / PAGE_SIZE)) 436 vm_kmem_size = (mem_size / VM_KMEM_SIZE_SCALE) * PAGE_SIZE; 437 #endif 438 439 #if defined(VM_KMEM_SIZE_MAX) 440 if (vm_kmem_size >= VM_KMEM_SIZE_MAX) 441 vm_kmem_size = VM_KMEM_SIZE_MAX; 442 #endif 443 444 /* Allow final override from the kernel environment */ 445 #ifndef BURN_BRIDGES 446 if (TUNABLE_INT_FETCH("kern.vm.kmem.size", &vm_kmem_size) != 0) 447 printf("kern.vm.kmem.size is now called vm.kmem_size!\n"); 448 #endif 449 TUNABLE_INT_FETCH("vm.kmem_size", &vm_kmem_size); 450 451 /* 452 * Limit kmem virtual size to twice the physical memory. 453 * This allows for kmem map sparseness, but limits the size 454 * to something sane. Be careful to not overflow the 32bit 455 * ints while doing the check. 456 */ 457 if (((vm_kmem_size / 2) / PAGE_SIZE) > cnt.v_page_count) 458 vm_kmem_size = 2 * cnt.v_page_count * PAGE_SIZE; 459 460 /* 461 * Tune settings based on the kernel map's size at this time. 462 */ 463 init_param3(vm_kmem_size / PAGE_SIZE); 464 465 /* 466 * In mbuf_init(), we set up submaps for mbufs and clusters, in which 467 * case we rounddown() (nmbufs * MSIZE) and (nmbclusters * MCLBYTES), 468 * respectively. Mathematically, this means that what we do here may 469 * amount to slightly more address space than we need for the submaps, 470 * but it never hurts to have an extra page in kmem_map. 471 */ 472 npg = (nmbufs*MSIZE + nmbclusters*MCLBYTES + vm_kmem_size) / PAGE_SIZE; 473 474 kmem_map = kmem_suballoc(kernel_map, (vm_offset_t *)&kmembase, 475 (vm_offset_t *)&kmemlimit, (vm_size_t)(npg * PAGE_SIZE)); 476 kmem_map->system_map = 1; 477 478 uma_startup2(); 479 480 for (i = 0, indx = 0; kmemzones[indx].kz_size != 0; indx++) { 481 int size = kmemzones[indx].kz_size; 482 char *name = kmemzones[indx].kz_name; 483 484 kmemzones[indx].kz_zone = uma_zcreate(name, size, 485 #ifdef INVARIANTS 486 mtrash_ctor, mtrash_dtor, mtrash_init, mtrash_fini, 487 #else 488 NULL, NULL, NULL, NULL, 489 #endif 490 UMA_ALIGN_PTR, UMA_ZONE_MALLOC); 491 492 for (;i <= size; i+= KMEM_ZBASE) 493 kmemsize[i >> KMEM_ZSHIFT] = indx; 494 495 } 496 } 497 498 void 499 malloc_init(data) 500 void *data; 501 { 502 struct malloc_type *type = (struct malloc_type *)data; 503 504 mtx_lock(&malloc_mtx); 505 if (type->ks_magic != M_MAGIC) 506 panic("malloc type lacks magic"); 507 508 if (cnt.v_page_count == 0) 509 panic("malloc_init not allowed before vm init"); 510 511 if (type->ks_next != NULL) 512 return; 513 514 type->ks_next = kmemstatistics; 515 kmemstatistics = type; 516 mtx_init(&type->ks_mtx, type->ks_shortdesc, "Malloc Stats", MTX_DEF); 517 mtx_unlock(&malloc_mtx); 518 } 519 520 void 521 malloc_uninit(data) 522 void *data; 523 { 524 struct malloc_type *type = (struct malloc_type *)data; 525 struct malloc_type *t; 526 527 mtx_lock(&malloc_mtx); 528 mtx_lock(&type->ks_mtx); 529 if (type->ks_magic != M_MAGIC) 530 panic("malloc type lacks magic"); 531 532 if (cnt.v_page_count == 0) 533 panic("malloc_uninit not allowed before vm init"); 534 535 if (type == kmemstatistics) 536 kmemstatistics = type->ks_next; 537 else { 538 for (t = kmemstatistics; t->ks_next != NULL; t = t->ks_next) { 539 if (t->ks_next == type) { 540 t->ks_next = type->ks_next; 541 break; 542 } 543 } 544 } 545 type->ks_next = NULL; 546 mtx_destroy(&type->ks_mtx); 547 mtx_unlock(&malloc_mtx); 548 } 549 550 static int 551 sysctl_kern_malloc(SYSCTL_HANDLER_ARGS) 552 { 553 struct malloc_type *type; 554 int linesize = 128; 555 int curline; 556 int bufsize; 557 int first; 558 int error; 559 char *buf; 560 char *p; 561 int cnt; 562 int len; 563 int i; 564 565 cnt = 0; 566 567 mtx_lock(&malloc_mtx); 568 for (type = kmemstatistics; type != NULL; type = type->ks_next) 569 cnt++; 570 571 mtx_unlock(&malloc_mtx); 572 bufsize = linesize * (cnt + 1); 573 p = buf = (char *)malloc(bufsize, M_TEMP, M_WAITOK|M_ZERO); 574 mtx_lock(&malloc_mtx); 575 576 len = snprintf(p, linesize, 577 "\n Type InUse MemUse HighUse Requests Size(s)\n"); 578 p += len; 579 580 for (type = kmemstatistics; cnt != 0 && type != NULL; 581 type = type->ks_next, cnt--) { 582 if (type->ks_calls == 0) 583 continue; 584 585 curline = linesize - 2; /* Leave room for the \n */ 586 len = snprintf(p, curline, "%13s%6lu%6luK%7luK%9llu", 587 type->ks_shortdesc, 588 type->ks_inuse, 589 (type->ks_memuse + 1023) / 1024, 590 (type->ks_maxused + 1023) / 1024, 591 (long long unsigned)type->ks_calls); 592 curline -= len; 593 p += len; 594 595 first = 1; 596 for (i = 0; i < sizeof(kmemzones) / sizeof(kmemzones[0]) - 1; 597 i++) { 598 if (type->ks_size & (1 << i)) { 599 if (first) 600 len = snprintf(p, curline, " "); 601 else 602 len = snprintf(p, curline, ","); 603 curline -= len; 604 p += len; 605 606 len = snprintf(p, curline, 607 "%s", kmemzones[i].kz_name); 608 curline -= len; 609 p += len; 610 611 first = 0; 612 } 613 } 614 615 len = snprintf(p, 2, "\n"); 616 p += len; 617 } 618 619 mtx_unlock(&malloc_mtx); 620 error = SYSCTL_OUT(req, buf, p - buf); 621 622 free(buf, M_TEMP); 623 return (error); 624 } 625 626 SYSCTL_OID(_kern, OID_AUTO, malloc, CTLTYPE_STRING|CTLFLAG_RD, 627 NULL, 0, sysctl_kern_malloc, "A", "Malloc Stats"); 628 629 #ifdef MALLOC_PROFILE 630 631 static int 632 sysctl_kern_mprof(SYSCTL_HANDLER_ARGS) 633 { 634 int linesize = 64; 635 uint64_t count; 636 uint64_t waste; 637 uint64_t mem; 638 int bufsize; 639 int error; 640 char *buf; 641 int rsize; 642 int size; 643 char *p; 644 int len; 645 int i; 646 647 bufsize = linesize * (KMEM_ZSIZE + 1); 648 bufsize += 128; /* For the stats line */ 649 bufsize += 128; /* For the banner line */ 650 waste = 0; 651 mem = 0; 652 653 p = buf = (char *)malloc(bufsize, M_TEMP, M_WAITOK|M_ZERO); 654 len = snprintf(p, bufsize, 655 "\n Size Requests Real Size\n"); 656 bufsize -= len; 657 p += len; 658 659 for (i = 0; i < KMEM_ZSIZE; i++) { 660 size = i << KMEM_ZSHIFT; 661 rsize = kmemzones[kmemsize[i]].kz_size; 662 count = (long long unsigned)krequests[i]; 663 664 len = snprintf(p, bufsize, "%6d%28llu%11d\n", 665 size, (unsigned long long)count, rsize); 666 bufsize -= len; 667 p += len; 668 669 if ((rsize * count) > (size * count)) 670 waste += (rsize * count) - (size * count); 671 mem += (rsize * count); 672 } 673 674 len = snprintf(p, bufsize, 675 "\nTotal memory used:\t%30llu\nTotal Memory wasted:\t%30llu\n", 676 (unsigned long long)mem, (unsigned long long)waste); 677 p += len; 678 679 error = SYSCTL_OUT(req, buf, p - buf); 680 681 free(buf, M_TEMP); 682 return (error); 683 } 684 685 SYSCTL_OID(_kern, OID_AUTO, mprof, CTLTYPE_STRING|CTLFLAG_RD, 686 NULL, 0, sysctl_kern_mprof, "A", "Malloc Profiling"); 687 #endif /* MALLOC_PROFILE */ 688