1 /* $NetBSD: kmem.c,v 1.2 2019/05/23 08:32:30 hannken Exp $ */ 2 3 /*- 4 * Copyright (c) 2017 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/kmem.h> 30 31 struct kmem_cache { 32 pool_cache_t km_pool; 33 void *km_private; 34 int (*km_constructor)(void *, void *, int); 35 void (*km_destructor)(void *, void *); 36 void (*km_reclaim)(void *); 37 }; 38 39 static int 40 solaris_constructor(void *private, void *object, int flag) 41 { 42 kmem_cache_t *km = private; 43 44 if (km->km_constructor) 45 return (*km->km_constructor)(object, km->km_private, flag); 46 47 return 0; 48 } 49 50 static void 51 solaris_destructor(void *private, void *object) 52 { 53 kmem_cache_t *km = private; 54 55 if (km->km_destructor) 56 (*km->km_destructor)(object, km->km_private); 57 } 58 59 static void 60 solaris_reclaim(void *private, int flag) 61 { 62 63 kmem_cache_t *km = private; 64 65 if (km->km_reclaim) 66 (*km->km_reclaim)(km->km_private); 67 } 68 69 kmem_cache_t * 70 kmem_cache_create(char *name, size_t bufsize, size_t align, 71 int (*constructor)(void *, void *, int), void (*destructor)(void *, void *), 72 void (*reclaim)(void *) __unused, void *private, vmem_t *vmp, int flags) 73 { 74 kmem_cache_t *km; 75 76 KASSERT(ISSET(flags, ~(KMC_NOTOUCH | KMC_NODEBUG)) == 0); 77 KASSERT(private == NULL); 78 KASSERT(vmp == NULL); 79 80 km = kmem_zalloc(sizeof(*km), KM_SLEEP); 81 km->km_private = private; 82 km->km_constructor = constructor; 83 km->km_destructor = destructor; 84 km->km_reclaim = reclaim; 85 km->km_pool = pool_cache_init(bufsize, align, 0, 0, name, NULL, 86 IPL_NONE, solaris_constructor, solaris_destructor, km); 87 if (km->km_pool == NULL) { 88 kmem_free(km, sizeof(*km)); 89 return NULL; 90 } 91 if (reclaim) 92 pool_cache_set_drain_hook(km->km_pool, solaris_reclaim, km); 93 94 return km; 95 } 96 void 97 kmem_cache_destroy(kmem_cache_t *km) 98 { 99 100 pool_cache_destroy(km->km_pool); 101 kmem_free(km, sizeof(*km)); 102 } 103 104 void * 105 kmem_cache_alloc(kmem_cache_t *km, int flags) 106 { 107 108 KASSERT(ISSET(flags, ~(KM_SLEEP | KM_NOSLEEP | KM_PUSHPAGE)) == 0); 109 110 return pool_cache_get(km->km_pool, flags); 111 } 112 113 void 114 kmem_cache_free(kmem_cache_t *km, void *object) 115 { 116 117 pool_cache_put(km->km_pool, object); 118 } 119 120 void 121 kmem_cache_reap_now(kmem_cache_t *km) 122 { 123 124 pool_cache_invalidate(km->km_pool); 125 } 126 127 #undef kmem_alloc 128 #undef kmem_zalloc 129 #undef kmem_free 130 131 /* 132 * Solaris allows allocating zero bytes (which returns NULL) 133 * and freeing a NULL pointer (which does nothing), 134 * so allow that here with wrappers around the native functions 135 * (which do not allow those things). 136 */ 137 138 void * 139 solaris_kmem_alloc(size_t size, int flags) 140 { 141 142 if (size == 0) 143 return NULL; 144 return kmem_alloc(size, flags); 145 } 146 147 void * 148 solaris_kmem_zalloc(size_t size, int flags) 149 { 150 151 if (size == 0) 152 return NULL; 153 return kmem_zalloc(size, flags); 154 } 155 156 void 157 solaris_kmem_free(void *buf, size_t size) 158 { 159 160 if (buf == NULL) 161 return; 162 kmem_free(buf, size); 163 } 164