opensolaris_kmem.c revision 175632
1191665Sbms/*- 2191665Sbms * Copyright (c) 2006-2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3191665Sbms * All rights reserved. 4191665Sbms * 5191665Sbms * Redistribution and use in source and binary forms, with or without 6191665Sbms * modification, are permitted provided that the following conditions 7191665Sbms * are met: 8191665Sbms * 1. Redistributions of source code must retain the above copyright 9191665Sbms * notice, this list of conditions and the following disclaimer. 10191665Sbms * 2. Redistributions in binary form must reproduce the above copyright 11191665Sbms * notice, this list of conditions and the following disclaimer in the 12191665Sbms * documentation and/or other materials provided with the distribution. 13191665Sbms * 14191665Sbms * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15191665Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16191665Sbms * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17191665Sbms * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18191665Sbms * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19191665Sbms * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20191665Sbms * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21191665Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22191665Sbms * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23191665Sbms * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24191665Sbms * SUCH DAMAGE. 25191665Sbms */ 26191665Sbms 27191665Sbms#include <sys/cdefs.h> 28191665Sbms__FBSDID("$FreeBSD: head/sys/cddl/compat/opensolaris/kern/opensolaris_kmem.c 175632 2008-01-24 11:21:54Z pjd $"); 29191665Sbms 30191665Sbms#include <sys/param.h> 31191665Sbms#include <sys/kernel.h> 32191672Sbms#include <sys/systm.h> 33191665Sbms#include <sys/malloc.h> 34191665Sbms#include <sys/kmem.h> 35191665Sbms#include <sys/debug.h> 36191665Sbms#include <sys/mutex.h> 37191665Sbms 38191665Sbms#include <vm/vm_page.h> 39191665Sbms#include <vm/vm_object.h> 40191665Sbms#include <vm/vm_kern.h> 41191665Sbms#include <vm/vm_map.h> 42191665Sbms 43191665Sbms#ifdef KMEM_DEBUG 44191665Sbms#include <sys/queue.h> 45191665Sbms#include <sys/stack.h> 46191665Sbms#endif 47191665Sbms 48191665Sbms#ifdef _KERNEL 49191665Sbmsstatic MALLOC_DEFINE(M_SOLARIS, "solaris", "Solaris"); 50191665Sbms#else 51191665Sbms#define malloc(size, type, flags) malloc(size) 52191665Sbms#define free(addr, type) free(addr) 53191665Sbms#endif 54191665Sbms 55191665Sbms#ifdef KMEM_DEBUG 56191665Sbmsstruct kmem_item { 57191665Sbms struct stack stack; 58191665Sbms LIST_ENTRY(kmem_item) next; 59191665Sbms}; 60191665Sbmsstatic LIST_HEAD(, kmem_item) kmem_items; 61191665Sbmsstatic struct mtx kmem_items_mtx; 62191665SbmsMTX_SYSINIT(kmem_items_mtx, &kmem_items_mtx, "kmem_items", MTX_DEF); 63191665Sbms#endif /* KMEM_DEBUG */ 64191665Sbms 65191665Sbmsvoid * 66191665Sbmszfs_kmem_alloc(size_t size, int kmflags) 67191665Sbms{ 68191665Sbms void *p; 69195699Srwatson#ifdef KMEM_DEBUG 70191665Sbms struct kmem_item *i; 71191665Sbms 72191665Sbms size += sizeof(struct kmem_item); 73191665Sbms#endif 74191665Sbms p = malloc(size, M_SOLARIS, kmflags); 75191665Sbms#ifndef _KERNEL 76191665Sbms if (kmflags & KM_SLEEP) 77191665Sbms assert(p != NULL); 78191665Sbms#endif 79191665Sbms#ifdef KMEM_DEBUG 80191665Sbms if (p != NULL) { 81191665Sbms i = p; 82191665Sbms p = (u_char *)p + sizeof(struct kmem_item); 83191665Sbms stack_save(&i->stack); 84191665Sbms mtx_lock(&kmem_items_mtx); 85191665Sbms LIST_INSERT_HEAD(&kmem_items, i, next); 86191665Sbms mtx_unlock(&kmem_items_mtx); 87191665Sbms } 88191665Sbms#endif 89191665Sbms return (p); 90191665Sbms} 91191665Sbms 92191665Sbmsvoid 93191665Sbmszfs_kmem_free(void *buf, size_t size __unused) 94191665Sbms{ 95191665Sbms#ifdef KMEM_DEBUG 96191665Sbms struct kmem_item *i; 97191665Sbms 98191665Sbms buf = (u_char *)buf - sizeof(struct kmem_item); 99191665Sbms mtx_lock(&kmem_items_mtx); 100191665Sbms LIST_FOREACH(i, &kmem_items, next) { 101191665Sbms if (i == buf) 102191665Sbms break; 103191665Sbms } 104191665Sbms ASSERT(i != NULL); 105191665Sbms LIST_REMOVE(i, next); 106191665Sbms mtx_unlock(&kmem_items_mtx); 107191665Sbms#endif 108191665Sbms free(buf, M_SOLARIS); 109191665Sbms} 110191665Sbms 111191665Sbmsuint64_t 112191665Sbmskmem_size(void) 113191665Sbms{ 114191665Sbms 115191665Sbms return ((uint64_t)vm_kmem_size); 116191665Sbms} 117191665Sbms 118191665Sbmsuint64_t 119191665Sbmskmem_used(void) 120191665Sbms{ 121191665Sbms 122191665Sbms return ((uint64_t)kmem_map->size); 123191665Sbms} 124191665Sbms 125191665Sbmsstatic int 126191665Sbmskmem_std_constructor(void *mem, int size __unused, void *private, int flags) 127191665Sbms{ 128191665Sbms struct kmem_cache *cache = private; 129191665Sbms 130191665Sbms return (cache->kc_constructor(mem, cache->kc_private, flags)); 131191665Sbms} 132191665Sbms 133191665Sbmsstatic void 134191665Sbmskmem_std_destructor(void *mem, int size __unused, void *private) 135191665Sbms{ 136191665Sbms struct kmem_cache *cache = private; 137191665Sbms 138191665Sbms cache->kc_destructor(mem, cache->kc_private); 139191665Sbms} 140191665Sbms 141191665Sbmskmem_cache_t * 142191665Sbmskmem_cache_create(char *name, size_t bufsize, size_t align, 143191672Sbms int (*constructor)(void *, void *, int), void (*destructor)(void *, void *), 144191672Sbms void (*reclaim)(void *) __unused, void *private, vmem_t *vmp, int cflags) 145191672Sbms{ 146191665Sbms kmem_cache_t *cache; 147191665Sbms 148191665Sbms ASSERT(vmp == NULL); 149191665Sbms 150191665Sbms cache = kmem_alloc(sizeof(*cache), KM_SLEEP); 151191665Sbms strlcpy(cache->kc_name, name, sizeof(cache->kc_name)); 152191665Sbms cache->kc_constructor = constructor; 153227309Sed cache->kc_destructor = destructor; 154227309Sed cache->kc_private = private; 155191665Sbms#ifdef _KERNEL 156191665Sbms cache->kc_zone = uma_zcreate(cache->kc_name, bufsize, 157191665Sbms constructor != NULL ? kmem_std_constructor : NULL, 158191665Sbms destructor != NULL ? kmem_std_destructor : NULL, 159191665Sbms NULL, NULL, align > 0 ? align - 1 : 0, cflags); 160191665Sbms#else 161191665Sbms cache->kc_size = bufsize; 162191665Sbms#endif 163191665Sbms 164191665Sbms return (cache); 165191665Sbms} 166191665Sbms 167191665Sbmsvoid 168191665Sbmskmem_cache_destroy(kmem_cache_t *cache) 169191665Sbms{ 170191665Sbms uma_zdestroy(cache->kc_zone); 171191665Sbms kmem_free(cache, sizeof(*cache)); 172191665Sbms} 173191665Sbms 174227309Sedvoid * 175191665Sbmskmem_cache_alloc(kmem_cache_t *cache, int flags) 176191665Sbms{ 177191665Sbms#ifdef _KERNEL 178191665Sbms return (uma_zalloc_arg(cache->kc_zone, cache, flags)); 179191665Sbms#else 180191665Sbms void *p; 181191665Sbms 182191665Sbms p = kmem_alloc(cache->kc_size, flags); 183191665Sbms if (p != NULL) { 184191665Sbms kmem_std_constructor(p, cache->kc_size, cache->kc_private, 185191665Sbms flags); 186191665Sbms } 187191665Sbms return (p); 188191665Sbms#endif 189191665Sbms} 190191665Sbms 191191665Sbmsvoid 192191665Sbmskmem_cache_free(kmem_cache_t *cache, void *buf) 193191665Sbms{ 194191665Sbms#ifdef _KERNEL 195191665Sbms uma_zfree_arg(cache->kc_zone, buf, cache); 196191665Sbms#else 197191665Sbms kmem_std_destructor(buf, cache->kc_size, cache->kc_private); 198191665Sbms kmem_free(buf, cache->kc_size); 199191665Sbms#endif 200191665Sbms} 201191665Sbms 202191665Sbms#ifdef _KERNEL 203191665Sbmsextern void zone_drain(uma_zone_t zone); 204191665Sbmsvoid 205191665Sbmskmem_cache_reap_now(kmem_cache_t *cache) 206191665Sbms{ 207191665Sbms zone_drain(cache->kc_zone); 208191665Sbms} 209191665Sbms 210191665Sbmsvoid 211191665Sbmskmem_reap(void) 212191665Sbms{ 213191665Sbms uma_reclaim(); 214191665Sbms} 215191665Sbms#else 216191665Sbmsvoid 217191665Sbmskmem_cache_reap_now(kmem_cache_t *cache __unused) 218191665Sbms{ 219191665Sbms} 220191665Sbms 221191665Sbmsvoid 222191665Sbmskmem_reap(void) 223191665Sbms{ 224191665Sbms} 225191665Sbms#endif 226191665Sbms 227191665Sbmsint 228191665Sbmskmem_debugging(void) 229191665Sbms{ 230191665Sbms return (0); 231191665Sbms} 232191665Sbms 233191665Sbmsvoid * 234191665Sbmscalloc(size_t n, size_t s) 235191665Sbms{ 236191665Sbms return (kmem_zalloc(n * s, KM_NOSLEEP)); 237191665Sbms} 238191665Sbms 239191665Sbms#ifdef KMEM_DEBUG 240191665Sbmsstatic void 241191665Sbmskmem_show(void *dummy __unused) 242191665Sbms{ 243191665Sbms struct kmem_item *i; 244191665Sbms 245191665Sbms mtx_lock(&kmem_items_mtx); 246191665Sbms if (LIST_EMPTY(&kmem_items)) 247191665Sbms printf("KMEM_DEBUG: No leaked elements.\n"); 248191665Sbms else { 249191665Sbms printf("KMEM_DEBUG: Leaked elements:\n\n"); 250191665Sbms LIST_FOREACH(i, &kmem_items, next) { 251191665Sbms printf("address=%p\n", i); 252191665Sbms stack_print(&i->stack); 253191665Sbms printf("\n"); 254191665Sbms } 255191665Sbms } 256191665Sbms mtx_unlock(&kmem_items_mtx); 257191665Sbms} 258191665Sbms 259191665SbmsSYSUNINIT(sol_kmem, SI_SUB_DRIVERS, SI_ORDER_FIRST, kmem_show, NULL); 260191665Sbms#endif /* KMEM_DEBUG */ 261191665Sbms