The Design and Implementation of the FreeBSD Operating System, Second Edition
[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/vm/uma_dbg.c

Version: -  FREEBSD  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org>
    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 unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 /*
   28  * uma_dbg.c    Debugging features for UMA users
   29  *
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: src/sys/vm/uma_dbg.c,v 1.15.2.1 2004/10/16 01:41:34 green Exp $");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/types.h>
   39 #include <sys/queue.h>
   40 #include <sys/lock.h>
   41 #include <sys/mutex.h>
   42 #include <sys/malloc.h>
   43 
   44 #include <vm/vm.h>
   45 #include <vm/vm_object.h>
   46 #include <vm/vm_page.h>
   47 #include <vm/uma.h>
   48 #include <vm/uma_int.h>
   49 #include <vm/uma_dbg.h>
   50 
   51 static const u_int32_t uma_junk = 0xdeadc0de;
   52 
   53 /*
   54  * Checks an item to make sure it hasn't been overwritten since it was freed,
   55  * prior to subsequent reallocation.
   56  *
   57  * Complies with standard ctor arg/return
   58  *
   59  */
   60 int
   61 trash_ctor(void *mem, int size, void *arg, int flags)
   62 {
   63         int cnt;
   64         u_int32_t *p;
   65 
   66         cnt = size / sizeof(uma_junk);
   67 
   68         for (p = mem; cnt > 0; cnt--, p++)
   69                 if (*p != uma_junk)
   70                         panic("Memory modified after free %p(%d) val=%x @ %p\n",
   71                             mem, size, *p, p);
   72         return (0);
   73 }
   74 
   75 /*
   76  * Fills an item with predictable garbage
   77  *
   78  * Complies with standard dtor arg/return
   79  *
   80  */
   81 void
   82 trash_dtor(void *mem, int size, void *arg)
   83 {
   84         int cnt;
   85         u_int32_t *p;
   86 
   87         cnt = size / sizeof(uma_junk);
   88 
   89         for (p = mem; cnt > 0; cnt--, p++)
   90                 *p = uma_junk;
   91 }
   92 
   93 /*
   94  * Fills an item with predictable garbage
   95  *
   96  * Complies with standard init arg/return
   97  *
   98  */
   99 int
  100 trash_init(void *mem, int size, int flags)
  101 {
  102         trash_dtor(mem, size, NULL);
  103         return (0);
  104 }
  105 
  106 /*
  107  * Checks an item to make sure it hasn't been overwritten since it was freed.
  108  *
  109  * Complies with standard fini arg/return
  110  *
  111  */
  112 void
  113 trash_fini(void *mem, int size)
  114 {
  115         (void)trash_ctor(mem, size, NULL, 0);
  116 }
  117 
  118 int
  119 mtrash_ctor(void *mem, int size, void *arg, int flags)
  120 {
  121         struct malloc_type **ksp;
  122         u_int32_t *p = mem;
  123         int cnt;
  124 
  125         size -= sizeof(struct malloc_type *);
  126         ksp = (struct malloc_type **)mem;
  127         ksp += size / sizeof(struct malloc_type *);
  128         cnt = size / sizeof(uma_junk);
  129 
  130         for (p = mem; cnt > 0; cnt--, p++)
  131                 if (*p != uma_junk) {
  132                         printf("Memory modified after free %p(%d) val=%x @ %p\n",
  133                             mem, size, *p, p);
  134                         panic("Most recently used by %s\n", (*ksp == NULL)?
  135                             "none" : (*ksp)->ks_shortdesc);
  136                 }
  137         return (0);
  138 }
  139 
  140 /*
  141  * Fills an item with predictable garbage
  142  *
  143  * Complies with standard dtor arg/return
  144  *
  145  */
  146 void
  147 mtrash_dtor(void *mem, int size, void *arg)
  148 {
  149         int cnt;
  150         u_int32_t *p;
  151 
  152         size -= sizeof(struct malloc_type *);
  153         cnt = size / sizeof(uma_junk);
  154 
  155         for (p = mem; cnt > 0; cnt--, p++)
  156                 *p = uma_junk;
  157 }
  158 
  159 /*
  160  * Fills an item with predictable garbage
  161  *
  162  * Complies with standard init arg/return
  163  *
  164  */
  165 int
  166 mtrash_init(void *mem, int size, int flags)
  167 {
  168         struct malloc_type **ksp;
  169 
  170         mtrash_dtor(mem, size, NULL);
  171 
  172         ksp = (struct malloc_type **)mem;
  173         ksp += (size / sizeof(struct malloc_type *)) - 1;
  174         *ksp = NULL;
  175         return (0);
  176 }
  177 
  178 /*
  179  * Checks an item to make sure it hasn't been overwritten since it was freed,
  180  * prior to freeing it back to available memory.
  181  *
  182  * Complies with standard fini arg/return
  183  *
  184  */
  185 void
  186 mtrash_fini(void *mem, int size)
  187 {
  188         (void)mtrash_ctor(mem, size, NULL, 0);
  189 }
  190 
  191 static uma_slab_t
  192 uma_dbg_getslab(uma_zone_t zone, void *item)
  193 {
  194         uma_slab_t slab;
  195         uma_keg_t keg;
  196         u_int8_t *mem;
  197 
  198         keg = zone->uz_keg;
  199         mem = (u_int8_t *)((unsigned long)item & (~UMA_SLAB_MASK));
  200         if (keg->uk_flags & UMA_ZONE_MALLOC) {
  201                 slab = vtoslab((vm_offset_t)mem);
  202         } else if (keg->uk_flags & UMA_ZONE_HASH) {
  203                 slab = hash_sfind(&keg->uk_hash, mem);
  204         } else {
  205                 mem += keg->uk_pgoff;
  206                 slab = (uma_slab_t)mem;
  207         }
  208 
  209         return (slab);
  210 }
  211 
  212 /*
  213  * Set up the slab's freei data such that uma_dbg_free can function.
  214  *
  215  */
  216 
  217 void
  218 uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item)
  219 {
  220         uma_keg_t keg;
  221         uma_slabrefcnt_t slabref;
  222         int freei;
  223 
  224         keg = zone->uz_keg;
  225         if (slab == NULL) {
  226                 slab = uma_dbg_getslab(zone, item);
  227                 if (slab == NULL) 
  228                         panic("uma: item %p did not belong to zone %s\n",
  229                             item, zone->uz_name);
  230         }
  231 
  232         freei = ((unsigned long)item - (unsigned long)slab->us_data)
  233             / keg->uk_rsize;
  234 
  235         if (keg->uk_flags & UMA_ZONE_REFCNT) {
  236                 slabref = (uma_slabrefcnt_t)slab;
  237                 slabref->us_freelist[freei].us_item = 255;
  238         } else {
  239                 slab->us_freelist[freei].us_item = 255;
  240         }
  241 
  242         return;
  243 }
  244 
  245 /*
  246  * Verifies freed addresses.  Checks for alignment, valid slab membership
  247  * and duplicate frees.
  248  *
  249  */
  250 
  251 void
  252 uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
  253 {
  254         uma_keg_t keg;
  255         uma_slabrefcnt_t slabref;
  256         int freei;
  257 
  258         keg = zone->uz_keg;
  259         if (slab == NULL) {
  260                 slab = uma_dbg_getslab(zone, item);
  261                 if (slab == NULL) 
  262                         panic("uma: Freed item %p did not belong to zone %s\n",
  263                             item, zone->uz_name);
  264         }
  265 
  266         freei = ((unsigned long)item - (unsigned long)slab->us_data)
  267             / keg->uk_rsize;
  268 
  269         if (freei >= keg->uk_ipers)
  270                 panic("zone: %s(%p) slab %p freelist %d out of range 0-%d\n",
  271                     zone->uz_name, zone, slab, freei, keg->uk_ipers-1);
  272 
  273         if (((freei * keg->uk_rsize) + slab->us_data) != item) {
  274                 printf("zone: %s(%p) slab %p freed address %p unaligned.\n",
  275                     zone->uz_name, zone, slab, item);
  276                 panic("should be %p\n",
  277                     (freei * keg->uk_rsize) + slab->us_data);
  278         }
  279 
  280         if (keg->uk_flags & UMA_ZONE_REFCNT) {
  281                 slabref = (uma_slabrefcnt_t)slab;
  282                 if (slabref->us_freelist[freei].us_item != 255) {
  283                         printf("Slab at %p, freei %d = %d.\n",
  284                             slab, freei, slabref->us_freelist[freei].us_item);
  285                         panic("Duplicate free of item %p from zone %p(%s)\n",
  286                             item, zone, zone->uz_name);
  287                 }
  288 
  289                 /*
  290                  * When this is actually linked into the slab this will change.
  291                  * Until then the count of valid slabs will make sure we don't
  292                  * accidentally follow this and assume it's a valid index.
  293                  */
  294                 slabref->us_freelist[freei].us_item = 0;
  295         } else {
  296                 if (slab->us_freelist[freei].us_item != 255) {
  297                         printf("Slab at %p, freei %d = %d.\n",
  298                             slab, freei, slab->us_freelist[freei].us_item);
  299                         panic("Duplicate free of item %p from zone %p(%s)\n",
  300                             item, zone, zone->uz_name);
  301                 }
  302 
  303                 /*
  304                  * When this is actually linked into the slab this will change.
  305                  * Until then the count of valid slabs will make sure we don't
  306                  * accidentally follow this and assume it's a valid index.
  307                  */
  308                 slab->us_freelist[freei].us_item = 0;
  309         }
  310 }

Cache object: 5d4e634622170ced3d2b2a25dbdcc75e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.