Annotation of Gnu-Mach/kern/slab.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  * Copyright (c) 2011 Free Software Foundation.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or modify
                      5:  * it under the terms of the GNU General Public License as published by
                      6:  * the Free Software Foundation; either version 2 of the License, or
                      7:  * (at your option) any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful,
                     10:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     12:  * GNU General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License along
                     15:  * with this program; if not, write to the Free Software Foundation, Inc.,
                     16:  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
                     17:  */
                     18: 
                     19: /*
                     20:  * Copyright (c) 2010, 2011 Richard Braun.
                     21:  * All rights reserved.
                     22:  *
                     23:  * Redistribution and use in source and binary forms, with or without
                     24:  * modification, are permitted provided that the following conditions
                     25:  * are met:
                     26:  * 1. Redistributions of source code must retain the above copyright
                     27:  *    notice, this list of conditions and the following disclaimer.
                     28:  * 2. Redistributions in binary form must reproduce the above copyright
                     29:  *    notice, this list of conditions and the following disclaimer in the
                     30:  *    documentation and/or other materials provided with the distribution.
                     31:  *
                     32:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     33:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     34:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     35:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     36:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     37:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     38:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     39:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     40:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     41:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     42:  *
                     43:  *
                     44:  * Object caching and general purpose memory allocator.
                     45:  *
                     46:  * This allocator is based on the paper "The Slab Allocator: An Object-Caching
                     47:  * Kernel Memory Allocator" by Jeff Bonwick.
                     48:  *
                     49:  * It allows the allocation of objects (i.e. fixed-size typed buffers) from
                     50:  * caches and is efficient in both space and time. This implementation follows
                     51:  * many of the indications from the paper mentioned. The most notable
                     52:  * differences are outlined below.
                     53:  *
                     54:  * The per-cache self-scaling hash table for buffer-to-bufctl conversion,
                     55:  * described in 3.2.3 "Slab Layout for Large Objects", has been replaced by
                     56:  * a red-black tree storing slabs, sorted by address. The use of a
                     57:  * self-balancing tree for buffer-to-slab conversions provides a few advantages
                     58:  * over a hash table. Unlike a hash table, a BST provides a "lookup nearest"
                     59:  * operation, so obtaining the slab data (whether it is embedded in the slab or
                     60:  * off slab) from a buffer address simply consists of a "lookup nearest towards
1.1.1.4   root       61:  * 0" tree search. Finally, a self-balancing tree is a true self-scaling data
                     62:  * structure, whereas a hash table requires periodic maintenance and complete
                     63:  * resizing, which is expensive. The only drawback is that releasing a buffer
                     64:  * to the slab layer takes logarithmic time instead of constant time.
1.1       root       65:  *
                     66:  * This implementation uses per-cpu pools of objects, which service most
                     67:  * allocation requests. These pools act as caches (but are named differently
                     68:  * to avoid confusion with CPU caches) that reduce contention on multiprocessor
                     69:  * systems. When a pool is empty and cannot provide an object, it is filled by
                     70:  * transferring multiple objects from the slab layer. The symmetric case is
                     71:  * handled likewise.
                     72:  */
                     73: 
                     74: #include <string.h>
                     75: #include <kern/assert.h>
                     76: #include <kern/mach_clock.h>
1.1.1.3   root       77: #include <kern/macros.h>
1.1       root       78: #include <kern/printf.h>
                     79: #include <kern/slab.h>
                     80: #include <kern/kalloc.h>
                     81: #include <kern/cpu_number.h>
                     82: #include <mach/vm_param.h>
                     83: #include <mach/machine/vm_types.h>
                     84: #include <vm/vm_kern.h>
1.1.1.4   root       85: #include <vm/vm_page.h>
1.1       root       86: #include <vm/vm_types.h>
                     87: #include <sys/types.h>
                     88: 
                     89: #ifdef MACH_DEBUG
                     90: #include <mach_debug/slab_info.h>
                     91: #endif
                     92: 
                     93: /*
                     94:  * Utility macros.
                     95:  */
                     96: #define P2ALIGNED(x, a) (((x) & ((a) - 1)) == 0)
                     97: #define ISP2(x)         P2ALIGNED(x, x)
                     98: #define P2ALIGN(x, a)   ((x) & -(a))
                     99: #define P2ROUND(x, a)   (-(-(x) & -(a)))
                    100: #define P2END(x, a)     (-(~(x) & -(a)))
                    101: #define likely(expr)    __builtin_expect(!!(expr), 1)
                    102: #define unlikely(expr)  __builtin_expect(!!(expr), 0)
                    103: 
                    104: /*
                    105:  * Minimum required alignment.
                    106:  */
                    107: #define KMEM_ALIGN_MIN 8
                    108: 
                    109: /*
                    110:  * Special buffer size under which slab data is unconditionnally allocated
                    111:  * from its associated slab.
                    112:  */
                    113: #define KMEM_BUF_SIZE_THRESHOLD (PAGE_SIZE / 8)
                    114: 
                    115: /*
                    116:  * Time (in ticks) between two garbage collection operations.
                    117:  */
                    118: #define KMEM_GC_INTERVAL (5 * hz)
                    119: 
                    120: /*
                    121:  * The transfer size of a CPU pool is computed by dividing the pool size by
                    122:  * this value.
                    123:  */
                    124: #define KMEM_CPU_POOL_TRANSFER_RATIO 2
                    125: 
                    126: /*
                    127:  * Redzone guard word.
                    128:  */
                    129: #ifdef __LP64__
                    130: #if _HOST_BIG_ENDIAN
                    131: #define KMEM_REDZONE_WORD 0xfeedfacefeedfaceUL
                    132: #else /* _HOST_BIG_ENDIAN */
                    133: #define KMEM_REDZONE_WORD 0xcefaedfecefaedfeUL
                    134: #endif /* _HOST_BIG_ENDIAN */
                    135: #else /* __LP64__ */
                    136: #if _HOST_BIG_ENDIAN
                    137: #define KMEM_REDZONE_WORD 0xfeedfaceUL
                    138: #else /* _HOST_BIG_ENDIAN */
                    139: #define KMEM_REDZONE_WORD 0xcefaedfeUL
                    140: #endif /* _HOST_BIG_ENDIAN */
                    141: #endif /* __LP64__ */
                    142: 
                    143: /*
                    144:  * Redzone byte for padding.
                    145:  */
                    146: #define KMEM_REDZONE_BYTE 0xbb
                    147: 
                    148: /*
                    149:  * Shift for the first kalloc cache size.
                    150:  */
                    151: #define KALLOC_FIRST_SHIFT 5
                    152: 
                    153: /*
                    154:  * Number of caches backing general purpose allocations.
                    155:  */
                    156: #define KALLOC_NR_CACHES 13
                    157: 
                    158: /*
                    159:  * Values the buftag state member can take.
                    160:  */
                    161: #ifdef __LP64__
                    162: #if _HOST_BIG_ENDIAN
                    163: #define KMEM_BUFTAG_ALLOC   0xa110c8eda110c8edUL
                    164: #define KMEM_BUFTAG_FREE    0xf4eeb10cf4eeb10cUL
                    165: #else /* _HOST_BIG_ENDIAN */
                    166: #define KMEM_BUFTAG_ALLOC   0xedc810a1edc810a1UL
                    167: #define KMEM_BUFTAG_FREE    0x0cb1eef40cb1eef4UL
                    168: #endif /* _HOST_BIG_ENDIAN */
                    169: #else /* __LP64__ */
                    170: #if _HOST_BIG_ENDIAN
                    171: #define KMEM_BUFTAG_ALLOC   0xa110c8edUL
                    172: #define KMEM_BUFTAG_FREE    0xf4eeb10cUL
                    173: #else /* _HOST_BIG_ENDIAN */
                    174: #define KMEM_BUFTAG_ALLOC   0xedc810a1UL
                    175: #define KMEM_BUFTAG_FREE    0x0cb1eef4UL
                    176: #endif /* _HOST_BIG_ENDIAN */
                    177: #endif /* __LP64__ */
                    178: 
                    179: /*
                    180:  * Free and uninitialized patterns.
                    181:  *
                    182:  * These values are unconditionnally 64-bit wide since buffers are at least
                    183:  * 8-byte aligned.
                    184:  */
                    185: #if _HOST_BIG_ENDIAN
                    186: #define KMEM_FREE_PATTERN   0xdeadbeefdeadbeefULL
                    187: #define KMEM_UNINIT_PATTERN 0xbaddcafebaddcafeULL
                    188: #else /* _HOST_BIG_ENDIAN */
                    189: #define KMEM_FREE_PATTERN   0xefbeaddeefbeaddeULL
                    190: #define KMEM_UNINIT_PATTERN 0xfecaddbafecaddbaULL
                    191: #endif /* _HOST_BIG_ENDIAN */
                    192: 
                    193: /*
                    194:  * Cache flags.
                    195:  *
                    196:  * The flags don't change once set and can be tested without locking.
                    197:  */
