opensolaris_kmem.c revision 168566
1168404Spjd/*- 2168404Spjd * Copyright (c) 2006-2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3168404Spjd * All rights reserved. 4168404Spjd * 5168404Spjd * Redistribution and use in source and binary forms, with or without 6168404Spjd * modification, are permitted provided that the following conditions 7168404Spjd * are met: 8168404Spjd * 1. Redistributions of source code must retain the above copyright 9168404Spjd * notice, this list of conditions and the following disclaimer. 10168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 11168404Spjd * notice, this list of conditions and the following disclaimer in the 12168404Spjd * documentation and/or other materials provided with the distribution. 13168404Spjd * 14168404Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17168404Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18168404Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19168404Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20168404Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24168404Spjd * SUCH DAMAGE. 25168404Spjd */ 26168404Spjd 27168404Spjd#include <sys/cdefs.h> 28168404Spjd__FBSDID("$FreeBSD: head/sys/cddl/compat/opensolaris/kern/opensolaris_kmem.c 168566 2007-04-10 02:35:57Z pjd $"); 29168404Spjd 30168404Spjd#include <sys/param.h> 31168404Spjd#include <sys/kernel.h> 32168404Spjd#include <sys/systm.h> 33168404Spjd#include <sys/malloc.h> 34168404Spjd#include <sys/kmem.h> 35168404Spjd#include <sys/debug.h> 36168404Spjd#include <sys/mutex.h> 37168566Spjd 38168566Spjd#include <vm/vm_page.h> 39168566Spjd#include <vm/vm_object.h> 40168566Spjd#include <vm/vm_kern.h> 41168566Spjd#include <vm/vm_map.h> 42168566Spjd 43168566Spjd#ifdef KMEM_DEBUG 44168404Spjd#include <sys/queue.h> 45168404Spjd#include <sys/stack.h> 46168566Spjd#endif 47168404Spjd 48168404Spjd#ifdef _KERNEL 49168404Spjdstatic MALLOC_DEFINE(M_SOLARIS, "solaris", "Solaris"); 50168404Spjd#else 51168404Spjd#define malloc(size, type, flags) malloc(size) 52168404Spjd#define free(addr, type) free(addr) 53168404Spjd#endif 54168404Spjd 55168404Spjd#ifdef KMEM_DEBUG 56168404Spjdstruct kmem_item { 57168404Spjd struct stack stack; 58168404Spjd LIST_ENTRY(kmem_item) next; 59168404Spjd}; 60168404Spjdstatic LIST_HEAD(, kmem_item) kmem_items; 61168404Spjdstatic struct mtx kmem_items_mtx; 62168404SpjdMTX_SYSINIT(kmem_items_mtx, &kmem_items_mtx, "kmem_items", MTX_DEF); 63168404Spjd#endif /* KMEM_DEBUG */ 64168404Spjd 65168404Spjdvoid * 66168404Spjdzfs_kmem_alloc(size_t size, int kmflags) 67168404Spjd{ 68168404Spjd void *p; 69168404Spjd#ifdef KMEM_DEBUG 70168404Spjd struct kmem_item *i; 71168404Spjd 72168404Spjd size += sizeof(struct kmem_item); 73168404Spjd#endif 74168404Spjd p = malloc(size, M_SOLARIS, kmflags); 75168404Spjd#ifndef _KERNEL 76168404Spjd if (kmflags & KM_SLEEP) 77168404Spjd assert(p != NULL); 78168404Spjd#endif 79168404Spjd#ifdef KMEM_DEBUG 80168404Spjd if (p != NULL) { 81168404Spjd i = p; 82168404Spjd p = (u_char *)p + sizeof(struct kmem_item); 83168404Spjd stack_save(&i->stack); 84168404Spjd mtx_lock(&kmem_items_mtx); 85168404Spjd LIST_INSERT_HEAD(&kmem_items, i, next); 86168404Spjd mtx_unlock(&kmem_items_mtx); 87168404Spjd } 88168404Spjd#endif 89168404Spjd return (p); 90168404Spjd} 91168404Spjd 92168404Spjdvoid 93168404Spjdzfs_kmem_free(void *buf, size_t size __unused) 94168404Spjd{ 95168404Spjd#ifdef KMEM_DEBUG 96168404Spjd struct kmem_item *i; 97168404Spjd 98168404Spjd buf = (u_char *)buf - sizeof(struct kmem_item); 99168404Spjd mtx_lock(&kmem_items_mtx); 100168404Spjd LIST_FOREACH(i, &kmem_items, next) { 101168404Spjd if (i == buf) 102168404Spjd break; 103168404Spjd } 104168404Spjd ASSERT(i != NULL); 105168404Spjd LIST_REMOVE(i, next); 106168404Spjd mtx_unlock(&kmem_items_mtx); 107168404Spjd#endif 108168404Spjd free(buf, M_SOLARIS); 109168404Spjd} 110168404Spjd 111168566Spjdu_long 112168566Spjdkmem_size(void) 113168566Spjd{ 114168566Spjd 115168566Spjd return ((u_long)vm_kmem_size); 116168566Spjd} 117168566Spjd 118168566Spjdu_long 119168566Spjdkmem_used(void) 120168566Spjd{ 121168566Spjd 122168566Spjd return ((u_long)kmem_map->size); 123168566Spjd} 124168566Spjd 125168404Spjdstatic int 126168404Spjdkmem_std_constructor(void *mem, int size __unused, void *private, int flags) 127168404Spjd{ 128168404Spjd struct kmem_cache *cache = private; 129168404Spjd 130168404Spjd return (cache->kc_constructor(mem, cache->kc_private, flags)); 131168404Spjd} 132168404Spjd 133168404Spjdstatic void 134168404Spjdkmem_std_destructor(void *mem, int size __unused, void *private) 135168404Spjd{ 136168404Spjd struct kmem_cache *cache = private; 137168404Spjd 138168404Spjd cache->kc_destructor(mem, cache->kc_private); 139168404Spjd} 140168404Spjd 141168404Spjdkmem_cache_t * 142168404Spjdkmem_cache_create(char *name, size_t bufsize, size_t align, 143168404Spjd int (*constructor)(void *, void *, int), void (*destructor)(void *, void *), 144168404Spjd void (*reclaim)(void *) __unused, void *private, vmem_t *vmp, int cflags) 145168404Spjd{ 146168404Spjd kmem_cache_t *cache; 147168404Spjd 148168404Spjd ASSERT(vmp == NULL); 149168404Spjd 150168404Spjd cache = kmem_alloc(sizeof(*cache), KM_SLEEP); 151168404Spjd strlcpy(cache->kc_name, name, sizeof(cache->kc_name)); 152168404Spjd cache->kc_constructor = constructor; 153168404Spjd cache->kc_destructor = destructor; 154168404Spjd cache->kc_private = private; 155168404Spjd#ifdef _KERNEL 156168404Spjd cache->kc_zone = uma_zcreate(cache->kc_name, bufsize, 157168404Spjd constructor != NULL ? kmem_std_constructor : NULL, 158168404Spjd destructor != NULL ? kmem_std_destructor : NULL, 159168404Spjd NULL, NULL, align > 0 ? align - 1 : 0, cflags); 160168404Spjd#else 161168404Spjd cache->kc_size = bufsize; 162168404Spjd#endif 163168404Spjd 164168404Spjd return (cache); 165168404Spjd} 166168404Spjd 167168404Spjdvoid 168168404Spjdkmem_cache_destroy(kmem_cache_t *cache) 169168404Spjd{ 170168404Spjd uma_zdestroy(cache->kc_zone); 171168404Spjd kmem_free(cache, sizeof(*cache)); 172168404Spjd} 173168404Spjd 174168404Spjdvoid * 175168404Spjdkmem_cache_alloc(kmem_cache_t *cache, int flags) 176168404Spjd{ 177168404Spjd#ifdef _KERNEL 178168404Spjd return (uma_zalloc_arg(cache->kc_zone, cache, flags)); 179168404Spjd#else 180168404Spjd void *p; 181168404Spjd 182168404Spjd p = kmem_alloc(cache->kc_size, flags); 183168404Spjd if (p != NULL) { 184168404Spjd kmem_std_constructor(p, cache->kc_size, cache->kc_private, 185168404Spjd flags); 186168404Spjd } 187168404Spjd return (p); 188168404Spjd#endif 189168404Spjd} 190168404Spjd 191168404Spjdvoid 192168404Spjdkmem_cache_free(kmem_cache_t *cache, void *buf) 193168404Spjd{ 194168404Spjd#ifdef _KERNEL 195168404Spjd uma_zfree_arg(cache->kc_zone, buf, cache); 196168404Spjd#else 197168404Spjd kmem_std_destructor(buf, cache->kc_size, cache->kc_private); 198168404Spjd kmem_free(buf, cache->kc_size); 199168404Spjd#endif 200168404Spjd} 201168404Spjd 202168404Spjd#ifdef _KERNEL 203168404Spjdextern void zone_drain(uma_zone_t zone); 204168404Spjdvoid 205168404Spjdkmem_cache_reap_now(kmem_cache_t *cache) 206168404Spjd{ 207168404Spjd zone_drain(cache->kc_zone); 208168404Spjd} 209168404Spjd 210168404Spjdvoid 211168404Spjdkmem_reap(void) 212168404Spjd{ 213168404Spjd uma_reclaim(); 214168404Spjd} 215168404Spjd#else 216168404Spjdvoid 217168404Spjdkmem_cache_reap_now(kmem_cache_t *cache __unused) 218168404Spjd{ 219168404Spjd} 220168404Spjd 221168404Spjdvoid 222168404Spjdkmem_reap(void) 223168404Spjd{ 224168404Spjd} 225168404Spjd#endif 226168404Spjd 227168404Spjdint 228168404Spjdkmem_debugging(void) 229168404Spjd{ 230168404Spjd return (0); 231168404Spjd} 232168404Spjd 233168404Spjdvoid * 234168404Spjdcalloc(size_t n, size_t s) 235168404Spjd{ 236168404Spjd return (kmem_zalloc(n * s, KM_NOSLEEP)); 237168404Spjd} 238168404Spjd 239168404Spjd#ifdef KMEM_DEBUG 240168404Spjdstatic void 241168404Spjdkmem_show(void *dummy __unused) 242168404Spjd{ 243168404Spjd struct kmem_item *i; 244168404Spjd 245168404Spjd mtx_lock(&kmem_items_mtx); 246168404Spjd if (LIST_EMPTY(&kmem_items)) 247168404Spjd printf("KMEM_DEBUG: No leaked elements.\n"); 248168404Spjd else { 249168404Spjd printf("KMEM_DEBUG: Leaked elements:\n\n"); 250168404Spjd LIST_FOREACH(i, &kmem_items, next) { 251168404Spjd printf("address=%p\n", i); 252168404Spjd stack_print(&i->stack); 253168404Spjd printf("\n"); 254168404Spjd } 255168404Spjd } 256168404Spjd mtx_unlock(&kmem_items_mtx); 257168404Spjd} 258168404Spjd 259168404SpjdSYSUNINIT(sol_kmem, SI_SUB_DRIVERS, SI_ORDER_FIRST, kmem_show, NULL); 260168404Spjd#endif /* KMEM_DEBUG */ 261