Index: head/sys/kern/kern_malloc.c =================================================================== --- head/sys/kern/kern_malloc.c (revision 95930) +++ head/sys/kern/kern_malloc.c (revision 95931) @@ -1,600 +1,618 @@ /* * Copyright (c) 1987, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 * $FreeBSD$ */ #include "opt_vm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(INVARIANTS) && defined(__i386__) #include #endif /* * When realloc() is called, if the new size is sufficiently smaller than * the old size, realloc() will allocate a new, smaller block to avoid * wasting memory. 'Sufficiently smaller' is defined as: newsize <= * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'. */ #ifndef REALLOC_FRACTION #define REALLOC_FRACTION 1 /* new block if <= half the size */ #endif MALLOC_DEFINE(M_CACHE, "cache", "Various Dynamically allocated caches"); MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); MALLOC_DEFINE(M_TEMP, "temp", "misc temporary data buffers"); MALLOC_DEFINE(M_IP6OPT, "ip6opt", "IPv6 options"); MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery"); static void kmeminit(void *); SYSINIT(kmem, SI_SUB_KMEM, SI_ORDER_FIRST, kmeminit, NULL) static MALLOC_DEFINE(M_FREE, "free", "should be on free list"); static struct malloc_type *kmemstatistics; static char *kmembase; static char *kmemlimit; #define KMEM_ZSHIFT 4 #define KMEM_ZBASE 16 #define KMEM_ZMASK (KMEM_ZBASE - 1) #define KMEM_ZMAX 65536 #define KMEM_ZSIZE (KMEM_ZMAX >> KMEM_ZSHIFT) static u_int8_t kmemsize[KMEM_ZSIZE + 1]; /* These won't be powers of two for long */ struct { int kz_size; char *kz_name; uma_zone_t kz_zone; } kmemzones[] = { {16, "16", NULL}, {32, "32", NULL}, {64, "64", NULL}, {128, "128", NULL}, {256, "256", NULL}, {512, "512", NULL}, {1024, "1024", NULL}, {2048, "2048", NULL}, {4096, "4096", NULL}, {8192, "8192", NULL}, {16384, "16384", NULL}, {32768, "32768", NULL}, {65536, "65536", NULL}, {0, NULL}, }; u_int vm_kmem_size; /* * The malloc_mtx protects the kmemstatistics linked list as well as the * mallochash. */ struct mtx malloc_mtx; #ifdef MALLOC_PROFILE uint64_t krequests[KMEM_ZSIZE + 1]; static int sysctl_kern_mprof(SYSCTL_HANDLER_ARGS); #endif static int sysctl_kern_malloc(SYSCTL_HANDLER_ARGS); /* * malloc: * * Allocate a block of memory. * * If M_NOWAIT is set, this routine will not block and return NULL if * the allocation fails. */ void * malloc(size, type, flags) unsigned long size; struct malloc_type *type; int flags; { int indx; caddr_t va; uma_zone_t zone; register struct malloc_type *ksp = type; #if 0 if (size == 0) Debugger("zero size malloc"); #endif #if defined(INVARIANTS) if (flags == M_WAITOK) KASSERT(curthread->td_intr_nesting_level == 0, ("malloc(M_WAITOK) in interrupt context")); #endif if (size <= KMEM_ZMAX) { if (size & KMEM_ZMASK) size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; indx = kmemsize[size >> KMEM_ZSHIFT]; zone = kmemzones[indx].kz_zone; #ifdef MALLOC_PROFILE krequests[size >> KMEM_ZSHIFT]++; #endif va = uma_zalloc(zone, flags); mtx_lock(&ksp->ks_mtx); if (va == NULL) goto out; ksp->ks_size |= 1 << indx; size = zone->uz_size; } else { size = roundup(size, PAGE_SIZE); zone = NULL; va = uma_large_malloc(size, flags); mtx_lock(&ksp->ks_mtx); if (va == NULL) goto out; } ksp->ks_memuse += size; ksp->ks_inuse++; out: ksp->ks_calls++; if (ksp->ks_memuse > ksp->ks_maxused) ksp->ks_maxused = ksp->ks_memuse; mtx_unlock(&ksp->ks_mtx); return ((void *) va); } /* * free: * * Free a block of memory allocated by malloc. * * This routine may not block. */ void free(addr, type) void *addr; struct malloc_type *type; { uma_slab_t slab; void *mem; u_long size; register struct malloc_type *ksp = type; /* free(NULL, ...) does nothing */ if (addr == NULL) return; size = 0; mem = (void *)((u_long)addr & (~UMA_SLAB_MASK)); mtx_lock(&malloc_mtx); slab = hash_sfind(mallochash, mem); mtx_unlock(&malloc_mtx); if (slab == NULL) panic("free: address %p(%p) has not been allocated.\n", addr, mem); if (!(slab->us_flags & UMA_SLAB_MALLOC)) { +#ifdef INVARIANTS + struct malloc_type **mtp = addr; +#endif size = slab->us_zone->uz_size; +#ifdef INVARIANTS + /* + * Cache a pointer to the malloc_type that most recently freed + * this memory here. This way we know who is most likely to + * have stepped on it later. + * + * This code assumes that size is a multiple of 8 bytes for + * 64 bit machines + */ + mtp = (struct malloc_type **) + ((unsigned long)mtp & ~UMA_ALIGN_PTR); + mtp += (size - sizeof(struct malloc_type *)) / + sizeof(struct malloc_type *); + *mtp = type; +#endif uma_zfree_arg(slab->us_zone, addr, slab); } else { size = slab->us_size; uma_large_free(slab); } mtx_lock(&ksp->ks_mtx); ksp->ks_memuse -= size; ksp->ks_inuse--; mtx_unlock(&ksp->ks_mtx); } /* * realloc: change the size of a memory block */ void * realloc(addr, size, type, flags) void *addr; unsigned long size; struct malloc_type *type; int flags; { uma_slab_t slab; unsigned long alloc; void *newaddr; /* realloc(NULL, ...) is equivalent to malloc(...) */ if (addr == NULL) return (malloc(size, type, flags)); mtx_lock(&malloc_mtx); slab = hash_sfind(mallochash, (void *)((u_long)addr & ~(UMA_SLAB_MASK))); mtx_unlock(&malloc_mtx); /* Sanity check */ KASSERT(slab != NULL, ("realloc: address %p out of range", (void *)addr)); /* Get the size of the original block */ if (slab->us_zone) alloc = slab->us_zone->uz_size; else alloc = slab->us_size; /* Reuse the original block if appropriate */ if (size <= alloc && (size > (alloc >> REALLOC_FRACTION) || alloc == MINALLOCSIZE)) return (addr); /* Allocate a new, bigger (or smaller) block */ if ((newaddr = malloc(size, type, flags)) == NULL) return (NULL); /* Copy over original contents */ bcopy(addr, newaddr, min(size, alloc)); free(addr, type); return (newaddr); } /* * reallocf: same as realloc() but free memory on failure. */ void * reallocf(addr, size, type, flags) void *addr; unsigned long size; struct malloc_type *type; int flags; { void *mem; if ((mem = realloc(addr, size, type, flags)) == NULL) free(addr, type); return (mem); } /* * Initialize the kernel memory allocator */ /* ARGSUSED*/ static void kmeminit(dummy) void *dummy; { u_int8_t indx; u_long npg; u_long mem_size; void *hashmem; u_long hashsize; int highbit; int bits; int i; mtx_init(&malloc_mtx, "malloc", NULL, MTX_DEF); /* * Try to auto-tune the kernel memory size, so that it is * more applicable for a wider range of machine sizes. * On an X86, a VM_KMEM_SIZE_SCALE value of 4 is good, while * a VM_KMEM_SIZE of 12MB is a fair compromise. The * VM_KMEM_SIZE_MAX is dependent on the maximum KVA space * available, and on an X86 with a total KVA space of 256MB, * try to keep VM_KMEM_SIZE_MAX at 80MB or below. * * Note that the kmem_map is also used by the zone allocator, * so make sure that there is enough space. */ vm_kmem_size = VM_KMEM_SIZE; mem_size = cnt.v_page_count * PAGE_SIZE; #if defined(VM_KMEM_SIZE_SCALE) if ((mem_size / VM_KMEM_SIZE_SCALE) > vm_kmem_size) vm_kmem_size = mem_size / VM_KMEM_SIZE_SCALE; #endif #if defined(VM_KMEM_SIZE_MAX) if (vm_kmem_size >= VM_KMEM_SIZE_MAX) vm_kmem_size = VM_KMEM_SIZE_MAX; #endif /* Allow final override from the kernel environment */ TUNABLE_INT_FETCH("kern.vm.kmem.size", &vm_kmem_size); /* * Limit kmem virtual size to twice the physical memory. * This allows for kmem map sparseness, but limits the size * to something sane. Be careful to not overflow the 32bit * ints while doing the check. */ if ((vm_kmem_size / 2) > (cnt.v_page_count * PAGE_SIZE)) vm_kmem_size = 2 * cnt.v_page_count * PAGE_SIZE; /* * In mbuf_init(), we set up submaps for mbufs and clusters, in which * case we rounddown() (nmbufs * MSIZE) and (nmbclusters * MCLBYTES), * respectively. Mathematically, this means that what we do here may * amount to slightly more address space than we need for the submaps, * but it never hurts to have an extra page in kmem_map. */ npg = (nmbufs * MSIZE + nmbclusters * MCLBYTES + nmbcnt * sizeof(u_int) + vm_kmem_size) / PAGE_SIZE; kmem_map = kmem_suballoc(kernel_map, (vm_offset_t *)&kmembase, (vm_offset_t *)&kmemlimit, (vm_size_t)(npg * PAGE_SIZE)); kmem_map->system_map = 1; hashsize = npg * sizeof(void *); highbit = 0; bits = 0; /* The hash size must be a power of two */ for (i = 0; i < 8 * sizeof(hashsize); i++) if (hashsize & (1 << i)) { highbit = i; bits++; } if (bits > 1) hashsize = 1 << (highbit); hashmem = (void *)kmem_alloc(kernel_map, (vm_size_t)hashsize); uma_startup2(hashmem, hashsize / sizeof(void *)); for (i = 0, indx = 0; kmemzones[indx].kz_size != 0; indx++) { int size = kmemzones[indx].kz_size; char *name = kmemzones[indx].kz_name; kmemzones[indx].kz_zone = uma_zcreate(name, size, #ifdef INVARIANTS - trash_ctor, trash_dtor, trash_init, trash_fini, + mtrash_ctor, mtrash_dtor, mtrash_init, mtrash_fini, #else NULL, NULL, NULL, NULL, #endif UMA_ALIGN_PTR, UMA_ZONE_MALLOC); for (;i <= size; i+= KMEM_ZBASE) kmemsize[i >> KMEM_ZSHIFT] = indx; } } void malloc_init(data) void *data; { struct malloc_type *type = (struct malloc_type *)data; mtx_lock(&malloc_mtx); if (type->ks_magic != M_MAGIC) panic("malloc type lacks magic"); if (cnt.v_page_count == 0) panic("malloc_init not allowed before vm init"); if (type->ks_next != NULL) return; type->ks_next = kmemstatistics; kmemstatistics = type; mtx_init(&type->ks_mtx, type->ks_shortdesc, "Malloc Stats", MTX_DEF); mtx_unlock(&malloc_mtx); } void malloc_uninit(data) void *data; { struct malloc_type *type = (struct malloc_type *)data; struct malloc_type *t; mtx_lock(&malloc_mtx); mtx_lock(&type->ks_mtx); if (type->ks_magic != M_MAGIC) panic("malloc type lacks magic"); if (cnt.v_page_count == 0) panic("malloc_uninit not allowed before vm init"); if (type == kmemstatistics) kmemstatistics = type->ks_next; else { for (t = kmemstatistics; t->ks_next != NULL; t = t->ks_next) { if (t->ks_next == type) { t->ks_next = type->ks_next; break; } } } type->ks_next = NULL; mtx_destroy(&type->ks_mtx); mtx_unlock(&malloc_mtx); } static int sysctl_kern_malloc(SYSCTL_HANDLER_ARGS) { struct malloc_type *type; int linesize = 128; int curline; int bufsize; int first; int error; char *buf; char *p; int cnt; int len; int i; cnt = 0; mtx_lock(&malloc_mtx); for (type = kmemstatistics; type != NULL; type = type->ks_next) cnt++; mtx_unlock(&malloc_mtx); bufsize = linesize * (cnt + 1); p = buf = (char *)malloc(bufsize, M_TEMP, M_WAITOK|M_ZERO); mtx_lock(&malloc_mtx); len = snprintf(p, linesize, "\n Type InUse MemUse HighUse Requests Size(s)\n"); p += len; for (type = kmemstatistics; cnt != 0 && type != NULL; type = type->ks_next, cnt--) { if (type->ks_calls == 0) continue; curline = linesize - 2; /* Leave room for the \n */ len = snprintf(p, curline, "%13s%6lu%6luK%7luK%9llu", type->ks_shortdesc, type->ks_inuse, (type->ks_memuse + 1023) / 1024, (type->ks_maxused + 1023) / 1024, (long long unsigned)type->ks_calls); curline -= len; p += len; first = 1; for (i = 0; i < 8 * sizeof(type->ks_size); i++) if (type->ks_size & (1 << i)) { if (first) len = snprintf(p, curline, " "); else len = snprintf(p, curline, ","); curline -= len; p += len; len = snprintf(p, curline, "%s", kmemzones[i].kz_name); curline -= len; p += len; first = 0; } len = snprintf(p, 2, "\n"); p += len; } mtx_unlock(&malloc_mtx); error = SYSCTL_OUT(req, buf, p - buf); free(buf, M_TEMP); return (error); } SYSCTL_OID(_kern, OID_AUTO, malloc, CTLTYPE_STRING|CTLFLAG_RD, NULL, 0, sysctl_kern_malloc, "A", "Malloc Stats"); #ifdef MALLOC_PROFILE static int sysctl_kern_mprof(SYSCTL_HANDLER_ARGS) { int linesize = 64; uint64_t count; uint64_t waste; uint64_t mem; int bufsize; int error; char *buf; int rsize; int size; char *p; int len; int i; bufsize = linesize * (KMEM_ZSIZE + 1); bufsize += 128; /* For the stats line */ bufsize += 128; /* For the banner line */ waste = 0; mem = 0; p = buf = (char *)malloc(bufsize, M_TEMP, M_WAITOK|M_ZERO); len = snprintf(p, bufsize, "\n Size Requests Real Size\n"); bufsize -= len; p += len; for (i = 0; i < KMEM_ZSIZE; i++) { size = i << KMEM_ZSHIFT; rsize = kmemzones[kmemsize[i]].kz_size; count = (long long unsigned)krequests[i]; len = snprintf(p, bufsize, "%6d%28llu%11d\n", size, (unsigned long long)count, rsize); bufsize -= len; p += len; if ((rsize * count) > (size * count)) waste += (rsize * count) - (size * count); mem += (rsize * count); } len = snprintf(p, bufsize, "\nTotal memory used:\t%30llu\nTotal Memory wasted:\t%30llu\n", (unsigned long long)mem, (unsigned long long)waste); p += len; error = SYSCTL_OUT(req, buf, p - buf); free(buf, M_TEMP); return (error); } SYSCTL_OID(_kern, OID_AUTO, mprof, CTLTYPE_STRING|CTLFLAG_RD, NULL, 0, sysctl_kern_mprof, "A", "Malloc Profiling"); #endif /* MALLOC_PROFILE */ Index: head/sys/vm/uma_dbg.c =================================================================== --- head/sys/vm/uma_dbg.c (revision 95930) +++ head/sys/vm/uma_dbg.c (revision 95931) @@ -1,209 +1,284 @@ /* * Copyright (c) 2002, Jeffrey Roberson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ * */ /* * uma_dbg.c Debugging features for UMA users * */ #include #include #include #include #include #include #include +#include #include #include #include #include static const u_int32_t uma_junk = 0xdeadc0de; /* * Checks an item to make sure it hasn't been overwritten since freed. * * Complies with standard ctor arg/return * */ void trash_ctor(void *mem, int size, void *arg) { int cnt; u_int32_t *p; cnt = size / sizeof(uma_junk); for (p = mem; cnt > 0; cnt--, p++) if (*p != uma_junk) panic("Memory modified after free %p(%d)\n", mem, size); } /* * Fills an item with predictable garbage * * Complies with standard dtor arg/return * */ void trash_dtor(void *mem, int size, void *arg) { int cnt; u_int32_t *p; cnt = size / sizeof(uma_junk); for (p = mem; cnt > 0; cnt--, p++) *p = uma_junk; } /* * Fills an item with predictable garbage * * Complies with standard init arg/return * */ void trash_init(void *mem, int size) { trash_dtor(mem, size, NULL); } /* * Checks an item to make sure it hasn't been overwritten since it was freed. * * Complies with standard fini arg/return * */ void trash_fini(void *mem, int size) { trash_ctor(mem, size, NULL); } +/* + * Checks an item to make sure it hasn't been overwritten since freed. + * + * Complies with standard ctor arg/return + * + */ +void +mtrash_ctor(void *mem, int size, void *arg) +{ + struct malloc_type **ksp; + u_int32_t *p = mem; + int cnt; + + size -= sizeof(struct malloc_type *); + ksp = (struct malloc_type **)mem; + ksp += size / sizeof(struct malloc_type *); + cnt = size / sizeof(uma_junk); + + for (p = mem; cnt > 0; cnt--, p++) + if (*p != uma_junk) { + printf("Memory modified after free %p(%d)\n", + mem, size); + panic("Most recently used by %s\n", (*ksp == NULL)? + "none" : (*ksp)->ks_shortdesc); + } +} + +/* + * Fills an item with predictable garbage + * + * Complies with standard dtor arg/return + * + */ +void +mtrash_dtor(void *mem, int size, void *arg) +{ + int cnt; + u_int32_t *p; + + size -= sizeof(struct malloc_type *); + cnt = size / sizeof(uma_junk); + + for (p = mem; cnt > 0; cnt--, p++) + *p = uma_junk; +} + +/* + * Fills an item with predictable garbage + * + * Complies with standard init arg/return + * + */ +void +mtrash_init(void *mem, int size) +{ + struct malloc_type **ksp; + + mtrash_dtor(mem, size, NULL); + + ksp = (struct malloc_type **)mem; + ksp += (size / sizeof(struct malloc_type *)) - 1; + *ksp = NULL; +} + +/* + * Checks an item to make sure it hasn't been overwritten since it was freed. + * + * Complies with standard fini arg/return + * + */ +void +mtrash_fini(void *mem, int size) +{ + mtrash_ctor(mem, size, NULL); +} + static uma_slab_t uma_dbg_getslab(uma_zone_t zone, void *item) { uma_slab_t slab; u_int8_t *mem; mem = (u_int8_t *)((unsigned long)item & (~UMA_SLAB_MASK)); if (zone->uz_flags & UMA_ZFLAG_MALLOC) { mtx_lock(&malloc_mtx); slab = hash_sfind(mallochash, mem); mtx_unlock(&malloc_mtx); } else if (zone->uz_flags & UMA_ZFLAG_OFFPAGE) { ZONE_LOCK(zone); slab = hash_sfind(&zone->uz_hash, mem); ZONE_UNLOCK(zone); } else { mem += zone->uz_pgoff; slab = (uma_slab_t)mem; } return (slab); } /* * Set up the slab's freei data such that uma_dbg_free can function. * */ void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item) { int freei; if (slab == NULL) { slab = uma_dbg_getslab(zone, item); if (slab == NULL) panic("uma: item %p did not belong to zone %s\n", item, zone->uz_name); } freei = ((unsigned long)item - (unsigned long)slab->us_data) / zone->uz_rsize; slab->us_freelist[freei] = 255; return; } /* * Verifies freed addresses. Checks for alignment, valid slab membership * and duplicate frees. * */ void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item) { int freei; - - return; if (slab == NULL) { slab = uma_dbg_getslab(zone, item); if (slab == NULL) panic("uma: Freed item %p did not belong to zone %s\n", item, zone->uz_name); } freei = ((unsigned long)item - (unsigned long)slab->us_data) / zone->uz_rsize; if (freei >= zone->uz_ipers) panic("zone: %s(%p) slab %p freelist %i out of range 0-%d\n", zone->uz_name, zone, slab, freei, zone->uz_ipers-1); if (((freei * zone->uz_rsize) + slab->us_data) != item) { printf("zone: %s(%p) slab %p freed address %p unaligned.\n", zone->uz_name, zone, slab, item); panic("should be %p\n", (freei * zone->uz_rsize) + slab->us_data); } if (slab->us_freelist[freei] != 255) { printf("Slab at %p, freei %d = %d.\n", slab, freei, slab->us_freelist[freei]); panic("Duplicate free of item %p from zone %p(%s)\n", item, zone, zone->uz_name); } /* * When this is actually linked into the slab this will change. * Until then the count of valid slabs will make sure we don't * accidentally follow this and assume it's a valid index. */ slab->us_freelist[freei] = 0; } Index: head/sys/vm/uma_dbg.h =================================================================== --- head/sys/vm/uma_dbg.h (revision 95930) +++ head/sys/vm/uma_dbg.h (revision 95931) @@ -1,49 +1,56 @@ /* * Copyright (c) 2002, Jeffrey Roberson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ * */ /* * * Jeff Roberson * * This file includes definitions, structures, prototypes, and inlines used * when debugging users of the UMA interface. * */ #ifndef VM_UMA_DBG_H #define VM_UMA_DBG_H void trash_ctor(void *mem, int size, void *arg); void trash_dtor(void *mem, int size, void *arg); void trash_init(void *mem, int size); void trash_fini(void *mem, int size); + +/* For use only by malloc */ +void mtrash_ctor(void *mem, int size, void *arg); +void mtrash_dtor(void *mem, int size, void *arg); +void mtrash_init(void *mem, int size); +void mtrash_fini(void *mem, int size); + void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item); void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item); #endif /* VM_UMA_DBG_H */