1.1.1.4   root      198: #define KMEM_CF_SLAB_EXTERNAL   0x01    /* Slab data is off slab */
                    199: #define KMEM_CF_PHYSMEM         0x02    /* Allocate from physical memory */
                    200: #define KMEM_CF_DIRECT          0x04    /* Direct buf-to-slab translation
                    201:                                            (implies !KMEM_CF_SLAB_EXTERNAL) */
                    202: #define KMEM_CF_USE_TREE        0x08    /* Use red-black tree to track slab
                    203:                                            data */
                    204: #define KMEM_CF_USE_PAGE        0x10    /* Use page private data to track slab
                    205:                                            data (implies KMEM_CF_SLAB_EXTERNAL
                    206:                                            and KMEM_CF_PHYSMEM) */
                    207: #define KMEM_CF_VERIFY          0x20    /* Debugging facilities enabled
                    208:                                            (implies KMEM_CF_USE_TREE) */
1.1       root      209: 
                    210: /*
                    211:  * Options for kmem_cache_alloc_verify().
                    212:  */
                    213: #define KMEM_AV_NOCONSTRUCT 0
                    214: #define KMEM_AV_CONSTRUCT   1
                    215: 
                    216: /*
                    217:  * Error codes for kmem_cache_error().
                    218:  */
                    219: #define KMEM_ERR_INVALID    0   /* Invalid address being freed */
                    220: #define KMEM_ERR_DOUBLEFREE 1   /* Freeing already free address */
                    221: #define KMEM_ERR_BUFTAG     2   /* Invalid buftag content */
                    222: #define KMEM_ERR_MODIFIED   3   /* Buffer modified while free */
                    223: #define KMEM_ERR_REDZONE    4   /* Redzone violation */
                    224: 
                    225: #if SLAB_USE_CPU_POOLS
                    226: /*
                    227:  * Available CPU pool types.
                    228:  *
                    229:  * For each entry, the CPU pool size applies from the entry buf_size
                    230:  * (excluded) up to (and including) the buf_size of the preceding entry.
                    231:  *
                    232:  * See struct kmem_cpu_pool_type for a description of the values.
                    233:  */
                    234: static struct kmem_cpu_pool_type kmem_cpu_pool_types[] = {
                    235:     {  32768,   1, 0,           NULL },
                    236:     {   4096,   8, CPU_L1_SIZE, NULL },
                    237:     {    256,  64, CPU_L1_SIZE, NULL },
                    238:     {      0, 128, CPU_L1_SIZE, NULL }
                    239: };
                    240: 
                    241: /*
                    242:  * Caches where CPU pool arrays are allocated from.
                    243:  */
                    244: static struct kmem_cache kmem_cpu_array_caches[ARRAY_SIZE(kmem_cpu_pool_types)];
                    245: #endif /* SLAB_USE_CPU_POOLS */
                    246: 
                    247: /*
                    248:  * Cache for off slab data.
                    249:  */
                    250: static struct kmem_cache kmem_slab_cache;
                    251: 
                    252: /*
                    253:  * General purpose caches array.
                    254:  */
                    255: static struct kmem_cache kalloc_caches[KALLOC_NR_CACHES];
                    256: 
                    257: /*
                    258:  * List of all caches managed by the allocator.
                    259:  */
                    260: static struct list kmem_cache_list;
                    261: static unsigned int kmem_nr_caches;
                    262: static simple_lock_data_t __attribute__((used)) kmem_cache_list_lock;
                    263: 
                    264: /*
                    265:  * Time of the last memory reclaim, in clock ticks.
                    266:  */
                    267: static unsigned long kmem_gc_last_tick;
                    268: 
                    269: #define kmem_error(format, ...)                         \
1.1.1.2   root      270:     panic("mem: error: %s(): " format "\n", __func__,   \
                    271:           ## __VA_ARGS__)
1.1       root      272: 
                    273: #define kmem_warn(format, ...)                              \
                    274:     printf("mem: warning: %s(): " format "\n", __func__,    \
                    275:            ## __VA_ARGS__)
                    276: 
                    277: #define kmem_print(format, ...) \
                    278:     printf(format "\n", ## __VA_ARGS__)
                    279: 
                    280: static void kmem_cache_error(struct kmem_cache *cache, void *buf, int error,
                    281:                              void *arg);
                    282: static void * kmem_cache_alloc_from_slab(struct kmem_cache *cache);
                    283: static void kmem_cache_free_to_slab(struct kmem_cache *cache, void *buf);
                    284: 
                    285: static void * kmem_buf_verify_bytes(void *buf, void *pattern, size_t size)
                    286: {
                    287:     char *ptr, *pattern_ptr, *end;
                    288: 
                    289:     end = buf + size;
                    290: 
                    291:     for (ptr = buf, pattern_ptr = pattern; ptr < end; ptr++, pattern_ptr++)
                    292:         if (*ptr != *pattern_ptr)
                    293:             return ptr;
                    294: 
                    295:     return NULL;
                    296: }
                    297: 
                    298: static void * kmem_buf_verify(void *buf, uint64_t pattern, vm_size_t size)
                    299: {
                    300:     uint64_t *ptr, *end;
                    301: 
                    302:     assert(P2ALIGNED((unsigned long)buf, sizeof(uint64_t)));
                    303:     assert(P2ALIGNED(size, sizeof(uint64_t)));
                    304: 
                    305:     end = buf + size;
                    306: 
                    307:     for (ptr = buf; ptr < end; ptr++)
                    308:         if (*ptr != pattern)
                    309:             return kmem_buf_verify_bytes(ptr, &pattern, sizeof(pattern));
                    310: 
                    311:     return NULL;
                    312: }
                    313: 
                    314: static void kmem_buf_fill(void *buf, uint64_t pattern, size_t size)
                    315: {
                    316:     uint64_t *ptr, *end;
                    317: 
                    318:     assert(P2ALIGNED((unsigned long)buf, sizeof(uint64_t)));
                    319:     assert(P2ALIGNED(size, sizeof(uint64_t)));
                    320: 
                    321:     end = buf + size;
                    322: 
                    323:     for (ptr = buf; ptr < end; ptr++)
                    324:         *ptr = pattern;
                    325: }
                    326: 
                    327: static void * kmem_buf_verify_fill(void *buf, uint64_t old, uint64_t new,
                    328:                                    size_t size)
                    329: {
                    330:     uint64_t *ptr, *end;
                    331: 
                    332:     assert(P2ALIGNED((unsigned long)buf, sizeof(uint64_t)));
                    333:     assert(P2ALIGNED(size, sizeof(uint64_t)));
                    334: 
                    335:     end = buf + size;
                    336: 
                    337:     for (ptr = buf; ptr < end; ptr++) {
                    338:         if (*ptr != old)
                    339:             return kmem_buf_verify_bytes(ptr, &old, sizeof(old));
                    340: 
                    341:         *ptr = new;
                    342:     }
                    343: 
                    344:     return NULL;
                    345: }
                    346: 
                    347: static inline union kmem_bufctl *
                    348: kmem_buf_to_bufctl(void *buf, struct kmem_cache *cache)
                    349: {
                    350:     return (union kmem_bufctl *)(buf + cache->bufctl_dist);
                    351: }
                    352: 
                    353: static inline struct kmem_buftag *
                    354: kmem_buf_to_buftag(void *buf, struct kmem_cache *cache)
                    355: {
                    356:     return (struct kmem_buftag *)(buf + cache->buftag_dist);
                    357: }
                    358: 
                    359: static inline void * kmem_bufctl_to_buf(union kmem_bufctl *bufctl,
                    360:                                         struct kmem_cache *cache)
                    361: {
                    362:     return (void *)bufctl - cache->bufctl_dist;
                    363: }
                    364: 
1.1.1.4   root      365: static vm_offset_t
                    366: kmem_pagealloc_physmem(vm_size_t size)
                    367: {
                    368:     struct vm_page *page;
                    369: 
                    370:     assert(size == PAGE_SIZE);
                    371: 
                    372:     for (;;) {
1.1.1.5 ! root      373:         page = vm_page_grab();
1.1.1.4   root      374: 
                    375:         if (page != NULL)
                    376:             break;
                    377: 
                    378:         VM_PAGE_WAIT(NULL);
                    379:     }
                    380: 
                    381:     return phystokv(vm_page_to_pa(page));
                    382: }
                    383: 
                    384: static void
                    385: kmem_pagefree_physmem(vm_offset_t addr, vm_size_t size)
                    386: {
                    387:     struct vm_page *page;
                    388: 
                    389:     assert(size == PAGE_SIZE);
                    390:     page = vm_page_lookup_pa(kvtophys(addr));
                    391:     assert(page != NULL);
1.1.1.5 ! root      392:     vm_page_release(page, FALSE, FALSE);
1.1.1.4   root      393: }
                    394: 
                    395: static vm_offset_t
                    396: kmem_pagealloc_virtual(vm_size_t size, vm_size_t align)
1.1       root      397: {
                    398:     vm_offset_t addr;
                    399:     kern_return_t kr;
                    400: 
1.1.1.4   root      401:     assert(size > PAGE_SIZE);
                    402:     size = vm_page_round(size);
                    403: 
                    404:     if (align <= PAGE_SIZE)
                    405:         kr = kmem_alloc_wired(kernel_map, &addr, size);
                    406:     else
                    407:         kr = kmem_alloc_aligned(kernel_map, &addr, size);
1.1       root      408: 
                    409:     if (kr != KERN_SUCCESS)
                    410:         return 0;
                    411: 
                    412:     return addr;
                    413: }
                    414: 
1.1.1.4   root      415: static void
                    416: kmem_pagefree_virtual(vm_offset_t addr, vm_size_t size)
1.1       root      417: {
1.1.1.4   root      418:     assert(size > PAGE_SIZE);
                    419:     size = vm_page_round(size);
                    420:     kmem_free(kernel_map, addr, size);
                    421: }
                    422: 
                    423: static vm_offset_t
                    424: kmem_pagealloc(vm_size_t size, vm_size_t align, int flags)
                    425: {
                    426:     assert(align <= size);
                    427:     return (flags & KMEM_CF_PHYSMEM)
                    428:            ? kmem_pagealloc_physmem(size)
                    429:            : kmem_pagealloc_virtual(size, align);
                    430: }
                    431: 
                    432: static void
                    433: kmem_pagefree(vm_offset_t addr, vm_size_t size, int flags)
                    434: {
                    435:     return (flags & KMEM_CF_PHYSMEM)
                    436:            ? kmem_pagefree_physmem(addr, size)
                    437:            : kmem_pagefree_virtual(addr, size);
1.1       root      438: }
                    439: 
                    440: static void kmem_slab_create_verify(struct kmem_slab *slab,
                    441:                                     struct kmem_cache *cache)
                    442: {
                    443:     struct kmem_buftag *buftag;
                    444:     size_t buf_size;
                    445:     unsigned long buffers;
                    446:     void *buf;
                    447: 
                    448:     buf_size = cache->buf_size;
                    449:     buf = slab->addr;
                    450:     buftag = kmem_buf_to_buftag(buf, cache);
                    451: 
                    452:     for (buffers = cache->bufs_per_slab; buffers != 0; buffers--) {
                    453:         kmem_buf_fill(buf, KMEM_FREE_PATTERN, cache->bufctl_dist);
                    454:         buftag->state = KMEM_BUFTAG_FREE;
                    455:         buf += buf_size;
                    456:         buftag = kmem_buf_to_buftag(buf, cache);
                    457:     }
                    458: }
                    459: 
                    460: /*
                    461:  * Create an empty slab for a cache.
                    462:  *
                    463:  * The caller must drop all locks before calling this function.
                    464:  */
                    465: static struct kmem_slab * kmem_slab_create(struct kmem_cache *cache,
                    466:                                            size_t color)
                    467: {
                    468:     struct kmem_slab *slab;
                    469:     union kmem_bufctl *bufctl;
                    470:     size_t buf_size;
                    471:     unsigned long buffers;
1.1.1.4   root      472:     vm_offset_t slab_buf;
1.1       root      473: 
1.1.1.4   root      474:     slab_buf = kmem_pagealloc(cache->slab_size, cache->align, cache->flags);
1.1       root      475: 
1.1.1.4   root      476:     if (slab_buf == 0)
1.1       root      477:         return NULL;
                    478: 
                    479:     if (cache->flags & KMEM_CF_SLAB_EXTERNAL) {
                    480:         slab = (struct kmem_slab *)kmem_cache_alloc(&kmem_slab_cache);
                    481: 
                    482:         if (slab == NULL) {
1.1.1.4   root      483:             kmem_pagefree(slab_buf, cache->slab_size, cache->flags);
1.1       root      484:             return NULL;
                    485:         }
1.1.1.4   root      486: 
                    487:         if (cache->flags & KMEM_CF_USE_PAGE) {
                    488:             struct vm_page *page;
                    489: 
                    490:             page = vm_page_lookup_pa(kvtophys(slab_buf));
                    491:             assert(page != NULL);
                    492:             vm_page_set_priv(page, slab);
                    493:         }
1.1       root      494:     } else {
                    495:         slab = (struct kmem_slab *)(slab_buf + cache->slab_size) - 1;
                    496:     }
                    497: 
1.1.1.5 ! root      498:     slab->cache = cache;
1.1       root      499:     list_node_init(&slab->list_node);
                    500:     rbtree_node_init(&slab->tree_node);
                    501:     slab->nr_refs = 0;
                    502:     slab->first_free = NULL;
1.1.1.4   root      503:     slab->addr = (void *)(slab_buf + color);
1.1       root      504: 
                    505:     buf_size = cache->buf_size;
                    506:     bufctl = kmem_buf_to_bufctl(slab->addr, cache);
                    507: 
                    508:     for (buffers = cache->bufs_per_slab; buffers != 0; buffers--) {
                    509:         bufctl->next = slab->first_free;
                    510:         slab->first_free = bufctl;
                    511:         bufctl = (union kmem_bufctl *)((void *)bufctl + buf_size);
                    512:     }
                    513: 
                    514:     if (cache->flags & KMEM_CF_VERIFY)
                    515:         kmem_slab_create_verify(slab, cache);
                    516: 
                    517:     return slab;
                    518: }
                    519: 
                    520: static void kmem_slab_destroy_verify(struct kmem_slab *slab,
                    521:                                      struct kmem_cache *cache)
                    522: {
                    523:     struct kmem_buftag *buftag;
                    524:     size_t buf_size;
                    525:     unsigned long buffers;
                    526:     void *buf, *addr;
                    527: 
                    528:     buf_size = cache->buf_size;
                    529:     buf = slab->addr;
                    530:     buftag = kmem_buf_to_buftag(buf, cache);
                    531: 
                    532:     for (buffers = cache->bufs_per_slab; buffers != 0; buffers--) {
                    533:         if (buftag->state != KMEM_BUFTAG_FREE)
                    534:             kmem_cache_error(cache, buf, KMEM_ERR_BUFTAG, buftag);
                    535: 
                    536:         addr = kmem_buf_verify(buf, KMEM_FREE_PATTERN, cache->bufctl_dist);
                    537: 
                    538:         if (addr != NULL)
                    539:             kmem_cache_error(cache, buf, KMEM_ERR_MODIFIED, addr);
                    540: 
                    541:         buf += buf_size;
                    542:         buftag = kmem_buf_to_buftag(buf, cache);
                    543:     }
                    544: }
                    545: 
                    546: /*
                    547:  * Destroy a slab.
                    548:  *
                    549:  * The caller must drop all locks before calling this function.
                    550:  */
                    551: static void kmem_slab_destroy(struct kmem_slab *slab, struct kmem_cache *cache)
                    552: {
                    553:     vm_offset_t slab_buf;
                    554: 
                    555:     assert(slab->nr_refs == 0);
                    556:     assert(slab->first_free != NULL);
                    557: 
                    558:     if (cache->flags & KMEM_CF_VERIFY)
                    559:         kmem_slab_destroy_verify(slab, cache);
                    560: 
                    561:     slab_buf = (vm_offset_t)P2ALIGN((unsigned long)slab->addr, PAGE_SIZE);
                    562: 
1.1.1.4   root      563:     if (cache->flags & KMEM_CF_SLAB_EXTERNAL) {
                    564:         if (cache->flags & KMEM_CF_USE_PAGE) {
                    565:             struct vm_page *page;
                    566: 
                    567:             /* Not strictly needed, but let's increase safety */
                    568:             page = vm_page_lookup_pa(kvtophys(slab_buf));
                    569:             assert(page != NULL);
                    570:             vm_page_set_priv(page, NULL);
                    571:         }
1.1       root      572: 
                    573:         kmem_cache_free(&kmem_slab_cache, (vm_offset_t)slab);
1.1.1.4   root      574:     }
1.1       root      575: 
1.1.1.4   root      576:     kmem_pagefree(slab_buf, cache->slab_size, cache->flags);
1.1       root      577: }
                    578: 
                    579: static inline int kmem_slab_cmp_lookup(const void *addr,
                    580:                                        const struct rbtree_node *node)
                    581: {
                    582:     struct kmem_slab *slab;
                    583: 
                    584:     slab = rbtree_entry(node, struct kmem_slab, tree_node);
                    585: 
                    586:     if (addr == slab->addr)
                    587:         return 0;
                    588:     else if (addr < slab->addr)
                    589:         return -1;
                    590:     else
                    591:         return 1;
                    592: }
                    593: 
                    594: static inline int kmem_slab_cmp_insert(const struct rbtree_node *a,
                    595:                                        const struct rbtree_node *b)
                    596: {
                    597:     struct kmem_slab *slab;
                    598: 
                    599:     slab = rbtree_entry(a, struct kmem_slab, tree_node);
                    600:     return kmem_slab_cmp_lookup(slab->addr, b);
                    601: }
                    602: 
                    603: #if SLAB_USE_CPU_POOLS
                    604: static void kmem_cpu_pool_init(struct kmem_cpu_pool *cpu_pool,
                    605:                                struct kmem_cache *cache)
                    606: {
                    607:     simple_lock_init(&cpu_pool->lock);
                    608:     cpu_pool->flags = cache->flags;
                    609:     cpu_pool->size = 0;
                    610:     cpu_pool->transfer_size = 0;
                    611:     cpu_pool->nr_objs = 0;
                    612:     cpu_pool->array = NULL;
                    613: }
                    614: 
                    615: /*
                    616:  * Return a CPU pool.
                    617:  *
                    618:  * This function will generally return the pool matching the CPU running the
                    619:  * calling thread. Because of context switches and thread migration, the
                    620:  * caller might be running on another processor after this function returns.
                    621:  * Although not optimal, this should rarely happen, and it doesn't affect the
                    622:  * allocator operations in any other way, as CPU pools are always valid, and
                    623:  * their access is serialized by a lock.
                    624:  */
                    625: static inline struct kmem_cpu_pool * kmem_cpu_pool_get(struct kmem_cache *cache)
                    626: {
                    627:     return &cache->cpu_pools[cpu_number()];
                    628: }
                    629: 
                    630: static inline void kmem_cpu_pool_build(struct kmem_cpu_pool *cpu_pool,
                    631:                                        struct kmem_cache *cache, void **array)
                    632: {
                    633:     cpu_pool->size = cache->cpu_pool_type->array_size;
                    634:     cpu_pool->transfer_size = (cpu_pool->size
                    635:                                + KMEM_CPU_POOL_TRANSFER_RATIO - 1)
                    636:                               / KMEM_CPU_POOL_TRANSFER_RATIO;
                    637:     cpu_pool->array = array;
                    638: }
                    639: 
                    640: static inline void * kmem_cpu_pool_pop(struct kmem_cpu_pool *cpu_pool)
                    641: {
                    642:     cpu_pool->nr_objs--;
                    643:     return cpu_pool->array[cpu_pool->nr_objs];
                    644: }
                    645: 
                    646: static inline void kmem_cpu_pool_push(struct kmem_cpu_pool *cpu_pool, void *obj)
                    647: {
                    648:     cpu_pool->array[cpu_pool->nr_objs] = obj;
                    649:     cpu_pool->nr_objs++;
                    650: }
                    651: 
                    652: static int kmem_cpu_pool_fill(struct kmem_cpu_pool *cpu_pool,
                    653:                               struct kmem_cache *cache)
                    654: {
                    655:     kmem_cache_ctor_t ctor;
                    656:     void *buf;
                    657:     int i;
                    658: 
                    659:     ctor = (cpu_pool->flags & KMEM_CF_VERIFY) ? NULL : cache->ctor;
                    660: 
                    661:     simple_lock(&cache->lock);
                    662: 
                    663:     for (i = 0; i < cpu_pool->transfer_size; i++) {
                    664:         buf = kmem_cache_alloc_from_slab(cache);
                    665: 
                    666:         if (buf == NULL)
                    667:             break;
                    668: 
                    669:         if (ctor != NULL)
                    670:             ctor(buf);
                    671: 
                    672:         kmem_cpu_pool_push(cpu_pool, buf);
                    673:     }
                    674: 
                    675:     simple_unlock(&cache->lock);
                    676: 
                    677:     return i;
                    678: }
                    679: 
                    680: static void kmem_cpu_pool_drain(struct kmem_cpu_pool *cpu_pool,
                    681:                                 struct kmem_cache *cache)
                    682: {
                    683:     void *obj;
                    684:     int i;
                    685: 
                    686:     simple_lock(&cache->lock);
                    687: 
                    688:     for (i = cpu_pool->transfer_size; i > 0; i--) {
                    689:         obj = kmem_cpu_pool_pop(cpu_pool);
                    690:         kmem_cache_free_to_slab(cache, obj);
                    691:     }
                    692: 
                    693:     simple_unlock(&cache->lock);
                    694: }
                    695: #endif /* SLAB_USE_CPU_POOLS */
                    696: 
                    697: static void kmem_cache_error(struct kmem_cache *cache, void *buf, int error,
                    698:                              void *arg)
                    699: {
                    700:     struct kmem_buftag *buftag;
                    701: 
1.1.1.2   root      702:     kmem_warn("cache: %s, buffer: %p", cache->name, (void *)buf);
1.1       root      703: 
                    704:     switch(error) {
                    705:     case KMEM_ERR_INVALID:
                    706:         kmem_error("freeing invalid address");
                    707:         break;
                    708:     case KMEM_ERR_DOUBLEFREE:
                    709:         kmem_error("attempting to free the same address twice");
                    710:         break;
                    711:     case KMEM_ERR_BUFTAG:
                    712:         buftag = arg;
                    713:         kmem_error("invalid buftag content, buftag state: %p",
                    714:                    (void *)buftag->state);
                    715:         break;
                    716:     case KMEM_ERR_MODIFIED:
                    717:         kmem_error("free buffer modified, fault address: %p, "
                    718:                    "offset in buffer: %td", arg, arg - buf);
                    719:         break;
                    720:     case KMEM_ERR_REDZONE:
                    721:         kmem_error("write beyond end of buffer, fault address: %p, "
                    722:                    "offset in buffer: %td", arg, arg - buf);
                    723:         break;
                    724:     default:
                    725:         kmem_error("unknown error");
                    726:     }
                    727: 
                    728:     /*
                    729:      * Never reached.
                    730:      */
                    731: }
                    732: 
                    733: /*
1.1.1.4   root      734:  * Compute properties such as slab size for the given cache.
1.1       root      735:  *
                    736:  * Once the slab size is known, this function sets the related properties
1.1.1.4   root      737:  * (buffers per slab and maximum color). It can also set some KMEM_CF_xxx
                    738:  * flags depending on the resulting layout.
1.1       root      739:  */
1.1.1.4   root      740: static void kmem_cache_compute_properties(struct kmem_cache *cache, int flags)
1.1       root      741: {
1.1.1.4   root      742:     size_t size, waste;
                    743:     int embed;
1.1       root      744: 
1.1.1.4   root      745:     if (cache->buf_size < KMEM_BUF_SIZE_THRESHOLD)
1.1       root      746:         flags |= KMEM_CACHE_NOOFFSLAB;
                    747: 
1.1.1.4   root      748:     cache->slab_size = PAGE_SIZE;
1.1       root      749: 
1.1.1.4   root      750:     for (;;) {
1.1       root      751:         if (flags & KMEM_CACHE_NOOFFSLAB)
                    752:             embed = 1;
1.1.1.4   root      753:         else {
                    754:             waste = cache->slab_size % cache->buf_size;
                    755:             embed = (sizeof(struct kmem_slab) <= waste);
1.1       root      756:         }
                    757: 
1.1.1.4   root      758:         size = cache->slab_size;
1.1       root      759: 
1.1.1.4   root      760:         if (embed)
                    761:             size -= sizeof(struct kmem_slab);
1.1       root      762: 
1.1.1.4   root      763:         if (size >= cache->buf_size)
                    764:             break;
                    765: 
                    766:         cache->slab_size += PAGE_SIZE;
                    767:     }
                    768: 
                    769:     cache->bufs_per_slab = size / cache->buf_size;
                    770:     cache->color_max = size % cache->buf_size;
1.1       root      771: 
                    772:     if (cache->color_max >= PAGE_SIZE)
1.1.1.4   root      773:         cache->color_max = 0;
                    774: 
                    775:     if (!embed)
                    776:         cache->flags |= KMEM_CF_SLAB_EXTERNAL;
                    777: 
                    778:     if ((flags & KMEM_CACHE_PHYSMEM) || (cache->slab_size == PAGE_SIZE)) {
                    779:         cache->flags |= KMEM_CF_PHYSMEM;
1.1       root      780: 
1.1.1.4   root      781:         /*
                    782:          * Avoid using larger-than-page slabs backed by the direct physical
                    783:          * mapping to completely prevent physical memory fragmentation from
                    784:          * making slab allocations fail.
                    785:          */
                    786:         if (cache->slab_size != PAGE_SIZE)
                    787:             panic("slab: invalid cache parameters");
                    788:     }
                    789: 
                    790:     if (cache->flags & KMEM_CF_VERIFY)
                    791:         cache->flags |= KMEM_CF_USE_TREE;
                    792: 
                    793:     if (cache->flags & KMEM_CF_SLAB_EXTERNAL) {
                    794:         if (cache->flags & KMEM_CF_PHYSMEM)
                    795:             cache->flags |= KMEM_CF_USE_PAGE;
                    796:         else
                    797:             cache->flags |= KMEM_CF_USE_TREE;
                    798:     } else {
1.1       root      799:         if (cache->slab_size == PAGE_SIZE)
                    800:             cache->flags |= KMEM_CF_DIRECT;
1.1.1.4   root      801:         else
                    802:             cache->flags |= KMEM_CF_USE_TREE;
1.1       root      803:     }
                    804: }
                    805: 
                    806: void kmem_cache_init(struct kmem_cache *cache, const char *name,
1.1.1.4   root      807:                      size_t obj_size, size_t align,
                    808:                      kmem_cache_ctor_t ctor, int flags)
1.1       root      809: {
                    810: #if SLAB_USE_CPU_POOLS
                    811:     struct kmem_cpu_pool_type *cpu_pool_type;
                    812:     size_t i;
                    813: #endif /* SLAB_USE_CPU_POOLS */
                    814:     size_t buf_size;
                    815: 
                    816: #if SLAB_VERIFY
                    817:     cache->flags = KMEM_CF_VERIFY;
                    818: #else /* SLAB_VERIFY */
                    819:     cache->flags = 0;
                    820: #endif /* SLAB_VERIFY */
                    821: 
                    822:     if (flags & KMEM_CACHE_VERIFY)
                    823:         cache->flags |= KMEM_CF_VERIFY;
                    824: 
                    825:     if (align < KMEM_ALIGN_MIN)
                    826:         align = KMEM_ALIGN_MIN;
                    827: 
                    828:     assert(obj_size > 0);
                    829:     assert(ISP2(align));
                    830: 
                    831:     buf_size = P2ROUND(obj_size, align);
                    832: 
                    833:     simple_lock_init(&cache->lock);
                    834:     list_node_init(&cache->node);
                    835:     list_init(&cache->partial_slabs);
                    836:     list_init(&cache->free_slabs);
                    837:     rbtree_init(&cache->active_slabs);
                    838:     cache->obj_size = obj_size;
                    839:     cache->align = align;
                    840:     cache->buf_size = buf_size;
                    841:     cache->bufctl_dist = buf_size - sizeof(union kmem_bufctl);
                    842:     cache->color = 0;
                    843:     cache->nr_objs = 0;
                    844:     cache->nr_bufs = 0;
                    845:     cache->nr_slabs = 0;
                    846:     cache->nr_free_slabs = 0;
                    847:     cache->ctor = ctor;
                    848:     strncpy(cache->name, name, sizeof(cache->name));
                    849:     cache->name[sizeof(cache->name) - 1] = '\0';
                    850:     cache->buftag_dist = 0;
                    851:     cache->redzone_pad = 0;
                    852: 
                    853:     if (cache->flags & KMEM_CF_VERIFY) {
                    854:         cache->bufctl_dist = buf_size;
                    855:         cache->buftag_dist = cache->bufctl_dist + sizeof(union kmem_bufctl);
                    856:         cache->redzone_pad = cache->bufctl_dist - cache->obj_size;
                    857:         buf_size += sizeof(union kmem_bufctl) + sizeof(struct kmem_buftag);
                    858:         buf_size = P2ROUND(buf_size, align);
                    859:         cache->buf_size = buf_size;
                    860:     }
                    861: 
1.1.1.4   root      862:     kmem_cache_compute_properties(cache, flags);
1.1       root      863: 
                    864: #if SLAB_USE_CPU_POOLS
                    865:     for (cpu_pool_type = kmem_cpu_pool_types;
                    866:          buf_size <= cpu_pool_type->buf_size;
                    867:          cpu_pool_type++);
                    868: 
                    869:     cache->cpu_pool_type = cpu_pool_type;
                    870: 
                    871:     for (i = 0; i < ARRAY_SIZE(cache->cpu_pools); i++)
                    872:         kmem_cpu_pool_init(&cache->cpu_pools[i], cache);
                    873: #endif /* SLAB_USE_CPU_POOLS */
                    874: 
                    875:     simple_lock(&kmem_cache_list_lock);
                    876:     list_insert_tail(&kmem_cache_list, &cache->node);
                    877:     kmem_nr_caches++;
                    878:     simple_unlock(&kmem_cache_list_lock);
                    879: }
                    880: 
                    881: static inline int kmem_cache_empty(struct kmem_cache *cache)
                    882: {
                    883:     return cache->nr_objs == cache->nr_bufs;
                    884: }
                    885: 
                    886: static int kmem_cache_grow(struct kmem_cache *cache)
                    887: {
                    888:     struct kmem_slab *slab;
                    889:     size_t color;
                    890:     int empty;
                    891: 
                    892:     simple_lock(&cache->lock);
                    893: 
                    894:     if (!kmem_cache_empty(cache)) {
                    895:         simple_unlock(&cache->lock);
                    896:         return 1;
                    897:     }
                    898: 
                    899:     color = cache->color;
                    900:     cache->color += cache->align;
                    901: 
                    902:     if (cache->color > cache->color_max)
                    903:         cache->color = 0;
                    904: 
                    905:     simple_unlock(&cache->lock);
                    906: 
                    907:     slab = kmem_slab_create(cache, color);
                    908: 
                    909:     simple_lock(&cache->lock);
                    910: 
                    911:     if (slab != NULL) {
                    912:         list_insert_head(&cache->free_slabs, &slab->list_node);
                    913:         cache->nr_bufs += cache->bufs_per_slab;
                    914:         cache->nr_slabs++;
                    915:         cache->nr_free_slabs++;
                    916:     }
                    917: 
                    918:     /*
                    919:      * Even if our slab creation failed, another thread might have succeeded
                    920:      * in growing the cache.
                    921:      */
                    922:     empty = kmem_cache_empty(cache);
                    923: 
                    924:     simple_unlock(&cache->lock);
                    925: 
                    926:     return !empty;
                    927: }
                    928: 
1.1.1.5 ! root      929: static void kmem_cache_reap(struct kmem_cache *cache, struct list *dead_slabs)
1.1       root      930: {
                    931:     simple_lock(&cache->lock);
1.1.1.5 ! root      932: 
        !           933:     list_concat(dead_slabs, &cache->free_slabs);
1.1       root      934:     list_init(&cache->free_slabs);
1.1.1.5 ! root      935:     cache->nr_bufs -= cache->bufs_per_slab * cache->nr_free_slabs;
        !           936:     cache->nr_slabs -= cache->nr_free_slabs;
1.1       root      937:     cache->nr_free_slabs = 0;
                    938: 
1.1.1.5 ! root      939:     simple_unlock(&cache->lock);
1.1       root      940: }
                    941: 
                    942: /*
                    943:  * Allocate a raw (unconstructed) buffer from the slab layer of a cache.
                    944:  *
                    945:  * The cache must be locked before calling this function.
                    946:  */
                    947: static void * kmem_cache_alloc_from_slab(struct kmem_cache *cache)
                    948: {
                    949:     struct kmem_slab *slab;
                    950:     union kmem_bufctl *bufctl;
                    951: 
                    952:     if (!list_empty(&cache->partial_slabs))
                    953:         slab = list_first_entry(&cache->partial_slabs, struct kmem_slab,
                    954:                                 list_node);
                    955:     else if (!list_empty(&cache->free_slabs))
                    956:         slab = list_first_entry(&cache->free_slabs, struct kmem_slab,
                    957:                                 list_node);
                    958:     else
                    959:         return NULL;
                    960: 
                    961:     bufctl = slab->first_free;
                    962:     assert(bufctl != NULL);
                    963:     slab->first_free = bufctl->next;
                    964:     slab->nr_refs++;
                    965:     cache->nr_objs++;
                    966: 
                    967:     if (slab->nr_refs == cache->bufs_per_slab) {
                    968:         /* The slab has become complete */
                    969:         list_remove(&slab->list_node);
                    970: 
                    971:         if (slab->nr_refs == 1)
                    972:             cache->nr_free_slabs--;
                    973:     } else if (slab->nr_refs == 1) {
                    974:         /*
                    975:          * The slab has become partial. Insert the new slab at the end of
                    976:          * the list to reduce fragmentation.
                    977:          */
                    978:         list_remove(&slab->list_node);
                    979:         list_insert_tail(&cache->partial_slabs, &slab->list_node);
                    980:         cache->nr_free_slabs--;
                    981:     }
                    982: 
1.1.1.4   root      983:     if ((slab->nr_refs == 1) && (cache->flags & KMEM_CF_USE_TREE))
1.1       root      984:         rbtree_insert(&cache->active_slabs, &slab->tree_node,
                    985:                       kmem_slab_cmp_insert);
                    986: 
                    987:     return kmem_bufctl_to_buf(bufctl, cache);
                    988: }
                    989: 
                    990: /*
                    991:  * Release a buffer to the slab layer of a cache.
                    992:  *
                    993:  * The cache must be locked before calling this function.
                    994:  */
                    995: static void kmem_cache_free_to_slab(struct kmem_cache *cache, void *buf)
                    996: {
                    997:     struct kmem_slab *slab;
                    998:     union kmem_bufctl *bufctl;
                    999: 
                   1000:     if (cache->flags & KMEM_CF_DIRECT) {
                   1001:         assert(cache->slab_size == PAGE_SIZE);
                   1002:         slab = (struct kmem_slab *)P2END((unsigned long)buf, cache->slab_size)
                   1003:                - 1;
1.1.1.4   root     1004:     } else if (cache->flags & KMEM_CF_USE_PAGE) {
                   1005:         struct vm_page *page;
                   1006: 
                   1007:         page = vm_page_lookup_pa(kvtophys((vm_offset_t)buf));
                   1008:         assert(page != NULL);
                   1009:         slab = vm_page_get_priv(page);
1.1       root     1010:     } else {
                   1011:         struct rbtree_node *node;
                   1012: 
1.1.1.4   root     1013:         assert(cache->flags & KMEM_CF_USE_TREE);
1.1       root     1014:         node = rbtree_lookup_nearest(&cache->active_slabs, buf,
                   1015:                                      kmem_slab_cmp_lookup, RBTREE_LEFT);
                   1016:         assert(node != NULL);
                   1017:         slab = rbtree_entry(node, struct kmem_slab, tree_node);
                   1018:     }
                   1019: 
1.1.1.4   root     1020:     assert((unsigned long)buf >= (unsigned long)slab->addr);
                   1021:     assert(((unsigned long)buf + cache->buf_size)
                   1022:            <= vm_page_trunc((unsigned long)slab->addr + cache->slab_size));
                   1023: 
1.1       root     1024:     assert(slab->nr_refs >= 1);
                   1025:     assert(slab->nr_refs <= cache->bufs_per_slab);
                   1026:     bufctl = kmem_buf_to_bufctl(buf, cache);
                   1027:     bufctl->next = slab->first_free;
                   1028:     slab->first_free = bufctl;
                   1029:     slab->nr_refs--;
                   1030:     cache->nr_objs--;
                   1031: 
                   1032:     if (slab->nr_refs == 0) {
                   1033:         /* The slab has become free */
                   1034: 
1.1.1.4   root     1035:         if (cache->flags & KMEM_CF_USE_TREE)
1.1       root     1036:             rbtree_remove(&cache->active_slabs, &slab->tree_node);
                   1037: 
                   1038:         if (cache->bufs_per_slab > 1)
                   1039:             list_remove(&slab->list_node);
                   1040: 
                   1041:         list_insert_head(&cache->free_slabs, &slab->list_node);
                   1042:         cache->nr_free_slabs++;
                   1043:     } else if (slab->nr_refs == (cache->bufs_per_slab - 1)) {
                   1044:         /* The slab has become partial */
                   1045:         list_insert_head(&cache->partial_slabs, &slab->list_node);
                   1046:     }
                   1047: }
                   1048: 
                   1049: static void kmem_cache_alloc_verify(struct kmem_cache *cache, void *buf,
                   1050:                                     int construct)
                   1051: {
                   1052:     struct kmem_buftag *buftag;
                   1053:     union kmem_bufctl *bufctl;
                   1054:     void *addr;
                   1055: 
                   1056:     buftag = kmem_buf_to_buftag(buf, cache);
                   1057: 
                   1058:     if (buftag->state != KMEM_BUFTAG_FREE)
                   1059:         kmem_cache_error(cache, buf, KMEM_ERR_BUFTAG, buftag);
                   1060: 
                   1061:     addr = kmem_buf_verify_fill(buf, KMEM_FREE_PATTERN, KMEM_UNINIT_PATTERN,
                   1062:                                 cache->bufctl_dist);
                   1063: 
                   1064:     if (addr != NULL)
                   1065:         kmem_cache_error(cache, buf, KMEM_ERR_MODIFIED, addr);
                   1066: 
                   1067:     addr = buf + cache->obj_size;
                   1068:     memset(addr, KMEM_REDZONE_BYTE, cache->redzone_pad);
                   1069: 
                   1070:     bufctl = kmem_buf_to_bufctl(buf, cache);
                   1071:     bufctl->redzone = KMEM_REDZONE_WORD;
                   1072:     buftag->state = KMEM_BUFTAG_ALLOC;
                   1073: 
                   1074:     if (construct && (cache->ctor != NULL))
                   1075:         cache->ctor(buf);
                   1076: }
                   1077: 
                   1078: vm_offset_t kmem_cache_alloc(struct kmem_cache *cache)
                   1079: {
                   1080:     int filled;
                   1081:     void *buf;
                   1082: 
                   1083: #if SLAB_USE_CPU_POOLS
                   1084:     struct kmem_cpu_pool *cpu_pool;
                   1085: 
                   1086:     cpu_pool = kmem_cpu_pool_get(cache);
                   1087: 
                   1088:     if (cpu_pool->flags & KMEM_CF_NO_CPU_POOL)
                   1089:         goto slab_alloc;
                   1090: 
                   1091:     simple_lock(&cpu_pool->lock);
                   1092: 
                   1093: fast_alloc:
                   1094:     if (likely(cpu_pool->nr_objs > 0)) {
                   1095:         buf = kmem_cpu_pool_pop(cpu_pool);
                   1096:         simple_unlock(&cpu_pool->lock);
                   1097: 
                   1098:         if (cpu_pool->flags & KMEM_CF_VERIFY)
                   1099:             kmem_cache_alloc_verify(cache, buf, KMEM_AV_CONSTRUCT);
                   1100: 
                   1101:         return (vm_offset_t)buf;
                   1102:     }
                   1103: 
                   1104:     if (cpu_pool->array != NULL) {
                   1105:         filled = kmem_cpu_pool_fill(cpu_pool, cache);
                   1106: 
                   1107:         if (!filled) {
                   1108:             simple_unlock(&cpu_pool->lock);
                   1109: 
                   1110:             filled = kmem_cache_grow(cache);
                   1111: 
                   1112:             if (!filled)
                   1113:                 return 0;
                   1114: 
                   1115:             simple_lock(&cpu_pool->lock);
                   1116:         }
                   1117: 
                   1118:         goto fast_alloc;
                   1119:     }
                   1120: 
                   1121:     simple_unlock(&cpu_pool->lock);
                   1122: #endif /* SLAB_USE_CPU_POOLS */
                   1123: 
                   1124: slab_alloc:
                   1125:     simple_lock(&cache->lock);
                   1126:     buf = kmem_cache_alloc_from_slab(cache);
                   1127:     simple_unlock(&cache->lock);
                   1128: 
                   1129:     if (buf == NULL) {
                   1130:         filled = kmem_cache_grow(cache);
                   1131: 
                   1132:         if (!filled)
                   1133:             return 0;
                   1134: 
                   1135:         goto slab_alloc;
                   1136:     }
                   1137: 
                   1138:     if (cache->flags & KMEM_CF_VERIFY)
                   1139:         kmem_cache_alloc_verify(cache, buf, KMEM_AV_NOCONSTRUCT);
                   1140: 
                   1141:     if (cache->ctor != NULL)
                   1142:         cache->ctor(buf);
                   1143: 
                   1144:     return (vm_offset_t)buf;
                   1145: }
                   1146: 
                   1147: static void kmem_cache_free_verify(struct kmem_cache *cache, void *buf)
                   1148: {
                   1149:     struct rbtree_node *node;
                   1150:     struct kmem_buftag *buftag;
                   1151:     struct kmem_slab *slab;
                   1152:     union kmem_bufctl *bufctl;
                   1153:     unsigned char *redzone_byte;
                   1154:     unsigned long slabend;
                   1155: 
1.1.1.4   root     1156:     assert(cache->flags & KMEM_CF_USE_TREE);
                   1157: 
1.1       root     1158:     simple_lock(&cache->lock);
                   1159:     node = rbtree_lookup_nearest(&cache->active_slabs, buf,
                   1160:                                  kmem_slab_cmp_lookup, RBTREE_LEFT);
                   1161:     simple_unlock(&cache->lock);
                   1162: 
                   1163:     if (node == NULL)
                   1164:         kmem_cache_error(cache, buf, KMEM_ERR_INVALID, NULL);
                   1165: 
                   1166:     slab = rbtree_entry(node, struct kmem_slab, tree_node);
                   1167:     slabend = P2ALIGN((unsigned long)slab->addr + cache->slab_size, PAGE_SIZE);
                   1168: 
                   1169:     if ((unsigned long)buf >= slabend)
                   1170:         kmem_cache_error(cache, buf, KMEM_ERR_INVALID, NULL);
                   1171: 
                   1172:     if ((((unsigned long)buf - (unsigned long)slab->addr) % cache->buf_size)
                   1173:         != 0)
                   1174:         kmem_cache_error(cache, buf, KMEM_ERR_INVALID, NULL);
                   1175: 
                   1176:     /*
                   1177:      * As the buffer address is valid, accessing its buftag is safe.
                   1178:      */
                   1179:     buftag = kmem_buf_to_buftag(buf, cache);
                   1180: 
                   1181:     if (buftag->state != KMEM_BUFTAG_ALLOC) {
                   1182:         if (buftag->state == KMEM_BUFTAG_FREE)
                   1183:             kmem_cache_error(cache, buf, KMEM_ERR_DOUBLEFREE, NULL);
                   1184:         else
                   1185:             kmem_cache_error(cache, buf, KMEM_ERR_BUFTAG, buftag);
                   1186:     }
                   1187: 
                   1188:     redzone_byte = buf + cache->obj_size;
                   1189:     bufctl = kmem_buf_to_bufctl(buf, cache);
                   1190: 
                   1191:     while (redzone_byte < (unsigned char *)bufctl) {
                   1192:         if (*redzone_byte != KMEM_REDZONE_BYTE)
                   1193:             kmem_cache_error(cache, buf, KMEM_ERR_REDZONE, redzone_byte);
                   1194: 
                   1195:         redzone_byte++;
                   1196:     }
                   1197: 
                   1198:     if (bufctl->redzone != KMEM_REDZONE_WORD) {
                   1199:         unsigned long word;
                   1200: 
                   1201:         word = KMEM_REDZONE_WORD;
                   1202:         redzone_byte = kmem_buf_verify_bytes(&bufctl->redzone, &word,
                   1203:                                              sizeof(bufctl->redzone));
                   1204:         kmem_cache_error(cache, buf, KMEM_ERR_REDZONE, redzone_byte);
                   1205:     }
                   1206: 
                   1207:     kmem_buf_fill(buf, KMEM_FREE_PATTERN, cache->bufctl_dist);
                   1208:     buftag->state = KMEM_BUFTAG_FREE;
                   1209: }
                   1210: 
                   1211: void kmem_cache_free(struct kmem_cache *cache, vm_offset_t obj)
                   1212: {
                   1213: #if SLAB_USE_CPU_POOLS
                   1214:     struct kmem_cpu_pool *cpu_pool;
                   1215:     void **array;
                   1216: 
                   1217:     cpu_pool = kmem_cpu_pool_get(cache);
                   1218: 
                   1219:     if (cpu_pool->flags & KMEM_CF_VERIFY) {
                   1220: #else /* SLAB_USE_CPU_POOLS */
                   1221:     if (cache->flags & KMEM_CF_VERIFY) {
                   1222: #endif /* SLAB_USE_CPU_POOLS */
                   1223:         kmem_cache_free_verify(cache, (void *)obj);
                   1224:     }
                   1225: 
                   1226: #if SLAB_USE_CPU_POOLS
                   1227:     if (cpu_pool->flags & KMEM_CF_NO_CPU_POOL)
                   1228:         goto slab_free;
                   1229: 
                   1230:     simple_lock(&cpu_pool->lock);
                   1231: 
                   1232: fast_free:
                   1233:     if (likely(cpu_pool->nr_objs < cpu_pool->size)) {
                   1234:         kmem_cpu_pool_push(cpu_pool, (void *)obj);
                   1235:         simple_unlock(&cpu_pool->lock);
                   1236:         return;
                   1237:     }
                   1238: 
                   1239:     if (cpu_pool->array != NULL) {
                   1240:         kmem_cpu_pool_drain(cpu_pool, cache);
                   1241:         goto fast_free;
                   1242:     }
                   1243: 
                   1244:     simple_unlock(&cpu_pool->lock);
                   1245: 
                   1246:     array = (void *)kmem_cache_alloc(cache->cpu_pool_type->array_cache);
                   1247: 
                   1248:     if (array != NULL) {
                   1249:         simple_lock(&cpu_pool->lock);
                   1250: 
                   1251:         /*
                   1252:          * Another thread may have built the CPU pool while the lock was
                   1253:          * dropped.
                   1254:          */
                   1255:         if (cpu_pool->array != NULL) {
                   1256:             simple_unlock(&cpu_pool->lock);
                   1257:             kmem_cache_free(cache->cpu_pool_type->array_cache,
                   1258:                             (vm_offset_t)array);
                   1259:             simple_lock(&cpu_pool->lock);
                   1260:             goto fast_free;
                   1261:         }
                   1262: 
                   1263:         kmem_cpu_pool_build(cpu_pool, cache, array);
                   1264:         goto fast_free;
                   1265:     }
                   1266: 
                   1267: slab_free:
                   1268: #endif /* SLAB_USE_CPU_POOLS */
                   1269: 
                   1270:     simple_lock(&cache->lock);
                   1271:     kmem_cache_free_to_slab(cache, (void *)obj);
                   1272:     simple_unlock(&cache->lock);
                   1273: }
                   1274: 
                   1275: void slab_collect(void)
                   1276: {
                   1277:     struct kmem_cache *cache;
1.1.1.5 ! root     1278:     struct kmem_slab *slab;
        !          1279:     struct list dead_slabs;
1.1       root     1280: 
                   1281:     if (elapsed_ticks <= (kmem_gc_last_tick + KMEM_GC_INTERVAL))
                   1282:         return;
                   1283: 
                   1284:     kmem_gc_last_tick = elapsed_ticks;
                   1285: 
1.1.1.5 ! root     1286:     list_init(&dead_slabs);
        !          1287: 
1.1       root     1288:     simple_lock(&kmem_cache_list_lock);
                   1289: 
                   1290:     list_for_each_entry(&kmem_cache_list, cache, node)
1.1.1.5 ! root     1291:         kmem_cache_reap(cache, &dead_slabs);
1.1       root     1292: 
                   1293:     simple_unlock(&kmem_cache_list_lock);
1.1.1.5 ! root     1294: 
        !          1295:     while (!list_empty(&dead_slabs)) {
        !          1296:         slab = list_first_entry(&dead_slabs, struct kmem_slab, list_node);
        !          1297:         list_remove(&slab->list_node);
        !          1298:         kmem_slab_destroy(slab, slab->cache);
        !          1299:     }
1.1       root     1300: }
                   1301: 
                   1302: void slab_bootstrap(void)
                   1303: {
                   1304:     /* Make sure a bufctl can always be stored in a buffer */
                   1305:     assert(sizeof(union kmem_bufctl) <= KMEM_ALIGN_MIN);
                   1306: 
                   1307:     list_init(&kmem_cache_list);
                   1308:     simple_lock_init(&kmem_cache_list_lock);
                   1309: }
                   1310: 
                   1311: void slab_init(void)
                   1312: {
                   1313: #if SLAB_USE_CPU_POOLS
                   1314:     struct kmem_cpu_pool_type *cpu_pool_type;
                   1315:     char name[KMEM_CACHE_NAME_SIZE];
                   1316:     size_t i, size;
                   1317: #endif /* SLAB_USE_CPU_POOLS */
                   1318: 
                   1319: #if SLAB_USE_CPU_POOLS
                   1320:     for (i = 0; i < ARRAY_SIZE(kmem_cpu_pool_types); i++) {
                   1321:         cpu_pool_type = &kmem_cpu_pool_types[i];
                   1322:         cpu_pool_type->array_cache = &kmem_cpu_array_caches[i];
                   1323:         sprintf(name, "kmem_cpu_array_%d", cpu_pool_type->array_size);
                   1324:         size = sizeof(void *) * cpu_pool_type->array_size;
                   1325:         kmem_cache_init(cpu_pool_type->array_cache, name, size,
1.1.1.4   root     1326:                         cpu_pool_type->array_align, NULL, 0);
1.1       root     1327:     }
                   1328: #endif /* SLAB_USE_CPU_POOLS */
                   1329: 
                   1330:     /*
                   1331:      * Prevent off slab data for the slab cache to avoid infinite recursion.
                   1332:      */
                   1333:     kmem_cache_init(&kmem_slab_cache, "kmem_slab", sizeof(struct kmem_slab),
1.1.1.4   root     1334:                     0, NULL, KMEM_CACHE_NOOFFSLAB);
1.1       root     1335: }
                   1336: 
                   1337: void kalloc_init(void)
                   1338: {
                   1339:     char name[KMEM_CACHE_NAME_SIZE];
                   1340:     size_t i, size;
                   1341: 
                   1342:     size = 1 << KALLOC_FIRST_SHIFT;
                   1343: 
                   1344:     for (i = 0; i < ARRAY_SIZE(kalloc_caches); i++) {
                   1345:         sprintf(name, "kalloc_%lu", size);
1.1.1.4   root     1346:         kmem_cache_init(&kalloc_caches[i], name, size, 0, NULL, 0);
1.1       root     1347:         size <<= 1;
                   1348:     }
                   1349: }
                   1350: 
                   1351: /*
                   1352:  * Return the kalloc cache index matching the given allocation size, which
                   1353:  * must be strictly greater than 0.
                   1354:  */
                   1355: static inline size_t kalloc_get_index(unsigned long size)
                   1356: {
                   1357:     assert(size != 0);
                   1358: 
                   1359:     size = (size - 1) >> KALLOC_FIRST_SHIFT;
                   1360: 
                   1361:     if (size == 0)
                   1362:         return 0;
                   1363:     else
                   1364:         return (sizeof(long) * 8) - __builtin_clzl(size);
                   1365: }
                   1366: 
                   1367: static void kalloc_verify(struct kmem_cache *cache, void *buf, size_t size)
                   1368: {
                   1369:     size_t redzone_size;
                   1370:     void *redzone;
                   1371: 
                   1372:     assert(size <= cache->obj_size);
                   1373: 
                   1374:     redzone = buf + size;
                   1375:     redzone_size = cache->obj_size - size;
                   1376:     memset(redzone, KMEM_REDZONE_BYTE, redzone_size);
                   1377: }
                   1378: 
                   1379: vm_offset_t kalloc(vm_size_t size)
                   1380: {
                   1381:     size_t index;
                   1382:     void *buf;
                   1383: 
                   1384:     if (size == 0)
                   1385:         return 0;
                   1386: 
                   1387:     index = kalloc_get_index(size);
                   1388: 
                   1389:     if (index < ARRAY_SIZE(kalloc_caches)) {
                   1390:         struct kmem_cache *cache;
                   1391: 
                   1392:         cache = &kalloc_caches[index];
                   1393:         buf = (void *)kmem_cache_alloc(cache);
                   1394: 
                   1395:         if ((buf != 0) && (cache->flags & KMEM_CF_VERIFY))
                   1396:             kalloc_verify(cache, buf, size);
1.1.1.4   root     1397:     } else {
                   1398:         buf = (void *)kmem_pagealloc_virtual(size, 0);
                   1399:     }
1.1       root     1400: 
                   1401:     return (vm_offset_t)buf;
                   1402: }
                   1403: 
                   1404: static void kfree_verify(struct kmem_cache *cache, void *buf, size_t size)
                   1405: {
                   1406:     unsigned char *redzone_byte, *redzone_end;
                   1407: 
                   1408:     assert(size <= cache->obj_size);
                   1409: 
                   1410:     redzone_byte = buf + size;
                   1411:     redzone_end = buf + cache->obj_size;
                   1412: 
                   1413:     while (redzone_byte < redzone_end) {
                   1414:         if (*redzone_byte != KMEM_REDZONE_BYTE)
                   1415:             kmem_cache_error(cache, buf, KMEM_ERR_REDZONE, redzone_byte);
                   1416: 
                   1417:         redzone_byte++;
                   1418:     }
                   1419: }
                   1420: 
                   1421: void kfree(vm_offset_t data, vm_size_t size)
                   1422: {
                   1423:     size_t index;
                   1424: 
                   1425:     if ((data == 0) || (size == 0))
                   1426:         return;
                   1427: 
                   1428:     index = kalloc_get_index(size);
                   1429: 
                   1430:     if (index < ARRAY_SIZE(kalloc_caches)) {
                   1431:         struct kmem_cache *cache;
                   1432: 
                   1433:         cache = &kalloc_caches[index];
                   1434: 
                   1435:         if (cache->flags & KMEM_CF_VERIFY)
                   1436:             kfree_verify(cache, (void *)data, size);
                   1437: 
                   1438:         kmem_cache_free(cache, data);
                   1439:     } else {
1.1.1.4   root     1440:         kmem_pagefree_virtual(data, size);
1.1       root     1441:     }
                   1442: }
                   1443: 
1.1.1.3   root     1444: static void _slab_info(int (printx)(const char *fmt, ...))
1.1       root     1445: {
                   1446:     struct kmem_cache *cache;
1.1.1.3   root     1447:     vm_size_t mem_usage, mem_reclaimable, mem_total, mem_total_reclaimable;
                   1448: 
                   1449:     mem_total = 0;
                   1450:     mem_total_reclaimable = 0;
1.1       root     1451: 
1.1.1.3   root     1452:     printx("cache                         obj slab  bufs   objs   bufs"
                   1453:            "    total reclaimable\n"
                   1454:            "name                 flags   size size /slab  usage  count"
                   1455:            "   memory      memory\n");
1.1       root     1456: 
                   1457:     simple_lock(&kmem_cache_list_lock);
                   1458: 
                   1459:     list_for_each_entry(&kmem_cache_list, cache, node) {
                   1460:         simple_lock(&cache->lock);
                   1461: 
                   1462:         mem_usage = (cache->nr_slabs * cache->slab_size) >> 10;
                   1463:         mem_reclaimable = (cache->nr_free_slabs * cache->slab_size) >> 10;
                   1464: 
1.1.1.3   root     1465:         printx("%-20s %04x %7lu %3luk  %4lu %6lu %6lu %7uk %10uk\n",
                   1466:                cache->name, cache->flags, cache->obj_size,
                   1467:                cache->slab_size >> 10,
1.1       root     1468:                cache->bufs_per_slab, cache->nr_objs, cache->nr_bufs,
                   1469:                mem_usage, mem_reclaimable);
                   1470: 
                   1471:         simple_unlock(&cache->lock);
1.1.1.3   root     1472: 
                   1473:         mem_total += mem_usage;
                   1474:         mem_total_reclaimable += mem_reclaimable;
1.1       root     1475:     }
                   1476: 
                   1477:     simple_unlock(&kmem_cache_list_lock);
1.1.1.3   root     1478: 
                   1479:     printx("total: %uk, reclaimable: %uk\n",
                   1480:            mem_total, mem_total_reclaimable);
                   1481: }
                   1482: 
                   1483: void slab_info(void)
                   1484: {
                   1485:     _slab_info(printf);
1.1       root     1486: }
                   1487: 
1.1.1.3   root     1488: #if MACH_KDB
                   1489: #include <ddb/db_output.h>
                   1490: 
                   1491:  void db_show_slab_info(void)
                   1492: {
                   1493:     _slab_info(db_printf);
                   1494: }
                   1495: 
                   1496: #endif /* MACH_KDB */
                   1497: 
1.1       root     1498: #if MACH_DEBUG
                   1499: kern_return_t host_slab_info(host_t host, cache_info_array_t *infop,
                   1500:                              unsigned int *infoCntp)
                   1501: {
                   1502:     struct kmem_cache *cache;
                   1503:     cache_info_t *info;
                   1504:     unsigned int i, nr_caches;
1.1.1.5 ! root     1505:     vm_size_t info_size;
1.1       root     1506:     kern_return_t kr;
                   1507: 
                   1508:     if (host == HOST_NULL)
                   1509:         return KERN_INVALID_HOST;
                   1510: 
1.1.1.5 ! root     1511:     /* Assume the cache list is mostly unaltered once the kernel is ready */
1.1       root     1512: 
1.1.1.5 ! root     1513: retry:
        !          1514:     /* Harmless unsynchronized access, real value checked later */
1.1       root     1515:     nr_caches = kmem_nr_caches;
1.1.1.5 ! root     1516:     info_size = nr_caches * sizeof(*info);
        !          1517:     info = (cache_info_t *)kalloc(info_size);
1.1       root     1518: 
                   1519:     if (info == NULL)
                   1520:         return KERN_RESOURCE_SHORTAGE;
                   1521: 
                   1522:     i = 0;
                   1523: 
1.1.1.5 ! root     1524:     simple_lock(&kmem_cache_list_lock);
        !          1525: 
        !          1526:     if (nr_caches != kmem_nr_caches) {
        !          1527:         simple_unlock(&kmem_cache_list_lock);
        !          1528:         kfree((vm_offset_t)info, info_size);
        !          1529:         goto retry;
        !          1530:     }
        !          1531: 
1.1       root     1532:     list_for_each_entry(&kmem_cache_list, cache, node) {
1.1.1.3   root     1533:         simple_lock(&cache->lock);
1.1.1.4   root     1534:         info[i].flags = cache->flags;
1.1       root     1535: #if SLAB_USE_CPU_POOLS
                   1536:         info[i].cpu_pool_size = cache->cpu_pool_type->array_size;
                   1537: #else /* SLAB_USE_CPU_POOLS */
                   1538:         info[i].cpu_pool_size = 0;
                   1539: #endif /* SLAB_USE_CPU_POOLS */
                   1540:         info[i].obj_size = cache->obj_size;
                   1541:         info[i].align = cache->align;
                   1542:         info[i].buf_size = cache->buf_size;
                   1543:         info[i].slab_size = cache->slab_size;
                   1544:         info[i].bufs_per_slab = cache->bufs_per_slab;
                   1545:         info[i].nr_objs = cache->nr_objs;
                   1546:         info[i].nr_bufs = cache->nr_bufs;
                   1547:         info[i].nr_slabs = cache->nr_slabs;
                   1548:         info[i].nr_free_slabs = cache->nr_free_slabs;
                   1549:         strncpy(info[i].name, cache->name, sizeof(info[i].name));
                   1550:         info[i].name[sizeof(info[i].name) - 1] = '\0';
                   1551:         simple_unlock(&cache->lock);
                   1552: 
                   1553:         i++;
                   1554:     }
                   1555: 
1.1.1.5 ! root     1556:     simple_unlock(&kmem_cache_list_lock);
        !          1557: 
        !          1558:     if (nr_caches <= *infoCntp) {
        !          1559:         memcpy(*infop, info, info_size);
        !          1560:     } else {
        !          1561:         vm_offset_t info_addr;
        !          1562:         vm_size_t total_size;
1.1       root     1563:         vm_map_copy_t copy;
                   1564: 
1.1.1.5 ! root     1565:         kr = kmem_alloc_pageable(ipc_kernel_map, &info_addr, info_size);
1.1       root     1566: 
1.1.1.5 ! root     1567:         if (kr != KERN_SUCCESS)
        !          1568:             goto out;
1.1       root     1569: 
1.1.1.5 ! root     1570:         memcpy((char *)info_addr, info, info_size);
        !          1571:         total_size = round_page(info_size);
1.1       root     1572: 
1.1.1.5 ! root     1573:         if (info_size < total_size)
        !          1574:             memset((char *)(info_addr + info_size),
        !          1575:                    0, total_size - info_size);
        !          1576: 
        !          1577:         kr = vm_map_copyin(ipc_kernel_map, info_addr, info_size, TRUE, &copy);
1.1       root     1578:         assert(kr == KERN_SUCCESS);
                   1579:         *infop = (cache_info_t *)copy;
                   1580:     }
                   1581: 
                   1582:     *infoCntp = nr_caches;
1.1.1.5 ! root     1583:     kr = KERN_SUCCESS;
        !          1584: 
        !          1585: out:
        !          1586:     kfree((vm_offset_t)info, info_size);
1.1       root     1587: 
1.1.1.5 ! root     1588:     return kr;
1.1       root     1589: }
                   1590: #endif /* MACH_DEBUG */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.